jQuery(document).on('beforeSubmit', '.formbuilder-form', function (e) {
e.preventDefault();
var $form = jQuery(this);
if ($form.data("submitting") === true){
return false;
}
$form.data("submitting", true);
var formTopOffset = $form.offset().top;
var ieFormData = new FormData(this);
$.each($form.find('input[type=file]'), function(i, obj) {
var fieldname = $(obj).attr('name');
ieFormData.delete(fieldname);
$.each(obj.files, function(j, file){
ieFormData.append(fieldname + "["+j+"]", file);
});
});
/* for (var keyf of ieFormData.keys()) {
console.log(keyf);
}*/
$form.find(".spinner-overay").fadeIn();
jQuery.ajax({
url: $form.attr('action'),
type: 'post',
dataType: 'jsonp',
jsonpCallback: 'jsonCallback',
processData: false,
contentType: false,
cache: false,
data: ieFormData,
success: function (data) {
// hide messages
$form.data("submitting", false);
$form.find(".spinner-overay").fadeOut();
$form.parent('.form').find('.msg-result').hide();
// show error message
var captchaImage = $form.find("img[src^=\"/captcha/image\"]");
if (data.status === true) {
$form.parent('.form').find('.msg-error').html('');
if (data.petition) {
// petitions.
var $petitionProgressBar = $("#petition-progress-bar-" + data.petition);
var $petitionProgressBarText = $("#petition-progress-text-" + data.petition + " p");
var count = data.petition_count;
var goal = data.petition_goal;
var leftover = data.petition_leftover;
var direction = $petitionProgressBar.data("direction");
var type = data.petition_bar_style;
$petitionProgressBar.empty();
var bar = new PetitionProgressBar($("#petition-progress-bar-" + data.petition));
bar.draw(type,goal, count, direction, "#3C0310", "#c90c37");
$petitionProgressBarText.html(data.progress_bar_message)
}
// All other forms.
$form.parent('.form').find('.msg-success').html('
' + data.message + '
').show();
$form[0].reset();
$form.hide();
} else {
var msg = '' + data.message + '
';
msg += '';
if (typeof data.form != 'undefined') {
jQuery(data.form.errors).each(function (index, el) {
msg += '- ' + el.value + '
';
});
msg += '
';
}
$form.parent('.form').find('.msg-error').html(msg).show();
}
captchaImage.yiiCaptcha("refresh");
captchaImage.siblings("input").val("");
//jQuery('.wh-element-contactform-input-verify_code img').click();
jQuery('html, body').animate({scrollTop: (formTopOffset - 100)}, 'slow');
}
});
return false; // prevent default submit
});
/**
* Go to next step in multistep form.
*/
$(document).on('click', '.form .btn-next', function (e) {
e.preventDefault = true;
var parent_div = $(this).closest('.form-page');
var next_step = false;
var $form = $(this).closest('form');
var hasError = false;
// Validate input fields on this page.
parent_div.find('input').each(function () {
var $id = $(this).attr("id");
if (typeof $id == 'undefined') {
$id = $(this).next().attr("id");
}
if (typeof $id != 'undefined') {
$form.yiiActiveForm('validateAttribute', $id);
}
});
// Validate select fields.
parent_div.find('select').each(function () {
var $id = $(this).attr("id");
if (typeof $id == 'undefined') {
$id = $(this).next().attr("id");
}
if (typeof $id != 'undefined') {
$form.yiiActiveForm('validateAttribute', $id);
}
});
// Check if there are error messages.
$form.on("afterValidateAttribute", function (event, attribute, messages) {
console.log(messages);
if (messages.length > 0)
hasError = true;
});
// Check for errors.
setTimeout(function () {
if (!hasError) {
// No errors.
next_step = true;
console.log(next_step);
parent_div.fadeOut(400, function () {
$(this).next().fadeIn();
});
}
}, 200);
});
/**
* Go to previous step in multistep form.
*/
$(document).on('click', '.form .btn-prev', function () {
$(this).parents('.form-page').fadeOut(400, function () {
var $prev = $(this).prev();
// $(".registration-step-title").text($prev.data("step-title"));
$prev.fadeIn();
});
});
$(document).ready(function () {
// sticky header
$(window).on('scroll', function () {
if ($(window).scrollTop() >= 100 && $(window).width() > 768) {
$('.navbar-default').addClass('sticky');
} else {
$('.navbar-default').removeClass('sticky');
}
if ($(window).scrollTop() >= 100 && $(window).width() < 767) {
$('.navbar-default').addClass('sticky-mobile');
} else {
$('.navbar-default').removeClass('sticky-mobile');
}
});
$('.match-height-me').matchHeight();
// Play with background-color by sections
/// Home
$( ".only-col section:odd" ).addClass('gray-bg-odd-section');
$( ".only-col section:even" ).addClass('white-bg-even-section');
/// Default-theme
$( ".default-theme section:odd" ).addClass('gray-bg-odd-section');
$( ".default-theme section:even" ).addClass('white-bg-even-section');
// Slick Slider
$('.slick-me-hard').slick ({
slidesToShow: 1,
slidesToScroll: 1,
focusOnSelect: true,
arrows: true,
autoplay: true,
autoplaySpeed: 5500,
fade: true,
cssEase: 'linear',
dots: true,
infinite: true,
responsive: [
{
breakpoint: 1140,
settings: {
slidesToShow: 1,
slidesToScroll: 1,
infinite: false,
arrows: false,
dots: true,
},
}]
});
$('.s1').removeClass('start');
$('.s2').removeClass('start');
$('.s3').removeClass('start');
$('.s4').removeClass('start');
$('.s5').removeClass('start');
});
$(window).scroll(function(e){
parallax();
});
///*********** Parallax Effect on header *********///
function parallax(){
var scrolled = $(window).scrollTop();
var mediaQuery = window.matchMedia('(min-width: 800px)');
if (mediaQuery.matches) {
$('.header-banner-bg').css('top',-(scrolled*0.8)+'px');
}
}
function openOverlay(id) {
if (id === '') {
id = "#overlay";
} else {
id = "#"+id;
}
$(id).addClass('open');
$(id+' .form-overlay').addClass('open');
}
function closingTime() {
$('.overlay,#overlay').removeClass('open');
$('.form-overlay').removeClass('open');
$('.spinner-overlay').hide;
}
function prevenMe() {
if (!$(event.target).closest(".overlay").length) {
$("body").find(".overlay").removeClass("open");
}
}
function strtr(s, p, r) {
return !!s && {
2: function () {
for (var i in p) {
s = strtr(s, i, p[i]);
}
return s;
},
3: function () {
return s.replace(RegExp(p, 'g'), r);
},
0: function () {
}
}[arguments.length]();
}
function doNotOpen () {
}
/*$(document).click(function(event) {
//if you click on anything except the modal itself or the "open modal" link, close the modal
if (!$(event.target).closest(".overlay").length) {
$("body").find(".overlay").removeClass("open");
}
});*/
/*function preventMe(event) {
event.preventDefault();
}*/
/*document.getElementsByClassName("contactform-section").addEventListener("click", function(event){
event.preventDefault()
});*/
$(document).ready(function () {
//eslint-disable-next-line
(function(a){(jQuery.browser=jQuery.browser||{}).mobile=/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))})(navigator.userAgent||navigator.vendor||window.opera);
});
/**
* Created by quocdang on 09.02.17.
*/
jQuery(document).ready(function() {
jQuery('#menu-dropdown-button').click(function() {
if (jQuery('.navbar-right').hasClass('active')) {
jQuery('.navbar-right').removeClass('active');
}else {
jQuery('.navbar-right').addClass('active');
}
});
jQuery('.navbar-toggle').click(function() {
$('.navbar-default').toggleClass('im-so-height');
if (jQuery('.navbar-right').hasClass('active')) {
jQuery('.navbar-right').removeClass('active');
}else {
jQuery('.navbar-right').addClass('active');
console.log('drin');
}
});
});
/* global d3 */
//requires https://cdn.jsdelivr.net/npm/d3@5.11.0/dist/d3.min.js
function drawSmartSpider(targetSelector, electionId, candidateId){
"use strict";
function getSmartspiderOnly(electionId, candidateId, cb) {
var q = {
"operationName": "getSmartspider",
"variables": {"electionId": electionId, "candidateId": candidateId},
"query": "query getSmartspider($electionId: ID!, $candidateId: ID!) {\n candidate(electionId: $electionId, candidateId: $candidateId) {\n smartspider {\n id\n options {\n id\n cssClass\n fill\n __typename\n }\n axes {\n id\n cleavage {\n id\n name\n __typename\n }\n value\n __typename\n }\n __typename\n }\n __typename\n}}\n"
};
$.post("https://concierge.smartvote.ch/graphql", q, function (data) {
cb(data.data.candidate.smartspider);
});
}
/**
*
* @param _smartspiders Array
* @param d3Container object must be a d3.select("#ID") object
*/
function drawSpiders (_smartspiders, d3Container) {
var smartspiderElement;
//d3Container must be initialized using d3Container = d3.select("#elemID")
// smartspiderElement must be a d3 element
function linearScale100(min, max, val) {
return (val * (max - min) / 100) + min;
}
function
init() {
drawSmartspiderBackground();
drawSmartspiders();
}
function onChange() {
if (smartspiderElement) {
eraseSmartspider();
drawSmartspiders();
}
}
function drawSmartspiders() {
_smartspiders.forEach(function (spider) {
drawSmartspiderScaleAndAxis(spider);
});
_smartspiders.forEach(function (spider) {
drawSmartspider(spider);
});
}
function drawSmartspiderScaleAndAxis(spider) {
drawCircularScale(spider.axes.length);
drawCircularAxis(spider);
}
function drawSmartspider(spider) {
drawAreas(spider);
drawPositionsOnAxis(spider);
}
function eraseSmartspider() {
smartspiderElement.selectAll("*").remove();
}
function drawAreas(spider) {
var options = spider.options || {};
/** @type {number} */
var topOrientationInRadians = Math.PI / 2;
/** @type {number} */
var axesSpacingInRadians = -2 * Math.PI / spider.axes.length;
/** @type {number} */
var j = 0;
for (; j < spider.axes.length; j++) {
/** @type {!Array} */
var a = [
[
/* x1 */ Math.cos(topOrientationInRadians + j * axesSpacingInRadians) * linearScale100(7, 187, spider.axes[j].value),
/* y1 */ -Math.sin(topOrientationInRadians + j * axesSpacingInRadians) * linearScale100(7, 187, spider.axes[j].value)
],
[ // wrap-around (always draw to next point)
j === spider.axes.length - 1 ? Math.cos(topOrientationInRadians) * linearScale100(7, 187, spider.axes[0].value) : Math.cos(topOrientationInRadians + (j + 1) * axesSpacingInRadians) * linearScale100(7, 187, spider.axes[j + 1].value),
j === spider.axes.length - 1 ? -Math.sin(topOrientationInRadians) * linearScale100(7, 187, spider.axes[0].value) : -Math.sin(topOrientationInRadians + (j + 1) * axesSpacingInRadians) * linearScale100(7, 187, spider.axes[j + 1].value)
]
];
// line from
var shapeEdge = d3.area()
.x0(0)
.x1(function (n) {
return n[0];
})
.y0(0)
.y1(function (n) {
return n[1];
});
smartspiderElement.append("path").data([a]).attr("fill", options.fill ? options.fill : "none").attr("class", options.cssClass ? options.cssClass : "").attr("d", shapeEdge).attr("stroke-width", 2).attr("opacity", .5);
}
}
function drawPositionsOnAxis(results) {
var options = results.options || {};
var numAxes = results.axes.length;
/** @type {number} */
var topOrientationInRadians = Math.PI / 2;
/** @type {number} */
var axesSpacingInRadians = -2 * Math.PI / numAxes;
/** @type {number} */
var j = 0;
for (; j < numAxes; j++) {
// Todo function S_
smartspiderElement
.append("circle")
.attr("class", options.cssClass ? options.cssClass : "")
.attr("fill", options.fill ? options.fill : "none")
.attr("cx", Math.cos(topOrientationInRadians + j * axesSpacingInRadians) * linearScale100(7, 187, results.axes[j].value))
.attr("cy", -Math.sin(topOrientationInRadians + j * axesSpacingInRadians) * linearScale100(7, 187, results.axes[j].value))
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("r", 4);
}
}
function drawCircularAxis(spider) {
/** @type {null} */
var bentTextPath = null;
var numAxes = spider.axes.length;
/** @type {number} */
var startAngle = Math.PI / 2;
/** @type {number} */
var axesSpacingInRadians = -2 * Math.PI / numAxes;
smartspiderElement.append("circle").attr("cx", 0).attr("cy", 0).attr("r", "7px").attr("fill", "none").attr("stroke", "black").attr("stroke-width", "4px");
/** @type {number} */
var k = 0;
for (; k < numAxes; k++) {
/** @type {number} */
var ringAngle = startAngle + k * axesSpacingInRadians;
/** @type {number} */
var lineA_x = 7 * Math.cos(startAngle + k * axesSpacingInRadians);
/** @type {number} */
var lineA_y = 7 * -Math.sin(startAngle + k * axesSpacingInRadians);
/** @type {number} */
var lineB_x = 192 * Math.cos(startAngle + k * axesSpacingInRadians);
/** @type {number} */
var lineB_y = 192 * -Math.sin(startAngle + k * axesSpacingInRadians);
smartspiderElement
.append("line")
.attr("x1", lineA_x)
.attr("y1", lineA_y)
.attr("x2", lineB_x)
.attr("y2", lineB_y)
.attr("stroke-width", 4)
.attr("stroke", "black")
.attr("stroke-linecap", "round");
/** @type {number} */
var r = 1;
/** @type {number} */
var offset = 0;
if (Math.sin(ringAngle) < -.1 && (r = -1, offset = 5), spider.axes[k].cleavage.name.length >= 20) {
// if more than 20 characters, need to split to two lines
var words = spider.axes[k].cleavage.name.split(" ");
/** @type {string} */
var outerFragment = "";
/** @type {string} */
var innerFragment = "";
/** @type {boolean} */
var g = false;
/** @type {number} */
var i = 0;
for (; i < words.length; i++) {
if (outerFragment.length + words[i].length >= spider.axes[k].cleavage.name.length / 2 || g) {
/** @type {string} */
innerFragment = innerFragment + (words[i] + " ");
/** @type {boolean} */
g = true;
} else {
/** @type {string} */
outerFragment = outerFragment + (words[i] + " ");
}
}
bentTextPath = d3.arc().innerRadius(210 + 8 * r + offset).outerRadius(210 + 8 * r + offset).startAngle(2 * k * Math.PI / numAxes - r * Math.PI / numAxes).endAngle(2 * k * Math.PI / numAxes + r * Math.PI / numAxes);
smartspiderElement.append("path").attr("id", "path" + k + "outer").attr("d", bentTextPath);
smartspiderElement.append("text").style("font-size", "17px").style("font-weight", "bold").attr("font-family", "sans-serif").attr("text-anchor", "middle").append("textPath").attr("href", "#path"+k+"outer").attr("startOffset", "25%").text(outerFragment);
bentTextPath = d3.arc().innerRadius(210 - 8 * r + offset).outerRadius(210 - 8 * r + offset).startAngle(2 * k * Math.PI / numAxes - r * Math.PI / numAxes).endAngle(2 * k * Math.PI / numAxes + r * Math.PI / numAxes);
smartspiderElement.append("path").attr("id", "path" + k + "inner").attr("d", bentTextPath);
smartspiderElement.append("text").style("font-size", "17px").style("font-weight", "bold").attr("font-family", "sans-serif").attr("text-anchor", "middle").append("textPath").attr("href", "#path"+k+"inner").attr("startOffset", "25%").text(innerFragment);
} else {
bentTextPath = d3.arc().innerRadius(210 + 8 * r + offset).outerRadius(210 + 8 * r + offset).startAngle(2 * k * Math.PI / numAxes - r * Math.PI / numAxes).endAngle(2 * k * Math.PI / numAxes + r * Math.PI / numAxes);
smartspiderElement.append("path").attr("id", "path" + k).attr("d", bentTextPath);
smartspiderElement.append("text").style("font-size", "17px").style("font-weight", "bold").attr("font-family", "sans-serif").attr("text-anchor", "middle").append("textPath").attr("href", "#path"+k).attr("startOffset", "25%").text(spider.axes[k].cleavage.name);
}
}
}
/**
* Draws this weird scale plus the text between the spacing in the first two lines (0-100)
* @param numAxes
*/
function drawCircularScale(numAxes) {
smartspiderElement.append("text").attr("class", "smartspider-copyright").style("font-size", "10px").attr("font-family", "sans-serif").attr("text-anchor", "end").attr("x", 225).attr("y", 290).text("\u00a9 www.smartvote.ch / www.sotomo.ch (+ dbi, aca)");
/** @type {number} */
var i = 5;
for (; i <= 100; i = i + 5) {
/** @type {number} */
var x2coord = 1;
/** @type {string} */
var strokeColor = "#D9D9D9";
if (i % 25 == 0) {
/** @type {number} */
x2coord = 2;
/** @type {string} */
strokeColor = "#8F8F8F";
}
// TODO function S_
smartspiderElement.append("circle").attr("cx", 0).attr("cy", 0).attr("r", linearScale100(7, 187, i)).attr("stroke", strokeColor).attr("stroke-width", x2coord).attr("fill", "none");
}
/** @type {number} */
var x = Math.PI / 2;
/** @type {number} */
var axesSpacingInRadians = -2 * Math.PI / numAxes;
/** @type {number} */
var text_angle = 90 - 360 * (x + .5 * axesSpacingInRadians) / (2 * Math.PI);
/** @type {number} */
i = 25;
for (; i <= 100; i = i + 25) {
/** @type {number} */
var text_xPos = Math.cos(x + .5 * axesSpacingInRadians) * linearScale100(7, 187, i - 6);
/** @type {number} */
var text_yPos = -Math.sin(x + .5 * axesSpacingInRadians) * linearScale100(7, 187, i - 6);
smartspiderElement.append("text").attr("text-anchor", "middle").attr("font-size", "10px").attr("font-family", "sans-serif").attr("fill", "#8f8f8f").attr("transform", "translate(" + text_xPos + "," + text_yPos + ") rotate(" + text_angle + ")").text(i);
}
}
function drawSmartspiderBackground() {
var svg_element = d3Container.append("svg").attr("viewBox", "0 0 450 480").attr("preserveAspectRatio", "xMidYMin slice").style("width", "100%").style("padding-bottom", "107%").style("height", "1px").style("overflow", "visible").style("box-sizing", "content-box");
smartspiderElement = svg_element.append("g").attr("class", "smartspider").attr("transform", "translate(225,240)");
}
init();
}
getSmartspiderOnly(electionId, candidateId, function(spider){
drawSpiders([spider], d3.select(targetSelector));
});
}
/*
* Copyright (c) 2019. Amos Calamida
*/
"use strict";
//Movement Events
/**
* Calculate move distance for jsValueSliderHandle instance based on mouse distance from slider handle.
* @param e The click/touch event
* @param handle The currently clicked/touched handle
*/
//TODO: Add vertical slider logic
function elementDrag(e, handle) {
e.preventDefault();
// calculate the new cursor position:
//get handle position and calculate it's center
var rect = handle.elem.getBoundingClientRect();
var center = rect.left + (rect.right - rect.left) / 2;
//get user's mouse position relative to the center of the handle
var clientX = 0;
if (e.type === 'touchmove') {
clientX = e.touches[0].clientX;
} else {
clientX = e.clientX;
}
var relMousePos = clientX - center;
//calculate how many steps to move based on the distance between the mouse and the center of the handle
var steps = relMousePos / handle.slider.pixelPointDistance / handle.step;
handle.move(Math.round(steps));
}
/**
* Destroy mouse move and touch move events for handle
* @param e The click/touch event
* @param handle The currently clicked/touched handle
*/
function closeDragElement(e, handle) {
/* stop moving when mouse button is released:*/
document.onmouseup = null;
document.onmousemove = null;
document.ontouchend = null;
document.ontouchmove = null;
}
/**
* Register mouse move and touch move events for handle
* @param e The click/touch event
* @param handle The currently clicked/touched handle
*/
function dragMouseDown(e, handle) {
e.preventDefault();
document.onmouseup = function (e) {
closeDragElement(e, handle);
};
document.ontouchend = function (e) {
closeDragElement(e, handle);
};
// call a function whenever the cursor moves:
document.onmousemove = function (e) {
elementDrag(e, handle);
};
document.ontouchmove = function (e) {
elementDrag(e, handle);
};
}
//End Movement Events
//Slider Static Functions
var sliders = {}; //Array to store all slider instances.
window.onresize = function () {
for (var i in sliders) {
if (Object.prototype.hasOwnProperty.call(sliders,i)) {
sliders[i].calculatePixelPointDistance();
sliders[i].setPositions();
sliders[i].handles.forEach(function (handle) {
handle.updatePixelPosition();
handle.labels.forEach(function (label) {
label.updatePosition(label.position.value);
});
});
}
}
};
/**
* Return a jsValueSlider based on the slider's DOM id
* @param id DOM id of slider
* @returns jsValueSlider
*/
function getjsValueSliderById(id) {
if (Object.prototype.hasOwnProperty.call(sliders, id)) {
return sliders[id];
}
return null;
}
function buildJsValueSliders(data) {
if (Object.prototype.hasOwnProperty.call(data,'sliders')) {
data.sliders.forEach(function (slider) {
if (Object.prototype.hasOwnProperty.call(slider, 'slider')) {
var currSlider = new jsValueSlider(
slider.slider,
slider.min,
slider.max,
slider.step
);
if (Object.prototype.hasOwnProperty.call(slider,'handles')) {
slider.handles.forEach(function (handle) {
var currHandle = new jsValueSliderHandle(
currSlider,
handle.min,
handle.max,
handle.step,
handle.currPos,
handle.elem
);
if (Object.prototype.hasOwnProperty.call(handle, 'labels')) {
handle.labels.forEach(function (label) {
new jsValueSliderLabel(
currSlider,
currHandle,
label.position,
label.content,
label.elem
);
});
}
if (Object.prototype.hasOwnProperty.call(handle, 'outputs')) {
handle.outputs.forEach(function (output) {
new jsValueSliderOutput(
currSlider,
currHandle,
output.elem
);
});
}
});
}
}
});
}
}
function buildJsValueSliderFromRangeInput(elem, id, orientation) {
if (typeof elem === 'string') {
elem = document.querySelector(elem);
}
var sliderContainer = document.createElement('div');
sliderContainer.classList.add('js_value_slider_container');
//TODO: Add support for vertical sliders
//var orientationClass = orientation === 'vertical' ? js_value_slider_vertical : js_value_slider_horizontal;
//sliderContainer.classList.add(orientationClass);
sliderContainer.classList.add('js_value_slider_horizontal');
var sliderElem = document.createElement('div');
sliderElem.classList.add('js_value_slider');
sliderElem.id = elem.id;
sliderContainer.appendChild(sliderElem);
var sliderBar = document.createElement('div');
sliderBar.classList.add('js_value_slider_bar');
sliderElem.appendChild(sliderBar);
var sliderScale = document.createElement('div');
sliderScale.classList.add('js_value_slider_scale');
sliderElem.appendChild(sliderScale);
elem.parentNode.insertBefore(sliderContainer, elem.nextSibling);
elem.setAttribute('style', 'display:none;');
var slider = new jsValueSlider(
sliderElem,
elem.getAttribute('min'),
elem.getAttribute('max'),
1
);
var handle = new jsValueSliderHandle(
slider,
elem.getAttribute('min'),
elem.getAttribute('max'),
elem.getAttribute('step'),
elem.getAttribute('value')
);
handle.registerMoveListener(function (e) {
elem.setAttribute('value', handle.currPos);
});
var labels = document.querySelectorAll('label[for="' + elem + '"]');
return slider;
}
//End Slider Static Functions
//Slider Class
/**
* jsValueSlider Class
* @param elem The DOM element the slider is bound to
* @param min Minimum value of slider positions
* @param max Maximum value of slider positions
* @param step How many values the slider increments/decrements by at once.
*/
var jsValueSlider = function (elem, min, max, step) {
this.elem = elem;
if (typeof this.elem === 'string') {
this.elem = document.querySelector(this.elem);
}
this.min = typeof min === 'undefined' ? 1 : parseInt(min);
this.max = typeof max === 'undefined' ? 100 : parseInt(max);
this.step = typeof step === 'undefined' ? 1 : parseInt(step);
this.handles = [];
this.calculatePixelPointDistance();
this.setPositions();
sliders[this.elem.id] = this;
};
jsValueSlider.prototype.calculatePixelPointDistance = function () {
var sliderPixelWidth = this.elem.querySelector('.js_value_slider_scale').clientWidth;
this.pixelPointDistance = sliderPixelWidth / (this.max - this.min);
};
jsValueSlider.prototype.setPositions = function () {
this.positions = {};
new jsValueSliderPosition(this, this.min, 0);
var currPixelPos = 0;
for (var i = this.min + this.step; i <= this.max; i = i + this.step) {
currPixelPos += this.pixelPointDistance * this.step;
new jsValueSliderPosition(this, i, currPixelPos);
}
if (typeof this.positions[this.max] === 'undefined') {
var maxPixelPos = this.pixelPointDistance * (this.max - this.min);
new jsValueSliderPosition(this, this.max, maxPixelPos);
}
};
jsValueSlider.prototype.getAllValues = function () {
var values = [];
this.handles.forEach(function (handle) {
values.push(parseInt(handle.currPos));
});
return values;
};
//End Slider Class
//Slider Position Class
/**
* jsValueSliderPosition Class - Represents a "position"/"Pixel Position" for each slider value.
* @param slider
* @param value
* @param pixelPos
*/
var jsValueSliderPosition = function (slider, value, pixelPos) {
this.slider = slider;
this.slider.positions[value] = this;
this.value = value;
this.pixelPos = typeof pixelPos === 'undefined' ? 0 : pixelPos;
this.labels = [];
};
//End Slider Position Class
//Slider Handle Class
/**
* jsValueSliderHandle Class - Represents a "handle" which the user moves to modify it's value
* @param slider
* @param min
* @param max
* @param step
* @param currPos
* @param elem
*/
var jsValueSliderHandle = function (slider, min, max, step, currPos, elem) {
this.slider = slider;
this.slider.handles.push(this);
this.min = typeof min === 'undefined' ? this.slider.min : parseInt(min);
this.max = typeof max === 'undefined' ? this.slider.max : parseInt(max);
this.step = typeof step === 'undefined' ? this.slider.step : parseInt(step);
this.events = [];
//handle step must be either
if (this.step % this.slider.step !== 0) {
this.step = this.slider.step * this.step;
}
if (this.step > this.max - this.min) {
this.step = this.max - this.min;
}
this.currPos = typeof currPos === 'undefined' ? this.min : currPos;
this.labels = [];
this.outputs = [];
this.elem = typeof elem === 'undefined' ? null : elem;
if (typeof elem === 'string') {
this.elem = this.slider.elem.querySelector(elem);
}
if (this.elem === null) {
this.elem = document.createElement('div');
this.elem.classList.add('js_value_slider_handle');
}
var handleHolder = this.slider.elem.querySelector('.js_value_slider_handle_holder');
if (handleHolder === null) {
handleHolder = document.createElement('div');
handleHolder.classList.add('js_value_slider_handle_holder');
this.slider.elem.appendChild(handleHolder);
}
handleHolder.appendChild(this.elem);
var currHandle = this;
this.elem.onmousedown = function (e) {
dragMouseDown(e, currHandle);
};
this.elem.ontouchstart = function (e) {
dragMouseDown(e, currHandle);
};
this.updatePosition(this.currPos);
};
/**
* Calculate handle position based on "steps" and update
* @param steps signed integer representing the number of values to move
* negative = left/down, positive = right/up.
*/
jsValueSliderHandle.prototype.move = function (steps) {
steps = typeof steps === 'undefined' ? 1 : steps;
var currentPosition = this.slider.positions[this.currPos];
var possiblePositions = Object.keys(this.slider.positions);
var desiredPositionKey = possiblePositions.indexOf(String(this.currPos)) + steps * this.step;
if (desiredPositionKey > possiblePositions.length - 1) {
desiredPositionKey = possiblePositions.length - 1;
} else if (desiredPositionKey < 0) {
desiredPositionKey = 0;
}
var desiredPosition = possiblePositions[desiredPositionKey];
var currPos = this.slider.positions[desiredPosition].value;
this.updatePosition(currPos);
};
/**
* Update handle position by setting the "left" style attribute of the handle.
* @param currPos
*/
jsValueSliderHandle.prototype.updatePosition = function (currPos) {
if (currPos > this.max) {
currPos = this.max;
}
if (currPos < this.min) {
currPos = this.min;
}
this.currPos = parseInt(currPos);
this.updatePixelPosition();
var currHandle = this;
this.outputs.forEach(function (output) {
if (output.elem.nodeName.toLowerCase() === 'input') {
output.elem.value = currHandle.currPos;
} else {
output.elem.innerHTML = currHandle.currPos;
}
});
this.elem.setAttribute('data-text', this.currPos);
};
jsValueSliderHandle.prototype.updatePixelPosition = function () {
this.pixelPos = this.slider.positions[this.currPos].pixelPos;
this.elem.style.left = this.pixelPos + 'px';
};
jsValueSliderHandle.prototype.registerEventListener = function (type, callback) {
this.elem.addEventListener('mousedown', function (e) {
document.addEventListener(type, callback);
});
this.elem.addEventListener('touchstart', function (e) {
document.addEventListener(type, callback);
});
};
jsValueSliderHandle.prototype.registerMoveListener = function (callback) {
this.elem.addEventListener('mousedown', function (e) {
document.addEventListener('mousemove', callback);
document.addEventListener('mouseup', function a(e) {
document.removeEventListener('mousemove', callback);
document.removeEventListener('mouseup', a);
});
});
this.elem.addEventListener('touchstart', function (e) {
document.addEventListener('touchmove', callback);
document.addEventListener('touchend', function b(e) {
document.removeEventListener('touchmove', callback);
document.removeEventListener('touchend', b);
});
});
};
//End Slider Handle Class
//Slider Label Class
/**
* jsValueSliderLabel Class - Represent a "label" relative to a position.
* Current behaviour: Update handle position to label "onclick", show content
* @param slider jsValueSlider
* @param handle jsValueSliderHandle
* @param position int
* @param content string
* @param elem
*/
var jsValueSliderLabel = function (slider, handle, position, content, elem, category) {
this.slider = slider;
this.handle = handle;
this.position = this.slider.positions[position];
this.position.labels.push(this);
if (typeof elem !== 'undefined') {
this.elem = elem;
if (typeof this.elem === 'string') {
this.elem = document.querySelector(this.elem);
}
this.addData(content);
} else {
this.elem = document.createElement('div');
this.elem.classList.add('js_value_slider_label');
this.addData(content);
var labelHolder = this.position.slider.elem.querySelector('.js_value_slider_label_holder');
if (labelHolder === null) {
labelHolder = document.createElement('div');
labelHolder.classList.add('js_value_slider_label_holder');
this.position.slider.elem.appendChild(labelHolder);
}
labelHolder.appendChild(this.elem);
}
this.handle.labels.push(this);
};
/**
* Attempt to solve problem of adding all relevant data before instance is rendered to DOM
* @param content
*/
//Refactor: Improve code smell.
jsValueSliderLabel.prototype.addData = function (content) {
this.addContent(content);
this.elem.setAttribute('data-pos', this.position.value);
this.updatePosition(this.position.value);
var currHandle = this.handle;
this.elem.onclick = function (e) {
currHandle.updatePosition(this.getAttribute('data-pos'));
};
};
jsValueSliderLabel.prototype.updatePosition = function (currPos) {
this.position = this.slider.positions[currPos];
this.elem.style.left = this.position.pixelPos + 'px';
};
/**
* Add label content.
* @param content
*/
jsValueSliderLabel.prototype.addContent = function (content) {
content = typeof content === 'undefined' ? '' : content;
var contentHolder = document.createElement('div');
contentHolder.innerHTML = content;
this.content = contentHolder;
this.elem.appendChild(this.content);
};
//End Slider Label Class
//Slider Output Class
/**
* jsValueSliderOutput Class - Represents DOM element where handle value should be displayed.
* @param slider jsValueSlider
* @param handle jsValueSliderHandle
* @param elem
*/
var jsValueSliderOutput = function (slider, handle, elem) {
this.slider = slider;
this.handle = handle;
this.handle.outputs.push(this);
this.elem = elem;
if (typeof this.elem === 'string') {
this.elem = document.querySelector(this.elem);
}
if (this.elem.nodeName.toLowerCase() === 'input') {
this.elem.value = this.handle.currPos;
} else {
this.elem.innerHTML = this.handle.currPos;
}
};
/**
* Created by dominic.bieri on 24.01.17.
*/
$(document).ready(function(){
$('.fake-radio').click(function(){
var $this = $(this);
$("input[name="+$this.data("input-name")+"]").val($this.data("value"));
$this.addClass('checked').siblings('.fake-radio').removeClass('checked');
});
$('.fake-radio + label').click(function(){
var $this = $(this);
$("#"+$this.attr("for")+".fake-radio").trigger('click');
});
});
/**
* Flatcollapsible
* is an extension of materialize collapsible, usable on flat items.
*
* Authors: Materialize, Dominic Bieri
* Copyright: 2016 BERTA Kommunikation AG
*/
;(function ($) {
$.fn.flatcollapsible = function(options) {
var defaults = {
accordion: undefined
};
options = $.extend(defaults, options);
return this.each(function() {
var $this = $(this);
var $panel_headers = $(this).find('> .collapsible-header');
var collapsible_type = $this.data("collapsible");
// Turn off any existing event handlers
$this.off('click.collapse', '> .collapsible-header');
$panel_headers.off('click.collapse');
/****************
Helper Functions
****************/
// Accordion Open
function accordionOpen(object) {
$panel_headers = $this.find(' > .collapsible-header');
if (object.hasClass('active')) {
object.parent().addClass('active');
}
else {
object.parent().removeClass('active');
}
if (object.parent().hasClass('active')){
object.siblings('.collapsible-body').stop(true,false).slideDown({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
}
else{
object.siblings('.collapsible-body').stop(true,false).slideUp({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
}
$panel_headers.not(object).removeClass('active').parent().removeClass('active');
$panel_headers.not(object).parent().children('.collapsible-body').stop(true,false).slideUp(
{
duration: 350,
easing: "easeOutQuart",
queue: false,
complete:
function() {
$(this).css('height', '');
}
});
}
// Expandable Open
function expandableOpen(object) {
if (object.hasClass('active')) {
object.parent().addClass('active');
}
else {
object.parent().removeClass('active');
}
if (object.parent().hasClass('active')){
object.siblings('.collapsible-body').stop(true,false).slideDown({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
}
else{
object.siblings('.collapsible-body').stop(true,false).slideUp({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
}
}
/**
* Check if object is children of panel header
* @param {Object} object Jquery object
* @return {Boolean} true if it is children
*/
function isChildrenOfPanelHeader(object) {
var panelHeader = getPanelHeader(object);
return panelHeader.length > 0;
}
/**
* Get panel header from a children element
* @param {Object} object Jquery object
* @return {Object} panel header object
*/
function getPanelHeader(object) {
return object.closest('.collapsible-header');
}
/***** End Helper Functions *****/
// Add click handler to only direct collapsible header children
$this.on('click.collapse', '> .collapsible-header', function(e) {
var $header = $(this),
element = $(e.target);
if (isChildrenOfPanelHeader(element)) {
element = getPanelHeader(element);
}
element.toggleClass('active');
if (options.accordion || collapsible_type === "accordion" || collapsible_type === undefined) { // Handle Accordion
accordionOpen(element);
} else { // Handle Expandables
expandableOpen(element);
if ($header.hasClass('active')) {
expandableOpen($header);
}
}
});
// Open first active
var $panel_headers = $this.find('> .collapsible-header');
if (options.accordion || collapsible_type === "accordion" || collapsible_type === undefined) { // Handle Accordion
accordionOpen($panel_headers.filter('.active').first());
}
else { // Handle Expandables
$panel_headers.filter('.active').each(function() {
expandableOpen($(this));
});
}
});
};
$(document).ready(function(){
$('.collapsible.post-item').flatcollapsible();
});
}( jQuery ));
(function ($) {
$.fn.collapsible = function(options) {
var defaults = {
accordion: undefined
};
options = $.extend(defaults, options);
return this.each(function() {
var $this = $(this);
var $panel_headers = $(this).find('> li > .collapsible-header');
var collapsible_type = $this.data("collapsible");
// Turn off any existing event handlers
$this.off('click.collapse', '> li > .collapsible-header');
$panel_headers.off('click.collapse');
/****************
Helper Functions
****************/
// Accordion Open
function accordionOpen(object) {
$panel_headers = $this.find('> li > .collapsible-header');
if (object.hasClass('active')) {
object.parent().addClass('active');
}
else {
object.parent().removeClass('active');
}
if (object.parent().hasClass('active')){
object.siblings('.collapsible-body').stop(true,false).slideDown({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
}
else{
object.siblings('.collapsible-body').stop(true,false).slideUp({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
}
$panel_headers.not(object).removeClass('active').parent().removeClass('active');
$panel_headers.not(object).parent().children('.collapsible-body').stop(true,false).slideUp(
{
duration: 350,
easing: "easeOutQuart",
queue: false,
complete:
function() {
$(this).css('height', '');
}
});
}
// Expandable Open
function expandableOpen(object) {
if (object.hasClass('active')) {
object.parent().addClass('active');
}
else {
object.parent().removeClass('active');
}
if (object.parent().hasClass('active')){
object.siblings('.collapsible-body').stop(true,false).slideDown({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
}
else{
object.siblings('.collapsible-body').stop(true,false).slideUp({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
}
}
/**
* Check if object is children of panel header
* @param {Object} object Jquery object
* @return {Boolean} true if it is children
*/
function isChildrenOfPanelHeader(object) {
var panelHeader = getPanelHeader(object);
return panelHeader.length > 0;
}
/**
* Get panel header from a children element
* @param {Object} object Jquery object
* @return {Object} panel header object
*/
function getPanelHeader(object) {
return object.closest('li > .collapsible-header');
}
/***** End Helper Functions *****/
// Add click handler to only direct collapsible header children
$this.on('click.collapse', '> li > .collapsible-header', function(e) {
var $header = $(this),
element = $(e.target);
if (isChildrenOfPanelHeader(element)) {
element = getPanelHeader(element);
}
element.toggleClass('active');
if (options.accordion || collapsible_type === "accordion" || collapsible_type === undefined) { // Handle Accordion
accordionOpen(element);
} else { // Handle Expandables
expandableOpen(element);
if ($header.hasClass('active')) {
expandableOpen($header);
}
}
});
// Open first active
var $panel_headers = $this.find('> li > .collapsible-header');
if (options.accordion || collapsible_type === "accordion" || collapsible_type === undefined) { // Handle Accordion
accordionOpen($panel_headers.filter('.active').first());
}
else { // Handle Expandables
$panel_headers.filter('.active').each(function() {
expandableOpen($(this));
});
}
});
};
$(document).ready(function(){
$('.collapsible').collapsible();
});
}( jQuery ));
/*!
* jQCloud Plugin for jQuery
*
* Version 1.0.4
*
* Copyright 2011, Luca Ongaro
* Licensed under the MIT license.
*
* Date: 2013-05-09 18:54:22 +0200
*/
(function( $ ) {
"use strict";
$.fn.jQCloud = function(word_array, options) {
// Reference to the container element
var $this = this;
// Namespace word ids to avoid collisions between multiple clouds
var cloud_namespace = $this.attr('id') || Math.floor((Math.random()*1000000)).toString(36);
// Default options value
var default_options = {
width: $this.width(),
height: $this.height(),
center: {
x: ((options && options.width) ? options.width : $this.width()) / 2.0,
y: ((options && options.height) ? options.height : $this.height()) / 2.0
},
delayedMode: word_array.length > 50,
shape: false, // It defaults to elliptic shape
encodeURI: true,
removeOverflowing: true
};
options = $.extend(default_options, options || {});
// Add the "jqcloud" class to the container for easy CSS styling, set container width/height
$this.addClass("jqcloud").width(options.width).height(options.height);
// Container's CSS position cannot be 'static'
if ($this.css("position") === "static") {
$this.css("position", "relative");
}
var drawWordCloud = function() {
// Helper function to test if an element overlaps others
var hitTest = function(elem, other_elems) {
// Pairwise overlap detection
var overlapping = function(a, b) {
if (Math.abs(2.0*a.offsetLeft + a.offsetWidth - 2.0*b.offsetLeft - b.offsetWidth) < a.offsetWidth + b.offsetWidth) {
if (Math.abs(2.0*a.offsetTop + a.offsetHeight - 2.0*b.offsetTop - b.offsetHeight) < a.offsetHeight + b.offsetHeight) {
return true;
}
}
return false;
};
var i = 0;
// Check elements for overlap one by one, stop and return false as soon as an overlap is found
for(i = 0; i < other_elems.length; i++) {
if (overlapping(elem, other_elems[i])) {
return true;
}
}
return false;
};
// Make sure every weight is a number before sorting
for (var i = 0; i < word_array.length; i++) {
word_array[i].weight = parseFloat(word_array[i].weight, 10);
}
// Sort word_array from the word with the highest weight to the one with the lowest
word_array.sort(function(a, b) { if (a.weight < b.weight) {return 1;} else if (a.weight > b.weight) {return -1;} else {return 0;} });
var step = (options.shape === "rectangular") ? 18.0 : 2.0,
already_placed_words = [],
aspect_ratio = options.width / options.height;
// Function to draw a word, by moving it in spiral until it finds a suitable empty place. This will be iterated on each word.
var drawOneWord = function(index, word) {
// Define the ID attribute of the span that will wrap the word, and the associated jQuery selector string
var word_id = cloud_namespace + "_word_" + index,
word_selector = "#" + word_id,
angle = 6.28 * Math.random(),
radius = 0.0,
// Only used if option.shape == 'rectangular'
steps_in_direction = 0.0,
quarter_turns = 0.0,
weight = 5,
custom_class = "",
inner_html = "",
word_span;
// Extend word html options with defaults
word.html = $.extend(word.html, {id: word_id});
// If custom class was specified, put them into a variable and remove it from html attrs, to avoid overwriting classes set by jQCloud
if (word.html && word.html["class"]) {
custom_class = word.html["class"];
delete word.html["class"];
}
// Check if min(weight) > max(weight) otherwise use default
if (word_array[0].weight > word_array[word_array.length - 1].weight) {
// Linearly map the original weight to a discrete scale from 1 to 10
weight = Math.round((word.weight - word_array[word_array.length - 1].weight) /
(word_array[0].weight - word_array[word_array.length - 1].weight) * 9.0) + 1;
}
word_span = $('').attr(word.html).addClass('w' + weight + " " + custom_class);
// Append link if word.url attribute was set
if (word.link) {
// If link is a string, then use it as the link href
if (typeof word.link === "string") {
word.link = {href: word.link};
}
// Extend link html options with defaults
if ( options.encodeURI ) {
word.link = $.extend(word.link, { href: encodeURI(word.link.href).replace(/'/g, "%27") });
}
inner_html = $('').attr(word.link).text(word.text);
} else {
inner_html = word.text;
}
word_span.append(inner_html);
// Bind handlers to words
if (!!word.handlers) {
for (var prop in word.handlers) {
if (word.handlers.hasOwnProperty(prop) && typeof word.handlers[prop] === 'function') {
$(word_span).bind(prop, word.handlers[prop]);
}
}
}
$this.append(word_span);
var width = word_span.width(),
height = word_span.height(),
left = options.center.x - width / 2.0,
top = options.center.y - height / 2.0;
// Save a reference to the style property, for better performance
var word_style = word_span[0].style;
word_style.position = "absolute";
word_style.left = left + "px";
word_style.top = top + "px";
while(hitTest(word_span[0], already_placed_words)) {
// option shape is 'rectangular' so move the word in a rectangular spiral
if (options.shape === "rectangular") {
steps_in_direction++;
if (steps_in_direction * step > (1 + Math.floor(quarter_turns / 2.0)) * step * ((quarter_turns % 4 % 2) === 0 ? 1 : aspect_ratio)) {
steps_in_direction = 0.0;
quarter_turns++;
}
switch(quarter_turns % 4) {
case 1:
left += step * aspect_ratio + Math.random() * 2.0;
break;
case 2:
top -= step + Math.random() * 2.0;
break;
case 3:
left -= step * aspect_ratio + Math.random() * 2.0;
break;
case 0:
top += step + Math.random() * 2.0;
break;
}
} else { // Default settings: elliptic spiral shape
radius += step;
angle += (index % 2 === 0 ? 1 : -1)*step;
left = options.center.x - (width / 2.0) + (radius*Math.cos(angle)) * aspect_ratio;
top = options.center.y + radius*Math.sin(angle) - (height / 2.0);
}
word_style.left = left + "px";
word_style.top = top + "px";
}
// Don't render word if part of it would be outside the container
if (options.removeOverflowing && (left < 0 || top < 0 || (left + width) > options.width || (top + height) > options.height)) {
word_span.remove();
return;
}
already_placed_words.push(word_span[0]);
// Invoke callback if existing
if ($.isFunction(word.afterWordRender)) {
word.afterWordRender.call(word_span);
}
};
var drawOneWordDelayed = function(index) {
index = index || 0;
if (!$this.is(':visible')) { // if not visible then do not attempt to draw
setTimeout(function(){drawOneWordDelayed(index);},10);
return;
}
if (index < word_array.length) {
drawOneWord(index, word_array[index]);
setTimeout(function(){drawOneWordDelayed(index + 1);}, 10);
} else {
if ($.isFunction(options.afterCloudRender)) {
options.afterCloudRender.call($this);
}
}
};
// Iterate drawOneWord on every word. The way the iteration is done depends on the drawing mode (delayedMode is true or false)
if (options.delayedMode){
drawOneWordDelayed();
}
else {
$.each(word_array, drawOneWord);
if ($.isFunction(options.afterCloudRender)) {
options.afterCloudRender.call($this);
}
}
};
// Delay execution so that the browser can render the page before the computatively intensive word cloud drawing
setTimeout(function(){drawWordCloud();}, 10);
return $this;
};
})(jQuery);
$(document).on('submit', '.api-form-submit', function (e) {
e.preventDefault();
$.ajax({
context: $(this),
url: jQuery(this).attr('action'),
type: 'post',
dataType: 'jsonp',
jsonpCallback: 'jsonCallback',
data: jQuery(this).serialize(),
success: function (data) {
// hide messages
this.find('.api-message').hide();
// show error message
if (data.success === true) {
this.find('.api-message-success').html('' + (data.message || "OK") + '
').show();
this[0].reset();
}
else {
var msg = '' + (data.message || "Unbekannter Fehler") + '
';
msg += '';
if (data.form)
jQuery(data.form.errors).each(function (index, el) {
msg += '- ' + el.value + '
';
});
msg += '
';
this.find('.api-message-error').html(msg).show();
}
var captcha = this.find('img[src^="/captcha/image"]');
if (captcha.length) {
captcha.yiiCaptcha('refresh');
captcha.siblings("input").val("");
}
}
});
});
/**
* BxSlider v4.1.2 - Fully loaded, responsive content slider
* http://bxslider.com
*
* Copyright 2014, Steven Wanderski - http://stevenwanderski.com - http://bxcreative.com
* Written while drinking Belgian ales and listening to jazz
*
* Released under the MIT license - http://opensource.org/licenses/MIT
*/
;(function($){
var plugin = {};
var defaults = {
// GENERAL
mode: 'horizontal',
slideSelector: '',
infiniteLoop: true,
hideControlOnEnd: false,
speed: 500,
easing: null,
slideMargin: 0,
startSlide: 0,
randomStart: false,
captions: false,
ticker: false,
tickerHover: false,
adaptiveHeight: false,
adaptiveHeightSpeed: 500,
video: false,
useCSS: true,
preloadImages: 'visible',
responsive: true,
slideZIndex: 50,
wrapperClass: 'bx-wrapper',
// TOUCH
touchEnabled: true,
swipeThreshold: 50,
oneToOneTouch: true,
preventDefaultSwipeX: true,
preventDefaultSwipeY: false,
// PAGER
pager: true,
pagerType: 'full',
pagerShortSeparator: ' / ',
pagerSelector: null,
buildPager: null,
pagerCustom: null,
// CONTROLS
controls: true,
nextText: 'Next',
prevText: 'Prev',
nextSelector: null,
prevSelector: null,
autoControls: false,
startText: 'Start',
stopText: 'Stop',
autoControlsCombine: false,
autoControlsSelector: null,
// AUTO
auto: false,
pause: 4000,
autoStart: true,
autoDirection: 'next',
autoHover: false,
autoDelay: 0,
autoSlideForOnePage: false,
// CAROUSEL
minSlides: 1,
maxSlides: 1,
moveSlides: 0,
slideWidth: 0,
// CALLBACKS
onSliderLoad: function() {},
onSlideBefore: function() {},
onSlideAfter: function() {},
onSlideNext: function() {},
onSlidePrev: function() {},
onSliderResize: function() {}
};
$.fn.bxSlider = function(options){
if(this.length == 0) return this;
// support mutltiple elements
if(this.length > 1){
this.each(function(){$(this).bxSlider(options)});
return this;
}
// create a namespace to be used throughout the plugin
var slider = {};
// set a reference to our slider element
var el = this;
plugin.el = this;
/**
* Makes slideshow responsive
*/
// first get the original window dimens (thanks alot IE)
var windowWidth = $(window).width();
var windowHeight = $(window).height();
/**
* ===================================================================================
* = PRIVATE FUNCTIONS
* ===================================================================================
*/
/**
* Initializes namespace settings to be used throughout plugin
*/
var init = function(){
// merge user-supplied options with the defaults
slider.settings = $.extend({}, defaults, options);
// parse slideWidth setting
slider.settings.slideWidth = parseInt(slider.settings.slideWidth);
// store the original children
slider.children = el.children(slider.settings.slideSelector);
// check if actual number of slides is less than minSlides / maxSlides
if(slider.children.length < slider.settings.minSlides) slider.settings.minSlides = slider.children.length;
if(slider.children.length < slider.settings.maxSlides) slider.settings.maxSlides = slider.children.length;
// if random start, set the startSlide setting to random number
if(slider.settings.randomStart) slider.settings.startSlide = Math.floor(Math.random() * slider.children.length);
// store active slide information
slider.active = { index: slider.settings.startSlide };
// store if the slider is in carousel mode (displaying / moving multiple slides)
slider.carousel = slider.settings.minSlides > 1 || slider.settings.maxSlides > 1;
// if carousel, force preloadImages = 'all'
if(slider.carousel) slider.settings.preloadImages = 'all';
// calculate the min / max width thresholds based on min / max number of slides
// used to setup and update carousel slides dimensions
slider.minThreshold = (slider.settings.minSlides * slider.settings.slideWidth) + ((slider.settings.minSlides - 1) * slider.settings.slideMargin);
slider.maxThreshold = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin);
// store the current state of the slider (if currently animating, working is true)
slider.working = false;
// initialize the controls object
slider.controls = {};
// initialize an auto interval
slider.interval = null;
// determine which property to use for transitions
slider.animProp = slider.settings.mode == 'vertical' ? 'top' : 'left';
// determine if hardware acceleration can be used
slider.usingCSS = slider.settings.useCSS && slider.settings.mode != 'fade' && (function(){
// create our test div element
var div = document.createElement('div');
// css transition properties
var props = ['WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];
// test for each property
for(var i in props){
if(div.style[props[i]] !== undefined){
slider.cssPrefix = props[i].replace('Perspective', '').toLowerCase();
slider.animProp = '-' + slider.cssPrefix + '-transform';
return true;
}
}
return false;
}());
// if vertical mode always make maxSlides and minSlides equal
if(slider.settings.mode == 'vertical') slider.settings.maxSlides = slider.settings.minSlides;
// save original style data
el.data("origStyle", el.attr("style"));
el.children(slider.settings.slideSelector).each(function() {
$(this).data("origStyle", $(this).attr("style"));
});
// perform all DOM / CSS modifications
setup();
};
/**
* Performs all DOM and CSS modifications
*/
var setup = function(){
// wrap el in a wrapper
el.wrap('');
// store a namspace reference to .bx-viewport
slider.viewport = el.parent();
// add a loading div to display while images are loading
slider.loader = $('');
slider.viewport.prepend(slider.loader);
// set el to a massive width, to hold any needed slides
// also strip any margin and padding from el
el.css({
width: slider.settings.mode == 'horizontal' ? (slider.children.length * 100 + 215) + '%' : 'auto',
position: 'relative'
});
// if using CSS, add the easing property
if(slider.usingCSS && slider.settings.easing){
el.css('-' + slider.cssPrefix + '-transition-timing-function', slider.settings.easing);
// if not using CSS and no easing value was supplied, use the default JS animation easing (swing)
}else if(!slider.settings.easing){
slider.settings.easing = 'swing';
}
var slidesShowing = getNumberSlidesShowing();
// make modifications to the viewport (.bx-viewport)
slider.viewport.css({
width: '100%',
overflow: 'hidden',
position: 'relative'
});
slider.viewport.parent().css({
maxWidth: getViewportMaxWidth()
});
// make modification to the wrapper (.bx-wrapper)
if(!slider.settings.pager) {
slider.viewport.parent().css({
margin: '0 auto 0px'
});
}
// apply css to all slider children
slider.children.css({
'float': slider.settings.mode == 'horizontal' ? 'left' : 'none',
listStyle: 'none',
position: 'relative'
});
// apply the calculated width after the float is applied to prevent scrollbar interference
slider.children.css('width', getSlideWidth());
// if slideMargin is supplied, add the css
if(slider.settings.mode == 'horizontal' && slider.settings.slideMargin > 0) slider.children.css('marginRight', slider.settings.slideMargin);
if(slider.settings.mode == 'vertical' && slider.settings.slideMargin > 0) slider.children.css('marginBottom', slider.settings.slideMargin);
// if "fade" mode, add positioning and z-index CSS
if(slider.settings.mode == 'fade'){
slider.children.css({
position: 'absolute',
zIndex: 0,
display: 'none'
});
// prepare the z-index on the showing element
slider.children.eq(slider.settings.startSlide).css({zIndex: slider.settings.slideZIndex, display: 'block'});
}
// create an element to contain all slider controls (pager, start / stop, etc)
slider.controls.el = $('');
// if captions are requested, add them
if(slider.settings.captions) appendCaptions();
// check if startSlide is last slide
slider.active.last = slider.settings.startSlide == getPagerQty() - 1;
// if video is true, set up the fitVids plugin
if(slider.settings.video) el.fitVids();
// set the default preload selector (visible)
var preloadSelector = slider.children.eq(slider.settings.startSlide);
if (slider.settings.preloadImages == "all") preloadSelector = slider.children;
// only check for control addition if not in "ticker" mode
if(!slider.settings.ticker){
// if pager is requested, add it
if(slider.settings.pager) appendPager();
// if controls are requested, add them
if(slider.settings.controls) appendControls();
// if auto is true, and auto controls are requested, add them
if(slider.settings.auto && slider.settings.autoControls) appendControlsAuto();
// if any control option is requested, add the controls wrapper
if(slider.settings.controls || slider.settings.autoControls || slider.settings.pager) slider.viewport.after(slider.controls.el);
// if ticker mode, do not allow a pager
}else{
slider.settings.pager = false;
}
// preload all images, then perform final DOM / CSS modifications that depend on images being loaded
loadElements(preloadSelector, start);
};
var loadElements = function(selector, callback){
var total = selector.find('img, iframe').length;
if (total == 0){
callback();
return;
}
var count = 0;
selector.find('img, iframe').each(function(){
$(this).one('load', function() {
if(++count == total) callback();
}).each(function() {
if(this.complete) $(this).load();
});
});
};
/**
* Start the slider
*/
var start = function(){
// if infinite loop, prepare additional slides
if(slider.settings.infiniteLoop && slider.settings.mode != 'fade' && !slider.settings.ticker){
var slice = slider.settings.mode == 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides;
var sliceAppend = slider.children.slice(0, slice).clone().addClass('bx-clone');
var slicePrepend = slider.children.slice(-slice).clone().addClass('bx-clone');
el.append(sliceAppend).prepend(slicePrepend);
}
// remove the loading DOM element
slider.loader.remove();
// set the left / top position of "el"
setSlidePosition();
// if "vertical" mode, always use adaptiveHeight to prevent odd behavior
if (slider.settings.mode == 'vertical') slider.settings.adaptiveHeight = true;
// set the viewport height
slider.viewport.height(getViewportHeight());
// make sure everything is positioned just right (same as a window resize)
el.redrawSlider();
// onSliderLoad callback
slider.settings.onSliderLoad(slider.active.index);
// slider has been fully initialized
slider.initialized = true;
// bind the resize call to the window
if (slider.settings.responsive) $(window).bind('resize', resizeWindow);
// if auto is true and has more than 1 page, start the show
if (slider.settings.auto && slider.settings.autoStart && (getPagerQty() > 1 || slider.settings.autoSlideForOnePage)) initAuto();
// if ticker is true, start the ticker
if (slider.settings.ticker) initTicker();
// if pager is requested, make the appropriate pager link active
if (slider.settings.pager) updatePagerActive(slider.settings.startSlide);
// check for any updates to the controls (like hideControlOnEnd updates)
if (slider.settings.controls) updateDirectionControls();
// if touchEnabled is true, setup the touch events
if (slider.settings.touchEnabled && !slider.settings.ticker) initTouch();
};
/**
* Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value
*/
var getViewportHeight = function(){
var height = 0;
// first determine which children (slides) should be used in our height calculation
var children = $();
// if mode is not "vertical" and adaptiveHeight is false, include all children
if(slider.settings.mode != 'vertical' && !slider.settings.adaptiveHeight){
children = slider.children;
}else{
// if not carousel, return the single active child
if(!slider.carousel){
children = slider.children.eq(slider.active.index);
// if carousel, return a slice of children
}else{
// get the individual slide index
var currentIndex = slider.settings.moveSlides == 1 ? slider.active.index : slider.active.index * getMoveBy();
// add the current slide to the children
children = slider.children.eq(currentIndex);
// cycle through the remaining "showing" slides
for (i = 1; i <= slider.settings.maxSlides - 1; i++){
// if looped back to the start
if(currentIndex + i >= slider.children.length){
children = children.add(slider.children.eq(i - 1));
}else{
children = children.add(slider.children.eq(currentIndex + i));
}
}
}
}
// if "vertical" mode, calculate the sum of the heights of the children
if(slider.settings.mode == 'vertical'){
children.each(function(index) {
height += $(this).outerHeight();
});
// add user-supplied margins
if(slider.settings.slideMargin > 0){
height += slider.settings.slideMargin * (slider.settings.minSlides - 1);
}
// if not "vertical" mode, calculate the max height of the children
}else{
height = Math.max.apply(Math, children.map(function(){
return $(this).outerHeight(false);
}).get());
}
if(slider.viewport.css('box-sizing') == 'border-box'){
height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')) +
parseFloat(slider.viewport.css('border-top-width')) + parseFloat(slider.viewport.css('border-bottom-width'));
}else if(slider.viewport.css('box-sizing') == 'padding-box'){
height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom'));
}
return height;
};
/**
* Returns the calculated width to be used for the outer wrapper / viewport
*/
var getViewportMaxWidth = function(){
var width = '100%';
if(slider.settings.slideWidth > 0){
if(slider.settings.mode == 'horizontal'){
width = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin);
}else{
width = slider.settings.slideWidth;
}
}
return width;
};
/**
* Returns the calculated width to be applied to each slide
*/
var getSlideWidth = function(){
// start with any user-supplied slide width
var newElWidth = slider.settings.slideWidth;
// get the current viewport width
var wrapWidth = slider.viewport.width();
// if slide width was not supplied, or is larger than the viewport use the viewport width
if(slider.settings.slideWidth == 0 ||
(slider.settings.slideWidth > wrapWidth && !slider.carousel) ||
slider.settings.mode == 'vertical'){
newElWidth = wrapWidth;
// if carousel, use the thresholds to determine the width
}else if(slider.settings.maxSlides > 1 && slider.settings.mode == 'horizontal'){
if(wrapWidth > slider.maxThreshold){
// newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.maxSlides - 1))) / slider.settings.maxSlides;
}else if(wrapWidth < slider.minThreshold){
newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides;
}
}
return newElWidth;
};
/**
* Returns the number of slides currently visible in the viewport (includes partially visible slides)
*/
var getNumberSlidesShowing = function(){
var slidesShowing = 1;
if(slider.settings.mode == 'horizontal' && slider.settings.slideWidth > 0){
// if viewport is smaller than minThreshold, return minSlides
if(slider.viewport.width() < slider.minThreshold){
slidesShowing = slider.settings.minSlides;
// if viewport is larger than minThreshold, return maxSlides
}else if(slider.viewport.width() > slider.maxThreshold){
slidesShowing = slider.settings.maxSlides;
// if viewport is between min / max thresholds, divide viewport width by first child width
}else{
var childWidth = slider.children.first().width() + slider.settings.slideMargin;
slidesShowing = Math.floor((slider.viewport.width() +
slider.settings.slideMargin) / childWidth);
}
// if "vertical" mode, slides showing will always be minSlides
}else if(slider.settings.mode == 'vertical'){
slidesShowing = slider.settings.minSlides;
}
return slidesShowing;
};
/**
* Returns the number of pages (one full viewport of slides is one "page")
*/
var getPagerQty = function(){
var pagerQty = 0;
// if moveSlides is specified by the user
if(slider.settings.moveSlides > 0){
if(slider.settings.infiniteLoop){
pagerQty = Math.ceil(slider.children.length / getMoveBy());
}else{
// use a while loop to determine pages
var breakPoint = 0;
var counter = 0;
// when breakpoint goes above children length, counter is the number of pages
while (breakPoint < slider.children.length){
++pagerQty;
breakPoint = counter + getNumberSlidesShowing();
counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing();
}
}
// if moveSlides is 0 (auto) divide children length by sides showing, then round up
}else{
pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing());
}
return pagerQty;
};
/**
* Returns the number of indivual slides by which to shift the slider
*/
var getMoveBy = function(){
// if moveSlides was set by the user and moveSlides is less than number of slides showing
if(slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()){
return slider.settings.moveSlides;
}
// if moveSlides is 0 (auto)
return getNumberSlidesShowing();
};
/**
* Sets the slider's (el) left or top position
*/
var setSlidePosition = function(){
// if last slide, not infinite loop, and number of children is larger than specified maxSlides
if(slider.children.length > slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop){
if (slider.settings.mode == 'horizontal'){
// get the last child's position
var lastChild = slider.children.last();
var position = lastChild.position();
// set the left position
setPositionProperty(-(position.left - (slider.viewport.width() - lastChild.outerWidth())), 'reset', 0);
}else if(slider.settings.mode == 'vertical'){
// get the last showing index's position
var lastShowingIndex = slider.children.length - slider.settings.minSlides;
var position = slider.children.eq(lastShowingIndex).position();
// set the top position
setPositionProperty(-position.top, 'reset', 0);
}
// if not last slide
}else{
// get the position of the first showing slide
var position = slider.children.eq(slider.active.index * getMoveBy()).position();
// check for last slide
if (slider.active.index == getPagerQty() - 1) slider.active.last = true;
// set the repective position
if (position != undefined){
if (slider.settings.mode == 'horizontal') setPositionProperty(-position.left, 'reset', 0);
else if (slider.settings.mode == 'vertical') setPositionProperty(-position.top, 'reset', 0);
}
}
};
/**
* Sets the el's animating property position (which in turn will sometimes animate el).
* If using CSS, sets the transform property. If not using CSS, sets the top / left property.
*
* @param value (int)
* - the animating property's value
*
* @param type (string) 'slider', 'reset', 'ticker'
* - the type of instance for which the function is being
*
* @param duration (int)
* - the amount of time (in ms) the transition should occupy
*
* @param params (array) optional
* - an optional parameter containing any variables that need to be passed in
*/
var setPositionProperty = function(value, type, duration, params){
// use CSS transform
if(slider.usingCSS){
// determine the translate3d value
var propValue = slider.settings.mode == 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)';
// add the CSS transition-duration
el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's');
if(type == 'slide'){
// set the property value
el.css(slider.animProp, propValue);
// bind a callback method - executes when CSS transition completes
el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){
// unbind the callback
el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
updateAfterSlideTransition();
});
}else if(type == 'reset'){
el.css(slider.animProp, propValue);
}else if(type == 'ticker'){
// make the transition use 'linear'
el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear');
el.css(slider.animProp, propValue);
// bind a callback method - executes when CSS transition completes
el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){
// unbind the callback
el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
// reset the position
setPositionProperty(params['resetValue'], 'reset', 0);
// start the loop again
tickerLoop();
});
}
// use JS animate
}else{
var animateObj = {};
animateObj[slider.animProp] = value;
if(type == 'slide'){
el.animate(animateObj, duration, slider.settings.easing, function(){
updateAfterSlideTransition();
});
}else if(type == 'reset'){
el.css(slider.animProp, value)
}else if(type == 'ticker'){
el.animate(animateObj, speed, 'linear', function(){
setPositionProperty(params['resetValue'], 'reset', 0);
// run the recursive loop after animation
tickerLoop();
});
}
}
};
/**
* Populates the pager with proper amount of pages
*/
var populatePager = function(){
var pagerHtml = '';
var pagerQty = getPagerQty();
// loop through each pager item
for(var i=0; i < pagerQty; i++){
var linkContent = '';
// if a buildPager function is supplied, use it to get pager link value, else use index + 1
if(slider.settings.buildPager && $.isFunction(slider.settings.buildPager)){
linkContent = slider.settings.buildPager(i);
slider.pagerEl.addClass('bx-custom-pager');
}else{
linkContent = i + 1;
slider.pagerEl.addClass('bx-default-pager');
}
// var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1;
// add the markup to the string
pagerHtml += '';
}
// populate the pager element with pager links
slider.pagerEl.html(pagerHtml);
};
/**
* Appends the pager to the controls element
*/
var appendPager = function(){
if(!slider.settings.pagerCustom){
// create the pager DOM element
slider.pagerEl = $('');
// if a pager selector was supplied, populate it with the pager
if(slider.settings.pagerSelector){
$(slider.settings.pagerSelector).html(slider.pagerEl);
// if no pager selector was supplied, add it after the wrapper
}else{
slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl);
}
// populate the pager
populatePager();
}else{
slider.pagerEl = $(slider.settings.pagerCustom);
}
// assign the pager click binding
slider.pagerEl.on('click', 'a', clickPagerBind);
};
/**
* Appends prev / next controls to the controls element
*/
var appendControls = function(){
slider.controls.next = $('' + slider.settings.nextText + '');
slider.controls.prev = $('' + slider.settings.prevText + '');
// bind click actions to the controls
slider.controls.next.bind('click', clickNextBind);
slider.controls.prev.bind('click', clickPrevBind);
// if nextSlector was supplied, populate it
if(slider.settings.nextSelector){
$(slider.settings.nextSelector).append(slider.controls.next);
}
// if prevSlector was supplied, populate it
if(slider.settings.prevSelector){
$(slider.settings.prevSelector).append(slider.controls.prev);
}
// if no custom selectors were supplied
if(!slider.settings.nextSelector && !slider.settings.prevSelector){
// add the controls to the DOM
slider.controls.directionEl = $('');
// add the control elements to the directionEl
slider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next);
// slider.viewport.append(slider.controls.directionEl);
slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl);
}
};
/**
* Appends start / stop auto controls to the controls element
*/
var appendControlsAuto = function(){
slider.controls.start = $('');
slider.controls.stop = $('');
// add the controls to the DOM
slider.controls.autoEl = $('');
// bind click actions to the controls
slider.controls.autoEl.on('click', '.bx-start', clickStartBind);
slider.controls.autoEl.on('click', '.bx-stop', clickStopBind);
// if autoControlsCombine, insert only the "start" control
if(slider.settings.autoControlsCombine){
slider.controls.autoEl.append(slider.controls.start);
// if autoControlsCombine is false, insert both controls
}else{
slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop);
}
// if auto controls selector was supplied, populate it with the controls
if(slider.settings.autoControlsSelector){
$(slider.settings.autoControlsSelector).html(slider.controls.autoEl);
// if auto controls selector was not supplied, add it after the wrapper
}else{
slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl);
}
// update the auto controls
updateAutoControls(slider.settings.autoStart ? 'stop' : 'start');
};
/**
* Appends image captions to the DOM
*/
var appendCaptions = function(){
// cycle through each child
slider.children.each(function(index){
// get the image title attribute
var title = $(this).find('img:first').attr('title');
// append the caption
if (title != undefined && ('' + title).length) {
$(this).append('' + title + '
');
}
});
};
/**
* Click next binding
*
* @param e (event)
* - DOM event object
*/
var clickNextBind = function(e){
// if auto show is running, stop it
if (slider.settings.auto) el.stopAuto();
el.goToNextSlide();
e.preventDefault();
};
/**
* Click prev binding
*
* @param e (event)
* - DOM event object
*/
var clickPrevBind = function(e){
// if auto show is running, stop it
if (slider.settings.auto) el.stopAuto();
el.goToPrevSlide();
e.preventDefault();
};
/**
* Click start binding
*
* @param e (event)
* - DOM event object
*/
var clickStartBind = function(e){
el.startAuto();
e.preventDefault();
};
/**
* Click stop binding
*
* @param e (event)
* - DOM event object
*/
var clickStopBind = function(e){
el.stopAuto();
e.preventDefault();
};
/**
* Click pager binding
*
* @param e (event)
* - DOM event object
*/
var clickPagerBind = function(e){
// if auto show is running, stop it
if (slider.settings.auto) el.stopAuto();
var pagerLink = $(e.currentTarget);
if(pagerLink.attr('data-slide-index') !== undefined){
var pagerIndex = parseInt(pagerLink.attr('data-slide-index'));
// if clicked pager link is not active, continue with the goToSlide call
if(pagerIndex != slider.active.index) el.goToSlide(pagerIndex);
e.preventDefault();
}
};
/**
* Updates the pager links with an active class
*
* @param slideIndex (int)
* - index of slide to make active
*/
var updatePagerActive = function(slideIndex){
// if "short" pager type
var len = slider.children.length; // nb of children
if(slider.settings.pagerType == 'short'){
if(slider.settings.maxSlides > 1) {
len = Math.ceil(slider.children.length/slider.settings.maxSlides);
}
slider.pagerEl.html( (slideIndex + 1) + slider.settings.pagerShortSeparator + len);
return;
}
// remove all pager active classes
slider.pagerEl.find('a').removeClass('active');
// apply the active class for all pagers
slider.pagerEl.each(function(i, el) { $(el).find('a').eq(slideIndex).addClass('active'); });
};
/**
* Performs needed actions after a slide transition
*/
var updateAfterSlideTransition = function(){
// if infinte loop is true
if(slider.settings.infiniteLoop){
var position = '';
// first slide
if(slider.active.index == 0){
// set the new position
position = slider.children.eq(0).position();
// carousel, last slide
}else if(slider.active.index == getPagerQty() - 1 && slider.carousel){
position = slider.children.eq((getPagerQty() - 1) * getMoveBy()).position();
// last slide
}else if(slider.active.index == slider.children.length - 1){
position = slider.children.eq(slider.children.length - 1).position();
}
if(position){
if (slider.settings.mode == 'horizontal') { setPositionProperty(-position.left, 'reset', 0); }
else if (slider.settings.mode == 'vertical') { setPositionProperty(-position.top, 'reset', 0); }
}
}
// declare that the transition is complete
slider.working = false;
// onSlideAfter callback
slider.settings.onSlideAfter(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
};
/**
* Updates the auto controls state (either active, or combined switch)
*
* @param state (string) "start", "stop"
* - the new state of the auto show
*/
var updateAutoControls = function(state){
// if autoControlsCombine is true, replace the current control with the new state
if(slider.settings.autoControlsCombine){
slider.controls.autoEl.html(slider.controls[state]);
// if autoControlsCombine is false, apply the "active" class to the appropriate control
}else{
slider.controls.autoEl.find('a').removeClass('active');
slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active');
}
};
/**
* Updates the direction controls (checks if either should be hidden)
*/
var updateDirectionControls = function(){
if(getPagerQty() == 1){
slider.controls.prev.addClass('disabled');
slider.controls.next.addClass('disabled');
}else if(!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd){
// if first slide
if (slider.active.index == 0){
slider.controls.prev.addClass('disabled');
slider.controls.next.removeClass('disabled');
// if last slide
}else if(slider.active.index == getPagerQty() - 1){
slider.controls.next.addClass('disabled');
slider.controls.prev.removeClass('disabled');
// if any slide in the middle
}else{
slider.controls.prev.removeClass('disabled');
slider.controls.next.removeClass('disabled');
}
}
};
/**
* Initialzes the auto process
*/
var initAuto = function(){
// if autoDelay was supplied, launch the auto show using a setTimeout() call
if(slider.settings.autoDelay > 0){
var timeout = setTimeout(el.startAuto, slider.settings.autoDelay);
// if autoDelay was not supplied, start the auto show normally
}else{
el.startAuto();
}
// if autoHover is requested
if(slider.settings.autoHover){
// on el hover
el.hover(function(){
// if the auto show is currently playing (has an active interval)
if(slider.interval){
// stop the auto show and pass true agument which will prevent control update
el.stopAuto(true);
// create a new autoPaused value which will be used by the relative "mouseout" event
slider.autoPaused = true;
}
}, function(){
// if the autoPaused value was created be the prior "mouseover" event
if(slider.autoPaused){
// start the auto show and pass true agument which will prevent control update
el.startAuto(true);
// reset the autoPaused value
slider.autoPaused = null;
}
});
}
};
/**
* Initialzes the ticker process
*/
var initTicker = function(){
var startPosition = 0;
// if autoDirection is "next", append a clone of the entire slider
if(slider.settings.autoDirection == 'next'){
el.append(slider.children.clone().addClass('bx-clone'));
// if autoDirection is "prev", prepend a clone of the entire slider, and set the left position
}else{
el.prepend(slider.children.clone().addClass('bx-clone'));
var position = slider.children.first().position();
startPosition = slider.settings.mode == 'horizontal' ? -position.left : -position.top;
}
setPositionProperty(startPosition, 'reset', 0);
// do not allow controls in ticker mode
slider.settings.pager = false;
slider.settings.controls = false;
slider.settings.autoControls = false;
// if autoHover is requested
if(slider.settings.tickerHover && !slider.usingCSS){
// on el hover
slider.viewport.hover(function(){
el.stop();
}, function(){
// calculate the total width of children (used to calculate the speed ratio)
var totalDimens = 0;
slider.children.each(function(index){
totalDimens += slider.settings.mode == 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true);
});
// calculate the speed ratio (used to determine the new speed to finish the paused animation)
var ratio = slider.settings.speed / totalDimens;
// determine which property to use
var property = slider.settings.mode == 'horizontal' ? 'left' : 'top';
// calculate the new speed
var newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property)))));
tickerLoop(newSpeed);
});
}
// start the ticker loop
tickerLoop();
};
/**
* Runs a continuous loop, news ticker-style
*/
var tickerLoop = function(resumeSpeed){
speed = resumeSpeed ? resumeSpeed : slider.settings.speed;
var position = {left: 0, top: 0};
var reset = {left: 0, top: 0};
// if "next" animate left position to last child, then reset left to 0
if(slider.settings.autoDirection == 'next'){
position = el.find('.bx-clone').first().position();
// if "prev" animate left position to 0, then reset left to first non-clone child
}else{
reset = slider.children.first().position();
}
var animateProperty = slider.settings.mode == 'horizontal' ? -position.left : -position.top;
var resetValue = slider.settings.mode == 'horizontal' ? -reset.left : -reset.top;
var params = {resetValue: resetValue};
setPositionProperty(animateProperty, 'ticker', speed, params);
};
/**
* Initializes touch events
*/
var initTouch = function(){
// initialize object to contain all touch values
slider.touch = {
start: {x: 0, y: 0},
end: {x: 0, y: 0}
};
slider.viewport.bind('touchstart', onTouchStart);
};
/**
* Event handler for "touchstart"
*
* @param e (event)
* - DOM event object
*/
var onTouchStart = function(e){
if(slider.working){
e.preventDefault();
}else{
// record the original position when touch starts
slider.touch.originalPos = el.position();
var orig = e.originalEvent;
// record the starting touch x, y coordinates
slider.touch.start.x = orig.changedTouches[0].pageX;
slider.touch.start.y = orig.changedTouches[0].pageY;
// bind a "touchmove" event to the viewport
slider.viewport.bind('touchmove', onTouchMove);
// bind a "touchend" event to the viewport
slider.viewport.bind('touchend', onTouchEnd);
}
};
/**
* Event handler for "touchmove"
*
* @param e (event)
* - DOM event object
*/
var onTouchMove = function(e){
var orig = e.originalEvent;
// if scrolling on y axis, do not prevent default
var xMovement = Math.abs(orig.changedTouches[0].pageX - slider.touch.start.x);
var yMovement = Math.abs(orig.changedTouches[0].pageY - slider.touch.start.y);
// x axis swipe
if((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX){
e.preventDefault();
// y axis swipe
}else if((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY){
e.preventDefault();
}
if(slider.settings.mode != 'fade' && slider.settings.oneToOneTouch){
var value = 0;
// if horizontal, drag along x axis
if(slider.settings.mode == 'horizontal'){
var change = orig.changedTouches[0].pageX - slider.touch.start.x;
value = slider.touch.originalPos.left + change;
// if vertical, drag along y axis
}else{
var change = orig.changedTouches[0].pageY - slider.touch.start.y;
value = slider.touch.originalPos.top + change;
}
setPositionProperty(value, 'reset', 0);
}
};
/**
* Event handler for "touchend"
*
* @param e (event)
* - DOM event object
*/
var onTouchEnd = function(e){
slider.viewport.unbind('touchmove', onTouchMove);
var orig = e.originalEvent;
var value = 0;
// record end x, y positions
slider.touch.end.x = orig.changedTouches[0].pageX;
slider.touch.end.y = orig.changedTouches[0].pageY;
// if fade mode, check if absolute x distance clears the threshold
if(slider.settings.mode == 'fade'){
var distance = Math.abs(slider.touch.start.x - slider.touch.end.x);
if(distance >= slider.settings.swipeThreshold){
slider.touch.start.x > slider.touch.end.x ? el.goToNextSlide() : el.goToPrevSlide();
el.stopAuto();
}
// not fade mode
}else{
var distance = 0;
// calculate distance and el's animate property
if(slider.settings.mode == 'horizontal'){
distance = slider.touch.end.x - slider.touch.start.x;
value = slider.touch.originalPos.left;
}else{
distance = slider.touch.end.y - slider.touch.start.y;
value = slider.touch.originalPos.top;
}
// if not infinite loop and first / last slide, do not attempt a slide transition
if(!slider.settings.infiniteLoop && ((slider.active.index == 0 && distance > 0) || (slider.active.last && distance < 0))){
setPositionProperty(value, 'reset', 200);
}else{
// check if distance clears threshold
if(Math.abs(distance) >= slider.settings.swipeThreshold){
distance < 0 ? el.goToNextSlide() : el.goToPrevSlide();
el.stopAuto();
}else{
// el.animate(property, 200);
setPositionProperty(value, 'reset', 200);
}
}
}
slider.viewport.unbind('touchend', onTouchEnd);
};
/**
* Window resize event callback
*/
var resizeWindow = function(e){
// don't do anything if slider isn't initialized.
if(!slider.initialized) return;
// get the new window dimens (again, thank you IE)
var windowWidthNew = $(window).width();
var windowHeightNew = $(window).height();
// make sure that it is a true window resize
// *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements
// are resized. Can you just die already?*
if(windowWidth != windowWidthNew || windowHeight != windowHeightNew){
// set the new window dimens
windowWidth = windowWidthNew;
windowHeight = windowHeightNew;
// update all dynamic elements
el.redrawSlider();
// Call user resize handler
slider.settings.onSliderResize.call(el, slider.active.index);
}
};
/**
* ===================================================================================
* = PUBLIC FUNCTIONS
* ===================================================================================
*/
/**
* Performs slide transition to the specified slide
*
* @param slideIndex (int)
* - the destination slide's index (zero-based)
*
* @param direction (string)
* - INTERNAL USE ONLY - the direction of travel ("prev" / "next")
*/
el.goToSlide = function(slideIndex, direction){
// if plugin is currently in motion, ignore request
if(slider.working || slider.active.index == slideIndex) return;
// declare that plugin is in motion
slider.working = true;
// store the old index
slider.oldIndex = slider.active.index;
// if slideIndex is less than zero, set active index to last child (this happens during infinite loop)
if(slideIndex < 0){
slider.active.index = getPagerQty() - 1;
// if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop)
}else if(slideIndex >= getPagerQty()){
slider.active.index = 0;
// set active index to requested slide
}else{
slider.active.index = slideIndex;
}
// onSlideBefore, onSlideNext, onSlidePrev callbacks
slider.settings.onSlideBefore(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
if(direction == 'next'){
slider.settings.onSlideNext(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
}else if(direction == 'prev'){
slider.settings.onSlidePrev(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
}
// check if last slide
slider.active.last = slider.active.index >= getPagerQty() - 1;
// update the pager with active class
if(slider.settings.pager) updatePagerActive(slider.active.index);
// // check for direction control update
if(slider.settings.controls) updateDirectionControls();
// if slider is set to mode: "fade"
if(slider.settings.mode == 'fade'){
// if adaptiveHeight is true and next height is different from current height, animate to the new height
if(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){
slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);
}
// fade out the visible child and reset its z-index value
slider.children.filter(':visible').fadeOut(slider.settings.speed).css({zIndex: 0});
// fade in the newly requested slide
slider.children.eq(slider.active.index).css('zIndex', slider.settings.slideZIndex+1).fadeIn(slider.settings.speed, function(){
$(this).css('zIndex', slider.settings.slideZIndex);
updateAfterSlideTransition();
});
// slider mode is not "fade"
}else{
// if adaptiveHeight is true and next height is different from current height, animate to the new height
if(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){
slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);
}
var moveBy = 0;
var position = {left: 0, top: 0};
// if carousel and not infinite loop
if(!slider.settings.infiniteLoop && slider.carousel && slider.active.last){
if(slider.settings.mode == 'horizontal'){
// get the last child position
var lastChild = slider.children.eq(slider.children.length - 1);
position = lastChild.position();
// calculate the position of the last slide
moveBy = slider.viewport.width() - lastChild.outerWidth();
}else{
// get last showing index position
var lastShowingIndex = slider.children.length - slider.settings.minSlides;
position = slider.children.eq(lastShowingIndex).position();
}
// horizontal carousel, going previous while on first slide (infiniteLoop mode)
}else if(slider.carousel && slider.active.last && direction == 'prev'){
// get the last child position
var eq = slider.settings.moveSlides == 1 ? slider.settings.maxSlides - getMoveBy() : ((getPagerQty() - 1) * getMoveBy()) - (slider.children.length - slider.settings.maxSlides);
var lastChild = el.children('.bx-clone').eq(eq);
position = lastChild.position();
// if infinite loop and "Next" is clicked on the last slide
}else if(direction == 'next' && slider.active.index == 0){
// get the last clone position
position = el.find('> .bx-clone').eq(slider.settings.maxSlides).position();
slider.active.last = false;
// normal non-zero requests
}else if(slideIndex >= 0){
var requestEl = slideIndex * getMoveBy();
position = slider.children.eq(requestEl).position();
}
/* If the position doesn't exist
* (e.g. if you destroy the slider on a next click),
* it doesn't throw an error.
*/
if ("undefined" !== typeof(position)) {
var value = slider.settings.mode == 'horizontal' ? -(position.left - moveBy) : -position.top;
// plugin values to be animated
setPositionProperty(value, 'slide', slider.settings.speed);
}
}
};
/**
* Transitions to the next slide in the show
*/
el.goToNextSlide = function(){
// if infiniteLoop is false and last page is showing, disregard call
if (!slider.settings.infiniteLoop && slider.active.last) return;
var pagerIndex = parseInt(slider.active.index) + 1;
el.goToSlide(pagerIndex, 'next');
};
/**
* Transitions to the prev slide in the show
*/
el.goToPrevSlide = function(){
// if infiniteLoop is false and last page is showing, disregard call
if (!slider.settings.infiniteLoop && slider.active.index == 0) return;
var pagerIndex = parseInt(slider.active.index) - 1;
el.goToSlide(pagerIndex, 'prev');
};
/**
* Starts the auto show
*
* @param preventControlUpdate (boolean)
* - if true, auto controls state will not be updated
*/
el.startAuto = function(preventControlUpdate){
// if an interval already exists, disregard call
if(slider.interval) return;
// create an interval
slider.interval = setInterval(function(){
slider.settings.autoDirection == 'next' ? el.goToNextSlide() : el.goToPrevSlide();
}, slider.settings.pause);
// if auto controls are displayed and preventControlUpdate is not true
if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('stop');
};
/**
* Stops the auto show
*
* @param preventControlUpdate (boolean)
* - if true, auto controls state will not be updated
*/
el.stopAuto = function(preventControlUpdate){
// if no interval exists, disregard call
if(!slider.interval) return;
// clear the interval
clearInterval(slider.interval);
slider.interval = null;
// if auto controls are displayed and preventControlUpdate is not true
if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('start');
};
/**
* Returns current slide index (zero-based)
*/
el.getCurrentSlide = function(){
return slider.active.index;
};
/**
* Returns current slide element
*/
el.getCurrentSlideElement = function(){
return slider.children.eq(slider.active.index);
};
/**
* Returns number of slides in show
*/
el.getSlideCount = function(){
return slider.children.length;
};
/**
* Update all dynamic slider elements
*/
el.redrawSlider = function(){
// resize all children in ratio to new screen size
slider.children.add(el.find('.bx-clone')).width(getSlideWidth());
// adjust the height
slider.viewport.css('height', getViewportHeight());
// update the slide position
if(!slider.settings.ticker) setSlidePosition();
// if active.last was true before the screen resize, we want
// to keep it last no matter what screen size we end on
if (slider.active.last) slider.active.index = getPagerQty() - 1;
// if the active index (page) no longer exists due to the resize, simply set the index as last
if (slider.active.index >= getPagerQty()) slider.active.last = true;
// if a pager is being displayed and a custom pager is not being used, update it
if(slider.settings.pager && !slider.settings.pagerCustom){
populatePager();
updatePagerActive(slider.active.index);
}
};
/**
* Destroy the current instance of the slider (revert everything back to original state)
*/
el.destroySlider = function(){
// don't do anything if slider has already been destroyed
if(!slider.initialized) return;
slider.initialized = false;
$('.bx-clone', this).remove();
slider.children.each(function() {
$(this).data("origStyle") != undefined ? $(this).attr("style", $(this).data("origStyle")) : $(this).removeAttr('style');
});
$(this).data("origStyle") != undefined ? this.attr("style", $(this).data("origStyle")) : $(this).removeAttr('style');
$(this).unwrap().unwrap();
if(slider.controls.el) slider.controls.el.remove();
if(slider.controls.next) slider.controls.next.remove();
if(slider.controls.prev) slider.controls.prev.remove();
if(slider.pagerEl && slider.settings.controls) slider.pagerEl.remove();
$('.bx-caption', this).remove();
if(slider.controls.autoEl) slider.controls.autoEl.remove();
clearInterval(slider.interval);
if(slider.settings.responsive) $(window).unbind('resize', resizeWindow);
};
/**
* Reload the slider (revert all DOM changes, and re-initialize)
*/
el.reloadSlider = function(settings){
if (settings != undefined) options = settings;
el.destroySlider();
init();
};
init();
// returns the current jQuery object
return this;
}
})(jQuery);
/*!
* jQuery Cookie Plugin v1.4.1
* https://github.com/carhartl/jquery-cookie
*
* Copyright 2006, 2014 Klaus Hartl
* Released under the MIT license
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// CommonJS
factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var pluses = /\+/g;
function encode(s) {
return config.raw ? s : encodeURIComponent(s);
}
function decode(s) {
return config.raw ? s : decodeURIComponent(s);
}
function stringifyCookieValue(value) {
return encode(config.json ? JSON.stringify(value) : String(value));
}
function parseCookieValue(s) {
if (s.indexOf('"') === 0) {
// This is a quoted cookie as according to RFC2068, unescape...
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
}
try {
// Replace server-side written pluses with spaces.
// If we can't decode the cookie, ignore it, it's unusable.
// If we can't parse the cookie, ignore it, it's unusable.
s = decodeURIComponent(s.replace(pluses, ' '));
return config.json ? JSON.parse(s) : s;
} catch(e) {}
}
function read(s, converter) {
var value = config.raw ? s : parseCookieValue(s);
return $.isFunction(converter) ? converter(value) : value;
}
var config = $.cookie = function (key, value, options) {
// Write
if (arguments.length > 1 && !$.isFunction(value)) {
options = $.extend({}, config.defaults, options);
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setTime(+t + days * 864e+5);
}
return (document.cookie = [
encode(key), '=', stringifyCookieValue(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
}
// Read
var result = key ? undefined : {};
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling $.cookie().
var cookies = document.cookie ? document.cookie.split('; ') : [];
for (var i = 0, l = cookies.length; i < l; i++) {
var parts = cookies[i].split('=');
var name = decode(parts.shift());
var cookie = parts.join('=');
if (key && key === name) {
// If second argument (value) is a function it's a converter...
result = read(cookie, value);
break;
}
// Prevent storing a cookie that we couldn't decode.
if (!key && (cookie = read(cookie)) !== undefined) {
result[name] = cookie;
}
}
return result;
};
config.defaults = {};
$.removeCookie = function (key, options) {
if ($.cookie(key) === undefined) {
return false;
}
// Must not alter options, thus extending a fresh object...
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
return !$.cookie(key);
};
}));
( function( $ ) {
$.fn.hoverfold = function( args ) {
this.each( function() {
$( this ).children( '.view' ).each( function() {
var $item = $( this ),
img = $item.children( 'img' ).attr( 'src' ),
struct = '';
struct +='
';
struct +='
';
struct +='
';
struct +='
';
struct +='
';
struct +='
';
struct +='
';
struct +='
';
struct +='
';
var $struct = $( struct );
$item.find( 'img' ).remove().end().append( $struct ).find( 'div.slice' ).css( 'background-image', 'url(' + img + ')' ).prepend( $( '' ) );
} );
});
};
} )( jQuery );
/**
* jquery-match-height 0.7.0 by @liabru
* http://brm.io/jquery-match-height/
* License: MIT
*/
;(function(factory) { // eslint-disable-line no-extra-semi
'use strict';
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof module !== 'undefined' && module.exports) {
// CommonJS
module.exports = factory(require('jquery'));
} else {
// Global
factory(jQuery);
}
})(function($) {
/*
* internal
*/
var _previousResizeWidth = -1,
_updateTimeout = -1;
/*
* _parse
* value parse utility function
*/
var _parse = function(value) {
// parse value and convert NaN to 0
return parseFloat(value) || 0;
};
/*
* _rows
* utility function returns array of jQuery selections representing each row
* (as displayed after float wrapping applied by browser)
*/
var _rows = function(elements) {
var tolerance = 1,
$elements = $(elements),
lastTop = null,
rows = [];
// group elements by their top position
$elements.each(function(){
var $that = $(this),
top = $that.offset().top - _parse($that.css('margin-top')),
lastRow = rows.length > 0 ? rows[rows.length - 1] : null;
if (lastRow === null) {
// first item on the row, so just push it
rows.push($that);
} else {
// if the row top is the same, add to the row group
if (Math.floor(Math.abs(lastTop - top)) <= tolerance) {
rows[rows.length - 1] = lastRow.add($that);
} else {
// otherwise start a new row group
rows.push($that);
}
}
// keep track of the last row top
lastTop = top;
});
return rows;
};
/*
* _parseOptions
* handle plugin options
*/
var _parseOptions = function(options) {
var opts = {
byRow: true,
property: 'height',
target: null,
remove: false
};
if (typeof options === 'object') {
return $.extend(opts, options);
}
if (typeof options === 'boolean') {
opts.byRow = options;
} else if (options === 'remove') {
opts.remove = true;
}
return opts;
};
/*
* matchHeight
* plugin definition
*/
var matchHeight = $.fn.matchHeight = function(options) {
var opts = _parseOptions(options);
// handle remove
if (opts.remove) {
var that = this;
// remove fixed height from all selected elements
this.css(opts.property, '');
// remove selected elements from all groups
$.each(matchHeight._groups, function(key, group) {
group.elements = group.elements.not(that);
});
// TODO: cleanup empty groups
return this;
}
if (this.length <= 1 && !opts.target) {
return this;
}
// keep track of this group so we can re-apply later on load and resize events
matchHeight._groups.push({
elements: this,
options: opts
});
// match each element's height to the tallest element in the selection
matchHeight._apply(this, opts);
return this;
};
/*
* plugin global options
*/
matchHeight.version = '0.7.0';
matchHeight._groups = [];
matchHeight._throttle = 80;
matchHeight._maintainScroll = false;
matchHeight._beforeUpdate = null;
matchHeight._afterUpdate = null;
matchHeight._rows = _rows;
matchHeight._parse = _parse;
matchHeight._parseOptions = _parseOptions;
/*
* matchHeight._apply
* apply matchHeight to given elements
*/
matchHeight._apply = function(elements, options) {
var opts = _parseOptions(options),
$elements = $(elements),
rows = [$elements];
// take note of scroll position
var scrollTop = $(window).scrollTop(),
htmlHeight = $('html').outerHeight(true);
// get hidden parents
var $hiddenParents = $elements.parents().filter(':hidden');
// cache the original inline style
$hiddenParents.each(function() {
var $that = $(this);
$that.data('style-cache', $that.attr('style'));
});
// temporarily must force hidden parents visible
$hiddenParents.css('display', 'block');
// get rows if using byRow, otherwise assume one row
if (opts.byRow && !opts.target) {
// must first force an arbitrary equal height so floating elements break evenly
$elements.each(function() {
var $that = $(this),
display = $that.css('display');
// temporarily force a usable display value
if (display !== 'inline-block' && display !== 'flex' && display !== 'inline-flex') {
display = 'block';
}
// cache the original inline style
$that.data('style-cache', $that.attr('style'));
$that.css({
'display': display,
'padding-top': '0',
'padding-bottom': '0',
'margin-top': '0',
'margin-bottom': '0',
'border-top-width': '0',
'border-bottom-width': '0',
'height': '100px',
'overflow': 'hidden'
});
});
// get the array of rows (based on element top position)
rows = _rows($elements);
// revert original inline styles
$elements.each(function() {
var $that = $(this);
$that.attr('style', $that.data('style-cache') || '');
});
}
$.each(rows, function(key, row) {
var $row = $(row),
targetHeight = 0;
if (!opts.target) {
// skip apply to rows with only one item
if (opts.byRow && $row.length <= 1) {
$row.css(opts.property, '');
return;
}
// iterate the row and find the max height
$row.each(function(){
var $that = $(this),
style = $that.attr('style'),
display = $that.css('display');
// temporarily force a usable display value
if (display !== 'inline-block' && display !== 'flex' && display !== 'inline-flex') {
display = 'block';
}
// ensure we get the correct actual height (and not a previously set height value)
var css = { 'display': display };
css[opts.property] = '';
$that.css(css);
// find the max height (including padding, but not margin)
if ($that.outerHeight(false) > targetHeight) {
targetHeight = $that.outerHeight(false);
}
// revert styles
if (style) {
$that.attr('style', style);
} else {
$that.css('display', '');
}
});
} else {
// if target set, use the height of the target element
targetHeight = opts.target.outerHeight(false);
}
// iterate the row and apply the height to all elements
$row.each(function(){
var $that = $(this),
verticalPadding = 0;
// don't apply to a target
if (opts.target && $that.is(opts.target)) {
return;
}
// handle padding and border correctly (required when not using border-box)
if ($that.css('box-sizing') !== 'border-box') {
verticalPadding += _parse($that.css('border-top-width')) + _parse($that.css('border-bottom-width'));
verticalPadding += _parse($that.css('padding-top')) + _parse($that.css('padding-bottom'));
}
// set the height (accounting for padding and border)
$that.css(opts.property, (targetHeight - verticalPadding) + 'px');
});
});
// revert hidden parents
$hiddenParents.each(function() {
var $that = $(this);
$that.attr('style', $that.data('style-cache') || null);
});
// restore scroll position if enabled
if (matchHeight._maintainScroll) {
$(window).scrollTop((scrollTop / htmlHeight) * $('html').outerHeight(true));
}
return this;
};
/*
* matchHeight._applyDataApi
* applies matchHeight to all elements with a data-match-height attribute
*/
matchHeight._applyDataApi = function() {
var groups = {};
// generate groups by their groupId set by elements using data-match-height
$('[data-match-height], [data-mh]').each(function() {
var $this = $(this),
groupId = $this.attr('data-mh') || $this.attr('data-match-height');
if (groupId in groups) {
groups[groupId] = groups[groupId].add($this);
} else {
groups[groupId] = $this;
}
});
// apply matchHeight to each group
$.each(groups, function() {
this.matchHeight(true);
});
};
/*
* matchHeight._update
* updates matchHeight on all current groups with their correct options
*/
var _update = function(event) {
if (matchHeight._beforeUpdate) {
matchHeight._beforeUpdate(event, matchHeight._groups);
}
$.each(matchHeight._groups, function() {
matchHeight._apply(this.elements, this.options);
});
if (matchHeight._afterUpdate) {
matchHeight._afterUpdate(event, matchHeight._groups);
}
};
matchHeight._update = function(throttle, event) {
// prevent update if fired from a resize event
// where the viewport width hasn't actually changed
// fixes an event looping bug in IE8
if (event && event.type === 'resize') {
var windowWidth = $(window).width();
if (windowWidth === _previousResizeWidth) {
return;
}
_previousResizeWidth = windowWidth;
}
// throttle updates
if (!throttle) {
_update(event);
} else if (_updateTimeout === -1) {
_updateTimeout = setTimeout(function() {
_update(event);
_updateTimeout = -1;
}, matchHeight._throttle);
}
};
/*
* bind events
*/
// apply on DOM ready event
$(matchHeight._applyDataApi);
// update heights on load and resize events
$(window).bind('load', function(event) {
matchHeight._update(false, event);
});
// throttled update heights on resize events
$(window).bind('resize orientationchange', function(event) {
matchHeight._update(true, event);
});
});
/*! SmartMenus jQuery Plugin - v0.9.7 - August 25, 2014
* http://www.smartmenus.org/
* Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. http://vadikom.com; Licensed MIT */(function(t){function i(i){var a=".smartmenus_mouse";if(h||i)h&&i&&(t(document).unbind(a),h=!1);else{var u=!0,l=null;t(document).bind(o([["mousemove",function(i){var e={x:i.pageX,y:i.pageY,timeStamp:(new Date).getTime()};if(l){var s=Math.abs(l.x-e.x),o=Math.abs(l.y-e.y);if((s>0||o>0)&&2>=s&&2>=o&&300>=e.timeStamp-l.timeStamp&&(r=!0,u)){var a=t(i.target).closest("a");a.is("a")&&t.each(n,function(){return t.contains(this.$root[0],a[0])?(this.itemEnter({currentTarget:a[0]}),!1):void 0}),u=!1}}l=e}],[s()?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut",function(t){e(t.originalEvent)&&(r=!1)}]],a)),h=!0}}function e(t){return!/^(4|mouse)$/.test(t.pointerType)}function s(){return"ontouchstart"in window}function o(i,e){e||(e="");var s={};return t.each(i,function(t,i){s[i[0].split(" ").join(e+" ")+e]=i[1]}),s}var n=[],a=!!window.createPopup,r=!1,h=!1;t.SmartMenus=function(i,e){this.$root=t(i),this.opts=e,this.rootId="",this.$subArrow=null,this.subMenus=[],this.activatedItems=[],this.visibleSubMenus=[],this.showTimeout=0,this.hideTimeout=0,this.scrollTimeout=0,this.clickActivated=!1,this.zIndexInc=0,this.$firstLink=null,this.$firstSub=null,this.disabled=!1,this.$disableOverlay=null,this.isTouchScrolling=!1,this.init()},t.extend(t.SmartMenus,{hideAll:function(){t.each(n,function(){this.menuHideAll()})},destroy:function(){for(;n.length;)n[0].destroy();i(!0)},prototype:{init:function(e){var s=this;if(!e){n.push(this),this.rootId=((new Date).getTime()+Math.random()+"").replace(/\D/g,""),this.$root.hasClass("sm-rtl")&&(this.opts.rightToLeftSubMenus=!0);var a=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).bind(o([["mouseover focusin",t.proxy(this.rootOver,this)],["mouseout focusout",t.proxy(this.rootOut,this)]],a)).delegate("a",o([["mouseenter",t.proxy(this.itemEnter,this)],["mouseleave",t.proxy(this.itemLeave,this)],["mousedown",t.proxy(this.itemDown,this)],["focus",t.proxy(this.itemFocus,this)],["blur",t.proxy(this.itemBlur,this)],["click",t.proxy(this.itemClick,this)],["touchend",t.proxy(this.itemTouchEnd,this)]],a)),a+=this.rootId,this.opts.hideOnClick&&t(document).bind(o([["touchstart",t.proxy(this.docTouchStart,this)],["touchmove",t.proxy(this.docTouchMove,this)],["touchend",t.proxy(this.docTouchEnd,this)],["click",t.proxy(this.docClick,this)]],a)),t(window).bind(o([["resize orientationchange",t.proxy(this.winResize,this)]],a)),this.opts.subIndicators&&(this.$subArrow=t("").addClass("sub-arrow"),this.opts.subIndicatorsText&&this.$subArrow.html(this.opts.subIndicatorsText)),i()}if(this.$firstSub=this.$root.find("ul").each(function(){s.menuInit(t(this))}).eq(0),this.$firstLink=this.$root.find("a").eq(0),this.opts.markCurrentItem){var r=/(index|default)\.[^#\?\/]*/i,h=/#.*/,u=window.location.href.replace(r,""),l=u.replace(h,"");this.$root.find("a").each(function(){var i=this.href.replace(r,""),e=t(this);(i==u||i==l)&&(e.addClass("current"),s.opts.markCurrentTree&&e.parent().parentsUntil("[data-smartmenus-id]","li").children("a").addClass("current"))})}},destroy:function(){this.menuHideAll();var i=".smartmenus";this.$root.removeData("smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").unbind(i).undelegate(i),i+=this.rootId,t(document).unbind(i),t(window).unbind(i),this.opts.subIndicators&&(this.$subArrow=null);var e=this;t.each(this.subMenus,function(){this.hasClass("mega-menu")&&this.find("ul").removeDataSM("in-mega"),this.dataSM("shown-before")&&((e.opts.subMenusMinWidth||e.opts.subMenusMaxWidth)&&this.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap"),this.dataSM("scroll-arrows")&&this.dataSM("scroll-arrows").remove(),this.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})),e.opts.subIndicators&&this.dataSM("parent-a").removeClass("has-submenu").children("span.sub-arrow").remove(),this.removeDataSM("shown-before").removeDataSM("ie-shim").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").parent().removeDataSM("sub")}),this.opts.markCurrentItem&&this.$root.find("a.current").removeClass("current"),this.$root=null,this.$firstLink=null,this.$firstSub=null,this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),n.splice(t.inArray(this,n),1)},disable:function(i){if(!this.disabled){if(this.menuHideAll(),!i&&!this.opts.isPopup&&this.$root.is(":visible")){var e=this.$root.offset();this.$disableOverlay=t('').css({position:"absolute",top:e.top,left:e.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(!0),opacity:0}).appendTo(document.body)}this.disabled=!0}},docClick:function(i){return this.isTouchScrolling?(this.isTouchScrolling=!1,void 0):((this.visibleSubMenus.length&&!t.contains(this.$root[0],i.target)||t(i.target).is("a"))&&this.menuHideAll(),void 0)},docTouchEnd:function(){if(this.lastTouch){if(!(!this.visibleSubMenus.length||void 0!==this.lastTouch.x2&&this.lastTouch.x1!=this.lastTouch.x2||void 0!==this.lastTouch.y2&&this.lastTouch.y1!=this.lastTouch.y2||this.lastTouch.target&&t.contains(this.$root[0],this.lastTouch.target))){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var i=this;this.hideTimeout=setTimeout(function(){i.menuHideAll()},350)}this.lastTouch=null}},docTouchMove:function(t){if(this.lastTouch){var i=t.originalEvent.touches[0];this.lastTouch.x2=i.pageX,this.lastTouch.y2=i.pageY}},docTouchStart:function(t){var i=t.originalEvent.touches[0];this.lastTouch={x1:i.pageX,y1:i.pageY,target:i.target}},enable:function(){this.disabled&&(this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),this.disabled=!1)},getClosestMenu:function(i){for(var e=t(i).closest("ul");e.dataSM("in-mega");)e=e.parent().closest("ul");return e[0]||null},getHeight:function(t){return this.getOffset(t,!0)},getOffset:function(t,i){var e;"none"==t.css("display")&&(e={position:t[0].style.position,visibility:t[0].style.visibility},t.css({position:"absolute",visibility:"hidden"}).show());var s=t[0].getBoundingClientRect&&t[0].getBoundingClientRect(),o=s&&(i?s.height||s.bottom-s.top:s.width||s.right-s.left);return o||0===o||(o=i?t[0].offsetHeight:t[0].offsetWidth),e&&t.hide().css(e),o},getStartZIndex:function(t){var i=parseInt(this[t?"$root":"$firstSub"].css("z-index"));return!t&&isNaN(i)&&(i=parseInt(this.$root.css("z-index"))),isNaN(i)?1:i},getTouchPoint:function(t){return t.touches&&t.touches[0]||t.changedTouches&&t.changedTouches[0]||t},getViewport:function(t){var i=t?"Height":"Width",e=document.documentElement["client"+i],s=window["inner"+i];return s&&(e=Math.min(e,s)),e},getViewportHeight:function(){return this.getViewport(!0)},getViewportWidth:function(){return this.getViewport()},getWidth:function(t){return this.getOffset(t)},handleEvents:function(){return!this.disabled&&this.isCSSOn()},handleItemEvents:function(t){return this.handleEvents()&&!this.isLinkInMegaMenu(t)},isCollapsible:function(){return"static"==this.$firstSub.css("position")},isCSSOn:function(){return"block"==this.$firstLink.css("display")},isFixed:function(){var i="fixed"==this.$root.css("position");return i||this.$root.parentsUntil("body").each(function(){return"fixed"==t(this).css("position")?(i=!0,!1):void 0}),i},isLinkInMegaMenu:function(t){return!t.parent().parent().dataSM("level")},isTouchMode:function(){return!r||this.isCollapsible()},itemActivate:function(i){var e=i.parent(),s=e.parent(),o=s.dataSM("level");if(o>1&&(!this.activatedItems[o-2]||this.activatedItems[o-2][0]!=s.dataSM("parent-a")[0])){var n=this;t(s.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(s).each(function(){n.itemActivate(t(this).dataSM("parent-a"))})}if(this.visibleSubMenus.length>o&&this.menuHideSubMenus(this.activatedItems[o-1]&&this.activatedItems[o-1][0]==i[0]?o:o-1),this.activatedItems[o-1]=i,this.visibleSubMenus[o-1]=s,this.$root.triggerHandler("activate.smapi",i[0])!==!1){var a=e.dataSM("sub");a&&(this.isTouchMode()||!this.opts.showOnClick||this.clickActivated)&&this.menuShow(a)}},itemBlur:function(i){var e=t(i.currentTarget);this.handleItemEvents(e)&&this.$root.triggerHandler("blur.smapi",e[0])},itemClick:function(i){if(this.isTouchScrolling)return this.isTouchScrolling=!1,i.stopPropagation(),!1;var e=t(i.currentTarget);if(this.handleItemEvents(e)){if(e.removeDataSM("mousedown"),this.$root.triggerHandler("click.smapi",e[0])===!1)return!1;var s=e.parent().dataSM("sub");if(this.isTouchMode()){if(e.dataSM("href")&&e.attr("href",e.dataSM("href")).removeDataSM("href"),s&&(!s.dataSM("shown-before")||!s.is(":visible"))&&(this.itemActivate(e),s.is(":visible")))return!1}else if(this.opts.showOnClick&&1==e.parent().parent().dataSM("level")&&s)return this.clickActivated=!0,this.menuShow(s),!1;return e.hasClass("disabled")?!1:this.$root.triggerHandler("select.smapi",e[0])===!1?!1:void 0}},itemDown:function(i){var e=t(i.currentTarget);this.handleItemEvents(e)&&e.dataSM("mousedown",!0)},itemEnter:function(i){var e=t(i.currentTarget);if(this.handleItemEvents(e)){if(!this.isTouchMode()){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);var s=this;this.showTimeout=setTimeout(function(){s.itemActivate(e)},this.opts.showOnClick&&1==e.parent().parent().dataSM("level")?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",e[0])}},itemFocus:function(i){var e=t(i.currentTarget);this.handleItemEvents(e)&&(this.isTouchMode()&&e.dataSM("mousedown")||this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0]==e[0]||this.itemActivate(e),this.$root.triggerHandler("focus.smapi",e[0]))},itemLeave:function(i){var e=t(i.currentTarget);this.handleItemEvents(e)&&(this.isTouchMode()||(e[0].blur&&e[0].blur(),this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0)),e.removeDataSM("mousedown"),this.$root.triggerHandler("mouseleave.smapi",e[0]))},itemTouchEnd:function(i){var e=t(i.currentTarget);if(this.handleItemEvents(e)){var s=e.parent().dataSM("sub");"#"===e.attr("href").charAt(0)||!s||s.dataSM("shown-before")&&s.is(":visible")||(e.dataSM("href",e.attr("href")),e.attr("href","#"))}},menuFixLayout:function(t){t.dataSM("shown-before")||t.hide().dataSM("shown-before",!0)},menuHide:function(t){if(this.$root.triggerHandler("beforehide.smapi",t[0])!==!1&&(t.stop(!0,!0),t.is(":visible"))){var i=function(){t.css("z-index","")};this.isCollapsible()?this.opts.collapsibleHideFunction?this.opts.collapsibleHideFunction.call(this,t,i):t.hide(this.opts.collapsibleHideDuration,i):this.opts.hideFunction?this.opts.hideFunction.call(this,t,i):t.hide(this.opts.hideDuration,i),t.dataSM("ie-shim")&&t.dataSM("ie-shim").remove(),t.dataSM("scroll")&&(this.menuScrollStop(t),t.css({"touch-action":"","-ms-touch-action":""}).unbind(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()),t.dataSM("parent-a").removeClass("highlighted");var e=t.dataSM("level");this.activatedItems.splice(e-1,1),this.visibleSubMenus.splice(e-1,1),this.$root.triggerHandler("hide.smapi",t[0])}},menuHideAll:function(){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0),this.menuHideSubMenus(),this.opts.isPopup&&(this.$root.stop(!0,!0),this.$root.is(":visible")&&(this.opts.hideFunction?this.opts.hideFunction.call(this,this.$root):this.$root.hide(this.opts.hideDuration),this.$root.dataSM("ie-shim")&&this.$root.dataSM("ie-shim").remove())),this.activatedItems=[],this.visibleSubMenus=[],this.clickActivated=!1,this.zIndexInc=0},menuHideSubMenus:function(t){t||(t=0);for(var i=this.visibleSubMenus.length-1;i>t;i--)this.menuHide(this.visibleSubMenus[i])},menuIframeShim:function(i){a&&this.opts.overlapControlsInIE&&!i.dataSM("ie-shim")&&i.dataSM("ie-shim",t("").attr({src:"javascript:0",tabindex:-9}).css({position:"absolute",top:"auto",left:"0",opacity:0,border:"0"}))},menuInit:function(t){if(!t.dataSM("in-mega")){this.subMenus.push(t),t.hasClass("mega-menu")&&t.find("ul").dataSM("in-mega",!0);for(var i=2,e=t[0];(e=e.parentNode.parentNode)!=this.$root[0];)i++;t.dataSM("parent-a",t.prevAll("a").eq(-1)).dataSM("level",i).parent().dataSM("sub",t),this.opts.subIndicators&&t.dataSM("parent-a").addClass("has-submenu")[this.opts.subIndicatorsPos](this.$subArrow.clone())}},menuPosition:function(i){var e,n,a=i.dataSM("parent-a"),r=i.parent().parent(),h=i.dataSM("level"),u=this.getWidth(i),l=this.getHeight(i),c=a.offset(),d=c.left,m=c.top,p=this.getWidth(a),f=this.getHeight(a),v=t(window),S=v.scrollLeft(),b=v.scrollTop(),M=this.getViewportWidth(),g=this.getViewportHeight(),w=r.hasClass("sm")&&!r.hasClass("sm-vertical"),T=2==h?this.opts.mainMenuSubOffsetX:this.opts.subMenusSubOffsetX,$=2==h?this.opts.mainMenuSubOffsetY:this.opts.subMenusSubOffsetY;if(w?(e=this.opts.rightToLeftSubMenus?p-u-T:T,n=this.opts.bottomToTopSubMenus?-l-$:f+$):(e=this.opts.rightToLeftSubMenus?T-u:p-T,n=this.opts.bottomToTopSubMenus?f-$-l:$),this.opts.keepInViewport&&!this.isCollapsible()){var I=d+e,y=m+n;if(this.opts.rightToLeftSubMenus&&S>I?e=w?S-I+e:p-T:!this.opts.rightToLeftSubMenus&&I+u>S+M&&(e=w?S+M-u-I+e:T-u),w||(g>l&&y+l>b+g?n+=b+g-l-y:(l>=g||b>y)&&(n+=b-y)),w&&(y+l>b+g+.49||b>y)||!w&&l>g+.49){var x=this;i.dataSM("scroll-arrows")||i.dataSM("scroll-arrows",t([t('')[0],t('')[0]]).bind({mouseenter:function(){i.dataSM("scroll").up=t(this).hasClass("scroll-up"),x.menuScroll(i)},mouseleave:function(t){x.menuScrollStop(i),x.menuScrollOut(i,t)},"mousewheel DOMMouseScroll":function(t){t.preventDefault()}}).insertAfter(i));var C=".smartmenus_scroll";i.dataSM("scroll",{step:1,itemH:f,subH:l,arrowDownH:this.getHeight(i.dataSM("scroll-arrows").eq(1))}).bind(o([["mouseover",function(t){x.menuScrollOver(i,t)}],["mouseout",function(t){x.menuScrollOut(i,t)}],["mousewheel DOMMouseScroll",function(t){x.menuScrollMousewheel(i,t)}]],C)).dataSM("scroll-arrows").css({top:"auto",left:"0",marginLeft:e+(parseInt(i.css("border-left-width"))||0),width:u-(parseInt(i.css("border-left-width"))||0)-(parseInt(i.css("border-right-width"))||0),zIndex:i.css("z-index")}).eq(w&&this.opts.bottomToTopSubMenus?0:1).show(),this.isFixed()&&i.css({"touch-action":"none","-ms-touch-action":"none"}).bind(o([[s()?"touchstart touchmove touchend":"pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp",function(t){x.menuScrollTouch(i,t)}]],C))}}i.css({top:"auto",left:"0",marginLeft:e,marginTop:n-f}),this.menuIframeShim(i),i.dataSM("ie-shim")&&i.dataSM("ie-shim").css({zIndex:i.css("z-index"),width:u,height:l,marginLeft:e,marginTop:n-f})},menuScroll:function(t,i,e){var s,o=t.dataSM("scroll"),n=t.dataSM("scroll-arrows"),a=parseFloat(t.css("margin-top")),h=o.up?o.upEnd:o.downEnd;if(!i&&o.velocity){if(o.velocity*=.9,s=o.velocity,.5>s)return this.menuScrollStop(t),void 0}else s=e||(i||!this.opts.scrollAccelerate?this.opts.scrollStep:Math.floor(o.step));var u=t.dataSM("level");this.visibleSubMenus.length>u&&this.menuHideSubMenus(u-1);var l=o.up&&a>=h||!o.up&&h>=a?a:Math.abs(h-a)>s?a+(o.up?s:-s):h;if(t.add(t.dataSM("ie-shim")).css("margin-top",l),r&&(o.up&&l>o.downEnd||!o.up&&o.upEnd>l)&&n.eq(o.up?1:0).show(),l==h)r&&n.eq(o.up?0:1).hide(),this.menuScrollStop(t);else if(!i){this.opts.scrollAccelerate&&o.step0;t.dataSM("scroll-arrows").eq(e?0:1).is(":visible")&&(t.dataSM("scroll").up=e,this.menuScroll(t,!0))}i.preventDefault()},menuScrollOut:function(i,e){r&&(/^scroll-(up|down)/.test((e.relatedTarget||"").className)||(i[0]==e.relatedTarget||t.contains(i[0],e.relatedTarget))&&this.getClosestMenu(e.relatedTarget)==i[0]||i.dataSM("scroll-arrows").css("visibility","hidden"))},menuScrollOver:function(t,i){if(r&&!/^scroll-(up|down)/.test(i.target.className)&&this.getClosestMenu(i.target)==t[0]){this.menuScrollRefreshData(t);var e=t.dataSM("scroll");t.dataSM("scroll-arrows").eq(0).css("margin-top",e.upEnd).end().eq(1).css("margin-top",e.downEnd+e.subH-e.arrowDownH).end().css("visibility","visible")}},menuScrollRefreshData:function(i){var e=i.dataSM("scroll"),s=t(window),o=s.scrollTop()-i.dataSM("parent-a").offset().top-e.itemH;t.extend(e,{upEnd:o,downEnd:o+this.getViewportHeight()-e.subH})},menuScrollStop:function(i){return this.scrollTimeout?(clearTimeout(this.scrollTimeout),this.scrollTimeout=0,t.extend(i.dataSM("scroll"),{step:1,velocity:0}),!0):void 0},menuScrollTouch:function(i,s){if(s=s.originalEvent,e(s)){var o=this.getTouchPoint(s);if(this.getClosestMenu(o.target)==i[0]){var n=i.dataSM("scroll");if(/(start|down)$/i.test(s.type))this.menuScrollStop(i)?(s.preventDefault(),this.isTouchScrolling=!0):this.isTouchScrolling=!1,this.menuScrollRefreshData(i),t.extend(n,{touchY:o.pageY,touchTimestamp:s.timeStamp,velocity:0});else if(/move$/i.test(s.type)){var a=n.touchY;void 0!==a&&a!=o.pageY&&(this.isTouchScrolling=!0,t.extend(n,{up:o.pageY>a,touchY:o.pageY,touchTimestamp:s.timeStamp,velocity:n.velocity+.5*Math.abs(o.pageY-a)}),this.menuScroll(i,!0,Math.abs(n.touchY-a))),s.preventDefault()}else void 0!==n.touchY&&(120>s.timeStamp-n.touchTimestamp&&n.velocity>0&&(n.velocity*=.5,this.menuScrollStop(i),this.menuScroll(i),s.preventDefault()),delete n.touchY)}}},menuShow:function(t){if((t.dataSM("beforefirstshowfired")||(t.dataSM("beforefirstshowfired",!0),this.$root.triggerHandler("beforefirstshow.smapi",t[0])!==!1))&&this.$root.triggerHandler("beforeshow.smapi",t[0])!==!1&&(this.menuFixLayout(t),t.stop(!0,!0),!t.is(":visible"))){if(t.css("z-index",this.zIndexInc=(this.zIndexInc||this.getStartZIndex())+1),(this.opts.keepHighlighted||this.isCollapsible())&&t.dataSM("parent-a").addClass("highlighted"),(this.opts.subMenusMinWidth||this.opts.subMenusMaxWidth)&&(t.css({width:"auto",minWidth:"",maxWidth:""}).addClass("sm-nowrap"),this.opts.subMenusMinWidth&&t.css("min-width",this.opts.subMenusMinWidth),this.opts.subMenusMaxWidth)){var i=this.getWidth(t);t.css("max-width",this.opts.subMenusMaxWidth),i>this.getWidth(t)&&t.removeClass("sm-nowrap").css("width",this.opts.subMenusMaxWidth)}this.menuPosition(t),t.dataSM("ie-shim")&&t.dataSM("ie-shim").insertBefore(t);var e=function(){t.css("overflow","")};this.isCollapsible()?this.opts.collapsibleShowFunction?this.opts.collapsibleShowFunction.call(this,t,e):t.show(this.opts.collapsibleShowDuration,e):this.opts.showFunction?this.opts.showFunction.call(this,t,e):t.show(this.opts.showDuration,e),this.visibleSubMenus[t.dataSM("level")-1]=t,this.$root.triggerHandler("show.smapi",t[0])}},popupHide:function(t){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var i=this;this.hideTimeout=setTimeout(function(){i.menuHideAll()},t?1:this.opts.hideTimeout)},popupShow:function(t,i){if(!this.opts.isPopup)return alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'),void 0;if(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),this.menuFixLayout(this.$root),this.$root.stop(!0,!0),!this.$root.is(":visible")){this.$root.css({left:t,top:i}),this.menuIframeShim(this.$root),this.$root.dataSM("ie-shim")&&this.$root.dataSM("ie-shim").css({zIndex:this.$root.css("z-index"),width:this.getWidth(this.$root),height:this.getHeight(this.$root),left:t,top:i}).insertBefore(this.$root);var e=this,s=function(){e.$root.css("overflow","")};this.opts.showFunction?this.opts.showFunction.call(this,this.$root,s):this.$root.show(this.opts.showDuration,s),this.visibleSubMenus[0]=this.$root}},refresh:function(){this.menuHideAll(),this.$root.find("ul").each(function(){var i=t(this);i.dataSM("scroll-arrows")&&i.dataSM("scroll-arrows").remove()}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("ie-shim").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired"),this.$root.find("a.has-submenu").removeClass("has-submenu").parent().removeDataSM("sub"),this.opts.subIndicators&&this.$root.find("span.sub-arrow").remove(),this.opts.markCurrentItem&&this.$root.find("a.current").removeClass("current"),this.subMenus=[],this.init(!0)},rootOut:function(t){if(this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),!this.opts.showOnClick||!this.opts.hideOnClick)){var i=this;this.hideTimeout=setTimeout(function(){i.menuHideAll()},this.opts.hideTimeout)}},rootOver:function(t){this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0)},winResize:function(t){if(this.handleEvents())this.isCollapsible()||"onorientationchange"in window&&"orientationchange"!=t.type||(this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0].blur(),this.menuHideAll());else if(this.$disableOverlay){var i=this.$root.offset();this.$disableOverlay.css({top:i.top,left:i.left,width:this.$root.outerWidth(),height:this.$root.outerHeight()})}}}}),t.fn.dataSM=function(t,i){return i?this.data(t+"_smartmenus",i):this.data(t+"_smartmenus")},t.fn.removeDataSM=function(t){return this.removeData(t+"_smartmenus")},t.fn.smartmenus=function(i){if("string"==typeof i){var e=arguments,s=i;return Array.prototype.shift.call(e),this.each(function(){var i=t(this).data("smartmenus");i&&i[s]&&i[s].apply(i,e)})}var o=t.extend({},t.fn.smartmenus.defaults,i);return this.each(function(){new t.SmartMenus(this,o)})},t.fn.smartmenus.defaults={isPopup:!1,mainMenuSubOffsetX:0,mainMenuSubOffsetY:0,subMenusSubOffsetX:0,subMenusSubOffsetY:0,subMenusMinWidth:"10em",subMenusMaxWidth:"20em",subIndicators:!0,subIndicatorsPos:"prepend",subIndicatorsText:"+",scrollStep:30,scrollInterval:30,scrollAccelerate:!0,showTimeout:250,hideTimeout:500,showDuration:0,showFunction:null,hideDuration:0,hideFunction:function(t,i){t.fadeOut(200,i)},collapsibleShowDuration:0,collapsibleShowFunction:function(t,i){t.slideDown(200,i)},collapsibleHideDuration:0,collapsibleHideFunction:function(t,i){t.slideUp(200,i)},showOnClick:!1,hideOnClick:!0,keepInViewport:!0,keepHighlighted:!0,markCurrentItem:!1,markCurrentTree:!0,rightToLeftSubMenus:!1,bottomToTopSubMenus:!1,overlapControlsInIE:!0}})(jQuery);
(function(){var b,d,c;b=jQuery;c=(function(){function b(){this.fadeDuration=500;this.fitImagesInViewport=true;this.resizeDuration=700;this.showImageNumberLabel=true;this.wrapAround=false}b.prototype.albumLabel=function(b,c){return"Image "+b+" of "+c};return b})();d=(function(){function c(b){this.options=b;this.album=[];this.currentImageIndex=void 0;this.init()}c.prototype.init=function(){this.enable();return this.build()};c.prototype.enable=function(){var c=this;return b('body').on('click','a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]',function(d){c.start(b(d.currentTarget));return false})};c.prototype.build=function(){var c=this;b("").appendTo(b('body'));this.$lightbox=b('#lightbox');this.$overlay=b('#lightboxOverlay');this.$outerContainer=this.$lightbox.find('.lb-outerContainer');this.$container=this.$lightbox.find('.lb-container');this.containerTopPadding=parseInt(this.$container.css('padding-top'),10);this.containerRightPadding=parseInt(this.$container.css('padding-right'),10);this.containerBottomPadding=parseInt(this.$container.css('padding-bottom'),10);this.containerLeftPadding=parseInt(this.$container.css('padding-left'),10);this.$overlay.hide().on('click',function(){c.end();return false});this.$lightbox.hide().on('click',function(d){if(b(d.target).attr('id')==='lightbox'){c.end()}return false});this.$outerContainer.on('click',function(d){if(b(d.target).attr('id')==='lightbox'){c.end()}return false});this.$lightbox.find('.lb-prev').on('click',function(){if(c.currentImageIndex===0){c.changeImage(c.album.length-1)}else{c.changeImage(c.currentImageIndex-1)}return false});this.$lightbox.find('.lb-next').on('click',function(){if(c.currentImageIndex===c.album.length-1){c.changeImage(0)}else{c.changeImage(c.currentImageIndex+1)}return false});return this.$lightbox.find('.lb-loader, .lb-close').on('click',function(){c.end();return false})};c.prototype.start=function(c){var f,e,j,d,g,n,o,k,l,m,p,h,i;b(window).on("resize",this.sizeOverlay);b('select, object, embed').css({visibility:"hidden"});this.$overlay.width(b(document).width()).height(b(document).height()).fadeIn(this.options.fadeDuration);this.album=[];g=0;j=c.attr('data-lightbox');if(j){h=b(c.prop("tagName")+'[data-lightbox="'+j+'"]');for(d=k=0,m=h.length;kj)||(c.height>i)){if((c.width/j)>(c.height/i)){h=j;g=parseInt(c.height/(c.width/h),10);d.width(h);d.height(g)}else{g=i;h=parseInt(c.width/(c.height/g),10);d.width(h);d.height(g)}}}return e.sizeContainer(d.width(),d.height())};c.src=this.album[f].link;this.currentImageIndex=f};c.prototype.sizeOverlay=function(){return b('#lightboxOverlay').width(b(document).width()).height(b(document).height())};c.prototype.sizeContainer=function(f,g){var b,d,e,h,c=this;h=this.$outerContainer.outerWidth();e=this.$outerContainer.outerHeight();d=f+this.containerLeftPadding+this.containerRightPadding;b=g+this.containerTopPadding+this.containerBottomPadding;this.$outerContainer.animate({width:d,height:b},this.options.resizeDuration,'swing');setTimeout(function(){c.$lightbox.find('.lb-dataContainer').width(d);c.$lightbox.find('.lb-prevLink').height(b);c.$lightbox.find('.lb-nextLink').height(b);c.showImage()},this.options.resizeDuration)};c.prototype.showImage=function(){this.$lightbox.find('.lb-loader').hide();this.$lightbox.find('.lb-image').fadeIn('slow');this.updateNav();this.updateDetails();this.preloadNeighboringImages();this.enableKeyboardNav()};c.prototype.updateNav=function(){this.$lightbox.find('.lb-nav').show();if(this.album.length>1){if(this.options.wrapAround){this.$lightbox.find('.lb-prev, .lb-next').show()}else{if(this.currentImageIndex>0){this.$lightbox.find('.lb-prev').show()}if(this.currentImageIndex1&&this.options.showImageNumberLabel){this.$lightbox.find('.lb-number').text(this.options.albumLabel(this.currentImageIndex+1,this.album.length)).fadeIn('fast')}else{this.$lightbox.find('.lb-number').hide()}this.$outerContainer.removeClass('animating');this.$lightbox.find('.lb-dataContainer').fadeIn(this.resizeDuration,function(){return b.sizeOverlay()})};c.prototype.preloadNeighboringImages=function(){var c,b;if(this.album.length>this.currentImageIndex+1){c=new Image();c.src=this.album[this.currentImageIndex+1].link}if(this.currentImageIndex>0){b=new Image();b.src=this.album[this.currentImageIndex-1].link}};c.prototype.enableKeyboardNav=function(){b(document).on('keyup.keyboard',b.proxy(this.keyboardAction,this))};c.prototype.disableKeyboardNav=function(){b(document).off('.keyboard')};c.prototype.keyboardAction=function(g){var d,e,f,c,b;d=27;e=37;f=39;b=g.keyCode;c=String.fromCharCode(b).toLowerCase();if(b===d||c.match(/x|o|c/)){this.end()}else if(c==='p'||b===e){if(this.currentImageIndex!==0){this.changeImage(this.currentImageIndex-1)}}else if(c==='n'||b===f){if(this.currentImageIndex!==this.album.length-1){this.changeImage(this.currentImageIndex+1)}}};c.prototype.end=function(){this.disableKeyboardNav();b(window).off("resize",this.sizeOverlay);this.$lightbox.fadeOut(this.options.fadeDuration);this.$overlay.fadeOut(this.options.fadeDuration);return b('select, object, embed').css({visibility:"visible"})};return c})();b(function(){var e,b;b=new c();return e=new d(b)})}).call(this);
/* Modernizr 2.5.3 (Custom Build) | MIT & BSD
* Build: http://modernizr.com/download/#-csstransforms3d-csstransitions-shiv-cssclasses-teststyles-testprop-testallprops-prefixes-domprefixes-load
*/
;window.Modernizr=function(a,b,c){function z(a){j.cssText=a}function A(a,b){return z(m.join(a+";")+(b||""))}function B(a,b){return typeof a===b}function C(a,b){return!!~(""+a).indexOf(b)}function D(a,b){for(var d in a)if(j[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function E(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:B(f,"function")?f.bind(d||b):f}return!1}function F(a,b,c){var d=a.charAt(0).toUpperCase()+a.substr(1),e=(a+" "+o.join(d+" ")+d).split(" ");return B(b,"string")||B(b,"undefined")?D(e,b):(e=(a+" "+p.join(d+" ")+d).split(" "),E(e,b,c))}var d="2.5.3",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n="Webkit Moz O ms",o=n.split(" "),p=n.toLowerCase().split(" "),q={},r={},s={},t=[],u=t.slice,v,w=function(a,c,d,e){var f,i,j,k=b.createElement("div"),l=b.body,m=l?l:b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),k.appendChild(j);return f=["",""].join(""),k.id=h,(l?k:m).innerHTML+=f,m.appendChild(k),l||(m.style.background="",g.appendChild(m)),i=c(k,a),l?k.parentNode.removeChild(k):m.parentNode.removeChild(m),!!i},x={}.hasOwnProperty,y;!B(x,"undefined")&&!B(x.call,"undefined")?y=function(a,b){return x.call(a,b)}:y=function(a,b){return b in a&&B(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=u.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(u.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(u.call(arguments)))};return e});var G=function(a,c){var d=a.join(""),f=c.length;w(d,function(a,c){var d=b.styleSheets[b.styleSheets.length-1],g=d?d.cssRules&&d.cssRules[0]?d.cssRules[0].cssText:d.cssText||"":"",h=a.childNodes,i={};while(f--)i[h[f].id]=h[f];e.csstransforms3d=(i.csstransforms3d&&i.csstransforms3d.offsetLeft)===9&&i.csstransforms3d.offsetHeight===3},f,c)}([,["@media (",m.join("transform-3d),("),h,")","{#csstransforms3d{left:9px;position:absolute;height:3px;}}"].join("")],[,"csstransforms3d"]);q.csstransforms3d=function(){var a=!!F("perspective");return a&&"webkitPerspective"in g.style&&(a=e.csstransforms3d),a},q.csstransitions=function(){return F("transition")};for(var H in q)y(q,H)&&(v=H.toLowerCase(),e[v]=q[H](),t.push((e[v]?"":"no-")+v));return z(""),i=k=null,function(a,b){function g(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function h(){var a=k.elements;return typeof a=="string"?a.split(" "):a}function i(a){var b={},c=a.createElement,e=a.createDocumentFragment,f=e();a.createElement=function(a){var e=(b[a]||(b[a]=c(a))).cloneNode();return k.shivMethods&&e.canHaveChildren&&!d.test(a)?f.appendChild(e):e},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+h().join().replace(/\w+/g,function(a){return b[a]=c(a),f.createElement(a),'c("'+a+'")'})+");return n}")(k,f)}function j(a){var b;return a.documentShived?a:(k.shivCSS&&!e&&(b=!!g(a,"article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio{display:none}canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}mark{background:#FF0;color:#000}")),f||(b=!i(a)),b&&(a.documentShived=b),a)}var c=a.html5||{},d=/^<|^(?:button|form|map|select|textarea)$/i,e,f;(function(){var a=b.createElement("a");a.innerHTML="",e="hidden"in a,f=a.childNodes.length==1||function(){try{b.createElement("a")}catch(a){return!0}var c=b.createDocumentFragment();return typeof c.cloneNode=="undefined"||typeof c.createDocumentFragment=="undefined"||typeof c.createElement=="undefined"}()})();var k={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:j};a.html5=k,j(b)}(this,b),e._version=d,e._prefixes=m,e._domPrefixes=p,e._cssomPrefixes=o,e.testProp=function(a){return D([a])},e.testAllProps=F,e.testStyles=w,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+t.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return o.call(a)=="[object Function]"}function e(a){return typeof a=="string"}function f(){}function g(a){return!a||a=="loaded"||a=="complete"||a=="uninitialized"}function h(){var a=p.shift();q=1,a?a.t?m(function(){(a.t=="c"?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){a!="img"&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l={},o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};y[c]===1&&(r=1,y[c]=[],l=b.createElement(a)),a=="object"?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),a!="img"&&(r||y[c]===2?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i(b=="c"?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),p.length==1&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&o.call(a.opera)=="[object Opera]",l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return o.call(a)=="[object Array]"},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f= 33) {
last = now();
return fn(diff, function() {
return requestAnimationFrame(tick);
});
} else {
return setTimeout(tick, 33 - diff);
}
};
return tick();
};
result = function() {
var args, key, obj;
obj = arguments[0], key = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
if (typeof obj[key] === 'function') {
return obj[key].apply(obj, args);
} else {
return obj[key];
}
};
extend = function() {
var key, out, source, sources, val, _i, _len;
out = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
for (_i = 0, _len = sources.length; _i < _len; _i++) {
source = sources[_i];
if (source) {
for (key in source) {
if (!__hasProp.call(source, key)) continue;
val = source[key];
if ((out[key] != null) && typeof out[key] === 'object' && (val != null) && typeof val === 'object') {
extend(out[key], val);
} else {
out[key] = val;
}
}
}
}
return out;
};
avgAmplitude = function(arr) {
var count, sum, v, _i, _len;
sum = count = 0;
for (_i = 0, _len = arr.length; _i < _len; _i++) {
v = arr[_i];
sum += Math.abs(v);
count++;
}
return sum / count;
};
getFromDOM = function(key, json) {
var data, e, el;
if (key == null) {
key = 'options';
}
if (json == null) {
json = true;
}
el = document.querySelector("[data-pace-" + key + "]");
if (!el) {
return;
}
data = el.getAttribute("data-pace-" + key);
if (!json) {
return data;
}
try {
return JSON.parse(data);
} catch (_error) {
e = _error;
return typeof console !== "undefined" && console !== null ? console.error("Error parsing inline pace options", e) : void 0;
}
};
Evented = (function() {
function Evented() {}
Evented.prototype.on = function(event, handler, ctx, once) {
var _base;
if (once == null) {
once = false;
}
if (this.bindings == null) {
this.bindings = {};
}
if ((_base = this.bindings)[event] == null) {
_base[event] = [];
}
return this.bindings[event].push({
handler: handler,
ctx: ctx,
once: once
});
};
Evented.prototype.once = function(event, handler, ctx) {
return this.on(event, handler, ctx, true);
};
Evented.prototype.off = function(event, handler) {
var i, _ref, _results;
if (((_ref = this.bindings) != null ? _ref[event] : void 0) == null) {
return;
}
if (handler == null) {
return delete this.bindings[event];
} else {
i = 0;
_results = [];
while (i < this.bindings[event].length) {
if (this.bindings[event][i].handler === handler) {
_results.push(this.bindings[event].splice(i, 1));
} else {
_results.push(i++);
}
}
return _results;
}
};
Evented.prototype.trigger = function() {
var args, ctx, event, handler, i, once, _ref, _ref1, _results;
event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
if ((_ref = this.bindings) != null ? _ref[event] : void 0) {
i = 0;
_results = [];
while (i < this.bindings[event].length) {
_ref1 = this.bindings[event][i], handler = _ref1.handler, ctx = _ref1.ctx, once = _ref1.once;
handler.apply(ctx != null ? ctx : this, args);
if (once) {
_results.push(this.bindings[event].splice(i, 1));
} else {
_results.push(i++);
}
}
return _results;
}
};
return Evented;
})();
Pace = window.Pace || {};
window.Pace = Pace;
extend(Pace, Evented.prototype);
options = Pace.options = extend({}, defaultOptions, window.paceOptions, getFromDOM());
_ref = ['ajax', 'document', 'eventLag', 'elements'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
source = _ref[_i];
if (options[source] === true) {
options[source] = defaultOptions[source];
}
}
NoTargetError = (function(_super) {
__extends(NoTargetError, _super);
function NoTargetError() {
_ref1 = NoTargetError.__super__.constructor.apply(this, arguments);
return _ref1;
}
return NoTargetError;
})(Error);
Bar = (function() {
function Bar() {
this.progress = 0;
}
Bar.prototype.getElement = function() {
var targetElement;
if (this.el == null) {
targetElement = document.querySelector(options.target);
if (!targetElement) {
throw new NoTargetError;
}
this.el = document.createElement('div');
this.el.className = "pace pace-active";
document.body.className = document.body.className.replace(/pace-done/g, '');
document.body.className += ' pace-running';
this.el.innerHTML = '\n';
if (targetElement.firstChild != null) {
targetElement.insertBefore(this.el, targetElement.firstChild);
} else {
targetElement.appendChild(this.el);
}
}
return this.el;
};
Bar.prototype.finish = function() {
var el;
el = this.getElement();
el.className = el.className.replace('pace-active', '');
el.className += ' pace-inactive';
document.body.className = document.body.className.replace('pace-running', '');
return document.body.className += ' pace-done';
};
Bar.prototype.update = function(prog) {
this.progress = prog;
return this.render();
};
Bar.prototype.destroy = function() {
try {
this.getElement().parentNode.removeChild(this.getElement());
} catch (_error) {
NoTargetError = _error;
}
return this.el = void 0;
};
Bar.prototype.render = function() {
var el, key, progressStr, transform, _j, _len1, _ref2;
if (document.querySelector(options.target) == null) {
return false;
}
el = this.getElement();
transform = "translate3d(" + this.progress + "%, 0, 0)";
_ref2 = ['webkitTransform', 'msTransform', 'transform'];
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
key = _ref2[_j];
el.children[0].style[key] = transform;
}
if (!this.lastRenderedProgress || this.lastRenderedProgress | 0 !== this.progress | 0) {
el.children[0].setAttribute('data-progress-text', "" + (this.progress | 0) + "%");
if (this.progress >= 100) {
progressStr = '99';
} else {
progressStr = this.progress < 10 ? "0" : "";
progressStr += this.progress | 0;
}
el.children[0].setAttribute('data-progress', "" + progressStr);
}
return this.lastRenderedProgress = this.progress;
};
Bar.prototype.done = function() {
return this.progress >= 100;
};
return Bar;
})();
Events = (function() {
function Events() {
this.bindings = {};
}
Events.prototype.trigger = function(name, val) {
var binding, _j, _len1, _ref2, _results;
if (this.bindings[name] != null) {
_ref2 = this.bindings[name];
_results = [];
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
binding = _ref2[_j];
_results.push(binding.call(this, val));
}
return _results;
}
};
Events.prototype.on = function(name, fn) {
var _base;
if ((_base = this.bindings)[name] == null) {
_base[name] = [];
}
return this.bindings[name].push(fn);
};
return Events;
})();
_XMLHttpRequest = window.XMLHttpRequest;
_XDomainRequest = window.XDomainRequest;
_WebSocket = window.WebSocket;
extendNative = function(to, from) {
var e, key, _results;
_results = [];
for (key in from.prototype) {
try {
if ((to[key] == null) && typeof from[key] !== 'function') {
if (typeof Object.defineProperty === 'function') {
_results.push(Object.defineProperty(to, key, {
get: function() {
return from.prototype[key];
},
configurable: true,
enumerable: true
}));
} else {
_results.push(to[key] = from.prototype[key]);
}
} else {
_results.push(void 0);
}
} catch (_error) {
e = _error;
}
}
return _results;
};
ignoreStack = [];
Pace.ignore = function() {
var args, fn, ret;
fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
ignoreStack.unshift('ignore');
ret = fn.apply(null, args);
ignoreStack.shift();
return ret;
};
Pace.track = function() {
var args, fn, ret;
fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
ignoreStack.unshift('track');
ret = fn.apply(null, args);
ignoreStack.shift();
return ret;
};
shouldTrack = function(method) {
var _ref2;
if (method == null) {
method = 'GET';
}
if (ignoreStack[0] === 'track') {
return 'force';
}
if (!ignoreStack.length && options.ajax) {
if (method === 'socket' && options.ajax.trackWebSockets) {
return true;
} else if (_ref2 = method.toUpperCase(), __indexOf.call(options.ajax.trackMethods, _ref2) >= 0) {
return true;
}
}
return false;
};
RequestIntercept = (function(_super) {
__extends(RequestIntercept, _super);
function RequestIntercept() {
var monitorXHR,
_this = this;
RequestIntercept.__super__.constructor.apply(this, arguments);
monitorXHR = function(req) {
var _open;
_open = req.open;
return req.open = function(type, url, async) {
if (shouldTrack(type)) {
_this.trigger('request', {
type: type,
url: url,
request: req
});
}
return _open.apply(req, arguments);
};
};
window.XMLHttpRequest = function(flags) {
var req;
req = new _XMLHttpRequest(flags);
monitorXHR(req);
return req;
};
try {
extendNative(window.XMLHttpRequest, _XMLHttpRequest);
} catch (_error) {}
if (_XDomainRequest != null) {
window.XDomainRequest = function() {
var req;
req = new _XDomainRequest;
monitorXHR(req);
return req;
};
try {
extendNative(window.XDomainRequest, _XDomainRequest);
} catch (_error) {}
}
if ((_WebSocket != null) && options.ajax.trackWebSockets) {
window.WebSocket = function(url, protocols) {
var req;
if (protocols != null) {
req = new _WebSocket(url, protocols);
} else {
req = new _WebSocket(url);
}
if (shouldTrack('socket')) {
_this.trigger('request', {
type: 'socket',
url: url,
protocols: protocols,
request: req
});
}
return req;
};
try {
extendNative(window.WebSocket, _WebSocket);
} catch (_error) {}
}
}
return RequestIntercept;
})(Events);
_intercept = null;
getIntercept = function() {
if (_intercept == null) {
_intercept = new RequestIntercept;
}
return _intercept;
};
shouldIgnoreURL = function(url) {
var pattern, _j, _len1, _ref2;
_ref2 = options.ajax.ignoreURLs;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
pattern = _ref2[_j];
if (typeof pattern === 'string') {
if (url.indexOf(pattern) !== -1) {
return true;
}
} else {
if (pattern.test(url)) {
return true;
}
}
}
return false;
};
getIntercept().on('request', function(_arg) {
var after, args, request, type, url;
type = _arg.type, request = _arg.request, url = _arg.url;
if (shouldIgnoreURL(url)) {
return;
}
if (!Pace.running && (options.restartOnRequestAfter !== false || shouldTrack(type) === 'force')) {
args = arguments;
after = options.restartOnRequestAfter || 0;
if (typeof after === 'boolean') {
after = 0;
}
return setTimeout(function() {
var stillActive, _j, _len1, _ref2, _ref3, _results;
if (type === 'socket') {
stillActive = request.readyState < 2;
} else {
stillActive = (0 < (_ref2 = request.readyState) && _ref2 < 4);
}
if (stillActive) {
Pace.restart();
_ref3 = Pace.sources;
_results = [];
for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {
source = _ref3[_j];
if (source instanceof AjaxMonitor) {
source.watch.apply(source, args);
break;
} else {
_results.push(void 0);
}
}
return _results;
}
}, after);
}
});
AjaxMonitor = (function() {
function AjaxMonitor() {
var _this = this;
this.elements = [];
getIntercept().on('request', function() {
return _this.watch.apply(_this, arguments);
});
}
AjaxMonitor.prototype.watch = function(_arg) {
var request, tracker, type, url;
type = _arg.type, request = _arg.request, url = _arg.url;
if (shouldIgnoreURL(url)) {
return;
}
if (type === 'socket') {
tracker = new SocketRequestTracker(request);
} else {
tracker = new XHRRequestTracker(request);
}
return this.elements.push(tracker);
};
return AjaxMonitor;
})();
XHRRequestTracker = (function() {
function XHRRequestTracker(request) {
var event, size, _j, _len1, _onreadystatechange, _ref2,
_this = this;
this.progress = 0;
if (window.ProgressEvent != null) {
size = null;
request.addEventListener('progress', function(evt) {
if (evt.lengthComputable) {
return _this.progress = 100 * evt.loaded / evt.total;
} else {
return _this.progress = _this.progress + (100 - _this.progress) / 2;
}
}, false);
_ref2 = ['load', 'abort', 'timeout', 'error'];
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
event = _ref2[_j];
request.addEventListener(event, function() {
return _this.progress = 100;
}, false);
}
} else {
_onreadystatechange = request.onreadystatechange;
request.onreadystatechange = function() {
var _ref3;
if ((_ref3 = request.readyState) === 0 || _ref3 === 4) {
_this.progress = 100;
} else if (request.readyState === 3) {
_this.progress = 50;
}
return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0;
};
}
}
return XHRRequestTracker;
})();
SocketRequestTracker = (function() {
function SocketRequestTracker(request) {
var event, _j, _len1, _ref2,
_this = this;
this.progress = 0;
_ref2 = ['error', 'open'];
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
event = _ref2[_j];
request.addEventListener(event, function() {
return _this.progress = 100;
}, false);
}
}
return SocketRequestTracker;
})();
ElementMonitor = (function() {
function ElementMonitor(options) {
var selector, _j, _len1, _ref2;
if (options == null) {
options = {};
}
this.elements = [];
if (options.selectors == null) {
options.selectors = [];
}
_ref2 = options.selectors;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
selector = _ref2[_j];
this.elements.push(new ElementTracker(selector));
}
}
return ElementMonitor;
})();
ElementTracker = (function() {
function ElementTracker(selector) {
this.selector = selector;
this.progress = 0;
this.check();
}
ElementTracker.prototype.check = function() {
var _this = this;
if (document.querySelector(this.selector)) {
return this.done();
} else {
return setTimeout((function() {
return _this.check();
}), options.elements.checkInterval);
}
};
ElementTracker.prototype.done = function() {
return this.progress = 100;
};
return ElementTracker;
})();
DocumentMonitor = (function() {
DocumentMonitor.prototype.states = {
loading: 0,
interactive: 50,
complete: 100
};
function DocumentMonitor() {
var _onreadystatechange, _ref2,
_this = this;
this.progress = (_ref2 = this.states[document.readyState]) != null ? _ref2 : 100;
_onreadystatechange = document.onreadystatechange;
document.onreadystatechange = function() {
if (_this.states[document.readyState] != null) {
_this.progress = _this.states[document.readyState];
}
return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0;
};
}
return DocumentMonitor;
})();
EventLagMonitor = (function() {
function EventLagMonitor() {
var avg, interval, last, points, samples,
_this = this;
this.progress = 0;
avg = 0;
samples = [];
points = 0;
last = now();
interval = setInterval(function() {
var diff;
diff = now() - last - 50;
last = now();
samples.push(diff);
if (samples.length > options.eventLag.sampleCount) {
samples.shift();
}
avg = avgAmplitude(samples);
if (++points >= options.eventLag.minSamples && avg < options.eventLag.lagThreshold) {
_this.progress = 100;
return clearInterval(interval);
} else {
return _this.progress = 100 * (3 / (avg + 3));
}
}, 50);
}
return EventLagMonitor;
})();
Scaler = (function() {
function Scaler(source) {
this.source = source;
this.last = this.sinceLastUpdate = 0;
this.rate = options.initialRate;
this.catchup = 0;
this.progress = this.lastProgress = 0;
if (this.source != null) {
this.progress = result(this.source, 'progress');
}
}
Scaler.prototype.tick = function(frameTime, val) {
var scaling;
if (val == null) {
val = result(this.source, 'progress');
}
if (val >= 100) {
this.done = true;
}
if (val === this.last) {
this.sinceLastUpdate += frameTime;
} else {
if (this.sinceLastUpdate) {
this.rate = (val - this.last) / this.sinceLastUpdate;
}
this.catchup = (val - this.progress) / options.catchupTime;
this.sinceLastUpdate = 0;
this.last = val;
}
if (val > this.progress) {
this.progress += this.catchup * frameTime;
}
scaling = 1 - Math.pow(this.progress / 100, options.easeFactor);
this.progress += scaling * this.rate * frameTime;
this.progress = Math.min(this.lastProgress + options.maxProgressPerFrame, this.progress);
this.progress = Math.max(0, this.progress);
this.progress = Math.min(100, this.progress);
this.lastProgress = this.progress;
return this.progress;
};
return Scaler;
})();
sources = null;
scalers = null;
bar = null;
uniScaler = null;
animation = null;
cancelAnimation = null;
Pace.running = false;
handlePushState = function() {
if (options.restartOnPushState) {
return Pace.restart();
}
};
if (window.history.pushState != null) {
_pushState = window.history.pushState;
window.history.pushState = function() {
handlePushState();
return _pushState.apply(window.history, arguments);
};
}
if (window.history.replaceState != null) {
_replaceState = window.history.replaceState;
window.history.replaceState = function() {
handlePushState();
return _replaceState.apply(window.history, arguments);
};
}
SOURCE_KEYS = {
ajax: AjaxMonitor,
elements: ElementMonitor,
document: DocumentMonitor,
eventLag: EventLagMonitor
};
(init = function() {
var type, _j, _k, _len1, _len2, _ref2, _ref3, _ref4;
Pace.sources = sources = [];
_ref2 = ['ajax', 'elements', 'document', 'eventLag'];
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
type = _ref2[_j];
if (options[type] !== false) {
sources.push(new SOURCE_KEYS[type](options[type]));
}
}
_ref4 = (_ref3 = options.extraSources) != null ? _ref3 : [];
for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) {
source = _ref4[_k];
sources.push(new source(options));
}
Pace.bar = bar = new Bar;
scalers = [];
return uniScaler = new Scaler;
})();
Pace.stop = function() {
Pace.trigger('stop');
Pace.running = false;
bar.destroy();
cancelAnimation = true;
if (animation != null) {
if (typeof cancelAnimationFrame === "function") {
cancelAnimationFrame(animation);
}
animation = null;
}
return init();
};
Pace.restart = function() {
Pace.trigger('restart');
Pace.stop();
return Pace.start();
};
Pace.go = function() {
var start;
Pace.running = true;
bar.render();
start = now();
cancelAnimation = false;
return animation = runAnimation(function(frameTime, enqueueNextFrame) {
var avg, count, done, element, elements, i, j, remaining, scaler, scalerList, sum, _j, _k, _len1, _len2, _ref2;
remaining = 100 - bar.progress;
count = sum = 0;
done = true;
for (i = _j = 0, _len1 = sources.length; _j < _len1; i = ++_j) {
source = sources[i];
scalerList = scalers[i] != null ? scalers[i] : scalers[i] = [];
elements = (_ref2 = source.elements) != null ? _ref2 : [source];
for (j = _k = 0, _len2 = elements.length; _k < _len2; j = ++_k) {
element = elements[j];
scaler = scalerList[j] != null ? scalerList[j] : scalerList[j] = new Scaler(element);
done &= scaler.done;
if (scaler.done) {
continue;
}
count++;
sum += scaler.tick(frameTime);
}
}
avg = sum / count;
bar.update(uniScaler.tick(frameTime, avg));
if (bar.done() || done || cancelAnimation) {
bar.update(100);
Pace.trigger('done');
return setTimeout(function() {
bar.finish();
Pace.running = false;
return Pace.trigger('hide');
}, Math.max(options.ghostTime, Math.max(options.minTime - (now() - start), 0)));
} else {
return enqueueNextFrame();
}
});
};
Pace.start = function(_options) {
extend(options, _options);
Pace.running = true;
try {
bar.render();
} catch (_error) {
NoTargetError = _error;
}
if (!document.querySelector('.pace')) {
return setTimeout(Pace.start, 50);
} else {
Pace.trigger('start');
return Pace.go();
}
};
if (typeof define === 'function' && define.amd) {
define(['pace'], function() {
return Pace;
});
} else if (typeof exports === 'object') {
module.exports = Pace;
} else {
if (options.startOnPageLoad) {
Pace.start();
}
}
}).call(this);
/*!
* wordcloud2.js
* http://timdream.org/wordcloud2.js/
*
* Copyright 2011 - 2013 Tim Chien
* Released under the MIT license
*
* Adapted by Dominic Bieri (BERTA Kommunikation AG) to accept special tag parameter in list items
*/
'use strict';
// setImmediate
if (!window.setImmediate) {
window.setImmediate = (function setupSetImmediate() {
return window.msSetImmediate ||
window.webkitSetImmediate ||
window.mozSetImmediate ||
window.oSetImmediate ||
(function setupSetZeroTimeout() {
if (!window.postMessage || !window.addEventListener) {
return null;
}
var callbacks = [undefined];
var message = 'zero-timeout-message';
// Like setTimeout, but only takes a function argument. There's
// no time argument (always zero) and no arguments (you have to
// use a closure).
var setZeroTimeout = function setZeroTimeout(callback) {
var id = callbacks.length;
callbacks.push(callback);
window.postMessage(message + id.toString(36), '*');
return id;
};
window.addEventListener('message', function setZeroTimeoutMessage(evt) {
// Skipping checking event source, retarded IE confused this window
// object with another in the presence of iframe
if (typeof evt.data !== 'string' ||
evt.data.substr(0, message.length) !== message/* ||
evt.source !== window */) {
return;
}
evt.stopImmediatePropagation();
var id = parseInt(evt.data.substr(message.length), 36);
if (!callbacks[id]) {
return;
}
callbacks[id]();
callbacks[id] = undefined;
}, true);
/* specify clearImmediate() here since we need the scope */
window.clearImmediate = function clearZeroTimeout(id) {
if (!callbacks[id]) {
return;
}
callbacks[id] = undefined;
};
return setZeroTimeout;
})() ||
// fallback
function setImmediateFallback(fn) {
window.setTimeout(fn, 0);
};
})();
}
if (!window.clearImmediate) {
window.clearImmediate = (function setupClearImmediate() {
return window.msClearImmediate ||
window.webkitClearImmediate ||
window.mozClearImmediate ||
window.oClearImmediate ||
// "clearZeroTimeout" is implement on the previous block ||
// fallback
function clearImmediateFallback(timer) {
window.clearTimeout(timer);
};
})();
}
(function(global) {
// Check if WordCloud can run on this browser
var isSupported = (function isSupported() {
var canvas = document.createElement('canvas');
if (!canvas || !canvas.getContext) {
return false;
}
var ctx = canvas.getContext('2d');
if (!ctx.getImageData) {
return false;
}
if (!ctx.fillText) {
return false;
}
if (!Array.prototype.some) {
return false;
}
if (!Array.prototype.push) {
return false;
}
return true;
}());
// Find out if the browser impose minium font size by
// drawing small texts on a canvas and measure it's width.
var minFontSize = (function getMinFontSize() {
if (!isSupported) {
return;
}
var ctx = document.createElement('canvas').getContext('2d');
// start from 20
var size = 20;
// two sizes to measure
var hanWidth, mWidth;
while (size) {
ctx.font = size.toString(10) + 'px sans-serif';
if ((ctx.measureText('\uFF37').width === hanWidth) &&
(ctx.measureText('m').width) === mWidth) {
return (size + 1);
}
hanWidth = ctx.measureText('\uFF37').width;
mWidth = ctx.measureText('m').width;
size--;
}
return 0;
})();
// Based on http://jsfromhell.com/array/shuffle
var shuffleArray = function shuffleArray(arr) {
for (var j, x, i = arr.length; i;
j = Math.floor(Math.random() * i),
x = arr[--i], arr[i] = arr[j],
arr[j] = x) {}
return arr;
};
var WordCloud = function WordCloud(elements, options) {
if (!isSupported) {
return;
}
if (!Array.isArray(elements)) {
elements = [elements];
}
elements.forEach(function(el, i) {
if (typeof el === 'string') {
elements[i] = document.getElementById(el);
if (!elements[i]) {
throw 'The element id specified is not found.';
}
} else if (!el.tagName && !el.appendChild) {
throw 'You must pass valid HTML elements, or ID of the element.';
}
});
/* Default values to be overwritten by options object */
var settings = {
list: [],
fontFamily: '"Trebuchet MS", "Heiti TC", "微軟正黑體", ' +
'"Arial Unicode MS", "Droid Fallback Sans", sans-serif',
fontWeight: 'normal',
color: 'random-dark',
minSize: 0, // 0 to disable
weightFactor: 1,
clearCanvas: true,
backgroundColor: '#fff', // opaque white = rgba(255, 255, 255, 1)
gridSize: 8,
drawOutOfBound: false,
origin: null,
drawMask: false,
maskColor: 'rgba(255,0,0,0.3)',
maskGapWidth: 0.3,
wait: 0,
abortThreshold: 0, // disabled
abort: function noop() {},
minRotation: - Math.PI / 2,
maxRotation: Math.PI / 2,
rotationSteps: 0,
shuffle: true,
rotateRatio: 0.1,
shape: 'circle',
ellipticity: 0.65,
classes: null,
hover: null,
click: null
};
if (options) {
for (var key in options) {
if (key in settings) {
settings[key] = options[key];
}
}
}
/* Convert weightFactor into a function */
if (typeof settings.weightFactor !== 'function') {
var factor = settings.weightFactor;
settings.weightFactor = function weightFactor(pt) {
return pt * factor; //in px
};
}
/* Convert shape into a function */
if (typeof settings.shape !== 'function') {
switch (settings.shape) {
case 'circle':
/* falls through */
default:
// 'circle' is the default and a shortcut in the code loop.
settings.shape = 'circle';
break;
case 'cardioid':
settings.shape = function shapeCardioid(theta) {
return 1 - Math.sin(theta);
};
break;
/*
To work out an X-gon, one has to calculate "m",
where 1/(cos(2*PI/X)+m*sin(2*PI/X)) = 1/(cos(0)+m*sin(0))
http://www.wolframalpha.com/input/?i=1%2F%28cos%282*PI%2FX%29%2Bm*sin%28
2*PI%2FX%29%29+%3D+1%2F%28cos%280%29%2Bm*sin%280%29%29
Copy the solution into polar equation r = 1/(cos(t') + m*sin(t'))
where t' equals to mod(t, 2PI/X);
*/
case 'diamond':
case 'square':
// http://www.wolframalpha.com/input/?i=plot+r+%3D+1%2F%28cos%28mod+
// %28t%2C+PI%2F2%29%29%2Bsin%28mod+%28t%2C+PI%2F2%29%29%29%2C+t+%3D
// +0+..+2*PI
settings.shape = function shapeSquare(theta) {
var thetaPrime = theta % (2 * Math.PI / 4);
return 1 / (Math.cos(thetaPrime) + Math.sin(thetaPrime));
};
break;
case 'triangle-forward':
// http://www.wolframalpha.com/input/?i=plot+r+%3D+1%2F%28cos%28mod+
// %28t%2C+2*PI%2F3%29%29%2Bsqrt%283%29sin%28mod+%28t%2C+2*PI%2F3%29
// %29%29%2C+t+%3D+0+..+2*PI
settings.shape = function shapeTriangle(theta) {
var thetaPrime = theta % (2 * Math.PI / 3);
return 1 / (Math.cos(thetaPrime) +
Math.sqrt(3) * Math.sin(thetaPrime));
};
break;
case 'triangle':
case 'triangle-upright':
settings.shape = function shapeTriangle(theta) {
var thetaPrime = (theta + Math.PI * 3 / 2) % (2 * Math.PI / 3);
return 1 / (Math.cos(thetaPrime) +
Math.sqrt(3) * Math.sin(thetaPrime));
};
break;
case 'pentagon':
settings.shape = function shapePentagon(theta) {
var thetaPrime = (theta + 0.955) % (2 * Math.PI / 5);
return 1 / (Math.cos(thetaPrime) +
0.726543 * Math.sin(thetaPrime));
};
break;
case 'star':
settings.shape = function shapeStar(theta) {
var thetaPrime = (theta + 0.955) % (2 * Math.PI / 10);
if ((theta + 0.955) % (2 * Math.PI / 5) - (2 * Math.PI / 10) >= 0) {
return 1 / (Math.cos((2 * Math.PI / 10) - thetaPrime) +
3.07768 * Math.sin((2 * Math.PI / 10) - thetaPrime));
} else {
return 1 / (Math.cos(thetaPrime) +
3.07768 * Math.sin(thetaPrime));
}
};
break;
}
}
/* Make sure gridSize is a whole number and is not smaller than 4px */
settings.gridSize = Math.max(Math.floor(settings.gridSize), 4);
/* shorthand */
var g = settings.gridSize;
var maskRectWidth = g - settings.maskGapWidth;
/* normalize rotation settings */
var rotationRange = Math.abs(settings.maxRotation - settings.minRotation);
var rotationSteps = Math.abs(Math.floor(settings.rotationSteps));
var minRotation = Math.min(settings.maxRotation, settings.minRotation);
/* information/object available to all functions, set when start() */
var grid, // 2d array containing filling information
ngx, ngy, // width and height of the grid
center, // position of the center of the cloud
maxRadius;
/* timestamp for measuring each putWord() action */
var escapeTime;
/* function for getting the color of the text */
var getTextColor;
function random_hsl_color(min, max) {
return 'hsl(' +
(Math.random() * 360).toFixed() + ',' +
(Math.random() * 30 + 70).toFixed() + '%,' +
(Math.random() * (max - min) + min).toFixed() + '%)';
}
switch (settings.color) {
case 'random-dark':
getTextColor = function getRandomDarkColor() {
return random_hsl_color(10, 50);
};
break;
case 'random-light':
getTextColor = function getRandomLightColor() {
return random_hsl_color(50, 90);
};
break;
default:
if (typeof settings.color === 'function') {
getTextColor = settings.color;
}
break;
}
/* function for getting the classes of the text */
var getTextClasses = null;
if (typeof settings.classes === 'function') {
getTextClasses = settings.classes;
}
/* Interactive */
var interactive = false;
var infoGrid = [];
var hovered;
var getInfoGridFromMouseTouchEvent =
function getInfoGridFromMouseTouchEvent(evt) {
var canvas = evt.currentTarget;
var rect = canvas.getBoundingClientRect();
var clientX;
var clientY;
/** Detect if touches are available */
if (evt.touches) {
clientX = evt.touches[0].clientX;
clientY = evt.touches[0].clientY;
} else {
clientX = evt.clientX;
clientY = evt.clientY;
}
var eventX = clientX - rect.left;
var eventY = clientY - rect.top;
var x = Math.floor(eventX * ((canvas.width / rect.width) || 1) / g);
var y = Math.floor(eventY * ((canvas.height / rect.height) || 1) / g);
return infoGrid[x][y];
};
var wordcloudhover = function wordcloudhover(evt) {
var info = getInfoGridFromMouseTouchEvent(evt);
if (hovered === info) {
return;
}
hovered = info;
if (!info) {
settings.hover(undefined, undefined, evt);
return;
}
settings.hover(info.item, info.dimension, evt);
};
var wordcloudclick = function wordcloudclick(evt) {
var info = getInfoGridFromMouseTouchEvent(evt);
if (!info) {
return;
}
settings.click(info.item, info.dimension, evt);
evt.preventDefault();
};
/* Get points on the grid for a given radius away from the center */
var pointsAtRadius = [];
var getPointsAtRadius = function getPointsAtRadius(radius) {
if (pointsAtRadius[radius]) {
return pointsAtRadius[radius];
}
// Look for these number of points on each radius
var T = radius * 8;
// Getting all the points at this radius
var t = T;
var points = [];
if (radius === 0) {
points.push([center[0], center[1], 0]);
}
while (t--) {
// distort the radius to put the cloud in shape
var rx = 1;
if (settings.shape !== 'circle') {
rx = settings.shape(t / T * 2 * Math.PI); // 0 to 1
}
// Push [x, y, t]; t is used solely for getTextColor()
points.push([
center[0] + radius * rx * Math.cos(-t / T * 2 * Math.PI),
center[1] + radius * rx * Math.sin(-t / T * 2 * Math.PI) *
settings.ellipticity,
t / T * 2 * Math.PI]);
}
pointsAtRadius[radius] = points;
return points;
};
/* Return true if we had spent too much time */
var exceedTime = function exceedTime() {
return ((settings.abortThreshold > 0) &&
((new Date()).getTime() - escapeTime > settings.abortThreshold));
};
/* Get the deg of rotation according to settings, and luck. */
var getRotateDeg = function getRotateDeg() {
if (settings.rotateRatio === 0) {
return 0;
}
if (Math.random() > settings.rotateRatio) {
return 0;
}
if (rotationRange === 0) {
return minRotation;
}
if (rotationSteps > 0) {
return minRotation +
(1 / Math.floor((Math.random() * rotationSteps) + 1)) *
rotationRange;
}
else {
return minRotation + Math.random() * rotationRange;
}
};
var getTextInfo = function getTextInfo(word, weight, rotateDeg) {
// calculate the acutal font size
// fontSize === 0 means weightFactor function wants the text skipped,
// and size < minSize means we cannot draw the text.
var debug = false;
var fontSize = settings.weightFactor(weight);
if (fontSize <= settings.minSize) {
return false;
}
// Scale factor here is to make sure fillText is not limited by
// the minium font size set by browser.
// It will always be 1 or 2n.
var mu = 1;
if (fontSize < minFontSize) {
mu = (function calculateScaleFactor() {
var mu = 2;
while (mu * fontSize < minFontSize) {
mu += 2;
}
return mu;
})();
}
var fcanvas = document.createElement('canvas');
var fctx = fcanvas.getContext('2d', { willReadFrequently: true });
fctx.font = settings.fontWeight + ' ' +
(fontSize * mu).toString(10) + 'px ' + settings.fontFamily;
// Estimate the dimension of the text with measureText().
var fw = fctx.measureText(word).width / mu;
var fh = Math.max(fontSize * mu,
fctx.measureText('m').width,
fctx.measureText('\uFF37').width) / mu;
// Create a boundary box that is larger than our estimates,
// so text don't get cut of (it sill might)
var boxWidth = fw + fh * 2;
var boxHeight = fh * 3;
var fgw = Math.ceil(boxWidth / g);
var fgh = Math.ceil(boxHeight / g);
boxWidth = fgw * g;
boxHeight = fgh * g;
// Calculate the proper offsets to make the text centered at
// the preferred position.
// This is simply half of the width.
var fillTextOffsetX = - fw / 2;
// Instead of moving the box to the exact middle of the preferred
// position, for Y-offset we move 0.4 instead, so Latin alphabets look
// vertical centered.
var fillTextOffsetY = - fh * 0.4;
// Calculate the actual dimension of the canvas, considering the rotation.
var cgh = Math.ceil((boxWidth * Math.abs(Math.sin(rotateDeg)) +
boxHeight * Math.abs(Math.cos(rotateDeg))) / g);
var cgw = Math.ceil((boxWidth * Math.abs(Math.cos(rotateDeg)) +
boxHeight * Math.abs(Math.sin(rotateDeg))) / g);
var width = cgw * g;
var height = cgh * g;
fcanvas.setAttribute('width', width);
fcanvas.setAttribute('height', height);
if (debug) {
// Attach fcanvas to the DOM
document.body.appendChild(fcanvas);
// Save it's state so that we could restore and draw the grid correctly.
fctx.save();
}
// Scale the canvas with |mu|.
fctx.scale(1 / mu, 1 / mu);
fctx.translate(width * mu / 2, height * mu / 2);
fctx.rotate(- rotateDeg);
// Once the width/height is set, ctx info will be reset.
// Set it again here.
fctx.font = settings.fontWeight + ' ' +
(fontSize * mu).toString(10) + 'px ' + settings.fontFamily;
// Fill the text into the fcanvas.
// XXX: We cannot because textBaseline = 'top' here because
// Firefox and Chrome uses different default line-height for canvas.
// Please read https://bugzil.la/737852#c6.
// Here, we use textBaseline = 'middle' and draw the text at exactly
// 0.5 * fontSize lower.
fctx.fillStyle = '#000';
fctx.textBaseline = 'middle';
fctx.fillText(word, fillTextOffsetX * mu,
(fillTextOffsetY + fontSize * 0.5) * mu);
// Get the pixels of the text
var imageData = fctx.getImageData(0, 0, width, height).data;
if (exceedTime()) {
return false;
}
if (debug) {
// Draw the box of the original estimation
fctx.strokeRect(fillTextOffsetX * mu,
fillTextOffsetY, fw * mu, fh * mu);
fctx.restore();
}
// Read the pixels and save the information to the occupied array
var occupied = [];
var gx = cgw, gy, x, y;
var bounds = [cgh / 2, cgw / 2, cgh / 2, cgw / 2];
while (gx--) {
gy = cgh;
while (gy--) {
y = g;
singleGridLoop: {
while (y--) {
x = g;
while (x--) {
if (imageData[((gy * g + y) * width +
(gx * g + x)) * 4 + 3]) {
occupied.push([gx, gy]);
if (gx < bounds[3]) {
bounds[3] = gx;
}
if (gx > bounds[1]) {
bounds[1] = gx;
}
if (gy < bounds[0]) {
bounds[0] = gy;
}
if (gy > bounds[2]) {
bounds[2] = gy;
}
if (debug) {
fctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
fctx.fillRect(gx * g, gy * g, g - 0.5, g - 0.5);
}
break singleGridLoop;
}
}
}
if (debug) {
fctx.fillStyle = 'rgba(0, 0, 255, 0.5)';
fctx.fillRect(gx * g, gy * g, g - 0.5, g - 0.5);
}
}
}
}
if (debug) {
fctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
fctx.fillRect(bounds[3] * g,
bounds[0] * g,
(bounds[1] - bounds[3] + 1) * g,
(bounds[2] - bounds[0] + 1) * g);
}
// Return information needed to create the text on the real canvas
return {
mu: mu,
occupied: occupied,
bounds: bounds,
gw: cgw,
gh: cgh,
fillTextOffsetX: fillTextOffsetX,
fillTextOffsetY: fillTextOffsetY,
fillTextWidth: fw,
fillTextHeight: fh,
fontSize: fontSize
};
};
/* Determine if there is room available in the given dimension */
var canFitText = function canFitText(gx, gy, gw, gh, occupied) {
// Go through the occupied points,
// return false if the space is not available.
var i = occupied.length;
while (i--) {
var px = gx + occupied[i][0];
var py = gy + occupied[i][1];
if (px >= ngx || py >= ngy || px < 0 || py < 0) {
if (!settings.drawOutOfBound) {
return false;
}
continue;
}
if (!grid[px][py]) {
return false;
}
}
return true;
};
/* Actually draw the text on the grid */
var drawText = function drawText(gx, gy, info, word, weight,
distance, theta, rotateDeg, attributes) {
var fontSize = info.fontSize;
var color;
if (getTextColor) {
color = getTextColor(word, weight, fontSize, distance, theta);
} else {
color = settings.color;
}
var classes;
if (getTextClasses) {
classes = getTextClasses(word, weight, fontSize, distance, theta);
} else {
classes = settings.classes;
}
var dimension;
var bounds = info.bounds;
dimension = {
x: (gx + bounds[3]) * g,
y: (gy + bounds[0]) * g,
w: (bounds[1] - bounds[3] + 1) * g,
h: (bounds[2] - bounds[0] + 1) * g
};
elements.forEach(function(el) {
if (el.getContext) {
var ctx = el.getContext('2d');
var mu = info.mu;
// Save the current state before messing it
ctx.save();
ctx.scale(1 / mu, 1 / mu);
ctx.font = settings.fontWeight + ' ' +
(fontSize * mu).toString(10) + 'px ' + settings.fontFamily;
ctx.fillStyle = color;
// Translate the canvas position to the origin coordinate of where
// the text should be put.
ctx.translate((gx + info.gw / 2) * g * mu,
(gy + info.gh / 2) * g * mu);
if (rotateDeg !== 0) {
ctx.rotate(- rotateDeg);
}
// Finally, fill the text.
// XXX: We cannot because textBaseline = 'top' here because
// Firefox and Chrome uses different default line-height for canvas.
// Please read https://bugzil.la/737852#c6.
// Here, we use textBaseline = 'middle' and draw the text at exactly
// 0.5 * fontSize lower.
ctx.textBaseline = 'middle';
ctx.fillText(word, info.fillTextOffsetX * mu,
(info.fillTextOffsetY + fontSize * 0.5) * mu);
// The below box is always matches how s are positioned
/* ctx.strokeRect(info.fillTextOffsetX, info.fillTextOffsetY,
info.fillTextWidth, info.fillTextHeight); */
// Restore the state.
ctx.restore();
} else {
// drawText on DIV element
if (! attributes.hasOwnProperty('tag')){
attributes.tag = 'span';
}
var span = document.createElement(attributes.tag);
var transformRule = '';
transformRule = 'rotate(' + (- rotateDeg / Math.PI * 180) + 'deg) ';
if (info.mu !== 1) {
transformRule +=
'translateX(-' + (info.fillTextWidth / 4) + 'px) ' +
'scale(' + (1 / info.mu) + ')';
}
var styleRules = {
'position': 'absolute',
'display': 'block',
'font': settings.fontWeight + ' ' +
(fontSize * info.mu) + 'px ' + settings.fontFamily,
'left': ((gx + info.gw / 2) * g + info.fillTextOffsetX) + 'px',
'top': ((gy + info.gh / 2) * g + info.fillTextOffsetY) + 'px',
'width': info.fillTextWidth + 'px',
'height': info.fillTextHeight + 'px',
'lineHeight': fontSize + 'px',
'whiteSpace': 'nowrap',
'transform': transformRule,
'webkitTransform': transformRule,
'msTransform': transformRule,
'transformOrigin': '50% 40%',
'webkitTransformOrigin': '50% 40%',
'msTransformOrigin': '50% 40%'
};
if (color) {
styleRules.color = color;
}
span.textContent = word;
for (var cssProp in styleRules) {
span.style[cssProp] = styleRules[cssProp];
}
if (attributes) {
for (var attribute in attributes) {
if (attribute == 'tag') continue;
span.setAttribute(attribute, attributes[attribute]);
}
}
if (classes) {
span.className += classes;
}
el.appendChild(span);
}
});
};
/* Help function to updateGrid */
var fillGridAt = function fillGridAt(x, y, drawMask, dimension, item) {
if (x >= ngx || y >= ngy || x < 0 || y < 0) {
return;
}
grid[x][y] = false;
if (drawMask) {
var ctx = elements[0].getContext('2d');
ctx.fillRect(x * g, y * g, maskRectWidth, maskRectWidth);
}
if (interactive) {
infoGrid[x][y] = { item: item, dimension: dimension };
}
};
/* Update the filling information of the given space with occupied points.
Draw the mask on the canvas if necessary. */
var updateGrid = function updateGrid(gx, gy, gw, gh, info, item) {
var occupied = info.occupied;
var drawMask = settings.drawMask;
var ctx;
if (drawMask) {
ctx = elements[0].getContext('2d');
ctx.save();
ctx.fillStyle = settings.maskColor;
}
var dimension;
if (interactive) {
var bounds = info.bounds;
dimension = {
x: (gx + bounds[3]) * g,
y: (gy + bounds[0]) * g,
w: (bounds[1] - bounds[3] + 1) * g,
h: (bounds[2] - bounds[0] + 1) * g
};
}
var i = occupied.length;
while (i--) {
var px = gx + occupied[i][0];
var py = gy + occupied[i][1];
if (px >= ngx || py >= ngy || px < 0 || py < 0) {
continue;
}
fillGridAt(px, py, drawMask, dimension, item);
}
if (drawMask) {
ctx.restore();
}
};
/* putWord() processes each item on the list,
calculate it's size and determine it's position, and actually
put it on the canvas. */
var putWord = function putWord(item) {
var word, weight, attributes;
if (Array.isArray(item)) {
word = item[0];
weight = item[1];
} else {
word = item.word;
weight = item.weight;
attributes = item.attributes;
}
var rotateDeg = getRotateDeg();
// get info needed to put the text onto the canvas
var info = getTextInfo(word, weight, rotateDeg);
// not getting the info means we shouldn't be drawing this one.
if (!info) {
return false;
}
if (exceedTime()) {
return false;
}
// If drawOutOfBound is set to false,
// skip the loop if we have already know the bounding box of
// word is larger than the canvas.
if (!settings.drawOutOfBound) {
var bounds = info.bounds;
if ((bounds[1] - bounds[3] + 1) > ngx ||
(bounds[2] - bounds[0] + 1) > ngy) {
return false;
}
}
// Determine the position to put the text by
// start looking for the nearest points
var r = maxRadius + 1;
var tryToPutWordAtPoint = function(gxy) {
var gx = Math.floor(gxy[0] - info.gw / 2);
var gy = Math.floor(gxy[1] - info.gh / 2);
var gw = info.gw;
var gh = info.gh;
// If we cannot fit the text at this position, return false
// and go to the next position.
if (!canFitText(gx, gy, gw, gh, info.occupied)) {
return false;
}
// Actually put the text on the canvas
drawText(gx, gy, info, word, weight,
(maxRadius - r), gxy[2], rotateDeg, attributes);
// Mark the spaces on the grid as filled
updateGrid(gx, gy, gw, gh, info, item);
// Return true so some() will stop and also return true.
return true;
};
while (r--) {
var points = getPointsAtRadius(maxRadius - r);
if (settings.shuffle) {
points = [].concat(points);
shuffleArray(points);
}
// Try to fit the words by looking at each point.
// array.some() will stop and return true
// when putWordAtPoint() returns true.
// If all the points returns false, array.some() returns false.
var drawn = points.some(tryToPutWordAtPoint);
if (drawn) {
// leave putWord() and return true
return true;
}
}
// we tried all distances but text won't fit, return false
return false;
};
/* Send DOM event to all elements. Will stop sending event and return
if the previous one is canceled (for cancelable events). */
var sendEvent = function sendEvent(type, cancelable, detail) {
if (cancelable) {
return !elements.some(function(el) {
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(type, true, cancelable, detail || {});
return !el.dispatchEvent(evt);
}, this);
} else {
elements.forEach(function(el) {
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(type, true, cancelable, detail || {});
el.dispatchEvent(evt);
}, this);
}
};
/* Start drawing on a canvas */
var start = function start() {
// For dimensions, clearCanvas etc.,
// we only care about the first element.
var canvas = elements[0];
if (canvas.getContext) {
ngx = Math.ceil(canvas.width / g);
ngy = Math.ceil(canvas.height / g);
} else {
var rect = canvas.getBoundingClientRect();
ngx = Math.ceil(rect.width / g);
ngy = Math.ceil(rect.height / g);
}
// Sending a wordcloudstart event which cause the previous loop to stop.
// Do nothing if the event is canceled.
if (!sendEvent('wordcloudstart', true)) {
return;
}
// Determine the center of the word cloud
center = (settings.origin) ?
[settings.origin[0]/g, settings.origin[1]/g] :
[ngx / 2, ngy / 2];
// Maxium radius to look for space
maxRadius = Math.floor(Math.sqrt(ngx * ngx + ngy * ngy));
/* Clear the canvas only if the clearCanvas is set,
if not, update the grid to the current canvas state */
grid = [];
var gx, gy, i;
if (!canvas.getContext || settings.clearCanvas) {
elements.forEach(function(el) {
if (el.getContext) {
var ctx = el.getContext('2d');
ctx.fillStyle = settings.backgroundColor;
ctx.clearRect(0, 0, ngx * (g + 1), ngy * (g + 1));
ctx.fillRect(0, 0, ngx * (g + 1), ngy * (g + 1));
} else {
el.textContent = '';
el.style.backgroundColor = settings.backgroundColor;
el.style.position = 'relative';
}
});
/* fill the grid with empty state */
gx = ngx;
while (gx--) {
grid[gx] = [];
gy = ngy;
while (gy--) {
grid[gx][gy] = true;
}
}
} else {
/* Determine bgPixel by creating
another canvas and fill the specified background color. */
var bctx = document.createElement('canvas').getContext('2d');
bctx.fillStyle = settings.backgroundColor;
bctx.fillRect(0, 0, 1, 1);
var bgPixel = bctx.getImageData(0, 0, 1, 1).data;
/* Read back the pixels of the canvas we got to tell which part of the
canvas is empty.
(no clearCanvas only works with a canvas, not divs) */
var imageData =
canvas.getContext('2d').getImageData(0, 0, ngx * g, ngy * g).data;
gx = ngx;
var x, y;
while (gx--) {
grid[gx] = [];
gy = ngy;
while (gy--) {
y = g;
singleGridLoop: while (y--) {
x = g;
while (x--) {
i = 4;
while (i--) {
if (imageData[((gy * g + y) * ngx * g +
(gx * g + x)) * 4 + i] !== bgPixel[i]) {
grid[gx][gy] = false;
break singleGridLoop;
}
}
}
}
if (grid[gx][gy] !== false) {
grid[gx][gy] = true;
}
}
}
imageData = bctx = bgPixel = undefined;
}
// fill the infoGrid with empty state if we need it
if (settings.hover || settings.click) {
interactive = true;
/* fill the grid with empty state */
gx = ngx + 1;
while (gx--) {
infoGrid[gx] = [];
}
if (settings.hover) {
canvas.addEventListener('mousemove', wordcloudhover);
}
if (settings.click) {
canvas.addEventListener('click', wordcloudclick);
canvas.addEventListener('touchstart', wordcloudclick);
canvas.addEventListener('touchend', function (e) {
e.preventDefault();
});
canvas.style.webkitTapHighlightColor = 'rgba(0, 0, 0, 0)';
}
canvas.addEventListener('wordcloudstart', function stopInteraction() {
canvas.removeEventListener('wordcloudstart', stopInteraction);
canvas.removeEventListener('mousemove', wordcloudhover);
canvas.removeEventListener('click', wordcloudclick);
hovered = undefined;
});
}
i = 0;
var loopingFunction, stoppingFunction;
if (settings.wait !== 0) {
loopingFunction = window.setTimeout;
stoppingFunction = window.clearTimeout;
} else {
loopingFunction = window.setImmediate;
stoppingFunction = window.clearImmediate;
}
var addEventListener = function addEventListener(type, listener) {
elements.forEach(function(el) {
el.addEventListener(type, listener);
}, this);
};
var removeEventListener = function removeEventListener(type, listener) {
elements.forEach(function(el) {
el.removeEventListener(type, listener);
}, this);
};
var anotherWordCloudStart = function anotherWordCloudStart() {
removeEventListener('wordcloudstart', anotherWordCloudStart);
stoppingFunction(timer);
};
addEventListener('wordcloudstart', anotherWordCloudStart);
var timer = loopingFunction(function loop() {
if (i >= settings.list.length) {
stoppingFunction(timer);
sendEvent('wordcloudstop', false);
removeEventListener('wordcloudstart', anotherWordCloudStart);
return;
}
escapeTime = (new Date()).getTime();
var drawn = putWord(settings.list[i]);
var canceled = !sendEvent('wordclouddrawn', true, {
item: settings.list[i], drawn: drawn });
if (exceedTime() || canceled) {
stoppingFunction(timer);
settings.abort();
sendEvent('wordcloudabort', false);
sendEvent('wordcloudstop', false);
removeEventListener('wordcloudstart', anotherWordCloudStart);
return;
}
i++;
timer = loopingFunction(loop, settings.wait);
}, settings.wait);
};
// All set, start the drawing
start();
};
WordCloud.isSupported = isSupported;
WordCloud.minFontSize = minFontSize;
// Expose the library as an AMD module
if (typeof define === 'function' && define.amd) {
global.WordCloud = WordCloud;
define('wordcloud', [], function() { return WordCloud; });
} else if (typeof module !== 'undefined' && module.exports) {
module.exports = WordCloud;
} else {
global.WordCloud = WordCloud;
}
})(this); //jshint ignore:line