")
.attr("role", "tooltip")
.addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content " +
(this.options.tooltipClass || "")),
id = tooltip.uniqueId().attr("id");
$("
")
.addClass("ui-tooltip-content")
.appendTo(tooltip);
tooltip.appendTo(this.document[0].body);
return this.tooltips[id] = {
element: element,
tooltip: tooltip
};
},
_find: function (target) {
var id = target.data("ui-tooltip-id");
return id ? this.tooltips[id] : null;
},
_removeTooltip: function (tooltip) {
tooltip.remove();
delete this.tooltips[tooltip.attr("id")];
},
_destroy: function () {
var that = this;
// close open tooltips
$.each(this.tooltips, function (id, tooltipData) {
// Delegate to close method to handle common cleanup
var event = $.Event("blur"),
element = tooltipData.element;
event.target = event.currentTarget = element[0];
that.close(event, true);
// Remove immediately; destroying an open tooltip doesn't use the
// hide animation
$("#" + id).remove();
// Restore the title
if (element.data("ui-tooltip-title")) {
// If the title attribute has changed since open(), don't restore
if (!element.attr("title")) {
element.attr("title", element.data("ui-tooltip-title"));
}
element.removeData("ui-tooltip-title");
}
});
this.liveRegion.remove();
}
});
}));
/*!
* jquery-timepicker v1.8.1 - A jQuery timepicker plugin inspired by Google Calendar. It supports both mouse and keyboard navigation.
* Copyright (c) 2015 Jon Thornton - http://jonthornton.github.com/jquery-timepicker/
* License: MIT
*/
(function (factory) {
if (typeof exports === "object" && exports &&
typeof module === "object" && module && module.exports === exports) {
// Browserify. Attach to jQuery module.
factory(require("jquery"));
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var _baseDate = _generateBaseDate();
var _ONE_DAY = 86400;
var _lang = {
am: 'am',
pm: 'pm',
AM: 'AM',
PM: 'PM',
decimal: '.',
mins: 'mins',
hr: 'hr',
hrs: 'hrs'
};
var methods = {
init: function (options) {
return this.each(function () {
var self = $(this);
// pick up settings from data attributes
var attributeOptions = [];
for (var key in $.fn.timepicker.defaults) {
if (self.data(key)) {
attributeOptions[key] = self.data(key);
}
}
var settings = $.extend({}, $.fn.timepicker.defaults, attributeOptions, options);
if (settings.lang) {
_lang = $.extend(_lang, settings.lang);
}
settings = _parseSettings(settings);
self.data('timepicker-settings', settings);
self.addClass('ui-timepicker-input');
if (settings.useSelect) {
_render(self);
} else {
self.prop('autocomplete', 'off');
if (settings.showOn) {
for (i in settings.showOn) {
self.on(settings.showOn[i] + '.timepicker', methods.show);
}
}
self.on('change.timepicker', _formatValue);
self.on('keydown.timepicker', _keydownhandler);
self.on('keyup.timepicker', _keyuphandler);
if (settings.disableTextInput) {
self.on('keypress.timepicker', function (e) { e.preventDefault(); });
}
_formatValue.call(self.get(0));
}
});
},
show: function (e) {
var self = $(this);
var settings = self.data('timepicker-settings');
if (e) {
e.preventDefault();
}
if (settings.useSelect) {
self.data('timepicker-list').focus();
return;
}
if (_hideKeyboard(self)) {
// block the keyboard on mobile devices
self.blur();
}
var list = self.data('timepicker-list');
// check if input is readonly
if (self.prop('readonly')) {
return;
}
// check if list needs to be rendered
if (!list || list.length === 0 || typeof settings.durationTime === 'function') {
_render(self);
list = self.data('timepicker-list');
}
if (_isVisible(list)) {
return;
}
self.data('ui-timepicker-value', self.val());
_setSelected(self, list);
// make sure other pickers are hidden
methods.hide();
// position the dropdown relative to the input
list.show();
var listOffset = {};
if (settings.orientation.match(/r/)) {
// right-align the dropdown
listOffset.left = self.offset().left + self.outerWidth() - list.outerWidth() + parseInt(list.css('marginLeft').replace('px', ''), 10);
} else {
// left-align the dropdown
listOffset.left = self.offset().left + parseInt(list.css('marginLeft').replace('px', ''), 10);
}
var verticalOrientation;
if (settings.orientation.match(/t/)) {
verticalOrientation = 't';
} else if (settings.orientation.match(/b/)) {
verticalOrientation = 'b';
} else if ((self.offset().top + self.outerHeight(true) + list.outerHeight()) > $(window).height() + $(window).scrollTop()) {
verticalOrientation = 't';
} else {
verticalOrientation = 'b';
}
if (verticalOrientation == 't') {
// position the dropdown on top
list.addClass('ui-timepicker-positioned-top');
listOffset.top = self.offset().top - list.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10);
} else {
// put it under the input
list.removeClass('ui-timepicker-positioned-top');
listOffset.top = self.offset().top + self.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10);
}
list.offset(listOffset);
// position scrolling
var selected = list.find('.ui-timepicker-selected');
if (!selected.length) {
if (_getTimeValue(self)) {
selected = _findRow(self, list, _time2int(_getTimeValue(self)));
} else if (settings.scrollDefault) {
selected = _findRow(self, list, settings.scrollDefault());
}
}
if (selected && selected.length) {
var topOffset = list.scrollTop() + selected.position().top - selected.outerHeight();
list.scrollTop(topOffset);
} else {
list.scrollTop(0);
}
// prevent scroll propagation
if (settings.stopScrollPropagation) {
$(document).on('wheel.ui-timepicker', '.ui-timepicker-wrapper', function (e) {
e.preventDefault();
var currentScroll = $(this).scrollTop();
$(this).scrollTop(currentScroll + e.originalEvent.deltaY);
});
}
// attach close handlers
$(document).on('touchstart.ui-timepicker mousedown.ui-timepicker', _closeHandler);
$(window).on('resize.ui-timepicker', _closeHandler);
if (settings.closeOnWindowScroll) {
$(document).on('scroll.ui-timepicker', _closeHandler);
}
self.trigger('showTimepicker');
return this;
},
hide: function (e) {
var self = $(this);
var settings = self.data('timepicker-settings');
if (settings && settings.useSelect) {
self.blur();
}
$('.ui-timepicker-wrapper').each(function () {
var list = $(this);
if (!_isVisible(list)) {
return;
}
var self = list.data('timepicker-input');
var settings = self.data('timepicker-settings');
if (settings && settings.selectOnBlur) {
_selectValue(self);
}
list.hide();
self.trigger('hideTimepicker');
});
return this;
},
option: function (key, value) {
return this.each(function () {
var self = $(this);
var settings = self.data('timepicker-settings');
var list = self.data('timepicker-list');
if (typeof key == 'object') {
settings = $.extend(settings, key);
} else if (typeof key == 'string' && typeof value != 'undefined') {
settings[key] = value;
} else if (typeof key == 'string') {
return settings[key];
}
settings = _parseSettings(settings);
self.data('timepicker-settings', settings);
if (list) {
list.remove();
self.data('timepicker-list', false);
}
if (settings.useSelect) {
_render(self);
}
});
},
getSecondsFromMidnight: function () {
return _time2int(_getTimeValue(this));
},
getTime: function (relative_date) {
var self = this;
var time_string = _getTimeValue(self);
if (!time_string) {
return null;
}
var offset = _time2int(time_string);
if (offset === null) {
return null;
}
if (!relative_date) {
relative_date = new Date();
}
// construct a Date with today's date, and offset's time
var time = new Date(relative_date);
time.setHours(offset / 3600);
time.setMinutes(offset % 3600 / 60);
time.setSeconds(offset % 60);
time.setMilliseconds(0);
return time;
},
setTime: function (value) {
var self = this;
var settings = self.data('timepicker-settings');
if (settings.forceRoundTime) {
var prettyTime = _roundAndFormatTime(_time2int(value), settings)
} else {
var prettyTime = _int2time(_time2int(value), settings);
}
if (value && prettyTime === null && settings.noneOption) {
prettyTime = value;
}
_setTimeValue(self, prettyTime);
if (self.data('timepicker-list')) {
_setSelected(self, self.data('timepicker-list'));
}
return this;
},
remove: function () {
var self = this;
// check if this element is a timepicker
if (!self.hasClass('ui-timepicker-input')) {
return;
}
var settings = self.data('timepicker-settings');
self.removeAttr('autocomplete', 'off');
self.removeClass('ui-timepicker-input');
self.removeData('timepicker-settings');
self.off('.timepicker');
// timepicker-list won't be present unless the user has interacted with this timepicker
if (self.data('timepicker-list')) {
self.data('timepicker-list').remove();
}
if (settings.useSelect) {
self.show();
}
self.removeData('timepicker-list');
return this;
}
};
// private methods
function _isVisible(elem) {
var el = elem[0];
return el.offsetWidth > 0 && el.offsetHeight > 0;
}
function _parseSettings(settings) {
if (settings.minTime) {
settings.minTime = _time2int(settings.minTime);
}
if (settings.maxTime) {
settings.maxTime = _time2int(settings.maxTime);
}
if (settings.durationTime && typeof settings.durationTime !== 'function') {
settings.durationTime = _time2int(settings.durationTime);
}
if (settings.scrollDefault == 'now') {
settings.scrollDefault = function () {
return settings.roundingFunction(_time2int(new Date()), settings);
}
} else if (settings.scrollDefault && typeof settings.scrollDefault != 'function') {
var val = settings.scrollDefault;
settings.scrollDefault = function () {
return settings.roundingFunction(_time2int(val), settings);
}
} else if (settings.minTime) {
settings.scrollDefault = function () {
return settings.roundingFunction(settings.minTime, settings);
}
}
if ($.type(settings.timeFormat) === "string" && settings.timeFormat.match(/[gh]/)) {
settings._twelveHourTime = true;
}
if (settings.showOnFocus === false && settings.showOn.indexOf('focus') != -1) {
settings.showOn.splice(settings.showOn.indexOf('focus'), 1);
}
if (settings.disableTimeRanges.length > 0) {
// convert string times to integers
for (var i in settings.disableTimeRanges) {
settings.disableTimeRanges[i] = [
_time2int(settings.disableTimeRanges[i][0]),
_time2int(settings.disableTimeRanges[i][1])
];
}
// sort by starting time
settings.disableTimeRanges = settings.disableTimeRanges.sort(function (a, b) {
return a[0] - b[0];
});
// merge any overlapping ranges
for (var i = settings.disableTimeRanges.length - 1; i > 0; i--) {
if (settings.disableTimeRanges[i][0] <= settings.disableTimeRanges[i - 1][1]) {
settings.disableTimeRanges[i - 1] = [
Math.min(settings.disableTimeRanges[i][0], settings.disableTimeRanges[i - 1][0]),
Math.max(settings.disableTimeRanges[i][1], settings.disableTimeRanges[i - 1][1])
];
settings.disableTimeRanges.splice(i, 1);
}
}
}
return settings;
}
function _render(self) {
var settings = self.data('timepicker-settings');
var list = self.data('timepicker-list');
if (list && list.length) {
list.remove();
self.data('timepicker-list', false);
}
if (settings.useSelect) {
list = $('
', { 'class': 'ui-timepicker-select' });
var wrapped_list = list;
} else {
list = $('
', { 'class': 'ui-timepicker-list' });
var wrapped_list = $('
', { 'class': 'ui-timepicker-wrapper', 'tabindex': -1 });
wrapped_list.css({ 'display': 'none', 'position': 'absolute' }).append(list);
}
if (settings.noneOption) {
if (settings.noneOption === true) {
settings.noneOption = (settings.useSelect) ? 'Time...' : 'None';
}
if ($.isArray(settings.noneOption)) {
for (var i in settings.noneOption) {
if (parseInt(i, 10) == i) {
var noneElement = _generateNoneElement(settings.noneOption[i], settings.useSelect);
list.append(noneElement);
}
}
} else {
var noneElement = _generateNoneElement(settings.noneOption, settings.useSelect);
list.append(noneElement);
}
}
if (settings.className) {
wrapped_list.addClass(settings.className);
}
if ((settings.minTime !== null || settings.durationTime !== null) && settings.showDuration) {
var stepval = typeof settings.step == 'function' ? 'function' : settings.step;
wrapped_list.addClass('ui-timepicker-with-duration');
wrapped_list.addClass('ui-timepicker-step-' + settings.step);
}
var durStart = settings.minTime;
if (typeof settings.durationTime === 'function') {
durStart = _time2int(settings.durationTime());
} else if (settings.durationTime !== null) {
durStart = settings.durationTime;
}
var start = (settings.minTime !== null) ? settings.minTime : 0;
var end = (settings.maxTime !== null) ? settings.maxTime : (start + _ONE_DAY - 1);
if (end < start) {
// make sure the end time is greater than start time, otherwise there will be no list to show
end += _ONE_DAY;
}
if (end === _ONE_DAY - 1 && $.type(settings.timeFormat) === "string" && settings.show2400) {
// show a 24:00 option when using military time
end = _ONE_DAY;
}
var dr = settings.disableTimeRanges;
var drCur = 0;
var drLen = dr.length;
var stepFunc = settings.step;
if (typeof stepFunc != 'function') {
stepFunc = function () {
return settings.step;
}
}
for (var i = start, j = 0; i <= end; j++, i += stepFunc(j) * 60) {
var timeInt = i;
var timeString = _int2time(timeInt, settings);
if (settings.useSelect) {
var row = $('
', { 'value': timeString });
row.text(timeString);
} else {
var row = $('
');
row.data('time', (timeInt <= 86400 ? timeInt : timeInt % 86400));
row.text(timeString);
}
if ((settings.minTime !== null || settings.durationTime !== null) && settings.showDuration) {
var durationString = _int2duration(i - durStart, settings.step);
if (settings.useSelect) {
row.text(row.text() + ' (' + durationString + ')');
} else {
var duration = $('
', { 'class': 'ui-timepicker-duration' });
duration.text(' (' + durationString + ')');
row.append(duration);
}
}
if (drCur < drLen) {
if (timeInt >= dr[drCur][1]) {
drCur += 1;
}
if (dr[drCur] && timeInt >= dr[drCur][0] && timeInt < dr[drCur][1]) {
if (settings.useSelect) {
row.prop('disabled', true);
} else {
row.addClass('ui-timepicker-disabled');
}
}
}
list.append(row);
}
wrapped_list.data('timepicker-input', self);
self.data('timepicker-list', wrapped_list);
if (settings.useSelect) {
if (self.val()) {
list.val(_roundAndFormatTime(_time2int(self.val()), settings));
}
list.on('focus', function () {
$(this).data('timepicker-input').trigger('showTimepicker');
});
list.on('blur', function () {
$(this).data('timepicker-input').trigger('hideTimepicker');
});
list.on('change', function () {
_setTimeValue(self, $(this).val(), 'select');
});
_setTimeValue(self, list.val(), 'initial');
self.hide().after(list);
} else {
var appendTo = settings.appendTo;
if (typeof appendTo === 'string') {
appendTo = $(appendTo);
} else if (typeof appendTo === 'function') {
appendTo = appendTo(self);
}
appendTo.append(wrapped_list);
_setSelected(self, list);
list.on('mousedown', 'li', function (e) {
// hack: temporarily disable the focus handler
// to deal with the fact that IE fires 'focus'
// events asynchronously
self.off('focus.timepicker');
self.on('focus.timepicker-ie-hack', function () {
self.off('focus.timepicker-ie-hack');
self.on('focus.timepicker', methods.show);
});
if (!_hideKeyboard(self)) {
self[0].focus();
}
// make sure only the clicked row is selected
list.find('li').removeClass('ui-timepicker-selected');
$(this).addClass('ui-timepicker-selected');
if (_selectValue(self)) {
self.trigger('hideTimepicker');
list.on('mouseup.timepicker', 'li', function (e) {
list.off('mouseup.timepicker');
wrapped_list.hide();
});
}
});
}
}
function _generateNoneElement(optionValue, useSelect) {
var label, className, value;
if (typeof optionValue == 'object') {
label = optionValue.label;
className = optionValue.className;
value = optionValue.value;
} else if (typeof optionValue == 'string') {
label = optionValue;
} else {
$.error('Invalid noneOption value');
}
if (useSelect) {
return $('
', {
'value': value,
'class': className,
'text': label
});
} else {
return $('
', {
'class': className,
'text': label
}).data('time', value);
}
}
function _roundAndFormatTime(seconds, settings) {
seconds = settings.roundingFunction(seconds, settings);
if (seconds !== null) {
return _int2time(seconds, settings);
}
}
function _generateBaseDate() {
return new Date(1970, 1, 1, 0, 0, 0);
}
// event handler to decide whether to close timepicker
function _closeHandler(e) {
var target = $(e.target);
var input = target.closest('.ui-timepicker-input');
if (input.length === 0 && target.closest('.ui-timepicker-wrapper').length === 0) {
methods.hide();
$(document).unbind('.ui-timepicker');
$(window).unbind('.ui-timepicker');
}
}
function _hideKeyboard(self) {
var settings = self.data('timepicker-settings');
return ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && settings.disableTouchKeyboard);
}
function _findRow(self, list, value) {
if (!value && value !== 0) {
return false;
}
var settings = self.data('timepicker-settings');
var out = false;
var value = settings.roundingFunction(value, settings);
// loop through the menu items
list.find('li').each(function (i, obj) {
var jObj = $(obj);
if (typeof jObj.data('time') != 'number') {
return;
}
if (jObj.data('time') == value) {
out = jObj;
return false;
}
});
return out;
}
function _setSelected(self, list) {
list.find('li').removeClass('ui-timepicker-selected');
var timeValue = _time2int(_getTimeValue(self), self.data('timepicker-settings'));
if (timeValue === null) {
return;
}
var selected = _findRow(self, list, timeValue);
if (selected) {
var topDelta = selected.offset().top - list.offset().top;
if (topDelta + selected.outerHeight() > list.outerHeight() || topDelta < 0) {
list.scrollTop(list.scrollTop() + selected.position().top - selected.outerHeight());
}
selected.addClass('ui-timepicker-selected');
}
}
function _formatValue(e, origin) {
if (this.value === '' || origin == 'timepicker') {
return;
}
var self = $(this);
if (self.is(':focus') && (!e || e.type != 'change')) {
return;
}
var settings = self.data('timepicker-settings');
var seconds = _time2int(this.value, settings);
if (seconds === null) {
self.trigger('timeFormatError');
return;
}
var rangeError = false;
// check that the time in within bounds
if (settings.minTime !== null && seconds < settings.minTime) {
rangeError = true;
} else if (settings.maxTime !== null && seconds > settings.maxTime) {
rangeError = true;
}
// check that time isn't within disabled time ranges
$.each(settings.disableTimeRanges, function () {
if (seconds >= this[0] && seconds < this[1]) {
rangeError = true;
return false;
}
});
if (settings.forceRoundTime) {
seconds = settings.roundingFunction(seconds, settings);
}
var prettyTime = _int2time(seconds, settings);
if (rangeError) {
if (_setTimeValue(self, prettyTime, 'error')) {
self.trigger('timeRangeError');
}
} else {
_setTimeValue(self, prettyTime);
}
}
function _getTimeValue(self) {
if (self.is('input')) {
return self.val();
} else {
// use the element's data attributes to store values
return self.data('ui-timepicker-value');
}
}
function _setTimeValue(self, value, source) {
if (self.is('input')) {
self.val(value);
var settings = self.data('timepicker-settings');
if (settings.useSelect && source != 'select' && source != 'initial') {
self.data('timepicker-list').val(_roundAndFormatTime(_time2int(value), settings));
}
}
if (self.data('ui-timepicker-value') != value) {
self.data('ui-timepicker-value', value);
if (source == 'select') {
self.trigger('selectTime').trigger('changeTime').trigger('change', 'timepicker');
} else if (source != 'error') {
self.trigger('changeTime');
}
return true;
} else {
self.trigger('selectTime');
return false;
}
}
/*
* Keyboard navigation via arrow keys
*/
function _keydownhandler(e) {
var self = $(this);
var list = self.data('timepicker-list');
if (!list || !_isVisible(list)) {
if (e.keyCode == 40) {
// show the list!
methods.show.call(self.get(0));
list = self.data('timepicker-list');
if (!_hideKeyboard(self)) {
self.focus();
}
} else {
return true;
}
}
switch (e.keyCode) {
case 13: // return
if (_selectValue(self)) {
methods.hide.apply(this);
}
e.preventDefault();
return false;
case 38: // up
var selected = list.find('.ui-timepicker-selected');
if (!selected.length) {
list.find('li').each(function (i, obj) {
if ($(obj).position().top > 0) {
selected = $(obj);
return false;
}
});
selected.addClass('ui-timepicker-selected');
} else if (!selected.is(':first-child')) {
selected.removeClass('ui-timepicker-selected');
selected.prev().addClass('ui-timepicker-selected');
if (selected.prev().position().top < selected.outerHeight()) {
list.scrollTop(list.scrollTop() - selected.outerHeight());
}
}
return false;
case 40: // down
selected = list.find('.ui-timepicker-selected');
if (selected.length === 0) {
list.find('li').each(function (i, obj) {
if ($(obj).position().top > 0) {
selected = $(obj);
return false;
}
});
selected.addClass('ui-timepicker-selected');
} else if (!selected.is(':last-child')) {
selected.removeClass('ui-timepicker-selected');
selected.next().addClass('ui-timepicker-selected');
if (selected.next().position().top + 2 * selected.outerHeight() > list.outerHeight()) {
list.scrollTop(list.scrollTop() + selected.outerHeight());
}
}
return false;
case 27: // escape
list.find('li').removeClass('ui-timepicker-selected');
methods.hide();
break;
case 9: //tab
methods.hide();
break;
default:
return true;
}
}
/*
* Time typeahead
*/
function _keyuphandler(e) {
var self = $(this);
var list = self.data('timepicker-list');
var settings = self.data('timepicker-settings');
if (!list || !_isVisible(list) || settings.disableTextInput) {
return true;
}
switch (e.keyCode) {
case 96: // numpad numerals
case 97:
case 98:
case 99:
case 100:
case 101:
case 102:
case 103:
case 104:
case 105:
case 48: // numerals
case 49:
case 50:
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57:
case 65: // a
case 77: // m
case 80: // p
case 186: // colon
case 8: // backspace
case 46: // delete
if (settings.typeaheadHighlight) {
_setSelected(self, list);
} else {
list.hide();
}
break;
}
}
function _selectValue(self) {
var settings = self.data('timepicker-settings');
var list = self.data('timepicker-list');
var timeValue = null;
var cursor = list.find('.ui-timepicker-selected');
if (cursor.hasClass('ui-timepicker-disabled')) {
return false;
}
if (cursor.length) {
// selected value found
timeValue = cursor.data('time');
}
if (timeValue !== null) {
if (typeof timeValue != 'string') {
timeValue = _int2time(timeValue, settings);
}
_setTimeValue(self, timeValue, 'select');
}
return true;
}
function _int2duration(seconds, step) {
seconds = Math.abs(seconds);
var minutes = Math.round(seconds / 60),
duration = [],
hours, mins;
if (minutes < 60) {
// Only show (x mins) under 1 hour
duration = [minutes, _lang.mins];
} else {
hours = Math.floor(minutes / 60);
mins = minutes % 60;
// Show decimal notation (eg: 1.5 hrs) for 30 minute steps
if (step == 30 && mins == 30) {
hours += _lang.decimal + 5;
}
duration.push(hours);
duration.push(hours == 1 ? _lang.hr : _lang.hrs);
// Show remainder minutes notation (eg: 1 hr 15 mins) for non-30 minute steps
// and only if there are remainder minutes to show
if (step != 30 && mins) {
duration.push(mins);
duration.push(_lang.mins);
}
}
return duration.join(' ');
}
function _int2time(seconds, settings) {
if (seconds === null) {
return null;
}
var time = new Date(_baseDate.valueOf() + (seconds * 1000));
if (isNaN(time.getTime())) {
return null;
}
if ($.type(settings.timeFormat) === "function") {
return settings.timeFormat(time);
}
var output = '';
var hour, code;
for (var i = 0; i < settings.timeFormat.length; i++) {
code = settings.timeFormat.charAt(i);
switch (code) {
case 'a':
output += (time.getHours() > 11) ? _lang.pm : _lang.am;
break;
case 'A':
output += (time.getHours() > 11) ? _lang.PM : _lang.AM;
break;
case 'g':
hour = time.getHours() % 12;
output += (hour === 0) ? '12' : hour;
break;
case 'G':
hour = time.getHours();
if (seconds === _ONE_DAY) hour = 24;
output += hour;
break;
case 'h':
hour = time.getHours() % 12;
if (hour !== 0 && hour < 10) {
hour = '0' + hour;
}
output += (hour === 0) ? '12' : hour;
break;
case 'H':
hour = time.getHours();
if (seconds === _ONE_DAY) hour = 24;
output += (hour > 9) ? hour : '0' + hour;
break;
case 'i':
var minutes = time.getMinutes();
output += (minutes > 9) ? minutes : '0' + minutes;
break;
case 's':
seconds = time.getSeconds();
output += (seconds > 9) ? seconds : '0' + seconds;
break;
case '\\':
// escape character; add the next character and skip ahead
i++;
output += settings.timeFormat.charAt(i);
break;
default:
output += code;
}
}
return output;
}
function _time2int(timeString, settings) {
if (timeString === '') return null;
if (!timeString || timeString + 0 == timeString) return timeString;
if (typeof (timeString) == 'object') {
return timeString.getHours() * 3600 + timeString.getMinutes() * 60 + timeString.getSeconds();
}
timeString = timeString.toLowerCase().replace(/[\s\.]/g, '');
// if the last character is an "a" or "p", add the "m"
if (timeString.slice(-1) == 'a' || timeString.slice(-1) == 'p') {
timeString += 'm';
}
var ampmRegex = '(' +
_lang.am.replace('.', '') + '|' +
_lang.pm.replace('.', '') + '|' +
_lang.AM.replace('.', '') + '|' +
_lang.PM.replace('.', '') + ')?';
// try to parse time input
var pattern = new RegExp('^' + ampmRegex + '([0-2]?[0-9])\\W?([0-5][0-9])?\\W?([0-5][0-9])?' + ampmRegex + '$');
var time = timeString.match(pattern);
if (!time) {
return null;
}
var hour = parseInt(time[2] * 1, 10);
var ampm = time[1] || time[5];
var hours = hour;
if (hour <= 12 && ampm) {
var isPm = (ampm == _lang.pm || ampm == _lang.PM);
if (hour == 12) {
hours = isPm ? 12 : 0;
} else {
hours = (hour + (isPm ? 12 : 0));
}
}
var minutes = (time[3] * 1 || 0);
var seconds = (time[4] * 1 || 0);
var timeInt = hours * 3600 + minutes * 60 + seconds;
// if no am/pm provided, intelligently guess based on the scrollDefault
if (!ampm && settings && settings._twelveHourTime && settings.scrollDefault) {
var delta = timeInt - settings.scrollDefault();
if (delta < 0 && delta >= _ONE_DAY / -2) {
timeInt = (timeInt + (_ONE_DAY / 2)) % _ONE_DAY;
}
}
return timeInt;
}
function _pad2(n) {
return ("0" + n).slice(-2);
}
// Plugin entry
$.fn.timepicker = function (method) {
if (!this.length) return this;
if (methods[method]) {
// check if this element is a timepicker
if (!this.hasClass('ui-timepicker-input')) {
return this;
}
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if (typeof method === "object" || !method) { return methods.init.apply(this, arguments); }
else { $.error("Method " + method + " does not exist on jQuery.timepicker"); }
};
// Global defaults
$.fn.timepicker.defaults = {
className: null,
minTime: null,
maxTime: null,
durationTime: null,
step: 30,
showDuration: false,
showOnFocus: true,
showOn: ['click', 'focus'],
timeFormat: 'g:ia',
scrollDefault: null,
selectOnBlur: false,
disableTextInput: false,
disableTouchKeyboard: false,
forceRoundTime: false,
roundingFunction: function (seconds, settings) {
if (seconds === null) {
return null;
} else {
var offset = seconds % (settings.step * 60); // step is in minutes
if (offset >= settings.step * 30) {
// if offset is larger than a half step, round up
seconds += (settings.step * 60) - offset;
} else {
// round down
seconds -= offset;
}
return seconds;
}
},
appendTo: 'body',
orientation: 'l',
disableTimeRanges: [],
closeOnWindowScroll: false,
typeaheadHighlight: true,
noneOption: false,
show2400: false,
stopScrollPropagation: false
};
}));
//! moment.js
//! version : 2.10.6
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com
!function (a, b) { "object" == typeof exports && "undefined" != typeof module ? module.exports = b() : "function" == typeof define && define.amd ? define(b) : a.moment = b() }(this, function () {
"use strict"; function a() { return Hc.apply(null, arguments) } function b(a) { Hc = a } function c(a) { return "[object Array]" === Object.prototype.toString.call(a) } function d(a) { return a instanceof Date || "[object Date]" === Object.prototype.toString.call(a) } function e(a, b) { var c, d = []; for (c = 0; c < a.length; ++c) d.push(b(a[c], c)); return d } function f(a, b) { return Object.prototype.hasOwnProperty.call(a, b) } function g(a, b) { for (var c in b) f(b, c) && (a[c] = b[c]); return f(b, "toString") && (a.toString = b.toString), f(b, "valueOf") && (a.valueOf = b.valueOf), a } function h(a, b, c, d) { return Ca(a, b, c, d, !0).utc() } function i() { return { empty: !1, unusedTokens: [], unusedInput: [], overflow: -2, charsLeftOver: 0, nullInput: !1, invalidMonth: null, invalidFormat: !1, userInvalidated: !1, iso: !1 } } function j(a) { return null == a._pf && (a._pf = i()), a._pf } function k(a) { if (null == a._isValid) { var b = j(a); a._isValid = !(isNaN(a._d.getTime()) || !(b.overflow < 0) || b.empty || b.invalidMonth || b.invalidWeekday || b.nullInput || b.invalidFormat || b.userInvalidated), a._strict && (a._isValid = a._isValid && 0 === b.charsLeftOver && 0 === b.unusedTokens.length && void 0 === b.bigHour) } return a._isValid } function l(a) { var b = h(NaN); return null != a ? g(j(b), a) : j(b).userInvalidated = !0, b } function m(a, b) { var c, d, e; if ("undefined" != typeof b._isAMomentObject && (a._isAMomentObject = b._isAMomentObject), "undefined" != typeof b._i && (a._i = b._i), "undefined" != typeof b._f && (a._f = b._f), "undefined" != typeof b._l && (a._l = b._l), "undefined" != typeof b._strict && (a._strict = b._strict), "undefined" != typeof b._tzm && (a._tzm = b._tzm), "undefined" != typeof b._isUTC && (a._isUTC = b._isUTC), "undefined" != typeof b._offset && (a._offset = b._offset), "undefined" != typeof b._pf && (a._pf = j(b)), "undefined" != typeof b._locale && (a._locale = b._locale), Jc.length > 0) for (c in Jc) d = Jc[c], e = b[d], "undefined" != typeof e && (a[d] = e); return a } function n(b) { m(this, b), this._d = new Date(null != b._d ? b._d.getTime() : NaN), Kc === !1 && (Kc = !0, a.updateOffset(this), Kc = !1) } function o(a) { return a instanceof n || null != a && null != a._isAMomentObject } function p(a) { return 0 > a ? Math.ceil(a) : Math.floor(a) } function q(a) { var b = +a, c = 0; return 0 !== b && isFinite(b) && (c = p(b)), c } function r(a, b, c) { var d, e = Math.min(a.length, b.length), f = Math.abs(a.length - b.length), g = 0; for (d = 0; e > d; d++) (c && a[d] !== b[d] || !c && q(a[d]) !== q(b[d])) && g++; return g + f } function s() { } function t(a) { return a ? a.toLowerCase().replace("_", "-") : a } function u(a) { for (var b, c, d, e, f = 0; f < a.length;) { for (e = t(a[f]).split("-"), b = e.length, c = t(a[f + 1]), c = c ? c.split("-") : null; b > 0;) { if (d = v(e.slice(0, b).join("-"))) return d; if (c && c.length >= b && r(e, c, !0) >= b - 1) break; b-- } f++ } return null } function v(a) { var b = null; if (!Lc[a] && "undefined" != typeof module && module && module.exports) try { b = Ic._abbr, require("./locale/" + a), w(b) } catch (c) { } return Lc[a] } function w(a, b) { var c; return a && (c = "undefined" == typeof b ? y(a) : x(a, b), c && (Ic = c)), Ic._abbr } function x(a, b) { return null !== b ? (b.abbr = a, Lc[a] = Lc[a] || new s, Lc[a].set(b), w(a), Lc[a]) : (delete Lc[a], null) } function y(a) { var b; if (a && a._locale && a._locale._abbr && (a = a._locale._abbr), !a) return Ic; if (!c(a)) { if (b = v(a)) return b; a = [a] } return u(a) } function z(a, b) { var c = a.toLowerCase(); Mc[c] = Mc[c + "s"] = Mc[b] = a } function A(a) { return "string" == typeof a ? Mc[a] || Mc[a.toLowerCase()] : void 0 } function B(a) { var b, c, d = {}; for (c in a) f(a, c) && (b = A(c), b && (d[b] = a[c])); return d } function C(b, c) { return function (d) { return null != d ? (E(this, b, d), a.updateOffset(this, c), this) : D(this, b) } } function D(a, b) { return a._d["get" + (a._isUTC ? "UTC" : "") + b]() } function E(a, b, c) { return a._d["set" + (a._isUTC ? "UTC" : "") + b](c) } function F(a, b) { var c; if ("object" == typeof a) for (c in a) this.set(c, a[c]); else if (a = A(a), "function" == typeof this[a]) return this[a](b); return this } function G(a, b, c) { var d = "" + Math.abs(a), e = b - d.length, f = a >= 0; return (f ? c ? "+" : "" : "-") + Math.pow(10, Math.max(0, e)).toString().substr(1) + d } function H(a, b, c, d) { var e = d; "string" == typeof d && (e = function () { return this[d]() }), a && (Qc[a] = e), b && (Qc[b[0]] = function () { return G(e.apply(this, arguments), b[1], b[2]) }), c && (Qc[c] = function () { return this.localeData().ordinal(e.apply(this, arguments), a) }) } function I(a) { return a.match(/\[[\s\S]/) ? a.replace(/^\[|\]$/g, "") : a.replace(/\\/g, "") } function J(a) { var b, c, d = a.match(Nc); for (b = 0, c = d.length; c > b; b++) Qc[d[b]] ? d[b] = Qc[d[b]] : d[b] = I(d[b]); return function (e) { var f = ""; for (b = 0; c > b; b++) f += d[b] instanceof Function ? d[b].call(e, a) : d[b]; return f } } function K(a, b) { return a.isValid() ? (b = L(b, a.localeData()), Pc[b] = Pc[b] || J(b), Pc[b](a)) : a.localeData().invalidDate() } function L(a, b) { function c(a) { return b.longDateFormat(a) || a } var d = 5; for (Oc.lastIndex = 0; d >= 0 && Oc.test(a) ;) a = a.replace(Oc, c), Oc.lastIndex = 0, d -= 1; return a } function M(a) { return "function" == typeof a && "[object Function]" === Object.prototype.toString.call(a) } function N(a, b, c) { dd[a] = M(b) ? b : function (a) { return a && c ? c : b } } function O(a, b) { return f(dd, a) ? dd[a](b._strict, b._locale) : new RegExp(P(a)) } function P(a) { return a.replace("\\", "").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (a, b, c, d, e) { return b || c || d || e }).replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&") } function Q(a, b) { var c, d = b; for ("string" == typeof a && (a = [a]), "number" == typeof b && (d = function (a, c) { c[b] = q(a) }), c = 0; c < a.length; c++) ed[a[c]] = d } function R(a, b) { Q(a, function (a, c, d, e) { d._w = d._w || {}, b(a, d._w, d, e) }) } function S(a, b, c) { null != b && f(ed, a) && ed[a](b, c._a, c, a) } function T(a, b) { return new Date(Date.UTC(a, b + 1, 0)).getUTCDate() } function U(a) { return this._months[a.month()] } function V(a) { return this._monthsShort[a.month()] } function W(a, b, c) { var d, e, f; for (this._monthsParse || (this._monthsParse = [], this._longMonthsParse = [], this._shortMonthsParse = []), d = 0; 12 > d; d++) { if (e = h([2e3, d]), c && !this._longMonthsParse[d] && (this._longMonthsParse[d] = new RegExp("^" + this.months(e, "").replace(".", "") + "$", "i"), this._shortMonthsParse[d] = new RegExp("^" + this.monthsShort(e, "").replace(".", "") + "$", "i")), c || this._monthsParse[d] || (f = "^" + this.months(e, "") + "|^" + this.monthsShort(e, ""), this._monthsParse[d] = new RegExp(f.replace(".", ""), "i")), c && "MMMM" === b && this._longMonthsParse[d].test(a)) return d; if (c && "MMM" === b && this._shortMonthsParse[d].test(a)) return d; if (!c && this._monthsParse[d].test(a)) return d } } function X(a, b) { var c; return "string" == typeof b && (b = a.localeData().monthsParse(b), "number" != typeof b) ? a : (c = Math.min(a.date(), T(a.year(), b)), a._d["set" + (a._isUTC ? "UTC" : "") + "Month"](b, c), a) } function Y(b) { return null != b ? (X(this, b), a.updateOffset(this, !0), this) : D(this, "Month") } function Z() { return T(this.year(), this.month()) } function $(a) { var b, c = a._a; return c && -2 === j(a).overflow && (b = c[gd] < 0 || c[gd] > 11 ? gd : c[hd] < 1 || c[hd] > T(c[fd], c[gd]) ? hd : c[id] < 0 || c[id] > 24 || 24 === c[id] && (0 !== c[jd] || 0 !== c[kd] || 0 !== c[ld]) ? id : c[jd] < 0 || c[jd] > 59 ? jd : c[kd] < 0 || c[kd] > 59 ? kd : c[ld] < 0 || c[ld] > 999 ? ld : -1, j(a)._overflowDayOfYear && (fd > b || b > hd) && (b = hd), j(a).overflow = b), a } function _(b) { a.suppressDeprecationWarnings === !1 && "undefined" != typeof console && console.warn && console.warn("Deprecation warning: " + b) } function aa(a, b) { var c = !0; return g(function () { return c && (_(a + "\n" + (new Error).stack), c = !1), b.apply(this, arguments) }, b) } function ba(a, b) { od[a] || (_(b), od[a] = !0) } function ca(a) { var b, c, d = a._i, e = pd.exec(d); if (e) { for (j(a).iso = !0, b = 0, c = qd.length; c > b; b++) if (qd[b][1].exec(d)) { a._f = qd[b][0]; break } for (b = 0, c = rd.length; c > b; b++) if (rd[b][1].exec(d)) { a._f += (e[6] || " ") + rd[b][0]; break } d.match(ad) && (a._f += "Z"), va(a) } else a._isValid = !1 } function da(b) { var c = sd.exec(b._i); return null !== c ? void (b._d = new Date(+c[1])) : (ca(b), void (b._isValid === !1 && (delete b._isValid, a.createFromInputFallback(b)))) } function ea(a, b, c, d, e, f, g) { var h = new Date(a, b, c, d, e, f, g); return 1970 > a && h.setFullYear(a), h } function fa(a) { var b = new Date(Date.UTC.apply(null, arguments)); return 1970 > a && b.setUTCFullYear(a), b } function ga(a) { return ha(a) ? 366 : 365 } function ha(a) { return a % 4 === 0 && a % 100 !== 0 || a % 400 === 0 } function ia() { return ha(this.year()) } function ja(a, b, c) { var d, e = c - b, f = c - a.day(); return f > e && (f -= 7), e - 7 > f && (f += 7), d = Da(a).add(f, "d"), { week: Math.ceil(d.dayOfYear() / 7), year: d.year() } } function ka(a) { return ja(a, this._week.dow, this._week.doy).week } function la() { return this._week.dow } function ma() { return this._week.doy } function na(a) { var b = this.localeData().week(this); return null == a ? b : this.add(7 * (a - b), "d") } function oa(a) { var b = ja(this, 1, 4).week; return null == a ? b : this.add(7 * (a - b), "d") } function pa(a, b, c, d, e) { var f, g = 6 + e - d, h = fa(a, 0, 1 + g), i = h.getUTCDay(); return e > i && (i += 7), c = null != c ? 1 * c : e, f = 1 + g + 7 * (b - 1) - i + c, { year: f > 0 ? a : a - 1, dayOfYear: f > 0 ? f : ga(a - 1) + f } } function qa(a) { var b = Math.round((this.clone().startOf("day") - this.clone().startOf("year")) / 864e5) + 1; return null == a ? b : this.add(a - b, "d") } function ra(a, b, c) { return null != a ? a : null != b ? b : c } function sa(a) { var b = new Date; return a._useUTC ? [b.getUTCFullYear(), b.getUTCMonth(), b.getUTCDate()] : [b.getFullYear(), b.getMonth(), b.getDate()] } function ta(a) { var b, c, d, e, f = []; if (!a._d) { for (d = sa(a), a._w && null == a._a[hd] && null == a._a[gd] && ua(a), a._dayOfYear && (e = ra(a._a[fd], d[fd]), a._dayOfYear > ga(e) && (j(a)._overflowDayOfYear = !0), c = fa(e, 0, a._dayOfYear), a._a[gd] = c.getUTCMonth(), a._a[hd] = c.getUTCDate()), b = 0; 3 > b && null == a._a[b]; ++b) a._a[b] = f[b] = d[b]; for (; 7 > b; b++) a._a[b] = f[b] = null == a._a[b] ? 2 === b ? 1 : 0 : a._a[b]; 24 === a._a[id] && 0 === a._a[jd] && 0 === a._a[kd] && 0 === a._a[ld] && (a._nextDay = !0, a._a[id] = 0), a._d = (a._useUTC ? fa : ea).apply(null, f), null != a._tzm && a._d.setUTCMinutes(a._d.getUTCMinutes() - a._tzm), a._nextDay && (a._a[id] = 24) } } function ua(a) { var b, c, d, e, f, g, h; b = a._w, null != b.GG || null != b.W || null != b.E ? (f = 1, g = 4, c = ra(b.GG, a._a[fd], ja(Da(), 1, 4).year), d = ra(b.W, 1), e = ra(b.E, 1)) : (f = a._locale._week.dow, g = a._locale._week.doy, c = ra(b.gg, a._a[fd], ja(Da(), f, g).year), d = ra(b.w, 1), null != b.d ? (e = b.d, f > e && ++d) : e = null != b.e ? b.e + f : f), h = pa(c, d, e, g, f), a._a[fd] = h.year, a._dayOfYear = h.dayOfYear } function va(b) { if (b._f === a.ISO_8601) return void ca(b); b._a = [], j(b).empty = !0; var c, d, e, f, g, h = "" + b._i, i = h.length, k = 0; for (e = L(b._f, b._locale).match(Nc) || [], c = 0; c < e.length; c++) f = e[c], d = (h.match(O(f, b)) || [])[0], d && (g = h.substr(0, h.indexOf(d)), g.length > 0 && j(b).unusedInput.push(g), h = h.slice(h.indexOf(d) + d.length), k += d.length), Qc[f] ? (d ? j(b).empty = !1 : j(b).unusedTokens.push(f), S(f, d, b)) : b._strict && !d && j(b).unusedTokens.push(f); j(b).charsLeftOver = i - k, h.length > 0 && j(b).unusedInput.push(h), j(b).bigHour === !0 && b._a[id] <= 12 && b._a[id] > 0 && (j(b).bigHour = void 0), b._a[id] = wa(b._locale, b._a[id], b._meridiem), ta(b), $(b) } function wa(a, b, c) { var d; return null == c ? b : null != a.meridiemHour ? a.meridiemHour(b, c) : null != a.isPM ? (d = a.isPM(c), d && 12 > b && (b += 12), d || 12 !== b || (b = 0), b) : b } function xa(a) { var b, c, d, e, f; if (0 === a._f.length) return j(a).invalidFormat = !0, void (a._d = new Date(NaN)); for (e = 0; e < a._f.length; e++) f = 0, b = m({}, a), null != a._useUTC && (b._useUTC = a._useUTC), b._f = a._f[e], va(b), k(b) && (f += j(b).charsLeftOver, f += 10 * j(b).unusedTokens.length, j(b).score = f, (null == d || d > f) && (d = f, c = b)); g(a, c || b) } function ya(a) { if (!a._d) { var b = B(a._i); a._a = [b.year, b.month, b.day || b.date, b.hour, b.minute, b.second, b.millisecond], ta(a) } } function za(a) { var b = new n($(Aa(a))); return b._nextDay && (b.add(1, "d"), b._nextDay = void 0), b } function Aa(a) { var b = a._i, e = a._f; return a._locale = a._locale || y(a._l), null === b || void 0 === e && "" === b ? l({ nullInput: !0 }) : ("string" == typeof b && (a._i = b = a._locale.preparse(b)), o(b) ? new n($(b)) : (c(e) ? xa(a) : e ? va(a) : d(b) ? a._d = b : Ba(a), a)) } function Ba(b) { var f = b._i; void 0 === f ? b._d = new Date : d(f) ? b._d = new Date(+f) : "string" == typeof f ? da(b) : c(f) ? (b._a = e(f.slice(0), function (a) { return parseInt(a, 10) }), ta(b)) : "object" == typeof f ? ya(b) : "number" == typeof f ? b._d = new Date(f) : a.createFromInputFallback(b) } function Ca(a, b, c, d, e) { var f = {}; return "boolean" == typeof c && (d = c, c = void 0), f._isAMomentObject = !0, f._useUTC = f._isUTC = e, f._l = c, f._i = a, f._f = b, f._strict = d, za(f) } function Da(a, b, c, d) { return Ca(a, b, c, d, !1) } function Ea(a, b) { var d, e; if (1 === b.length && c(b[0]) && (b = b[0]), !b.length) return Da(); for (d = b[0], e = 1; e < b.length; ++e) (!b[e].isValid() || b[e][a](d)) && (d = b[e]); return d } function Fa() { var a = [].slice.call(arguments, 0); return Ea("isBefore", a) } function Ga() { var a = [].slice.call(arguments, 0); return Ea("isAfter", a) } function Ha(a) { var b = B(a), c = b.year || 0, d = b.quarter || 0, e = b.month || 0, f = b.week || 0, g = b.day || 0, h = b.hour || 0, i = b.minute || 0, j = b.second || 0, k = b.millisecond || 0; this._milliseconds = +k + 1e3 * j + 6e4 * i + 36e5 * h, this._days = +g + 7 * f, this._months = +e + 3 * d + 12 * c, this._data = {}, this._locale = y(), this._bubble() } function Ia(a) { return a instanceof Ha } function Ja(a, b) { H(a, 0, 0, function () { var a = this.utcOffset(), c = "+"; return 0 > a && (a = -a, c = "-"), c + G(~~(a / 60), 2) + b + G(~~a % 60, 2) }) } function Ka(a) { var b = (a || "").match(ad) || [], c = b[b.length - 1] || [], d = (c + "").match(xd) || ["-", 0, 0], e = +(60 * d[1]) + q(d[2]); return "+" === d[0] ? e : -e } function La(b, c) { var e, f; return c._isUTC ? (e = c.clone(), f = (o(b) || d(b) ? +b : +Da(b)) - +e, e._d.setTime(+e._d + f), a.updateOffset(e, !1), e) : Da(b).local() } function Ma(a) { return 15 * -Math.round(a._d.getTimezoneOffset() / 15) } function Na(b, c) { var d, e = this._offset || 0; return null != b ? ("string" == typeof b && (b = Ka(b)), Math.abs(b) < 16 && (b = 60 * b), !this._isUTC && c && (d = Ma(this)), this._offset = b, this._isUTC = !0, null != d && this.add(d, "m"), e !== b && (!c || this._changeInProgress ? bb(this, Ya(b - e, "m"), 1, !1) : this._changeInProgress || (this._changeInProgress = !0, a.updateOffset(this, !0), this._changeInProgress = null)), this) : this._isUTC ? e : Ma(this) } function Oa(a, b) { return null != a ? ("string" != typeof a && (a = -a), this.utcOffset(a, b), this) : -this.utcOffset() } function Pa(a) { return this.utcOffset(0, a) } function Qa(a) { return this._isUTC && (this.utcOffset(0, a), this._isUTC = !1, a && this.subtract(Ma(this), "m")), this } function Ra() { return this._tzm ? this.utcOffset(this._tzm) : "string" == typeof this._i && this.utcOffset(Ka(this._i)), this } function Sa(a) { return a = a ? Da(a).utcOffset() : 0, (this.utcOffset() - a) % 60 === 0 } function Ta() { return this.utcOffset() > this.clone().month(0).utcOffset() || this.utcOffset() > this.clone().month(5).utcOffset() } function Ua() { if ("undefined" != typeof this._isDSTShifted) return this._isDSTShifted; var a = {}; if (m(a, this), a = Aa(a), a._a) { var b = a._isUTC ? h(a._a) : Da(a._a); this._isDSTShifted = this.isValid() && r(a._a, b.toArray()) > 0 } else this._isDSTShifted = !1; return this._isDSTShifted } function Va() { return !this._isUTC } function Wa() { return this._isUTC } function Xa() { return this._isUTC && 0 === this._offset } function Ya(a, b) { var c, d, e, g = a, h = null; return Ia(a) ? g = { ms: a._milliseconds, d: a._days, M: a._months } : "number" == typeof a ? (g = {}, b ? g[b] = a : g.milliseconds = a) : (h = yd.exec(a)) ? (c = "-" === h[1] ? -1 : 1, g = { y: 0, d: q(h[hd]) * c, h: q(h[id]) * c, m: q(h[jd]) * c, s: q(h[kd]) * c, ms: q(h[ld]) * c }) : (h = zd.exec(a)) ? (c = "-" === h[1] ? -1 : 1, g = { y: Za(h[2], c), M: Za(h[3], c), d: Za(h[4], c), h: Za(h[5], c), m: Za(h[6], c), s: Za(h[7], c), w: Za(h[8], c) }) : null == g ? g = {} : "object" == typeof g && ("from" in g || "to" in g) && (e = _a(Da(g.from), Da(g.to)), g = {}, g.ms = e.milliseconds, g.M = e.months), d = new Ha(g), Ia(a) && f(a, "_locale") && (d._locale = a._locale), d } function Za(a, b) { var c = a && parseFloat(a.replace(",", ".")); return (isNaN(c) ? 0 : c) * b } function $a(a, b) { var c = { milliseconds: 0, months: 0 }; return c.months = b.month() - a.month() + 12 * (b.year() - a.year()), a.clone().add(c.months, "M").isAfter(b) && --c.months, c.milliseconds = +b - +a.clone().add(c.months, "M"), c } function _a(a, b) { var c; return b = La(b, a), a.isBefore(b) ? c = $a(a, b) : (c = $a(b, a), c.milliseconds = -c.milliseconds, c.months = -c.months), c } function ab(a, b) { return function (c, d) { var e, f; return null === d || isNaN(+d) || (ba(b, "moment()." + b + "(period, number) is deprecated. Please use moment()." + b + "(number, period)."), f = c, c = d, d = f), c = "string" == typeof c ? +c : c, e = Ya(c, d), bb(this, e, a), this } } function bb(b, c, d, e) { var f = c._milliseconds, g = c._days, h = c._months; e = null == e ? !0 : e, f && b._d.setTime(+b._d + f * d), g && E(b, "Date", D(b, "Date") + g * d), h && X(b, D(b, "Month") + h * d), e && a.updateOffset(b, g || h) } function cb(a, b) { var c = a || Da(), d = La(c, this).startOf("day"), e = this.diff(d, "days", !0), f = -6 > e ? "sameElse" : -1 > e ? "lastWeek" : 0 > e ? "lastDay" : 1 > e ? "sameDay" : 2 > e ? "nextDay" : 7 > e ? "nextWeek" : "sameElse"; return this.format(b && b[f] || this.localeData().calendar(f, this, Da(c))) } function db() { return new n(this) } function eb(a, b) { var c; return b = A("undefined" != typeof b ? b : "millisecond"), "millisecond" === b ? (a = o(a) ? a : Da(a), +this > +a) : (c = o(a) ? +a : +Da(a), c < +this.clone().startOf(b)) } function fb(a, b) { var c; return b = A("undefined" != typeof b ? b : "millisecond"), "millisecond" === b ? (a = o(a) ? a : Da(a), +a > +this) : (c = o(a) ? +a : +Da(a), +this.clone().endOf(b) < c) } function gb(a, b, c) { return this.isAfter(a, c) && this.isBefore(b, c) } function hb(a, b) { var c; return b = A(b || "millisecond"), "millisecond" === b ? (a = o(a) ? a : Da(a), +this === +a) : (c = +Da(a), +this.clone().startOf(b) <= c && c <= +this.clone().endOf(b)) } function ib(a, b, c) { var d, e, f = La(a, this), g = 6e4 * (f.utcOffset() - this.utcOffset()); return b = A(b), "year" === b || "month" === b || "quarter" === b ? (e = jb(this, f), "quarter" === b ? e /= 3 : "year" === b && (e /= 12)) : (d = this - f, e = "second" === b ? d / 1e3 : "minute" === b ? d / 6e4 : "hour" === b ? d / 36e5 : "day" === b ? (d - g) / 864e5 : "week" === b ? (d - g) / 6048e5 : d), c ? e : p(e) } function jb(a, b) { var c, d, e = 12 * (b.year() - a.year()) + (b.month() - a.month()), f = a.clone().add(e, "months"); return 0 > b - f ? (c = a.clone().add(e - 1, "months"), d = (b - f) / (f - c)) : (c = a.clone().add(e + 1, "months"), d = (b - f) / (c - f)), -(e + d) } function kb() { return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ") } function lb() { var a = this.clone().utc(); return 0 < a.year() && a.year() <= 9999 ? "function" == typeof Date.prototype.toISOString ? this.toDate().toISOString() : K(a, "YYYY-MM-DD[T]HH:mm:ss.SSS[Z]") : K(a, "YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]") } function mb(b) { var c = K(this, b || a.defaultFormat); return this.localeData().postformat(c) } function nb(a, b) { return this.isValid() ? Ya({ to: this, from: a }).locale(this.locale()).humanize(!b) : this.localeData().invalidDate() } function ob(a) { return this.from(Da(), a) } function pb(a, b) { return this.isValid() ? Ya({ from: this, to: a }).locale(this.locale()).humanize(!b) : this.localeData().invalidDate() } function qb(a) { return this.to(Da(), a) } function rb(a) { var b; return void 0 === a ? this._locale._abbr : (b = y(a), null != b && (this._locale = b), this) } function sb() { return this._locale } function tb(a) { switch (a = A(a)) { case "year": this.month(0); case "quarter": case "month": this.date(1); case "week": case "isoWeek": case "day": this.hours(0); case "hour": this.minutes(0); case "minute": this.seconds(0); case "second": this.milliseconds(0) } return "week" === a && this.weekday(0), "isoWeek" === a && this.isoWeekday(1), "quarter" === a && this.month(3 * Math.floor(this.month() / 3)), this } function ub(a) { return a = A(a), void 0 === a || "millisecond" === a ? this : this.startOf(a).add(1, "isoWeek" === a ? "week" : a).subtract(1, "ms") } function vb() { return +this._d - 6e4 * (this._offset || 0) } function wb() { return Math.floor(+this / 1e3) } function xb() { return this._offset ? new Date(+this) : this._d } function yb() { var a = this; return [a.year(), a.month(), a.date(), a.hour(), a.minute(), a.second(), a.millisecond()] } function zb() { var a = this; return { years: a.year(), months: a.month(), date: a.date(), hours: a.hours(), minutes: a.minutes(), seconds: a.seconds(), milliseconds: a.milliseconds() } } function Ab() { return k(this) } function Bb() { return g({}, j(this)) } function Cb() { return j(this).overflow } function Db(a, b) { H(0, [a, a.length], 0, b) } function Eb(a, b, c) { return ja(Da([a, 11, 31 + b - c]), b, c).week } function Fb(a) { var b = ja(this, this.localeData()._week.dow, this.localeData()._week.doy).year; return null == a ? b : this.add(a - b, "y") } function Gb(a) { var b = ja(this, 1, 4).year; return null == a ? b : this.add(a - b, "y") } function Hb() { return Eb(this.year(), 1, 4) } function Ib() { var a = this.localeData()._week; return Eb(this.year(), a.dow, a.doy) } function Jb(a) { return null == a ? Math.ceil((this.month() + 1) / 3) : this.month(3 * (a - 1) + this.month() % 3) } function Kb(a, b) { return "string" != typeof a ? a : isNaN(a) ? (a = b.weekdaysParse(a), "number" == typeof a ? a : null) : parseInt(a, 10) } function Lb(a) { return this._weekdays[a.day()] } function Mb(a) { return this._weekdaysShort[a.day()] } function Nb(a) { return this._weekdaysMin[a.day()] } function Ob(a) { var b, c, d; for (this._weekdaysParse = this._weekdaysParse || [], b = 0; 7 > b; b++) if (this._weekdaysParse[b] || (c = Da([2e3, 1]).day(b), d = "^" + this.weekdays(c, "") + "|^" + this.weekdaysShort(c, "") + "|^" + this.weekdaysMin(c, ""), this._weekdaysParse[b] = new RegExp(d.replace(".", ""), "i")), this._weekdaysParse[b].test(a)) return b } function Pb(a) { var b = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); return null != a ? (a = Kb(a, this.localeData()), this.add(a - b, "d")) : b } function Qb(a) { var b = (this.day() + 7 - this.localeData()._week.dow) % 7; return null == a ? b : this.add(a - b, "d") } function Rb(a) { return null == a ? this.day() || 7 : this.day(this.day() % 7 ? a : a - 7) } function Sb(a, b) { H(a, 0, 0, function () { return this.localeData().meridiem(this.hours(), this.minutes(), b) }) } function Tb(a, b) { return b._meridiemParse } function Ub(a) { return "p" === (a + "").toLowerCase().charAt(0) } function Vb(a, b, c) { return a > 11 ? c ? "pm" : "PM" : c ? "am" : "AM" } function Wb(a, b) { b[ld] = q(1e3 * ("0." + a)) } function Xb() { return this._isUTC ? "UTC" : "" } function Yb() { return this._isUTC ? "Coordinated Universal Time" : "" } function Zb(a) { return Da(1e3 * a) } function $b() { return Da.apply(null, arguments).parseZone() } function _b(a, b, c) { var d = this._calendar[a]; return "function" == typeof d ? d.call(b, c) : d } function ac(a) { var b = this._longDateFormat[a], c = this._longDateFormat[a.toUpperCase()]; return b || !c ? b : (this._longDateFormat[a] = c.replace(/MMMM|MM|DD|dddd/g, function (a) { return a.slice(1) }), this._longDateFormat[a]) } function bc() { return this._invalidDate } function cc(a) { return this._ordinal.replace("%d", a) } function dc(a) { return a } function ec(a, b, c, d) { var e = this._relativeTime[c]; return "function" == typeof e ? e(a, b, c, d) : e.replace(/%d/i, a) } function fc(a, b) { var c = this._relativeTime[a > 0 ? "future" : "past"]; return "function" == typeof c ? c(b) : c.replace(/%s/i, b) } function gc(a) { var b, c; for (c in a) b = a[c], "function" == typeof b ? this[c] = b : this["_" + c] = b; this._ordinalParseLenient = new RegExp(this._ordinalParse.source + "|" + /\d{1,2}/.source) } function hc(a, b, c, d) { var e = y(), f = h().set(d, b); return e[c](f, a) } function ic(a, b, c, d, e) { if ("number" == typeof a && (b = a, a = void 0), a = a || "", null != b) return hc(a, b, c, e); var f, g = []; for (f = 0; d > f; f++) g[f] = hc(a, f, c, e); return g } function jc(a, b) { return ic(a, b, "months", 12, "month") } function kc(a, b) { return ic(a, b, "monthsShort", 12, "month") } function lc(a, b) { return ic(a, b, "weekdays", 7, "day") } function mc(a, b) { return ic(a, b, "weekdaysShort", 7, "day") } function nc(a, b) { return ic(a, b, "weekdaysMin", 7, "day") } function oc() { var a = this._data; return this._milliseconds = Wd(this._milliseconds), this._days = Wd(this._days), this._months = Wd(this._months), a.milliseconds = Wd(a.milliseconds), a.seconds = Wd(a.seconds), a.minutes = Wd(a.minutes), a.hours = Wd(a.hours), a.months = Wd(a.months), a.years = Wd(a.years), this } function pc(a, b, c, d) { var e = Ya(b, c); return a._milliseconds += d * e._milliseconds, a._days += d * e._days, a._months += d * e._months, a._bubble() } function qc(a, b) { return pc(this, a, b, 1) } function rc(a, b) { return pc(this, a, b, -1) } function sc(a) { return 0 > a ? Math.floor(a) : Math.ceil(a) } function tc() { var a, b, c, d, e, f = this._milliseconds, g = this._days, h = this._months, i = this._data; return f >= 0 && g >= 0 && h >= 0 || 0 >= f && 0 >= g && 0 >= h || (f += 864e5 * sc(vc(h) + g), g = 0, h = 0), i.milliseconds = f % 1e3, a = p(f / 1e3), i.seconds = a % 60, b = p(a / 60), i.minutes = b % 60, c = p(b / 60), i.hours = c % 24, g += p(c / 24), e = p(uc(g)), h += e, g -= sc(vc(e)), d = p(h / 12), h %= 12, i.days = g, i.months = h, i.years = d, this } function uc(a) { return 4800 * a / 146097 } function vc(a) { return 146097 * a / 4800 } function wc(a) { var b, c, d = this._milliseconds; if (a = A(a), "month" === a || "year" === a) return b = this._days + d / 864e5, c = this._months + uc(b), "month" === a ? c : c / 12; switch (b = this._days + Math.round(vc(this._months)), a) { case "week": return b / 7 + d / 6048e5; case "day": return b + d / 864e5; case "hour": return 24 * b + d / 36e5; case "minute": return 1440 * b + d / 6e4; case "second": return 86400 * b + d / 1e3; case "millisecond": return Math.floor(864e5 * b) + d; default: throw new Error("Unknown unit " + a) } } function xc() { return this._milliseconds + 864e5 * this._days + this._months % 12 * 2592e6 + 31536e6 * q(this._months / 12) } function yc(a) { return function () { return this.as(a) } } function zc(a) { return a = A(a), this[a + "s"]() } function Ac(a) { return function () { return this._data[a] } } function Bc() { return p(this.days() / 7) } function Cc(a, b, c, d, e) { return e.relativeTime(b || 1, !!c, a, d) } function Dc(a, b, c) { var d = Ya(a).abs(), e = ke(d.as("s")), f = ke(d.as("m")), g = ke(d.as("h")), h = ke(d.as("d")), i = ke(d.as("M")), j = ke(d.as("y")), k = e < le.s && ["s", e] || 1 === f && ["m"] || f < le.m && ["mm", f] || 1 === g && ["h"] || g < le.h && ["hh", g] || 1 === h && ["d"] || h < le.d && ["dd", h] || 1 === i && ["M"] || i < le.M && ["MM", i] || 1 === j && ["y"] || ["yy", j]; return k[2] = b, k[3] = +a > 0, k[4] = c, Cc.apply(null, k) } function Ec(a, b) { return void 0 === le[a] ? !1 : void 0 === b ? le[a] : (le[a] = b, !0) } function Fc(a) { var b = this.localeData(), c = Dc(this, !a, b); return a && (c = b.pastFuture(+this, c)), b.postformat(c) } function Gc() { var a, b, c, d = me(this._milliseconds) / 1e3, e = me(this._days), f = me(this._months); a = p(d / 60), b = p(a / 60), d %= 60, a %= 60, c = p(f / 12), f %= 12; var g = c, h = f, i = e, j = b, k = a, l = d, m = this.asSeconds(); return m ? (0 > m ? "-" : "") + "P" + (g ? g + "Y" : "") + (h ? h + "M" : "") + (i ? i + "D" : "") + (j || k || l ? "T" : "") + (j ? j + "H" : "") + (k ? k + "M" : "") + (l ? l + "S" : "") : "P0D" } var Hc, Ic, Jc = a.momentProperties = [], Kc = !1, Lc = {}, Mc = {}, Nc = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g, Oc = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, Pc = {}, Qc = {}, Rc = /\d/, Sc = /\d\d/, Tc = /\d{3}/, Uc = /\d{4}/, Vc = /[+-]?\d{6}/, Wc = /\d\d?/, Xc = /\d{1,3}/, Yc = /\d{1,4}/, Zc = /[+-]?\d{1,6}/, $c = /\d+/, _c = /[+-]?\d+/, ad = /Z|[+-]\d\d:?\d\d/gi, bd = /[+-]?\d+(\.\d{1,3})?/, cd = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, dd = {}, ed = {}, fd = 0, gd = 1, hd = 2, id = 3, jd = 4, kd = 5, ld = 6; H("M", ["MM", 2], "Mo", function () { return this.month() + 1 }), H("MMM", 0, 0, function (a) { return this.localeData().monthsShort(this, a) }), H("MMMM", 0, 0, function (a) { return this.localeData().months(this, a) }), z("month", "M"), N("M", Wc), N("MM", Wc, Sc), N("MMM", cd), N("MMMM", cd), Q(["M", "MM"], function (a, b) { b[gd] = q(a) - 1 }), Q(["MMM", "MMMM"], function (a, b, c, d) { var e = c._locale.monthsParse(a, d, c._strict); null != e ? b[gd] = e : j(c).invalidMonth = a }); var md = "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), nd = "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), od = {}; a.suppressDeprecationWarnings = !1; var pd = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/, qd = [["YYYYYY-MM-DD", /[+-]\d{6}-\d{2}-\d{2}/], ["YYYY-MM-DD", /\d{4}-\d{2}-\d{2}/], ["GGGG-[W]WW-E", /\d{4}-W\d{2}-\d/], ["GGGG-[W]WW", /\d{4}-W\d{2}/], ["YYYY-DDD", /\d{4}-\d{3}/]], rd = [["HH:mm:ss.SSSS", /(T| )\d\d:\d\d:\d\d\.\d+/], ["HH:mm:ss", /(T| )\d\d:\d\d:\d\d/], ["HH:mm", /(T| )\d\d:\d\d/], ["HH", /(T| )\d\d/]], sd = /^\/?Date\((\-?\d+)/i; a.createFromInputFallback = aa("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.", function (a) { a._d = new Date(a._i + (a._useUTC ? " UTC" : "")) }), H(0, ["YY", 2], 0, function () { return this.year() % 100 }), H(0, ["YYYY", 4], 0, "year"), H(0, ["YYYYY", 5], 0, "year"), H(0, ["YYYYYY", 6, !0], 0, "year"), z("year", "y"), N("Y", _c), N("YY", Wc, Sc), N("YYYY", Yc, Uc), N("YYYYY", Zc, Vc), N("YYYYYY", Zc, Vc), Q(["YYYYY", "YYYYYY"], fd), Q("YYYY", function (b, c) { c[fd] = 2 === b.length ? a.parseTwoDigitYear(b) : q(b) }), Q("YY", function (b, c) { c[fd] = a.parseTwoDigitYear(b) }), a.parseTwoDigitYear = function (a) { return q(a) + (q(a) > 68 ? 1900 : 2e3) }; var td = C("FullYear", !1); H("w", ["ww", 2], "wo", "week"), H("W", ["WW", 2], "Wo", "isoWeek"), z("week", "w"), z("isoWeek", "W"), N("w", Wc), N("ww", Wc, Sc), N("W", Wc), N("WW", Wc, Sc), R(["w", "ww", "W", "WW"], function (a, b, c, d) { b[d.substr(0, 1)] = q(a) }); var ud = { dow: 0, doy: 6 }; H("DDD", ["DDDD", 3], "DDDo", "dayOfYear"), z("dayOfYear", "DDD"), N("DDD", Xc), N("DDDD", Tc), Q(["DDD", "DDDD"], function (a, b, c) { c._dayOfYear = q(a) }), a.ISO_8601 = function () { }; var vd = aa("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548", function () { var a = Da.apply(null, arguments); return this > a ? this : a }), wd = aa("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548", function () { var a = Da.apply(null, arguments); return a > this ? this : a }); Ja("Z", ":"), Ja("ZZ", ""), N("Z", ad), N("ZZ", ad), Q(["Z", "ZZ"], function (a, b, c) { c._useUTC = !0, c._tzm = Ka(a) }); var xd = /([\+\-]|\d\d)/gi; a.updateOffset = function () { }; var yd = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/, zd = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/; Ya.fn = Ha.prototype; var Ad = ab(1, "add"), Bd = ab(-1, "subtract"); a.defaultFormat = "YYYY-MM-DDTHH:mm:ssZ"; var Cd = aa("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.", function (a) { return void 0 === a ? this.localeData() : this.locale(a) }); H(0, ["gg", 2], 0, function () { return this.weekYear() % 100 }), H(0, ["GG", 2], 0, function () { return this.isoWeekYear() % 100 }), Db("gggg", "weekYear"), Db("ggggg", "weekYear"), Db("GGGG", "isoWeekYear"), Db("GGGGG", "isoWeekYear"), z("weekYear", "gg"), z("isoWeekYear", "GG"), N("G", _c), N("g", _c), N("GG", Wc, Sc), N("gg", Wc, Sc), N("GGGG", Yc, Uc), N("gggg", Yc, Uc), N("GGGGG", Zc, Vc), N("ggggg", Zc, Vc), R(["gggg", "ggggg", "GGGG", "GGGGG"], function (a, b, c, d) { b[d.substr(0, 2)] = q(a) }), R(["gg", "GG"], function (b, c, d, e) { c[e] = a.parseTwoDigitYear(b) }), H("Q", 0, 0, "quarter"), z("quarter", "Q"), N("Q", Rc), Q("Q", function (a, b) { b[gd] = 3 * (q(a) - 1) }), H("D", ["DD", 2], "Do", "date"), z("date", "D"), N("D", Wc), N("DD", Wc, Sc), N("Do", function (a, b) { return a ? b._ordinalParse : b._ordinalParseLenient }), Q(["D", "DD"], hd), Q("Do", function (a, b) { b[hd] = q(a.match(Wc)[0], 10) }); var Dd = C("Date", !0); H("d", 0, "do", "day"), H("dd", 0, 0, function (a) { return this.localeData().weekdaysMin(this, a) }), H("ddd", 0, 0, function (a) { return this.localeData().weekdaysShort(this, a) }), H("dddd", 0, 0, function (a) { return this.localeData().weekdays(this, a) }), H("e", 0, 0, "weekday"), H("E", 0, 0, "isoWeekday"), z("day", "d"), z("weekday", "e"), z("isoWeekday", "E"), N("d", Wc), N("e", Wc), N("E", Wc), N("dd", cd), N("ddd", cd), N("dddd", cd), R(["dd", "ddd", "dddd"], function (a, b, c) { var d = c._locale.weekdaysParse(a); null != d ? b.d = d : j(c).invalidWeekday = a }), R(["d", "e", "E"], function (a, b, c, d) { b[d] = q(a) }); var Ed = "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), Fd = "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), Gd = "Su_Mo_Tu_We_Th_Fr_Sa".split("_"); H("H", ["HH", 2], 0, "hour"), H("h", ["hh", 2], 0, function () { return this.hours() % 12 || 12 }), Sb("a", !0), Sb("A", !1), z("hour", "h"), N("a", Tb), N("A", Tb), N("H", Wc), N("h", Wc), N("HH", Wc, Sc), N("hh", Wc, Sc), Q(["H", "HH"], id), Q(["a", "A"], function (a, b, c) { c._isPm = c._locale.isPM(a), c._meridiem = a }), Q(["h", "hh"], function (a, b, c) { b[id] = q(a), j(c).bigHour = !0 }); var Hd = /[ap]\.?m?\.?/i, Id = C("Hours", !0); H("m", ["mm", 2], 0, "minute"), z("minute", "m"), N("m", Wc), N("mm", Wc, Sc), Q(["m", "mm"], jd); var Jd = C("Minutes", !1); H("s", ["ss", 2], 0, "second"), z("second", "s"), N("s", Wc), N("ss", Wc, Sc), Q(["s", "ss"], kd); var Kd = C("Seconds", !1); H("S", 0, 0, function () { return ~~(this.millisecond() / 100) }), H(0, ["SS", 2], 0, function () { return ~~(this.millisecond() / 10) }), H(0, ["SSS", 3], 0, "millisecond"), H(0, ["SSSS", 4], 0, function () { return 10 * this.millisecond() }), H(0, ["SSSSS", 5], 0, function () { return 100 * this.millisecond() }), H(0, ["SSSSSS", 6], 0, function () { return 1e3 * this.millisecond() }), H(0, ["SSSSSSS", 7], 0, function () { return 1e4 * this.millisecond() }), H(0, ["SSSSSSSS", 8], 0, function () { return 1e5 * this.millisecond() }), H(0, ["SSSSSSSSS", 9], 0, function () { return 1e6 * this.millisecond() }), z("millisecond", "ms"), N("S", Xc, Rc), N("SS", Xc, Sc), N("SSS", Xc, Tc); var Ld; for (Ld = "SSSS"; Ld.length <= 9; Ld += "S") N(Ld, $c); for (Ld = "S"; Ld.length <= 9; Ld += "S") Q(Ld, Wb); var Md = C("Milliseconds", !1); H("z", 0, 0, "zoneAbbr"), H("zz", 0, 0, "zoneName"); var Nd = n.prototype; Nd.add = Ad, Nd.calendar = cb, Nd.clone = db, Nd.diff = ib, Nd.endOf = ub, Nd.format = mb, Nd.from = nb, Nd.fromNow = ob, Nd.to = pb, Nd.toNow = qb, Nd.get = F, Nd.invalidAt = Cb, Nd.isAfter = eb, Nd.isBefore = fb, Nd.isBetween = gb, Nd.isSame = hb, Nd.isValid = Ab, Nd.lang = Cd, Nd.locale = rb, Nd.localeData = sb, Nd.max = wd, Nd.min = vd, Nd.parsingFlags = Bb, Nd.set = F, Nd.startOf = tb, Nd.subtract = Bd, Nd.toArray = yb, Nd.toObject = zb, Nd.toDate = xb, Nd.toISOString = lb, Nd.toJSON = lb, Nd.toString = kb, Nd.unix = wb, Nd.valueOf = vb, Nd.year = td, Nd.isLeapYear = ia, Nd.weekYear = Fb, Nd.isoWeekYear = Gb, Nd.quarter = Nd.quarters = Jb, Nd.month = Y, Nd.daysInMonth = Z, Nd.week = Nd.weeks = na, Nd.isoWeek = Nd.isoWeeks = oa, Nd.weeksInYear = Ib, Nd.isoWeeksInYear = Hb, Nd.date = Dd, Nd.day = Nd.days = Pb, Nd.weekday = Qb, Nd.isoWeekday = Rb, Nd.dayOfYear = qa, Nd.hour = Nd.hours = Id, Nd.minute = Nd.minutes = Jd, Nd.second = Nd.seconds = Kd,
Nd.millisecond = Nd.milliseconds = Md, Nd.utcOffset = Na, Nd.utc = Pa, Nd.local = Qa, Nd.parseZone = Ra, Nd.hasAlignedHourOffset = Sa, Nd.isDST = Ta, Nd.isDSTShifted = Ua, Nd.isLocal = Va, Nd.isUtcOffset = Wa, Nd.isUtc = Xa, Nd.isUTC = Xa, Nd.zoneAbbr = Xb, Nd.zoneName = Yb, Nd.dates = aa("dates accessor is deprecated. Use date instead.", Dd), Nd.months = aa("months accessor is deprecated. Use month instead", Y), Nd.years = aa("years accessor is deprecated. Use year instead", td), Nd.zone = aa("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779", Oa); var Od = Nd, Pd = { sameDay: "[Today at] LT", nextDay: "[Tomorrow at] LT", nextWeek: "dddd [at] LT", lastDay: "[Yesterday at] LT", lastWeek: "[Last] dddd [at] LT", sameElse: "L" }, Qd = { LTS: "h:mm:ss A", LT: "h:mm A", L: "MM/DD/YYYY", LL: "MMMM D, YYYY", LLL: "MMMM D, YYYY h:mm A", LLLL: "dddd, MMMM D, YYYY h:mm A" }, Rd = "Invalid date", Sd = "%d", Td = /\d{1,2}/, Ud = { future: "in %s", past: "%s ago", s: "a few seconds", m: "a minute", mm: "%d minutes", h: "an hour", hh: "%d hours", d: "a day", dd: "%d days", M: "a month", MM: "%d months", y: "a year", yy: "%d years" }, Vd = s.prototype; Vd._calendar = Pd, Vd.calendar = _b, Vd._longDateFormat = Qd, Vd.longDateFormat = ac, Vd._invalidDate = Rd, Vd.invalidDate = bc, Vd._ordinal = Sd, Vd.ordinal = cc, Vd._ordinalParse = Td, Vd.preparse = dc, Vd.postformat = dc, Vd._relativeTime = Ud, Vd.relativeTime = ec, Vd.pastFuture = fc, Vd.set = gc, Vd.months = U, Vd._months = md, Vd.monthsShort = V, Vd._monthsShort = nd, Vd.monthsParse = W, Vd.week = ka, Vd._week = ud, Vd.firstDayOfYear = ma, Vd.firstDayOfWeek = la, Vd.weekdays = Lb, Vd._weekdays = Ed, Vd.weekdaysMin = Nb, Vd._weekdaysMin = Gd, Vd.weekdaysShort = Mb, Vd._weekdaysShort = Fd, Vd.weekdaysParse = Ob, Vd.isPM = Ub, Vd._meridiemParse = Hd, Vd.meridiem = Vb, w("en", { ordinalParse: /\d{1,2}(th|st|nd|rd)/, ordinal: function (a) { var b = a % 10, c = 1 === q(a % 100 / 10) ? "th" : 1 === b ? "st" : 2 === b ? "nd" : 3 === b ? "rd" : "th"; return a + c } }), a.lang = aa("moment.lang is deprecated. Use moment.locale instead.", w), a.langData = aa("moment.langData is deprecated. Use moment.localeData instead.", y); var Wd = Math.abs, Xd = yc("ms"), Yd = yc("s"), Zd = yc("m"), $d = yc("h"), _d = yc("d"), ae = yc("w"), be = yc("M"), ce = yc("y"), de = Ac("milliseconds"), ee = Ac("seconds"), fe = Ac("minutes"), ge = Ac("hours"), he = Ac("days"), ie = Ac("months"), je = Ac("years"), ke = Math.round, le = { s: 45, m: 45, h: 22, d: 26, M: 11 }, me = Math.abs, ne = Ha.prototype; ne.abs = oc, ne.add = qc, ne.subtract = rc, ne.as = wc, ne.asMilliseconds = Xd, ne.asSeconds = Yd, ne.asMinutes = Zd, ne.asHours = $d, ne.asDays = _d, ne.asWeeks = ae, ne.asMonths = be, ne.asYears = ce, ne.valueOf = xc, ne._bubble = tc, ne.get = zc, ne.milliseconds = de, ne.seconds = ee, ne.minutes = fe, ne.hours = ge, ne.days = he, ne.weeks = Bc, ne.months = ie, ne.years = je, ne.humanize = Fc, ne.toISOString = Gc, ne.toString = Gc, ne.toJSON = Gc, ne.locale = rb, ne.localeData = sb, ne.toIsoString = aa("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)", Gc), ne.lang = Cd, H("X", 0, 0, "unix"), H("x", 0, 0, "valueOf"), N("x", _c), N("X", bd), Q("X", function (a, b, c) { c._d = new Date(1e3 * parseFloat(a, 10)) }), Q("x", function (a, b, c) { c._d = new Date(q(a)) }), a.version = "2.10.6", b(Da), a.fn = Od, a.min = Fa, a.max = Ga, a.utc = h, a.unix = Zb, a.months = jc, a.isDate = d, a.locale = w, a.invalid = l, a.duration = Ya, a.isMoment = o, a.weekdays = lc, a.parseZone = $b, a.localeData = y, a.isDuration = Ia, a.monthsShort = kc, a.weekdaysMin = nc, a.defineLocale = x, a.weekdaysShort = mc, a.normalizeUnits = A, a.relativeTimeThreshold = Ec; var oe = a; return oe
});
//! moment-timezone.js
//! version : 0.5.0
//! author : Tim Wood
//! license : MIT
//! github.com/moment/moment-timezone
!function (a, b) { "use strict"; "function" == typeof define && define.amd ? define(["moment"], b) : "object" == typeof module && module.exports ? module.exports = b(require("moment")) : b(a.moment) }(this, function (a) {
"use strict"; function b(a) { return a > 96 ? a - 87 : a > 64 ? a - 29 : a - 48 } function c(a) { var c, d = 0, e = a.split("."), f = e[0], g = e[1] || "", h = 1, i = 0, j = 1; for (45 === a.charCodeAt(0) && (d = 1, j = -1), d; d < f.length; d++) c = b(f.charCodeAt(d)), i = 60 * i + c; for (d = 0; d < g.length; d++) h /= 60, c = b(g.charCodeAt(d)), i += c * h; return i * j } function d(a) { for (var b = 0; b < a.length; b++) a[b] = c(a[b]) } function e(a, b) { for (var c = 0; b > c; c++) a[c] = Math.round((a[c - 1] || 0) + 6e4 * a[c]); a[b - 1] = 1 / 0 } function f(a, b) { var c, d = []; for (c = 0; c < b.length; c++) d[c] = a[b[c]]; return d } function g(a) { var b = a.split("|"), c = b[2].split(" "), g = b[3].split(""), h = b[4].split(" "); return d(c), d(g), d(h), e(h, g.length), { name: b[0], abbrs: f(b[1].split(" "), g), offsets: f(c, g), untils: h, population: 0 | b[5] } } function h(a) { a && this._set(g(a)) } function i(a) { var b = a.toTimeString(), c = b.match(/\(.+\)/); c = c && c[0] ? c[0].match(/[A-Z]/g).join("") : b.match(/[A-Z]{3,5}/g)[0], "GMT" === c && (c = void 0), this.at = +a, this.abbr = c, this.offset = a.getTimezoneOffset() } function j(a) { this.zone = a, this.offsetScore = 0, this.abbrScore = 0 } function k(a, b) { for (var c, d; d = 6e4 * ((b.at - a.at) / 12e4 | 0) ;) c = new i(new Date(a.at + d)), c.offset === a.offset ? a = c : b = c; return a } function l() { var a, b, c, d = (new Date).getFullYear() - 2, e = new i(new Date(d, 0, 1)), f = [e]; for (c = 1; 48 > c; c++) b = new i(new Date(d, c, 1)), b.offset !== e.offset && (a = k(e, b), f.push(a), f.push(new i(new Date(a.at + 6e4)))), e = b; for (c = 0; 4 > c; c++) f.push(new i(new Date(d + c, 0, 1))), f.push(new i(new Date(d + c, 6, 1))); return f } function m(a, b) { return a.offsetScore !== b.offsetScore ? a.offsetScore - b.offsetScore : a.abbrScore !== b.abbrScore ? a.abbrScore - b.abbrScore : b.zone.population - a.zone.population } function n(a, b) { var c, e; for (d(b), c = 0; c < b.length; c++) e = b[c], I[e] = I[e] || {}, I[e][a] = !0 } function o(a) { var b, c, d, e = a.length, f = {}, g = []; for (b = 0; e > b; b++) { d = I[a[b].offset] || {}; for (c in d) d.hasOwnProperty(c) && (f[c] = !0) } for (b in f) f.hasOwnProperty(b) && g.push(H[b]); return g } function p() { var a, b, c, d = l(), e = d.length, f = o(d), g = []; for (b = 0; b < f.length; b++) { for (a = new j(t(f[b]), e), c = 0; e > c; c++) a.scoreOffsetAt(d[c]); g.push(a) } return g.sort(m), g.length > 0 ? g[0].zone.name : void 0 } function q(a) { return (!D || a) && (D = p()), D } function r(a) { return (a || "").toLowerCase().replace(/\//g, "_") } function s(a) { var b, c, d, e; for ("string" == typeof a && (a = [a]), b = 0; b < a.length; b++) d = a[b].split("|"), c = d[0], e = r(c), F[e] = a[b], H[e] = c, d[5] && n(e, d[2].split(" ")) } function t(a, b) { a = r(a); var c, d = F[a]; return d instanceof h ? d : "string" == typeof d ? (d = new h(d), F[a] = d, d) : G[a] && b !== t && (c = t(G[a], t)) ? (d = F[a] = new h, d._set(c), d.name = H[a], d) : null } function u() { var a, b = []; for (a in H) H.hasOwnProperty(a) && (F[a] || F[G[a]]) && H[a] && b.push(H[a]); return b.sort() } function v(a) { var b, c, d, e; for ("string" == typeof a && (a = [a]), b = 0; b < a.length; b++) c = a[b].split("|"), d = r(c[0]), e = r(c[1]), G[d] = e, H[d] = c[0], G[e] = d, H[e] = c[1] } function w(a) { s(a.zones), v(a.links), A.dataVersion = a.version } function x(a) { return x.didShowError || (x.didShowError = !0, z("moment.tz.zoneExists('" + a + "') has been deprecated in favor of !moment.tz.zone('" + a + "')")), !!t(a) } function y(a) { return !(!a._a || void 0 !== a._tzm) } function z(a) { "undefined" != typeof console && "function" == typeof console.error && console.error(a) } function A(b) { var c = Array.prototype.slice.call(arguments, 0, -1), d = arguments[arguments.length - 1], e = t(d), f = a.utc.apply(null, c); return e && !a.isMoment(b) && y(f) && f.add(e.parse(f), "minutes"), f.tz(d), f } function B(a) { return function () { return this._z ? this._z.abbr(this) : a.call(this) } } function C(a) { return function () { return this._z = null, a.apply(this, arguments) } } if (void 0 !== a.tz) return z("Moment Timezone " + a.tz.version + " was already loaded " + (a.tz.dataVersion ? "with data from " : "without any data") + a.tz.dataVersion), a; var D, E = "0.5.0", F = {}, G = {}, H = {}, I = {}, J = a.version.split("."), K = +J[0], L = +J[1]; (2 > K || 2 === K && 6 > L) && z("Moment Timezone requires Moment.js >= 2.6.0. You are using Moment.js " + a.version + ". See momentjs.com"), h.prototype = { _set: function (a) { this.name = a.name, this.abbrs = a.abbrs, this.untils = a.untils, this.offsets = a.offsets, this.population = a.population }, _index: function (a) { var b, c = +a, d = this.untils; for (b = 0; b < d.length; b++) if (c < d[b]) return b }, parse: function (a) { var b, c, d, e, f = +a, g = this.offsets, h = this.untils, i = h.length - 1; for (e = 0; i > e; e++) if (b = g[e], c = g[e + 1], d = g[e ? e - 1 : e], c > b && A.moveAmbiguousForward ? b = c : b > d && A.moveInvalidForward && (b = d), f < h[e] - 6e4 * b) return g[e]; return g[i] }, abbr: function (a) { return this.abbrs[this._index(a)] }, offset: function (a) { return this.offsets[this._index(a)] } }, j.prototype.scoreOffsetAt = function (a) { this.offsetScore += Math.abs(this.zone.offset(a.at) - a.offset), this.zone.abbr(a.at).match(/[A-Z]/g).join("") !== a.abbr && this.abbrScore++ }, A.version = E, A.dataVersion = "", A._zones = F, A._links = G, A._names = H, A.add = s, A.link = v, A.load = w, A.zone = t, A.zoneExists = x, A.guess = q, A.names = u, A.Zone = h, A.unpack = g, A.unpackBase60 = c, A.needsOffset = y, A.moveInvalidForward = !0, A.moveAmbiguousForward = !1; var M = a.fn; a.tz = A, a.defaultZone = null, a.updateOffset = function (b, c) { var d, e = a.defaultZone; void 0 === b._z && (e && y(b) && !b._isUTC && (b._d = a.utc(b._a)._d, b.utc().add(e.parse(b), "minutes")), b._z = e), b._z && (d = b._z.offset(b), Math.abs(d) < 16 && (d /= 60), void 0 !== b.utcOffset ? b.utcOffset(-d, c) : b.zone(d, c)) }, M.tz = function (b) { return b ? (this._z = t(b), this._z ? a.updateOffset(this) : z("Moment Timezone has no data for " + b + ". See http://momentjs.com/timezone/docs/#/data-loading/."), this) : this._z ? this._z.name : void 0 }, M.zoneName = B(M.zoneName), M.zoneAbbr = B(M.zoneAbbr), M.utc = C(M.utc), a.tz.setDefault = function (b) { return (2 > K || 2 === K && 9 > L) && z("Moment Timezone setDefault() requires Moment.js >= 2.9.0. You are using Moment.js " + a.version + "."), a.defaultZone = b ? t(b) : null, a }; var N = a.momentProperties; return "[object Array]" === Object.prototype.toString.call(N) ? (N.push("_z"), N.push("_a")) : N && (N._z = null), w({
version: "2015g", zones: ["Africa/Abidjan|GMT|0|0||48e5", "Africa/Khartoum|EAT|-30|0||51e5", "Africa/Algiers|CET|-10|0||26e5", "Africa/Lagos|WAT|-10|0||17e6", "Africa/Maputo|CAT|-20|0||26e5", "Africa/Cairo|EET EEST|-20 -30|010101010|1Cby0 Fb0 c10 8n0 8Nd0 gL0 e10 mn0|15e6", "Africa/Casablanca|WET WEST|0 -10|01010101010101010101010101010101010101010|1Cco0 Db0 1zd0 Lz0 1Nf0 wM0 co0 go0 1o00 s00 dA0 vc0 11A0 A00 e00 y00 11A0 uM0 e00 Dc0 11A0 s00 e00 IM0 WM0 mo0 gM0 LA0 WM0 jA0 e00 Rc0 11A0 e00 e00 U00 11A0 8o0 e00 11A0|32e5", "Europe/Paris|CET CEST|-10 -20|01010101010101010101010|1BWp0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|11e6", "Africa/Johannesburg|SAST|-20|0||84e5", "Africa/Tripoli|EET CET CEST|-20 -10 -20|0120|1IlA0 TA0 1o00|11e5", "Africa/Windhoek|WAST WAT|-20 -10|01010101010101010101010|1C1c0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0|32e4", "America/Adak|HST HDT|a0 90|01010101010101010101010|1BR00 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|326", "America/Anchorage|AKST AKDT|90 80|01010101010101010101010|1BQX0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|30e4", "America/Santo_Domingo|AST|40|0||29e5", "America/Araguaina|BRT BRST|30 20|010|1IdD0 Lz0|14e4", "America/Argentina/Buenos_Aires|ART|30|0|", "America/Asuncion|PYST PYT|30 40|01010101010101010101010|1C430 1a10 1fz0 1a10 1fz0 1cN0 17b0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1ip0 17b0 1ip0 17b0 1ip0|28e5", "America/Panama|EST|50|0||15e5", "America/Bahia|BRT BRST|30 20|010|1FJf0 Rb0|27e5", "America/Bahia_Banderas|MST CDT CST|70 50 60|01212121212121212121212|1C1l0 1nW0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|84e3", "America/Fortaleza|BRT|30|0||34e5", "America/Managua|CST|60|0||22e5", "America/Manaus|AMT|40|0||19e5", "America/Bogota|COT|50|0||90e5", "America/Denver|MST MDT|70 60|01010101010101010101010|1BQV0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|26e5", "America/Campo_Grande|AMST AMT|30 40|01010101010101010101010|1BIr0 1zd0 On0 1zd0 Rb0 1zd0 Lz0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1C10 Lz0 1C10 Lz0 1C10|77e4", "America/Cancun|CST CDT EST|60 50 50|010101010102|1C1k0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 Dd0|63e4", "America/Caracas|VET|4u|0||29e5", "America/Cayenne|GFT|30|0||58e3", "America/Cayman|EST EDT|50 40|01010101010|1Qtj0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|58e3", "America/Chicago|CST CDT|60 50|01010101010101010101010|1BQU0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|92e5", "America/Chihuahua|MST MDT|70 60|01010101010101010101010|1C1l0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|81e4", "America/Phoenix|MST|70|0||42e5", "America/Los_Angeles|PST PDT|80 70|01010101010101010101010|1BQW0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|15e6", "America/New_York|EST EDT|50 40|01010101010101010101010|1BQT0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|21e6", "America/Rio_Branco|AMT ACT|40 50|01|1KLE0|31e4", "America/Fort_Nelson|PST PDT MST|80 70 70|010101010102|1BQW0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0|39e2", "America/Halifax|AST ADT|40 30|01010101010101010101010|1BQS0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|39e4", "America/Godthab|WGT WGST|30 20|01010101010101010101010|1BWp0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|17e3", "America/Goose_Bay|AST ADT|40 30|01010101010101010101010|1BQQ1 1zb0 Op0 1zcX Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|76e2", "America/Grand_Turk|EST EDT AST|50 40 40|0101010101012|1BQT0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|37e2", "America/Guayaquil|ECT|50|0||27e5", "America/Guyana|GYT|40|0||80e4", "America/Havana|CST CDT|50 40|01010101010101010101010|1BQR0 1wo0 U00 1zc0 U00 1qM0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0|21e5", "America/La_Paz|BOT|40|0||19e5", "America/Lima|PET|50|0||11e6", "America/Mexico_City|CST CDT|60 50|01010101010101010101010|1C1k0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|20e6", "America/Metlakatla|PST|80|0||14e2", "America/Miquelon|PMST PMDT|30 20|01010101010101010101010|1BQR0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|61e2", "America/Montevideo|UYST UYT|20 30|010101010101|1BQQ0 1ld0 14n0 1ld0 14n0 1o10 11z0 1o10 11z0 1o10 11z0|17e5", "America/Noronha|FNT|20|0||30e2", "America/North_Dakota/Beulah|MST MDT CST CDT|70 60 60 50|01232323232323232323232|1BQV0 1zb0 Oo0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0", "America/Paramaribo|SRT|30|0||24e4", "America/Port-au-Prince|EST EDT|50 40|0101010101010101010|1GI70 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|23e5", "America/Santa_Isabel|PST PDT|80 70|01010101010101010101010|1C1m0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|23e3", "America/Santiago|CLST CLT CLT|30 40 30|010101010102|1C1f0 1fB0 1nX0 G10 1EL0 Op0 1zb0 Rd0 1wn0 Rd0 1wn0|62e5", "America/Sao_Paulo|BRST BRT|20 30|01010101010101010101010|1BIq0 1zd0 On0 1zd0 Rb0 1zd0 Lz0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1C10 Lz0 1C10 Lz0 1C10|20e6", "America/Scoresbysund|EGT EGST|10 0|01010101010101010101010|1BWp0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|452", "America/St_Johns|NST NDT|3u 2u|01010101010101010101010|1BQPv 1zb0 Op0 1zcX Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|11e4", "Antarctica/Casey|CAST AWST|-b0 -80|0101|1BN30 40P0 KL0|10", "Antarctica/Davis|DAVT DAVT|-50 -70|0101|1BPw0 3Wn0 KN0|70", "Antarctica/DumontDUrville|DDUT|-a0|0||80", "Antarctica/Macquarie|AEDT MIST|-b0 -b0|01|1C140|1", "Antarctica/Mawson|MAWT|-50|0||60", "Pacific/Auckland|NZDT NZST|-d0 -c0|01010101010101010101010|1C120 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00|14e5", "Antarctica/Rothera|ROTT|30|0||130", "Antarctica/Syowa|SYOT|-30|0||20", "Antarctica/Troll|UTC CEST|0 -20|01010101010101010101010|1BWp0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|40", "Antarctica/Vostok|VOST|-60|0||25", "Asia/Baghdad|AST|-30|0||66e5", "Asia/Almaty|ALMT|-60|0||15e5", "Asia/Amman|EET EEST|-20 -30|010101010101010101010|1BVy0 1qM0 11A0 1o00 11A0 4bX0 Dd0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0|25e5", "Asia/Anadyr|ANAT ANAST ANAT|-c0 -c0 -b0|0120|1BWe0 1qN0 WM0|13e3", "Asia/Aqtobe|AQTT|-50|0||27e4", "Asia/Ashgabat|TMT|-50|0||41e4", "Asia/Baku|AZT AZST|-40 -50|01010101010101010101010|1BWo0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|27e5", "Asia/Bangkok|ICT|-70|0||15e6", "Asia/Beirut|EET EEST|-20 -30|01010101010101010101010|1BWm0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0|22e5", "Asia/Bishkek|KGT|-60|0||87e4", "Asia/Brunei|BNT|-80|0||42e4", "Asia/Kolkata|IST|-5u|0||15e6", "Asia/Chita|YAKT YAKST YAKT IRKT|-90 -a0 -a0 -80|01023|1BWh0 1qM0 WM0 8Hz0|33e4", "Asia/Choibalsan|CHOT CHOST|-80 -90|0101010101010|1O8G0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0|38e3", "Asia/Shanghai|CST|-80|0||23e6", "Asia/Dhaka|BDT|-60|0||16e6", "Asia/Damascus|EET EEST|-20 -30|01010101010101010101010|1C0m0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0|26e5", "Asia/Dili|TLT|-90|0||19e4", "Asia/Dubai|GST|-40|0||39e5", "Asia/Dushanbe|TJT|-50|0||76e4", "Asia/Gaza|EET EEST|-20 -30|01010101010101010101010|1BVW1 SKX 1xd1 MKX 1AN0 1a00 1fA0 1cL0 1cN0 1nX0 1210 1nz0 1210 1nz0 14N0 1nz0 1210 1nz0 1210 1nz0 1210 1nz0|18e5", "Asia/Hebron|EET EEST|-20 -30|0101010101010101010101010|1BVy0 Tb0 1xd1 MKX bB0 cn0 1cN0 1a00 1fA0 1cL0 1cN0 1nX0 1210 1nz0 1210 1nz0 14N0 1nz0 1210 1nz0 1210 1nz0 1210 1nz0|25e4", "Asia/Hong_Kong|HKT|-80|0||73e5", "Asia/Hovd|HOVT HOVST|-70 -80|0101010101010|1O8H0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0|81e3", "Asia/Irkutsk|IRKT IRKST IRKT|-80 -90 -90|01020|1BWi0 1qM0 WM0 8Hz0|60e4", "Europe/Istanbul|EET EEST|-20 -30|01010101010101010101010|1BWp0 1qM0 Xc0 1qo0 WM0 1qM0 11A0 1o00 1200 1nA0 11A0 1tA0 U00 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|13e6", "Asia/Jakarta|WIB|-70|0||31e6", "Asia/Jayapura|WIT|-90|0||26e4", "Asia/Jerusalem|IST IDT|-20 -30|01010101010101010101010|1BVA0 17X0 1kp0 1dz0 1c10 1aL0 1eN0 1oL0 10N0 1oL0 10N0 1oL0 10N0 1rz0 W10 1rz0 W10 1rz0 10N0 1oL0 10N0 1oL0|81e4", "Asia/Kabul|AFT|-4u|0||46e5", "Asia/Kamchatka|PETT PETST PETT|-c0 -c0 -b0|0120|1BWe0 1qN0 WM0|18e4", "Asia/Karachi|PKT|-50|0||24e6", "Asia/Urumqi|XJT|-60|0||32e5", "Asia/Kathmandu|NPT|-5J|0||12e5", "Asia/Khandyga|VLAT VLAST VLAT YAKT YAKT|-a0 -b0 -b0 -a0 -90|010234|1BWg0 1qM0 WM0 17V0 7zD0|66e2", "Asia/Krasnoyarsk|KRAT KRAST KRAT|-70 -80 -80|01020|1BWj0 1qM0 WM0 8Hz0|10e5", "Asia/Kuala_Lumpur|MYT|-80|0||71e5", "Asia/Magadan|MAGT MAGST MAGT MAGT|-b0 -c0 -c0 -a0|01023|1BWf0 1qM0 WM0 8Hz0|95e3", "Asia/Makassar|WITA|-80|0||15e5", "Asia/Manila|PHT|-80|0||24e6", "Europe/Athens|EET EEST|-20 -30|01010101010101010101010|1BWp0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|35e5", "Asia/Novokuznetsk|KRAT NOVST NOVT NOVT|-70 -70 -60 -70|01230|1BWj0 1qN0 WM0 8Hz0|55e4", "Asia/Novosibirsk|NOVT NOVST NOVT|-60 -70 -70|01020|1BWk0 1qM0 WM0 8Hz0|15e5", "Asia/Omsk|OMST OMSST OMST|-60 -70 -70|01020|1BWk0 1qM0 WM0 8Hz0|12e5", "Asia/Oral|ORAT|-50|0||27e4", "Asia/Pyongyang|KST KST|-90 -8u|01|1P4D0|29e5", "Asia/Qyzylorda|QYZT|-60|0||73e4", "Asia/Rangoon|MMT|-6u|0||48e5", "Asia/Sakhalin|SAKT SAKST SAKT|-a0 -b0 -b0|01020|1BWg0 1qM0 WM0 8Hz0|58e4", "Asia/Tashkent|UZT|-50|0||23e5", "Asia/Seoul|KST|-90|0||23e6", "Asia/Singapore|SGT|-80|0||56e5", "Asia/Srednekolymsk|MAGT MAGST MAGT SRET|-b0 -c0 -c0 -b0|01023|1BWf0 1qM0 WM0 8Hz0|35e2", "Asia/Tbilisi|GET|-40|0||11e5", "Asia/Tehran|IRST IRDT|-3u -4u|01010101010101010101010|1BTUu 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0|14e6", "Asia/Thimphu|BTT|-60|0||79e3", "Asia/Tokyo|JST|-90|0||38e6", "Asia/Ulaanbaatar|ULAT ULAST|-80 -90|0101010101010|1O8G0 1cJ0 1cP0 1cJ0 1cP0 1fx0 1cP0 1cJ0 1cP0 1cJ0 1cP0 1cJ0|12e5", "Asia/Ust-Nera|MAGT MAGST MAGT VLAT VLAT|-b0 -c0 -c0 -b0 -a0|010234|1BWf0 1qM0 WM0 17V0 7zD0|65e2", "Asia/Vladivostok|VLAT VLAST VLAT|-a0 -b0 -b0|01020|1BWg0 1qM0 WM0 8Hz0|60e4", "Asia/Yakutsk|YAKT YAKST YAKT|-90 -a0 -a0|01020|1BWh0 1qM0 WM0 8Hz0|28e4", "Asia/Yekaterinburg|YEKT YEKST YEKT|-50 -60 -60|01020|1BWl0 1qM0 WM0 8Hz0|14e5", "Asia/Yerevan|AMT AMST|-40 -50|01010|1BWm0 1qM0 WM0 1qM0|13e5", "Atlantic/Azores|AZOT AZOST|10 0|01010101010101010101010|1BWp0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|25e4", "Europe/Lisbon|WET WEST|0 -10|01010101010101010101010|1BWp0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|27e5", "Atlantic/Cape_Verde|CVT|10|0||50e4", "Atlantic/South_Georgia|GST|20|0||30", "Atlantic/Stanley|FKST FKT|30 40|010|1C6R0 U10|21e2", "Australia/Sydney|AEDT AEST|-b0 -a0|01010101010101010101010|1C140 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|40e5", "Australia/Adelaide|ACDT ACST|-au -9u|01010101010101010101010|1C14u 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|11e5", "Australia/Brisbane|AEST|-a0|0||20e5", "Australia/Darwin|ACST|-9u|0||12e4", "Australia/Eucla|ACWST|-8J|0||368", "Australia/Lord_Howe|LHDT LHST|-b0 -au|01010101010101010101010|1C130 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu|347", "Australia/Perth|AWST|-80|0||18e5", "Pacific/Easter|EASST EAST EAST|50 60 50|010101010102|1C1f0 1fB0 1nX0 G10 1EL0 Op0 1zb0 Rd0 1wn0 Rd0 1wn0|30e2", "Europe/Dublin|GMT IST|0 -10|01010101010101010101010|1BWp0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|12e5", "Etc/GMT+1|GMT+1|10|0|", "Etc/GMT+10|GMT+10|a0|0|", "Etc/GMT+11|GMT+11|b0|0|", "Etc/GMT+12|GMT+12|c0|0|", "Etc/GMT+2|GMT+2|20|0|", "Etc/GMT+3|GMT+3|30|0|", "Etc/GMT+4|GMT+4|40|0|", "Etc/GMT+5|GMT+5|50|0|", "Etc/GMT+6|GMT+6|60|0|", "Etc/GMT+7|GMT+7|70|0|", "Etc/GMT+8|GMT+8|80|0|", "Etc/GMT+9|GMT+9|90|0|", "Etc/GMT-1|GMT-1|-10|0|", "Etc/GMT-10|GMT-10|-a0|0|", "Etc/GMT-11|GMT-11|-b0|0|", "Etc/GMT-12|GMT-12|-c0|0|", "Etc/GMT-13|GMT-13|-d0|0|", "Etc/GMT-14|GMT-14|-e0|0|", "Etc/GMT-2|GMT-2|-20|0|", "Etc/GMT-3|GMT-3|-30|0|", "Etc/GMT-4|GMT-4|-40|0|", "Etc/GMT-5|GMT-5|-50|0|", "Etc/GMT-6|GMT-6|-60|0|", "Etc/GMT-7|GMT-7|-70|0|", "Etc/GMT-8|GMT-8|-80|0|", "Etc/GMT-9|GMT-9|-90|0|", "Etc/UCT|UCT|0|0|", "Etc/UTC|UTC|0|0|", "Europe/London|GMT BST|0 -10|01010101010101010101010|1BWp0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|10e6", "Europe/Chisinau|EET EEST|-20 -30|01010101010101010101010|1BWo0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|67e4", "Europe/Kaliningrad|EET EEST FET|-20 -30 -30|01020|1BWo0 1qM0 WM0 8Hz0|44e4", "Europe/Minsk|EET EEST FET MSK|-20 -30 -30 -30|01023|1BWo0 1qM0 WM0 8Hy0|19e5", "Europe/Moscow|MSK MSD MSK|-30 -40 -40|01020|1BWn0 1qM0 WM0 8Hz0|16e6", "Europe/Samara|SAMT SAMST SAMT|-40 -40 -30|0120|1BWm0 1qN0 WM0|12e5", "Europe/Simferopol|EET EEST MSK MSK|-20 -30 -40 -30|01010101023|1BWp0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11z0 1nW0|33e4", "Pacific/Honolulu|HST|a0|0||37e4", "Indian/Chagos|IOT|-60|0||30e2", "Indian/Christmas|CXT|-70|0||21e2", "Indian/Cocos|CCT|-6u|0||596", "Indian/Kerguelen|TFT|-50|0||130", "Indian/Mahe|SCT|-40|0||79e3", "Indian/Maldives|MVT|-50|0||35e4", "Indian/Mauritius|MUT|-40|0||15e4", "Indian/Reunion|RET|-40|0||84e4", "Pacific/Majuro|MHT|-c0|0||28e3", "MET|MET MEST|-10 -20|01010101010101010101010|1BWp0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00", "Pacific/Chatham|CHADT CHAST|-dJ -cJ|01010101010101010101010|1C120 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00|600", "Pacific/Apia|SST SDT WSDT WSST|b0 a0 -e0 -d0|01012323232323232323232|1Dbn0 1ff0 1a00 CI0 AQ0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00|37e3", "Pacific/Bougainville|PGT BST|-a0 -b0|01|1NwE0|18e4", "Pacific/Chuuk|CHUT|-a0|0||49e3", "Pacific/Efate|VUT|-b0|0||66e3", "Pacific/Enderbury|PHOT|-d0|0||1", "Pacific/Fakaofo|TKT TKT|b0 -d0|01|1Gfn0|483", "Pacific/Fiji|FJST FJT|-d0 -c0|01010101010101010101010|1BWe0 1o00 Rc0 1wo0 Ao0 1Nc0 Ao0 1Q00 xz0 1SN0 uM0 1SM0 uM0 1VA0 s00 1VA0 uM0 1SM0 uM0 1SM0 uM0 1SM0|88e4", "Pacific/Funafuti|TVT|-c0|0||45e2", "Pacific/Galapagos|GALT|60|0||25e3", "Pacific/Gambier|GAMT|90|0||125", "Pacific/Guadalcanal|SBT|-b0|0||11e4", "Pacific/Guam|ChST|-a0|0||17e4", "Pacific/Kiritimati|LINT|-e0|0||51e2", "Pacific/Kosrae|KOST|-b0|0||66e2", "Pacific/Marquesas|MART|9u|0||86e2", "Pacific/Pago_Pago|SST|b0|0||37e2", "Pacific/Nauru|NRT|-c0|0||10e3", "Pacific/Niue|NUT|b0|0||12e2", "Pacific/Norfolk|NFT NFT|-bu -b0|01|1PoCu|25e4", "Pacific/Noumea|NCT|-b0|0||98e3", "Pacific/Palau|PWT|-90|0||21e3", "Pacific/Pohnpei|PONT|-b0|0||34e3", "Pacific/Port_Moresby|PGT|-a0|0||25e4", "Pacific/Rarotonga|CKT|a0|0||13e3", "Pacific/Tahiti|TAHT|a0|0||18e4", "Pacific/Tarawa|GILT|-c0|0||29e3", "Pacific/Tongatapu|TOT|-d0|0||75e3", "Pacific/Wake|WAKT|-c0|0||16e3", "Pacific/Wallis|WFT|-c0|0||94"], links: ["Africa/Abidjan|Africa/Accra", "Africa/Abidjan|Africa/Bamako", "Africa/Abidjan|Africa/Banjul", "Africa/Abidjan|Africa/Bissau", "Africa/Abidjan|Africa/Conakry", "Africa/Abidjan|Africa/Dakar", "Africa/Abidjan|Africa/Freetown", "Africa/Abidjan|Africa/Lome", "Africa/Abidjan|Africa/Monrovia", "Africa/Abidjan|Africa/Nouakchott", "Africa/Abidjan|Africa/Ouagadougou", "Africa/Abidjan|Africa/Sao_Tome", "Africa/Abidjan|Africa/Timbuktu", "Africa/Abidjan|America/Danmarkshavn", "Africa/Abidjan|Atlantic/Reykjavik", "Africa/Abidjan|Atlantic/St_Helena", "Africa/Abidjan|Etc/GMT", "Africa/Abidjan|Etc/GMT+0", "Africa/Abidjan|Etc/GMT-0", "Africa/Abidjan|Etc/GMT0", "Africa/Abidjan|Etc/Greenwich", "Africa/Abidjan|GMT", "Africa/Abidjan|GMT+0", "Africa/Abidjan|GMT-0", "Africa/Abidjan|GMT0", "Africa/Abidjan|Greenwich", "Africa/Abidjan|Iceland", "Africa/Algiers|Africa/Tunis", "Africa/Cairo|Egypt", "Africa/Casablanca|Africa/El_Aaiun", "Africa/Johannesburg|Africa/Maseru", "Africa/Johannesburg|Africa/Mbabane", "Africa/Khartoum|Africa/Addis_Ababa", "Africa/Khartoum|Africa/Asmara", "Africa/Khartoum|Africa/Asmera", "Africa/Khartoum|Africa/Dar_es_Salaam", "Africa/Khartoum|Africa/Djibouti", "Africa/Khartoum|Africa/Juba", "Africa/Khartoum|Africa/Kampala", "Africa/Khartoum|Africa/Mogadishu", "Africa/Khartoum|Africa/Nairobi", "Africa/Khartoum|Indian/Antananarivo", "Africa/Khartoum|Indian/Comoro", "Africa/Khartoum|Indian/Mayotte", "Africa/Lagos|Africa/Bangui", "Africa/Lagos|Africa/Brazzaville", "Africa/Lagos|Africa/Douala", "Africa/Lagos|Africa/Kinshasa", "Africa/Lagos|Africa/Libreville", "Africa/Lagos|Africa/Luanda", "Africa/Lagos|Africa/Malabo", "Africa/Lagos|Africa/Ndjamena", "Africa/Lagos|Africa/Niamey", "Africa/Lagos|Africa/Porto-Novo", "Africa/Maputo|Africa/Blantyre", "Africa/Maputo|Africa/Bujumbura", "Africa/Maputo|Africa/Gaborone", "Africa/Maputo|Africa/Harare", "Africa/Maputo|Africa/Kigali", "Africa/Maputo|Africa/Lubumbashi", "Africa/Maputo|Africa/Lusaka", "Africa/Tripoli|Libya", "America/Adak|America/Atka", "America/Adak|US/Aleutian", "America/Anchorage|America/Juneau", "America/Anchorage|America/Nome", "America/Anchorage|America/Sitka", "America/Anchorage|America/Yakutat", "America/Anchorage|US/Alaska", "America/Argentina/Buenos_Aires|America/Argentina/Catamarca", "America/Argentina/Buenos_Aires|America/Argentina/ComodRivadavia", "America/Argentina/Buenos_Aires|America/Argentina/Cordoba", "America/Argentina/Buenos_Aires|America/Argentina/Jujuy", "America/Argentina/Buenos_Aires|America/Argentina/La_Rioja", "America/Argentina/Buenos_Aires|America/Argentina/Mendoza", "America/Argentina/Buenos_Aires|America/Argentina/Rio_Gallegos", "America/Argentina/Buenos_Aires|America/Argentina/Salta", "America/Argentina/Buenos_Aires|America/Argentina/San_Juan", "America/Argentina/Buenos_Aires|America/Argentina/San_Luis", "America/Argentina/Buenos_Aires|America/Argentina/Tucuman", "America/Argentina/Buenos_Aires|America/Argentina/Ushuaia", "America/Argentina/Buenos_Aires|America/Buenos_Aires", "America/Argentina/Buenos_Aires|America/Catamarca", "America/Argentina/Buenos_Aires|America/Cordoba", "America/Argentina/Buenos_Aires|America/Jujuy", "America/Argentina/Buenos_Aires|America/Mendoza", "America/Argentina/Buenos_Aires|America/Rosario", "America/Campo_Grande|America/Cuiaba", "America/Chicago|America/Indiana/Knox", "America/Chicago|America/Indiana/Tell_City", "America/Chicago|America/Knox_IN", "America/Chicago|America/Matamoros", "America/Chicago|America/Menominee", "America/Chicago|America/North_Dakota/Center", "America/Chicago|America/North_Dakota/New_Salem", "America/Chicago|America/Rainy_River", "America/Chicago|America/Rankin_Inlet", "America/Chicago|America/Resolute", "America/Chicago|America/Winnipeg", "America/Chicago|CST6CDT", "America/Chicago|Canada/Central", "America/Chicago|US/Central", "America/Chicago|US/Indiana-Starke", "America/Chihuahua|America/Mazatlan", "America/Chihuahua|Mexico/BajaSur", "America/Denver|America/Boise", "America/Denver|America/Cambridge_Bay", "America/Denver|America/Edmonton", "America/Denver|America/Inuvik", "America/Denver|America/Ojinaga", "America/Denver|America/Shiprock", "America/Denver|America/Yellowknife", "America/Denver|Canada/Mountain", "America/Denver|MST7MDT", "America/Denver|Navajo", "America/Denver|US/Mountain", "America/Fortaleza|America/Belem", "America/Fortaleza|America/Maceio", "America/Fortaleza|America/Recife", "America/Fortaleza|America/Santarem", "America/Halifax|America/Glace_Bay", "America/Halifax|America/Moncton", "America/Halifax|America/Thule", "America/Halifax|Atlantic/Bermuda", "America/Halifax|Canada/Atlantic", "America/Havana|Cuba", "America/Los_Angeles|America/Dawson", "America/Los_Angeles|America/Ensenada", "America/Los_Angeles|America/Tijuana", "America/Los_Angeles|America/Vancouver", "America/Los_Angeles|America/Whitehorse", "America/Los_Angeles|Canada/Pacific", "America/Los_Angeles|Canada/Yukon", "America/Los_Angeles|Mexico/BajaNorte", "America/Los_Angeles|PST8PDT", "America/Los_Angeles|US/Pacific", "America/Los_Angeles|US/Pacific-New", "America/Managua|America/Belize", "America/Managua|America/Costa_Rica", "America/Managua|America/El_Salvador", "America/Managua|America/Guatemala", "America/Managua|America/Regina", "America/Managua|America/Swift_Current", "America/Managua|America/Tegucigalpa", "America/Managua|Canada/East-Saskatchewan", "America/Managua|Canada/Saskatchewan", "America/Manaus|America/Boa_Vista", "America/Manaus|America/Porto_Velho", "America/Manaus|Brazil/West", "America/Metlakatla|Pacific/Pitcairn", "America/Mexico_City|America/Merida", "America/Mexico_City|America/Monterrey", "America/Mexico_City|Mexico/General", "America/New_York|America/Detroit", "America/New_York|America/Fort_Wayne", "America/New_York|America/Indiana/Indianapolis", "America/New_York|America/Indiana/Marengo", "America/New_York|America/Indiana/Petersburg", "America/New_York|America/Indiana/Vevay", "America/New_York|America/Indiana/Vincennes", "America/New_York|America/Indiana/Winamac", "America/New_York|America/Indianapolis", "America/New_York|America/Iqaluit", "America/New_York|America/Kentucky/Louisville", "America/New_York|America/Kentucky/Monticello", "America/New_York|America/Louisville", "America/New_York|America/Montreal", "America/New_York|America/Nassau", "America/New_York|America/Nipigon", "America/New_York|America/Pangnirtung", "America/New_York|America/Thunder_Bay", "America/New_York|America/Toronto", "America/New_York|Canada/Eastern", "America/New_York|EST5EDT", "America/New_York|US/East-Indiana", "America/New_York|US/Eastern", "America/New_York|US/Michigan", "America/Noronha|Brazil/DeNoronha", "America/Panama|America/Atikokan", "America/Panama|America/Coral_Harbour", "America/Panama|America/Jamaica", "America/Panama|EST", "America/Panama|Jamaica", "America/Phoenix|America/Creston", "America/Phoenix|America/Dawson_Creek", "America/Phoenix|America/Hermosillo", "America/Phoenix|MST", "America/Phoenix|US/Arizona", "America/Rio_Branco|America/Eirunepe", "America/Rio_Branco|America/Porto_Acre", "America/Rio_Branco|Brazil/Acre", "America/Santiago|Antarctica/Palmer", "America/Santiago|Chile/Continental", "America/Santo_Domingo|America/Anguilla", "America/Santo_Domingo|America/Antigua", "America/Santo_Domingo|America/Aruba", "America/Santo_Domingo|America/Barbados", "America/Santo_Domingo|America/Blanc-Sablon", "America/Santo_Domingo|America/Curacao", "America/Santo_Domingo|America/Dominica", "America/Santo_Domingo|America/Grenada", "America/Santo_Domingo|America/Guadeloupe", "America/Santo_Domingo|America/Kralendijk", "America/Santo_Domingo|America/Lower_Princes", "America/Santo_Domingo|America/Marigot", "America/Santo_Domingo|America/Martinique", "America/Santo_Domingo|America/Montserrat", "America/Santo_Domingo|America/Port_of_Spain", "America/Santo_Domingo|America/Puerto_Rico", "America/Santo_Domingo|America/St_Barthelemy", "America/Santo_Domingo|America/St_Kitts", "America/Santo_Domingo|America/St_Lucia", "America/Santo_Domingo|America/St_Thomas", "America/Santo_Domingo|America/St_Vincent", "America/Santo_Domingo|America/Tortola", "America/Santo_Domingo|America/Virgin", "America/Sao_Paulo|Brazil/East", "America/St_Johns|Canada/Newfoundland", "Asia/Aqtobe|Asia/Aqtau", "Asia/Ashgabat|Asia/Ashkhabad", "Asia/Baghdad|Asia/Aden", "Asia/Baghdad|Asia/Bahrain", "Asia/Baghdad|Asia/Kuwait", "Asia/Baghdad|Asia/Qatar", "Asia/Baghdad|Asia/Riyadh", "Asia/Bangkok|Asia/Ho_Chi_Minh", "Asia/Bangkok|Asia/Phnom_Penh", "Asia/Bangkok|Asia/Saigon", "Asia/Bangkok|Asia/Vientiane", "Asia/Dhaka|Asia/Dacca", "Asia/Dubai|Asia/Muscat", "Asia/Hong_Kong|Hongkong", "Asia/Jakarta|Asia/Pontianak", "Asia/Jerusalem|Asia/Tel_Aviv", "Asia/Jerusalem|Israel", "Asia/Kathmandu|Asia/Katmandu", "Asia/Kolkata|Asia/Calcutta", "Asia/Kolkata|Asia/Colombo", "Asia/Kuala_Lumpur|Asia/Kuching", "Asia/Makassar|Asia/Ujung_Pandang", "Asia/Seoul|ROK", "Asia/Shanghai|Asia/Chongqing", "Asia/Shanghai|Asia/Chungking", "Asia/Shanghai|Asia/Harbin", "Asia/Shanghai|Asia/Macao", "Asia/Shanghai|Asia/Macau", "Asia/Shanghai|Asia/Taipei", "Asia/Shanghai|PRC", "Asia/Shanghai|ROC", "Asia/Singapore|Singapore", "Asia/Tashkent|Asia/Samarkand", "Asia/Tehran|Iran", "Asia/Thimphu|Asia/Thimbu", "Asia/Tokyo|Japan", "Asia/Ulaanbaatar|Asia/Ulan_Bator", "Asia/Urumqi|Asia/Kashgar", "Australia/Adelaide|Australia/Broken_Hill", "Australia/Adelaide|Australia/South", "Australia/Adelaide|Australia/Yancowinna", "Australia/Brisbane|Australia/Lindeman", "Australia/Brisbane|Australia/Queensland", "Australia/Darwin|Australia/North", "Australia/Lord_Howe|Australia/LHI", "Australia/Perth|Australia/West", "Australia/Sydney|Australia/ACT", "Australia/Sydney|Australia/Canberra", "Australia/Sydney|Australia/Currie", "Australia/Sydney|Australia/Hobart", "Australia/Sydney|Australia/Melbourne", "Australia/Sydney|Australia/NSW", "Australia/Sydney|Australia/Tasmania", "Australia/Sydney|Australia/Victoria", "Etc/UCT|UCT", "Etc/UTC|Etc/Universal", "Etc/UTC|Etc/Zulu", "Etc/UTC|UTC", "Etc/UTC|Universal", "Etc/UTC|Zulu", "Europe/Athens|Asia/Nicosia", "Europe/Athens|EET", "Europe/Athens|Europe/Bucharest", "Europe/Athens|Europe/Helsinki", "Europe/Athens|Europe/Kiev", "Europe/Athens|Europe/Mariehamn", "Europe/Athens|Europe/Nicosia", "Europe/Athens|Europe/Riga", "Europe/Athens|Europe/Sofia", "Europe/Athens|Europe/Tallinn", "Europe/Athens|Europe/Uzhgorod", "Europe/Athens|Europe/Vilnius", "Europe/Athens|Europe/Zaporozhye", "Europe/Chisinau|Europe/Tiraspol", "Europe/Dublin|Eire", "Europe/Istanbul|Asia/Istanbul", "Europe/Istanbul|Turkey", "Europe/Lisbon|Atlantic/Canary", "Europe/Lisbon|Atlantic/Faeroe", "Europe/Lisbon|Atlantic/Faroe", "Europe/Lisbon|Atlantic/Madeira", "Europe/Lisbon|Portugal", "Europe/Lisbon|WET", "Europe/London|Europe/Belfast", "Europe/London|Europe/Guernsey", "Europe/London|Europe/Isle_of_Man", "Europe/London|Europe/Jersey", "Europe/London|GB", "Europe/London|GB-Eire", "Europe/Moscow|Europe/Volgograd", "Europe/Moscow|W-SU", "Europe/Paris|Africa/Ceuta", "Europe/Paris|Arctic/Longyearbyen", "Europe/Paris|Atlantic/Jan_Mayen", "Europe/Paris|CET", "Europe/Paris|Europe/Amsterdam", "Europe/Paris|Europe/Andorra", "Europe/Paris|Europe/Belgrade", "Europe/Paris|Europe/Berlin", "Europe/Paris|Europe/Bratislava", "Europe/Paris|Europe/Brussels", "Europe/Paris|Europe/Budapest", "Europe/Paris|Europe/Busingen", "Europe/Paris|Europe/Copenhagen", "Europe/Paris|Europe/Gibraltar", "Europe/Paris|Europe/Ljubljana", "Europe/Paris|Europe/Luxembourg", "Europe/Paris|Europe/Madrid", "Europe/Paris|Europe/Malta", "Europe/Paris|Europe/Monaco", "Europe/Paris|Europe/Oslo", "Europe/Paris|Europe/Podgorica", "Europe/Paris|Europe/Prague", "Europe/Paris|Europe/Rome", "Europe/Paris|Europe/San_Marino", "Europe/Paris|Europe/Sarajevo", "Europe/Paris|Europe/Skopje", "Europe/Paris|Europe/Stockholm", "Europe/Paris|Europe/Tirane", "Europe/Paris|Europe/Vaduz", "Europe/Paris|Europe/Vatican", "Europe/Paris|Europe/Vienna", "Europe/Paris|Europe/Warsaw", "Europe/Paris|Europe/Zagreb", "Europe/Paris|Europe/Zurich", "Europe/Paris|Poland", "Pacific/Auckland|Antarctica/McMurdo", "Pacific/Auckland|Antarctica/South_Pole", "Pacific/Auckland|NZ", "Pacific/Chatham|NZ-CHAT", "Pacific/Chuuk|Pacific/Truk", "Pacific/Chuuk|Pacific/Yap", "Pacific/Easter|Chile/EasterIsland", "Pacific/Guam|Pacific/Saipan", "Pacific/Honolulu|HST", "Pacific/Honolulu|Pacific/Johnston", "Pacific/Honolulu|US/Hawaii", "Pacific/Majuro|Kwajalein", "Pacific/Majuro|Pacific/Kwajalein", "Pacific/Pago_Pago|Pacific/Midway", "Pacific/Pago_Pago|Pacific/Samoa", "Pacific/Pago_Pago|US/Samoa", "Pacific/Pohnpei|Pacific/Ponape"]
}), a
});
/*
jquery-circle-progress - jQuery Plugin to draw animated circular progress bars
URL: http://kottenator.github.io/jquery-circle-progress/
Author: Rostyslav Bryzgunov
Version: 1.1.2
License: MIT
*/
(function ($) {
function CircleProgress(config) {
this.init(config);
}
CircleProgress.prototype = {
//----------------------------------------------- public options -----------------------------------------------
/**
* This is the only required option. It should be from 0.0 to 1.0
* @type {number}
*/
value: 0.0,
/**
* Size of the circle / canvas in pixels
* @type {number}
*/
size: 100.0,
/**
* Initial angle for 0.0 value in radians
* @type {number}
*/
startAngle: -Math.PI,
/**
* Width of the arc. By default it's auto-calculated as 1/14 of size, but you may set it explicitly in pixels
* @type {number|string}
*/
thickness: 'auto',
/**
* Border around the arc. This is applied to the empty circle, and is added to the thickness
* @type {number|string}
*/
border: 0.0,
/**
* Fill of the arc. You may set it to:
* - solid color:
* - { color: '#3aeabb' }
* - { color: 'rgba(255, 255, 255, .3)' }
* - linear gradient (left to right):
* - { gradient: ['#3aeabb', '#fdd250'], gradientAngle: Math.PI / 4 }
* - { gradient: ['red', 'green', 'blue'], gradientDirection: [x0, y0, x1, y1] }
* - image:
* - { image: 'http://i.imgur.com/pT0i89v.png' }
* - { image: imageObject }
* - { color: 'lime', image: 'http://i.imgur.com/pT0i89v.png' } - color displayed until the image is loaded
*/
fill: {
gradient: ['#3aeabb', '#fdd250']
},
/**
* Color of the "empty" arc. Only a color fill supported by now
* @type {string}
*/
emptyFill: 'rgba(0, 0, 0, .1)',
/**
* Animation config (see jQuery animations: http://api.jquery.com/animate/)
*/
animation: {
duration: 1200,
easing: 'circleProgressEasing'
},
/**
* Default animation starts at 0.0 and ends at specified `value`. Let's call this direct animation.
* If you want to make reversed animation then you should set `animationStartValue` to 1.0.
* Also you may specify any other value from 0.0 to 1.0
* @type {number}
*/
animationStartValue: 0.0,
/**
* Reverse animation and arc draw
* @type {boolean}
*/
reverse: false,
/**
* Arc line cap ('butt' (default), 'round' and 'square')
* Read more: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.lineCap
* @type {string}
*/
lineCap: 'butt',
//-------------------------------------- protected properties and methods --------------------------------------
/**
* @protected
*/
constructor: CircleProgress,
/**
* Container element. Should be passed into constructor config
* @protected
* @type {jQuery}
*/
el: null,
/**
* Canvas element. Automatically generated and prepended to the {@link CircleProgress.el container}
* @protected
* @type {HTMLCanvasElement}
*/
canvas: null,
/**
* 2D-context of the {@link CircleProgress.canvas canvas}
* @protected
* @type {CanvasRenderingContext2D}
*/
ctx: null,
/**
* Radius of the outer circle. Automatically calculated as {@link CircleProgress.size} / 2
* @protected
* @type {number}
*/
radius: 0.0,
/**
* Fill of the main arc. Automatically calculated, depending on {@link CircleProgress.fill} option
* @protected
* @type {string|CanvasGradient|CanvasPattern}
*/
arcFill: null,
/**
* Last rendered frame value
* @protected
* @type {number}
*/
lastFrameValue: 0.0,
/**
* Init/re-init the widget
* @param {object} config Config
*/
init: function (config) {
$.extend(this, config);
this.radius = this.size / 2;
this.initWidget();
this.initFill();
this.draw();
},
/**
* @protected
*/
initWidget: function () {
var canvas = this.canvas = this.canvas || $('').prependTo(this.el)[0];
canvas.width = this.size;
canvas.height = this.size;
this.ctx = canvas.getContext('2d');
},
/**
* This method sets {@link CircleProgress.arcFill}
* It could do this async (on image load)
* @protected
*/
initFill: function () {
var self = this,
fill = this.fill,
ctx = this.ctx,
size = this.size;
if (!fill)
throw Error("The fill is not specified!");
if (fill.color)
this.arcFill = fill.color;
if (fill.gradient) {
var gr = fill.gradient;
if (gr.length == 1) {
this.arcFill = gr[0];
} else if (gr.length > 1) {
var ga = fill.gradientAngle || 0, // gradient direction angle; 0 by default
gd = fill.gradientDirection || [
size / 2 * (1 - Math.cos(ga)), // x0
size / 2 * (1 + Math.sin(ga)), // y0
size / 2 * (1 + Math.cos(ga)), // x1
size / 2 * (1 - Math.sin(ga)) // y1
];
var lg = ctx.createLinearGradient.apply(ctx, gd);
for (var i = 0; i < gr.length; i++) {
var color = gr[i],
pos = i / (gr.length - 1);
if ($.isArray(color)) {
pos = color[1];
color = color[0];
}
lg.addColorStop(pos, color);
}
this.arcFill = lg;
}
}
if (fill.image) {
var img;
if (fill.image instanceof Image) {
img = fill.image;
} else {
img = new Image();
img.src = fill.image;
}
if (img.complete)
setImageFill();
else
img.onload = setImageFill;
}
function setImageFill() {
var bg = $('')[0];
bg.width = self.size;
bg.height = self.size;
bg.getContext('2d').drawImage(img, 0, 0, size, size);
self.arcFill = self.ctx.createPattern(bg, 'no-repeat');
self.drawFrame(self.lastFrameValue);
}
},
draw: function () {
if (this.animation)
this.drawAnimated(this.value);
else
this.drawFrame(this.value);
},
/**
* @protected
* @param {number} v Frame value
*/
drawFrame: function (v) {
this.lastFrameValue = v;
this.ctx.clearRect(0, 0, this.size, this.size);
this.drawEmptyArc(v);
this.drawArc(v);
},
/**
* @protected
* @param {number} v Frame value
*/
drawArc: function (v) {
var ctx = this.ctx,
r = this.radius,
t = this.getThickness(),
a = this.startAngle;
ctx.save();
ctx.beginPath();
if (!this.reverse) {
ctx.arc(r, r, r - t / 2 - this.border, a, a + Math.PI * 2 * v);
} else {
ctx.arc(r, r, r - t / 2 - this.border, a - Math.PI * 2 * v, a);
}
ctx.lineWidth = t;
ctx.lineCap = this.lineCap;
ctx.strokeStyle = this.arcFill;
ctx.stroke();
ctx.restore();
},
/**
* @protected
* @param {number} v Frame value
*/
drawEmptyArc: function (v) {
var ctx = this.ctx,
r = this.radius,
t = this.getThickness() + (this.border * 2),
a = this.startAngle;
if (v < 1) {
ctx.save();
ctx.beginPath();
if (this.border > 0 || v <= 0) {
// draw the empty circle a full 360 degrees
// this is necessary if there is a border
ctx.arc(r, r, r - t / 2, 0, Math.PI * 2);
} else {
// draw the empty circle as an arc
if (!this.reverse) {
ctx.arc(r, r, r - t / 2, a + Math.PI * 2 * v, a);
} else {
ctx.arc(r, r, r - t / 2, a, a - Math.PI * 2 * v);
}
}
ctx.lineWidth = t;
ctx.strokeStyle = this.emptyFill;
ctx.stroke();
ctx.restore();
}
},
/**
* @protected
* @param {number} v Value
*/
drawAnimated: function (v) {
var self = this,
el = this.el;
el.trigger('circle-animation-start');
$(this.canvas)
.stop(true, true)
.css({ animationProgress: 0 })
.animate({ animationProgress: 1 }, $.extend({}, this.animation, {
step: function (animationProgress) {
var stepValue = self.animationStartValue * (1 - animationProgress) + v * animationProgress;
self.drawFrame(stepValue);
el.trigger('circle-animation-progress', [animationProgress, stepValue]);
},
complete: function () {
el.trigger('circle-animation-end');
}
}));
},
/**
* @protected
* @returns {number}
*/
getThickness: function () {
return $.isNumeric(this.thickness) ? this.thickness : this.size / 14;
}
};
//-------------------------------------------- Initiating jQuery plugin --------------------------------------------
$.circleProgress = {
// Default options (you may override them)
defaults: CircleProgress.prototype
};
// ease-in-out-cubic
$.easing.circleProgressEasing = function (x, t, b, c, d) {
if ((t /= d / 2) < 1)
return c / 2 * t * t * t + b;
return c / 2 * ((t -= 2) * t * t + 2) + b;
};
/**
* Draw animated circular progress bar.
*
* Appends to the element or updates already appended one.
*
* If animated, throws 3 events:
*
* - circle-animation-start(jqEvent)
* - circle-animation-progress(jqEvent, animationProgress, stepValue) - multiple event;
* animationProgress: from 0.0 to 1.0;
* stepValue: from 0.0 to value
* - circle-animation-end(jqEvent)
*
* @param config Example: { value: 0.75, size: 50, animation: false };
* you may set any of public options;
* `animation` may be set to false;
* you may also use .circleProgress('widget') to get the canvas
*/
$.fn.circleProgress = function (config) {
var dataName = 'circle-progress';
if (config == 'widget') {
var data = this.data(dataName);
return data && data.canvas;
}
return this.each(function () {
var el = $(this),
instance = el.data(dataName),
cfg = $.isPlainObject(config) ? config : {};
if (instance) {
instance.init(cfg);
} else {
cfg.el = el;
instance = new CircleProgress(cfg);
el.data(dataName, instance);
}
});
};
})(jQuery);
/*!
* headroom.js v0.7.0 - Give your page some headroom. Hide your header until you need it
* Copyright (c) 2014 Nick Williams - http://wicky.nillia.ms/headroom.js
* License: MIT
*/
(function (window, document) {
'use strict';
/* exported features */
var features = {
bind: !!(function () { }.bind),
classList: 'classList' in document.documentElement,
rAF: !!(window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame)
};
window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
/**
* Handles debouncing of events via requestAnimationFrame
* @see http://www.html5rocks.com/en/tutorials/speed/animations/
* @param {Function} callback The callback to handle whichever event
*/
function Debouncer(callback) {
this.callback = callback;
this.ticking = false;
}
Debouncer.prototype = {
constructor: Debouncer,
/**
* dispatches the event to the supplied callback
* @private
*/
update: function () {
this.callback && this.callback();
this.ticking = false;
},
/**
* ensures events don't get stacked
* @private
*/
requestTick: function () {
if (!this.ticking) {
requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this)));
this.ticking = true;
}
},
/**
* Attach this as the event listeners
*/
handleEvent: function () {
this.requestTick();
}
};
/**
* Check if object is part of the DOM
* @constructor
* @param {Object} obj element to check
*/
function isDOMElement(obj) {
return obj && typeof window !== 'undefined' && (obj === window || obj.nodeType);
}
/**
* Helper function for extending objects
*/
function extend(object /*, objectN ... */) {
if (arguments.length <= 0) {
throw new Error('Missing arguments in extend function');
}
var result = object || {},
key,
i;
for (i = 1; i < arguments.length; i++) {
var replacement = arguments[i] || {};
for (key in replacement) {
// Recurse into object except if the object is a DOM element
if (typeof result[key] === 'object' && !isDOMElement(result[key])) {
result[key] = extend(result[key], replacement[key]);
}
else {
result[key] = result[key] || replacement[key];
}
}
}
return result;
}
/**
* Helper function for normalizing tolerance option to object format
*/
function normalizeTolerance(t) {
return t === Object(t) ? t : { down: t, up: t };
}
/**
* UI enhancement for fixed headers.
* Hides header when scrolling down
* Shows header when scrolling up
* @constructor
* @param {DOMElement} elem the header element
* @param {Object} options options for the widget
*/
function Headroom(elem, options) {
options = extend(options, Headroom.options);
this.lastKnownScrollY = 0;
this.elem = elem;
this.debouncer = new Debouncer(this.update.bind(this));
this.tolerance = normalizeTolerance(options.tolerance);
this.classes = options.classes;
this.offset = options.offset;
this.scroller = options.scroller;
this.initialised = false;
this.onPin = options.onPin;
this.onUnpin = options.onUnpin;
this.onTop = options.onTop;
this.onNotTop = options.onNotTop;
}
Headroom.prototype = {
constructor: Headroom,
/**
* Initialises the widget
*/
init: function () {
if (!Headroom.cutsTheMustard) {
return;
}
this.elem.classList.add(this.classes.initial);
// defer event registration to handle browser
// potentially restoring previous scroll position
setTimeout(this.attachEvent.bind(this), 100);
return this;
},
/**
* Unattaches events and removes any classes that were added
*/
destroy: function () {
var classes = this.classes;
this.initialised = false;
this.elem.classList.remove(classes.unpinned, classes.pinned, classes.top, classes.initial);
this.scroller.removeEventListener('scroll', this.debouncer, false);
},
/**
* Attaches the scroll event
* @private
*/
attachEvent: function () {
if (!this.initialised) {
this.lastKnownScrollY = this.getScrollY();
this.initialised = true;
this.scroller.addEventListener('scroll', this.debouncer, false);
this.debouncer.handleEvent();
}
},
/**
* Unpins the header if it's currently pinned
*/
unpin: function () {
var classList = this.elem.classList,
classes = this.classes;
if (classList.contains(classes.pinned) || !classList.contains(classes.unpinned)) {
classList.add(classes.unpinned);
classList.remove(classes.pinned);
this.onUnpin && this.onUnpin.call(this);
}
},
/**
* Pins the header if it's currently unpinned
*/
pin: function () {
var classList = this.elem.classList,
classes = this.classes;
if (classList.contains(classes.unpinned)) {
classList.remove(classes.unpinned);
classList.add(classes.pinned);
this.onPin && this.onPin.call(this);
}
},
/**
* Handles the top states
*/
top: function () {
var classList = this.elem.classList,
classes = this.classes;
if (!classList.contains(classes.top)) {
classList.add(classes.top);
classList.remove(classes.notTop);
this.onTop && this.onTop.call(this);
}
},
/**
* Handles the not top state
*/
notTop: function () {
var classList = this.elem.classList,
classes = this.classes;
if (!classList.contains(classes.notTop)) {
classList.add(classes.notTop);
classList.remove(classes.top);
this.onNotTop && this.onNotTop.call(this);
}
},
/**
* Gets the Y scroll position
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY
* @return {Number} pixels the page has scrolled along the Y-axis
*/
getScrollY: function () {
return (this.scroller.pageYOffset !== undefined)
? this.scroller.pageYOffset
: (this.scroller.scrollTop !== undefined)
? this.scroller.scrollTop
: (document.documentElement || document.body.parentNode || document.body).scrollTop;
},
/**
* Gets the height of the viewport
* @see http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript
* @return {int} the height of the viewport in pixels
*/
getViewportHeight: function () {
return window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
},
/**
* Gets the height of the document
* @see http://james.padolsey.com/javascript/get-document-height-cross-browser/
* @return {int} the height of the document in pixels
*/
getDocumentHeight: function () {
var body = document.body,
documentElement = document.documentElement;
return Math.max(
body.scrollHeight, documentElement.scrollHeight,
body.offsetHeight, documentElement.offsetHeight,
body.clientHeight, documentElement.clientHeight
);
},
/**
* Gets the height of the DOM element
* @param {Object} elm the element to calculate the height of which
* @return {int} the height of the element in pixels
*/
getElementHeight: function (elm) {
return Math.max(
elm.scrollHeight,
elm.offsetHeight,
elm.clientHeight
);
},
/**
* Gets the height of the scroller element
* @return {int} the height of the scroller element in pixels
*/
getScrollerHeight: function () {
return (this.scroller === window || this.scroller === document.body)
? this.getDocumentHeight()
: this.getElementHeight(this.scroller);
},
/**
* determines if the scroll position is outside of document boundaries
* @param {int} currentScrollY the current y scroll position
* @return {bool} true if out of bounds, false otherwise
*/
isOutOfBounds: function (currentScrollY) {
var pastTop = currentScrollY < 0,
pastBottom = currentScrollY + this.getViewportHeight() > this.getScrollerHeight();
return pastTop || pastBottom;
},
/**
* determines if the tolerance has been exceeded
* @param {int} currentScrollY the current scroll y position
* @return {bool} true if tolerance exceeded, false otherwise
*/
toleranceExceeded: function (currentScrollY, direction) {
return Math.abs(currentScrollY - this.lastKnownScrollY) >= this.tolerance[direction];
},
/**
* determine if it is appropriate to unpin
* @param {int} currentScrollY the current y scroll position
* @param {bool} toleranceExceeded has the tolerance been exceeded?
* @return {bool} true if should unpin, false otherwise
*/
shouldUnpin: function (currentScrollY, toleranceExceeded) {
var scrollingDown = currentScrollY > this.lastKnownScrollY,
pastOffset = currentScrollY >= this.offset;
return scrollingDown && pastOffset && toleranceExceeded;
},
/**
* determine if it is appropriate to pin
* @param {int} currentScrollY the current y scroll position
* @param {bool} toleranceExceeded has the tolerance been exceeded?
* @return {bool} true if should pin, false otherwise
*/
shouldPin: function (currentScrollY, toleranceExceeded) {
var scrollingUp = currentScrollY < this.lastKnownScrollY,
pastOffset = currentScrollY <= this.offset;
return (scrollingUp && toleranceExceeded) || pastOffset;
},
/**
* Handles updating the state of the widget
*/
update: function () {
var currentScrollY = this.getScrollY(),
scrollDirection = currentScrollY > this.lastKnownScrollY ? 'down' : 'up',
toleranceExceeded = this.toleranceExceeded(currentScrollY, scrollDirection);
if (this.isOutOfBounds(currentScrollY)) { // Ignore bouncy scrolling in OSX
return;
}
if (currentScrollY <= this.offset) {
this.top();
} else {
this.notTop();
}
if (this.shouldUnpin(currentScrollY, toleranceExceeded)) {
this.unpin();
}
else if (this.shouldPin(currentScrollY, toleranceExceeded)) {
this.pin();
}
this.lastKnownScrollY = currentScrollY;
}
};
/**
* Default options
* @type {Object}
*/
Headroom.options = {
tolerance: {
up: 0,
down: 0
},
offset: 0,
scroller: window,
classes: {
pinned: 'headroom--pinned',
unpinned: 'headroom--unpinned',
top: 'headroom--top',
notTop: 'headroom--not-top',
initial: 'headroom'
}
};
Headroom.cutsTheMustard = typeof features !== 'undefined' && features.rAF && features.bind && features.classList;
window.Headroom = Headroom;
}(window, document));
/*!
* headroom.js v0.7.0 - Give your page some headroom. Hide your header until you need it
* Copyright (c) 2014 Nick Williams - http://wicky.nillia.ms/headroom.js
* License: MIT
*/
(function ($) {
if (!$) {
return;
}
////////////
// Plugin //
////////////
$.fn.headroom = function (option) {
return this.each(function () {
var $this = $(this),
data = $this.data('headroom'),
options = typeof option === 'object' && option;
options = $.extend(true, {}, Headroom.options, options);
if (!data) {
data = new Headroom(this, options);
data.init();
$this.data('headroom', data);
}
if (typeof option === 'string') {
data[option]();
}
});
};
//////////////
// Data API //
//////////////
$('[data-headroom]').each(function () {
var $this = $(this);
$this.headroom($this.data());
});
}(window.Zepto || window.jQuery));
/**
* jquery.matchHeight.js master
* http://brm.io/jquery-match-height/
* License: MIT
*/
; (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._groups = [];
matchHeight._throttle = 80;
matchHeight._maintainScroll = false;
matchHeight._beforeUpdate = null;
matchHeight._afterUpdate = null;
/*
* 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') === 'inline-block' ? 'inline-block' : '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'
});
});
// 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),
display = $that.css('display') === 'inline-block' ? 'inline-block' : '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 display block
$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);
});
});
// 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);
});
})(jQuery);
/*
_ _ _ _
___| (_) ___| | __ (_)___
/ __| | |/ __| |/ / | / __|
\__ \ | | (__| < _ | \__ \
|___/_|_|\___|_|\_(_)/ |___/
|__/
Version: 1.5.8
Author: Ken Wheeler
Website: http://kenwheeler.github.io
Docs: http://kenwheeler.github.io/slick
Repo: http://github.com/kenwheeler/slick
Issues: http://github.com/kenwheeler/slick/issues
*/
/* global window, document, define, jQuery, setInterval, clearInterval */
(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof exports !== 'undefined') {
module.exports = factory(require('jquery'));
} else {
factory(jQuery);
}
}(function ($) {
'use strict';
var Slick = window.Slick || {};
Slick = (function () {
var instanceUid = 0;
function Slick(element, settings) {
var _ = this, dataSettings;
_.defaults = {
accessibility: true,
adaptiveHeight: false,
appendArrows: $(element),
appendDots: $(element),
arrows: true,
asNavFor: null,
prevArrow: 'Previous ',
nextArrow: 'Next ',
autoplay: false,
autoplaySpeed: 3000,
centerMode: false,
centerPadding: '50px',
cssEase: 'ease',
customPaging: function (slider, i) {
return '' + (i + 1) + ' ';
},
dots: false,
dotsClass: 'slick-dots',
draggable: true,
easing: 'linear',
edgeFriction: 0.35,
fade: false,
focusOnSelect: false,
infinite: true,
initialSlide: 0,
lazyLoad: 'ondemand',
mobileFirst: false,
pauseOnHover: true,
pauseOnDotsHover: false,
respondTo: 'window',
responsive: null,
rows: 1,
rtl: false,
slide: '',
slidesPerRow: 1,
slidesToShow: 1,
slidesToScroll: 1,
speed: 500,
swipe: true,
swipeToSlide: false,
touchMove: true,
touchThreshold: 5,
useCSS: true,
variableWidth: false,
vertical: false,
verticalSwiping: false,
waitForAnimate: true,
zIndex: 1000
};
_.initials = {
animating: false,
dragging: false,
autoPlayTimer: null,
currentDirection: 0,
currentLeft: null,
currentSlide: 0,
direction: 1,
$dots: null,
listWidth: null,
listHeight: null,
loadIndex: 0,
$nextArrow: null,
$prevArrow: null,
slideCount: null,
slideWidth: null,
$slideTrack: null,
$slides: null,
sliding: false,
slideOffset: 0,
swipeLeft: null,
$list: null,
touchObject: {},
transformsEnabled: false,
unslicked: false
};
$.extend(_, _.initials);
_.activeBreakpoint = null;
_.animType = null;
_.animProp = null;
_.breakpoints = [];
_.breakpointSettings = [];
_.cssTransitions = false;
_.hidden = 'hidden';
_.paused = false;
_.positionProp = null;
_.respondTo = null;
_.rowCount = 1;
_.shouldClick = true;
_.$slider = $(element);
_.$slidesCache = null;
_.transformType = null;
_.transitionType = null;
_.visibilityChange = 'visibilitychange';
_.windowWidth = 0;
_.windowTimer = null;
dataSettings = $(element).data('slick') || {};
_.options = $.extend({}, _.defaults, dataSettings, settings);
_.currentSlide = _.options.initialSlide;
_.originalSettings = _.options;
if (typeof document.mozHidden !== 'undefined') {
_.hidden = 'mozHidden';
_.visibilityChange = 'mozvisibilitychange';
} else if (typeof document.webkitHidden !== 'undefined') {
_.hidden = 'webkitHidden';
_.visibilityChange = 'webkitvisibilitychange';
}
_.autoPlay = $.proxy(_.autoPlay, _);
_.autoPlayClear = $.proxy(_.autoPlayClear, _);
_.changeSlide = $.proxy(_.changeSlide, _);
_.clickHandler = $.proxy(_.clickHandler, _);
_.selectHandler = $.proxy(_.selectHandler, _);
_.setPosition = $.proxy(_.setPosition, _);
_.swipeHandler = $.proxy(_.swipeHandler, _);
_.dragHandler = $.proxy(_.dragHandler, _);
_.keyHandler = $.proxy(_.keyHandler, _);
_.autoPlayIterator = $.proxy(_.autoPlayIterator, _);
_.instanceUid = instanceUid++;
// A simple way to check for HTML strings
// Strict HTML recognition (must start with <)
// Extracted from jQuery v1.11 source
_.htmlExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/;
_.registerBreakpoints();
_.init(true);
_.checkResponsive(true);
}
return Slick;
}());
Slick.prototype.addSlide = Slick.prototype.slickAdd = function (markup, index, addBefore) {
var _ = this;
if (typeof (index) === 'boolean') {
addBefore = index;
index = null;
} else if (index < 0 || (index >= _.slideCount)) {
return false;
}
_.unload();
if (typeof (index) === 'number') {
if (index === 0 && _.$slides.length === 0) {
$(markup).appendTo(_.$slideTrack);
} else if (addBefore) {
$(markup).insertBefore(_.$slides.eq(index));
} else {
$(markup).insertAfter(_.$slides.eq(index));
}
} else {
if (addBefore === true) {
$(markup).prependTo(_.$slideTrack);
} else {
$(markup).appendTo(_.$slideTrack);
}
}
_.$slides = _.$slideTrack.children(this.options.slide);
_.$slideTrack.children(this.options.slide).detach();
_.$slideTrack.append(_.$slides);
_.$slides.each(function (index, element) {
$(element).attr('data-slick-index', index);
});
_.$slidesCache = _.$slides;
_.reinit();
};
Slick.prototype.animateHeight = function () {
var _ = this;
if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {
var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);
_.$list.animate({
height: targetHeight
}, _.options.speed);
}
};
Slick.prototype.animateSlide = function (targetLeft, callback) {
var animProps = {},
_ = this;
_.animateHeight();
if (_.options.rtl === true && _.options.vertical === false) {
targetLeft = -targetLeft;
}
if (_.transformsEnabled === false) {
if (_.options.vertical === false) {
_.$slideTrack.animate({
left: targetLeft
}, _.options.speed, _.options.easing, callback);
} else {
_.$slideTrack.animate({
top: targetLeft
}, _.options.speed, _.options.easing, callback);
}
} else {
if (_.cssTransitions === false) {
if (_.options.rtl === true) {
_.currentLeft = -(_.currentLeft);
}
$({
animStart: _.currentLeft
}).animate({
animStart: targetLeft
}, {
duration: _.options.speed,
easing: _.options.easing,
step: function (now) {
now = Math.ceil(now);
if (_.options.vertical === false) {
animProps[_.animType] = 'translate(' +
now + 'px, 0px)';
_.$slideTrack.css(animProps);
} else {
animProps[_.animType] = 'translate(0px,' +
now + 'px)';
_.$slideTrack.css(animProps);
}
},
complete: function () {
if (callback) {
callback.call();
}
}
});
} else {
_.applyTransition();
targetLeft = Math.ceil(targetLeft);
if (_.options.vertical === false) {
animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)';
} else {
animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)';
}
_.$slideTrack.css(animProps);
if (callback) {
setTimeout(function () {
_.disableTransition();
callback.call();
}, _.options.speed);
}
}
}
};
Slick.prototype.asNavFor = function (index) {
var _ = this,
asNavFor = _.options.asNavFor;
if (asNavFor && asNavFor !== null) {
asNavFor = $(asNavFor).not(_.$slider);
}
if (asNavFor !== null && typeof asNavFor === 'object') {
asNavFor.each(function () {
var target = $(this).slick('getSlick');
if (!target.unslicked) {
target.slideHandler(index, true);
}
});
}
};
Slick.prototype.applyTransition = function (slide) {
var _ = this,
transition = {};
if (_.options.fade === false) {
transition[_.transitionType] = _.transformType + ' ' + _.options.speed + 'ms ' + _.options.cssEase;
} else {
transition[_.transitionType] = 'opacity ' + _.options.speed + 'ms ' + _.options.cssEase;
}
if (_.options.fade === false) {
_.$slideTrack.css(transition);
} else {
_.$slides.eq(slide).css(transition);
}
};
Slick.prototype.autoPlay = function () {
var _ = this;
if (_.autoPlayTimer) {
clearInterval(_.autoPlayTimer);
}
if (_.slideCount > _.options.slidesToShow && _.paused !== true) {
_.autoPlayTimer = setInterval(_.autoPlayIterator,
_.options.autoplaySpeed);
}
};
Slick.prototype.autoPlayClear = function () {
var _ = this;
if (_.autoPlayTimer) {
clearInterval(_.autoPlayTimer);
}
};
Slick.prototype.autoPlayIterator = function () {
var _ = this;
if (_.options.infinite === false) {
if (_.direction === 1) {
if ((_.currentSlide + 1) === _.slideCount -
1) {
_.direction = 0;
}
_.slideHandler(_.currentSlide + _.options.slidesToScroll);
} else {
if ((_.currentSlide - 1 === 0)) {
_.direction = 1;
}
_.slideHandler(_.currentSlide - _.options.slidesToScroll);
}
} else {
_.slideHandler(_.currentSlide + _.options.slidesToScroll);
}
};
Slick.prototype.buildArrows = function () {
var _ = this;
if (_.options.arrows === true) {
_.$prevArrow = $(_.options.prevArrow).addClass('slick-arrow');
_.$nextArrow = $(_.options.nextArrow).addClass('slick-arrow');
if (_.slideCount > _.options.slidesToShow) {
_.$prevArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex');
_.$nextArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex');
if (_.htmlExpr.test(_.options.prevArrow)) {
_.$prevArrow.prependTo(_.options.appendArrows);
}
if (_.htmlExpr.test(_.options.nextArrow)) {
_.$nextArrow.appendTo(_.options.appendArrows);
}
if (_.options.infinite !== true) {
_.$prevArrow
.addClass('slick-disabled')
.attr('aria-disabled', 'true');
}
} else {
_.$prevArrow.add(_.$nextArrow)
.addClass('slick-hidden')
.attr({
'aria-disabled': 'true',
'tabindex': '-1'
});
}
}
};
Slick.prototype.buildDots = function () {
var _ = this,
i, dotString;
if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
dotString = '';
for (i = 0; i <= _.getDotCount() ; i += 1) {
dotString += '' + _.options.customPaging.call(this, _, i) + ' ';
}
dotString += ' ';
_.$dots = $(dotString).appendTo(
_.options.appendDots);
_.$dots.find('li').first().addClass('slick-active').attr('aria-hidden', 'false');
}
};
Slick.prototype.buildOut = function () {
var _ = this;
_.$slides =
_.$slider
.children(_.options.slide + ':not(.slick-cloned)')
.addClass('slick-slide');
_.slideCount = _.$slides.length;
_.$slides.each(function (index, element) {
$(element)
.attr('data-slick-index', index)
.data('originalStyling', $(element).attr('style') || '');
});
_.$slidesCache = _.$slides;
_.$slider.addClass('slick-slider');
_.$slideTrack = (_.slideCount === 0) ?
$('
').appendTo(_.$slider) :
_.$slides.wrapAll('
').parent();
_.$list = _.$slideTrack.wrap(
'
').parent();
_.$slideTrack.css('opacity', 0);
if (_.options.centerMode === true || _.options.swipeToSlide === true) {
_.options.slidesToScroll = 1;
}
$('img[data-lazy]', _.$slider).not('[src]').addClass('slick-loading');
_.setupInfinite();
_.buildArrows();
_.buildDots();
_.updateDots();
_.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0);
if (_.options.draggable === true) {
_.$list.addClass('draggable');
}
};
Slick.prototype.buildRows = function () {
var _ = this, a, b, c, newSlides, numOfSlides, originalSlides, slidesPerSection;
newSlides = document.createDocumentFragment();
originalSlides = _.$slider.children();
if (_.options.rows > 1) {
slidesPerSection = _.options.slidesPerRow * _.options.rows;
numOfSlides = Math.ceil(
originalSlides.length / slidesPerSection
);
for (a = 0; a < numOfSlides; a++) {
var slide = document.createElement('div');
for (b = 0; b < _.options.rows; b++) {
var row = document.createElement('div');
for (c = 0; c < _.options.slidesPerRow; c++) {
var target = (a * slidesPerSection + ((b * _.options.slidesPerRow) + c));
if (originalSlides.get(target)) {
row.appendChild(originalSlides.get(target));
}
}
slide.appendChild(row);
}
newSlides.appendChild(slide);
}
_.$slider.html(newSlides);
_.$slider.children().children().children()
.css({
'width': (100 / _.options.slidesPerRow) + '%',
'display': 'inline-block'
});
}
};
Slick.prototype.checkResponsive = function (initial, forceUpdate) {
var _ = this,
breakpoint, targetBreakpoint, respondToWidth, triggerBreakpoint = false;
var sliderWidth = _.$slider.width();
var windowWidth = window.innerWidth || $(window).width();
if (_.respondTo === 'window') {
respondToWidth = windowWidth;
} else if (_.respondTo === 'slider') {
respondToWidth = sliderWidth;
} else if (_.respondTo === 'min') {
respondToWidth = Math.min(windowWidth, sliderWidth);
}
if (_.options.responsive &&
_.options.responsive.length &&
_.options.responsive !== null) {
targetBreakpoint = null;
for (breakpoint in _.breakpoints) {
if (_.breakpoints.hasOwnProperty(breakpoint)) {
if (_.originalSettings.mobileFirst === false) {
if (respondToWidth < _.breakpoints[breakpoint]) {
targetBreakpoint = _.breakpoints[breakpoint];
}
} else {
if (respondToWidth > _.breakpoints[breakpoint]) {
targetBreakpoint = _.breakpoints[breakpoint];
}
}
}
}
if (targetBreakpoint !== null) {
if (_.activeBreakpoint !== null) {
if (targetBreakpoint !== _.activeBreakpoint || forceUpdate) {
_.activeBreakpoint =
targetBreakpoint;
if (_.breakpointSettings[targetBreakpoint] === 'unslick') {
_.unslick(targetBreakpoint);
} else {
_.options = $.extend({}, _.originalSettings,
_.breakpointSettings[
targetBreakpoint]);
if (initial === true) {
_.currentSlide = _.options.initialSlide;
}
_.refresh(initial);
}
triggerBreakpoint = targetBreakpoint;
}
} else {
_.activeBreakpoint = targetBreakpoint;
if (_.breakpointSettings[targetBreakpoint] === 'unslick') {
_.unslick(targetBreakpoint);
} else {
_.options = $.extend({}, _.originalSettings,
_.breakpointSettings[
targetBreakpoint]);
if (initial === true) {
_.currentSlide = _.options.initialSlide;
}
_.refresh(initial);
}
triggerBreakpoint = targetBreakpoint;
}
} else {
if (_.activeBreakpoint !== null) {
_.activeBreakpoint = null;
_.options = _.originalSettings;
if (initial === true) {
_.currentSlide = _.options.initialSlide;
}
_.refresh(initial);
triggerBreakpoint = targetBreakpoint;
}
}
// only trigger breakpoints during an actual break. not on initialize.
if (!initial && triggerBreakpoint !== false) {
_.$slider.trigger('breakpoint', [_, triggerBreakpoint]);
}
}
};
Slick.prototype.changeSlide = function (event, dontAnimate) {
var _ = this,
$target = $(event.target),
indexOffset, slideOffset, unevenOffset;
// If target is a link, prevent default action.
if ($target.is('a')) {
event.preventDefault();
}
// If target is not the element (ie: a child), find the .
if (!$target.is('li')) {
$target = $target.closest('li');
}
unevenOffset = (_.slideCount % _.options.slidesToScroll !== 0);
indexOffset = unevenOffset ? 0 : (_.slideCount - _.currentSlide) % _.options.slidesToScroll;
switch (event.data.message) {
case 'previous':
slideOffset = indexOffset === 0 ? _.options.slidesToScroll : _.options.slidesToShow - indexOffset;
if (_.slideCount > _.options.slidesToShow) {
_.slideHandler(_.currentSlide - slideOffset, false, dontAnimate);
}
break;
case 'next':
slideOffset = indexOffset === 0 ? _.options.slidesToScroll : indexOffset;
if (_.slideCount > _.options.slidesToShow) {
_.slideHandler(_.currentSlide + slideOffset, false, dontAnimate);
}
break;
case 'index':
var index = event.data.index === 0 ? 0 :
event.data.index || $target.index() * _.options.slidesToScroll;
_.slideHandler(_.checkNavigable(index), false, dontAnimate);
$target.children().trigger('focus');
break;
default:
return;
}
};
Slick.prototype.checkNavigable = function (index) {
var _ = this,
navigables, prevNavigable;
navigables = _.getNavigableIndexes();
prevNavigable = 0;
if (index > navigables[navigables.length - 1]) {
index = navigables[navigables.length - 1];
} else {
for (var n in navigables) {
if (index < navigables[n]) {
index = prevNavigable;
break;
}
prevNavigable = navigables[n];
}
}
return index;
};
Slick.prototype.cleanUpEvents = function () {
var _ = this;
if (_.options.dots && _.$dots !== null) {
if ($('li', _.$dots) == null) return;
$('li', _.$dots).off('click.slick', _.changeSlide);
if (_.options.pauseOnDotsHover === true && _.options.autoplay === true) {
$('li', _.$dots)
.off('mouseenter.slick', $.proxy(_.setPaused, _, true))
.off('mouseleave.slick', $.proxy(_.setPaused, _, false));
}
}
if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
_.$prevArrow && _.$prevArrow.off('click.slick', _.changeSlide);
_.$nextArrow && _.$nextArrow.off('click.slick', _.changeSlide);
}
if (_.$list == null) return;
_.$list.off('touchstart.slick mousedown.slick', _.swipeHandler);
_.$list.off('touchmove.slick mousemove.slick', _.swipeHandler);
_.$list.off('touchend.slick mouseup.slick', _.swipeHandler);
_.$list.off('touchcancel.slick mouseleave.slick', _.swipeHandler);
_.$list.off('click.slick', _.clickHandler);
$(document).off(_.visibilityChange, _.visibility);
_.$list.off('mouseenter.slick', $.proxy(_.setPaused, _, true));
_.$list.off('mouseleave.slick', $.proxy(_.setPaused, _, false));
if (_.options.accessibility === true) {
_.$list.off('keydown.slick', _.keyHandler);
}
if (_.options.focusOnSelect === true) {
$(_.$slideTrack).children().off('click.slick', _.selectHandler);
}
$(window).off('orientationchange.slick.slick-' + _.instanceUid, _.orientationChange);
$(window).off('resize.slick.slick-' + _.instanceUid, _.resize);
$('[draggable!=true]', _.$slideTrack).off('dragstart', _.preventDefault);
$(window).off('load.slick.slick-' + _.instanceUid, _.setPosition);
$(document).off('ready.slick.slick-' + _.instanceUid, _.setPosition);
};
Slick.prototype.cleanUpRows = function () {
var _ = this, originalSlides;
if (_.options.rows > 1) {
originalSlides = _.$slides.children().children();
originalSlides.removeAttr('style');
_.$slider.html(originalSlides);
}
};
Slick.prototype.clickHandler = function (event) {
var _ = this;
if (_.shouldClick === false) {
event.stopImmediatePropagation();
event.stopPropagation();
event.preventDefault();
}
};
Slick.prototype.destroy = function (refresh) {
var _ = this;
_.autoPlayClear();
_.touchObject = {};
_.cleanUpEvents();
$('.slick-cloned', _.$slider).detach();
if (_.$dots) {
_.$dots.remove();
}
if (_.$prevArrow && _.$prevArrow.length) {
_.$prevArrow
.removeClass('slick-disabled slick-arrow slick-hidden')
.removeAttr('aria-hidden aria-disabled tabindex')
.css("display", "");
if (_.htmlExpr.test(_.options.prevArrow)) {
_.$prevArrow.remove();
}
}
if (_.$nextArrow && _.$nextArrow.length) {
_.$nextArrow
.removeClass('slick-disabled slick-arrow slick-hidden')
.removeAttr('aria-hidden aria-disabled tabindex')
.css("display", "");
if (_.htmlExpr.test(_.options.nextArrow)) {
_.$nextArrow.remove();
}
}
if (_.$slides) {
_.$slides
.removeClass('slick-slide slick-active slick-center slick-visible slick-current')
.removeAttr('aria-hidden')
.removeAttr('data-slick-index')
.each(function () {
$(this).attr('style', $(this).data('originalStyling'));
});
_.$slideTrack.children(this.options.slide).detach();
_.$slideTrack.detach();
_.$list.detach();
_.$slider.append(_.$slides);
}
_.cleanUpRows();
_.$slider.removeClass('slick-slider');
_.$slider.removeClass('slick-initialized');
_.unslicked = true;
if (!refresh) {
_.$slider.trigger('destroy', [_]);
}
};
Slick.prototype.disableTransition = function (slide) {
var _ = this,
transition = {};
transition[_.transitionType] = '';
if (_.options.fade === false) {
_.$slideTrack.css(transition);
} else {
_.$slides.eq(slide).css(transition);
}
};
Slick.prototype.fadeSlide = function (slideIndex, callback) {
var _ = this;
if (_.cssTransitions === false) {
_.$slides.eq(slideIndex).css({
zIndex: _.options.zIndex
});
_.$slides.eq(slideIndex).animate({
opacity: 1
}, _.options.speed, _.options.easing, callback);
} else {
_.applyTransition(slideIndex);
_.$slides.eq(slideIndex).css({
opacity: 1,
zIndex: _.options.zIndex
});
if (callback) {
setTimeout(function () {
_.disableTransition(slideIndex);
callback.call();
}, _.options.speed);
}
}
};
Slick.prototype.fadeSlideOut = function (slideIndex) {
var _ = this;
if (_.cssTransitions === false) {
_.$slides.eq(slideIndex).animate({
opacity: 0,
zIndex: _.options.zIndex - 2
}, _.options.speed, _.options.easing);
} else {
_.applyTransition(slideIndex);
_.$slides.eq(slideIndex).css({
opacity: 0,
zIndex: _.options.zIndex - 2
});
}
};
Slick.prototype.filterSlides = Slick.prototype.slickFilter = function (filter) {
var _ = this;
if (filter !== null) {
_.unload();
_.$slideTrack.children(this.options.slide).detach();
_.$slidesCache.filter(filter).appendTo(_.$slideTrack);
_.reinit();
}
};
Slick.prototype.getCurrent = Slick.prototype.slickCurrentSlide = function () {
var _ = this;
return _.currentSlide;
};
Slick.prototype.getDotCount = function () {
var _ = this;
var breakPoint = 0;
var counter = 0;
var pagerQty = 0;
if (_.options.infinite === true) {
while (breakPoint < _.slideCount) {
++pagerQty;
breakPoint = counter + _.options.slidesToShow;
counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
}
} else if (_.options.centerMode === true) {
pagerQty = _.slideCount;
} else {
while (breakPoint < _.slideCount) {
++pagerQty;
breakPoint = counter + _.options.slidesToShow;
counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
}
}
return pagerQty - 1;
};
Slick.prototype.getLeft = function (slideIndex) {
var _ = this,
targetLeft,
verticalHeight,
verticalOffset = 0,
targetSlide;
_.slideOffset = 0;
verticalHeight = _.$slides.first().outerHeight(true);
if (_.options.infinite === true) {
if (_.slideCount > _.options.slidesToShow) {
_.slideOffset = (_.slideWidth * _.options.slidesToShow) * -1;
verticalOffset = (verticalHeight * _.options.slidesToShow) * -1;
}
if (_.slideCount % _.options.slidesToScroll !== 0) {
if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) {
if (slideIndex > _.slideCount) {
_.slideOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * _.slideWidth) * -1;
verticalOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * verticalHeight) * -1;
} else {
_.slideOffset = ((_.slideCount % _.options.slidesToScroll) * _.slideWidth) * -1;
verticalOffset = ((_.slideCount % _.options.slidesToScroll) * verticalHeight) * -1;
}
}
}
} else {
if (slideIndex + _.options.slidesToShow > _.slideCount) {
_.slideOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * _.slideWidth;
verticalOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * verticalHeight;
}
}
if (_.slideCount <= _.options.slidesToShow) {
_.slideOffset = 0;
verticalOffset = 0;
}
if (_.options.centerMode === true && _.options.infinite === true) {
_.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth;
} else if (_.options.centerMode === true) {
_.slideOffset = 0;
_.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2);
}
if (_.options.vertical === false) {
targetLeft = ((slideIndex * _.slideWidth) * -1) + _.slideOffset;
} else {
targetLeft = ((slideIndex * verticalHeight) * -1) + verticalOffset;
}
if (_.options.variableWidth === true) {
if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {
targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
} else {
targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow);
}
targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
if (_.options.centerMode === true) {
if (_.options.infinite === false) {
targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
} else {
targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow + 1);
}
targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
targetLeft += (_.$list.width() - targetSlide.outerWidth()) / 2;
}
}
return targetLeft;
};
Slick.prototype.getOption = Slick.prototype.slickGetOption = function (option) {
var _ = this;
return _.options[option];
};
Slick.prototype.getNavigableIndexes = function () {
var _ = this,
breakPoint = 0,
counter = 0,
indexes = [],
max;
if (_.options.infinite === false) {
max = _.slideCount;
} else {
breakPoint = _.options.slidesToScroll * -1;
counter = _.options.slidesToScroll * -1;
max = _.slideCount * 2;
}
while (breakPoint < max) {
indexes.push(breakPoint);
breakPoint = counter + _.options.slidesToScroll;
counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
}
return indexes;
};
Slick.prototype.getSlick = function () {
return this;
};
Slick.prototype.getSlideCount = function () {
var _ = this,
slidesTraversed, swipedSlide, centerOffset;
centerOffset = _.options.centerMode === true ? _.slideWidth * Math.floor(_.options.slidesToShow / 2) : 0;
if (_.options.swipeToSlide === true) {
_.$slideTrack.find('.slick-slide').each(function (index, slide) {
if (slide.offsetLeft - centerOffset + ($(slide).outerWidth() / 2) > (_.swipeLeft * -1)) {
swipedSlide = slide;
return false;
}
});
slidesTraversed = Math.abs($(swipedSlide).attr('data-slick-index') - _.currentSlide) || 1;
return slidesTraversed;
} else {
return _.options.slidesToScroll;
}
};
Slick.prototype.goTo = Slick.prototype.slickGoTo = function (slide, dontAnimate) {
var _ = this;
_.changeSlide({
data: {
message: 'index',
index: parseInt(slide)
}
}, dontAnimate);
};
Slick.prototype.init = function (creation) {
var _ = this;
if (!$(_.$slider).hasClass('slick-initialized')) {
$(_.$slider).addClass('slick-initialized');
_.buildRows();
_.buildOut();
_.setProps();
_.startLoad();
_.loadSlider();
_.initializeEvents();
_.updateArrows();
_.updateDots();
}
if (creation) {
_.$slider.trigger('init', [_]);
}
if (_.options.accessibility === true) {
_.initADA();
}
};
Slick.prototype.initArrowEvents = function () {
var _ = this;
if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
_.$prevArrow.on('click.slick', {
message: 'previous'
}, _.changeSlide);
_.$nextArrow.on('click.slick', {
message: 'next'
}, _.changeSlide);
}
};
Slick.prototype.initDotEvents = function () {
var _ = this;
if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
$('li', _.$dots).on('click.slick', {
message: 'index'
}, _.changeSlide);
}
if (_.options.dots === true && _.options.pauseOnDotsHover === true && _.options.autoplay === true) {
$('li', _.$dots)
.on('mouseenter.slick', $.proxy(_.setPaused, _, true))
.on('mouseleave.slick', $.proxy(_.setPaused, _, false));
}
};
Slick.prototype.initializeEvents = function () {
var _ = this;
_.initArrowEvents();
_.initDotEvents();
_.$list.on('touchstart.slick mousedown.slick', {
action: 'start'
}, _.swipeHandler);
_.$list.on('touchmove.slick mousemove.slick', {
action: 'move'
}, _.swipeHandler);
_.$list.on('touchend.slick mouseup.slick', {
action: 'end'
}, _.swipeHandler);
_.$list.on('touchcancel.slick mouseleave.slick', {
action: 'end'
}, _.swipeHandler);
_.$list.on('click.slick', _.clickHandler);
$(document).on(_.visibilityChange, $.proxy(_.visibility, _));
_.$list.on('mouseenter.slick', $.proxy(_.setPaused, _, true));
_.$list.on('mouseleave.slick', $.proxy(_.setPaused, _, false));
if (_.options.accessibility === true) {
_.$list.on('keydown.slick', _.keyHandler);
}
if (_.options.focusOnSelect === true) {
$(_.$slideTrack).children().on('click.slick', _.selectHandler);
}
$(window).on('orientationchange.slick.slick-' + _.instanceUid, $.proxy(_.orientationChange, _));
$(window).on('resize.slick.slick-' + _.instanceUid, $.proxy(_.resize, _));
$('[draggable!=true]', _.$slideTrack).on('dragstart', _.preventDefault);
$(window).on('load.slick.slick-' + _.instanceUid, _.setPosition);
$(document).on('ready.slick.slick-' + _.instanceUid, _.setPosition);
};
Slick.prototype.initUI = function () {
var _ = this;
if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
_.$prevArrow.show();
_.$nextArrow.show();
}
if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
_.$dots.show();
}
if (_.options.autoplay === true) {
_.autoPlay();
}
};
Slick.prototype.keyHandler = function (event) {
var _ = this;
//Dont slide if the cursor is inside the form fields and arrow keys are pressed
if (!event.target.tagName.match('TEXTAREA|INPUT|SELECT')) {
if (event.keyCode === 37 && _.options.accessibility === true) {
_.changeSlide({
data: {
message: 'previous'
}
});
} else if (event.keyCode === 39 && _.options.accessibility === true) {
_.changeSlide({
data: {
message: 'next'
}
});
}
}
};
Slick.prototype.lazyLoad = function () {
var _ = this,
loadRange, cloneRange, rangeStart, rangeEnd;
function loadImages(imagesScope) {
$('img[data-lazy]', imagesScope).each(function () {
var image = $(this),
imageSource = $(this).attr('data-lazy'),
imageToLoad = document.createElement('img');
imageToLoad.onload = function () {
image
.animate({ opacity: 0 }, 100, function () {
image
.attr('src', imageSource)
.animate({ opacity: 1 }, 200, function () {
image
.removeAttr('data-lazy')
.removeClass('slick-loading');
});
});
};
imageToLoad.src = imageSource;
});
}
if (_.options.centerMode === true) {
if (_.options.infinite === true) {
rangeStart = _.currentSlide + (_.options.slidesToShow / 2 + 1);
rangeEnd = rangeStart + _.options.slidesToShow + 2;
} else {
rangeStart = Math.max(0, _.currentSlide - (_.options.slidesToShow / 2 + 1));
rangeEnd = 2 + (_.options.slidesToShow / 2 + 1) + _.currentSlide;
}
} else {
rangeStart = _.options.infinite ? _.options.slidesToShow + _.currentSlide : _.currentSlide;
rangeEnd = rangeStart + _.options.slidesToShow;
if (_.options.fade === true) {
if (rangeStart > 0) rangeStart--;
if (rangeEnd <= _.slideCount) rangeEnd++;
}
}
loadRange = _.$slider.find('.slick-slide').slice(rangeStart, rangeEnd);
loadImages(loadRange);
if (_.slideCount <= _.options.slidesToShow) {
cloneRange = _.$slider.find('.slick-slide');
loadImages(cloneRange);
} else
if (_.currentSlide >= _.slideCount - _.options.slidesToShow) {
cloneRange = _.$slider.find('.slick-cloned').slice(0, _.options.slidesToShow);
loadImages(cloneRange);
} else if (_.currentSlide === 0) {
cloneRange = _.$slider.find('.slick-cloned').slice(_.options.slidesToShow * -1);
loadImages(cloneRange);
}
};
Slick.prototype.loadSlider = function () {
var _ = this;
_.setPosition();
_.$slideTrack.css({
opacity: 1
});
_.$slider.removeClass('slick-loading');
_.initUI();
if (_.options.lazyLoad === 'progressive') {
_.progressiveLazyLoad();
}
};
Slick.prototype.next = Slick.prototype.slickNext = function () {
var _ = this;
_.changeSlide({
data: {
message: 'next'
}
});
};
Slick.prototype.orientationChange = function () {
var _ = this;
_.checkResponsive();
_.setPosition();
};
Slick.prototype.pause = Slick.prototype.slickPause = function () {
var _ = this;
_.autoPlayClear();
_.paused = true;
};
Slick.prototype.play = Slick.prototype.slickPlay = function () {
var _ = this;
_.paused = false;
_.autoPlay();
};
Slick.prototype.postSlide = function (index) {
var _ = this;
_.$slider.trigger('afterChange', [_, index]);
_.animating = false;
_.setPosition();
_.swipeLeft = null;
if (_.options.autoplay === true && _.paused === false) {
_.autoPlay();
}
if (_.options.accessibility === true) {
_.initADA();
}
};
Slick.prototype.prev = Slick.prototype.slickPrev = function () {
var _ = this;
_.changeSlide({
data: {
message: 'previous'
}
});
};
Slick.prototype.preventDefault = function (event) {
event.preventDefault();
};
Slick.prototype.progressiveLazyLoad = function () {
var _ = this,
imgCount, targetImage;
imgCount = $('img[data-lazy]', _.$slider).length;
if (imgCount > 0) {
targetImage = $('img[data-lazy]', _.$slider).first();
targetImage.attr('src', targetImage.attr('data-lazy')).removeClass('slick-loading').load(function () {
targetImage.removeAttr('data-lazy');
_.progressiveLazyLoad();
if (_.options.adaptiveHeight === true) {
_.setPosition();
}
})
.error(function () {
targetImage.removeAttr('data-lazy');
_.progressiveLazyLoad();
});
}
};
Slick.prototype.refresh = function (initializing) {
var _ = this,
currentSlide = _.currentSlide;
_.destroy(true);
$.extend(_, _.initials, { currentSlide: currentSlide });
_.init();
if (!initializing) {
_.changeSlide({
data: {
message: 'index',
index: currentSlide
}
}, false);
}
};
Slick.prototype.registerBreakpoints = function () {
var _ = this, breakpoint, currentBreakpoint, l,
responsiveSettings = _.options.responsive || null;
if ($.type(responsiveSettings) === "array" && responsiveSettings.length) {
_.respondTo = _.options.respondTo || 'window';
for (breakpoint in responsiveSettings) {
l = _.breakpoints.length - 1;
currentBreakpoint = responsiveSettings[breakpoint].breakpoint;
if (responsiveSettings.hasOwnProperty(breakpoint)) {
// loop through the breakpoints and cut out any existing
// ones with the same breakpoint number, we don't want dupes.
while (l >= 0) {
if (_.breakpoints[l] && _.breakpoints[l] === currentBreakpoint) {
_.breakpoints.splice(l, 1);
}
l--;
}
_.breakpoints.push(currentBreakpoint);
_.breakpointSettings[currentBreakpoint] = responsiveSettings[breakpoint].settings;
}
}
_.breakpoints.sort(function (a, b) {
return (_.options.mobileFirst) ? a - b : b - a;
});
}
};
Slick.prototype.reinit = function () {
var _ = this;
_.$slides =
_.$slideTrack
.children(_.options.slide)
.addClass('slick-slide');
_.slideCount = _.$slides.length;
if (_.currentSlide >= _.slideCount && _.currentSlide !== 0) {
_.currentSlide = _.currentSlide - _.options.slidesToScroll;
}
if (_.slideCount <= _.options.slidesToShow) {
_.currentSlide = 0;
}
_.registerBreakpoints();
_.setProps();
_.setupInfinite();
_.buildArrows();
_.updateArrows();
_.initArrowEvents();
_.buildDots();
_.updateDots();
_.initDotEvents();
_.checkResponsive(false, true);
if (_.options.focusOnSelect === true) {
$(_.$slideTrack).children().on('click.slick', _.selectHandler);
}
_.setSlideClasses(0);
_.setPosition();
_.$slider.trigger('reInit', [_]);
if (_.options.autoplay === true) {
_.focusHandler();
}
};
Slick.prototype.resize = function () {
var _ = this;
if (_.$slides.length != 0 && _.$slides.length < 3) _.currentSlide = 0;
if ($(window).width() !== _.windowWidth) {
clearTimeout(_.windowDelay);
_.windowDelay = window.setTimeout(function () {
_.windowWidth = $(window).width();
_.checkResponsive();
if (!_.unslicked) { _.setPosition(); }
}, 50);
}
};
Slick.prototype.removeSlide = Slick.prototype.slickRemove = function (index, removeBefore, removeAll) {
var _ = this;
if (typeof (index) === 'boolean') {
removeBefore = index;
index = removeBefore === true ? 0 : _.slideCount - 1;
} else {
index = removeBefore === true ? --index : index;
}
if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) {
return false;
}
_.unload();
if (removeAll === true) {
_.$slideTrack.children().remove();
} else {
_.$slideTrack.children(this.options.slide).eq(index).remove();
}
_.$slides = _.$slideTrack.children(this.options.slide);
_.$slideTrack.children(this.options.slide).detach();
_.$slideTrack.append(_.$slides);
_.$slidesCache = _.$slides;
_.reinit();
};
Slick.prototype.setCSS = function (position) {
var _ = this,
positionProps = {},
x, y;
if (_.options.rtl === true) {
position = -position;
}
x = _.positionProp == 'left' ? Math.ceil(position) + 'px' : '0px';
y = _.positionProp == 'top' ? Math.ceil(position) + 'px' : '0px';
positionProps[_.positionProp] = position;
if (_.transformsEnabled === false) {
_.$slideTrack.css(positionProps);
} else {
positionProps = {};
if (_.cssTransitions === false) {
positionProps[_.animType] = 'translate(' + x + ', ' + y + ')';
_.$slideTrack.css(positionProps);
} else {
positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)';
_.$slideTrack.css(positionProps);
}
}
};
Slick.prototype.setDimensions = function () {
var _ = this;
if (_.options.vertical === false) {
if (_.options.centerMode === true) {
_.$list.css({
padding: ('0px ' + _.options.centerPadding)
});
}
} else {
_.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow);
if (_.options.centerMode === true) {
_.$list.css({
padding: (_.options.centerPadding + ' 0px')
});
}
}
_.listWidth = _.$list.width();
_.listHeight = _.$list.height();
if (_.options.vertical === false && _.options.variableWidth === false) {
_.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow);
_.$slideTrack.width(Math.ceil((_.slideWidth * _.$slideTrack.children('.slick-slide').length)));
} else if (_.options.variableWidth === true) {
_.$slideTrack.width(5000 * _.slideCount);
} else {
_.slideWidth = Math.ceil(_.listWidth);
_.$slideTrack.height(Math.ceil((_.$slides.first().outerHeight(true) * _.$slideTrack.children('.slick-slide').length)));
}
var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width();
if (_.options.variableWidth === false) _.$slideTrack.children('.slick-slide').width(_.slideWidth - offset);
};
Slick.prototype.setFade = function () {
var _ = this,
targetLeft;
_.$slides.each(function (index, element) {
targetLeft = (_.slideWidth * index) * -1;
if (_.options.rtl === true) {
$(element).css({
position: 'relative',
right: targetLeft,
top: 0,
zIndex: _.options.zIndex - 2,
opacity: 0
});
} else {
$(element).css({
position: 'relative',
left: targetLeft,
top: 0,
zIndex: _.options.zIndex - 2,
opacity: 0
});
}
});
_.$slides.eq(_.currentSlide).css({
zIndex: _.options.zIndex - 1,
opacity: 1
});
};
Slick.prototype.setHeight = function () {
var _ = this;
if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {
var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);
_.$list.css('height', targetHeight);
}
};
Slick.prototype.setOption = Slick.prototype.slickSetOption = function (option, value, refresh) {
var _ = this, l, item;
if (option === "responsive" && $.type(value) === "array") {
for (item in value) {
if ($.type(_.options.responsive) !== "array") {
_.options.responsive = [value[item]];
} else {
l = _.options.responsive.length - 1;
// loop through the responsive object and splice out duplicates.
while (l >= 0) {
if (_.options.responsive[l].breakpoint === value[item].breakpoint) {
_.options.responsive.splice(l, 1);
}
l--;
}
_.options.responsive.push(value[item]);
}
}
} else {
_.options[option] = value;
}
if (refresh === true) {
_.unload();
_.reinit();
}
};
Slick.prototype.setPosition = function () {
var _ = this;
_.setDimensions();
_.setHeight();
if (_.options.fade === false) {
_.setCSS(_.getLeft(_.currentSlide));
} else {
_.setFade();
}
_.$slider.trigger('setPosition', [_]);
};
Slick.prototype.setProps = function () {
var _ = this,
bodyStyle = document.body.style;
_.positionProp = _.options.vertical === true ? 'top' : 'left';
if (_.positionProp === 'top') {
_.$slider.addClass('slick-vertical');
} else {
_.$slider.removeClass('slick-vertical');
}
if (bodyStyle.WebkitTransition !== undefined ||
bodyStyle.MozTransition !== undefined ||
bodyStyle.msTransition !== undefined) {
if (_.options.useCSS === true) {
_.cssTransitions = true;
}
}
if (_.options.fade) {
if (typeof _.options.zIndex === 'number') {
if (_.options.zIndex < 3) {
_.options.zIndex = 3;
}
} else {
_.options.zIndex = _.defaults.zIndex;
}
}
if (bodyStyle.OTransform !== undefined) {
_.animType = 'OTransform';
_.transformType = '-o-transform';
_.transitionType = 'OTransition';
if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
}
if (bodyStyle.MozTransform !== undefined) {
_.animType = 'MozTransform';
_.transformType = '-moz-transform';
_.transitionType = 'MozTransition';
if (bodyStyle.perspectiveProperty === undefined && bodyStyle.MozPerspective === undefined) _.animType = false;
}
if (bodyStyle.webkitTransform !== undefined) {
_.animType = 'webkitTransform';
_.transformType = '-webkit-transform';
_.transitionType = 'webkitTransition';
if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
}
if (bodyStyle.msTransform !== undefined) {
_.animType = 'msTransform';
_.transformType = '-ms-transform';
_.transitionType = 'msTransition';
if (bodyStyle.msTransform === undefined) _.animType = false;
}
if (bodyStyle.transform !== undefined && _.animType !== false) {
_.animType = 'transform';
_.transformType = 'transform';
_.transitionType = 'transition';
}
_.transformsEnabled = (_.animType !== null && _.animType !== false);
};
Slick.prototype.setSlideClasses = function (index) {
var _ = this,
centerOffset, allSlides, indexOffset, remainder;
allSlides = _.$slider
.find('.slick-slide')
.removeClass('slick-active slick-center slick-current')
.attr('aria-hidden', 'true');
_.$slides
.eq(index)
.addClass('slick-current');
if (_.options.centerMode === true) {
centerOffset = Math.floor(_.options.slidesToShow / 2);
if (_.options.infinite === true) {
if (index >= centerOffset && index <= (_.slideCount - 1) - centerOffset) {
_.$slides
.slice(index - centerOffset, index + centerOffset + 1)
.addClass('slick-active')
.attr('aria-hidden', 'false');
} else {
indexOffset = _.options.slidesToShow + index;
allSlides
.slice(indexOffset - centerOffset + 1, indexOffset + centerOffset + 2)
.addClass('slick-active')
.attr('aria-hidden', 'false');
}
if (index === 0) {
allSlides
.eq(allSlides.length - 1 - _.options.slidesToShow)
.addClass('slick-center');
} else if (index === _.slideCount - 1) {
allSlides
.eq(_.options.slidesToShow)
.addClass('slick-center');
}
}
_.$slides
.eq(index)
.addClass('slick-center');
} else {
if (index >= 0 && index <= (_.slideCount - _.options.slidesToShow)) {
_.$slides
.slice(index, index + _.options.slidesToShow)
.addClass('slick-active')
.attr('aria-hidden', 'false');
} else if (allSlides.length <= _.options.slidesToShow) {
allSlides
.addClass('slick-active')
.attr('aria-hidden', 'false');
} else {
remainder = _.slideCount % _.options.slidesToShow;
indexOffset = _.options.infinite === true ? _.options.slidesToShow + index : index;
if (_.options.slidesToShow == _.options.slidesToScroll && (_.slideCount - index) < _.options.slidesToShow) {
allSlides
.slice(indexOffset - (_.options.slidesToShow - remainder), indexOffset + remainder)
.addClass('slick-active')
.attr('aria-hidden', 'false');
} else {
allSlides
.slice(indexOffset, indexOffset + _.options.slidesToShow)
.addClass('slick-active')
.attr('aria-hidden', 'false');
}
}
}
if (_.options.lazyLoad === 'ondemand') {
_.lazyLoad();
}
};
Slick.prototype.setupInfinite = function () {
var _ = this,
i, slideIndex, infiniteCount;
if (_.options.fade === true) {
_.options.centerMode = false;
}
if (_.options.infinite === true && _.options.fade === false) {
slideIndex = null;
if (_.slideCount > _.options.slidesToShow) {
if (_.options.centerMode === true) {
infiniteCount = _.options.slidesToShow + 1;
} else {
infiniteCount = _.options.slidesToShow;
}
for (i = _.slideCount; i > (_.slideCount -
infiniteCount) ; i -= 1) {
slideIndex = i - 1;
$(_.$slides[slideIndex]).clone(true).attr('id', '')
.attr('data-slick-index', slideIndex - _.slideCount)
.prependTo(_.$slideTrack).addClass('slick-cloned');
}
for (i = 0; i < infiniteCount; i += 1) {
slideIndex = i;
$(_.$slides[slideIndex]).clone(true).attr('id', '')
.attr('data-slick-index', slideIndex + _.slideCount)
.appendTo(_.$slideTrack).addClass('slick-cloned');
}
_.$slideTrack.find('.slick-cloned').find('[id]').each(function () {
$(this).attr('id', '');
});
}
}
};
Slick.prototype.setPaused = function (paused) {
var _ = this;
if (_.options.autoplay === true && _.options.pauseOnHover === true) {
_.paused = paused;
if (!paused) {
_.autoPlay();
} else {
_.autoPlayClear();
}
}
};
Slick.prototype.selectHandler = function (event) {
var _ = this;
var targetElement =
$(event.target).is('.slick-slide') ?
$(event.target) :
$(event.target).parents('.slick-slide');
var index = parseInt(targetElement.attr('data-slick-index'));
if (!index) index = 0;
if (_.slideCount <= _.options.slidesToShow) {
_.setSlideClasses(index);
_.asNavFor(index);
return;
}
_.slideHandler(index);
};
Slick.prototype.slideHandler = function (index, sync, dontAnimate) {
var targetSlide, animSlide, oldSlide, slideLeft, targetLeft = null,
_ = this;
sync = sync || false;
if (_.animating === true && _.options.waitForAnimate === true) {
return;
}
if (_.options.fade === true && _.currentSlide === index) {
return;
}
if (_.slideCount <= _.options.slidesToShow) {
return;
}
if (sync === false) {
_.asNavFor(index);
}
targetSlide = index;
targetLeft = _.getLeft(targetSlide);
slideLeft = _.getLeft(_.currentSlide);
_.currentLeft = _.swipeLeft === null ? slideLeft : _.swipeLeft;
if (_.options.infinite === false && _.options.centerMode === false && (index < 0 || index > _.getDotCount() * _.options.slidesToScroll)) {
if (_.options.fade === false) {
targetSlide = _.currentSlide;
if (dontAnimate !== true) {
_.animateSlide(slideLeft, function () {
_.postSlide(targetSlide);
});
} else {
_.postSlide(targetSlide);
}
}
return;
} else if (_.options.infinite === false && _.options.centerMode === true && (index < 0 || index > (_.slideCount - _.options.slidesToScroll))) {
if (_.options.fade === false) {
targetSlide = _.currentSlide;
if (dontAnimate !== true) {
_.animateSlide(slideLeft, function () {
_.postSlide(targetSlide);
});
} else {
_.postSlide(targetSlide);
}
}
return;
}
if (_.options.autoplay === true) {
clearInterval(_.autoPlayTimer);
}
if (targetSlide < 0) {
if (_.slideCount % _.options.slidesToScroll !== 0) {
animSlide = _.slideCount - (_.slideCount % _.options.slidesToScroll);
} else {
animSlide = _.slideCount + targetSlide;
}
} else if (targetSlide >= _.slideCount) {
if (_.slideCount % _.options.slidesToScroll !== 0) {
animSlide = 0;
} else {
animSlide = targetSlide - _.slideCount;
}
} else {
animSlide = targetSlide;
}
_.animating = true;
_.$slider.trigger('beforeChange', [_, _.currentSlide, animSlide]);
oldSlide = _.currentSlide;
_.currentSlide = animSlide;
_.setSlideClasses(_.currentSlide);
_.updateDots();
_.updateArrows();
if (_.options.fade === true) {
if (dontAnimate !== true) {
_.fadeSlideOut(oldSlide);
_.fadeSlide(animSlide, function () {
_.postSlide(animSlide);
});
} else {
_.postSlide(animSlide);
}
_.animateHeight();
return;
}
if (dontAnimate !== true) {
_.animateSlide(targetLeft, function () {
_.postSlide(animSlide);
});
} else {
_.postSlide(animSlide);
}
};
Slick.prototype.startLoad = function () {
var _ = this;
if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
_.$prevArrow.hide();
_.$nextArrow.hide();
}
if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
_.$dots.hide();
}
_.$slider.addClass('slick-loading');
};
Slick.prototype.swipeDirection = function () {
var xDist, yDist, r, swipeAngle, _ = this;
xDist = _.touchObject.startX - _.touchObject.curX;
yDist = _.touchObject.startY - _.touchObject.curY;
r = Math.atan2(yDist, xDist);
swipeAngle = Math.round(r * 180 / Math.PI);
if (swipeAngle < 0) {
swipeAngle = 360 - Math.abs(swipeAngle);
}
if ((swipeAngle <= 45) && (swipeAngle >= 0)) {
return (_.options.rtl === false ? 'left' : 'right');
}
if ((swipeAngle <= 360) && (swipeAngle >= 315)) {
return (_.options.rtl === false ? 'left' : 'right');
}
if ((swipeAngle >= 135) && (swipeAngle <= 225)) {
return (_.options.rtl === false ? 'right' : 'left');
}
if (_.options.verticalSwiping === true) {
if ((swipeAngle >= 35) && (swipeAngle <= 135)) {
return 'left';
} else {
return 'right';
}
}
return 'vertical';
};
Slick.prototype.swipeEnd = function (event) {
var _ = this,
slideCount;
_.dragging = false;
_.shouldClick = (_.touchObject.swipeLength > 10) ? false : true;
if (_.touchObject.curX === undefined) {
return false;
}
if (_.touchObject.edgeHit === true) {
_.$slider.trigger('edge', [_, _.swipeDirection()]);
}
if (_.touchObject.swipeLength >= _.touchObject.minSwipe) {
switch (_.swipeDirection()) {
case 'left':
slideCount = _.options.swipeToSlide ? _.checkNavigable(_.currentSlide + _.getSlideCount()) : _.currentSlide + _.getSlideCount();
_.slideHandler(slideCount);
_.currentDirection = 0;
_.touchObject = {};
_.$slider.trigger('swipe', [_, 'left']);
break;
case 'right':
slideCount = _.options.swipeToSlide ? _.checkNavigable(_.currentSlide - _.getSlideCount()) : _.currentSlide - _.getSlideCount();
_.slideHandler(slideCount);
_.currentDirection = 1;
_.touchObject = {};
_.$slider.trigger('swipe', [_, 'right']);
break;
}
} else {
if (_.touchObject.startX !== _.touchObject.curX) {
_.slideHandler(_.currentSlide);
_.touchObject = {};
}
}
};
Slick.prototype.swipeHandler = function (event) {
var _ = this;
if ((_.options.swipe === false) || ('ontouchend' in document && _.options.swipe === false)) {
return;
} else if (_.options.draggable === false && event.type.indexOf('mouse') !== -1) {
return;
}
_.touchObject.fingerCount = event.originalEvent && event.originalEvent.touches !== undefined ?
event.originalEvent.touches.length : 1;
_.touchObject.minSwipe = _.listWidth / _.options
.touchThreshold;
if (_.options.verticalSwiping === true) {
_.touchObject.minSwipe = _.listHeight / _.options
.touchThreshold;
}
switch (event.data.action) {
case 'start':
_.swipeStart(event);
break;
case 'move':
_.swipeMove(event);
break;
case 'end':
_.swipeEnd(event);
break;
}
};
Slick.prototype.swipeMove = function (event) {
var _ = this,
edgeWasHit = false,
curLeft, swipeDirection, swipeLength, positionOffset, touches;
touches = event.originalEvent !== undefined ? event.originalEvent.touches : null;
if (!_.dragging || touches && touches.length !== 1) {
return false;
}
curLeft = _.getLeft(_.currentSlide);
_.touchObject.curX = touches !== undefined ? touches[0].pageX : event.clientX;
_.touchObject.curY = touches !== undefined ? touches[0].pageY : event.clientY;
_.touchObject.swipeLength = Math.round(Math.sqrt(
Math.pow(_.touchObject.curX - _.touchObject.startX, 2)));
if (_.options.verticalSwiping === true) {
_.touchObject.swipeLength = Math.round(Math.sqrt(
Math.pow(_.touchObject.curY - _.touchObject.startY, 2)));
}
swipeDirection = _.swipeDirection();
if (swipeDirection === 'vertical') {
return;
}
if (event.originalEvent !== undefined && _.touchObject.swipeLength > 4) {
event.preventDefault();
}
positionOffset = (_.options.rtl === false ? 1 : -1) * (_.touchObject.curX > _.touchObject.startX ? 1 : -1);
if (_.options.verticalSwiping === true) {
positionOffset = _.touchObject.curY > _.touchObject.startY ? 1 : -1;
}
swipeLength = _.touchObject.swipeLength;
_.touchObject.edgeHit = false;
if (_.options.infinite === false) {
if ((_.currentSlide === 0 && swipeDirection === 'right') || (_.currentSlide >= _.getDotCount() && swipeDirection === 'left')) {
swipeLength = _.touchObject.swipeLength * _.options.edgeFriction;
_.touchObject.edgeHit = true;
}
}
if (_.options.vertical === false) {
_.swipeLeft = curLeft + swipeLength * positionOffset;
} else {
_.swipeLeft = curLeft + (swipeLength * (_.$list.height() / _.listWidth)) * positionOffset;
}
if (_.options.verticalSwiping === true) {
_.swipeLeft = curLeft + swipeLength * positionOffset;
}
if (_.options.fade === true || _.options.touchMove === false) {
return false;
}
if (_.animating === true) {
_.swipeLeft = null;
return false;
}
_.setCSS(_.swipeLeft);
};
Slick.prototype.swipeStart = function (event) {
var _ = this,
touches;
if (_.touchObject.fingerCount !== 1 || _.slideCount <= _.options.slidesToShow) {
_.touchObject = {};
return false;
}
if (event.originalEvent !== undefined && event.originalEvent.touches !== undefined) {
touches = event.originalEvent.touches[0];
}
_.touchObject.startX = _.touchObject.curX = touches !== undefined ? touches.pageX : event.clientX;
_.touchObject.startY = _.touchObject.curY = touches !== undefined ? touches.pageY : event.clientY;
_.dragging = true;
};
Slick.prototype.unfilterSlides = Slick.prototype.slickUnfilter = function () {
var _ = this;
if (_.$slidesCache !== null) {
_.unload();
_.$slideTrack.children(this.options.slide).detach();
_.$slidesCache.appendTo(_.$slideTrack);
_.reinit();
}
};
Slick.prototype.unload = function () {
var _ = this;
$('.slick-cloned', _.$slider).remove();
if (_.$dots) {
_.$dots.remove();
}
if (_.$prevArrow && _.htmlExpr.test(_.options.prevArrow)) {
_.$prevArrow.remove();
}
if (_.$nextArrow && _.htmlExpr.test(_.options.nextArrow)) {
_.$nextArrow.remove();
}
_.$slides
.removeClass('slick-slide slick-active slick-visible slick-current')
.attr('aria-hidden', 'true')
.css('width', '');
};
Slick.prototype.unslick = function (fromBreakpoint) {
var _ = this;
_.$slider.trigger('unslick', [_, fromBreakpoint]);
_.destroy();
};
Slick.prototype.updateArrows = function () {
var _ = this,
centerOffset;
centerOffset = Math.floor(_.options.slidesToShow / 2);
if (_.options.arrows === true &&
_.slideCount > _.options.slidesToShow &&
!_.options.infinite) {
_.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
_.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
if (_.currentSlide === 0) {
_.$prevArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
_.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
} else if (_.currentSlide >= _.slideCount - _.options.slidesToShow && _.options.centerMode === false) {
_.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
_.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
} else if (_.currentSlide >= _.slideCount - 1 && _.options.centerMode === true) {
_.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
_.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
}
}
};
Slick.prototype.updateDots = function () {
var _ = this;
if (_.$dots !== null) {
_.$dots
.find('li')
.removeClass('slick-active')
.attr('aria-hidden', 'true');
_.$dots
.find('li')
.eq(Math.floor(_.currentSlide / _.options.slidesToScroll))
.addClass('slick-active')
.attr('aria-hidden', 'false');
}
};
Slick.prototype.visibility = function () {
var _ = this;
if (document[_.hidden]) {
_.paused = true;
_.autoPlayClear();
} else {
if (_.options.autoplay === true) {
_.paused = false;
_.autoPlay();
}
}
};
Slick.prototype.initADA = function () {
var _ = this;
if (_.$slides == null) return;
_.$slides.add(_.$slideTrack.find('.slick-cloned')).attr({
'aria-hidden': 'true',
'tabindex': '-1'
}).find('a, input, button, select').attr({
'tabindex': '-1'
});
//_.$slideTrack.attr('role', 'listbox');
_.$slides.not(_.$slideTrack.find('.slick-cloned')).each(function (i) {
/*$(this).attr({
'role': 'option',
'aria-describedby': 'slick-slide' + _.instanceUid + i + ''
});*/
});
if (_.$dots !== null) {
_.$dots.attr('role', 'tablist').find('li').each(function (i) {
$(this).attr({
'role': 'presentation',
'aria-selected': 'false',
'aria-controls': 'navigation' + _.instanceUid + i + '',
'id': 'slick-slide' + _.instanceUid + i + ''
});
})
.first().attr('aria-selected', 'true').end()
.find('button').attr('role', 'button').end()
.closest('div').attr('role', 'toolbar');
}
_.activateADA();
};
Slick.prototype.activateADA = function () {
var _ = this,
_isSlideOnFocus = _.$slider.find('*').is(':focus');
// _isSlideOnFocus = _.$slides.is(':focus') || _.$slides.find('*').is(':focus');
_.$slideTrack.find('.flipper.slick-active').attr({
'tabindex': '0'
})
_.$slideTrack.find('.slick-active').attr({
'aria-hidden': 'false'
}).find('a, input, button, select').attr({
'tabindex': '0'
});
(_isSlideOnFocus) && _.$slideTrack.find('.slick-active').focus();
};
Slick.prototype.focusHandler = function () {
var _ = this;
_.$slider.on('focus.slick blur.slick', '*', function (event) {
event.stopImmediatePropagation();
var sf = $(this);
setTimeout(function () {
if (_.isPlay) {
if (sf.is(':focus')) {
_.autoPlayClear();
_.paused = true;
} else {
_.paused = false;
_.autoPlay();
}
}
}, 0);
});
};
$.fn.slick = function () {
var _ = this,
opt = arguments[0],
args = Array.prototype.slice.call(arguments, 1),
l = _.length,
i = 0,
ret;
for (i; i < l; i++) {
if (typeof opt == 'object' || typeof opt == 'undefined')
_[i].slick = new Slick(_[i], opt);
else
ret = _[i].slick[opt].apply(_[i].slick, args);
if (typeof ret != 'undefined') return ret;
}
return _;
};
}));
/* ========================================================================
* Bootstrap: transition.js v3.3.4
* http://getbootstrap.com/javascript/#transitions
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
// ============================================================
function transitionEnd() {
var el = document.createElement('bootstrap')
var transEndEventNames = {
WebkitTransition: 'webkitTransitionEnd',
MozTransition: 'transitionend',
OTransition: 'oTransitionEnd otransitionend',
transition: 'transitionend'
}
for (var name in transEndEventNames) {
if (el.style[name] !== undefined) {
return { end: transEndEventNames[name] }
}
}
return false // explicit for ie8 ( ._.)
}
// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) {
var called = false
var $el = this
$(this).one('bsTransitionEnd', function () { called = true })
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
setTimeout(callback, duration)
return this
}
$(function () {
$.support.transition = transitionEnd()
if (!$.support.transition) return
$.event.special.bsTransitionEnd = {
bindType: $.support.transition.end,
delegateType: $.support.transition.end,
handle: function (e) {
if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
}
}
})
}(jQuery);
/* ========================================================================
* Bootstrap: collapse.js v3.3.4
* http://getbootstrap.com/javascript/#collapse
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// COLLAPSE PUBLIC CLASS DEFINITION
// ================================
var Collapse = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Collapse.DEFAULTS, options)
this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
'[data-toggle="collapse"][data-target="#' + element.id + '"]')
this.transitioning = null
if (this.options.parent) {
this.$parent = this.getParent()
} else {
this.addAriaAndCollapsedClass(this.$element, this.$trigger)
}
if (this.options.toggle) this.toggle()
}
Collapse.VERSION = '3.3.4'
Collapse.TRANSITION_DURATION = 350
Collapse.DEFAULTS = {
toggle: true
}
Collapse.prototype.dimension = function () {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}
Collapse.prototype.show = function () {
if (this.transitioning || this.$element.hasClass('in')) return
var activesData
var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
if (actives && actives.length) {
activesData = actives.data('bs.collapse')
if (activesData && activesData.transitioning) return
}
var startEvent = $.Event('show.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
if (actives && actives.length) {
Plugin.call(actives, 'hide')
activesData || actives.data('bs.collapse', null)
}
var dimension = this.dimension()
this.$element
.removeClass('collapse')
.addClass('collapsing')[dimension](0)
//.attr('aria-expanded', true)
this.$trigger
.removeClass('collapsed')
.attr('aria-expanded', true)
this.transitioning = 1
var complete = function () {
this.$element
.removeClass('collapsing')
.addClass('collapse in')[dimension]('')
this.transitioning = 0
this.$element
.trigger('shown.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
var scrollSize = $.camelCase(['scroll', dimension].join('-'))
this.$element
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
}
Collapse.prototype.hide = function () {
if (this.transitioning || !this.$element.hasClass('in')) return
var startEvent = $.Event('hide.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
var dimension = this.dimension()
this.$element[dimension](this.$element[dimension]())[0].offsetHeight
this.$element
.addClass('collapsing')
.removeClass('collapse in')
//.attr('aria-expanded', false)
this.$trigger
.addClass('collapsed')
.attr('aria-expanded', false)
this.transitioning = 1
var complete = function () {
this.transitioning = 0
this.$element
.removeClass('collapsing')
.addClass('collapse')
.trigger('hidden.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
this.$element
[dimension](0)
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)
}
Collapse.prototype.toggle = function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
Collapse.prototype.getParent = function () {
return $(this.options.parent)
.find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
.each($.proxy(function (i, element) {
var $element = $(element)
this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
}, this))
.end()
}
Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
var isOpen = $element.hasClass('in')
//$element.attr('aria-expanded', isOpen)
$trigger
.toggleClass('collapsed', !isOpen)
.attr('aria-expanded', isOpen)
}
function getTargetFromTrigger($trigger) {
var href
var target = $trigger.attr('data-target')
|| (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
return $(target)
}
// COLLAPSE PLUGIN DEFINITION
// ==========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.collapse')
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.collapse
$.fn.collapse = Plugin
$.fn.collapse.Constructor = Collapse
// COLLAPSE NO CONFLICT
// ====================
$.fn.collapse.noConflict = function () {
$.fn.collapse = old
return this
}
// COLLAPSE DATA-API
// =================
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
var $this = $(this)
if (!$this.attr('data-target')) e.preventDefault()
var $target = getTargetFromTrigger($this)
var data = $target.data('bs.collapse')
var option = data ? 'toggle' : $this.data()
Plugin.call($target, option)
})
}(jQuery);
/*!
handlebars v3.0.3
Copyright (C) 2011-2014 by Yehuda Katz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@license
*/
(function webpackUniversalModuleDefinition(root, factory) {
if (typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define(factory);
else if (typeof exports === 'object')
exports["Handlebars"] = factory();
else
root["Handlebars"] = factory();
})(this, function () {
return /******/ (function (modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if (installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/
};
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/
}
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/
})
/************************************************************************/
/******/([
/* 0 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
var _interopRequireWildcard = __webpack_require__(8)['default'];
exports.__esModule = true;
var _runtime = __webpack_require__(1);
var _runtime2 = _interopRequireWildcard(_runtime);
// Compiler imports
var _AST = __webpack_require__(2);
var _AST2 = _interopRequireWildcard(_AST);
var _Parser$parse = __webpack_require__(3);
var _Compiler$compile$precompile = __webpack_require__(4);
var _JavaScriptCompiler = __webpack_require__(5);
var _JavaScriptCompiler2 = _interopRequireWildcard(_JavaScriptCompiler);
var _Visitor = __webpack_require__(6);
var _Visitor2 = _interopRequireWildcard(_Visitor);
var _noConflict = __webpack_require__(7);
var _noConflict2 = _interopRequireWildcard(_noConflict);
var _create = _runtime2['default'].create;
function create() {
var hb = _create();
hb.compile = function (input, options) {
return _Compiler$compile$precompile.compile(input, options, hb);
};
hb.precompile = function (input, options) {
return _Compiler$compile$precompile.precompile(input, options, hb);
};
hb.AST = _AST2['default'];
hb.Compiler = _Compiler$compile$precompile.Compiler;
hb.JavaScriptCompiler = _JavaScriptCompiler2['default'];
hb.Parser = _Parser$parse.parser;
hb.parse = _Parser$parse.parse;
return hb;
}
var inst = create();
inst.create = create;
_noConflict2['default'](inst);
inst.Visitor = _Visitor2['default'];
inst['default'] = inst;
exports['default'] = inst;
module.exports = exports['default'];
/***/
},
/* 1 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
var _interopRequireWildcard = __webpack_require__(8)['default'];
exports.__esModule = true;
var _import = __webpack_require__(9);
var base = _interopRequireWildcard(_import);
// Each of these augment the Handlebars object. No need to setup here.
// (This is done to easily share code between commonjs and browse envs)
var _SafeString = __webpack_require__(10);
var _SafeString2 = _interopRequireWildcard(_SafeString);
var _Exception = __webpack_require__(11);
var _Exception2 = _interopRequireWildcard(_Exception);
var _import2 = __webpack_require__(12);
var Utils = _interopRequireWildcard(_import2);
var _import3 = __webpack_require__(13);
var runtime = _interopRequireWildcard(_import3);
var _noConflict = __webpack_require__(7);
var _noConflict2 = _interopRequireWildcard(_noConflict);
// For compatibility and usage outside of module systems, make the Handlebars object a namespace
function create() {
var hb = new base.HandlebarsEnvironment();
Utils.extend(hb, base);
hb.SafeString = _SafeString2['default'];
hb.Exception = _Exception2['default'];
hb.Utils = Utils;
hb.escapeExpression = Utils.escapeExpression;
hb.VM = runtime;
hb.template = function (spec) {
return runtime.template(spec, hb);
};
return hb;
}
var inst = create();
inst.create = create;
_noConflict2['default'](inst);
inst['default'] = inst;
exports['default'] = inst;
module.exports = exports['default'];
/***/
},
/* 2 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
var AST = {
Program: function Program(statements, blockParams, strip, locInfo) {
this.loc = locInfo;
this.type = 'Program';
this.body = statements;
this.blockParams = blockParams;
this.strip = strip;
},
MustacheStatement: function MustacheStatement(path, params, hash, escaped, strip, locInfo) {
this.loc = locInfo;
this.type = 'MustacheStatement';
this.path = path;
this.params = params || [];
this.hash = hash;
this.escaped = escaped;
this.strip = strip;
},
BlockStatement: function BlockStatement(path, params, hash, program, inverse, openStrip, inverseStrip, closeStrip, locInfo) {
this.loc = locInfo;
this.type = 'BlockStatement';
this.path = path;
this.params = params || [];
this.hash = hash;
this.program = program;
this.inverse = inverse;
this.openStrip = openStrip;
this.inverseStrip = inverseStrip;
this.closeStrip = closeStrip;
},
PartialStatement: function PartialStatement(name, params, hash, strip, locInfo) {
this.loc = locInfo;
this.type = 'PartialStatement';
this.name = name;
this.params = params || [];
this.hash = hash;
this.indent = '';
this.strip = strip;
},
ContentStatement: function ContentStatement(string, locInfo) {
this.loc = locInfo;
this.type = 'ContentStatement';
this.original = this.value = string;
},
CommentStatement: function CommentStatement(comment, strip, locInfo) {
this.loc = locInfo;
this.type = 'CommentStatement';
this.value = comment;
this.strip = strip;
},
SubExpression: function SubExpression(path, params, hash, locInfo) {
this.loc = locInfo;
this.type = 'SubExpression';
this.path = path;
this.params = params || [];
this.hash = hash;
},
PathExpression: function PathExpression(data, depth, parts, original, locInfo) {
this.loc = locInfo;
this.type = 'PathExpression';
this.data = data;
this.original = original;
this.parts = parts;
this.depth = depth;
},
StringLiteral: function StringLiteral(string, locInfo) {
this.loc = locInfo;
this.type = 'StringLiteral';
this.original = this.value = string;
},
NumberLiteral: function NumberLiteral(number, locInfo) {
this.loc = locInfo;
this.type = 'NumberLiteral';
this.original = this.value = Number(number);
},
BooleanLiteral: function BooleanLiteral(bool, locInfo) {
this.loc = locInfo;
this.type = 'BooleanLiteral';
this.original = this.value = bool === 'true';
},
UndefinedLiteral: function UndefinedLiteral(locInfo) {
this.loc = locInfo;
this.type = 'UndefinedLiteral';
this.original = this.value = undefined;
},
NullLiteral: function NullLiteral(locInfo) {
this.loc = locInfo;
this.type = 'NullLiteral';
this.original = this.value = null;
},
Hash: function Hash(pairs, locInfo) {
this.loc = locInfo;
this.type = 'Hash';
this.pairs = pairs;
},
HashPair: function HashPair(key, value, locInfo) {
this.loc = locInfo;
this.type = 'HashPair';
this.key = key;
this.value = value;
},
// Public API used to evaluate derived attributes regarding AST nodes
helpers: {
// a mustache is definitely a helper if:
// * it is an eligible helper, and
// * it has at least one parameter or hash segment
helperExpression: function helperExpression(node) {
return !!(node.type === 'SubExpression' || node.params.length || node.hash);
},
scopedId: function scopedId(path) {
return /^\.|this\b/.test(path.original);
},
// an ID is simple if it only has one part, and that part is not
// `..` or `this`.
simpleId: function simpleId(path) {
return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth;
}
}
};
// Must be exported as an object rather than the root of the module as the jison lexer
// must modify the object to operate properly.
exports['default'] = AST;
module.exports = exports['default'];
/***/
},
/* 3 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
var _interopRequireWildcard = __webpack_require__(8)['default'];
exports.__esModule = true;
exports.parse = parse;
var _parser = __webpack_require__(14);
var _parser2 = _interopRequireWildcard(_parser);
var _AST = __webpack_require__(2);
var _AST2 = _interopRequireWildcard(_AST);
var _WhitespaceControl = __webpack_require__(15);
var _WhitespaceControl2 = _interopRequireWildcard(_WhitespaceControl);
var _import = __webpack_require__(16);
var Helpers = _interopRequireWildcard(_import);
var _extend = __webpack_require__(12);
exports.parser = _parser2['default'];
var yy = {};
_extend.extend(yy, Helpers, _AST2['default']);
function parse(input, options) {
// Just return if an already-compiled AST was passed in.
if (input.type === 'Program') {
return input;
}
_parser2['default'].yy = yy;
// Altering the shared object here, but this is ok as parser is a sync operation
yy.locInfo = function (locInfo) {
return new yy.SourceLocation(options && options.srcName, locInfo);
};
var strip = new _WhitespaceControl2['default']();
return strip.accept(_parser2['default'].parse(input));
}
/***/
},
/* 4 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
var _interopRequireWildcard = __webpack_require__(8)['default'];
exports.__esModule = true;
exports.Compiler = Compiler;
exports.precompile = precompile;
exports.compile = compile;
var _Exception = __webpack_require__(11);
var _Exception2 = _interopRequireWildcard(_Exception);
var _isArray$indexOf = __webpack_require__(12);
var _AST = __webpack_require__(2);
var _AST2 = _interopRequireWildcard(_AST);
var slice = [].slice;
function Compiler() { }
// the foundHelper register will disambiguate helper lookup from finding a
// function in a context. This is necessary for mustache compatibility, which
// requires that context functions in blocks are evaluated by blockHelperMissing,
// and then proceed as if the resulting value was provided to blockHelperMissing.
Compiler.prototype = {
compiler: Compiler,
equals: function equals(other) {
var len = this.opcodes.length;
if (other.opcodes.length !== len) {
return false;
}
for (var i = 0; i < len; i++) {
var opcode = this.opcodes[i],
otherOpcode = other.opcodes[i];
if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) {
return false;
}
}
// We know that length is the same between the two arrays because they are directly tied
// to the opcode behavior above.
len = this.children.length;
for (var i = 0; i < len; i++) {
if (!this.children[i].equals(other.children[i])) {
return false;
}
}
return true;
},
guid: 0,
compile: function compile(program, options) {
this.sourceNode = [];
this.opcodes = [];
this.children = [];
this.options = options;
this.stringParams = options.stringParams;
this.trackIds = options.trackIds;
options.blockParams = options.blockParams || [];
// These changes will propagate to the other compiler components
var knownHelpers = options.knownHelpers;
options.knownHelpers = {
helperMissing: true,
blockHelperMissing: true,
each: true,
'if': true,
unless: true,
'with': true,
log: true,
lookup: true
};
if (knownHelpers) {
for (var _name in knownHelpers) {
if (_name in knownHelpers) {
options.knownHelpers[_name] = knownHelpers[_name];
}
}
}
return this.accept(program);
},
compileProgram: function compileProgram(program) {
var childCompiler = new this.compiler(),
// eslint-disable-line new-cap
result = childCompiler.compile(program, this.options),
guid = this.guid++;
this.usePartial = this.usePartial || result.usePartial;
this.children[guid] = result;
this.useDepths = this.useDepths || result.useDepths;
return guid;
},
accept: function accept(node) {
this.sourceNode.unshift(node);
var ret = this[node.type](node);
this.sourceNode.shift();
return ret;
},
Program: function Program(program) {
this.options.blockParams.unshift(program.blockParams);
var body = program.body,
bodyLength = body.length;
for (var i = 0; i < bodyLength; i++) {
this.accept(body[i]);
}
this.options.blockParams.shift();
this.isSimple = bodyLength === 1;
this.blockParams = program.blockParams ? program.blockParams.length : 0;
return this;
},
BlockStatement: function BlockStatement(block) {
transformLiteralToPath(block);
var program = block.program,
inverse = block.inverse;
program = program && this.compileProgram(program);
inverse = inverse && this.compileProgram(inverse);
var type = this.classifySexpr(block);
if (type === 'helper') {
this.helperSexpr(block, program, inverse);
} else if (type === 'simple') {
this.simpleSexpr(block);
// now that the simple mustache is resolved, we need to
// evaluate it by executing `blockHelperMissing`
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
this.opcode('emptyHash');
this.opcode('blockValue', block.path.original);
} else {
this.ambiguousSexpr(block, program, inverse);
// now that the simple mustache is resolved, we need to
// evaluate it by executing `blockHelperMissing`
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
this.opcode('emptyHash');
this.opcode('ambiguousBlockValue');
}
this.opcode('append');
},
PartialStatement: function PartialStatement(partial) {
this.usePartial = true;
var params = partial.params;
if (params.length > 1) {
throw new _Exception2['default']('Unsupported number of partial arguments: ' + params.length, partial);
} else if (!params.length) {
params.push({ type: 'PathExpression', parts: [], depth: 0 });
}
var partialName = partial.name.original,
isDynamic = partial.name.type === 'SubExpression';
if (isDynamic) {
this.accept(partial.name);
}
this.setupFullMustacheParams(partial, undefined, undefined, true);
var indent = partial.indent || '';
if (this.options.preventIndent && indent) {
this.opcode('appendContent', indent);
indent = '';
}
this.opcode('invokePartial', isDynamic, partialName, indent);
this.opcode('append');
},
MustacheStatement: function MustacheStatement(mustache) {
this.SubExpression(mustache); // eslint-disable-line new-cap
if (mustache.escaped && !this.options.noEscape) {
this.opcode('appendEscaped');
} else {
this.opcode('append');
}
},
ContentStatement: function ContentStatement(content) {
if (content.value) {
this.opcode('appendContent', content.value);
}
},
CommentStatement: function CommentStatement() { },
SubExpression: function SubExpression(sexpr) {
transformLiteralToPath(sexpr);
var type = this.classifySexpr(sexpr);
if (type === 'simple') {
this.simpleSexpr(sexpr);
} else if (type === 'helper') {
this.helperSexpr(sexpr);
} else {
this.ambiguousSexpr(sexpr);
}
},
ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) {
var path = sexpr.path,
name = path.parts[0],
isBlock = program != null || inverse != null;
this.opcode('getContext', path.depth);
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
this.accept(path);
this.opcode('invokeAmbiguous', name, isBlock);
},
simpleSexpr: function simpleSexpr(sexpr) {
this.accept(sexpr.path);
this.opcode('resolvePossibleLambda');
},
helperSexpr: function helperSexpr(sexpr, program, inverse) {
var params = this.setupFullMustacheParams(sexpr, program, inverse),
path = sexpr.path,
name = path.parts[0];
if (this.options.knownHelpers[name]) {
this.opcode('invokeKnownHelper', params.length, name);
} else if (this.options.knownHelpersOnly) {
throw new _Exception2['default']('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr);
} else {
path.falsy = true;
this.accept(path);
this.opcode('invokeHelper', params.length, path.original, _AST2['default'].helpers.simpleId(path));
}
},
PathExpression: function PathExpression(path) {
this.addDepth(path.depth);
this.opcode('getContext', path.depth);
var name = path.parts[0],
scoped = _AST2['default'].helpers.scopedId(path),
blockParamId = !path.depth && !scoped && this.blockParamIndex(name);
if (blockParamId) {
this.opcode('lookupBlockParam', blockParamId, path.parts);
} else if (!name) {
// Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
this.opcode('pushContext');
} else if (path.data) {
this.options.data = true;
this.opcode('lookupData', path.depth, path.parts);
} else {
this.opcode('lookupOnContext', path.parts, path.falsy, scoped);
}
},
StringLiteral: function StringLiteral(string) {
this.opcode('pushString', string.value);
},
NumberLiteral: function NumberLiteral(number) {
this.opcode('pushLiteral', number.value);
},
BooleanLiteral: function BooleanLiteral(bool) {
this.opcode('pushLiteral', bool.value);
},
UndefinedLiteral: function UndefinedLiteral() {
this.opcode('pushLiteral', 'undefined');
},
NullLiteral: function NullLiteral() {
this.opcode('pushLiteral', 'null');
},
Hash: function Hash(hash) {
var pairs = hash.pairs,
i = 0,
l = pairs.length;
this.opcode('pushHash');
for (; i < l; i++) {
this.pushParam(pairs[i].value);
}
while (i--) {
this.opcode('assignToHash', pairs[i].key);
}
this.opcode('popHash');
},
// HELPERS
opcode: function opcode(name) {
this.opcodes.push({ opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc });
},
addDepth: function addDepth(depth) {
if (!depth) {
return;
}
this.useDepths = true;
},
classifySexpr: function classifySexpr(sexpr) {
var isSimple = _AST2['default'].helpers.simpleId(sexpr.path);
var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]);
// a mustache is an eligible helper if:
// * its id is simple (a single part, not `this` or `..`)
var isHelper = !isBlockParam && _AST2['default'].helpers.helperExpression(sexpr);
// if a mustache is an eligible helper but not a definite
// helper, it is ambiguous, and will be resolved in a later
// pass or at runtime.
var isEligible = !isBlockParam && (isHelper || isSimple);
// if ambiguous, we can possibly resolve the ambiguity now
// An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc.
if (isEligible && !isHelper) {
var _name2 = sexpr.path.parts[0],
options = this.options;
if (options.knownHelpers[_name2]) {
isHelper = true;
} else if (options.knownHelpersOnly) {
isEligible = false;
}
}
if (isHelper) {
return 'helper';
} else if (isEligible) {
return 'ambiguous';
} else {
return 'simple';
}
},
pushParams: function pushParams(params) {
for (var i = 0, l = params.length; i < l; i++) {
this.pushParam(params[i]);
}
},
pushParam: function pushParam(val) {
var value = val.value != null ? val.value : val.original || '';
if (this.stringParams) {
if (value.replace) {
value = value.replace(/^(\.?\.\/)*/g, '').replace(/\//g, '.');
}
if (val.depth) {
this.addDepth(val.depth);
}
this.opcode('getContext', val.depth || 0);
this.opcode('pushStringParam', value, val.type);
if (val.type === 'SubExpression') {
// SubExpressions get evaluated and passed in
// in string params mode.
this.accept(val);
}
} else {
if (this.trackIds) {
var blockParamIndex = undefined;
if (val.parts && !_AST2['default'].helpers.scopedId(val) && !val.depth) {
blockParamIndex = this.blockParamIndex(val.parts[0]);
}
if (blockParamIndex) {
var blockParamChild = val.parts.slice(1).join('.');
this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild);
} else {
value = val.original || value;
if (value.replace) {
value = value.replace(/^\.\//g, '').replace(/^\.$/g, '');
}
this.opcode('pushId', val.type, value);
}
}
this.accept(val);
}
},
setupFullMustacheParams: function setupFullMustacheParams(sexpr, program, inverse, omitEmpty) {
var params = sexpr.params;
this.pushParams(params);
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
if (sexpr.hash) {
this.accept(sexpr.hash);
} else {
this.opcode('emptyHash', omitEmpty);
}
return params;
},
blockParamIndex: function blockParamIndex(name) {
for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) {
var blockParams = this.options.blockParams[depth],
param = blockParams && _isArray$indexOf.indexOf(blockParams, name);
if (blockParams && param >= 0) {
return [depth, param];
}
}
}
};
function precompile(input, options, env) {
if (input == null || typeof input !== 'string' && input.type !== 'Program') {
throw new _Exception2['default']('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input);
}
options = options || {};
if (!('data' in options)) {
options.data = true;
}
if (options.compat) {
options.useDepths = true;
}
var ast = env.parse(input, options),
environment = new env.Compiler().compile(ast, options);
return new env.JavaScriptCompiler().compile(environment, options);
}
function compile(input, _x, env) {
var options = arguments[1] === undefined ? {} : arguments[1];
if (input == null || typeof input !== 'string' && input.type !== 'Program') {
throw new _Exception2['default']('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input);
}
if (!('data' in options)) {
options.data = true;
}
if (options.compat) {
options.useDepths = true;
}
var compiled = undefined;
function compileInput() {
var ast = env.parse(input, options),
environment = new env.Compiler().compile(ast, options),
templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
return env.template(templateSpec);
}
// Template is only compiled on first use and cached after that point.
function ret(context, execOptions) {
if (!compiled) {
compiled = compileInput();
}
return compiled.call(this, context, execOptions);
}
ret._setup = function (setupOptions) {
if (!compiled) {
compiled = compileInput();
}
return compiled._setup(setupOptions);
};
ret._child = function (i, data, blockParams, depths) {
if (!compiled) {
compiled = compileInput();
}
return compiled._child(i, data, blockParams, depths);
};
return ret;
}
function argEquals(a, b) {
if (a === b) {
return true;
}
if (_isArray$indexOf.isArray(a) && _isArray$indexOf.isArray(b) && a.length === b.length) {
for (var i = 0; i < a.length; i++) {
if (!argEquals(a[i], b[i])) {
return false;
}
}
return true;
}
}
function transformLiteralToPath(sexpr) {
if (!sexpr.path.parts) {
var literal = sexpr.path;
// Casting to string here to make false and 0 literal values play nicely with the rest
// of the system.
sexpr.path = new _AST2['default'].PathExpression(false, 0, [literal.original + ''], literal.original + '', literal.loc);
}
}
/***/
},
/* 5 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
var _interopRequireWildcard = __webpack_require__(8)['default'];
exports.__esModule = true;
var _COMPILER_REVISION$REVISION_CHANGES = __webpack_require__(9);
var _Exception = __webpack_require__(11);
var _Exception2 = _interopRequireWildcard(_Exception);
var _isArray = __webpack_require__(12);
var _CodeGen = __webpack_require__(17);
var _CodeGen2 = _interopRequireWildcard(_CodeGen);
function Literal(value) {
this.value = value;
}
function JavaScriptCompiler() { }
JavaScriptCompiler.prototype = {
// PUBLIC API: You can override these methods in a subclass to provide
// alternative compiled forms for name lookup and buffering semantics
nameLookup: function nameLookup(parent, name /* , type*/) {
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
return [parent, '.', name];
} else {
return [parent, '[\'', name, '\']'];
}
},
depthedLookup: function depthedLookup(name) {
return [this.aliasable('this.lookup'), '(depths, "', name, '")'];
},
compilerInfo: function compilerInfo() {
var revision = _COMPILER_REVISION$REVISION_CHANGES.COMPILER_REVISION,
versions = _COMPILER_REVISION$REVISION_CHANGES.REVISION_CHANGES[revision];
return [revision, versions];
},
appendToBuffer: function appendToBuffer(source, location, explicit) {
// Force a source as this simplifies the merge logic.
if (!_isArray.isArray(source)) {
source = [source];
}
source = this.source.wrap(source, location);
if (this.environment.isSimple) {
return ['return ', source, ';'];
} else if (explicit) {
// This is a case where the buffer operation occurs as a child of another
// construct, generally braces. We have to explicitly output these buffer
// operations to ensure that the emitted code goes in the correct location.
return ['buffer += ', source, ';'];
} else {
source.appendToBuffer = true;
return source;
}
},
initializeBuffer: function initializeBuffer() {
return this.quotedString('');
},
// END PUBLIC API
compile: function compile(environment, options, context, asObject) {
this.environment = environment;
this.options = options;
this.stringParams = this.options.stringParams;
this.trackIds = this.options.trackIds;
this.precompile = !asObject;
this.name = this.environment.name;
this.isChild = !!context;
this.context = context || {
programs: [],
environments: []
};
this.preamble();
this.stackSlot = 0;
this.stackVars = [];
this.aliases = {};
this.registers = { list: [] };
this.hashes = [];
this.compileStack = [];
this.inlineStack = [];
this.blockParams = [];
this.compileChildren(environment, options);
this.useDepths = this.useDepths || environment.useDepths || this.options.compat;
this.useBlockParams = this.useBlockParams || environment.useBlockParams;
var opcodes = environment.opcodes,
opcode = undefined,
firstLoc = undefined,
i = undefined,
l = undefined;
for (i = 0, l = opcodes.length; i < l; i++) {
opcode = opcodes[i];
this.source.currentLocation = opcode.loc;
firstLoc = firstLoc || opcode.loc;
this[opcode.opcode].apply(this, opcode.args);
}
// Flush any trailing content that might be pending.
this.source.currentLocation = firstLoc;
this.pushSource('');
/* istanbul ignore next */
if (this.stackSlot || this.inlineStack.length || this.compileStack.length) {
throw new _Exception2['default']('Compile completed with content left on stack');
}
var fn = this.createFunctionContext(asObject);
if (!this.isChild) {
var ret = {
compiler: this.compilerInfo(),
main: fn
};
var programs = this.context.programs;
for (i = 0, l = programs.length; i < l; i++) {
if (programs[i]) {
ret[i] = programs[i];
}
}
if (this.environment.usePartial) {
ret.usePartial = true;
}
if (this.options.data) {
ret.useData = true;
}
if (this.useDepths) {
ret.useDepths = true;
}
if (this.useBlockParams) {
ret.useBlockParams = true;
}
if (this.options.compat) {
ret.compat = true;
}
if (!asObject) {
ret.compiler = JSON.stringify(ret.compiler);
this.source.currentLocation = { start: { line: 1, column: 0 } };
ret = this.objectLiteral(ret);
if (options.srcName) {
ret = ret.toStringWithSourceMap({ file: options.destName });
ret.map = ret.map && ret.map.toString();
} else {
ret = ret.toString();
}
} else {
ret.compilerOptions = this.options;
}
return ret;
} else {
return fn;
}
},
preamble: function preamble() {
// track the last context pushed into place to allow skipping the
// getContext opcode when it would be a noop
this.lastContext = 0;
this.source = new _CodeGen2['default'](this.options.srcName);
},
createFunctionContext: function createFunctionContext(asObject) {
var varDeclarations = '';
var locals = this.stackVars.concat(this.registers.list);
if (locals.length > 0) {
varDeclarations += ', ' + locals.join(', ');
}
// Generate minimizer alias mappings
//
// When using true SourceNodes, this will update all references to the given alias
// as the source nodes are reused in situ. For the non-source node compilation mode,
// aliases will not be used, but this case is already being run on the client and
// we aren't concern about minimizing the template size.
var aliasCount = 0;
for (var alias in this.aliases) {
// eslint-disable-line guard-for-in
var node = this.aliases[alias];
if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) {
varDeclarations += ', alias' + ++aliasCount + '=' + alias;
node.children[0] = 'alias' + aliasCount;
}
}
var params = ['depth0', 'helpers', 'partials', 'data'];
if (this.useBlockParams || this.useDepths) {
params.push('blockParams');
}
if (this.useDepths) {
params.push('depths');
}
// Perform a second pass over the output to merge content when possible
var source = this.mergeSource(varDeclarations);
if (asObject) {
params.push(source);
return Function.apply(this, params);
} else {
return this.source.wrap(['function(', params.join(','), ') {\n ', source, '}']);
}
},
mergeSource: function mergeSource(varDeclarations) {
var isSimple = this.environment.isSimple,
appendOnly = !this.forceBuffer,
appendFirst = undefined,
sourceSeen = undefined,
bufferStart = undefined,
bufferEnd = undefined;
this.source.each(function (line) {
if (line.appendToBuffer) {
if (bufferStart) {
line.prepend(' + ');
} else {
bufferStart = line;
}
bufferEnd = line;
} else {
if (bufferStart) {
if (!sourceSeen) {
appendFirst = true;
} else {
bufferStart.prepend('buffer += ');
}
bufferEnd.add(';');
bufferStart = bufferEnd = undefined;
}
sourceSeen = true;
if (!isSimple) {
appendOnly = false;
}
}
});
if (appendOnly) {
if (bufferStart) {
bufferStart.prepend('return ');
bufferEnd.add(';');
} else if (!sourceSeen) {
this.source.push('return "";');
}
} else {
varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer());
if (bufferStart) {
bufferStart.prepend('return buffer + ');
bufferEnd.add(';');
} else {
this.source.push('return buffer;');
}
}
if (varDeclarations) {
this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n'));
}
return this.source.merge();
},
// [blockValue]
//
// On stack, before: hash, inverse, program, value
// On stack, after: return value of blockHelperMissing
//
// The purpose of this opcode is to take a block of the form
// `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and
// replace it on the stack with the result of properly
// invoking blockHelperMissing.
blockValue: function blockValue(name) {
var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
params = [this.contextName(0)];
this.setupHelperArgs(name, 0, params);
var blockName = this.popStack();
params.splice(1, 0, blockName);
this.push(this.source.functionCall(blockHelperMissing, 'call', params));
},
// [ambiguousBlockValue]
//
// On stack, before: hash, inverse, program, value
// Compiler value, before: lastHelper=value of last found helper, if any
// On stack, after, if no lastHelper: same as [blockValue]
// On stack, after, if lastHelper: value
ambiguousBlockValue: function ambiguousBlockValue() {
// We're being a bit cheeky and reusing the options value from the prior exec
var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
params = [this.contextName(0)];
this.setupHelperArgs('', 0, params, true);
this.flushInline();
var current = this.topStack();
params.splice(1, 0, current);
this.pushSource(['if (!', this.lastHelper, ') { ', current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), '}']);
},
// [appendContent]
//
// On stack, before: ...
// On stack, after: ...
//
// Appends the string value of `content` to the current buffer
appendContent: function appendContent(content) {
if (this.pendingContent) {
content = this.pendingContent + content;
} else {
this.pendingLocation = this.source.currentLocation;
}
this.pendingContent = content;
},
// [append]
//
// On stack, before: value, ...
// On stack, after: ...
//
// Coerces `value` to a String and appends it to the current buffer.
//
// If `value` is truthy, or 0, it is coerced into a string and appended
// Otherwise, the empty string is appended
append: function append() {
if (this.isInline()) {
this.replaceStack(function (current) {
return [' != null ? ', current, ' : ""'];
});
this.pushSource(this.appendToBuffer(this.popStack()));
} else {
var local = this.popStack();
this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']);
if (this.environment.isSimple) {
this.pushSource(['else { ', this.appendToBuffer('\'\'', undefined, true), ' }']);
}
}
},
// [appendEscaped]
//
// On stack, before: value, ...
// On stack, after: ...
//
// Escape `value` and append it to the buffer
appendEscaped: function appendEscaped() {
this.pushSource(this.appendToBuffer([this.aliasable('this.escapeExpression'), '(', this.popStack(), ')']));
},
// [getContext]
//
// On stack, before: ...
// On stack, after: ...
// Compiler value, after: lastContext=depth
//
// Set the value of the `lastContext` compiler value to the depth
getContext: function getContext(depth) {
this.lastContext = depth;
},
// [pushContext]
//
// On stack, before: ...
// On stack, after: currentContext, ...
//
// Pushes the value of the current context onto the stack.
pushContext: function pushContext() {
this.pushStackLiteral(this.contextName(this.lastContext));
},
// [lookupOnContext]
//
// On stack, before: ...
// On stack, after: currentContext[name], ...
//
// Looks up the value of `name` on the current context and pushes
// it onto the stack.
lookupOnContext: function lookupOnContext(parts, falsy, scoped) {
var i = 0;
if (!scoped && this.options.compat && !this.lastContext) {
// The depthed query is expected to handle the undefined logic for the root level that
// is implemented below, so we evaluate that directly in compat mode
this.push(this.depthedLookup(parts[i++]));
} else {
this.pushContext();
}
this.resolvePath('context', parts, i, falsy);
},
// [lookupBlockParam]
//
// On stack, before: ...
// On stack, after: blockParam[name], ...
//
// Looks up the value of `parts` on the given block param and pushes
// it onto the stack.
lookupBlockParam: function lookupBlockParam(blockParamId, parts) {
this.useBlockParams = true;
this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']);
this.resolvePath('context', parts, 1);
},
// [lookupData]
//
// On stack, before: ...
// On stack, after: data, ...
//
// Push the data lookup operator
lookupData: function lookupData(depth, parts) {
if (!depth) {
this.pushStackLiteral('data');
} else {
this.pushStackLiteral('this.data(data, ' + depth + ')');
}
this.resolvePath('data', parts, 0, true);
},
resolvePath: function resolvePath(type, parts, i, falsy) {
var _this = this;
if (this.options.strict || this.options.assumeObjects) {
this.push(strictLookup(this.options.strict, this, parts, type));
return;
}
var len = parts.length;
for (; i < len; i++) {
/*eslint-disable no-loop-func */
this.replaceStack(function (current) {
var lookup = _this.nameLookup(current, parts[i], type);
// We want to ensure that zero and false are handled properly if the context (falsy flag)
// needs to have the special handling for these values.
if (!falsy) {
return [' != null ? ', lookup, ' : ', current];
} else {
// Otherwise we can use generic falsy handling
return [' && ', lookup];
}
});
/*eslint-enable no-loop-func */
}
},
// [resolvePossibleLambda]
//
// On stack, before: value, ...
// On stack, after: resolved value, ...
//
// If the `value` is a lambda, replace it on the stack by
// the return value of the lambda
resolvePossibleLambda: function resolvePossibleLambda() {
this.push([this.aliasable('this.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']);
},
// [pushStringParam]
//
// On stack, before: ...
// On stack, after: string, currentContext, ...
//
// This opcode is designed for use in string mode, which
// provides the string value of a parameter along with its
// depth rather than resolving it immediately.
pushStringParam: function pushStringParam(string, type) {
this.pushContext();
this.pushString(type);
// If it's a subexpression, the string result
// will be pushed after this opcode.
if (type !== 'SubExpression') {
if (typeof string === 'string') {
this.pushString(string);
} else {
this.pushStackLiteral(string);
}
}
},
emptyHash: function emptyHash(omitEmpty) {
if (this.trackIds) {
this.push('{}'); // hashIds
}
if (this.stringParams) {
this.push('{}'); // hashContexts
this.push('{}'); // hashTypes
}
this.pushStackLiteral(omitEmpty ? 'undefined' : '{}');
},
pushHash: function pushHash() {
if (this.hash) {
this.hashes.push(this.hash);
}
this.hash = { values: [], types: [], contexts: [], ids: [] };
},
popHash: function popHash() {
var hash = this.hash;
this.hash = this.hashes.pop();
if (this.trackIds) {
this.push(this.objectLiteral(hash.ids));
}
if (this.stringParams) {
this.push(this.objectLiteral(hash.contexts));
this.push(this.objectLiteral(hash.types));
}
this.push(this.objectLiteral(hash.values));
},
// [pushString]
//
// On stack, before: ...
// On stack, after: quotedString(string), ...
//
// Push a quoted version of `string` onto the stack
pushString: function pushString(string) {
this.pushStackLiteral(this.quotedString(string));
},
// [pushLiteral]
//
// On stack, before: ...
// On stack, after: value, ...
//
// Pushes a value onto the stack. This operation prevents
// the compiler from creating a temporary variable to hold
// it.
pushLiteral: function pushLiteral(value) {
this.pushStackLiteral(value);
},
// [pushProgram]
//
// On stack, before: ...
// On stack, after: program(guid), ...
//
// Push a program expression onto the stack. This takes
// a compile-time guid and converts it into a runtime-accessible
// expression.
pushProgram: function pushProgram(guid) {
if (guid != null) {
this.pushStackLiteral(this.programExpression(guid));
} else {
this.pushStackLiteral(null);
}
},
// [invokeHelper]
//
// On stack, before: hash, inverse, program, params..., ...
// On stack, after: result of helper invocation
//
// Pops off the helper's parameters, invokes the helper,
// and pushes the helper's return value onto the stack.
//
// If the helper is not found, `helperMissing` is called.
invokeHelper: function invokeHelper(paramSize, name, isSimple) {
var nonHelper = this.popStack(),
helper = this.setupHelper(paramSize, name),
simple = isSimple ? [helper.name, ' || '] : '';
var lookup = ['('].concat(simple, nonHelper);
if (!this.options.strict) {
lookup.push(' || ', this.aliasable('helpers.helperMissing'));
}
lookup.push(')');
this.push(this.source.functionCall(lookup, 'call', helper.callParams));
},
// [invokeKnownHelper]
//
// On stack, before: hash, inverse, program, params..., ...
// On stack, after: result of helper invocation
//
// This operation is used when the helper is known to exist,
// so a `helperMissing` fallback is not required.
invokeKnownHelper: function invokeKnownHelper(paramSize, name) {
var helper = this.setupHelper(paramSize, name);
this.push(this.source.functionCall(helper.name, 'call', helper.callParams));
},
// [invokeAmbiguous]
//
// On stack, before: hash, inverse, program, params..., ...
// On stack, after: result of disambiguation
//
// This operation is used when an expression like `{{foo}}`
// is provided, but we don't know at compile-time whether it
// is a helper or a path.
//
// This operation emits more code than the other options,
// and can be avoided by passing the `knownHelpers` and
// `knownHelpersOnly` flags at compile-time.
invokeAmbiguous: function invokeAmbiguous(name, helperCall) {
this.useRegister('helper');
var nonHelper = this.popStack();
this.emptyHash();
var helper = this.setupHelper(0, name, helperCall);
var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')'];
if (!this.options.strict) {
lookup[0] = '(helper = ';
lookup.push(' != null ? helper : ', this.aliasable('helpers.helperMissing'));
}
this.push(['(', lookup, helper.paramsInit ? ['),(', helper.paramsInit] : [], '),', '(typeof helper === ', this.aliasable('"function"'), ' ? ', this.source.functionCall('helper', 'call', helper.callParams), ' : helper))']);
},
// [invokePartial]
//
// On stack, before: context, ...
// On stack after: result of partial invocation
//
// This operation pops off a context, invokes a partial with that context,
// and pushes the result of the invocation back.
invokePartial: function invokePartial(isDynamic, name, indent) {
var params = [],
options = this.setupParams(name, 1, params, false);
if (isDynamic) {
name = this.popStack();
delete options.name;
}
if (indent) {
options.indent = JSON.stringify(indent);
}
options.helpers = 'helpers';
options.partials = 'partials';
if (!isDynamic) {
params.unshift(this.nameLookup('partials', name, 'partial'));
} else {
params.unshift(name);
}
if (this.options.compat) {
options.depths = 'depths';
}
options = this.objectLiteral(options);
params.push(options);
this.push(this.source.functionCall('this.invokePartial', '', params));
},
// [assignToHash]
//
// On stack, before: value, ..., hash, ...
// On stack, after: ..., hash, ...
//
// Pops a value off the stack and assigns it to the current hash
assignToHash: function assignToHash(key) {
var value = this.popStack(),
context = undefined,
type = undefined,
id = undefined;
if (this.trackIds) {
id = this.popStack();
}
if (this.stringParams) {
type = this.popStack();
context = this.popStack();
}
var hash = this.hash;
if (context) {
hash.contexts[key] = context;
}
if (type) {
hash.types[key] = type;
}
if (id) {
hash.ids[key] = id;
}
hash.values[key] = value;
},
pushId: function pushId(type, name, child) {
if (type === 'BlockParam') {
this.pushStackLiteral('blockParams[' + name[0] + '].path[' + name[1] + ']' + (child ? ' + ' + JSON.stringify('.' + child) : ''));
} else if (type === 'PathExpression') {
this.pushString(name);
} else if (type === 'SubExpression') {
this.pushStackLiteral('true');
} else {
this.pushStackLiteral('null');
}
},
// HELPERS
compiler: JavaScriptCompiler,
compileChildren: function compileChildren(environment, options) {
var children = environment.children,
child = undefined,
compiler = undefined;
for (var i = 0, l = children.length; i < l; i++) {
child = children[i];
compiler = new this.compiler(); // eslint-disable-line new-cap
var index = this.matchExistingProgram(child);
if (index == null) {
this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
index = this.context.programs.length;
child.index = index;
child.name = 'program' + index;
this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile);
this.context.environments[index] = child;
this.useDepths = this.useDepths || compiler.useDepths;
this.useBlockParams = this.useBlockParams || compiler.useBlockParams;
} else {
child.index = index;
child.name = 'program' + index;
this.useDepths = this.useDepths || child.useDepths;
this.useBlockParams = this.useBlockParams || child.useBlockParams;
}
}
},
matchExistingProgram: function matchExistingProgram(child) {
for (var i = 0, len = this.context.environments.length; i < len; i++) {
var environment = this.context.environments[i];
if (environment && environment.equals(child)) {
return i;
}
}
},
programExpression: function programExpression(guid) {
var child = this.environment.children[guid],
programParams = [child.index, 'data', child.blockParams];
if (this.useBlockParams || this.useDepths) {
programParams.push('blockParams');
}
if (this.useDepths) {
programParams.push('depths');
}
return 'this.program(' + programParams.join(', ') + ')';
},
useRegister: function useRegister(name) {
if (!this.registers[name]) {
this.registers[name] = true;
this.registers.list.push(name);
}
},
push: function push(expr) {
if (!(expr instanceof Literal)) {
expr = this.source.wrap(expr);
}
this.inlineStack.push(expr);
return expr;
},
pushStackLiteral: function pushStackLiteral(item) {
this.push(new Literal(item));
},
pushSource: function pushSource(source) {
if (this.pendingContent) {
this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation));
this.pendingContent = undefined;
}
if (source) {
this.source.push(source);
}
},
replaceStack: function replaceStack(callback) {
var prefix = ['('],
stack = undefined,
createdStack = undefined,
usedLiteral = undefined;
/* istanbul ignore next */
if (!this.isInline()) {
throw new _Exception2['default']('replaceStack on non-inline');
}
// We want to merge the inline statement into the replacement statement via ','
var top = this.popStack(true);
if (top instanceof Literal) {
// Literals do not need to be inlined
stack = [top.value];
prefix = ['(', stack];
usedLiteral = true;
} else {
// Get or create the current stack name for use by the inline
createdStack = true;
var _name = this.incrStack();
prefix = ['((', this.push(_name), ' = ', top, ')'];
stack = this.topStack();
}
var item = callback.call(this, stack);
if (!usedLiteral) {
this.popStack();
}
if (createdStack) {
this.stackSlot--;
}
this.push(prefix.concat(item, ')'));
},
incrStack: function incrStack() {
this.stackSlot++;
if (this.stackSlot > this.stackVars.length) {
this.stackVars.push('stack' + this.stackSlot);
}
return this.topStackName();
},
topStackName: function topStackName() {
return 'stack' + this.stackSlot;
},
flushInline: function flushInline() {
var inlineStack = this.inlineStack;
this.inlineStack = [];
for (var i = 0, len = inlineStack.length; i < len; i++) {
var entry = inlineStack[i];
/* istanbul ignore if */
if (entry instanceof Literal) {
this.compileStack.push(entry);
} else {
var stack = this.incrStack();
this.pushSource([stack, ' = ', entry, ';']);
this.compileStack.push(stack);
}
}
},
isInline: function isInline() {
return this.inlineStack.length;
},
popStack: function popStack(wrapped) {
var inline = this.isInline(),
item = (inline ? this.inlineStack : this.compileStack).pop();
if (!wrapped && item instanceof Literal) {
return item.value;
} else {
if (!inline) {
/* istanbul ignore next */
if (!this.stackSlot) {
throw new _Exception2['default']('Invalid stack pop');
}
this.stackSlot--;
}
return item;
}
},
topStack: function topStack() {
var stack = this.isInline() ? this.inlineStack : this.compileStack,
item = stack[stack.length - 1];
/* istanbul ignore if */
if (item instanceof Literal) {
return item.value;
} else {
return item;
}
},
contextName: function contextName(context) {
if (this.useDepths && context) {
return 'depths[' + context + ']';
} else {
return 'depth' + context;
}
},
quotedString: function quotedString(str) {
return this.source.quotedString(str);
},
objectLiteral: function objectLiteral(obj) {
return this.source.objectLiteral(obj);
},
aliasable: function aliasable(name) {
var ret = this.aliases[name];
if (ret) {
ret.referenceCount++;
return ret;
}
ret = this.aliases[name] = this.source.wrap(name);
ret.aliasable = true;
ret.referenceCount = 1;
return ret;
},
setupHelper: function setupHelper(paramSize, name, blockHelper) {
var params = [],
paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper);
var foundHelper = this.nameLookup('helpers', name, 'helper');
return {
params: params,
paramsInit: paramsInit,
name: foundHelper,
callParams: [this.contextName(0)].concat(params)
};
},
setupParams: function setupParams(helper, paramSize, params) {
var options = {},
contexts = [],
types = [],
ids = [],
param = undefined;
options.name = this.quotedString(helper);
options.hash = this.popStack();
if (this.trackIds) {
options.hashIds = this.popStack();
}
if (this.stringParams) {
options.hashTypes = this.popStack();
options.hashContexts = this.popStack();
}
var inverse = this.popStack(),
program = this.popStack();
// Avoid setting fn and inverse if neither are set. This allows
// helpers to do a check for `if (options.fn)`
if (program || inverse) {
options.fn = program || 'this.noop';
options.inverse = inverse || 'this.noop';
}
// The parameters go on to the stack in order (making sure that they are evaluated in order)
// so we need to pop them off the stack in reverse order
var i = paramSize;
while (i--) {
param = this.popStack();
params[i] = param;
if (this.trackIds) {
ids[i] = this.popStack();
}
if (this.stringParams) {
types[i] = this.popStack();
contexts[i] = this.popStack();
}
}
if (this.trackIds) {
options.ids = this.source.generateArray(ids);
}
if (this.stringParams) {
options.types = this.source.generateArray(types);
options.contexts = this.source.generateArray(contexts);
}
if (this.options.data) {
options.data = 'data';
}
if (this.useBlockParams) {
options.blockParams = 'blockParams';
}
return options;
},
setupHelperArgs: function setupHelperArgs(helper, paramSize, params, useRegister) {
var options = this.setupParams(helper, paramSize, params, true);
options = this.objectLiteral(options);
if (useRegister) {
this.useRegister('options');
params.push('options');
return ['options=', options];
} else {
params.push(options);
return '';
}
}
};
(function () {
var reservedWords = ('break else new var' + ' case finally return void' + ' catch for switch while' + ' continue function this with' + ' default if throw' + ' delete in try' + ' do instanceof typeof' + ' abstract enum int short' + ' boolean export interface static' + ' byte extends long super' + ' char final native synchronized' + ' class float package throws' + ' const goto private transient' + ' debugger implements protected volatile' + ' double import public let yield await' + ' null true false').split(' ');
var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
for (var i = 0, l = reservedWords.length; i < l; i++) {
compilerWords[reservedWords[i]] = true;
}
})();
JavaScriptCompiler.isValidJavaScriptVariableName = function (name) {
return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name);
};
function strictLookup(requireTerminal, compiler, parts, type) {
var stack = compiler.popStack(),
i = 0,
len = parts.length;
if (requireTerminal) {
len--;
}
for (; i < len; i++) {
stack = compiler.nameLookup(stack, parts[i], type);
}
if (requireTerminal) {
return [compiler.aliasable('this.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ')'];
} else {
return stack;
}
}
exports['default'] = JavaScriptCompiler;
module.exports = exports['default'];
/***/
},
/* 6 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
var _interopRequireWildcard = __webpack_require__(8)['default'];
exports.__esModule = true;
var _Exception = __webpack_require__(11);
var _Exception2 = _interopRequireWildcard(_Exception);
var _AST = __webpack_require__(2);
var _AST2 = _interopRequireWildcard(_AST);
function Visitor() {
this.parents = [];
}
Visitor.prototype = {
constructor: Visitor,
mutating: false,
// Visits a given value. If mutating, will replace the value if necessary.
acceptKey: function acceptKey(node, name) {
var value = this.accept(node[name]);
if (this.mutating) {
// Hacky sanity check:
if (value && (!value.type || !_AST2['default'][value.type])) {
throw new _Exception2['default']('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type);
}
node[name] = value;
}
},
// Performs an accept operation with added sanity check to ensure
// required keys are not removed.
acceptRequired: function acceptRequired(node, name) {
this.acceptKey(node, name);
if (!node[name]) {
throw new _Exception2['default'](node.type + ' requires ' + name);
}
},
// Traverses a given array. If mutating, empty respnses will be removed
// for child elements.
acceptArray: function acceptArray(array) {
for (var i = 0, l = array.length; i < l; i++) {
this.acceptKey(array, i);
if (!array[i]) {
array.splice(i, 1);
i--;
l--;
}
}
},
accept: function accept(object) {
if (!object) {
return;
}
if (this.current) {
this.parents.unshift(this.current);
}
this.current = object;
var ret = this[object.type](object);
this.current = this.parents.shift();
if (!this.mutating || ret) {
return ret;
} else if (ret !== false) {
return object;
}
},
Program: function Program(program) {
this.acceptArray(program.body);
},
MustacheStatement: function MustacheStatement(mustache) {
this.acceptRequired(mustache, 'path');
this.acceptArray(mustache.params);
this.acceptKey(mustache, 'hash');
},
BlockStatement: function BlockStatement(block) {
this.acceptRequired(block, 'path');
this.acceptArray(block.params);
this.acceptKey(block, 'hash');
this.acceptKey(block, 'program');
this.acceptKey(block, 'inverse');
},
PartialStatement: function PartialStatement(partial) {
this.acceptRequired(partial, 'name');
this.acceptArray(partial.params);
this.acceptKey(partial, 'hash');
},
ContentStatement: function ContentStatement() { },
CommentStatement: function CommentStatement() { },
SubExpression: function SubExpression(sexpr) {
this.acceptRequired(sexpr, 'path');
this.acceptArray(sexpr.params);
this.acceptKey(sexpr, 'hash');
},
PathExpression: function PathExpression() { },
StringLiteral: function StringLiteral() { },
NumberLiteral: function NumberLiteral() { },
BooleanLiteral: function BooleanLiteral() { },
UndefinedLiteral: function UndefinedLiteral() { },
NullLiteral: function NullLiteral() { },
Hash: function Hash(hash) {
this.acceptArray(hash.pairs);
},
HashPair: function HashPair(pair) {
this.acceptRequired(pair, 'value');
}
};
exports['default'] = Visitor;
module.exports = exports['default'];
/* content */ /* comment */ /* path */ /* string */ /* number */ /* bool */ /* literal */ /* literal */
/***/
},
/* 7 */
/***/ function (module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function (global) {
'use strict';
exports.__esModule = true;
/*global window */
exports['default'] = function (Handlebars) {
/* istanbul ignore next */
var root = typeof global !== 'undefined' ? global : window,
$Handlebars = root.Handlebars;
/* istanbul ignore next */
Handlebars.noConflict = function () {
if (root.Handlebars === Handlebars) {
root.Handlebars = $Handlebars;
}
};
};
module.exports = exports['default'];
/* WEBPACK VAR INJECTION */
}.call(exports, (function () { return this; }())))
/***/
},
/* 8 */
/***/ function (module, exports, __webpack_require__) {
"use strict";
exports["default"] = function (obj) {
return obj && obj.__esModule ? obj : {
"default": obj
};
};
exports.__esModule = true;
/***/
},
/* 9 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
var _interopRequireWildcard = __webpack_require__(8)['default'];
exports.__esModule = true;
exports.HandlebarsEnvironment = HandlebarsEnvironment;
exports.createFrame = createFrame;
var _import = __webpack_require__(12);
var Utils = _interopRequireWildcard(_import);
var _Exception = __webpack_require__(11);
var _Exception2 = _interopRequireWildcard(_Exception);
var VERSION = '3.0.1';
exports.VERSION = VERSION;
var COMPILER_REVISION = 6;
exports.COMPILER_REVISION = COMPILER_REVISION;
var REVISION_CHANGES = {
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
2: '== 1.0.0-rc.3',
3: '== 1.0.0-rc.4',
4: '== 1.x.x',
5: '== 2.0.0-alpha.x',
6: '>= 2.0.0-beta.1'
};
exports.REVISION_CHANGES = REVISION_CHANGES;
var isArray = Utils.isArray,
isFunction = Utils.isFunction,
toString = Utils.toString,
objectType = '[object Object]';
function HandlebarsEnvironment(helpers, partials) {
this.helpers = helpers || {};
this.partials = partials || {};
registerDefaultHelpers(this);
}
HandlebarsEnvironment.prototype = {
constructor: HandlebarsEnvironment,
logger: logger,
log: log,
registerHelper: function registerHelper(name, fn) {
if (toString.call(name) === objectType) {
if (fn) {
throw new _Exception2['default']('Arg not supported with multiple helpers');
}
Utils.extend(this.helpers, name);
} else {
this.helpers[name] = fn;
}
},
unregisterHelper: function unregisterHelper(name) {
delete this.helpers[name];
},
registerPartial: function registerPartial(name, partial) {
if (toString.call(name) === objectType) {
Utils.extend(this.partials, name);
} else {
if (typeof partial === 'undefined') {
throw new _Exception2['default']('Attempting to register a partial as undefined');
}
this.partials[name] = partial;
}
},
unregisterPartial: function unregisterPartial(name) {
delete this.partials[name];
}
};
function registerDefaultHelpers(instance) {
instance.registerHelper('helperMissing', function () {
if (arguments.length === 1) {
// A missing field in a {{foo}} constuct.
return undefined;
} else {
// Someone is actually trying to call something, blow up.
throw new _Exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"');
}
});
instance.registerHelper('blockHelperMissing', function (context, options) {
var inverse = options.inverse,
fn = options.fn;
if (context === true) {
return fn(this);
} else if (context === false || context == null) {
return inverse(this);
} else if (isArray(context)) {
if (context.length > 0) {
if (options.ids) {
options.ids = [options.name];
}
return instance.helpers.each(context, options);
} else {
return inverse(this);
}
} else {
if (options.data && options.ids) {
var data = createFrame(options.data);
data.contextPath = Utils.appendContextPath(options.data.contextPath, options.name);
options = { data: data };
}
return fn(context, options);
}
});
instance.registerHelper('each', function (context, options) {
if (!options) {
throw new _Exception2['default']('Must pass iterator to #each');
}
var fn = options.fn,
inverse = options.inverse,
i = 0,
ret = '',
data = undefined,
contextPath = undefined;
if (options.data && options.ids) {
contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.';
}
if (isFunction(context)) {
context = context.call(this);
}
if (options.data) {
data = createFrame(options.data);
}
function execIteration(field, index, last) {
if (data) {
data.key = field;
data.index = index;
data.first = index === 0;
data.last = !!last;
if (contextPath) {
data.contextPath = contextPath + field;
}
}
ret = ret + fn(context[field], {
data: data,
blockParams: Utils.blockParams([context[field], field], [contextPath + field, null])
});
}
if (context && typeof context === 'object') {
if (isArray(context)) {
for (var j = context.length; i < j; i++) {
execIteration(i, i, i === context.length - 1);
}
} else {
var priorKey = undefined;
for (var key in context) {
if (context.hasOwnProperty(key)) {
// We're running the iterations one step out of sync so we can detect
// the last iteration without have to scan the object twice and create
// an itermediate keys array.
if (priorKey) {
execIteration(priorKey, i - 1);
}
priorKey = key;
i++;
}
}
if (priorKey) {
execIteration(priorKey, i - 1, true);
}
}
}
if (i === 0) {
ret = inverse(this);
}
return ret;
});
instance.registerHelper('if', function (conditional, options) {
if (isFunction(conditional)) {
conditional = conditional.call(this);
}
// Default behavior is to render the positive path if the value is truthy and not empty.
// The `includeZero` option may be set to treat the condtional as purely not empty based on the
// behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
if (!options.hash.includeZero && !conditional || Utils.isEmpty(conditional)) {
return options.inverse(this);
} else {
return options.fn(this);
}
});
instance.registerHelper('unless', function (conditional, options) {
return instance.helpers['if'].call(this, conditional, { fn: options.inverse, inverse: options.fn, hash: options.hash });
});
instance.registerHelper('with', function (context, options) {
if (isFunction(context)) {
context = context.call(this);
}
var fn = options.fn;
if (!Utils.isEmpty(context)) {
if (options.data && options.ids) {
var data = createFrame(options.data);
data.contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]);
options = { data: data };
}
return fn(context, options);
} else {
return options.inverse(this);
}
});
instance.registerHelper('log', function (message, options) {
var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
instance.log(level, message);
});
instance.registerHelper('lookup', function (obj, field) {
return obj && obj[field];
});
}
var logger = {
methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' },
// State enum
DEBUG: 0,
INFO: 1,
WARN: 2,
ERROR: 3,
level: 1,
// Can be overridden in the host environment
log: function log(level, message) {
if (typeof console !== 'undefined' && logger.level <= level) {
var method = logger.methodMap[level];
(console[method] || console.log).call(console, message); // eslint-disable-line no-console
}
}
};
exports.logger = logger;
var log = logger.log;
exports.log = log;
function createFrame(object) {
var frame = Utils.extend({}, object);
frame._parent = object;
return frame;
}
/* [args, ]options */
/***/
},
/* 10 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
// Build out our basic SafeString type
function SafeString(string) {
this.string = string;
}
SafeString.prototype.toString = SafeString.prototype.toHTML = function () {
return '' + this.string;
};
exports['default'] = SafeString;
module.exports = exports['default'];
/***/
},
/* 11 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
function Exception(message, node) {
var loc = node && node.loc,
line = undefined,
column = undefined;
if (loc) {
line = loc.start.line;
column = loc.start.column;
message += ' - ' + line + ':' + column;
}
var tmp = Error.prototype.constructor.call(this, message);
// Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
for (var idx = 0; idx < errorProps.length; idx++) {
this[errorProps[idx]] = tmp[errorProps[idx]];
}
if (Error.captureStackTrace) {
Error.captureStackTrace(this, Exception);
}
if (loc) {
this.lineNumber = line;
this.column = column;
}
}
Exception.prototype = new Error();
exports['default'] = Exception;
module.exports = exports['default'];
/***/
},
/* 12 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
exports.extend = extend;
// Older IE versions do not directly support indexOf so we must implement our own, sadly.
exports.indexOf = indexOf;
exports.escapeExpression = escapeExpression;
exports.isEmpty = isEmpty;
exports.blockParams = blockParams;
exports.appendContextPath = appendContextPath;
var escape = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
'\'': ''',
'`': '`'
};
var badChars = /[&<>"'`]/g,
possible = /[&<>"'`]/;
function escapeChar(chr) {
return escape[chr];
}
function extend(obj /* , ...source */) {
for (var i = 1; i < arguments.length; i++) {
for (var key in arguments[i]) {
if (Object.prototype.hasOwnProperty.call(arguments[i], key)) {
obj[key] = arguments[i][key];
}
}
}
return obj;
}
var toString = Object.prototype.toString;
exports.toString = toString;
// Sourced from lodash
// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
/*eslint-disable func-style, no-var */
var isFunction = function isFunction(value) {
return typeof value === 'function';
};
// fallback for older versions of Chrome and Safari
/* istanbul ignore next */
if (isFunction(/x/)) {
exports.isFunction = isFunction = function (value) {
return typeof value === 'function' && toString.call(value) === '[object Function]';
};
}
var isFunction;
exports.isFunction = isFunction;
/*eslint-enable func-style, no-var */
/* istanbul ignore next */
var isArray = Array.isArray || function (value) {
return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false;
}; exports.isArray = isArray;
function indexOf(array, value) {
for (var i = 0, len = array.length; i < len; i++) {
if (array[i] === value) {
return i;
}
}
return -1;
}
function escapeExpression(string) {
if (typeof string !== 'string') {
// don't escape SafeStrings, since they're already safe
if (string && string.toHTML) {
return string.toHTML();
} else if (string == null) {
return '';
} else if (!string) {
return string + '';
}
// Force a string conversion as this will be done by the append regardless and
// the regex test will do this transparently behind the scenes, causing issues if
// an object's to string has escaped characters in it.
string = '' + string;
}
if (!possible.test(string)) {
return string;
}
return string.replace(badChars, escapeChar);
}
function isEmpty(value) {
if (!value && value !== 0) {
return true;
} else if (isArray(value) && value.length === 0) {
return true;
} else {
return false;
}
}
function blockParams(params, ids) {
params.path = ids;
return params;
}
function appendContextPath(contextPath, id) {
return (contextPath ? contextPath + '.' : '') + id;
}
/***/
},
/* 13 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
var _interopRequireWildcard = __webpack_require__(8)['default'];
exports.__esModule = true;
exports.checkRevision = checkRevision;
// TODO: Remove this line and break up compilePartial
exports.template = template;
exports.wrapProgram = wrapProgram;
exports.resolvePartial = resolvePartial;
exports.invokePartial = invokePartial;
exports.noop = noop;
var _import = __webpack_require__(12);
var Utils = _interopRequireWildcard(_import);
var _Exception = __webpack_require__(11);
var _Exception2 = _interopRequireWildcard(_Exception);
var _COMPILER_REVISION$REVISION_CHANGES$createFrame = __webpack_require__(9);
function checkRevision(compilerInfo) {
var compilerRevision = compilerInfo && compilerInfo[0] || 1,
currentRevision = _COMPILER_REVISION$REVISION_CHANGES$createFrame.COMPILER_REVISION;
if (compilerRevision !== currentRevision) {
if (compilerRevision < currentRevision) {
var runtimeVersions = _COMPILER_REVISION$REVISION_CHANGES$createFrame.REVISION_CHANGES[currentRevision],
compilerVersions = _COMPILER_REVISION$REVISION_CHANGES$createFrame.REVISION_CHANGES[compilerRevision];
throw new _Exception2['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').');
} else {
// Use the embedded version info since the runtime doesn't know about this revision yet
throw new _Exception2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').');
}
}
}
function template(templateSpec, env) {
/* istanbul ignore next */
if (!env) {
throw new _Exception2['default']('No environment passed to template');
}
if (!templateSpec || !templateSpec.main) {
throw new _Exception2['default']('Unknown template object: ' + typeof templateSpec);
}
// Note: Using env.VM references rather than local var references throughout this section to allow
// for external users to override these as psuedo-supported APIs.
env.VM.checkRevision(templateSpec.compiler);
function invokePartialWrapper(partial, context, options) {
if (options.hash) {
context = Utils.extend({}, context, options.hash);
}
partial = env.VM.resolvePartial.call(this, partial, context, options);
var result = env.VM.invokePartial.call(this, partial, context, options);
if (result == null && env.compile) {
options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
result = options.partials[options.name](context, options);
}
if (result != null) {
if (options.indent) {
var lines = result.split('\n');
for (var i = 0, l = lines.length; i < l; i++) {
if (!lines[i] && i + 1 === l) {
break;
}
lines[i] = options.indent + lines[i];
}
result = lines.join('\n');
}
return result;
} else {
throw new _Exception2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode');
}
}
// Just add water
var container = {
strict: function strict(obj, name) {
if (!(name in obj)) {
throw new _Exception2['default']('"' + name + '" not defined in ' + obj);
}
return obj[name];
},
lookup: function lookup(depths, name) {
var len = depths.length;
for (var i = 0; i < len; i++) {
if (depths[i] && depths[i][name] != null) {
return depths[i][name];
}
}
},
lambda: function lambda(current, context) {
return typeof current === 'function' ? current.call(context) : current;
},
escapeExpression: Utils.escapeExpression,
invokePartial: invokePartialWrapper,
fn: function fn(i) {
return templateSpec[i];
},
programs: [],
program: function program(i, data, declaredBlockParams, blockParams, depths) {
var programWrapper = this.programs[i],
fn = this.fn(i);
if (data || depths || blockParams || declaredBlockParams) {
programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths);
} else if (!programWrapper) {
programWrapper = this.programs[i] = wrapProgram(this, i, fn);
}
return programWrapper;
},
data: function data(value, depth) {
while (value && depth--) {
value = value._parent;
}
return value;
},
merge: function merge(param, common) {
var obj = param || common;
if (param && common && param !== common) {
obj = Utils.extend({}, common, param);
}
return obj;
},
noop: env.VM.noop,
compilerInfo: templateSpec.compiler
};
function ret(context) {
var options = arguments[1] === undefined ? {} : arguments[1];
var data = options.data;
ret._setup(options);
if (!options.partial && templateSpec.useData) {
data = initData(context, data);
}
var depths = undefined,
blockParams = templateSpec.useBlockParams ? [] : undefined;
if (templateSpec.useDepths) {
depths = options.depths ? [context].concat(options.depths) : [context];
}
return templateSpec.main.call(container, context, container.helpers, container.partials, data, blockParams, depths);
}
ret.isTop = true;
ret._setup = function (options) {
if (!options.partial) {
container.helpers = container.merge(options.helpers, env.helpers);
if (templateSpec.usePartial) {
container.partials = container.merge(options.partials, env.partials);
}
} else {
container.helpers = options.helpers;
container.partials = options.partials;
}
};
ret._child = function (i, data, blockParams, depths) {
if (templateSpec.useBlockParams && !blockParams) {
throw new _Exception2['default']('must pass block params');
}
if (templateSpec.useDepths && !depths) {
throw new _Exception2['default']('must pass parent depths');
}
return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths);
};
return ret;
}
function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) {
function prog(context) {
var options = arguments[1] === undefined ? {} : arguments[1];
return fn.call(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), depths && [context].concat(depths));
}
prog.program = i;
prog.depth = depths ? depths.length : 0;
prog.blockParams = declaredBlockParams || 0;
return prog;
}
function resolvePartial(partial, context, options) {
if (!partial) {
partial = options.partials[options.name];
} else if (!partial.call && !options.name) {
// This is a dynamic partial that returned a string
options.name = partial;
partial = options.partials[partial];
}
return partial;
}
function invokePartial(partial, context, options) {
options.partial = true;
if (partial === undefined) {
throw new _Exception2['default']('The partial ' + options.name + ' could not be found');
} else if (partial instanceof Function) {
return partial(context, options);
}
}
function noop() {
return '';
}
function initData(context, data) {
if (!data || !('root' in data)) {
data = data ? _COMPILER_REVISION$REVISION_CHANGES$createFrame.createFrame(data) : {};
data.root = context;
}
return data;
}
/***/
},
/* 14 */
/***/ function (module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
/* istanbul ignore next */
/* Jison generated parser */
var handlebars = (function () {
var parser = {
trace: function trace() { },
yy: {},
symbols_: { error: 2, root: 3, program: 4, EOF: 5, program_repetition0: 6, statement: 7, mustache: 8, block: 9, rawBlock: 10, partial: 11, content: 12, COMMENT: 13, CONTENT: 14, openRawBlock: 15, END_RAW_BLOCK: 16, OPEN_RAW_BLOCK: 17, helperName: 18, openRawBlock_repetition0: 19, openRawBlock_option0: 20, CLOSE_RAW_BLOCK: 21, openBlock: 22, block_option0: 23, closeBlock: 24, openInverse: 25, block_option1: 26, OPEN_BLOCK: 27, openBlock_repetition0: 28, openBlock_option0: 29, openBlock_option1: 30, CLOSE: 31, OPEN_INVERSE: 32, openInverse_repetition0: 33, openInverse_option0: 34, openInverse_option1: 35, openInverseChain: 36, OPEN_INVERSE_CHAIN: 37, openInverseChain_repetition0: 38, openInverseChain_option0: 39, openInverseChain_option1: 40, inverseAndProgram: 41, INVERSE: 42, inverseChain: 43, inverseChain_option0: 44, OPEN_ENDBLOCK: 45, OPEN: 46, mustache_repetition0: 47, mustache_option0: 48, OPEN_UNESCAPED: 49, mustache_repetition1: 50, mustache_option1: 51, CLOSE_UNESCAPED: 52, OPEN_PARTIAL: 53, partialName: 54, partial_repetition0: 55, partial_option0: 56, param: 57, sexpr: 58, OPEN_SEXPR: 59, sexpr_repetition0: 60, sexpr_option0: 61, CLOSE_SEXPR: 62, hash: 63, hash_repetition_plus0: 64, hashSegment: 65, ID: 66, EQUALS: 67, blockParams: 68, OPEN_BLOCK_PARAMS: 69, blockParams_repetition_plus0: 70, CLOSE_BLOCK_PARAMS: 71, path: 72, dataName: 73, STRING: 74, NUMBER: 75, BOOLEAN: 76, UNDEFINED: 77, NULL: 78, DATA: 79, pathSegments: 80, SEP: 81, $accept: 0, $end: 1 },
terminals_: { 2: "error", 5: "EOF", 13: "COMMENT", 14: "CONTENT", 16: "END_RAW_BLOCK", 17: "OPEN_RAW_BLOCK", 21: "CLOSE_RAW_BLOCK", 27: "OPEN_BLOCK", 31: "CLOSE", 32: "OPEN_INVERSE", 37: "OPEN_INVERSE_CHAIN", 42: "INVERSE", 45: "OPEN_ENDBLOCK", 46: "OPEN", 49: "OPEN_UNESCAPED", 52: "CLOSE_UNESCAPED", 53: "OPEN_PARTIAL", 59: "OPEN_SEXPR", 62: "CLOSE_SEXPR", 66: "ID", 67: "EQUALS", 69: "OPEN_BLOCK_PARAMS", 71: "CLOSE_BLOCK_PARAMS", 74: "STRING", 75: "NUMBER", 76: "BOOLEAN", 77: "UNDEFINED", 78: "NULL", 79: "DATA", 81: "SEP" },
productions_: [0, [3, 2], [4, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [12, 1], [10, 3], [15, 5], [9, 4], [9, 4], [22, 6], [25, 6], [36, 6], [41, 2], [43, 3], [43, 1], [24, 3], [8, 5], [8, 5], [11, 5], [57, 1], [57, 1], [58, 5], [63, 1], [65, 3], [68, 3], [18, 1], [18, 1], [18, 1], [18, 1], [18, 1], [18, 1], [18, 1], [54, 1], [54, 1], [73, 2], [72, 1], [80, 3], [80, 1], [6, 0], [6, 2], [19, 0], [19, 2], [20, 0], [20, 1], [23, 0], [23, 1], [26, 0], [26, 1], [28, 0], [28, 2], [29, 0], [29, 1], [30, 0], [30, 1], [33, 0], [33, 2], [34, 0], [34, 1], [35, 0], [35, 1], [38, 0], [38, 2], [39, 0], [39, 1], [40, 0], [40, 1], [44, 0], [44, 1], [47, 0], [47, 2], [48, 0], [48, 1], [50, 0], [50, 2], [51, 0], [51, 1], [55, 0], [55, 2], [56, 0], [56, 1], [60, 0], [60, 2], [61, 0], [61, 1], [64, 1], [64, 2], [70, 1], [70, 2]],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
var $0 = $$.length - 1;
switch (yystate) {
case 1:
return $$[$0 - 1];
break;
case 2:
this.$ = new yy.Program($$[$0], null, {}, yy.locInfo(this._$));
break;
case 3:
this.$ = $$[$0];
break;
case 4:
this.$ = $$[$0];
break;
case 5:
this.$ = $$[$0];
break;
case 6:
this.$ = $$[$0];
break;
case 7:
this.$ = $$[$0];
break;
case 8:
this.$ = new yy.CommentStatement(yy.stripComment($$[$0]), yy.stripFlags($$[$0], $$[$0]), yy.locInfo(this._$));
break;
case 9:
this.$ = new yy.ContentStatement($$[$0], yy.locInfo(this._$));
break;
case 10:
this.$ = yy.prepareRawBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$);
break;
case 11:
this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1] };
break;
case 12:
this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], false, this._$);
break;
case 13:
this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], true, this._$);
break;
case 14:
this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
break;
case 15:
this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
break;
case 16:
this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) };
break;
case 17:
this.$ = { strip: yy.stripFlags($$[$0 - 1], $$[$0 - 1]), program: $$[$0] };
break;
case 18:
var inverse = yy.prepareBlock($$[$0 - 2], $$[$0 - 1], $$[$0], $$[$0], false, this._$),
program = new yy.Program([inverse], null, {}, yy.locInfo(this._$));
program.chained = true;
this.$ = { strip: $$[$0 - 2].strip, program: program, chain: true };
break;
case 19:
this.$ = $$[$0];
break;
case 20:
this.$ = { path: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 2], $$[$0]) };
break;
case 21:
this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$);
break;
case 22:
this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$);
break;
case 23:
this.$ = new yy.PartialStatement($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], yy.stripFlags($$[$0 - 4], $$[$0]), yy.locInfo(this._$));
break;
case 24:
this.$ = $$[$0];
break;
case 25:
this.$ = $$[$0];
break;
case 26:
this.$ = new yy.SubExpression($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], yy.locInfo(this._$));
break;
case 27:
this.$ = new yy.Hash($$[$0], yy.locInfo(this._$));
break;
case 28:
this.$ = new yy.HashPair(yy.id($$[$0 - 2]), $$[$0], yy.locInfo(this._$));
break;
case 29:
this.$ = yy.id($$[$0 - 1]);
break;
case 30:
this.$ = $$[$0];
break;
case 31:
this.$ = $$[$0];
break;
case 32:
this.$ = new yy.StringLiteral($$[$0], yy.locInfo(this._$));
break;
case 33:
this.$ = new yy.NumberLiteral($$[$0], yy.locInfo(this._$));
break;
case 34:
this.$ = new yy.BooleanLiteral($$[$0], yy.locInfo(this._$));
break;
case 35:
this.$ = new yy.UndefinedLiteral(yy.locInfo(this._$));
break;
case 36:
this.$ = new yy.NullLiteral(yy.locInfo(this._$));
break;
case 37:
this.$ = $$[$0];
break;
case 38:
this.$ = $$[$0];
break;
case 39:
this.$ = yy.preparePath(true, $$[$0], this._$);
break;
case 40:
this.$ = yy.preparePath(false, $$[$0], this._$);
break;
case 41:
$$[$0 - 2].push({ part: yy.id($$[$0]), original: $$[$0], separator: $$[$0 - 1] }); this.$ = $$[$0 - 2];
break;
case 42:
this.$ = [{ part: yy.id($$[$0]), original: $$[$0] }];
break;
case 43:
this.$ = [];
break;
case 44:
$$[$0 - 1].push($$[$0]);
break;
case 45:
this.$ = [];
break;
case 46:
$$[$0 - 1].push($$[$0]);
break;
case 53:
this.$ = [];
break;
case 54:
$$[$0 - 1].push($$[$0]);
break;
case 59:
this.$ = [];
break;
case 60:
$$[$0 - 1].push($$[$0]);
break;
case 65:
this.$ = [];
break;
case 66:
$$[$0 - 1].push($$[$0]);
break;
case 73:
this.$ = [];
break;
case 74:
$$[$0 - 1].push($$[$0]);
break;
case 77:
this.$ = [];
break;
case 78:
$$[$0 - 1].push($$[$0]);
break;
case 81:
this.$ = [];
break;
case 82:
$$[$0 - 1].push($$[$0]);
break;
case 85:
this.$ = [];
break;
case 86:
$$[$0 - 1].push($$[$0]);
break;
case 89:
this.$ = [$$[$0]];
break;
case 90:
$$[$0 - 1].push($$[$0]);
break;
case 91:
this.$ = [$$[$0]];
break;
case 92:
$$[$0 - 1].push($$[$0]);
break;
}
},
table: [{ 3: 1, 4: 2, 5: [2, 43], 6: 3, 13: [2, 43], 14: [2, 43], 17: [2, 43], 27: [2, 43], 32: [2, 43], 46: [2, 43], 49: [2, 43], 53: [2, 43] }, { 1: [3] }, { 5: [1, 4] }, { 5: [2, 2], 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: [1, 11], 14: [1, 18], 15: 16, 17: [1, 21], 22: 14, 25: 15, 27: [1, 19], 32: [1, 20], 37: [2, 2], 42: [2, 2], 45: [2, 2], 46: [1, 12], 49: [1, 13], 53: [1, 17] }, { 1: [2, 1] }, { 5: [2, 44], 13: [2, 44], 14: [2, 44], 17: [2, 44], 27: [2, 44], 32: [2, 44], 37: [2, 44], 42: [2, 44], 45: [2, 44], 46: [2, 44], 49: [2, 44], 53: [2, 44] }, { 5: [2, 3], 13: [2, 3], 14: [2, 3], 17: [2, 3], 27: [2, 3], 32: [2, 3], 37: [2, 3], 42: [2, 3], 45: [2, 3], 46: [2, 3], 49: [2, 3], 53: [2, 3] }, { 5: [2, 4], 13: [2, 4], 14: [2, 4], 17: [2, 4], 27: [2, 4], 32: [2, 4], 37: [2, 4], 42: [2, 4], 45: [2, 4], 46: [2, 4], 49: [2, 4], 53: [2, 4] }, { 5: [2, 5], 13: [2, 5], 14: [2, 5], 17: [2, 5], 27: [2, 5], 32: [2, 5], 37: [2, 5], 42: [2, 5], 45: [2, 5], 46: [2, 5], 49: [2, 5], 53: [2, 5] }, { 5: [2, 6], 13: [2, 6], 14: [2, 6], 17: [2, 6], 27: [2, 6], 32: [2, 6], 37: [2, 6], 42: [2, 6], 45: [2, 6], 46: [2, 6], 49: [2, 6], 53: [2, 6] }, { 5: [2, 7], 13: [2, 7], 14: [2, 7], 17: [2, 7], 27: [2, 7], 32: [2, 7], 37: [2, 7], 42: [2, 7], 45: [2, 7], 46: [2, 7], 49: [2, 7], 53: [2, 7] }, { 5: [2, 8], 13: [2, 8], 14: [2, 8], 17: [2, 8], 27: [2, 8], 32: [2, 8], 37: [2, 8], 42: [2, 8], 45: [2, 8], 46: [2, 8], 49: [2, 8], 53: [2, 8] }, { 18: 22, 66: [1, 32], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 18: 33, 66: [1, 32], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 4: 34, 6: 3, 13: [2, 43], 14: [2, 43], 17: [2, 43], 27: [2, 43], 32: [2, 43], 37: [2, 43], 42: [2, 43], 45: [2, 43], 46: [2, 43], 49: [2, 43], 53: [2, 43] }, { 4: 35, 6: 3, 13: [2, 43], 14: [2, 43], 17: [2, 43], 27: [2, 43], 32: [2, 43], 42: [2, 43], 45: [2, 43], 46: [2, 43], 49: [2, 43], 53: [2, 43] }, { 12: 36, 14: [1, 18] }, { 18: 38, 54: 37, 58: 39, 59: [1, 40], 66: [1, 32], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 5: [2, 9], 13: [2, 9], 14: [2, 9], 16: [2, 9], 17: [2, 9], 27: [2, 9], 32: [2, 9], 37: [2, 9], 42: [2, 9], 45: [2, 9], 46: [2, 9], 49: [2, 9], 53: [2, 9] }, { 18: 41, 66: [1, 32], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 18: 42, 66: [1, 32], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 18: 43, 66: [1, 32], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 31: [2, 73], 47: 44, 59: [2, 73], 66: [2, 73], 74: [2, 73], 75: [2, 73], 76: [2, 73], 77: [2, 73], 78: [2, 73], 79: [2, 73] }, { 21: [2, 30], 31: [2, 30], 52: [2, 30], 59: [2, 30], 62: [2, 30], 66: [2, 30], 69: [2, 30], 74: [2, 30], 75: [2, 30], 76: [2, 30], 77: [2, 30], 78: [2, 30], 79: [2, 30] }, { 21: [2, 31], 31: [2, 31], 52: [2, 31], 59: [2, 31], 62: [2, 31], 66: [2, 31], 69: [2, 31], 74: [2, 31], 75: [2, 31], 76: [2, 31], 77: [2, 31], 78: [2, 31], 79: [2, 31] }, { 21: [2, 32], 31: [2, 32], 52: [2, 32], 59: [2, 32], 62: [2, 32], 66: [2, 32], 69: [2, 32], 74: [2, 32], 75: [2, 32], 76: [2, 32], 77: [2, 32], 78: [2, 32], 79: [2, 32] }, { 21: [2, 33], 31: [2, 33], 52: [2, 33], 59: [2, 33], 62: [2, 33], 66: [2, 33], 69: [2, 33], 74: [2, 33], 75: [2, 33], 76: [2, 33], 77: [2, 33], 78: [2, 33], 79: [2, 33] }, { 21: [2, 34], 31: [2, 34], 52: [2, 34], 59: [2, 34], 62: [2, 34], 66: [2, 34], 69: [2, 34], 74: [2, 34], 75: [2, 34], 76: [2, 34], 77: [2, 34], 78: [2, 34], 79: [2, 34] }, { 21: [2, 35], 31: [2, 35], 52: [2, 35], 59: [2, 35], 62: [2, 35], 66: [2, 35], 69: [2, 35], 74: [2, 35], 75: [2, 35], 76: [2, 35], 77: [2, 35], 78: [2, 35], 79: [2, 35] }, { 21: [2, 36], 31: [2, 36], 52: [2, 36], 59: [2, 36], 62: [2, 36], 66: [2, 36], 69: [2, 36], 74: [2, 36], 75: [2, 36], 76: [2, 36], 77: [2, 36], 78: [2, 36], 79: [2, 36] }, { 21: [2, 40], 31: [2, 40], 52: [2, 40], 59: [2, 40], 62: [2, 40], 66: [2, 40], 69: [2, 40], 74: [2, 40], 75: [2, 40], 76: [2, 40], 77: [2, 40], 78: [2, 40], 79: [2, 40], 81: [1, 45] }, { 66: [1, 32], 80: 46 }, { 21: [2, 42], 31: [2, 42], 52: [2, 42], 59: [2, 42], 62: [2, 42], 66: [2, 42], 69: [2, 42], 74: [2, 42], 75: [2, 42], 76: [2, 42], 77: [2, 42], 78: [2, 42], 79: [2, 42], 81: [2, 42] }, { 50: 47, 52: [2, 77], 59: [2, 77], 66: [2, 77], 74: [2, 77], 75: [2, 77], 76: [2, 77], 77: [2, 77], 78: [2, 77], 79: [2, 77] }, { 23: 48, 36: 50, 37: [1, 52], 41: 51, 42: [1, 53], 43: 49, 45: [2, 49] }, { 26: 54, 41: 55, 42: [1, 53], 45: [2, 51] }, { 16: [1, 56] }, { 31: [2, 81], 55: 57, 59: [2, 81], 66: [2, 81], 74: [2, 81], 75: [2, 81], 76: [2, 81], 77: [2, 81], 78: [2, 81], 79: [2, 81] }, { 31: [2, 37], 59: [2, 37], 66: [2, 37], 74: [2, 37], 75: [2, 37], 76: [2, 37], 77: [2, 37], 78: [2, 37], 79: [2, 37] }, { 31: [2, 38], 59: [2, 38], 66: [2, 38], 74: [2, 38], 75: [2, 38], 76: [2, 38], 77: [2, 38], 78: [2, 38], 79: [2, 38] }, { 18: 58, 66: [1, 32], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 28: 59, 31: [2, 53], 59: [2, 53], 66: [2, 53], 69: [2, 53], 74: [2, 53], 75: [2, 53], 76: [2, 53], 77: [2, 53], 78: [2, 53], 79: [2, 53] }, { 31: [2, 59], 33: 60, 59: [2, 59], 66: [2, 59], 69: [2, 59], 74: [2, 59], 75: [2, 59], 76: [2, 59], 77: [2, 59], 78: [2, 59], 79: [2, 59] }, { 19: 61, 21: [2, 45], 59: [2, 45], 66: [2, 45], 74: [2, 45], 75: [2, 45], 76: [2, 45], 77: [2, 45], 78: [2, 45], 79: [2, 45] }, { 18: 65, 31: [2, 75], 48: 62, 57: 63, 58: 66, 59: [1, 40], 63: 64, 64: 67, 65: 68, 66: [1, 69], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 66: [1, 70] }, { 21: [2, 39], 31: [2, 39], 52: [2, 39], 59: [2, 39], 62: [2, 39], 66: [2, 39], 69: [2, 39], 74: [2, 39], 75: [2, 39], 76: [2, 39], 77: [2, 39], 78: [2, 39], 79: [2, 39], 81: [1, 45] }, { 18: 65, 51: 71, 52: [2, 79], 57: 72, 58: 66, 59: [1, 40], 63: 73, 64: 67, 65: 68, 66: [1, 69], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 24: 74, 45: [1, 75] }, { 45: [2, 50] }, { 4: 76, 6: 3, 13: [2, 43], 14: [2, 43], 17: [2, 43], 27: [2, 43], 32: [2, 43], 37: [2, 43], 42: [2, 43], 45: [2, 43], 46: [2, 43], 49: [2, 43], 53: [2, 43] }, { 45: [2, 19] }, { 18: 77, 66: [1, 32], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 4: 78, 6: 3, 13: [2, 43], 14: [2, 43], 17: [2, 43], 27: [2, 43], 32: [2, 43], 45: [2, 43], 46: [2, 43], 49: [2, 43], 53: [2, 43] }, { 24: 79, 45: [1, 75] }, { 45: [2, 52] }, { 5: [2, 10], 13: [2, 10], 14: [2, 10], 17: [2, 10], 27: [2, 10], 32: [2, 10], 37: [2, 10], 42: [2, 10], 45: [2, 10], 46: [2, 10], 49: [2, 10], 53: [2, 10] }, { 18: 65, 31: [2, 83], 56: 80, 57: 81, 58: 66, 59: [1, 40], 63: 82, 64: 67, 65: 68, 66: [1, 69], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 59: [2, 85], 60: 83, 62: [2, 85], 66: [2, 85], 74: [2, 85], 75: [2, 85], 76: [2, 85], 77: [2, 85], 78: [2, 85], 79: [2, 85] }, { 18: 65, 29: 84, 31: [2, 55], 57: 85, 58: 66, 59: [1, 40], 63: 86, 64: 67, 65: 68, 66: [1, 69], 69: [2, 55], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 18: 65, 31: [2, 61], 34: 87, 57: 88, 58: 66, 59: [1, 40], 63: 89, 64: 67, 65: 68, 66: [1, 69], 69: [2, 61], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 18: 65, 20: 90, 21: [2, 47], 57: 91, 58: 66, 59: [1, 40], 63: 92, 64: 67, 65: 68, 66: [1, 69], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 31: [1, 93] }, { 31: [2, 74], 59: [2, 74], 66: [2, 74], 74: [2, 74], 75: [2, 74], 76: [2, 74], 77: [2, 74], 78: [2, 74], 79: [2, 74] }, { 31: [2, 76] }, { 21: [2, 24], 31: [2, 24], 52: [2, 24], 59: [2, 24], 62: [2, 24], 66: [2, 24], 69: [2, 24], 74: [2, 24], 75: [2, 24], 76: [2, 24], 77: [2, 24], 78: [2, 24], 79: [2, 24] }, { 21: [2, 25], 31: [2, 25], 52: [2, 25], 59: [2, 25], 62: [2, 25], 66: [2, 25], 69: [2, 25], 74: [2, 25], 75: [2, 25], 76: [2, 25], 77: [2, 25], 78: [2, 25], 79: [2, 25] }, { 21: [2, 27], 31: [2, 27], 52: [2, 27], 62: [2, 27], 65: 94, 66: [1, 95], 69: [2, 27] }, { 21: [2, 89], 31: [2, 89], 52: [2, 89], 62: [2, 89], 66: [2, 89], 69: [2, 89] }, { 21: [2, 42], 31: [2, 42], 52: [2, 42], 59: [2, 42], 62: [2, 42], 66: [2, 42], 67: [1, 96], 69: [2, 42], 74: [2, 42], 75: [2, 42], 76: [2, 42], 77: [2, 42], 78: [2, 42], 79: [2, 42], 81: [2, 42] }, { 21: [2, 41], 31: [2, 41], 52: [2, 41], 59: [2, 41], 62: [2, 41], 66: [2, 41], 69: [2, 41], 74: [2, 41], 75: [2, 41], 76: [2, 41], 77: [2, 41], 78: [2, 41], 79: [2, 41], 81: [2, 41] }, { 52: [1, 97] }, { 52: [2, 78], 59: [2, 78], 66: [2, 78], 74: [2, 78], 75: [2, 78], 76: [2, 78], 77: [2, 78], 78: [2, 78], 79: [2, 78] }, { 52: [2, 80] }, { 5: [2, 12], 13: [2, 12], 14: [2, 12], 17: [2, 12], 27: [2, 12], 32: [2, 12], 37: [2, 12], 42: [2, 12], 45: [2, 12], 46: [2, 12], 49: [2, 12], 53: [2, 12] }, { 18: 98, 66: [1, 32], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 36: 50, 37: [1, 52], 41: 51, 42: [1, 53], 43: 100, 44: 99, 45: [2, 71] }, { 31: [2, 65], 38: 101, 59: [2, 65], 66: [2, 65], 69: [2, 65], 74: [2, 65], 75: [2, 65], 76: [2, 65], 77: [2, 65], 78: [2, 65], 79: [2, 65] }, { 45: [2, 17] }, { 5: [2, 13], 13: [2, 13], 14: [2, 13], 17: [2, 13], 27: [2, 13], 32: [2, 13], 37: [2, 13], 42: [2, 13], 45: [2, 13], 46: [2, 13], 49: [2, 13], 53: [2, 13] }, { 31: [1, 102] }, { 31: [2, 82], 59: [2, 82], 66: [2, 82], 74: [2, 82], 75: [2, 82], 76: [2, 82], 77: [2, 82], 78: [2, 82], 79: [2, 82] }, { 31: [2, 84] }, { 18: 65, 57: 104, 58: 66, 59: [1, 40], 61: 103, 62: [2, 87], 63: 105, 64: 67, 65: 68, 66: [1, 69], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 30: 106, 31: [2, 57], 68: 107, 69: [1, 108] }, { 31: [2, 54], 59: [2, 54], 66: [2, 54], 69: [2, 54], 74: [2, 54], 75: [2, 54], 76: [2, 54], 77: [2, 54], 78: [2, 54], 79: [2, 54] }, { 31: [2, 56], 69: [2, 56] }, { 31: [2, 63], 35: 109, 68: 110, 69: [1, 108] }, { 31: [2, 60], 59: [2, 60], 66: [2, 60], 69: [2, 60], 74: [2, 60], 75: [2, 60], 76: [2, 60], 77: [2, 60], 78: [2, 60], 79: [2, 60] }, { 31: [2, 62], 69: [2, 62] }, { 21: [1, 111] }, { 21: [2, 46], 59: [2, 46], 66: [2, 46], 74: [2, 46], 75: [2, 46], 76: [2, 46], 77: [2, 46], 78: [2, 46], 79: [2, 46] }, { 21: [2, 48] }, { 5: [2, 21], 13: [2, 21], 14: [2, 21], 17: [2, 21], 27: [2, 21], 32: [2, 21], 37: [2, 21], 42: [2, 21], 45: [2, 21], 46: [2, 21], 49: [2, 21], 53: [2, 21] }, { 21: [2, 90], 31: [2, 90], 52: [2, 90], 62: [2, 90], 66: [2, 90], 69: [2, 90] }, { 67: [1, 96] }, { 18: 65, 57: 112, 58: 66, 59: [1, 40], 66: [1, 32], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 5: [2, 22], 13: [2, 22], 14: [2, 22], 17: [2, 22], 27: [2, 22], 32: [2, 22], 37: [2, 22], 42: [2, 22], 45: [2, 22], 46: [2, 22], 49: [2, 22], 53: [2, 22] }, { 31: [1, 113] }, { 45: [2, 18] }, { 45: [2, 72] }, { 18: 65, 31: [2, 67], 39: 114, 57: 115, 58: 66, 59: [1, 40], 63: 116, 64: 67, 65: 68, 66: [1, 69], 69: [2, 67], 72: 23, 73: 24, 74: [1, 25], 75: [1, 26], 76: [1, 27], 77: [1, 28], 78: [1, 29], 79: [1, 31], 80: 30 }, { 5: [2, 23], 13: [2, 23], 14: [2, 23], 17: [2, 23], 27: [2, 23], 32: [2, 23], 37: [2, 23], 42: [2, 23], 45: [2, 23], 46: [2, 23], 49: [2, 23], 53: [2, 23] }, { 62: [1, 117] }, { 59: [2, 86], 62: [2, 86], 66: [2, 86], 74: [2, 86], 75: [2, 86], 76: [2, 86], 77: [2, 86], 78: [2, 86], 79: [2, 86] }, { 62: [2, 88] }, { 31: [1, 118] }, { 31: [2, 58] }, { 66: [1, 120], 70: 119 }, { 31: [1, 121] }, { 31: [2, 64] }, { 14: [2, 11] }, { 21: [2, 28], 31: [2, 28], 52: [2, 28], 62: [2, 28], 66: [2, 28], 69: [2, 28] }, { 5: [2, 20], 13: [2, 20], 14: [2, 20], 17: [2, 20], 27: [2, 20], 32: [2, 20], 37: [2, 20], 42: [2, 20], 45: [2, 20], 46: [2, 20], 49: [2, 20], 53: [2, 20] }, { 31: [2, 69], 40: 122, 68: 123, 69: [1, 108] }, { 31: [2, 66], 59: [2, 66], 66: [2, 66], 69: [2, 66], 74: [2, 66], 75: [2, 66], 76: [2, 66], 77: [2, 66], 78: [2, 66], 79: [2, 66] }, { 31: [2, 68], 69: [2, 68] }, { 21: [2, 26], 31: [2, 26], 52: [2, 26], 59: [2, 26], 62: [2, 26], 66: [2, 26], 69: [2, 26], 74: [2, 26], 75: [2, 26], 76: [2, 26], 77: [2, 26], 78: [2, 26], 79: [2, 26] }, { 13: [2, 14], 14: [2, 14], 17: [2, 14], 27: [2, 14], 32: [2, 14], 37: [2, 14], 42: [2, 14], 45: [2, 14], 46: [2, 14], 49: [2, 14], 53: [2, 14] }, { 66: [1, 125], 71: [1, 124] }, { 66: [2, 91], 71: [2, 91] }, { 13: [2, 15], 14: [2, 15], 17: [2, 15], 27: [2, 15], 32: [2, 15], 42: [2, 15], 45: [2, 15], 46: [2, 15], 49: [2, 15], 53: [2, 15] }, { 31: [1, 126] }, { 31: [2, 70] }, { 31: [2, 29] }, { 66: [2, 92], 71: [2, 92] }, { 13: [2, 16], 14: [2, 16], 17: [2, 16], 27: [2, 16], 32: [2, 16], 37: [2, 16], 42: [2, 16], 45: [2, 16], 46: [2, 16], 49: [2, 16], 53: [2, 16] }],
defaultActions: { 4: [2, 1], 49: [2, 50], 51: [2, 19], 55: [2, 52], 64: [2, 76], 73: [2, 80], 78: [2, 17], 82: [2, 84], 92: [2, 48], 99: [2, 18], 100: [2, 72], 105: [2, 88], 107: [2, 58], 110: [2, 64], 111: [2, 11], 123: [2, 70], 124: [2, 29] },
parseError: function parseError(str, hash) {
throw new Error(str);
},
parse: function parse(input) {
var self = this,
stack = [0],
vstack = [null],
lstack = [],
table = this.table,
yytext = "",
yylineno = 0,
yyleng = 0,
recovering = 0,
TERROR = 2,
EOF = 1;
this.lexer.setInput(input);
this.lexer.yy = this.yy;
this.yy.lexer = this.lexer;
this.yy.parser = this;
if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {};
var yyloc = this.lexer.yylloc;
lstack.push(yyloc);
var ranges = this.lexer.options && this.lexer.options.ranges;
if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError;
function popStack(n) {
stack.length = stack.length - 2 * n;
vstack.length = vstack.length - n;
lstack.length = lstack.length - n;
}
function lex() {
var token;
token = self.lexer.lex() || 1;
if (typeof token !== "number") {
token = self.symbols_[token] || token;
}
return token;
}
var symbol,
preErrorSymbol,
state,
action,
a,
r,
yyval = {},
p,
len,
newState,
expected;
while (true) {
state = stack[stack.length - 1];
if (this.defaultActions[state]) {
action = this.defaultActions[state];
} else {
if (symbol === null || typeof symbol == "undefined") {
symbol = lex();
}
action = table[state] && table[state][symbol];
}
if (typeof action === "undefined" || !action.length || !action[0]) {
var errStr = "";
if (!recovering) {
expected = [];
for (p in table[state]) if (this.terminals_[p] && p > 2) {
expected.push("'" + this.terminals_[p] + "'");
}
if (this.lexer.showPosition) {
errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
} else {
errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'");
}
this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected });
}
}
if (action[0] instanceof Array && action.length > 1) {
throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
}
switch (action[0]) {
case 1:
stack.push(symbol);
vstack.push(this.lexer.yytext);
lstack.push(this.lexer.yylloc);
stack.push(action[1]);
symbol = null;
if (!preErrorSymbol) {
yyleng = this.lexer.yyleng;
yytext = this.lexer.yytext;
yylineno = this.lexer.yylineno;
yyloc = this.lexer.yylloc;
if (recovering > 0) recovering--;
} else {
symbol = preErrorSymbol;
preErrorSymbol = null;
}
break;
case 2:
len = this.productions_[action[1]][1];
yyval.$ = vstack[vstack.length - len];
yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column };
if (ranges) {
yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
}
r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
if (typeof r !== "undefined") {
return r;
}
if (len) {
stack = stack.slice(0, -1 * len * 2);
vstack = vstack.slice(0, -1 * len);
lstack = lstack.slice(0, -1 * len);
}
stack.push(this.productions_[action[1]][0]);
vstack.push(yyval.$);
lstack.push(yyval._$);
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
stack.push(newState);
break;
case 3:
return true;
}
}
return true;
}
};
/* Jison generated lexer */
var lexer = (function () {
var lexer = {
EOF: 1,
parseError: function parseError(str, hash) {
if (this.yy.parser) {
this.yy.parser.parseError(str, hash);
} else {
throw new Error(str);
}
},
setInput: function setInput(input) {
this._input = input;
this._more = this._less = this.done = false;
this.yylineno = this.yyleng = 0;
this.yytext = this.matched = this.match = "";
this.conditionStack = ["INITIAL"];
this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 };
if (this.options.ranges) this.yylloc.range = [0, 0];
this.offset = 0;
return this;
},
input: function input() {
var ch = this._input[0];
this.yytext += ch;
this.yyleng++;
this.offset++;
this.match += ch;
this.matched += ch;
var lines = ch.match(/(?:\r\n?|\n).*/g);
if (lines) {
this.yylineno++;
this.yylloc.last_line++;
} else {
this.yylloc.last_column++;
}
if (this.options.ranges) this.yylloc.range[1]++;
this._input = this._input.slice(1);
return ch;
},
unput: function unput(ch) {
var len = ch.length;
var lines = ch.split(/(?:\r\n?|\n)/g);
this._input = ch + this._input;
this.yytext = this.yytext.substr(0, this.yytext.length - len - 1);
//this.yyleng -= len;
this.offset -= len;
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
this.match = this.match.substr(0, this.match.length - 1);
this.matched = this.matched.substr(0, this.matched.length - 1);
if (lines.length - 1) this.yylineno -= lines.length - 1;
var r = this.yylloc.range;
this.yylloc = {
first_line: this.yylloc.first_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.first_column,
last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
};
if (this.options.ranges) {
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
}
return this;
},
more: function more() {
this._more = true;
return this;
},
less: function less(n) {
this.unput(this.match.slice(n));
},
pastInput: function pastInput() {
var past = this.matched.substr(0, this.matched.length - this.match.length);
return (past.length > 20 ? "..." : "") + past.substr(-20).replace(/\n/g, "");
},
upcomingInput: function upcomingInput() {
var next = this.match;
if (next.length < 20) {
next += this._input.substr(0, 20 - next.length);
}
return (next.substr(0, 20) + (next.length > 20 ? "..." : "")).replace(/\n/g, "");
},
showPosition: function showPosition() {
var pre = this.pastInput();
var c = new Array(pre.length + 1).join("-");
return pre + this.upcomingInput() + "\n" + c + "^";
},
next: function next() {
if (this.done) {
return this.EOF;
}
if (!this._input) this.done = true;
var token, match, tempMatch, index, col, lines;
if (!this._more) {
this.yytext = "";
this.match = "";
}
var rules = this._currentRules();
for (var i = 0; i < rules.length; i++) {
tempMatch = this._input.match(this.rules[rules[i]]);
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
match = tempMatch;
index = i;
if (!this.options.flex) break;
}
}
if (match) {
lines = match[0].match(/(?:\r\n?|\n).*/g);
if (lines) this.yylineno += lines.length;
this.yylloc = {
first_line: this.yylloc.last_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.last_column,
last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
};
this.yytext += match[0];
this.match += match[0];
this.matches = match;
this.yyleng = this.yytext.length;
if (this.options.ranges) {
this.yylloc.range = [this.offset, this.offset += this.yyleng];
}
this._more = false;
this._input = this._input.slice(match[0].length);
this.matched += match[0];
token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]);
if (this.done && this._input) this.done = false;
if (token) {
return token;
} else {
return;
}
}
if (this._input === "") {
return this.EOF;
} else {
return this.parseError("Lexical error on line " + (this.yylineno + 1) + ". Unrecognized text.\n" + this.showPosition(), { text: "", token: null, line: this.yylineno });
}
},
lex: function lex() {
var r = this.next();
if (typeof r !== "undefined") {
return r;
} else {
return this.lex();
}
},
begin: function begin(condition) {
this.conditionStack.push(condition);
},
popState: function popState() {
return this.conditionStack.pop();
},
_currentRules: function _currentRules() {
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
},
topState: function topState() {
return this.conditionStack[this.conditionStack.length - 2];
},
pushState: function begin(condition) {
this.begin(condition);
}
};
lexer.options = {};
lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
function strip(start, end) {
return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng - end);
}
var YYSTATE = YY_START;
switch ($avoiding_name_collisions) {
case 0:
if (yy_.yytext.slice(-2) === "\\\\") {
strip(0, 1);
this.begin("mu");
} else if (yy_.yytext.slice(-1) === "\\") {
strip(0, 1);
this.begin("emu");
} else {
this.begin("mu");
}
if (yy_.yytext) {
return 14;
} break;
case 1:
return 14;
break;
case 2:
this.popState();
return 14;
break;
case 3:
yy_.yytext = yy_.yytext.substr(5, yy_.yyleng - 9);
this.popState();
return 16;
break;
case 4:
return 14;
break;
case 5:
this.popState();
return 13;
break;
case 6:
return 59;
break;
case 7:
return 62;
break;
case 8:
return 17;
break;
case 9:
this.popState();
this.begin("raw");
return 21;
break;
case 10:
return 53;
break;
case 11:
return 27;
break;
case 12:
return 45;
break;
case 13:
this.popState(); return 42;
break;
case 14:
this.popState(); return 42;
break;
case 15:
return 32;
break;
case 16:
return 37;
break;
case 17:
return 49;
break;
case 18:
return 46;
break;
case 19:
this.unput(yy_.yytext);
this.popState();
this.begin("com");
break;
case 20:
this.popState();
return 13;
break;
case 21:
return 46;
break;
case 22:
return 67;
break;
case 23:
return 66;
break;
case 24:
return 66;
break;
case 25:
return 81;
break;
case 26:
// ignore whitespace
break;
case 27:
this.popState(); return 52;
break;
case 28:
this.popState(); return 31;
break;
case 29:
yy_.yytext = strip(1, 2).replace(/\\"/g, "\""); return 74;
break;
case 30:
yy_.yytext = strip(1, 2).replace(/\\'/g, "'"); return 74;
break;
case 31:
return 79;
break;
case 32:
return 76;
break;
case 33:
return 76;
break;
case 34:
return 77;
break;
case 35:
return 78;
break;
case 36:
return 75;
break;
case 37:
return 69;
break;
case 38:
return 71;
break;
case 39:
return 66;
break;
case 40:
return 66;
break;
case 41:
return "INVALID";
break;
case 42:
return 5;
break;
}
};
lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/, /^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/, /^(?:[^\x00]*?(?=(\{\{\{\{\/)))/, /^(?:[\s\S]*?--(~)?\}\})/, /^(?:\()/, /^(?:\))/, /^(?:\{\{\{\{)/, /^(?:\}\}\}\})/, /^(?:\{\{(~)?>)/, /^(?:\{\{(~)?#)/, /^(?:\{\{(~)?\/)/, /^(?:\{\{(~)?\^\s*(~)?\}\})/, /^(?:\{\{(~)?\s*else\s*(~)?\}\})/, /^(?:\{\{(~)?\^)/, /^(?:\{\{(~)?\s*else\b)/, /^(?:\{\{(~)?\{)/, /^(?:\{\{(~)?&)/, /^(?:\{\{(~)?!--)/, /^(?:\{\{(~)?![\s\S]*?\}\})/, /^(?:\{\{(~)?)/, /^(?:=)/, /^(?:\.\.)/, /^(?:\.(?=([=~}\s\/.)|])))/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}(~)?\}\})/, /^(?:(~)?\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@)/, /^(?:true(?=([~}\s)])))/, /^(?:false(?=([~}\s)])))/, /^(?:undefined(?=([~}\s)])))/, /^(?:null(?=([~}\s)])))/, /^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/, /^(?:as\s+\|)/, /^(?:\|)/, /^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/, /^(?:\[[^\]]*\])/, /^(?:.)/, /^(?:$)/];
lexer.conditions = { mu: { rules: [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42], inclusive: false }, emu: { rules: [2], inclusive: false }, com: { rules: [5], inclusive: false }, raw: { rules: [3, 4], inclusive: false }, INITIAL: { rules: [0, 1, 42], inclusive: true } };
return lexer;
})();
parser.lexer = lexer;
function Parser() {
this.yy = {};
} Parser.prototype = parser; parser.Parser = Parser;
return new Parser();
})(); exports["default"] = handlebars;
module.exports = exports["default"];
/***/
},
/* 15 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
var _interopRequireWildcard = __webpack_require__(8)['default'];
exports.__esModule = true;
var _Visitor = __webpack_require__(6);
var _Visitor2 = _interopRequireWildcard(_Visitor);
function WhitespaceControl() { }
WhitespaceControl.prototype = new _Visitor2['default']();
WhitespaceControl.prototype.Program = function (program) {
var isRoot = !this.isRootSeen;
this.isRootSeen = true;
var body = program.body;
for (var i = 0, l = body.length; i < l; i++) {
var current = body[i],
strip = this.accept(current);
if (!strip) {
continue;
}
var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot),
_isNextWhitespace = isNextWhitespace(body, i, isRoot),
openStandalone = strip.openStandalone && _isPrevWhitespace,
closeStandalone = strip.closeStandalone && _isNextWhitespace,
inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace;
if (strip.close) {
omitRight(body, i, true);
}
if (strip.open) {
omitLeft(body, i, true);
}
if (inlineStandalone) {
omitRight(body, i);
if (omitLeft(body, i)) {
// If we are on a standalone node, save the indent info for partials
if (current.type === 'PartialStatement') {
// Pull out the whitespace from the final line
current.indent = /([ \t]+$)/.exec(body[i - 1].original)[1];
}
}
}
if (openStandalone) {
omitRight((current.program || current.inverse).body);
// Strip out the previous content node if it's whitespace only
omitLeft(body, i);
}
if (closeStandalone) {
// Always strip the next node
omitRight(body, i);
omitLeft((current.inverse || current.program).body);
}
}
return program;
};
WhitespaceControl.prototype.BlockStatement = function (block) {
this.accept(block.program);
this.accept(block.inverse);
// Find the inverse program that is involed with whitespace stripping.
var program = block.program || block.inverse,
inverse = block.program && block.inverse,
firstInverse = inverse,
lastInverse = inverse;
if (inverse && inverse.chained) {
firstInverse = inverse.body[0].program;
// Walk the inverse chain to find the last inverse that is actually in the chain.
while (lastInverse.chained) {
lastInverse = lastInverse.body[lastInverse.body.length - 1].program;
}
}
var strip = {
open: block.openStrip.open,
close: block.closeStrip.close,
// Determine the standalone candiacy. Basically flag our content as being possibly standalone
// so our parent can determine if we actually are standalone
openStandalone: isNextWhitespace(program.body),
closeStandalone: isPrevWhitespace((firstInverse || program).body)
};
if (block.openStrip.close) {
omitRight(program.body, null, true);
}
if (inverse) {
var inverseStrip = block.inverseStrip;
if (inverseStrip.open) {
omitLeft(program.body, null, true);
}
if (inverseStrip.close) {
omitRight(firstInverse.body, null, true);
}
if (block.closeStrip.open) {
omitLeft(lastInverse.body, null, true);
}
// Find standalone else statments
if (isPrevWhitespace(program.body) && isNextWhitespace(firstInverse.body)) {
omitLeft(program.body);
omitRight(firstInverse.body);
}
} else if (block.closeStrip.open) {
omitLeft(program.body, null, true);
}
return strip;
};
WhitespaceControl.prototype.MustacheStatement = function (mustache) {
return mustache.strip;
};
WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function (node) {
/* istanbul ignore next */
var strip = node.strip || {};
return {
inlineStandalone: true,
open: strip.open,
close: strip.close
};
};
function isPrevWhitespace(body, i, isRoot) {
if (i === undefined) {
i = body.length;
}
// Nodes that end with newlines are considered whitespace (but are special
// cased for strip operations)
var prev = body[i - 1],
sibling = body[i - 2];
if (!prev) {
return isRoot;
}
if (prev.type === 'ContentStatement') {
return (sibling || !isRoot ? /\r?\n\s*?$/ : /(^|\r?\n)\s*?$/).test(prev.original);
}
}
function isNextWhitespace(body, i, isRoot) {
if (i === undefined) {
i = -1;
}
var next = body[i + 1],
sibling = body[i + 2];
if (!next) {
return isRoot;
}
if (next.type === 'ContentStatement') {
return (sibling || !isRoot ? /^\s*?\r?\n/ : /^\s*?(\r?\n|$)/).test(next.original);
}
}
// Marks the node to the right of the position as omitted.
// I.e. {{foo}}' ' will mark the ' ' node as omitted.
//
// If i is undefined, then the first child will be marked as such.
//
// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
// content is met.
function omitRight(body, i, multiple) {
var current = body[i == null ? 0 : i + 1];
if (!current || current.type !== 'ContentStatement' || !multiple && current.rightStripped) {
return;
}
var original = current.value;
current.value = current.value.replace(multiple ? /^\s+/ : /^[ \t]*\r?\n?/, '');
current.rightStripped = current.value !== original;
}
// Marks the node to the left of the position as omitted.
// I.e. ' '{{foo}} will mark the ' ' node as omitted.
//
// If i is undefined then the last child will be marked as such.
//
// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
// content is met.
function omitLeft(body, i, multiple) {
var current = body[i == null ? body.length - 1 : i - 1];
if (!current || current.type !== 'ContentStatement' || !multiple && current.leftStripped) {
return;
}
// We omit the last node if it's whitespace only and not preceeded by a non-content node.
var original = current.value;
current.value = current.value.replace(multiple ? /\s+$/ : /[ \t]+$/, '');
current.leftStripped = current.value !== original;
return current.leftStripped;
}
exports['default'] = WhitespaceControl;
module.exports = exports['default'];
/***/
},
/* 16 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
var _interopRequireWildcard = __webpack_require__(8)['default'];
exports.__esModule = true;
exports.SourceLocation = SourceLocation;
exports.id = id;
exports.stripFlags = stripFlags;
exports.stripComment = stripComment;
exports.preparePath = preparePath;
exports.prepareMustache = prepareMustache;
exports.prepareRawBlock = prepareRawBlock;
exports.prepareBlock = prepareBlock;
var _Exception = __webpack_require__(11);
var _Exception2 = _interopRequireWildcard(_Exception);
function SourceLocation(source, locInfo) {
this.source = source;
this.start = {
line: locInfo.first_line,
column: locInfo.first_column
};
this.end = {
line: locInfo.last_line,
column: locInfo.last_column
};
}
function id(token) {
if (/^\[.*\]$/.test(token)) {
return token.substr(1, token.length - 2);
} else {
return token;
}
}
function stripFlags(open, close) {
return {
open: open.charAt(2) === '~',
close: close.charAt(close.length - 3) === '~'
};
}
function stripComment(comment) {
return comment.replace(/^\{\{~?\!-?-?/, '').replace(/-?-?~?\}\}$/, '');
}
function preparePath(data, parts, locInfo) {
locInfo = this.locInfo(locInfo);
var original = data ? '@' : '',
dig = [],
depth = 0,
depthString = '';
for (var i = 0, l = parts.length; i < l; i++) {
var part = parts[i].part,
// If we have [] syntax then we do not treat path references as operators,
// i.e. foo.[this] resolves to approximately context.foo['this']
isLiteral = parts[i].original !== part;
original += (parts[i].separator || '') + part;
if (!isLiteral && (part === '..' || part === '.' || part === 'this')) {
if (dig.length > 0) {
throw new _Exception2['default']('Invalid path: ' + original, { loc: locInfo });
} else if (part === '..') {
depth++;
depthString += '../';
}
} else {
dig.push(part);
}
}
return new this.PathExpression(data, depth, dig, original, locInfo);
}
function prepareMustache(path, params, hash, open, strip, locInfo) {
// Must use charAt to support IE pre-10
var escapeFlag = open.charAt(3) || open.charAt(2),
escaped = escapeFlag !== '{' && escapeFlag !== '&';
return new this.MustacheStatement(path, params, hash, escaped, strip, this.locInfo(locInfo));
}
function prepareRawBlock(openRawBlock, content, close, locInfo) {
if (openRawBlock.path.original !== close) {
var errorNode = { loc: openRawBlock.path.loc };
throw new _Exception2['default'](openRawBlock.path.original + ' doesn\'t match ' + close, errorNode);
}
locInfo = this.locInfo(locInfo);
var program = new this.Program([content], null, {}, locInfo);
return new this.BlockStatement(openRawBlock.path, openRawBlock.params, openRawBlock.hash, program, undefined, {}, {}, {}, locInfo);
}
function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) {
// When we are chaining inverse calls, we will not have a close path
if (close && close.path && openBlock.path.original !== close.path.original) {
var errorNode = { loc: openBlock.path.loc };
throw new _Exception2['default'](openBlock.path.original + ' doesn\'t match ' + close.path.original, errorNode);
}
program.blockParams = openBlock.blockParams;
var inverse = undefined,
inverseStrip = undefined;
if (inverseAndProgram) {
if (inverseAndProgram.chain) {
inverseAndProgram.program.body[0].closeStrip = close.strip;
}
inverseStrip = inverseAndProgram.strip;
inverse = inverseAndProgram.program;
}
if (inverted) {
inverted = inverse;
inverse = program;
program = inverted;
}
return new this.BlockStatement(openBlock.path, openBlock.params, openBlock.hash, program, inverse, openBlock.strip, inverseStrip, close && close.strip, this.locInfo(locInfo));
}
/***/
},
/* 17 */
/***/ function (module, exports, __webpack_require__) {
'use strict';
exports.__esModule = true;
/*global define */
var _isArray = __webpack_require__(12);
var SourceNode = undefined;
try {
/* istanbul ignore next */
if (false) {
// We don't support this in AMD environments. For these environments, we asusme that
// they are running on the browser and thus have no need for the source-map library.
var SourceMap = require('source-map');
SourceNode = SourceMap.SourceNode;
}
} catch (err) { }
/* istanbul ignore if: tested but not covered in istanbul due to dist build */
if (!SourceNode) {
SourceNode = function (line, column, srcFile, chunks) {
this.src = '';
if (chunks) {
this.add(chunks);
}
};
/* istanbul ignore next */
SourceNode.prototype = {
add: function add(chunks) {
if (_isArray.isArray(chunks)) {
chunks = chunks.join('');
}
this.src += chunks;
},
prepend: function prepend(chunks) {
if (_isArray.isArray(chunks)) {
chunks = chunks.join('');
}
this.src = chunks + this.src;
},
toStringWithSourceMap: function toStringWithSourceMap() {
return { code: this.toString() };
},
toString: function toString() {
return this.src;
}
};
}
function castChunk(chunk, codeGen, loc) {
if (_isArray.isArray(chunk)) {
var ret = [];
for (var i = 0, len = chunk.length; i < len; i++) {
ret.push(codeGen.wrap(chunk[i], loc));
}
return ret;
} else if (typeof chunk === 'boolean' || typeof chunk === 'number') {
// Handle primitives that the SourceNode will throw up on
return chunk + '';
}
return chunk;
}
function CodeGen(srcFile) {
this.srcFile = srcFile;
this.source = [];
}
CodeGen.prototype = {
prepend: function prepend(source, loc) {
this.source.unshift(this.wrap(source, loc));
},
push: function push(source, loc) {
this.source.push(this.wrap(source, loc));
},
merge: function merge() {
var source = this.empty();
this.each(function (line) {
source.add([' ', line, '\n']);
});
return source;
},
each: function each(iter) {
for (var i = 0, len = this.source.length; i < len; i++) {
iter(this.source[i]);
}
},
empty: function empty() {
var loc = arguments[0] === undefined ? this.currentLocation || { start: {} } : arguments[0];
return new SourceNode(loc.start.line, loc.start.column, this.srcFile);
},
wrap: function wrap(chunk) {
var loc = arguments[1] === undefined ? this.currentLocation || { start: {} } : arguments[1];
if (chunk instanceof SourceNode) {
return chunk;
}
chunk = castChunk(chunk, this, loc);
return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk);
},
functionCall: function functionCall(fn, type, params) {
params = this.generateList(params);
return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']);
},
quotedString: function quotedString(str) {
return '"' + (str + '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
.replace(/\u2029/g, '\\u2029') + '"';
},
objectLiteral: function objectLiteral(obj) {
var pairs = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var value = castChunk(obj[key], this);
if (value !== 'undefined') {
pairs.push([this.quotedString(key), ':', value]);
}
}
}
var ret = this.generateList(pairs);
ret.prepend('{');
ret.add('}');
return ret;
},
generateList: function generateList(entries, loc) {
var ret = this.empty(loc);
for (var i = 0, len = entries.length; i < len; i++) {
if (i) {
ret.add(',');
}
ret.add(castChunk(entries[i], this, loc));
}
return ret;
},
generateArray: function generateArray(entries, loc) {
var ret = this.generateList(entries, loc);
ret.prepend('[');
ret.add(']');
return ret;
}
};
exports['default'] = CodeGen;
module.exports = exports['default'];
/* NOP */
/***/
}
/******/])
});
;
/*!
* jquery.sumoselect - v3.0.3
* http://hemantnegi.github.io/jquery.sumoselect
* 2016-12-12
*
* Copyright 2015 Hemant Negi
* Email : hemant.frnz@gmail.com
* Compressor http://refresh-sf.com/
*/
(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof exports !== 'undefined') {
module.exports = factory(require('jquery'));
} else {
factory(jQuery);
}
})(function ($) {
'namespace sumo';
$.fn.SumoSelect = function (options) {
// This is the easiest way to have default options.
var settings = $.extend({
placeholder: 'Select Here', // Dont change it here.
csvDispCount: 3, // display no. of items in multiselect. 0 to display all.
captionFormat: '{0} Selected', // format of caption text. you can set your locale.
captionFormatAllSelected: '{0} all selected!', // format of caption text when all elements are selected. set null to use captionFormat. It will not work if there are disabled elements in select.
floatWidth: 400, // Screen width of device at which the list is rendered in floating popup fashion.
forceCustomRendering: false, // force the custom modal on all devices below floatWidth resolution.
nativeOnDevice: ['Android', 'BlackBerry', 'iPhone', 'iPad', 'iPod', 'Opera Mini', 'IEMobile', 'Silk'], //
outputAsCSV: false, // true to POST data as csv ( false for Html control array ie. default select )
csvSepChar: ',', // separation char in csv mode
okCancelInMulti: false, // display ok cancel buttons in desktop mode multiselect also.
triggerChangeCombined: true, // im multi select mode wether to trigger change event on individual selection or combined selection.
selectAll: false, // to display select all button in multiselect mode.|| also select all will not be available on mobile devices.
search: false, // to display input for filtering content. selectAlltext will be input text placeholder
searchText: 'Search...', // placeholder for search input
noMatch: 'No matches for "{0}"',
prefix: '', // some prefix usually the field name. eg. 'Hello '
locale: ['OK', 'Cancel', 'Select All'], // all text that is used. don't change the index.
up: false, // set true to open upside.
showTitle: true // set to false to prevent title (tooltip) from appearing
}, options);
var ret = this.each(function () {
var selObj = this; // the original select object.
if (this.sumo || !$(this).is('select')) return; //already initialized
this.sumo = {
E: $(selObj), //the jquery object of original select element.
is_multi: $(selObj).attr('multiple'), //if its a multiple select
select: '',
caption: '',
placeholder: '',
optDiv: '',
CaptionCont: '',
ul: '',
is_floating: false,
is_opened: false,
//backdrop: '',
mob: false, // if to open device default select
Pstate: [],
createElems: function () {
var O = this;
O.E.wrap('');
O.select = O.E.parent();
O.caption = $('
');
O.CaptionCont = $('
')
.attr('style', O.E.attr('style'))
.prepend(O.caption);
O.select.append(O.CaptionCont);
// default turn off if no multiselect
if (!O.is_multi) settings.okCancelInMulti = false
if (O.E.attr('disabled'))
O.select.addClass('disabled').removeAttr('tabindex');
//if output as csv and is a multiselect.
if (settings.outputAsCSV && O.is_multi && O.E.attr('name')) {
//create a hidden field to store csv value.
O.select.append($(' ').attr('name', O.E.attr('name')).val(O.getSelStr()));
// so it can not post the original select.
O.E.removeAttr('name');
}
//break for mobile rendring.. if forceCustomRendering is false
if (O.isMobile() && !settings.forceCustomRendering) {
O.setNativeMobile();
return;
}
// if there is a name attr in select add a class to container div
if (O.E.attr('name')) O.select.addClass('sumo_' + O.E.attr('name').replace(/\[\]/, ''))
//hide original select
O.E.addClass('SumoUnder').attr('tabindex', '-1');
//## Creating the list...
O.optDiv = $('');
//branch for floating list in low res devices.
O.floatingList();
//Creating the markup for the available options
O.ul = $('
');
O.optDiv.append(O.ul);
// Select all functionality
if (settings.selectAll && O.is_multi) O.SelAll();
// search functionality
if (settings.search) O.Search();
O.ul.append(O.prepItems(O.E.children()));
//if multiple then add the class multiple and add OK / CANCEL button
if (O.is_multi) O.multiSelelect();
O.select.append(O.optDiv);
O.basicEvents();
O.selAllState();
},
prepItems: function (opts, d) {
var lis = [], O = this;
$(opts).each(function (i, opt) { // parsing options to li
opt = $(opt);
lis.push(opt.is('optgroup') ?
$('' + opt.attr('label') + ' ')
.find('ul')
.append(O.prepItems(opt.children(), opt[0].disabled))
.end()
:
O.createLi(opt, d)
);
});
return lis;
},
//## Creates a LI element from a given option and binds events to it
//## returns the jquery instance of li (not inserted in dom)
createLi: function (opt, d) {
var O = this;
if (!opt.attr('value')) opt.attr('value', opt.val());
var li = $('' + opt.text() + ' ');
li.data('opt', opt); // store a direct reference to option.
opt.data('li', li); // store a direct reference to list item.
if (O.is_multi) li.prepend(' ');
if (opt[0].disabled || d)
li = li.addClass('disabled');
O.onOptClick(li);
if (opt[0].selected)
li.addClass('selected');
if (opt.attr('class'))
li.addClass(opt.attr('class'));
if (opt.attr('title'))
li.attr('title', opt.attr('title'));
return li;
},
//## Returns the selected items as string in a Multiselect.
getSelStr: function () {
// get the pre selected items.
sopt = [];
this.E.find('option:selected').each(function () { sopt.push($(this).val()); });
return sopt.join(settings.csvSepChar);
},
//## THOSE OK/CANCEL BUTTONS ON MULTIPLE SELECT.
multiSelelect: function () {
var O = this;
O.optDiv.addClass('multiple');
O.okbtn = $('' + settings.locale[0] + '
').click(function () {
//if combined change event is set.
if (settings.triggerChangeCombined) {
//check for a change in the selection.
changed = false;
if (O.E.find('option:selected').length != O.Pstate.length) {
changed = true;
}
else {
O.E.find('option').each(function (i, e) {
if (e.selected && O.Pstate.indexOf(i) < 0) changed = true;
});
}
if (changed) {
O.callChange();
O.setText();
}
}
O.hideOpts();
});
O.cancelBtn = $('' + settings.locale[1] + '
').click(function () {
O._cnbtn();
O.hideOpts();
});
var btns = O.okbtn.add(O.cancelBtn);
O.optDiv.append($('').append(btns));
// handling keyboard navigation on ok cancel buttons.
btns.on('keydown.sumo', function (e) {
var el = $(this);
switch (e.which) {
case 32: // space
case 13: // enter
el.trigger('click');
break;
case 9: //tab
if (el.hasClass('btnOk')) return;
case 27: // esc
O._cnbtn();
O.hideOpts();
return;
}
e.stopPropagation();
e.preventDefault();
});
},
_cnbtn: function () {
var O = this;
//remove all selections
O.E.find('option:selected').each(function () { this.selected = false; });
O.optDiv.find('li.selected').removeClass('selected')
//restore selections from saved state.
for (var i = 0; i < O.Pstate.length; i++) {
O.E.find('option')[O.Pstate[i]].selected = true;
O.ul.find('li.opt').eq(O.Pstate[i]).addClass('selected');
}
O.selAllState();
},
SelAll: function () {
var O = this;
if (!O.is_multi) return;
O.selAll = $('
' + settings.locale[2] + '
');
O.optDiv.addClass('selall');
O.selAll.on('click', function () {
O.selAll.toggleClass('selected');
O.toggSelAll(O.selAll.hasClass('selected'), 1);
//O.selAllState();
});
O.optDiv.prepend(O.selAll);
},
// search module (can be removed if not required.)
Search: function () {
var O = this,
cc = O.CaptionCont.addClass('search'),
P = $('
');
O.ftxt = $(' ')
.on('click', function (e) {
e.stopPropagation();
});
cc.append(O.ftxt);
O.optDiv.children('ul').after(P);
O.ftxt.on('keyup.sumo', function () {
var hid = O.optDiv.find('ul.options li.opt').each(function (ix, e) {
e = $(e);
if (e.text().toLowerCase().indexOf(O.ftxt.val().toLowerCase()) > -1)
e.removeClass('hidden');
else
e.addClass('hidden');
}).not('.hidden');
P.html(settings.noMatch.replace(/\{0\}/g, ' ')).toggle(!hid.length);
P.find('em').text(O.ftxt.val());
O.selAllState();
});
},
selAllState: function () {
var O = this;
if (settings.selectAll && O.is_multi) {
var sc = 0, vc = 0;
O.optDiv.find('li.opt').not('.hidden').each(function (ix, e) {
if ($(e).hasClass('selected')) sc++;
if (!$(e).hasClass('disabled')) vc++;
});
//select all checkbox state change.
if (sc == vc) O.selAll.removeClass('partial').addClass('selected');
else if (sc == 0) O.selAll.removeClass('selected partial');
else O.selAll.addClass('partial')//.removeClass('selected');
}
},
showOpts: function () {
var O = this;
if (O.E.attr('disabled')) return; // if select is disabled then retrun
O.E.trigger('sumo:opening', O);
O.is_opened = true;
O.select.addClass('open').attr('aria-expanded', 'true');
O.E.trigger('sumo:opened', O);
if (O.ftxt) O.ftxt.focus();
else O.select.focus();
// hide options on click outside.
$(document).on('click.sumo', function (e) {
if (!O.select.is(e.target) // if the target of the click isn't the container...
&& O.select.has(e.target).length === 0) { // ... nor a descendant of the container
if (!O.is_opened) return;
O.hideOpts();
if (settings.okCancelInMulti) O._cnbtn();
}
});
if (O.is_floating) {
H = O.optDiv.children('ul').outerHeight() + 2; // +2 is clear fix
if (O.is_multi) H = H + parseInt(O.optDiv.css('padding-bottom'));
O.optDiv.css('height', H);
$('body').addClass('sumoStopScroll');
}
O.setPstate();
},
//maintain state when ok/cancel buttons are available storing the indexes.
setPstate: function () {
var O = this;
if (O.is_multi && (O.is_floating || settings.okCancelInMulti)) {
O.Pstate = [];
// assuming that find returns elements in tree order
O.E.find('option').each(function (i, e) { if (e.selected) O.Pstate.push(i); });
}
},
callChange: function () {
this.E.trigger('change').trigger('click');
},
hideOpts: function () {
var O = this;
if (O.is_opened) {
O.E.trigger('sumo:closing', O);
O.is_opened = false;
O.select.removeClass('open').attr('aria-expanded', 'true').find('ul li.sel').removeClass('sel');
O.E.trigger('sumo:closed', O);
$(document).off('click.sumo');
O.select.focus();
$('body').removeClass('sumoStopScroll');
// clear the search
if (settings.search) {
O.ftxt.val('');
O.optDiv.find('ul.options li').removeClass('hidden');
O.optDiv.find('.no-match').toggle(false);
}
}
},
setOnOpen: function () {
var O = this,
li = O.optDiv.find('li.opt:not(.hidden)').eq(settings.search ? 0 : O.E[0].selectedIndex);
if (li.hasClass('disabled')) {
li = li.next(':not(disabled)')
if (!li.length) return;
}
O.optDiv.find('li.sel').removeClass('sel');
li.addClass('sel');
O.showOpts();
},
nav: function (up) {
var O = this, c,
s = O.ul.find('li.opt:not(.disabled, .hidden)'),
sel = O.ul.find('li.opt.sel:not(.hidden)'),
idx = s.index(sel);
if (O.is_opened && sel.length) {
if (up && idx > 0)
c = s.eq(idx - 1);
else if (!up && idx < s.length - 1 && idx > -1)
c = s.eq(idx + 1);
else return; // if no items before or after
sel.removeClass('sel');
sel = c.addClass('sel');
// setting sel item to visible view.
var ul = O.ul,
st = ul.scrollTop(),
t = sel.position().top + st;
if (t >= st + ul.height() - sel.outerHeight())
ul.scrollTop(t - ul.height() + sel.outerHeight());
if (t < st)
ul.scrollTop(t);
}
else
O.setOnOpen();
},
basicEvents: function () {
var O = this;
O.CaptionCont.click(function (evt) {
O.E.trigger('click');
if (O.is_opened) O.hideOpts(); else O.showOpts();
evt.stopPropagation();
});
O.select.on('keydown.sumo', function (e) {
switch (e.which) {
case 38: // up
O.nav(true);
break;
case 40: // down
O.nav(false);
break;
case 65: // shortcut ctrl + a to select all and ctrl + shift + a to unselect all.
if (O.is_multi && e.ctrlKey) {
O.toggSelAll(!e.shiftKey, 1);
break;
}
else
return;
case 32: // space
if (settings.search && O.ftxt.is(e.target)) return;
case 13: // enter
if (O.is_opened)
O.optDiv.find('ul li.sel').trigger('click');
else
O.setOnOpen();
break;
case 9: //tab
if (!settings.okCancelInMulti)
O.hideOpts();
return;
case 27: // esc
if (settings.okCancelInMulti) O._cnbtn();
O.hideOpts();
return;
default:
return; // exit this handler for other keys
}
e.preventDefault(); // prevent the default action (scroll / move caret)
});
$(window).on('resize.sumo', function () {
O.floatingList();
});
},
onOptClick: function (li) {
var O = this;
li.click(function () {
var li = $(this);
if (li.hasClass('disabled')) return;
var txt = "";
if (O.is_multi) {
li.toggleClass('selected');
li.data('opt')[0].selected = li.hasClass('selected');
O.selAllState();
}
else {
li.parent().find('li.selected').removeClass('selected'); //if not multiselect then remove all selections from this list
li.toggleClass('selected');
li.data('opt')[0].selected = true;
}
//branch for combined change event.
if (!(O.is_multi && settings.triggerChangeCombined && (O.is_floating || settings.okCancelInMulti))) {
O.setText();
O.callChange();
}
if (!O.is_multi) O.hideOpts(); //if its not a multiselect then hide on single select.
});
},
setText: function () {
var O = this;
O.placeholder = "";
if (O.is_multi) {
sels = O.E.find(':selected').not(':disabled'); //selected options.
for (i = 0; i < sels.length; i++) {
if (i + 1 >= settings.csvDispCount && settings.csvDispCount) {
if (sels.length == O.E.find('option').length && settings.captionFormatAllSelected) {
O.placeholder = settings.captionFormatAllSelected.replace(/\{0\}/g, sels.length) + ',';
} else {
O.placeholder = settings.captionFormat.replace(/\{0\}/g, sels.length) + ',';
}
break;
}
else O.placeholder += $(sels[i]).text() + ", ";
}
O.placeholder = O.placeholder.replace(/,([^,]*)$/, '$1'); //remove unexpected "," from last.
}
else {
O.placeholder = O.E.find(':selected').not(':disabled').text();
}
var is_placeholder = false;
if (!O.placeholder) {
is_placeholder = true;
O.placeholder = O.E.attr('placeholder');
if (!O.placeholder) //if placeholder is there then set it
O.placeholder = O.E.find('option:disabled:selected').text();
}
O.placeholder = O.placeholder ? (settings.prefix + ' ' + O.placeholder) : settings.placeholder
//set display text
O.caption.html(O.placeholder);
if (settings.showTitle) O.CaptionCont.attr('title', O.placeholder);
//set the hidden field if post as csv is true.
var csvField = O.select.find('input.HEMANT123');
if (csvField.length) csvField.val(O.getSelStr());
//add class placeholder if its a placeholder text.
if (is_placeholder) O.caption.addClass('placeholder'); else O.caption.removeClass('placeholder');
return O.placeholder;
},
isMobile: function () {
// Adapted from http://www.detectmobilebrowsers.com
var ua = navigator.userAgent || navigator.vendor || window.opera;
// Checks for iOs, Android, Blackberry, Opera Mini, and Windows mobile devices
for (var i = 0; i < settings.nativeOnDevice.length; i++) if (ua.toString().toLowerCase().indexOf(settings.nativeOnDevice[i].toLowerCase()) > 0) return settings.nativeOnDevice[i];
return false;
},
setNativeMobile: function () {
var O = this;
O.E.addClass('SelectClass')//.css('height', O.select.outerHeight());
O.mob = true;
O.E.change(function () {
O.setText();
});
},
floatingList: function () {
var O = this;
//called on init and also on resize.
//O.is_floating = true if window width is < specified float width
O.is_floating = $(window).width() <= settings.floatWidth;
//set class isFloating
O.optDiv.toggleClass('isFloating', O.is_floating);
//remove height if not floating
if (!O.is_floating) O.optDiv.css('height', '');
//toggle class according to okCancelInMulti flag only when it is not floating
O.optDiv.toggleClass('okCancelInMulti', settings.okCancelInMulti && !O.is_floating);
},
//HELPERS FOR OUTSIDERS
// validates range of given item operations
vRange: function (i) {
var O = this;
var opts = O.E.find('option');
if (opts.length <= i || i < 0) throw "index out of bounds"
return O;
},
//toggles selection on c as boolean.
toggSel: function (c, i) {
var O = this;
var opt;
if (typeof (i) === "number") {
O.vRange(i);
opt = O.E.find('option')[i];
}
else {
opt = O.E.find('option[value="' + i + '"]')[0] || 0;
}
if (!opt || opt.disabled)
return;
if (opt.selected != c) {
opt.selected = c;
if (!O.mob) $(opt).data('li').toggleClass('selected', c);
O.callChange();
O.setPstate();
O.setText();
O.selAllState();
}
},
//toggles disabled on c as boolean.
toggDis: function (c, i) {
var O = this.vRange(i);
O.E.find('option')[i].disabled = c;
if (c) O.E.find('option')[i].selected = false;
if (!O.mob) O.optDiv.find('ul.options li').eq(i).toggleClass('disabled', c).removeClass('selected');
O.setText();
},
// toggle disable/enable on complete select control
toggSumo: function (val) {
var O = this;
O.enabled = val;
O.select.toggleClass('disabled', val);
if (val) {
O.E.attr('disabled', 'disabled');
O.select.removeAttr('tabindex');
}
else {
O.E.removeAttr('disabled');
O.select.attr('tabindex', '0');
}
return O;
},
// toggles all option on c as boolean.
// set direct=false/0 bypasses okCancelInMulti behaviour.
toggSelAll: function (c, direct) {
var O = this;
O.optDiv.find('li.opt:not(.hidden,.disabled)')
.each(function (ix, e) {
var e = $(e),
is_selected = e.hasClass('selected');
if (!!c) {
if (!is_selected) e.trigger('click');
}
else {
if (is_selected) e.trigger('click');
}
});
if (!direct) {
if (!O.mob && O.selAll) O.selAll.removeClass('partial').toggleClass('selected', !!c);
O.callChange();
O.setText();
O.setPstate();
}
},
/* outside accessibility options
which can be accessed from the element instance.
*/
reload: function () {
var elm = this.unload();
return $(elm).SumoSelect(settings);
},
unload: function () {
var O = this;
O.select.before(O.E);
O.E.show();
if (settings.outputAsCSV && O.is_multi && O.select.find('input.HEMANT123').length) {
O.E.attr('name', O.select.find('input.HEMANT123').attr('name')); // restore the name;
}
O.select.remove();
delete selObj.sumo;
return selObj;
},
//## add a new option to select at a given index.
add: function (val, txt, i) {
if (typeof val == "undefined") throw "No value to add"
var O = this;
opts = O.E.find('option')
if (typeof txt == "number") { i = txt; txt = val; }
if (typeof txt == "undefined") { txt = val; }
opt = $(" ").val(val).html(txt);
if (opts.length < i) throw "index out of bounds"
if (typeof i == "undefined" || opts.length == i) { // add it to the last if given index is last no or no index provides.
O.E.append(opt);
if (!O.mob) O.ul.append(O.createLi(opt));
}
else {
opts.eq(i).before(opt);
if (!O.mob) O.ul.find('li.opt').eq(i).before(O.createLi(opt));
}
return selObj;
},
//## removes an item at a given index.
remove: function (i) {
var O = this.vRange(i);
O.E.find('option').eq(i).remove();
if (!O.mob) O.optDiv.find('ul.options li').eq(i).remove();
O.setText();
},
//## Select an item at a given index.
selectItem: function (i) { this.toggSel(true, i); },
//## UnSelect an iten at a given index.
unSelectItem: function (i) { this.toggSel(false, i); },
//## Select all items of the select.
selectAll: function () { this.toggSelAll(true); },
//## UnSelect all items of the select.
unSelectAll: function () { this.toggSelAll(false); },
//## Disable an iten at a given index.
disableItem: function (i) { this.toggDis(true, i) },
//## Removes disabled an iten at a given index.
enableItem: function (i) { this.toggDis(false, i) },
//## New simple methods as getter and setter are not working fine in ie8-
//## variable to check state of control if enabled or disabled.
enabled: true,
//## Enables the control
enable: function () { return this.toggSumo(false) },
//## Disables the control
disable: function () { return this.toggSumo(true) },
init: function () {
var O = this;
O.createElems();
O.setText();
return O
}
};
selObj.sumo.init();
});
return ret.length == 1 ? ret[0] : ret;
};
});
// Underscore.js 1.8.3
// http://underscorejs.org
// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license.
(function () {
// Baseline setup
// --------------
// Establish the root object, `window` in the browser, or `exports` on the server.
var root = this;
// Save the previous value of the `_` variable.
var previousUnderscore = root._;
// Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
// Create quick reference variables for speed access to core prototypes.
var
push = ArrayProto.push,
slice = ArrayProto.slice,
toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty;
// All **ECMAScript 5** native function implementations that we hope to use
// are declared here.
var
nativeIsArray = Array.isArray,
nativeKeys = Object.keys,
nativeBind = FuncProto.bind,
nativeCreate = Object.create;
// Naked function reference for surrogate-prototype-swapping.
var Ctor = function () { };
// Create a safe reference to the Underscore object for use below.
var _ = function (obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
// Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we're in
// the browser, add `_` as a global object.
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = _;
}
exports._ = _;
} else {
root._ = _;
}
// Current version.
_.VERSION = '1.8.3';
// Internal function that returns an efficient (for current engines) version
// of the passed-in callback, to be repeatedly applied in other Underscore
// functions.
var optimizeCb = function (func, context, argCount) {
if (context === void 0) return func;
switch (argCount == null ? 3 : argCount) {
case 1: return function (value) {
return func.call(context, value);
};
case 2: return function (value, other) {
return func.call(context, value, other);
};
case 3: return function (value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function (accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
return function () {
return func.apply(context, arguments);
};
};
// A mostly-internal function to generate callbacks that can be applied
// to each element in a collection, returning the desired result — either
// identity, an arbitrary callback, a property matcher, or a property accessor.
var cb = function (value, context, argCount) {
if (value == null) return _.identity;
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
if (_.isObject(value)) return _.matcher(value);
return _.property(value);
};
_.iteratee = function (value, context) {
return cb(value, context, Infinity);
};
// An internal function for creating assigner functions.
var createAssigner = function (keysFunc, undefinedOnly) {
return function (obj) {
var length = arguments.length;
if (length < 2 || obj == null) return obj;
for (var index = 1; index < length; index++) {
var source = arguments[index],
keys = keysFunc(source),
l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
}
}
return obj;
};
};
// An internal function for creating a new object that inherits from another.
var baseCreate = function (prototype) {
if (!_.isObject(prototype)) return {};
if (nativeCreate) return nativeCreate(prototype);
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
};
var property = function (key) {
return function (obj) {
return obj == null ? void 0 : obj[key];
};
};
// Helper for collection methods to determine whether a collection
// should be iterated as an array or as an object
// Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
var getLength = property('length');
var isArrayLike = function (collection) {
var length = getLength(collection);
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
};
// Collection Functions
// --------------------
// The cornerstone, an `each` implementation, aka `forEach`.
// Handles raw objects in addition to array-likes. Treats all
// sparse array-likes as if they were dense.
_.each = _.forEach = function (obj, iteratee, context) {
iteratee = optimizeCb(iteratee, context);
var i, length;
if (isArrayLike(obj)) {
for (i = 0, length = obj.length; i < length; i++) {
iteratee(obj[i], i, obj);
}
} else {
var keys = _.keys(obj);
for (i = 0, length = keys.length; i < length; i++) {
iteratee(obj[keys[i]], keys[i], obj);
}
}
return obj;
};
// Return the results of applying the iteratee to each element.
_.map = _.collect = function (obj, iteratee, context) {
iteratee = cb(iteratee, context);
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length,
results = Array(length);
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
results[index] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
// Create a reducing function iterating left or right.
function createReduce(dir) {
// Optimized iterator function as using arguments.length
// in the main function will deoptimize the, see #1991.
function iterator(obj, iteratee, memo, keys, index, length) {
for (; index >= 0 && index < length; index += dir) {
var currentKey = keys ? keys[index] : index;
memo = iteratee(memo, obj[currentKey], currentKey, obj);
}
return memo;
}
return function (obj, iteratee, memo, context) {
iteratee = optimizeCb(iteratee, context, 4);
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length,
index = dir > 0 ? 0 : length - 1;
// Determine the initial value if none is provided.
if (arguments.length < 3) {
memo = obj[keys ? keys[index] : index];
index += dir;
}
return iterator(obj, iteratee, memo, keys, index, length);
};
}
// **Reduce** builds up a single result from a list of values, aka `inject`,
// or `foldl`.
_.reduce = _.foldl = _.inject = createReduce(1);
// The right-associative version of reduce, also known as `foldr`.
_.reduceRight = _.foldr = createReduce(-1);
// Return the first value which passes a truth test. Aliased as `detect`.
_.find = _.detect = function (obj, predicate, context) {
var key;
if (isArrayLike(obj)) {
key = _.findIndex(obj, predicate, context);
} else {
key = _.findKey(obj, predicate, context);
}
if (key !== void 0 && key !== -1) return obj[key];
};
// Return all the elements that pass a truth test.
// Aliased as `select`.
_.filter = _.select = function (obj, predicate, context) {
var results = [];
predicate = cb(predicate, context);
_.each(obj, function (value, index, list) {
if (predicate(value, index, list)) results.push(value);
});
return results;
};
// Return all the elements for which a truth test fails.
_.reject = function (obj, predicate, context) {
return _.filter(obj, _.negate(cb(predicate)), context);
};
// Determine whether all of the elements match a truth test.
// Aliased as `all`.
_.every = _.all = function (obj, predicate, context) {
predicate = cb(predicate, context);
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length;
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
if (!predicate(obj[currentKey], currentKey, obj)) return false;
}
return true;
};
// Determine if at least one element in the object matches a truth test.
// Aliased as `any`.
_.some = _.any = function (obj, predicate, context) {
predicate = cb(predicate, context);
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length;
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
if (predicate(obj[currentKey], currentKey, obj)) return true;
}
return false;
};
// Determine if the array or object contains a given item (using `===`).
// Aliased as `includes` and `include`.
_.contains = _.includes = _.include = function (obj, item, fromIndex, guard) {
if (!isArrayLike(obj)) obj = _.values(obj);
if (typeof fromIndex != 'number' || guard) fromIndex = 0;
return _.indexOf(obj, item, fromIndex) >= 0;
};
// Invoke a method (with arguments) on every item in a collection.
_.invoke = function (obj, method) {
var args = slice.call(arguments, 2);
var isFunc = _.isFunction(method);
return _.map(obj, function (value) {
var func = isFunc ? method : value[method];
return func == null ? func : func.apply(value, args);
});
};
// Convenience version of a common use case of `map`: fetching a property.
_.pluck = function (obj, key) {
return _.map(obj, _.property(key));
};
// Convenience version of a common use case of `filter`: selecting only objects
// containing specific `key:value` pairs.
_.where = function (obj, attrs) {
return _.filter(obj, _.matcher(attrs));
};
// Convenience version of a common use case of `find`: getting the first object
// containing specific `key:value` pairs.
_.findWhere = function (obj, attrs) {
return _.find(obj, _.matcher(attrs));
};
// Return the maximum element (or element-based computation).
_.max = function (obj, iteratee, context) {
var result = -Infinity, lastComputed = -Infinity,
value, computed;
if (iteratee == null && obj != null) {
obj = isArrayLike(obj) ? obj : _.values(obj);
for (var i = 0, length = obj.length; i < length; i++) {
value = obj[i];
if (value > result) {
result = value;
}
}
} else {
iteratee = cb(iteratee, context);
_.each(obj, function (value, index, list) {
computed = iteratee(value, index, list);
if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
result = value;
lastComputed = computed;
}
});
}
return result;
};
// Return the minimum element (or element-based computation).
_.min = function (obj, iteratee, context) {
var result = Infinity, lastComputed = Infinity,
value, computed;
if (iteratee == null && obj != null) {
obj = isArrayLike(obj) ? obj : _.values(obj);
for (var i = 0, length = obj.length; i < length; i++) {
value = obj[i];
if (value < result) {
result = value;
}
}
} else {
iteratee = cb(iteratee, context);
_.each(obj, function (value, index, list) {
computed = iteratee(value, index, list);
if (computed < lastComputed || computed === Infinity && result === Infinity) {
result = value;
lastComputed = computed;
}
});
}
return result;
};
// Shuffle a collection, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
_.shuffle = function (obj) {
var set = isArrayLike(obj) ? obj : _.values(obj);
var length = set.length;
var shuffled = Array(length);
for (var index = 0, rand; index < length; index++) {
rand = _.random(0, index);
if (rand !== index) shuffled[index] = shuffled[rand];
shuffled[rand] = set[index];
}
return shuffled;
};
// Sample **n** random values from a collection.
// If **n** is not specified, returns a single random element.
// The internal `guard` argument allows it to work with `map`.
_.sample = function (obj, n, guard) {
if (n == null || guard) {
if (!isArrayLike(obj)) obj = _.values(obj);
return obj[_.random(obj.length - 1)];
}
return _.shuffle(obj).slice(0, Math.max(0, n));
};
// Sort the object's values by a criterion produced by an iteratee.
_.sortBy = function (obj, iteratee, context) {
iteratee = cb(iteratee, context);
return _.pluck(_.map(obj, function (value, index, list) {
return {
value: value,
index: index,
criteria: iteratee(value, index, list)
};
}).sort(function (left, right) {
var a = left.criteria;
var b = right.criteria;
if (a !== b) {
if (a > b || a === void 0) return 1;
if (a < b || b === void 0) return -1;
}
return left.index - right.index;
}), 'value');
};
// An internal function used for aggregate "group by" operations.
var group = function (behavior) {
return function (obj, iteratee, context) {
var result = {};
iteratee = cb(iteratee, context);
_.each(obj, function (value, index) {
var key = iteratee(value, index, obj);
behavior(result, value, key);
});
return result;
};
};
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
_.groupBy = group(function (result, value, key) {
if (_.has(result, key)) result[key].push(value); else result[key] = [value];
});
// Indexes the object's values by a criterion, similar to `groupBy`, but for
// when you know that your index values will be unique.
_.indexBy = group(function (result, value, key) {
result[key] = value;
});
// Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the
// criterion.
_.countBy = group(function (result, value, key) {
if (_.has(result, key)) result[key]++; else result[key] = 1;
});
// Safely create a real, live array from anything iterable.
_.toArray = function (obj) {
if (!obj) return [];
if (_.isArray(obj)) return slice.call(obj);
if (isArrayLike(obj)) return _.map(obj, _.identity);
return _.values(obj);
};
// Return the number of elements in an object.
_.size = function (obj) {
if (obj == null) return 0;
return isArrayLike(obj) ? obj.length : _.keys(obj).length;
};
// Split a collection into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = function (obj, predicate, context) {
predicate = cb(predicate, context);
var pass = [], fail = [];
_.each(obj, function (value, key, obj) {
(predicate(value, key, obj) ? pass : fail).push(value);
});
return [pass, fail];
};
// Array Functions
// ---------------
// Get the first element of an array. Passing **n** will return the first N
// values in the array. Aliased as `head` and `take`. The **guard** check
// allows it to work with `_.map`.
_.first = _.head = _.take = function (array, n, guard) {
if (array == null) return void 0;
if (n == null || guard) return array[0];
return _.initial(array, array.length - n);
};
// Returns everything but the last entry of the array. Especially useful on
// the arguments object. Passing **n** will return all the values in
// the array, excluding the last N.
_.initial = function (array, n, guard) {
return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
};
// Get the last element of an array. Passing **n** will return the last N
// values in the array.
_.last = function (array, n, guard) {
if (array == null) return void 0;
if (n == null || guard) return array[array.length - 1];
return _.rest(array, Math.max(0, array.length - n));
};
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
// Especially useful on the arguments object. Passing an **n** will return
// the rest N values in the array.
_.rest = _.tail = _.drop = function (array, n, guard) {
return slice.call(array, n == null || guard ? 1 : n);
};
// Trim out all falsy values from an array.
_.compact = function (array) {
return _.filter(array, _.identity);
};
// Internal implementation of a recursive `flatten` function.
var flatten = function (input, shallow, strict, startIndex) {
var output = [], idx = 0;
for (var i = startIndex || 0, length = getLength(input) ; i < length; i++) {
var value = input[i];
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
//flatten current level of array or arguments object
if (!shallow) value = flatten(value, shallow, strict);
var j = 0, len = value.length;
output.length += len;
while (j < len) {
output[idx++] = value[j++];
}
} else if (!strict) {
output[idx++] = value;
}
}
return output;
};
// Flatten out an array, either recursively (by default), or just one level.
_.flatten = function (array, shallow) {
return flatten(array, shallow, false);
};
// Return a version of the array that does not contain the specified value(s).
_.without = function (array) {
return _.difference(array, slice.call(arguments, 1));
};
// Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`.
_.uniq = _.unique = function (array, isSorted, iteratee, context) {
if (!_.isBoolean(isSorted)) {
context = iteratee;
iteratee = isSorted;
isSorted = false;
}
if (iteratee != null) iteratee = cb(iteratee, context);
var result = [];
var seen = [];
for (var i = 0, length = getLength(array) ; i < length; i++) {
var value = array[i],
computed = iteratee ? iteratee(value, i, array) : value;
if (isSorted) {
if (!i || seen !== computed) result.push(value);
seen = computed;
} else if (iteratee) {
if (!_.contains(seen, computed)) {
seen.push(computed);
result.push(value);
}
} else if (!_.contains(result, value)) {
result.push(value);
}
}
return result;
};
// Produce an array that contains the union: each distinct element from all of
// the passed-in arrays.
_.union = function () {
return _.uniq(flatten(arguments, true, true));
};
// Produce an array that contains every item shared between all the
// passed-in arrays.
_.intersection = function (array) {
var result = [];
var argsLength = arguments.length;
for (var i = 0, length = getLength(array) ; i < length; i++) {
var item = array[i];
if (_.contains(result, item)) continue;
for (var j = 1; j < argsLength; j++) {
if (!_.contains(arguments[j], item)) break;
}
if (j === argsLength) result.push(item);
}
return result;
};
// Take the difference between one array and a number of other arrays.
// Only the elements present in just the first array will remain.
_.difference = function (array) {
var rest = flatten(arguments, true, true, 1);
return _.filter(array, function (value) {
return !_.contains(rest, value);
});
};
// Zip together multiple lists into a single array -- elements that share
// an index go together.
_.zip = function () {
return _.unzip(arguments);
};
// Complement of _.zip. Unzip accepts an array of arrays and groups
// each array's elements on shared indices
_.unzip = function (array) {
var length = array && _.max(array, getLength).length || 0;
var result = Array(length);
for (var index = 0; index < length; index++) {
result[index] = _.pluck(array, index);
}
return result;
};
// Converts lists into objects. Pass either a single array of `[key, value]`
// pairs, or two parallel arrays of the same length -- one of keys, and one of
// the corresponding values.
_.object = function (list, values) {
var result = {};
for (var i = 0, length = getLength(list) ; i < length; i++) {
if (values) {
result[list[i]] = values[i];
} else {
result[list[i][0]] = list[i][1];
}
}
return result;
};
// Generator function to create the findIndex and findLastIndex functions
function createPredicateIndexFinder(dir) {
return function (array, predicate, context) {
predicate = cb(predicate, context);
var length = getLength(array);
var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
return -1;
};
}
// Returns the first index on an array-like that passes a predicate test
_.findIndex = createPredicateIndexFinder(1);
_.findLastIndex = createPredicateIndexFinder(-1);
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function (array, obj, iteratee, context) {
iteratee = cb(iteratee, context, 1);
var value = iteratee(obj);
var low = 0, high = getLength(array);
while (low < high) {
var mid = Math.floor((low + high) / 2);
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
}
return low;
};
// Generator function to create the indexOf and lastIndexOf functions
function createIndexFinder(dir, predicateFind, sortedIndex) {
return function (array, item, idx) {
var i = 0, length = getLength(array);
if (typeof idx == 'number') {
if (dir > 0) {
i = idx >= 0 ? idx : Math.max(idx + length, i);
} else {
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
}
} else if (sortedIndex && idx && length) {
idx = sortedIndex(array, item);
return array[idx] === item ? idx : -1;
}
if (item !== item) {
idx = predicateFind(slice.call(array, i, length), _.isNaN);
return idx >= 0 ? idx + i : -1;
}
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
if (array[idx] === item) return idx;
}
return -1;
};
}
// Return the position of the first occurrence of an item in an array,
// or -1 if the item is not included in the array.
// If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search.
_.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
_.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
// Generate an integer Array containing an arithmetic progression. A port of
// the native Python `range()` function. See
// [the Python documentation](http://docs.python.org/library/functions.html#range).
_.range = function (start, stop, step) {
if (stop == null) {
stop = start || 0;
start = 0;
}
step = step || 1;
var length = Math.max(Math.ceil((stop - start) / step), 0);
var range = Array(length);
for (var idx = 0; idx < length; idx++, start += step) {
range[idx] = start;
}
return range;
};
// Function (ahem) Functions
// ------------------
// Determines whether to execute a function as a constructor
// or a normal function with the provided arguments
var executeBound = function (sourceFunc, boundFunc, context, callingContext, args) {
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
var self = baseCreate(sourceFunc.prototype);
var result = sourceFunc.apply(self, args);
if (_.isObject(result)) return result;
return self;
};
// Create a function bound to a given object (assigning `this`, and arguments,
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
// available.
_.bind = function (func, context) {
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
var args = slice.call(arguments, 2);
var bound = function () {
return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
};
return bound;
};
// Partially apply a function by creating a version that has had some of its
// arguments pre-filled, without changing its dynamic `this` context. _ acts
// as a placeholder, allowing any combination of arguments to be pre-filled.
_.partial = function (func) {
var boundArgs = slice.call(arguments, 1);
var bound = function () {
var position = 0, length = boundArgs.length;
var args = Array(length);
for (var i = 0; i < length; i++) {
args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
}
while (position < arguments.length) args.push(arguments[position++]);
return executeBound(func, bound, this, this, args);
};
return bound;
};
// Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it.
_.bindAll = function (obj) {
var i, length = arguments.length, key;
if (length <= 1) throw new Error('bindAll must be passed function names');
for (i = 1; i < length; i++) {
key = arguments[i];
obj[key] = _.bind(obj[key], obj);
}
return obj;
};
// Memoize an expensive function by storing its results.
_.memoize = function (func, hasher) {
var memoize = function (key) {
var cache = memoize.cache;
var address = '' + (hasher ? hasher.apply(this, arguments) : key);
if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
return cache[address];
};
memoize.cache = {};
return memoize;
};
// Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied.
_.delay = function (func, wait) {
var args = slice.call(arguments, 2);
return setTimeout(function () {
return func.apply(null, args);
}, wait);
};
// Defers a function, scheduling it to run after the current call stack has
// cleared.
_.defer = _.partial(_.delay, _, 1);
// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run
// as much as it can, without ever going more than once per `wait` duration;
// but if you'd like to disable the execution on the leading edge, pass
// `{leading: false}`. To disable execution on the trailing edge, ditto.
_.throttle = function (func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
if (!options) options = {};
var later = function () {
previous = options.leading === false ? 0 : _.now();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function () {
var now = _.now();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
};
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function (func, wait, immediate) {
var timeout, args, context, timestamp, result;
var later = function () {
var last = _.now() - timestamp;
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
if (!timeout) context = args = null;
}
}
};
return function () {
context = this;
args = arguments;
timestamp = _.now();
var callNow = immediate && !timeout;
if (!timeout) timeout = setTimeout(later, wait);
if (callNow) {
result = func.apply(context, args);
context = args = null;
}
return result;
};
};
// Returns the first function passed as an argument to the second,
// allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function.
_.wrap = function (func, wrapper) {
return _.partial(wrapper, func);
};
// Returns a negated version of the passed-in predicate.
_.negate = function (predicate) {
return function () {
return !predicate.apply(this, arguments);
};
};
// Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows.
_.compose = function () {
var args = arguments;
var start = args.length - 1;
return function () {
var i = start;
var result = args[start].apply(this, arguments);
while (i--) result = args[i].call(this, result);
return result;
};
};
// Returns a function that will only be executed on and after the Nth call.
_.after = function (times, func) {
return function () {
if (--times < 1) {
return func.apply(this, arguments);
}
};
};
// Returns a function that will only be executed up to (but not including) the Nth call.
_.before = function (times, func) {
var memo;
return function () {
if (--times > 0) {
memo = func.apply(this, arguments);
}
if (times <= 1) func = null;
return memo;
};
};
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = _.partial(_.before, 2);
// Object Functions
// ----------------
// Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
var hasEnumBug = !{ toString: null }.propertyIsEnumerable('toString');
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
function collectNonEnumProps(obj, keys) {
var nonEnumIdx = nonEnumerableProps.length;
var constructor = obj.constructor;
var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
// Constructor is a special case.
var prop = 'constructor';
if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
while (nonEnumIdx--) {
prop = nonEnumerableProps[nonEnumIdx];
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
keys.push(prop);
}
}
}
// Retrieve the names of an object's own properties.
// Delegates to **ECMAScript 5**'s native `Object.keys`
_.keys = function (obj) {
if (!_.isObject(obj)) return [];
if (nativeKeys) return nativeKeys(obj);
var keys = [];
for (var key in obj) if (_.has(obj, key)) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys;
};
// Retrieve all the property names of an object.
_.allKeys = function (obj) {
if (!_.isObject(obj)) return [];
var keys = [];
for (var key in obj) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys;
};
// Retrieve the values of an object's properties.
_.values = function (obj) {
var keys = _.keys(obj);
var length = keys.length;
var values = Array(length);
for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]];
}
return values;
};
// Returns the results of applying the iteratee to each element of the object
// In contrast to _.map it returns an object
_.mapObject = function (obj, iteratee, context) {
iteratee = cb(iteratee, context);
var keys = _.keys(obj),
length = keys.length,
results = {},
currentKey;
for (var index = 0; index < length; index++) {
currentKey = keys[index];
results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
// Convert an object into a list of `[key, value]` pairs.
_.pairs = function (obj) {
var keys = _.keys(obj);
var length = keys.length;
var pairs = Array(length);
for (var i = 0; i < length; i++) {
pairs[i] = [keys[i], obj[keys[i]]];
}
return pairs;
};
// Invert the keys and values of an object. The values must be serializable.
_.invert = function (obj) {
var result = {};
var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) {
result[obj[keys[i]]] = keys[i];
}
return result;
};
// Return a sorted list of the function names available on the object.
// Aliased as `methods`
_.functions = _.methods = function (obj) {
var names = [];
for (var key in obj) {
if (_.isFunction(obj[key])) names.push(key);
}
return names.sort();
};
// Extend a given object with all the properties in passed-in object(s).
_.extend = createAssigner(_.allKeys);
// Assigns a given object with all the own properties in the passed-in object(s)
// (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
_.extendOwn = _.assign = createAssigner(_.keys);
// Returns the first key on an object that passes a predicate test
_.findKey = function (obj, predicate, context) {
predicate = cb(predicate, context);
var keys = _.keys(obj), key;
for (var i = 0, length = keys.length; i < length; i++) {
key = keys[i];
if (predicate(obj[key], key, obj)) return key;
}
};
// Return a copy of the object only containing the whitelisted properties.
_.pick = function (object, oiteratee, context) {
var result = {}, obj = object, iteratee, keys;
if (obj == null) return result;
if (_.isFunction(oiteratee)) {
keys = _.allKeys(obj);
iteratee = optimizeCb(oiteratee, context);
} else {
keys = flatten(arguments, false, false, 1);
iteratee = function (value, key, obj) { return key in obj; };
obj = Object(obj);
}
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i];
var value = obj[key];
if (iteratee(value, key, obj)) result[key] = value;
}
return result;
};
// Return a copy of the object without the blacklisted properties.
_.omit = function (obj, iteratee, context) {
if (_.isFunction(iteratee)) {
iteratee = _.negate(iteratee);
} else {
var keys = _.map(flatten(arguments, false, false, 1), String);
iteratee = function (value, key) {
return !_.contains(keys, key);
};
}
return _.pick(obj, iteratee, context);
};
// Fill in a given object with default properties.
_.defaults = createAssigner(_.allKeys, true);
// Creates an object that inherits from the given prototype object.
// If additional properties are provided then they will be added to the
// created object.
_.create = function (prototype, props) {
var result = baseCreate(prototype);
if (props) _.extendOwn(result, props);
return result;
};
// Create a (shallow-cloned) duplicate of an object.
_.clone = function (obj) {
if (!_.isObject(obj)) return obj;
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};
// Invokes interceptor with the obj, and then returns obj.
// The primary purpose of this method is to "tap into" a method chain, in
// order to perform operations on intermediate results within the chain.
_.tap = function (obj, interceptor) {
interceptor(obj);
return obj;
};
// Returns whether an object has a given set of `key:value` pairs.
_.isMatch = function (object, attrs) {
var keys = _.keys(attrs), length = keys.length;
if (object == null) return !length;
var obj = Object(object);
for (var i = 0; i < length; i++) {
var key = keys[i];
if (attrs[key] !== obj[key] || !(key in obj)) return false;
}
return true;
};
// Internal recursive comparison function for `isEqual`.
var eq = function (a, b, aStack, bStack) {
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a === 1 / b;
// A strict comparison is necessary because `null == undefined`.
if (a == null || b == null) return a === b;
// Unwrap any wrapped objects.
if (a instanceof _) a = a._wrapped;
if (b instanceof _) b = b._wrapped;
// Compare `[[Class]]` names.
var className = toString.call(a);
if (className !== toString.call(b)) return false;
switch (className) {
// Strings, numbers, regular expressions, dates, and booleans are compared by value.
case '[object RegExp]':
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
case '[object String]':
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`.
return '' + a === '' + b;
case '[object Number]':
// `NaN`s are equivalent, but non-reflexive.
// Object(NaN) is equivalent to NaN
if (+a !== +a) return +b !== +b;
// An `egal` comparison is performed for other numeric values.
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case '[object Date]':
case '[object Boolean]':
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
// millisecond representations. Note that invalid dates with millisecond representations
// of `NaN` are not equivalent.
return +a === +b;
}
var areArrays = className === '[object Array]';
if (!areArrays) {
if (typeof a != 'object' || typeof b != 'object') return false;
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
_.isFunction(bCtor) && bCtor instanceof bCtor)
&& ('constructor' in a && 'constructor' in b)) {
return false;
}
}
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
// Initializing stack of traversed objects.
// It's done here since we only need them for objects and arrays comparison.
aStack = aStack || [];
bStack = bStack || [];
var length = aStack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
if (aStack[length] === a) return bStack[length] === b;
}
// Add the first object to the stack of traversed objects.
aStack.push(a);
bStack.push(b);
// Recursively compare objects and arrays.
if (areArrays) {
// Compare array lengths to determine if a deep comparison is necessary.
length = a.length;
if (length !== b.length) return false;
// Deep compare the contents, ignoring non-numeric properties.
while (length--) {
if (!eq(a[length], b[length], aStack, bStack)) return false;
}
} else {
// Deep compare objects.
var keys = _.keys(a), key;
length = keys.length;
// Ensure that both objects contain the same number of properties before comparing deep equality.
if (_.keys(b).length !== length) return false;
while (length--) {
// Deep compare each member
key = keys[length];
if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
}
}
// Remove the first object from the stack of traversed objects.
aStack.pop();
bStack.pop();
return true;
};
// Perform a deep comparison to check if two objects are equal.
_.isEqual = function (a, b) {
return eq(a, b);
};
// Is a given array, string, or object empty?
// An "empty" object has no enumerable own-properties.
_.isEmpty = function (obj) {
if (obj == null) return true;
if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
return _.keys(obj).length === 0;
};
// Is a given value a DOM element?
_.isElement = function (obj) {
return !!(obj && obj.nodeType === 1);
};
// Is a given value an array?
// Delegates to ECMA5's native Array.isArray
_.isArray = nativeIsArray || function (obj) {
return toString.call(obj) === '[object Array]';
};
// Is a given variable an object?
_.isObject = function (obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
};
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function (name) {
_['is' + name] = function (obj) {
return toString.call(obj) === '[object ' + name + ']';
};
});
// Define a fallback version of the method in browsers (ahem, IE < 9), where
// there isn't any inspectable "Arguments" type.
if (!_.isArguments(arguments)) {
_.isArguments = function (obj) {
return _.has(obj, 'callee');
};
}
// Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
// IE 11 (#1621), and in Safari 8 (#1929).
if (typeof /./ != 'function' && typeof Int8Array != 'object') {
_.isFunction = function (obj) {
return typeof obj == 'function' || false;
};
}
// Is a given object a finite number?
_.isFinite = function (obj) {
return isFinite(obj) && !isNaN(parseFloat(obj));
};
// Is the given value `NaN`? (NaN is the only number which does not equal itself).
_.isNaN = function (obj) {
return _.isNumber(obj) && obj !== +obj;
};
// Is a given value a boolean?
_.isBoolean = function (obj) {
return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
};
// Is a given value equal to null?
_.isNull = function (obj) {
return obj === null;
};
// Is a given variable undefined?
_.isUndefined = function (obj) {
return obj === void 0;
};
// Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype).
_.has = function (obj, key) {
return obj != null && hasOwnProperty.call(obj, key);
};
// Utility Functions
// -----------------
// Run Underscore.js in *noConflict* mode, returning the `_` variable to its
// previous owner. Returns a reference to the Underscore object.
_.noConflict = function () {
root._ = previousUnderscore;
return this;
};
// Keep the identity function around for default iteratees.
_.identity = function (value) {
return value;
};
// Predicate-generating functions. Often useful outside of Underscore.
_.constant = function (value) {
return function () {
return value;
};
};
_.noop = function () { };
_.property = property;
// Generates a function for a given object that returns a given property.
_.propertyOf = function (obj) {
return obj == null ? function () { } : function (key) {
return obj[key];
};
};
// Returns a predicate for checking whether an object has a given set of
// `key:value` pairs.
_.matcher = _.matches = function (attrs) {
attrs = _.extendOwn({}, attrs);
return function (obj) {
return _.isMatch(obj, attrs);
};
};
// Run a function **n** times.
_.times = function (n, iteratee, context) {
var accum = Array(Math.max(0, n));
iteratee = optimizeCb(iteratee, context, 1);
for (var i = 0; i < n; i++) accum[i] = iteratee(i);
return accum;
};
// Return a random integer between min and max (inclusive).
_.random = function (min, max) {
if (max == null) {
max = min;
min = 0;
}
return min + Math.floor(Math.random() * (max - min + 1));
};
// A (possibly faster) way to get the current timestamp as an integer.
_.now = Date.now || function () {
return new Date().getTime();
};
// List of HTML entities for escaping.
var escapeMap = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'`': '`'
};
var unescapeMap = _.invert(escapeMap);
// Functions for escaping and unescaping strings to/from HTML interpolation.
var createEscaper = function (map) {
var escaper = function (match) {
return map[match];
};
// Regexes for identifying a key that needs to be escaped
var source = '(?:' + _.keys(map).join('|') + ')';
var testRegexp = RegExp(source);
var replaceRegexp = RegExp(source, 'g');
return function (string) {
string = string == null ? '' : '' + string;
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
};
};
_.escape = createEscaper(escapeMap);
_.unescape = createEscaper(unescapeMap);
// If the value of the named `property` is a function then invoke it with the
// `object` as context; otherwise, return it.
_.result = function (object, property, fallback) {
var value = object == null ? void 0 : object[property];
if (value === void 0) {
value = fallback;
}
return _.isFunction(value) ? value.call(object) : value;
};
// Generate a unique integer id (unique within the entire client session).
// Useful for temporary DOM ids.
var idCounter = 0;
_.uniqueId = function (prefix) {
var id = ++idCounter + '';
return prefix ? prefix + id : id;
};
// By default, Underscore uses ERB-style template delimiters, change the
// following template settings to use alternative delimiters.
_.templateSettings = {
evaluate: /<%([\s\S]+?)%>/g,
interpolate: /<%=([\s\S]+?)%>/g,
escape: /<%-([\s\S]+?)%>/g
};
// When customizing `templateSettings`, if you don't want to define an
// interpolation, evaluation or escaping regex, we need one that is
// guaranteed not to match.
var noMatch = /(.)^/;
// Certain characters need to be escaped so that they can be put into a
// string literal.
var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
var escapeChar = function (match) {
return '\\' + escapes[match];
};
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
// NB: `oldSettings` only exists for backwards compatibility.
_.template = function (text, settings, oldSettings) {
if (!settings && oldSettings) settings = oldSettings;
settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation.
var matcher = RegExp([
(settings.escape || noMatch).source,
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join('|') + '|$', 'g');
// Compile the template source, escaping string literals appropriately.
var index = 0;
var source = "__p+='";
text.replace(matcher, function (match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset).replace(escaper, escapeChar);
index = offset + match.length;
if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
} else if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
} else if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
// Adobe VMs need the match returned to produce the correct offest.
return match;
});
source += "';\n";
// If a variable is not specified, place data values in local scope.
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
source + 'return __p;\n';
try {
var render = new Function(settings.variable || 'obj', '_', source);
} catch (e) {
e.source = source;
throw e;
}
var template = function (data) {
return render.call(this, data, _);
};
// Provide the compiled source as a convenience for precompilation.
var argument = settings.variable || 'obj';
template.source = 'function(' + argument + '){\n' + source + '}';
return template;
};
// Add a "chain" function. Start chaining a wrapped Underscore object.
_.chain = function (obj) {
var instance = _(obj);
instance._chain = true;
return instance;
};
// OOP
// ---------------
// If Underscore is called as a function, it returns a wrapped object that
// can be used OO-style. This wrapper holds altered versions of all the
// underscore functions. Wrapped objects may be chained.
// Helper function to continue chaining intermediate results.
var result = function (instance, obj) {
return instance._chain ? _(obj).chain() : obj;
};
// Add your own custom functions to the Underscore object.
_.mixin = function (obj) {
_.each(_.functions(obj), function (name) {
var func = _[name] = obj[name];
_.prototype[name] = function () {
var args = [this._wrapped];
push.apply(args, arguments);
return result(this, func.apply(_, args));
};
});
};
// Add all of the Underscore functions to the wrapper object.
_.mixin(_);
// Add all mutator Array functions to the wrapper.
_.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function (name) {
var method = ArrayProto[name];
_.prototype[name] = function () {
var obj = this._wrapped;
method.apply(obj, arguments);
if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
return result(this, obj);
};
});
// Add all accessor Array functions to the wrapper.
_.each(['concat', 'join', 'slice'], function (name) {
var method = ArrayProto[name];
_.prototype[name] = function () {
return result(this, method.apply(this._wrapped, arguments));
};
});
// Extracts the result from a wrapped and chained object.
_.prototype.value = function () {
return this._wrapped;
};
// Provide unwrapping proxy for some methods used in engine operations
// such as arithmetic and JSON stringification.
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
_.prototype.toString = function () {
return '' + this._wrapped;
};
// AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general
// practice for AMD registration is to be anonymous, underscore registers
// as a named module because, like jQuery, it is a base library that is
// popular enough to be bundled in a third party lib, but not be part of
// an AMD load request. Those cases could generate an error when an
// anonymous define() is called outside of a loader request.
if (typeof define === 'function' && define.amd) {
define('underscore', [], function () {
return _;
});
}
}.call(this));
// Backbone.js 1.2.0
// (c) 2010-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Backbone may be freely distributed under the MIT license.
// For all details and documentation:
// http://backbonejs.org
(function (factory) {
// Establish the root object, `window` (`self`) in the browser, or `global` on the server.
// We use `self` instead of `window` for `WebWorker` support.
var root = (typeof self == 'object' && self.self == self && self) ||
(typeof global == 'object' && global.global == global && global);
// Set up Backbone appropriately for the environment. Start with AMD.
if (typeof define === 'function' && define.amd) {
define(['underscore', 'jquery', 'exports'], function (_, $, exports) {
// Export global even in AMD case in case this script is loaded with
// others that may still expect a global Backbone.
root.Backbone = factory(root, exports, _, $);
});
// Next for Node.js or CommonJS. jQuery may not be needed as a module.
} else if (typeof exports !== 'undefined') {
var _ = require('underscore'), $;
try { $ = require('jquery'); } catch (e) { }
factory(root, exports, _, $);
// Finally, as a browser global.
} else {
root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
}
}(function (root, Backbone, _, $) {
// Initial Setup
// -------------
// Save the previous value of the `Backbone` variable, so that it can be
// restored later on, if `noConflict` is used.
var previousBackbone = root.Backbone;
// Create local references to array methods we'll want to use later.
var array = [];
var slice = array.slice;
// Current version of the library. Keep in sync with `package.json`.
Backbone.VERSION = '1.2.0';
// For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
// the `$` variable.
Backbone.$ = $;
// Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
// to its previous owner. Returns a reference to this Backbone object.
Backbone.noConflict = function () {
root.Backbone = previousBackbone;
return this;
};
// Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
// will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and
// set a `X-Http-Method-Override` header.
Backbone.emulateHTTP = false;
// Turn on `emulateJSON` to support legacy servers that can't deal with direct
// `application/json` requests ... this will encode the body as
// `application/x-www-form-urlencoded` instead and will send the model in a
// form param named `model`.
Backbone.emulateJSON = false;
// Backbone.Events
// ---------------
// A module that can be mixed in to *any object* in order to provide it with
// custom events. You may bind with `on` or remove with `off` callback
// functions to an event; `trigger`-ing an event fires all callbacks in
// succession.
//
// var object = {};
// _.extend(object, Backbone.Events);
// object.on('expand', function(){ alert('expanded'); });
// object.trigger('expand');
//
var Events = Backbone.Events = {};
// Regular expression used to split event strings.
var eventSplitter = /\s+/;
// Iterates over the standard `event, callback` (as well as the fancy multiple
// space-separated events `"change blur", callback` and jQuery-style event
// maps `{event: callback}`), reducing them by manipulating `memo`.
// Passes a normalized single event name and callback, as well as any
// optional `opts`.
var eventsApi = function (iteratee, memo, name, callback, opts) {
var i = 0, names;
if (name && typeof name === 'object') {
// Handle event maps.
for (names = _.keys(name) ; i < names.length ; i++) {
memo = iteratee(memo, names[i], name[names[i]], opts);
}
} else if (name && eventSplitter.test(name)) {
// Handle space separated event names.
for (names = name.split(eventSplitter) ; i < names.length; i++) {
memo = iteratee(memo, names[i], callback, opts);
}
} else {
memo = iteratee(memo, name, callback, opts);
}
return memo;
};
// Bind an event to a `callback` function. Passing `"all"` will bind
// the callback to all events fired.
Events.on = function (name, callback, context) {
return internalOn(this, name, callback, context);
};
// An internal use `on` function, used to guard the `listening` argument from
// the public API.
var internalOn = function (obj, name, callback, context, listening) {
obj._events = eventsApi(onApi, obj._events || {}, name, callback, {
context: context,
ctx: obj,
listening: listening
});
if (listening) {
var listeners = obj._listeners || (obj._listeners = {});
listeners[listening.id] = listening;
}
return obj;
};
// Inversion-of-control versions of `on`. Tell *this* object to listen to
// an event in another object... keeping track of what it's listening to.
Events.listenTo = function (obj, name, callback) {
if (!obj) return this;
var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
var listeningTo = this._listeningTo || (this._listeningTo = {});
var listening = listeningTo[id];
// This object is not listening to any other events on `obj` yet.
// Setup the necessary references to track the listening callbacks.
if (!listening) {
var thisId = this._listenId || (this._listenId = _.uniqueId('l'));
listening = listeningTo[id] = { obj: obj, objId: id, id: thisId, listeningTo: listeningTo, count: 0 };
}
// Bind callbacks on obj, and keep track of them on listening.
internalOn(obj, name, callback, this, listening);
return this;
};
// The reducing API that adds a callback to the `events` object.
var onApi = function (events, name, callback, options) {
if (callback) {
var handlers = events[name] || (events[name] = []);
var context = options.context, ctx = options.ctx, listening = options.listening;
if (listening) listening.count++;
handlers.push({ callback: callback, context: context, ctx: context || ctx, listening: listening });
}
return events;
};
// Remove one or many callbacks. If `context` is null, removes all
// callbacks with that function. If `callback` is null, removes all
// callbacks for the event. If `name` is null, removes all bound
// callbacks for all events.
Events.off = function (name, callback, context) {
if (!this._events) return this;
this._events = eventsApi(offApi, this._events, name, callback, {
context: context,
listeners: this._listeners
});
return this;
};
// Tell this object to stop listening to either specific events ... or
// to every object it's currently listening to.
Events.stopListening = function (obj, name, callback) {
var listeningTo = this._listeningTo;
if (!listeningTo) return this;
var ids = obj ? [obj._listenId] : _.keys(listeningTo);
for (var i = 0; i < ids.length; i++) {
var listening = listeningTo[ids[i]];
// If listening doesn't exist, this object is not currently
// listening to obj. Break out early.
if (!listening) break;
listening.obj.off(name, callback, this);
}
if (_.isEmpty(listeningTo)) this._listeningTo = void 0;
return this;
};
// The reducing API that removes a callback from the `events` object.
var offApi = function (events, name, callback, options) {
// No events to consider.
if (!events) return;
var i = 0, length, listening;
var context = options.context, listeners = options.listeners;
// Delete all events listeners and "drop" events.
if (!name && !callback && !context) {
var ids = _.keys(listeners);
for (; i < ids.length; i++) {
listening = listeners[ids[i]];
delete listeners[listening.id];
delete listening.listeningTo[listening.objId];
}
return;
}
var names = name ? [name] : _.keys(events);
for (; i < names.length; i++) {
name = names[i];
var handlers = events[name];
// Bail out if there are no events stored.
if (!handlers) break;
// Replace events if there are any remaining. Otherwise, clean up.
var remaining = [];
for (var j = 0; j < handlers.length; j++) {
var handler = handlers[j];
if (
callback && callback !== handler.callback &&
callback !== handler.callback._callback ||
context && context !== handler.context
) {
remaining.push(handler);
} else {
listening = handler.listening;
if (listening && --listening.count === 0) {
delete listeners[listening.id];
delete listening.listeningTo[listening.objId];
}
}
}
// Update tail event if the list has any events. Otherwise, clean up.
if (remaining.length) {
events[name] = remaining;
} else {
delete events[name];
}
}
if (_.size(events)) return events;
};
// Bind an event to only be triggered a single time. After the first time
// the callback is invoked, it will be removed. When multiple events are
// passed in using the space-separated syntax, the event will fire once for every
// event you passed in, not once for a combination of all events
Events.once = function (name, callback, context) {
// Map the event into a `{event: once}` object.
var events = eventsApi(onceMap, {}, name, callback, _.bind(this.off, this));
return this.on(events, void 0, context);
};
// Inversion-of-control versions of `once`.
Events.listenToOnce = function (obj, name, callback) {
// Map the event into a `{event: once}` object.
var events = eventsApi(onceMap, {}, name, callback, _.bind(this.stopListening, this, obj));
return this.listenTo(obj, events);
};
// Reduces the event callbacks into a map of `{event: onceWrapper}`.
// `offer` unbinds the `onceWrapper` after it as been called.
var onceMap = function (map, name, callback, offer) {
if (callback) {
var once = map[name] = _.once(function () {
offer(name, once);
callback.apply(this, arguments);
});
once._callback = callback;
}
return map;
};
// Trigger one or many events, firing all bound callbacks. Callbacks are
// passed the same arguments as `trigger` is, apart from the event name
// (unless you're listening on `"all"`, which will cause your callback to
// receive the true name of the event as the first argument).
Events.trigger = function (name) {
if (!this._events) return this;
var length = Math.max(0, arguments.length - 1);
var args = Array(length);
for (var i = 0; i < length; i++) args[i] = arguments[i + 1];
eventsApi(triggerApi, this._events, name, void 0, args);
return this;
};
// Handles triggering the appropriate event callbacks.
var triggerApi = function (objEvents, name, cb, args) {
if (objEvents) {
var events = objEvents[name];
var allEvents = objEvents.all;
if (events && allEvents) allEvents = allEvents.slice();
if (events) triggerEvents(events, args);
if (allEvents) triggerEvents(allEvents, [name].concat(args));
}
return objEvents;
};
// A difficult-to-believe, but optimized internal dispatch function for
// triggering events. Tries to keep the usual cases speedy (most internal
// Backbone events have 3 arguments).
var triggerEvents = function (events, args) {
var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
switch (args.length) {
case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
}
};
// Proxy Underscore methods to a Backbone class' prototype using a
// particular attribute as the data argument
var addMethod = function (length, method, attribute) {
switch (length) {
case 1: return function () {
return _[method](this[attribute]);
};
case 2: return function (value) {
return _[method](this[attribute], value);
};
case 3: return function (iteratee, context) {
return _[method](this[attribute], iteratee, context);
};
case 4: return function (iteratee, defaultVal, context) {
return _[method](this[attribute], iteratee, defaultVal, context);
};
default: return function () {
var args = slice.call(arguments);
args.unshift(this[attribute]);
return _[method].apply(_, args);
};
}
};
var addUnderscoreMethods = function (Class, methods, attribute) {
_.each(methods, function (length, method) {
if (_[method]) Class.prototype[method] = addMethod(length, method, attribute);
});
};
// Aliases for backwards compatibility.
Events.bind = Events.on;
Events.unbind = Events.off;
// Allow the `Backbone` object to serve as a global event bus, for folks who
// want global "pubsub" in a convenient place.
_.extend(Backbone, Events);
// Backbone.Model
// --------------
// Backbone **Models** are the basic data object in the framework --
// frequently representing a row in a table in a database on your server.
// A discrete chunk of data and a bunch of useful, related methods for
// performing computations and transformations on that data.
// Create a new model with the specified attributes. A client id (`cid`)
// is automatically generated and assigned for you.
var Model = Backbone.Model = function (attributes, options) {
var attrs = attributes || {};
options || (options = {});
this.cid = _.uniqueId(this.cidPrefix);
this.attributes = {};
if (options.collection) this.collection = options.collection;
if (options.parse) attrs = this.parse(attrs, options) || {};
attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
this.set(attrs, options);
this.changed = {};
this.initialize.apply(this, arguments);
};
// Attach all inheritable methods to the Model prototype.
_.extend(Model.prototype, Events, {
// A hash of attributes whose current and previous value differ.
changed: null,
// The value returned during the last failed validation.
validationError: null,
// The default name for the JSON `id` attribute is `"id"`. MongoDB and
// CouchDB users may want to set this to `"_id"`.
idAttribute: 'id',
// The prefix is used to create the client id which is used to identify models locally.
// You may want to override this if you're experiencing name clashes with model ids.
cidPrefix: 'c',
// Initialize is an empty function by default. Override it with your own
// initialization logic.
initialize: function () { },
// Return a copy of the model's `attributes` object.
toJSON: function (options) {
return _.clone(this.attributes);
},
// Proxy `Backbone.sync` by default -- but override this if you need
// custom syncing semantics for *this* particular model.
sync: function () {
return Backbone.sync.apply(this, arguments);
},
// Get the value of an attribute.
get: function (attr) {
return this.attributes[attr];
},
// Get the HTML-escaped value of an attribute.
escape: function (attr) {
return _.escape(this.get(attr));
},
// Returns `true` if the attribute contains a value that is not null
// or undefined.
has: function (attr) {
return this.get(attr) != null;
},
// Special-cased proxy to underscore's `_.matches` method.
matches: function (attrs) {
return !!_.iteratee(attrs, this)(this.attributes);
},
// Set a hash of model attributes on the object, firing `"change"`. This is
// the core primitive operation of a model, updating the data and notifying
// anyone who needs to know about the change in state. The heart of the beast.
set: function (key, val, options) {
var attr, attrs, unset, changes, silent, changing, prev, current;
if (key == null) return this;
// Handle both `"key", value` and `{key: value}` -style arguments.
if (typeof key === 'object') {
attrs = key;
options = val;
} else {
(attrs = {})[key] = val;
}
options || (options = {});
// Run validation.
if (!this._validate(attrs, options)) return false;
// Extract attributes and options.
unset = options.unset;
silent = options.silent;
changes = [];
changing = this._changing;
this._changing = true;
if (!changing) {
this._previousAttributes = _.clone(this.attributes);
this.changed = {};
}
current = this.attributes, prev = this._previousAttributes;
// Check for changes of `id`.
if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
// For each `set` attribute, update or delete the current value.
for (attr in attrs) {
val = attrs[attr];
if (!_.isEqual(current[attr], val)) changes.push(attr);
if (!_.isEqual(prev[attr], val)) {
this.changed[attr] = val;
} else {
delete this.changed[attr];
}
unset ? delete current[attr] : current[attr] = val;
}
// Trigger all relevant attribute changes.
if (!silent) {
if (changes.length) this._pending = options;
for (var i = 0; i < changes.length; i++) {
this.trigger('change:' + changes[i], this, current[changes[i]], options);
}
}
// You might be wondering why there's a `while` loop here. Changes can
// be recursively nested within `"change"` events.
if (changing) return this;
if (!silent) {
while (this._pending) {
options = this._pending;
this._pending = false;
this.trigger('change', this, options);
}
}
this._pending = false;
this._changing = false;
return this;
},
// Remove an attribute from the model, firing `"change"`. `unset` is a noop
// if the attribute doesn't exist.
unset: function (attr, options) {
return this.set(attr, void 0, _.extend({}, options, { unset: true }));
},
// Clear all attributes on the model, firing `"change"`.
clear: function (options) {
var attrs = {};
for (var key in this.attributes) attrs[key] = void 0;
return this.set(attrs, _.extend({}, options, { unset: true }));
},
// Determine if the model has changed since the last `"change"` event.
// If you specify an attribute name, determine if that attribute has changed.
hasChanged: function (attr) {
if (attr == null) return !_.isEmpty(this.changed);
return _.has(this.changed, attr);
},
// Return an object containing all the attributes that have changed, or
// false if there are no changed attributes. Useful for determining what
// parts of a view need to be updated and/or what attributes need to be
// persisted to the server. Unset attributes will be set to undefined.
// You can also pass an attributes object to diff against the model,
// determining if there *would be* a change.
changedAttributes: function (diff) {
if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
var val, changed = false;
var old = this._changing ? this._previousAttributes : this.attributes;
for (var attr in diff) {
if (_.isEqual(old[attr], (val = diff[attr]))) continue;
(changed || (changed = {}))[attr] = val;
}
return changed;
},
// Get the previous value of an attribute, recorded at the time the last
// `"change"` event was fired.
previous: function (attr) {
if (attr == null || !this._previousAttributes) return null;
return this._previousAttributes[attr];
},
// Get all of the attributes of the model at the time of the previous
// `"change"` event.
previousAttributes: function () {
return _.clone(this._previousAttributes);
},
// Fetch the model from the server, merging the response with the model's
// local attributes. Any changed attributes will trigger a "change" event.
fetch: function (options) {
options = options ? _.clone(options) : {};
if (options.parse === void 0) options.parse = true;
var model = this;
var success = options.success;
options.success = function (resp) {
if (!model.set(model.parse(resp, options), options)) return false;
if (success) success.call(options.context, model, resp, options);
model.trigger('sync', model, resp, options);
};
wrapError(this, options);
return this.sync('read', this, options);
},
// Set a hash of model attributes, and sync the model to the server.
// If the server returns an attributes hash that differs, the model's
// state will be `set` again.
save: function (key, val, options) {
var attrs, method, xhr, attributes = this.attributes, wait;
// Handle both `"key", value` and `{key: value}` -style arguments.
if (key == null || typeof key === 'object') {
attrs = key;
options = val;
} else {
(attrs = {})[key] = val;
}
options = _.extend({ validate: true }, options);
wait = options.wait;
// If we're not waiting and attributes exist, save acts as
// `set(attr).save(null, opts)` with validation. Otherwise, check if
// the model will be valid when the attributes, if any, are set.
if (attrs && !wait) {
if (!this.set(attrs, options)) return false;
} else {
if (!this._validate(attrs, options)) return false;
}
// Set temporary attributes if `{wait: true}`.
if (attrs && wait) {
this.attributes = _.extend({}, attributes, attrs);
}
// After a successful server-side save, the client is (optionally)
// updated with the server-side state.
if (options.parse === void 0) options.parse = true;
var model = this;
var success = options.success;
options.success = function (resp) {
// Ensure attributes are restored during synchronous saves.
model.attributes = attributes;
var serverAttrs = options.parse ? model.parse(resp, options) : resp;
if (wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) {
return false;
}
if (success) success.call(options.context, model, resp, options);
model.trigger('sync', model, resp, options);
};
wrapError(this, options);
method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
if (method === 'patch' && !options.attrs) options.attrs = attrs;
xhr = this.sync(method, this, options);
// Restore attributes.
if (attrs && wait) this.attributes = attributes;
return xhr;
},
// Destroy this model on the server if it was already persisted.
// Optimistically removes the model from its collection, if it has one.
// If `wait: true` is passed, waits for the server to respond before removal.
destroy: function (options) {
options = options ? _.clone(options) : {};
var model = this;
var success = options.success;
var wait = options.wait;
var destroy = function () {
model.stopListening();
model.trigger('destroy', model, model.collection, options);
};
options.success = function (resp) {
if (wait) destroy();
if (success) success.call(options.context, model, resp, options);
if (!model.isNew()) model.trigger('sync', model, resp, options);
};
var xhr = false;
if (this.isNew()) {
_.defer(options.success);
} else {
wrapError(this, options);
xhr = this.sync('delete', this, options);
}
if (!wait) destroy();
return xhr;
},
// Default URL for the model's representation on the server -- if you're
// using Backbone's restful methods, override this to change the endpoint
// that will be called.
url: function () {
var base =
_.result(this, 'urlRoot') ||
_.result(this.collection, 'url') ||
urlError();
if (this.isNew()) return base;
var id = this.id || this.attributes[this.idAttribute];
return base.replace(/([^\/])$/, '$1/') + encodeURIComponent(id);
},
// **parse** converts a response into the hash of attributes to be `set` on
// the model. The default implementation is just to pass the response along.
parse: function (resp, options) {
return resp;
},
// Create a new model with identical attributes to this one.
clone: function () {
return new this.constructor(this.attributes);
},
// A model is new if it has never been saved to the server, and lacks an id.
isNew: function () {
return !this.has(this.idAttribute);
},
// Check if the model is currently in a valid state.
isValid: function (options) {
return this._validate({}, _.extend(options || {}, { validate: true }));
},
// Run validation against the next complete set of model attributes,
// returning `true` if all is well. Otherwise, fire an `"invalid"` event.
_validate: function (attrs, options) {
if (!options.validate || !this.validate) return true;
attrs = _.extend({}, this.attributes, attrs);
var error = this.validationError = this.validate(attrs, options) || null;
if (!error) return true;
this.trigger('invalid', this, error, _.extend(options, { validationError: error }));
return false;
}
});
// Underscore methods that we want to implement on the Model.
var modelMethods = {
keys: 1, values: 1, pairs: 1, invert: 1, pick: 0,
omit: 0, chain: 1, isEmpty: 1
};
// Mix in each Underscore method as a proxy to `Model#attributes`.
addUnderscoreMethods(Model, modelMethods, 'attributes');
// Backbone.Collection
// -------------------
// If models tend to represent a single row of data, a Backbone Collection is
// more analogous to a table full of data ... or a small slice or page of that
// table, or a collection of rows that belong together for a particular reason
// -- all of the messages in this particular folder, all of the documents
// belonging to this particular author, and so on. Collections maintain
// indexes of their models, both in order, and for lookup by `id`.
// Create a new **Collection**, perhaps to contain a specific type of `model`.
// If a `comparator` is specified, the Collection will maintain
// its models in sort order, as they're added and removed.
var Collection = Backbone.Collection = function (models, options) {
options || (options = {});
if (options.model) this.model = options.model;
if (options.comparator !== void 0) this.comparator = options.comparator;
this._reset();
this.initialize.apply(this, arguments);
if (models) this.reset(models, _.extend({ silent: true }, options));
};
// Default options for `Collection#set`.
var setOptions = { add: true, remove: true, merge: true };
var addOptions = { add: true, remove: false };
// Define the Collection's inheritable methods.
_.extend(Collection.prototype, Events, {
// The default model for a collection is just a **Backbone.Model**.
// This should be overridden in most cases.
model: Model,
// Initialize is an empty function by default. Override it with your own
// initialization logic.
initialize: function () { },
// The JSON representation of a Collection is an array of the
// models' attributes.
toJSON: function (options) {
return this.map(function (model) { return model.toJSON(options); });
},
// Proxy `Backbone.sync` by default.
sync: function () {
return Backbone.sync.apply(this, arguments);
},
// Add a model, or list of models to the set.
add: function (models, options) {
return this.set(models, _.extend({ merge: false }, options, addOptions));
},
// Remove a model, or a list of models from the set.
remove: function (models, options) {
var singular = !_.isArray(models), removed;
models = singular ? [models] : _.clone(models);
options || (options = {});
removed = this._removeModels(models, options);
if (!options.silent && removed) this.trigger('update', this, options);
return singular ? models[0] : models;
},
// Update a collection by `set`-ing a new list of models, adding new ones,
// removing models that are no longer present, and merging models that
// already exist in the collection, as necessary. Similar to **Model#set**,
// the core operation for updating the data contained by the collection.
set: function (models, options) {
options = _.defaults({}, options, setOptions);
if (options.parse) models = this.parse(models, options);
var singular = !_.isArray(models);
models = singular ? (models ? [models] : []) : models.slice();
var id, model, attrs, existing, sort;
var at = options.at;
if (at != null) at = +at;
if (at < 0) at += this.length + 1;
var sortable = this.comparator && (at == null) && options.sort !== false;
var sortAttr = _.isString(this.comparator) ? this.comparator : null;
var toAdd = [], toRemove = [], modelMap = {};
var add = options.add, merge = options.merge, remove = options.remove;
var order = !sortable && add && remove ? [] : false;
var orderChanged = false;
// Turn bare objects into model references, and prevent invalid models
// from being added.
for (var i = 0; i < models.length; i++) {
attrs = models[i];
// If a duplicate is found, prevent it from being added and
// optionally merge it into the existing model.
if (existing = this.get(attrs)) {
if (remove) modelMap[existing.cid] = true;
if (merge && attrs !== existing) {
attrs = this._isModel(attrs) ? attrs.attributes : attrs;
if (options.parse) attrs = existing.parse(attrs, options);
existing.set(attrs, options);
if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true;
}
models[i] = existing;
// If this is a new, valid model, push it to the `toAdd` list.
} else if (add) {
model = models[i] = this._prepareModel(attrs, options);
if (!model) continue;
toAdd.push(model);
this._addReference(model, options);
}
// Do not add multiple models with the same `id`.
model = existing || model;
if (!model) continue;
id = this.modelId(model.attributes);
if (order && (model.isNew() || !modelMap[id])) {
order.push(model);
// Check to see if this is actually a new model at this index.
orderChanged = orderChanged || !this.models[i] || model.cid !== this.models[i].cid;
}
modelMap[id] = true;
}
// Remove nonexistent models if appropriate.
if (remove) {
for (var i = 0; i < this.length; i++) {
if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model);
}
if (toRemove.length) this._removeModels(toRemove, options);
}
// See if sorting is needed, update `length` and splice in new models.
if (toAdd.length || orderChanged) {
if (sortable) sort = true;
this.length += toAdd.length;
if (at != null) {
for (var i = 0; i < toAdd.length; i++) {
this.models.splice(at + i, 0, toAdd[i]);
}
} else {
if (order) this.models.length = 0;
var orderedModels = order || toAdd;
for (var i = 0; i < orderedModels.length; i++) {
this.models.push(orderedModels[i]);
}
}
}
// Silently sort the collection if appropriate.
if (sort) this.sort({ silent: true });
// Unless silenced, it's time to fire all appropriate add/sort events.
if (!options.silent) {
var addOpts = at != null ? _.clone(options) : options;
for (var i = 0; i < toAdd.length; i++) {
if (at != null) addOpts.index = at + i;
(model = toAdd[i]).trigger('add', model, this, addOpts);
}
if (sort || orderChanged) this.trigger('sort', this, options);
if (toAdd.length || toRemove.length) this.trigger('update', this, options);
}
// Return the added (or merged) model (or models).
return singular ? models[0] : models;
},
// When you have more items than you want to add or remove individually,
// you can reset the entire set with a new list of models, without firing
// any granular `add` or `remove` events. Fires `reset` when finished.
// Useful for bulk operations and optimizations.
reset: function (models, options) {
options = options ? _.clone(options) : {};
for (var i = 0; i < this.models.length; i++) {
this._removeReference(this.models[i], options);
}
options.previousModels = this.models;
this._reset();
models = this.add(models, _.extend({ silent: true }, options));
if (!options.silent) this.trigger('reset', this, options);
return models;
},
// Add a model to the end of the collection.
push: function (model, options) {
return this.add(model, _.extend({ at: this.length }, options));
},
// Remove a model from the end of the collection.
pop: function (options) {
var model = this.at(this.length - 1);
this.remove(model, options);
return model;
},
// Add a model to the beginning of the collection.
unshift: function (model, options) {
return this.add(model, _.extend({ at: 0 }, options));
},
// Remove a model from the beginning of the collection.
shift: function (options) {
var model = this.at(0);
this.remove(model, options);
return model;
},
// Slice out a sub-array of models from the collection.
slice: function () {
return slice.apply(this.models, arguments);
},
// Get a model from the set by id.
get: function (obj) {
if (obj == null) return void 0;
var id = this.modelId(this._isModel(obj) ? obj.attributes : obj);
return this._byId[obj] || this._byId[id] || this._byId[obj.cid];
},
// Get the model at the given index.
at: function (index) {
if (index < 0) index += this.length;
return this.models[index];
},
// Return models with matching attributes. Useful for simple cases of
// `filter`.
where: function (attrs, first) {
var matches = _.matches(attrs);
return this[first ? 'find' : 'filter'](function (model) {
return matches(model.attributes);
});
},
// Return the first model with matching attributes. Useful for simple cases
// of `find`.
findWhere: function (attrs) {
return this.where(attrs, true);
},
// Force the collection to re-sort itself. You don't need to call this under
// normal circumstances, as the set will maintain sort order as each item
// is added.
sort: function (options) {
if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
options || (options = {});
// Run sort based on type of `comparator`.
if (_.isString(this.comparator) || this.comparator.length === 1) {
this.models = this.sortBy(this.comparator, this);
} else {
this.models.sort(_.bind(this.comparator, this));
}
if (!options.silent) this.trigger('sort', this, options);
return this;
},
// Pluck an attribute from each model in the collection.
pluck: function (attr) {
return _.invoke(this.models, 'get', attr);
},
// Fetch the default set of models for this collection, resetting the
// collection when they arrive. If `reset: true` is passed, the response
// data will be passed through the `reset` method instead of `set`.
fetch: function (options) {
options = options ? _.clone(options) : {};
if (options.parse === void 0) options.parse = true;
var success = options.success;
var collection = this;
options.success = function (resp) {
var method = options.reset ? 'reset' : 'set';
collection[method](resp, options);
if (success) success.call(options.context, collection, resp, options);
collection.trigger('sync', collection, resp, options);
};
wrapError(this, options);
return this.sync('read', this, options);
},
// Create a new instance of a model in this collection. Add the model to the
// collection immediately, unless `wait: true` is passed, in which case we
// wait for the server to agree.
create: function (model, options) {
options = options ? _.clone(options) : {};
var wait = options.wait;
if (!(model = this._prepareModel(model, options))) return false;
if (!wait) this.add(model, options);
var collection = this;
var success = options.success;
options.success = function (model, resp, callbackOpts) {
if (wait) collection.add(model, callbackOpts);
if (success) success.call(callbackOpts.context, model, resp, callbackOpts);
};
model.save(null, options);
return model;
},
// **parse** converts a response into a list of models to be added to the
// collection. The default implementation is just to pass it through.
parse: function (resp, options) {
return resp;
},
// Create a new collection with an identical list of models as this one.
clone: function () {
return new this.constructor(this.models, {
model: this.model,
comparator: this.comparator
});
},
// Define how to uniquely identify models in the collection.
modelId: function (attrs) {
return attrs[this.model.prototype.idAttribute || 'id'];
},
// Private method to reset all internal state. Called when the collection
// is first initialized or reset.
_reset: function () {
this.length = 0;
this.models = [];
this._byId = {};
},
// Prepare a hash of attributes (or other model) to be added to this
// collection.
_prepareModel: function (attrs, options) {
if (this._isModel(attrs)) {
if (!attrs.collection) attrs.collection = this;
return attrs;
}
options = options ? _.clone(options) : {};
options.collection = this;
var model = new this.model(attrs, options);
if (!model.validationError) return model;
this.trigger('invalid', this, model.validationError, options);
return false;
},
// Internal method called by both remove and set. Does not trigger any
// additional events. Returns true if anything was actually removed.
_removeModels: function (models, options) {
var i, l, index, model, removed = false;
for (var i = 0, j = 0; i < models.length; i++) {
var model = models[i] = this.get(models[i]);
if (!model) continue;
var id = this.modelId(model.attributes);
if (id != null) delete this._byId[id];
delete this._byId[model.cid];
var index = this.indexOf(model);
this.models.splice(index, 1);
this.length--;
if (!options.silent) {
options.index = index;
model.trigger('remove', model, this, options);
}
models[j++] = model;
this._removeReference(model, options);
removed = true;
}
// We only need to slice if models array should be smaller, which is
// caused by some models not actually getting removed.
if (models.length !== j) models = models.slice(0, j);
return removed;
},
// Method for checking whether an object should be considered a model for
// the purposes of adding to the collection.
_isModel: function (model) {
return model instanceof Model;
},
// Internal method to create a model's ties to a collection.
_addReference: function (model, options) {
this._byId[model.cid] = model;
var id = this.modelId(model.attributes);
if (id != null) this._byId[id] = model;
model.on('all', this._onModelEvent, this);
},
// Internal method to sever a model's ties to a collection.
_removeReference: function (model, options) {
if (this === model.collection) delete model.collection;
model.off('all', this._onModelEvent, this);
},
// Internal method called every time a model in the set fires an event.
// Sets need to update their indexes when models change ids. All other
// events simply proxy through. "add" and "remove" events that originate
// in other collections are ignored.
_onModelEvent: function (event, model, collection, options) {
if ((event === 'add' || event === 'remove') && collection !== this) return;
if (event === 'destroy') this.remove(model, options);
if (event === 'change') {
var prevId = this.modelId(model.previousAttributes());
var id = this.modelId(model.attributes);
if (prevId !== id) {
if (prevId != null) delete this._byId[prevId];
if (id != null) this._byId[id] = model;
}
}
this.trigger.apply(this, arguments);
}
});
// Underscore methods that we want to implement on the Collection.
// 90% of the core usefulness of Backbone Collections is actually implemented
// right here:
var collectionMethods = {
forEach: 3, each: 3, map: 3, collect: 3, reduce: 4,
foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3,
select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 2,
contains: 2, invoke: 2, max: 3, min: 3, toArray: 1, size: 1, first: 3,
head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3,
without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3,
isEmpty: 1, chain: 1, sample: 3, partition: 3
};
// Mix in each Underscore method as a proxy to `Collection#models`.
addUnderscoreMethods(Collection, collectionMethods, 'models');
// Underscore methods that take a property name as an argument.
var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy'];
// Use attributes instead of properties.
_.each(attributeMethods, function (method) {
if (!_[method]) return;
Collection.prototype[method] = function (value, context) {
var iterator = _.isFunction(value) ? value : function (model) {
return model.get(value);
};
return _[method](this.models, iterator, context);
};
});
// Backbone.View
// -------------
// Backbone Views are almost more convention than they are actual code. A View
// is simply a JavaScript object that represents a logical chunk of UI in the
// DOM. This might be a single item, an entire list, a sidebar or panel, or
// even the surrounding frame which wraps your whole app. Defining a chunk of
// UI as a **View** allows you to define your DOM events declaratively, without
// having to worry about render order ... and makes it easy for the view to
// react to specific changes in the state of your models.
// Creating a Backbone.View creates its initial element outside of the DOM,
// if an existing element is not provided...
var View = Backbone.View = function (options) {
this.cid = _.uniqueId('view');
options || (options = {});
_.extend(this, _.pick(options, viewOptions));
this._ensureElement();
this.initialize.apply(this, arguments);
};
// Cached regex to split keys for `delegate`.
var delegateEventSplitter = /^(\S+)\s*(.*)$/;
// List of view options to be merged as properties.
var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
// Set up all inheritable **Backbone.View** properties and methods.
_.extend(View.prototype, Events, {
// The default `tagName` of a View's element is `"div"`.
tagName: 'div',
// jQuery delegate for element lookup, scoped to DOM elements within the
// current view. This should be preferred to global lookups where possible.
$: function (selector) {
return this.$el.find(selector);
},
// Initialize is an empty function by default. Override it with your own
// initialization logic.
initialize: function () { },
// **render** is the core function that your view should override, in order
// to populate its element (`this.el`), with the appropriate HTML. The
// convention is for **render** to always return `this`.
render: function () {
return this;
},
// Remove this view by taking the element out of the DOM, and removing any
// applicable Backbone.Events listeners.
remove: function () {
this._removeElement();
this.stopListening();
return this;
},
// Remove this view's element from the document and all event listeners
// attached to it. Exposed for subclasses using an alternative DOM
// manipulation API.
_removeElement: function () {
this.$el.remove();
},
// Change the view's element (`this.el` property) and re-delegate the
// view's events on the new element.
setElement: function (element) {
this.undelegateEvents();
this._setElement(element);
this.delegateEvents();
return this;
},
// Creates the `this.el` and `this.$el` references for this view using the
// given `el`. `el` can be a CSS selector or an HTML string, a jQuery
// context or an element. Subclasses can override this to utilize an
// alternative DOM manipulation API and are only required to set the
// `this.el` property.
_setElement: function (el) {
this.$el = el instanceof Backbone.$ ? el : Backbone.$(el);
this.el = this.$el[0];
},
// Set callbacks, where `this.events` is a hash of
//
// *{"event selector": "callback"}*
//
// {
// 'mousedown .title': 'edit',
// 'click .button': 'save',
// 'click .open': function(e) { ... }
// }
//
// pairs. Callbacks will be bound to the view, with `this` set properly.
// Uses event delegation for efficiency.
// Omitting the selector binds the event to `this.el`.
delegateEvents: function (events) {
if (!(events || (events = _.result(this, 'events')))) return this;
this.undelegateEvents();
for (var key in events) {
var method = events[key];
if (!_.isFunction(method)) method = this[events[key]];
if (!method) continue;
var match = key.match(delegateEventSplitter);
this.delegate(match[1], match[2], _.bind(method, this));
}
return this;
},
// Add a single event listener to the view's element (or a child element
// using `selector`). This only works for delegate-able events: not `focus`,
// `blur`, and not `change`, `submit`, and `reset` in Internet Explorer.
delegate: function (eventName, selector, listener) {
this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener);
},
// Clears all callbacks previously bound to the view by `delegateEvents`.
// You usually don't need to use this, but may wish to if you have multiple
// Backbone views attached to the same DOM element.
undelegateEvents: function () {
if (this.$el) this.$el.off('.delegateEvents' + this.cid);
return this;
},
// A finer-grained `undelegateEvents` for removing a single delegated event.
// `selector` and `listener` are both optional.
undelegate: function (eventName, selector, listener) {
this.$el.off(eventName + '.delegateEvents' + this.cid, selector, listener);
},
// Produces a DOM element to be assigned to your view. Exposed for
// subclasses using an alternative DOM manipulation API.
_createElement: function (tagName) {
return document.createElement(tagName);
},
// Ensure that the View has a DOM element to render into.
// If `this.el` is a string, pass it through `$()`, take the first
// matching element, and re-assign it to `el`. Otherwise, create
// an element from the `id`, `className` and `tagName` properties.
_ensureElement: function () {
if (!this.el) {
var attrs = _.extend({}, _.result(this, 'attributes'));
if (this.id) attrs.id = _.result(this, 'id');
if (this.className) attrs['class'] = _.result(this, 'className');
this.setElement(this._createElement(_.result(this, 'tagName')));
this._setAttributes(attrs);
} else {
this.setElement(_.result(this, 'el'));
}
},
// Set attributes from a hash on this view's element. Exposed for
// subclasses using an alternative DOM manipulation API.
_setAttributes: function (attributes) {
this.$el.attr(attributes);
}
});
// Backbone.sync
// -------------
// Override this function to change the manner in which Backbone persists
// models to the server. You will be passed the type of request, and the
// model in question. By default, makes a RESTful Ajax request
// to the model's `url()`. Some possible customizations could be:
//
// * Use `setTimeout` to batch rapid-fire updates into a single request.
// * Send up the models as XML instead of JSON.
// * Persist models via WebSockets instead of Ajax.
//
// Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests
// as `POST`, with a `_method` parameter containing the true HTTP method,
// as well as all requests with the body as `application/x-www-form-urlencoded`
// instead of `application/json` with the model in a param named `model`.
// Useful when interfacing with server-side languages like **PHP** that make
// it difficult to read the body of `PUT` requests.
Backbone.sync = function (method, model, options) {
var type = methodMap[method];
// Default options, unless specified.
_.defaults(options || (options = {}), {
emulateHTTP: Backbone.emulateHTTP,
emulateJSON: Backbone.emulateJSON
});
// Default JSON-request options.
var params = { type: type, dataType: 'json' };
// Ensure that we have a URL.
if (!options.url) {
params.url = _.result(model, 'url') || urlError();
}
// Ensure that we have the appropriate request data.
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
params.contentType = 'application/json';
params.data = JSON.stringify(options.attrs || model.toJSON(options));
}
// For older servers, emulate JSON by encoding the request into an HTML-form.
if (options.emulateJSON) {
params.contentType = 'application/x-www-form-urlencoded';
params.data = params.data ? { model: params.data } : {};
}
// For older servers, emulate HTTP by mimicking the HTTP method with `_method`
// And an `X-HTTP-Method-Override` header.
if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
params.type = 'POST';
if (options.emulateJSON) params.data._method = type;
var beforeSend = options.beforeSend;
options.beforeSend = function (xhr) {
xhr.setRequestHeader('X-HTTP-Method-Override', type);
if (beforeSend) return beforeSend.apply(this, arguments);
};
}
// Don't process data on a non-GET request.
if (params.type !== 'GET' && !options.emulateJSON) {
params.processData = false;
}
// Pass along `textStatus` and `errorThrown` from jQuery.
var error = options.error;
options.error = function (xhr, textStatus, errorThrown) {
options.textStatus = textStatus;
options.errorThrown = errorThrown;
if (error) error.call(options.context, xhr, textStatus, errorThrown);
};
// Make the request, allowing the user to override any Ajax options.
var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
model.trigger('request', model, xhr, options);
return xhr;
};
// Map from CRUD to HTTP for our default `Backbone.sync` implementation.
var methodMap = {
'create': 'POST',
'update': 'PUT',
'patch': 'PATCH',
'delete': 'DELETE',
'read': 'GET'
};
// Set the default implementation of `Backbone.ajax` to proxy through to `$`.
// Override this if you'd like to use a different library.
Backbone.ajax = function () {
return Backbone.$.ajax.apply(Backbone.$, arguments);
};
// Backbone.Router
// ---------------
// Routers map faux-URLs to actions, and fire events when routes are
// matched. Creating a new one sets its `routes` hash, if not set statically.
var Router = Backbone.Router = function (options) {
options || (options = {});
if (options.routes) this.routes = options.routes;
this._bindRoutes();
this.initialize.apply(this, arguments);
};
// Cached regular expressions for matching named param parts and splatted
// parts of route strings.
var optionalParam = /\((.*?)\)/g;
var namedParam = /(\(\?)?:\w+/g;
var splatParam = /\*\w+/g;
var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
// Set up all inheritable **Backbone.Router** properties and methods.
_.extend(Router.prototype, Events, {
// Initialize is an empty function by default. Override it with your own
// initialization logic.
initialize: function () { },
// Manually bind a single named route to a callback. For example:
//
// this.route('search/:query/p:num', 'search', function(query, num) {
// ...
// });
//
route: function (route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (_.isFunction(name)) {
callback = name;
name = '';
}
if (!callback) callback = this[name];
var router = this;
Backbone.history.route(route, function (fragment) {
var args = router._extractParameters(route, fragment);
if (router.execute(callback, args, name) !== false) {
router.trigger.apply(router, ['route:' + name].concat(args));
router.trigger('route', name, args);
Backbone.history.trigger('route', router, name, args);
}
});
return this;
},
// Execute a route handler with the provided parameters. This is an
// excellent place to do pre-route setup or post-route cleanup.
execute: function (callback, args, name) {
if (callback) callback.apply(this, args);
},
// Simple proxy to `Backbone.history` to save a fragment into the history.
navigate: function (fragment, options) {
Backbone.history.navigate(fragment, options);
return this;
},
// Bind all defined routes to `Backbone.history`. We have to reverse the
// order of the routes here to support behavior where the most general
// routes can be defined at the bottom of the route map.
_bindRoutes: function () {
if (!this.routes) return;
this.routes = _.result(this, 'routes');
var route, routes = _.keys(this.routes);
while ((route = routes.pop()) != null) {
this.route(route, this.routes[route]);
}
},
// Convert a route string into a regular expression, suitable for matching
// against the current location hash.
_routeToRegExp: function (route) {
route = route.replace(escapeRegExp, '\\$&')
.replace(optionalParam, '(?:$1)?')
.replace(namedParam, function (match, optional) {
return optional ? match : '([^/?]+)';
})
.replace(splatParam, '([^?]*?)');
return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
},
// Given a route, and a URL fragment that it matches, return the array of
// extracted decoded parameters. Empty or unmatched parameters will be
// treated as `null` to normalize cross-browser behavior.
_extractParameters: function (route, fragment) {
var params = route.exec(fragment).slice(1);
return _.map(params, function (param, i) {
// Don't decode the search params.
if (i === params.length - 1) return param || null;
return param ? decodeURIComponent(param) : null;
});
}
});
// Backbone.History
// ----------------
// Handles cross-browser history management, based on either
// [pushState](http://diveintohtml5.info/history.html) and real URLs, or
// [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange)
// and URL fragments. If the browser supports neither (old IE, natch),
// falls back to polling.
var History = Backbone.History = function () {
this.handlers = [];
_.bindAll(this, 'checkUrl');
// Ensure that `History` can be used outside of the browser.
if (typeof window !== 'undefined') {
this.location = window.location;
this.history = window.history;
}
};
// Cached regex for stripping a leading hash/slash and trailing space.
var routeStripper = /^[#\/]|\s+$/g;
// Cached regex for stripping leading and trailing slashes.
var rootStripper = /^\/+|\/+$/g;
// Cached regex for stripping urls of hash.
var pathStripper = /#.*$/;
// Has the history handling already been started?
History.started = false;
// Set up all inheritable **Backbone.History** properties and methods.
_.extend(History.prototype, Events, {
// The default interval to poll for hash changes, if necessary, is
// twenty times a second.
interval: 50,
// Are we at the app root?
atRoot: function () {
var path = this.location.pathname.replace(/[^\/]$/, '$&/');
return path === this.root && !this.getSearch();
},
// Does the pathname match the root?
matchRoot: function () {
var path = this.decodeFragment(this.location.pathname);
var root = path.slice(0, this.root.length - 1) + '/';
return root === this.root;
},
// Unicode characters in `location.pathname` are percent encoded so they're
// decoded for comparison. `%25` should not be decoded since it may be part
// of an encoded parameter.
decodeFragment: function (fragment) {
return decodeURI(fragment.replace(/%25/g, '%2525'));
},
// In IE6, the hash fragment and search params are incorrect if the
// fragment contains `?`.
getSearch: function () {
var match = this.location.href.replace(/#.*/, '').match(/\?.+/);
return match ? match[0] : '';
},
// Gets the true hash value. Cannot use location.hash directly due to bug
// in Firefox where location.hash will always be decoded.
getHash: function (window) {
var match = (window || this).location.href.match(/#(.*)$/);
return match ? match[1] : '';
},
// Get the pathname and search params, without the root.
getPath: function () {
var path = this.decodeFragment(
this.location.pathname + this.getSearch()
).slice(this.root.length - 1);
return path.charAt(0) === '/' ? path.slice(1) : path;
},
// Get the cross-browser normalized URL fragment from the path or hash.
getFragment: function (fragment) {
if (fragment == null) {
if (this._usePushState || !this._wantsHashChange) {
fragment = this.getPath();
} else {
fragment = this.getHash();
}
}
return fragment.replace(routeStripper, '');
},
// Start the hash change handling, returning `true` if the current URL matches
// an existing route, and `false` otherwise.
start: function (options) {
if (History.started) throw new Error('Backbone.history has already been started');
History.started = true;
// Figure out the initial configuration. Do we need an iframe?
// Is pushState desired ... is it available?
this.options = _.extend({ root: '/' }, this.options, options);
this.root = this.options.root;
this._wantsHashChange = this.options.hashChange !== false;
this._hasHashChange = 'onhashchange' in window;
this._useHashChange = this._wantsHashChange && this._hasHashChange;
this._wantsPushState = !!this.options.pushState;
this._hasPushState = !!(this.history && this.history.pushState);
this._usePushState = this._wantsPushState && this._hasPushState;
this.fragment = this.getFragment();
// Normalize root to always include a leading and trailing slash.
this.root = ('/' + this.root + '/').replace(rootStripper, '/');
// Transition from hashChange to pushState or vice versa if both are
// requested.
if (this._wantsHashChange && this._wantsPushState) {
// If we've started off with a route from a `pushState`-enabled
// browser, but we're currently in a browser that doesn't support it...
if (!this._hasPushState && !this.atRoot()) {
var root = this.root.slice(0, -1) || '/';
this.location.replace(root + '#' + this.getPath());
// Return immediately as browser will do redirect to new url
return true;
// Or if we've started out with a hash-based route, but we're currently
// in a browser where it could be `pushState`-based instead...
} else if (this._hasPushState && this.atRoot()) {
this.navigate(this.getHash(), { replace: true });
}
}
// Proxy an iframe to handle location events if the browser doesn't
// support the `hashchange` event, HTML5 history, or the user wants
// `hashChange` but not `pushState`.
if (!this._hasHashChange && this._wantsHashChange && !this._usePushState) {
var iframe = document.createElement('iframe');
iframe.src = 'javascript:0';
iframe.style.display = 'none';
iframe.tabIndex = -1;
var body = document.body;
// Using `appendChild` will throw on IE < 9 if the document is not ready.
this.iframe = body.insertBefore(iframe, body.firstChild).contentWindow;
this.iframe.document.open().close();
this.iframe.location.hash = '#' + this.fragment;
}
// Add a cross-platform `addEventListener` shim for older browsers.
var addEventListener = window.addEventListener || function (eventName, listener) {
return attachEvent('on' + eventName, listener);
};
// Depending on whether we're using pushState or hashes, and whether
// 'onhashchange' is supported, determine how we check the URL state.
if (this._usePushState) {
addEventListener('popstate', this.checkUrl, false);
} else if (this._useHashChange && !this.iframe) {
addEventListener('hashchange', this.checkUrl, false);
} else if (this._wantsHashChange) {
this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
}
if (!this.options.silent) return this.loadUrl();
},
// Disable Backbone.history, perhaps temporarily. Not useful in a real app,
// but possibly useful for unit testing Routers.
stop: function () {
// Add a cross-platform `removeEventListener` shim for older browsers.
var removeEventListener = window.removeEventListener || function (eventName, listener) {
return detachEvent('on' + eventName, listener);
};
// Remove window listeners.
if (this._usePushState) {
removeEventListener('popstate', this.checkUrl, false);
} else if (this._useHashChange && !this.iframe) {
removeEventListener('hashchange', this.checkUrl, false);
}
// Clean up the iframe if necessary.
if (this.iframe) {
document.body.removeChild(this.iframe.frameElement);
this.iframe = null;
}
// Some environments will throw when clearing an undefined interval.
if (this._checkUrlInterval) clearInterval(this._checkUrlInterval);
History.started = false;
},
// Add a route to be tested when the fragment changes. Routes added later
// may override previous routes.
route: function (route, callback) {
this.handlers.unshift({ route: route, callback: callback });
},
// Checks the current URL to see if it has changed, and if it has,
// calls `loadUrl`, normalizing across the hidden iframe.
checkUrl: function (e) {
var current = this.getFragment();
// If the user pressed the back button, the iframe's hash will have
// changed and we should use that for comparison.
if (current === this.fragment && this.iframe) {
current = this.getHash(this.iframe);
}
if (current === this.fragment) return false;
if (this.iframe) this.navigate(current);
this.loadUrl();
},
// Attempt to load the current URL fragment. If a route succeeds with a
// match, returns `true`. If no defined routes matches the fragment,
// returns `false`.
loadUrl: function (fragment) {
// If the root doesn't match, no routes can match either.
if (!this.matchRoot()) return false;
fragment = this.fragment = this.getFragment(fragment);
return _.any(this.handlers, function (handler) {
if (handler.route.test(fragment)) {
handler.callback(fragment);
return true;
}
});
},
// Save a fragment into the hash history, or replace the URL state if the
// 'replace' option is passed. You are responsible for properly URL-encoding
// the fragment in advance.
//
// The options object can contain `trigger: true` if you wish to have the
// route callback be fired (not usually desirable), or `replace: true`, if
// you wish to modify the current URL without adding an entry to the history.
navigate: function (fragment, options) {
if (!History.started) return false;
if (!options || options === true) options = { trigger: !!options };
// Normalize the fragment.
fragment = this.getFragment(fragment || '');
// Don't include a trailing slash on the root.
var root = this.root;
if (fragment === '' || fragment.charAt(0) === '?') {
root = root.slice(0, -1) || '/';
}
var url = root + fragment;
// Strip the hash and decode for matching.
fragment = this.decodeFragment(fragment.replace(pathStripper, ''));
if (this.fragment === fragment) return;
this.fragment = fragment;
// If pushState is available, we use it to set the fragment as a real URL.
if (this._usePushState) {
this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url);
// If hash changes haven't been explicitly disabled, update the hash
// fragment to store history.
} else if (this._wantsHashChange) {
this._updateHash(this.location, fragment, options.replace);
if (this.iframe && (fragment !== this.getHash(this.iframe))) {
// Opening and closing the iframe tricks IE7 and earlier to push a
// history entry on hash-tag change. When replace is true, we don't
// want this.
if (!options.replace) this.iframe.document.open().close();
this._updateHash(this.iframe.location, fragment, options.replace);
}
// If you've told us that you explicitly don't want fallback hashchange-
// based history, then `navigate` becomes a page refresh.
} else {
return this.location.assign(url);
}
if (options.trigger) return this.loadUrl(fragment);
},
// Update the hash location, either replacing the current entry, or adding
// a new one to the browser history.
_updateHash: function (location, fragment, replace) {
if (replace) {
var href = location.href.replace(/(javascript:|#).*$/, '');
location.replace(href + '#' + fragment);
} else {
// Some browsers require that `hash` contains a leading #.
location.hash = '#' + fragment;
}
}
});
// Create the default Backbone.history.
Backbone.history = new History;
// Helpers
// -------
// Helper function to correctly set up the prototype chain for subclasses.
// Similar to `goog.inherits`, but uses a hash of prototype properties and
// class properties to be extended.
var extend = function (protoProps, staticProps) {
var parent = this;
var child;
// The constructor function for the new subclass is either defined by you
// (the "constructor" property in your `extend` definition), or defaulted
// by us to simply call the parent constructor.
if (protoProps && _.has(protoProps, 'constructor')) {
child = protoProps.constructor;
} else {
child = function () { return parent.apply(this, arguments); };
}
// Add static properties to the constructor function, if supplied.
_.extend(child, parent, staticProps);
// Set the prototype chain to inherit from `parent`, without calling
// `parent` constructor function.
var Surrogate = function () { this.constructor = child; };
Surrogate.prototype = parent.prototype;
child.prototype = new Surrogate;
// Add prototype properties (instance properties) to the subclass,
// if supplied.
if (protoProps) _.extend(child.prototype, protoProps);
// Set a convenience property in case the parent's prototype is needed
// later.
child.__super__ = parent.prototype;
return child;
};
// Set up inheritance for the model, collection, router, view and history.
Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;
// Throw an error when a URL is needed, and none is supplied.
var urlError = function () {
throw new Error('A "url" property or function must be specified');
};
// Wrap an optional error callback with a fallback error event.
var wrapError = function (model, options) {
var error = options.error;
options.error = function (resp) {
if (error) error.call(options.context, model, resp, options);
model.trigger('error', model, resp, options);
};
};
return Backbone;
}));
/*!
* jQuery Form Plugin
* version: 3.46.0-2013.11.21
* Requires jQuery v1.5 or later
* Copyright (c) 2013 M. Alsup
* Examples and documentation at: http://malsup.com/jquery/form/
* Project repository: https://github.com/malsup/form
* Dual licensed under the MIT and GPL licenses.
* https://github.com/malsup/form#copyright-and-license
*/
/*global ActiveXObject */
// AMD support
(function (factory) {
if (typeof define === 'function' && define.amd) {
// using AMD; register as anon module
define(['jquery'], factory);
} else {
// no AMD; invoke directly
factory((typeof (jQuery) != 'undefined') ? jQuery : window.Zepto);
}
}
(function ($) {
"use strict";
/*
Usage Note:
-----------
Do not use both ajaxSubmit and ajaxForm on the same form. These
functions are mutually exclusive. Use ajaxSubmit if you want
to bind your own submit handler to the form. For example,
$(document).ready(function() {
$('#myForm').on('submit', function(e) {
e.preventDefault(); // <-- important
$(this).ajaxSubmit({
target: '#output'
});
});
});
Use ajaxForm when you want the plugin to manage all the event binding
for you. For example,
$(document).ready(function() {
$('#myForm').ajaxForm({
target: '#output'
});
});
You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
form does not have to exist when you invoke ajaxForm:
$('#myForm').ajaxForm({
delegation: true,
target: '#output'
});
When using ajaxForm, the ajaxSubmit function will be invoked for you
at the appropriate time.
*/
/**
* Feature detection
*/
var feature = {};
feature.fileapi = $(" ").get(0).files !== undefined;
feature.formdata = window.FormData !== undefined;
var hasProp = !!$.fn.prop;
// attr2 uses prop when it can but checks the return type for
// an expected string. this accounts for the case where a form
// contains inputs with names like "action" or "method"; in those
// cases "prop" returns the element
$.fn.attr2 = function () {
if (!hasProp)
return this.attr.apply(this, arguments);
var val = this.prop.apply(this, arguments);
if ((val && val.jquery) || typeof val === 'string')
return val;
return this.attr.apply(this, arguments);
};
/**
* ajaxSubmit() provides a mechanism for immediately submitting
* an HTML form using AJAX.
*/
$.fn.ajaxSubmit = function (options) {
/*jshint scripturl:true */
// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
if (!this.length) {
log('ajaxSubmit: skipping submit process - no element selected');
return this;
}
var method, action, url, $form = this;
if (typeof options == 'function') {
options = { success: options };
}
else if (options === undefined) {
options = {};
}
method = options.type || this.attr2('method');
action = options.url || this.attr2('action');
url = (typeof action === 'string') ? $.trim(action) : '';
url = url || window.location.href || '';
if (url) {
// clean url (don't include hash vaue)
url = (url.match(/^([^#]+)/) || [])[1];
}
options = $.extend(true, {
url: url,
success: $.ajaxSettings.success,
type: method || $.ajaxSettings.type,
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
}, options);
// hook for manipulating the form data before it is extracted;
// convenient for use with rich editors like tinyMCE or FCKEditor
var veto = {};
this.trigger('form-pre-serialize', [this, options, veto]);
if (veto.veto) {
log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
return this;
}
// provide opportunity to alter form data before it is serialized
if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
log('ajaxSubmit: submit aborted via beforeSerialize callback');
return this;
}
var traditional = options.traditional;
if (traditional === undefined) {
traditional = $.ajaxSettings.traditional;
}
var elements = [];
var qx, a = this.formToArray(options.semantic, elements);
if (options.data) {
options.extraData = options.data;
qx = $.param(options.data, traditional);
}
// give pre-submit callback an opportunity to abort the submit
if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
log('ajaxSubmit: submit aborted via beforeSubmit callback');
return this;
}
// fire vetoable 'validate' event
this.trigger('form-submit-validate', [a, this, options, veto]);
if (veto.veto) {
log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
return this;
}
var q = $.param(a, traditional);
if (qx) {
q = (q ? (q + '&' + qx) : qx);
}
if (options.type.toUpperCase() == 'GET') {
options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
options.data = null; // data is null for 'get'
}
else {
options.data = q; // data is the query string for 'post'
}
var callbacks = [];
if (options.resetForm) {
callbacks.push(function () { $form.resetForm(); });
}
if (options.clearForm) {
callbacks.push(function () { $form.clearForm(options.includeHidden); });
}
// perform a load on the target only if dataType is not provided
if (!options.dataType && options.target) {
var oldSuccess = options.success || function () { };
callbacks.push(function (data) {
var fn = options.replaceTarget ? 'replaceWith' : 'html';
$(options.target)[fn](data).each(oldSuccess, arguments);
});
}
else if (options.success) {
callbacks.push(options.success);
}
options.success = function (data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
var context = options.context || this; // jQuery 1.4+ supports scope context
for (var i = 0, max = callbacks.length; i < max; i++) {
callbacks[i].apply(context, [data, status, xhr || $form, $form]);
}
};
if (options.error) {
var oldError = options.error;
options.error = function (xhr, status, error) {
var context = options.context || this;
oldError.apply(context, [xhr, status, error, $form]);
};
}
if (options.complete) {
var oldComplete = options.complete;
options.complete = function (xhr, status) {
var context = options.context || this;
oldComplete.apply(context, [xhr, status, $form]);
};
}
// are there files to upload?
// [value] (issue #113), also see comment:
// https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
var fileInputs = $('input[type=file]:enabled', this).filter(function () { return $(this).val() !== ''; });
var hasFileInputs = fileInputs.length > 0;
var mp = 'multipart/form-data';
var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
var fileAPI = feature.fileapi && feature.formdata;
log("fileAPI :" + fileAPI);
var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
var jqxhr;
// options.iframe allows user to force iframe mode
// 06-NOV-09: now defaulting to iframe mode if file input is detected
if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
// hack to fix Safari hang (thanks to Tim Molendijk for this)
// see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
if (options.closeKeepAlive) {
$.get(options.closeKeepAlive, function () {
jqxhr = fileUploadIframe(a);
});
}
else {
jqxhr = fileUploadIframe(a);
}
}
else if ((hasFileInputs || multipart) && fileAPI) {
jqxhr = fileUploadXhr(a);
}
else {
jqxhr = $.ajax(options);
}
$form.removeData('jqxhr').data('jqxhr', jqxhr);
// clear element array
for (var k = 0; k < elements.length; k++)
elements[k] = null;
// fire 'notify' event
this.trigger('form-submit-notify', [this, options]);
return this;
// utility fn for deep serialization
function deepSerialize(extraData) {
var serialized = $.param(extraData, options.traditional).split('&');
var len = serialized.length;
var result = [];
var i, part;
for (i = 0; i < len; i++) {
// #252; undo param space replacement
serialized[i] = serialized[i].replace(/\+/g, ' ');
part = serialized[i].split('=');
// #278; use array instead of object storage, favoring array serializations
result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
}
return result;
}
// XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
function fileUploadXhr(a) {
var formdata = new FormData();
for (var i = 0; i < a.length; i++) {
formdata.append(a[i].name, a[i].value);
}
if (options.extraData) {
var serializedData = deepSerialize(options.extraData);
for (i = 0; i < serializedData.length; i++)
if (serializedData[i])
formdata.append(serializedData[i][0], serializedData[i][1]);
}
options.data = null;
var s = $.extend(true, {}, $.ajaxSettings, options, {
contentType: false,
processData: false,
cache: false,
type: method || 'POST'
});
if (options.uploadProgress) {
// workaround because jqXHR does not expose upload property
s.xhr = function () {
var xhr = $.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', function (event) {
var percent = 0;
var position = event.loaded || event.position; /*event.position is deprecated*/
var total = event.total;
if (event.lengthComputable) {
percent = Math.ceil(position / total * 100);
}
options.uploadProgress(event, position, total, percent);
}, false);
}
return xhr;
};
}
s.data = null;
var beforeSend = s.beforeSend;
s.beforeSend = function (xhr, o) {
//Send FormData() provided by user
if (options.formData)
o.data = options.formData;
else
o.data = formdata;
if (beforeSend)
beforeSend.call(this, xhr, o);
};
return $.ajax(s);
}
// private function for handling file uploads (hat tip to YAHOO!)
function fileUploadIframe(a) {
var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
var deferred = $.Deferred();
// #341
deferred.abort = function (status) {
xhr.abort(status);
};
if (a) {
// ensure that every serialized input is still enabled
for (i = 0; i < elements.length; i++) {
el = $(elements[i]);
if (hasProp)
el.prop('disabled', false);
else
el.removeAttr('disabled');
}
}
s = $.extend(true, {}, $.ajaxSettings, options);
s.context = s.context || s;
id = 'jqFormIO' + (new Date().getTime());
if (s.iframeTarget) {
$io = $(s.iframeTarget);
n = $io.attr2('name');
if (!n)
$io.attr2('name', id);
else
id = n;
}
else {
$io = $('');
$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
}
io = $io[0];
xhr = { // mock object
aborted: 0,
responseText: null,
responseXML: null,
status: 0,
statusText: 'n/a',
getAllResponseHeaders: function () { },
getResponseHeader: function () { },
setRequestHeader: function () { },
abort: function (status) {
var e = (status === 'timeout' ? 'timeout' : 'aborted');
log('aborting upload... ' + e);
this.aborted = 1;
try { // #214, #257
if (io.contentWindow.document.execCommand) {
io.contentWindow.document.execCommand('Stop');
}
}
catch (ignore) { }
$io.attr('src', s.iframeSrc); // abort op in progress
xhr.error = e;
if (s.error)
s.error.call(s.context, xhr, e, status);
if (g)
$.event.trigger("ajaxError", [xhr, s, e]);
if (s.complete)
s.complete.call(s.context, xhr, e);
}
};
g = s.global;
// trigger ajax global events so that activity/block indicators work like normal
if (g && 0 === $.active++) {
$.event.trigger("ajaxStart");
}
if (g) {
$.event.trigger("ajaxSend", [xhr, s]);
}
if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
if (s.global) {
$.active--;
}
deferred.reject();
return deferred;
}
if (xhr.aborted) {
deferred.reject();
return deferred;
}
// add submitting element to data if we know it
sub = form.clk;
if (sub) {
n = sub.name;
if (n && !sub.disabled) {
s.extraData = s.extraData || {};
s.extraData[n] = sub.value;
if (sub.type == "image") {
s.extraData[n + '.x'] = form.clk_x;
s.extraData[n + '.y'] = form.clk_y;
}
}
}
var CLIENT_TIMEOUT_ABORT = 1;
var SERVER_ABORT = 2;
function getDoc(frame) {
/* it looks like contentWindow or contentDocument do not
* carry the protocol property in ie8, when running under ssl
* frame.document is the only valid response document, since
* the protocol is know but not on the other two objects. strange?
* "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
*/
var doc = null;
// IE8 cascading access check
try {
if (frame.contentWindow) {
doc = frame.contentWindow.document;
}
} catch (err) {
// IE8 access denied under ssl & missing protocol
log('cannot get iframe.contentWindow document: ' + err);
}
if (doc) { // successful getting content
return doc;
}
try { // simply checking may throw in ie8 under ssl or mismatched protocol
doc = frame.contentDocument ? frame.contentDocument : frame.document;
} catch (err) {
// last attempt
log('cannot get iframe.contentDocument: ' + err);
doc = frame.document;
}
return doc;
}
// Rails CSRF hack (thanks to Yvan Barthelemy)
var csrf_token = $('meta[name=csrf-token]').attr('content');
var csrf_param = $('meta[name=csrf-param]').attr('content');
if (csrf_param && csrf_token) {
s.extraData = s.extraData || {};
s.extraData[csrf_param] = csrf_token;
}
// take a breath so that pending repaints get some cpu time before the upload starts
function doSubmit() {
// make sure form attrs are set
var t = $form.attr2('target'), a = $form.attr2('action');
// update form attrs in IE friendly way
form.setAttribute('target', id);
if (!method || /post/i.test(method)) {
form.setAttribute('method', 'POST');
}
if (a != s.url) {
form.setAttribute('action', s.url);
}
// ie borks in some cases when setting encoding
if (!s.skipEncodingOverride && (!method || /post/i.test(method))) {
$form.attr({
encoding: 'multipart/form-data',
enctype: 'multipart/form-data'
});
}
// support timout
if (s.timeout) {
timeoutHandle = setTimeout(function () { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
}
// look for server aborts
function checkState() {
try {
var state = getDoc(io).readyState;
log('state = ' + state);
if (state && state.toLowerCase() == 'uninitialized')
setTimeout(checkState, 50);
}
catch (e) {
log('Server abort: ', e, ' (', e.name, ')');
cb(SERVER_ABORT);
if (timeoutHandle)
clearTimeout(timeoutHandle);
timeoutHandle = undefined;
}
}
// add "extra" data to form if provided in options
var extraInputs = [];
try {
if (s.extraData) {
for (var n in s.extraData) {
if (s.extraData.hasOwnProperty(n)) {
// if using the $.param format that allows for multiple values with the same name
if ($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
extraInputs.push(
$(' ').val(s.extraData[n].value)
.appendTo(form)[0]);
} else {
extraInputs.push(
$(' ').val(s.extraData[n])
.appendTo(form)[0]);
}
}
}
}
if (!s.iframeTarget) {
// add iframe to doc and submit the form
$io.appendTo('body');
}
if (io.attachEvent)
io.attachEvent('onload', cb);
else
io.addEventListener('load', cb, false);
setTimeout(checkState, 15);
try {
form.submit();
} catch (err) {
// just in case form has element with name/id of 'submit'
var submitFn = document.createElement('form').submit;
submitFn.apply(form);
}
}
finally {
// reset attrs and remove "extra" input elements
form.setAttribute('action', a);
if (t) {
form.setAttribute('target', t);
} else {
$form.removeAttr('target');
}
$(extraInputs).remove();
}
}
if (s.forceSync) {
doSubmit();
}
else {
setTimeout(doSubmit, 10); // this lets dom updates render
}
var data, doc, domCheckCount = 50, callbackProcessed;
function cb(e) {
if (xhr.aborted || callbackProcessed) {
return;
}
doc = getDoc(io);
if (!doc) {
log('cannot access response document');
e = SERVER_ABORT;
}
if (e === CLIENT_TIMEOUT_ABORT && xhr) {
xhr.abort('timeout');
deferred.reject(xhr, 'timeout');
return;
}
else if (e == SERVER_ABORT && xhr) {
xhr.abort('server abort');
deferred.reject(xhr, 'error', 'server abort');
return;
}
if (!doc || doc.location.href == s.iframeSrc) {
// response not received yet
if (!timedOut)
return;
}
if (io.detachEvent)
io.detachEvent('onload', cb);
else
io.removeEventListener('load', cb, false);
var status = 'success', errMsg;
try {
if (timedOut) {
throw 'timeout';
}
var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
log('isXml=' + isXml);
if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
if (--domCheckCount) {
// in some browsers (Opera) the iframe DOM is not always traversable when
// the onload callback fires, so we loop a bit to accommodate
log('requeing onLoad callback, DOM not available');
setTimeout(cb, 250);
return;
}
// let this fall through because server response could be an empty document
//log('Could not access iframe DOM after mutiple tries.');
//throw 'DOMException: not available';
}
//log('response detected');
var docRoot = doc.body ? doc.body : doc.documentElement;
xhr.responseText = docRoot ? docRoot.innerHTML : null;
xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
if (isXml)
s.dataType = 'xml';
xhr.getResponseHeader = function (header) {
var headers = { 'content-type': s.dataType };
return headers[header.toLowerCase()];
};
// support for XHR 'status' & 'statusText' emulation :
if (docRoot) {
xhr.status = Number(docRoot.getAttribute('status')) || xhr.status;
xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
}
var dt = (s.dataType || '').toLowerCase();
var scr = /(json|script|text)/.test(dt);
if (scr || s.textarea) {
// see if user embedded response in textarea
var ta = doc.getElementsByTagName('textarea')[0];
if (ta) {
xhr.responseText = ta.value;
// support for XHR 'status' & 'statusText' emulation :
xhr.status = Number(ta.getAttribute('status')) || xhr.status;
xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
}
else if (scr) {
// account for browsers injecting pre around json response
var pre = doc.getElementsByTagName('pre')[0];
var b = doc.getElementsByTagName('body')[0];
if (pre) {
xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
}
else if (b) {
xhr.responseText = b.textContent ? b.textContent : b.innerText;
}
}
}
else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
xhr.responseXML = toXml(xhr.responseText);
}
try {
data = httpData(xhr, dt, s);
}
catch (err) {
status = 'parsererror';
xhr.error = errMsg = (err || status);
}
}
catch (err) {
log('error caught: ', err);
status = 'error';
xhr.error = errMsg = (err || status);
}
if (xhr.aborted) {
log('upload aborted');
status = null;
}
if (xhr.status) { // we've set xhr.status
status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
}
// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
if (status === 'success') {
if (s.success)
s.success.call(s.context, data, 'success', xhr);
deferred.resolve(xhr.responseText, 'success', xhr);
if (g)
$.event.trigger("ajaxSuccess", [xhr, s]);
}
else if (status) {
if (errMsg === undefined)
errMsg = xhr.statusText;
if (s.error)
s.error.call(s.context, xhr, status, errMsg);
deferred.reject(xhr, 'error', errMsg);
if (g)
$.event.trigger("ajaxError", [xhr, s, errMsg]);
}
if (g)
$.event.trigger("ajaxComplete", [xhr, s]);
if (g && ! --$.active) {
$.event.trigger("ajaxStop");
}
if (s.complete)
s.complete.call(s.context, xhr, status);
callbackProcessed = true;
if (s.timeout)
clearTimeout(timeoutHandle);
// clean up
setTimeout(function () {
if (!s.iframeTarget)
$io.remove();
else //adding else to clean up existing iframe response.
$io.attr('src', s.iframeSrc);
xhr.responseXML = null;
}, 100);
}
var toXml = $.parseXML || function (s, doc) { // use parseXML if available (jQuery 1.5+)
if (window.ActiveXObject) {
doc = new ActiveXObject('Microsoft.XMLDOM');
doc.async = 'false';
doc.loadXML(s);
}
else {
doc = (new DOMParser()).parseFromString(s, 'text/xml');
}
return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
};
var parseJSON = $.parseJSON || function (s) {
/*jslint evil:true */
return window['eval']('(' + s + ')');
};
var httpData = function (xhr, type, s) { // mostly lifted from jq1.4.4
var ct = xhr.getResponseHeader('content-type') || '',
xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
data = xml ? xhr.responseXML : xhr.responseText;
if (xml && data.documentElement.nodeName === 'parsererror') {
if ($.error)
$.error('parsererror');
}
if (s && s.dataFilter) {
data = s.dataFilter(data, type);
}
if (typeof data === 'string') {
if (type === 'json' || !type && ct.indexOf('json') >= 0) {
data = parseJSON(data);
} else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
$.globalEval(data);
}
}
return data;
};
return deferred;
}
};
/**
* ajaxForm() provides a mechanism for fully automating form submission.
*
* The advantages of using this method instead of ajaxSubmit() are:
*
* 1: This method will include coordinates for elements (if the element
* is used to submit the form).
* 2. This method will include the submit element's name/value data (for the element that was
* used to submit the form).
* 3. This method binds the submit() method to the form for you.
*
* The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
* passes the options argument along after properly binding events for submit elements and
* the form itself.
*/
$.fn.ajaxForm = function (options) {
options = options || {};
options.delegation = options.delegation && $.isFunction($.fn.on);
// in jQuery 1.3+ we can fix mistakes with the ready state
if (!options.delegation && this.length === 0) {
var o = { s: this.selector, c: this.context };
if (!$.isReady && o.s) {
log('DOM not ready, queuing ajaxForm');
$(function () {
$(o.s, o.c).ajaxForm(options);
});
return this;
}
// is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
return this;
}
if (options.delegation) {
$(document)
.off('submit.form-plugin', this.selector, doAjaxSubmit)
.off('click.form-plugin', this.selector, captureSubmittingElement)
.on('submit.form-plugin', this.selector, options, doAjaxSubmit)
.on('click.form-plugin', this.selector, options, captureSubmittingElement);
return this;
}
return this.ajaxFormUnbind()
.bind('submit.form-plugin', options, doAjaxSubmit)
.bind('click.form-plugin', options, captureSubmittingElement);
};
// private event handlers
function doAjaxSubmit(e) {
/*jshint validthis:true */
var options = e.data;
if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
e.preventDefault();
$(e.target).ajaxSubmit(options); // #365
}
}
function captureSubmittingElement(e) {
/*jshint validthis:true */
var target = e.target;
var $el = $(target);
if (!($el.is("[type=submit],[type=image]"))) {
// is this a child element of the submit el? (ex: a span within a button)
var t = $el.closest('[type=submit]');
if (t.length === 0) {
return;
}
target = t[0];
}
var form = this;
form.clk = target;
if (target.type == 'image') {
if (e.offsetX !== undefined) {
form.clk_x = e.offsetX;
form.clk_y = e.offsetY;
} else if (typeof $.fn.offset == 'function') {
var offset = $el.offset();
form.clk_x = e.pageX - offset.left;
form.clk_y = e.pageY - offset.top;
} else {
form.clk_x = e.pageX - target.offsetLeft;
form.clk_y = e.pageY - target.offsetTop;
}
}
// clear form vars
setTimeout(function () { form.clk = form.clk_x = form.clk_y = null; }, 100);
}
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function () {
return this.unbind('submit.form-plugin click.form-plugin');
};
/**
* formToArray() gathers form element data into an array of objects that can
* be passed to any of the following ajax functions: $.get, $.post, or load.
* Each object in the array has both a 'name' and 'value' property. An example of
* an array for a simple login form might be:
*
* [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
*
* It is this array that is passed to pre-submit callback functions provided to the
* ajaxSubmit() and ajaxForm() methods.
*/
$.fn.formToArray = function (semantic, elements) {
var a = [];
if (this.length === 0) {
return a;
}
var form = this[0];
var els = semantic ? form.getElementsByTagName('*') : form.elements;
if (!els) {
return a;
}
var i, j, n, v, el, max, jmax;
for (i = 0, max = els.length; i < max; i++) {
el = els[i];
n = el.name;
if (!n || el.disabled) {
continue;
}
if (semantic && form.clk && el.type == "image") {
// handle image inputs on the fly when semantic == true
if (form.clk == el) {
a.push({ name: n, value: $(el).val(), type: el.type });
a.push({ name: n + '.x', value: form.clk_x }, { name: n + '.y', value: form.clk_y });
}
continue;
}
v = $.fieldValue(el, true);
if (v && v.constructor == Array) {
if (elements)
elements.push(el);
for (j = 0, jmax = v.length; j < jmax; j++) {
a.push({ name: n, value: v[j] });
}
}
else if (feature.fileapi && el.type == 'file') {
if (elements)
elements.push(el);
var files = el.files;
if (files.length) {
for (j = 0; j < files.length; j++) {
a.push({ name: n, value: files[j], type: el.type });
}
}
else {
// #180
a.push({ name: n, value: '', type: el.type });
}
}
else if (v !== null && typeof v != 'undefined') {
if (elements)
elements.push(el);
a.push({ name: n, value: v, type: el.type, required: el.required });
}
}
if (!semantic && form.clk) {
// input type=='image' are not found in elements array! handle it here
var $input = $(form.clk), input = $input[0];
n = input.name;
if (n && !input.disabled && input.type == 'image') {
a.push({ name: n, value: $input.val() });
a.push({ name: n + '.x', value: form.clk_x }, { name: n + '.y', value: form.clk_y });
}
}
return a;
};
/**
* Serializes form data into a 'submittable' string. This method will return a string
* in the format: name1=value1&name2=value2
*/
$.fn.formSerialize = function (semantic) {
//hand off to jQuery.param for proper encoding
return $.param(this.formToArray(semantic));
};
/**
* Serializes all field elements in the jQuery object into a query string.
* This method will return a string in the format: name1=value1&name2=value2
*/
$.fn.fieldSerialize = function (successful) {
var a = [];
this.each(function () {
var n = this.name;
if (!n) {
return;
}
var v = $.fieldValue(this, successful);
if (v && v.constructor == Array) {
for (var i = 0, max = v.length; i < max; i++) {
a.push({ name: n, value: v[i] });
}
}
else if (v !== null && typeof v != 'undefined') {
a.push({ name: this.name, value: v });
}
});
//hand off to jQuery.param for proper encoding
return $.param(a);
};
/**
* Returns the value(s) of the element in the matched set. For example, consider the following form:
*
*
*
* var v = $('input[type=text]').fieldValue();
* // if no values are entered into the text inputs
* v == ['','']
* // if values entered into the text inputs are 'foo' and 'bar'
* v == ['foo','bar']
*
* var v = $('input[type=checkbox]').fieldValue();
* // if neither checkbox is checked
* v === undefined
* // if both checkboxes are checked
* v == ['B1', 'B2']
*
* var v = $('input[type=radio]').fieldValue();
* // if neither radio is checked
* v === undefined
* // if first radio is checked
* v == ['C1']
*
* The successful argument controls whether or not the field element must be 'successful'
* (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
* The default value of the successful argument is true. If this value is false the value(s)
* for each element is returned.
*
* Note: This method *always* returns an array. If no valid value can be determined the
* array will be empty, otherwise it will contain one or more values.
*/
$.fn.fieldValue = function (successful) {
for (var val = [], i = 0, max = this.length; i < max; i++) {
var el = this[i];
var v = $.fieldValue(el, successful);
if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
continue;
}
if (v.constructor == Array)
$.merge(val, v);
else
val.push(v);
}
return val;
};
/**
* Returns the value of the field element.
*/
$.fieldValue = function (el, successful) {
var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
if (successful === undefined) {
successful = true;
}
if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
(t == 'checkbox' || t == 'radio') && !el.checked ||
(t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
tag == 'select' && el.selectedIndex == -1)) {
return null;
}
if (tag == 'select') {
var index = el.selectedIndex;
if (index < 0) {
return null;
}
var a = [], ops = el.options;
var one = (t == 'select-one');
var max = (one ? index + 1 : ops.length);
for (var i = (one ? index : 0) ; i < max; i++) {
var op = ops[i];
if (op.selected) {
var v = op.value;
if (!v) { // extra pain for IE...
v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
}
if (one) {
return v;
}
a.push(v);
}
}
return a;
}
return $(el).val();
};
/**
* Clears the form data. Takes the following actions on the form's input fields:
* - input text fields will have their 'value' property set to the empty string
* - select elements will have their 'selectedIndex' property set to -1
* - checkbox and radio inputs will have their 'checked' property set to false
* - inputs of type submit, button, reset, and hidden will *not* be effected
* - button elements will *not* be effected
*/
$.fn.clearForm = function (includeHidden) {
return this.each(function () {
$('input,select,textarea', this).clearFields(includeHidden);
});
};
/**
* Clears the selected form elements.
*/
$.fn.clearFields = $.fn.clearInputs = function (includeHidden) {
var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
return this.each(function () {
var t = this.type, tag = this.tagName.toLowerCase();
if (re.test(t) || tag == 'textarea') {
this.value = '';
}
else if (t == 'checkbox' || t == 'radio') {
this.checked = false;
}
else if (tag == 'select') {
this.selectedIndex = -1;
}
else if (t == "file") {
if (/MSIE/.test(navigator.userAgent)) {
$(this).replaceWith($(this).clone(true));
} else {
$(this).val('');
}
}
else if (includeHidden) {
// includeHidden can be the value true, or it can be a selector string
// indicating a special test; for example:
// $('#myForm').clearForm('.special:hidden')
// the above would clean hidden inputs that have the class of 'special'
if ((includeHidden === true && /hidden/.test(t)) ||
(typeof includeHidden == 'string' && $(this).is(includeHidden)))
this.value = '';
}
});
};
/**
* Resets the form data. Causes all form elements to be reset to their original value.
*/
$.fn.resetForm = function () {
return this.each(function () {
// guard against an input with the name of 'reset'
// note that IE reports the reset function as an 'object'
if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
this.reset();
}
});
};
/**
* Enables or disables any matching elements.
*/
$.fn.enable = function (b) {
if (b === undefined) {
b = true;
}
return this.each(function () {
this.disabled = !b;
});
};
/**
* Checks/unchecks any matching checkboxes or radio buttons and
* selects/deselects and matching option elements.
*/
$.fn.selected = function (select) {
if (select === undefined) {
select = true;
}
return this.each(function () {
var t = this.type;
if (t == 'checkbox' || t == 'radio') {
this.checked = select;
}
else if (this.tagName.toLowerCase() == 'option') {
var $sel = $(this).parent('select');
if (select && $sel[0] && $sel[0].type == 'select-one') {
// deselect all other options
$sel.find('option').selected(false);
}
this.selected = select;
}
});
};
// expose debug var
$.fn.ajaxSubmit.debug = false;
// helper fn for console logging
function log() {
if (!$.fn.ajaxSubmit.debug)
return;
var msg = '[jquery.form] ' + Array.prototype.join.call(arguments, '');
if (window.console && window.console.log) {
window.console.log(msg);
}
else if (window.opera && window.opera.postError) {
window.opera.postError(msg);
}
}
}));
/*!
* Parsleyjs
* Guillaume Potier -
* Version 2.1.2 - built Tue Jun 16 2015 10:32:01
* MIT Licensed
*
*/
!(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module depending on jQuery.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Register plugin with global jQuery object.
factory(jQuery);
}
}(function ($) {
// small hack for requirejs if jquery is loaded through map and not path
// see http://requirejs.org/docs/jquery.html
if ('undefined' === typeof $ && 'undefined' !== typeof window.jQuery)
$ = window.jQuery;
var globalID = 1,
pastWarnings = {};
var ParsleyUtils = {
// Parsley DOM-API
// returns object from dom attributes and values
attr: function ($element, namespace, obj) {
var
attribute, attributes,
regex = new RegExp('^' + namespace, 'i');
if ('undefined' === typeof obj)
obj = {};
else {
// Clear all own properties. This won't affect prototype's values
for (var i in obj) {
if (obj.hasOwnProperty(i))
delete obj[i];
}
}
if ('undefined' === typeof $element || 'undefined' === typeof $element[0])
return obj;
attributes = $element[0].attributes;
for (var i = attributes.length; i--;) {
attribute = attributes[i];
if (attribute && attribute.specified && regex.test(attribute.name)) {
obj[this.camelize(attribute.name.slice(namespace.length))] = this.deserializeValue(attribute.value);
}
}
return obj;
},
checkAttr: function ($element, namespace, checkAttr) {
return $element.is('[' + namespace + checkAttr + ']');
},
setAttr: function ($element, namespace, attr, value) {
$element[0].setAttribute(this.dasherize(namespace + attr), String(value));
},
generateID: function () {
return '' + globalID++;
},
/** Third party functions **/
// Zepto deserialize function
deserializeValue: function (value) {
var num;
try {
return value ?
value == "true" ||
(value == "false" ? false :
value == "null" ? null :
!isNaN(num = Number(value)) ? num :
/^[\[\{]/.test(value) ? $.parseJSON(value) :
value)
: value;
} catch (e) { return value; }
},
// Zepto camelize function
camelize: function (str) {
return str.replace(/-+(.)?/g, function (match, chr) {
return chr ? chr.toUpperCase() : '';
});
},
// Zepto dasherize function
dasherize: function (str) {
return str.replace(/::/g, '/')
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
.replace(/([a-z\d])([A-Z])/g, '$1_$2')
.replace(/_/g, '-')
.toLowerCase();
},
warn: function () {
if (window.console && window.console.warn)
window.console.warn.apply(window.console, arguments);
},
warnOnce: function (msg) {
if (!pastWarnings[msg]) {
pastWarnings[msg] = true;
this.warn.apply(this, arguments);
}
},
_resetWarnings: function () {
pastWarnings = {};
},
// Object.create polyfill, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Polyfill
objectCreate: Object.create || (function () {
var Object = function () { };
return function (prototype) {
if (arguments.length > 1) {
throw Error('Second argument not supported');
}
if (typeof prototype != 'object') {
throw TypeError('Argument must be an object');
}
Object.prototype = prototype;
var result = new Object();
Object.prototype = null;
return result;
};
})()
};
// All these options could be overriden and specified directly in DOM using
// `data-parsley-` default DOM-API
// eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"`
// eg: `data-parsley-stop-on-first-failing-constraint="false"`
var ParsleyDefaults = {
// ### General
// Default data-namespace for DOM API
namespace: 'data-parsley-',
// Supported inputs by default
inputs: 'input, textarea, select',
// Excluded inputs by default
excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden]',
// Stop validating field on highest priority failing constraint
priorityEnabled: true,
// ### Field only
// identifier used to group together inputs (e.g. radio buttons...)
multiple: null,
// identifier (or array of identifiers) used to validate only a select group of inputs
group: null,
// ### UI
// Enable\Disable error messages
uiEnabled: true,
// Key events threshold before validation
validationThreshold: 3,
// Focused field on form validation error. 'fist'|'last'|'none'
focus: 'first',
// `$.Event()` that will trigger validation. eg: `keyup`, `change`...
trigger: false,
// Class that would be added on every failing validation Parsley field
errorClass: 'parsley-error',
// Same for success validation
successClass: 'parsley-success',
// Return the `$element` that will receive these above success or error classes
// Could also be (and given directly from DOM) a valid selector like `'#div'`
classHandler: function (ParsleyField) { },
// Return the `$element` where errors will be appended
// Could also be (and given directly from DOM) a valid selector like `'#div'`
errorsContainer: function (ParsleyField) { },
// ul elem that would receive errors' list
errorsWrapper: '',
// li elem that would receive error message
errorTemplate: ' '
};
var ParsleyAbstract = function () { };
ParsleyAbstract.prototype = {
asyncSupport: false,
actualizeOptions: function () {
ParsleyUtils.attr(this.$element, this.options.namespace, this.domOptions);
if (this.parent && this.parent.actualizeOptions)
this.parent.actualizeOptions();
return this;
},
_resetOptions: function (initOptions) {
this.domOptions = ParsleyUtils.objectCreate(this.parent.options);
this.options = ParsleyUtils.objectCreate(this.domOptions);
// Shallow copy of ownProperties of initOptions:
for (var i in initOptions) {
if (initOptions.hasOwnProperty(i))
this.options[i] = initOptions[i];
}
this.actualizeOptions();
},
// ParsleyValidator validate proxy function . Could be replaced by third party scripts
validateThroughValidator: function (value, constraints, priority) {
return window.ParsleyValidator.validate(value, constraints, priority);
},
_listeners: null,
// Register a callback for the given event name.
// Callback is called with context as the first argument and the `this`.
// The context is the current parsley instance, or window.Parsley if global.
// A return value of `false` will interrupt the calls
on: function (name, fn) {
this._listeners = this._listeners || {};
var queue = this._listeners[name] = this._listeners[name] || [];
queue.push(fn);
return this;
},
// Deprecated. Use `on` instead.
subscribe: function (name, fn) {
$.listenTo(this, name.toLowerCase(), fn);
},
// Unregister a callback (or all if none is given) for the given event name
off: function (name, fn) {
var queue = this._listeners && this._listeners[name];
if (queue) {
if (!fn) {
delete this._listeners[name];
} else {
for (var i = queue.length; i--;)
if (queue[i] === fn)
queue.splice(i, 1);
}
}
return this;
},
// Deprecated. Use `off`
unsubscribe: function (name, fn) {
$.unsubscribeTo(this, name.toLowerCase());
},
// Trigger an event of the given name.
// A return value of `false` interrupts the callback chain.
// Returns false if execution was interrupted.
trigger: function (name, target) {
target = target || this;
var queue = this._listeners && this._listeners[name];
var result, parentResult;
if (queue) {
for (var i = queue.length; i--;) {
result = queue[i].call(target, target);
if (result === false) return result;
}
}
if (this.parent) {
return this.parent.trigger(name, target);
}
return true;
},
// Reset UI
reset: function () {
// Field case: just emit a reset event for UI
if ('ParsleyForm' !== this.__class__)
return this._trigger('reset');
// Form case: emit a reset event for each field
for (var i = 0; i < this.fields.length; i++)
this.fields[i]._trigger('reset');
this._trigger('reset');
},
// Destroy Parsley instance (+ UI)
destroy: function () {
// Field case: emit destroy event to clean UI and then destroy stored instance
if ('ParsleyForm' !== this.__class__) {
this.$element.removeData('Parsley');
this.$element.removeData('ParsleyFieldMultiple');
this._trigger('destroy');
return;
}
// Form case: destroy all its fields and then destroy stored instance
for (var i = 0; i < this.fields.length; i++)
this.fields[i].destroy();
this.$element.removeData('Parsley');
this._trigger('destroy');
},
_findRelatedMultiple: function () {
return this.parent.$element.find('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]');
}
};
/*!
* validator.js
* Guillaume Potier -
* Version 1.0.1 - built Mon Aug 25 2014 16:10:10
* MIT Licensed
*
*/
var Validator = (function () {
var exports = {};
/**
* Validator
*/
var Validator = function (options) {
this.__class__ = 'Validator';
this.__version__ = '1.0.1';
this.options = options || {};
this.bindingKey = this.options.bindingKey || '_validatorjsConstraint';
};
Validator.prototype = {
constructor: Validator,
/*
* Validate string: validate( string, Assert, string ) || validate( string, [ Assert, Assert ], [ string, string ] )
* Validate object: validate( object, Constraint, string ) || validate( object, Constraint, [ string, string ] )
* Validate binded object: validate( object, string ) || validate( object, [ string, string ] )
*/
validate: function (objectOrString, AssertsOrConstraintOrGroup, group) {
if ('string' !== typeof objectOrString && 'object' !== typeof objectOrString)
throw new Error('You must validate an object or a string');
// string / array validation
if ('string' === typeof objectOrString || _isArray(objectOrString))
return this._validateString(objectOrString, AssertsOrConstraintOrGroup, group);
// binded object validation
if (this.isBinded(objectOrString))
return this._validateBindedObject(objectOrString, AssertsOrConstraintOrGroup);
// regular object validation
return this._validateObject(objectOrString, AssertsOrConstraintOrGroup, group);
},
bind: function (object, constraint) {
if ('object' !== typeof object)
throw new Error('Must bind a Constraint to an object');
object[this.bindingKey] = new Constraint(constraint);
return this;
},
unbind: function (object) {
if ('undefined' === typeof object._validatorjsConstraint)
return this;
delete object[this.bindingKey];
return this;
},
isBinded: function (object) {
return 'undefined' !== typeof object[this.bindingKey];
},
getBinded: function (object) {
return this.isBinded(object) ? object[this.bindingKey] : null;
},
_validateString: function (string, assert, group) {
var result, failures = [];
if (!_isArray(assert))
assert = [assert];
for (var i = 0; i < assert.length; i++) {
if (!(assert[i] instanceof Assert))
throw new Error('You must give an Assert or an Asserts array to validate a string');
result = assert[i].check(string, group);
if (result instanceof Violation)
failures.push(result);
}
return failures.length ? failures : true;
},
_validateObject: function (object, constraint, group) {
if ('object' !== typeof constraint)
throw new Error('You must give a constraint to validate an object');
if (constraint instanceof Constraint)
return constraint.check(object, group);
return new Constraint(constraint).check(object, group);
},
_validateBindedObject: function (object, group) {
return object[this.bindingKey].check(object, group);
}
};
Validator.errorCode = {
must_be_a_string: 'must_be_a_string',
must_be_an_array: 'must_be_an_array',
must_be_a_number: 'must_be_a_number',
must_be_a_string_or_array: 'must_be_a_string_or_array'
};
/**
* Constraint
*/
var Constraint = function (data, options) {
this.__class__ = 'Constraint';
this.options = options || {};
this.nodes = {};
if (data) {
try {
this._bootstrap(data);
} catch (err) {
throw new Error('Should give a valid mapping object to Constraint', err, data);
}
}
};
Constraint.prototype = {
constructor: Constraint,
check: function (object, group) {
var result, failures = {};
// check all constraint nodes.
for (var property in this.nodes) {
var isRequired = false;
var constraint = this.get(property);
var constraints = _isArray(constraint) ? constraint : [constraint];
for (var i = constraints.length - 1; i >= 0; i--) {
if ('Required' === constraints[i].__class__) {
isRequired = constraints[i].requiresValidation(group);
continue;
}
}
if (!this.has(property, object) && !this.options.strict && !isRequired) {
continue;
}
try {
if (!this.has(property, this.options.strict || isRequired ? object : undefined)) {
// we trigger here a HaveProperty Assert violation to have uniform Violation object in the end
new Assert().HaveProperty(property).validate(object);
}
result = this._check(property, object[property], group);
// check returned an array of Violations or an object mapping Violations
if ((_isArray(result) && result.length > 0) || (!_isArray(result) && !_isEmptyObject(result))) {
failures[property] = result;
}
} catch (violation) {
failures[property] = violation;
}
}
return _isEmptyObject(failures) ? true : failures;
},
add: function (node, object) {
if (object instanceof Assert || (_isArray(object) && object[0] instanceof Assert)) {
this.nodes[node] = object;
return this;
}
if ('object' === typeof object && !_isArray(object)) {
this.nodes[node] = object instanceof Constraint ? object : new Constraint(object);
return this;
}
throw new Error('Should give an Assert, an Asserts array, a Constraint', object);
},
has: function (node, nodes) {
nodes = 'undefined' !== typeof nodes ? nodes : this.nodes;
return 'undefined' !== typeof nodes[node];
},
get: function (node, placeholder) {
return this.has(node) ? this.nodes[node] : placeholder || null;
},
remove: function (node) {
var _nodes = [];
for (var i in this.nodes)
if (i !== node)
_nodes[i] = this.nodes[i];
this.nodes = _nodes;
return this;
},
_bootstrap: function (data) {
if (data instanceof Constraint)
return this.nodes = data.nodes;
for (var node in data)
this.add(node, data[node]);
},
_check: function (node, value, group) {
// Assert
if (this.nodes[node] instanceof Assert)
return this._checkAsserts(value, [this.nodes[node]], group);
// Asserts
if (_isArray(this.nodes[node]))
return this._checkAsserts(value, this.nodes[node], group);
// Constraint -> check api
if (this.nodes[node] instanceof Constraint)
return this.nodes[node].check(value, group);
throw new Error('Invalid node', this.nodes[node]);
},
_checkAsserts: function (value, asserts, group) {
var result, failures = [];
for (var i = 0; i < asserts.length; i++) {
result = asserts[i].check(value, group);
if ('undefined' !== typeof result && true !== result)
failures.push(result);
// Some asserts (Collection for example) could return an object
// if ( result && ! ( result instanceof Violation ) )
// return result;
//
// // Vast assert majority return Violation
// if ( result instanceof Violation )
// failures.push( result );
}
return failures;
}
};
/**
* Violation
*/
var Violation = function (assert, value, violation) {
this.__class__ = 'Violation';
if (!(assert instanceof Assert))
throw new Error('Should give an assertion implementing the Assert interface');
this.assert = assert;
this.value = value;
if ('undefined' !== typeof violation)
this.violation = violation;
};
Violation.prototype = {
show: function () {
var show = {
assert: this.assert.__class__,
value: this.value
};
if (this.violation)
show.violation = this.violation;
return show;
},
__toString: function () {
if ('undefined' !== typeof this.violation)
this.violation = '", ' + this.getViolation().constraint + ' expected was ' + this.getViolation().expected;
return this.assert.__class__ + ' assert failed for "' + this.value + this.violation || '';
},
getViolation: function () {
var constraint, expected;
for (constraint in this.violation)
expected = this.violation[constraint];
return { constraint: constraint, expected: expected };
}
};
/**
* Assert
*/
var Assert = function (group) {
this.__class__ = 'Assert';
this.__parentClass__ = this.__class__;
this.groups = [];
if ('undefined' !== typeof group)
this.addGroup(group);
};
Assert.prototype = {
construct: Assert,
requiresValidation: function (group) {
if (group && !this.hasGroup(group))
return false;
if (!group && this.hasGroups())
return false;
return true;
},
check: function (value, group) {
if (!this.requiresValidation(group))
return;
try {
return this.validate(value, group);
} catch (violation) {
return violation;
}
},
hasGroup: function (group) {
if (_isArray(group))
return this.hasOneOf(group);
// All Asserts respond to "Any" group
if ('Any' === group)
return true;
// Asserts with no group also respond to "Default" group. Else return false
if (!this.hasGroups())
return 'Default' === group;
return -1 !== this.groups.indexOf(group);
},
hasOneOf: function (groups) {
for (var i = 0; i < groups.length; i++)
if (this.hasGroup(groups[i]))
return true;
return false;
},
hasGroups: function () {
return this.groups.length > 0;
},
addGroup: function (group) {
if (_isArray(group))
return this.addGroups(group);
if (!this.hasGroup(group))
this.groups.push(group);
return this;
},
removeGroup: function (group) {
var _groups = [];
for (var i = 0; i < this.groups.length; i++)
if (group !== this.groups[i])
_groups.push(this.groups[i]);
this.groups = _groups;
return this;
},
addGroups: function (groups) {
for (var i = 0; i < groups.length; i++)
this.addGroup(groups[i]);
return this;
},
/**
* Asserts definitions
*/
HaveProperty: function (node) {
this.__class__ = 'HaveProperty';
this.node = node;
this.validate = function (object) {
if ('undefined' === typeof object[this.node])
throw new Violation(this, object, { value: this.node });
return true;
};
return this;
},
Blank: function () {
this.__class__ = 'Blank';
this.validate = function (value) {
if ('string' !== typeof value)
throw new Violation(this, value, { value: Validator.errorCode.must_be_a_string });
if ('' !== value.replace(/^\s+/g, '').replace(/\s+$/g, ''))
throw new Violation(this, value);
return true;
};
return this;
},
Callback: function (fn) {
this.__class__ = 'Callback';
this.arguments = Array.prototype.slice.call(arguments);
if (1 === this.arguments.length)
this.arguments = [];
else
this.arguments.splice(0, 1);
if ('function' !== typeof fn)
throw new Error('Callback must be instanciated with a function');
this.fn = fn;
this.validate = function (value) {
var result = this.fn.apply(this, [value].concat(this.arguments));
if (true !== result)
throw new Violation(this, value, { result: result });
return true;
};
return this;
},
Choice: function (list) {
this.__class__ = 'Choice';
if (!_isArray(list) && 'function' !== typeof list)
throw new Error('Choice must be instanciated with an array or a function');
this.list = list;
this.validate = function (value) {
var list = 'function' === typeof this.list ? this.list() : this.list;
for (var i = 0; i < list.length; i++)
if (value === list[i])
return true;
throw new Violation(this, value, { choices: list });
};
return this;
},
Collection: function (assertOrConstraint) {
this.__class__ = 'Collection';
this.constraint = 'undefined' !== typeof assertOrConstraint ? (assertOrConstraint instanceof Assert ? assertOrConstraint : new Constraint(assertOrConstraint)) : false;
this.validate = function (collection, group) {
var result, validator = new Validator(), count = 0, failures = {}, groups = this.groups.length ? this.groups : group;
if (!_isArray(collection))
throw new Violation(this, collection, { value: Validator.errorCode.must_be_an_array });
for (var i = 0; i < collection.length; i++) {
result = this.constraint ?
validator.validate(collection[i], this.constraint, groups) :
validator.validate(collection[i], groups);
if (!_isEmptyObject(result))
failures[count] = result;
count++;
}
return !_isEmptyObject(failures) ? failures : true;
};
return this;
},
Count: function (count) {
this.__class__ = 'Count';
this.count = count;
this.validate = function (array) {
if (!_isArray(array))
throw new Violation(this, array, { value: Validator.errorCode.must_be_an_array });
var count = 'function' === typeof this.count ? this.count(array) : this.count;
if (isNaN(Number(count)))
throw new Error('Count must be a valid interger', count);
if (count !== array.length)
throw new Violation(this, array, { count: count });
return true;
};
return this;
},
Email: function () {
this.__class__ = 'Email';
this.validate = function (value) {
var regExp = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
if ('string' !== typeof value)
throw new Violation(this, value, { value: Validator.errorCode.must_be_a_string });
if (!regExp.test(value))
throw new Violation(this, value);
return true;
};
return this;
},
EqualTo: function (reference) {
this.__class__ = 'EqualTo';
if ('undefined' === typeof reference)
throw new Error('EqualTo must be instanciated with a value or a function');
this.reference = reference;
this.validate = function (value) {
var reference = 'function' === typeof this.reference ? this.reference(value) : this.reference;
if (reference !== value)
throw new Violation(this, value, { value: reference });
return true;
};
return this;
},
GreaterThan: function (threshold) {
this.__class__ = 'GreaterThan';
if ('undefined' === typeof threshold)
throw new Error('Should give a threshold value');
this.threshold = threshold;
this.validate = function (value) {
if ('' === value || isNaN(Number(value)))
throw new Violation(this, value, { value: Validator.errorCode.must_be_a_number });
if (this.threshold >= value)
throw new Violation(this, value, { threshold: this.threshold });
return true;
};
return this;
},
GreaterThanOrEqual: function (threshold) {
this.__class__ = 'GreaterThanOrEqual';
if ('undefined' === typeof threshold)
throw new Error('Should give a threshold value');
this.threshold = threshold;
this.validate = function (value) {
if ('' === value || isNaN(Number(value)))
throw new Violation(this, value, { value: Validator.errorCode.must_be_a_number });
if (this.threshold > value)
throw new Violation(this, value, { threshold: this.threshold });
return true;
};
return this;
},
InstanceOf: function (classRef) {
this.__class__ = 'InstanceOf';
if ('undefined' === typeof classRef)
throw new Error('InstanceOf must be instanciated with a value');
this.classRef = classRef;
this.validate = function (value) {
if (true !== (value instanceof this.classRef))
throw new Violation(this, value, { classRef: this.classRef });
return true;
};
return this;
},
Length: function (boundaries) {
this.__class__ = 'Length';
if (!boundaries.min && !boundaries.max)
throw new Error('Lenth assert must be instanciated with a { min: x, max: y } object');
this.min = boundaries.min;
this.max = boundaries.max;
this.validate = function (value) {
if ('string' !== typeof value && !_isArray(value))
throw new Violation(this, value, { value: Validator.errorCode.must_be_a_string_or_array });
if ('undefined' !== typeof this.min && this.min === this.max && value.length !== this.min)
throw new Violation(this, value, { min: this.min, max: this.max });
if ('undefined' !== typeof this.max && value.length > this.max)
throw new Violation(this, value, { max: this.max });
if ('undefined' !== typeof this.min && value.length < this.min)
throw new Violation(this, value, { min: this.min });
return true;
};
return this;
},
LessThan: function (threshold) {
this.__class__ = 'LessThan';
if ('undefined' === typeof threshold)
throw new Error('Should give a threshold value');
this.threshold = threshold;
this.validate = function (value) {
if ('' === value || isNaN(Number(value)))
throw new Violation(this, value, { value: Validator.errorCode.must_be_a_number });
if (this.threshold <= value)
throw new Violation(this, value, { threshold: this.threshold });
return true;
};
return this;
},
LessThanOrEqual: function (threshold) {
this.__class__ = 'LessThanOrEqual';
if ('undefined' === typeof threshold)
throw new Error('Should give a threshold value');
this.threshold = threshold;
this.validate = function (value) {
if ('' === value || isNaN(Number(value)))
throw new Violation(this, value, { value: Validator.errorCode.must_be_a_number });
if (this.threshold < value)
throw new Violation(this, value, { threshold: this.threshold });
return true;
};
return this;
},
NotNull: function () {
this.__class__ = 'NotNull';
this.validate = function (value) {
if (null === value || 'undefined' === typeof value)
throw new Violation(this, value);
return true;
};
return this;
},
NotBlank: function () {
this.__class__ = 'NotBlank';
this.validate = function (value) {
if ('string' !== typeof value)
throw new Violation(this, value, { value: Validator.errorCode.must_be_a_string });
if ('' === value.replace(/^\s+/g, '').replace(/\s+$/g, ''))
throw new Violation(this, value);
return true;
};
return this;
},
Null: function () {
this.__class__ = 'Null';
this.validate = function (value) {
if (null !== value)
throw new Violation(this, value);
return true;
};
return this;
},
Range: function (min, max) {
this.__class__ = 'Range';
if ('undefined' === typeof min || 'undefined' === typeof max)
throw new Error('Range assert expects min and max values');
this.min = min;
this.max = max;
this.validate = function (value) {
try {
// validate strings and objects with their Length
if (('string' === typeof value && isNaN(Number(value))) || _isArray(value))
new Assert().Length({ min: this.min, max: this.max }).validate(value);
// validate numbers with their value
else
new Assert().GreaterThanOrEqual(this.min).validate(value) && new Assert().LessThanOrEqual(this.max).validate(value);
return true;
} catch (violation) {
throw new Violation(this, value, violation.violation);
}
return true;
};
return this;
},
Regexp: function (regexp, flag) {
this.__class__ = 'Regexp';
if ('undefined' === typeof regexp)
throw new Error('You must give a regexp');
this.regexp = regexp;
this.flag = flag || '';
this.validate = function (value) {
if ('string' !== typeof value)
throw new Violation(this, value, { value: Validator.errorCode.must_be_a_string });
if (!new RegExp(this.regexp, this.flag).test(value))
throw new Violation(this, value, { regexp: this.regexp, flag: this.flag });
return true;
};
return this;
},
Required: function () {
this.__class__ = 'Required';
this.validate = function (value) {
if ('undefined' === typeof value)
throw new Violation(this, value);
try {
if ('string' === typeof value)
new Assert().NotNull().validate(value) && new Assert().NotBlank().validate(value);
else if (true === _isArray(value))
new Assert().Length({ min: 1 }).validate(value);
} catch (violation) {
throw new Violation(this, value);
}
return true;
};
return this;
},
// Unique() or Unique ( { key: foo } )
Unique: function (object) {
this.__class__ = 'Unique';
if ('object' === typeof object)
this.key = object.key;
this.validate = function (array) {
var value, store = [];
if (!_isArray(array))
throw new Violation(this, array, { value: Validator.errorCode.must_be_an_array });
for (var i = 0; i < array.length; i++) {
value = 'object' === typeof array[i] ? array[i][this.key] : array[i];
if ('undefined' === typeof value)
continue;
if (-1 !== store.indexOf(value))
throw new Violation(this, array, { value: value });
store.push(value);
}
return true;
};
return this;
}
};
// expose to the world these awesome classes
exports.Assert = Assert;
exports.Validator = Validator;
exports.Violation = Violation;
exports.Constraint = Constraint;
/**
* Some useful object prototypes / functions here
*/
// IE8<= compatibility
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
if (!Array.prototype.indexOf)
Array.prototype.indexOf = function (searchElement /*, fromIndex */) {
"use strict";
if (this === null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) {
return -1;
}
var n = 0;
if (arguments.length > 1) {
n = Number(arguments[1]);
if (n != n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n !== 0 && n != Infinity && n != -Infinity) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
};
// Test if object is empty, useful for Constraint violations check
var _isEmptyObject = function (obj) {
for (var property in obj)
return false;
return true;
};
var _isArray = function (obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
};
// AMD export
if (typeof define === 'function' && define.amd) {
define('vendors/validator.js/dist/validator', [], function () {
return exports;
});
// commonjs export
} else if (typeof module !== 'undefined' && module.exports) {
module.exports = exports;
// browser
} else {
window['undefined' !== typeof validatorjs_ns ? validatorjs_ns : 'Validator'] = exports;
}
return exports;
})();
// This is needed for Browserify usage that requires Validator.js through module.exports
Validator = 'undefined' !== typeof Validator ? Validator : ('undefined' !== typeof module ? module.exports : null);
var ParsleyValidator = function (validators, catalog) {
this.__class__ = 'ParsleyValidator';
this.Validator = Validator;
// Default Parsley locale is en
this.locale = 'en';
this.init(validators || {}, catalog || {});
};
ParsleyValidator.prototype = {
init: function (validators, catalog) {
this.catalog = catalog;
// Copy prototype's validators:
this.validators = $.extend({}, this.validators);
for (var name in validators)
this.addValidator(name, validators[name].fn, validators[name].priority, validators[name].requirementsTransformer);
window.Parsley.trigger('parsley:validator:init');
},
// Set new messages locale if we have dictionary loaded in ParsleyConfig.i18n
setLocale: function (locale) {
if ('undefined' === typeof this.catalog[locale])
throw new Error(locale + ' is not available in the catalog');
this.locale = locale;
return this;
},
// Add a new messages catalog for a given locale. Set locale for this catalog if set === `true`
addCatalog: function (locale, messages, set) {
if ('object' === typeof messages)
this.catalog[locale] = messages;
if (true === set)
return this.setLocale(locale);
return this;
},
// Add a specific message for a given constraint in a given locale
addMessage: function (locale, name, message) {
if ('undefined' === typeof this.catalog[locale])
this.catalog[locale] = {};
this.catalog[locale][name.toLowerCase()] = message;
return this;
},
validate: function (value, constraints, priority) {
return new this.Validator.Validator().validate.apply(new Validator.Validator(), arguments);
},
// Add a new validator
addValidator: function (name, fn, priority, requirementsTransformer) {
if (this.validators[name])
ParsleyUtils.warn('Validator "' + name + '" is already defined.');
else if (ParsleyDefaults.hasOwnProperty(name)) {
ParsleyUtils.warn('"' + name + '" is a restricted keyword and is not a valid validator name.');
return;
};
return this._setValidator(name, fn, priority, requirementsTransformer);
},
updateValidator: function (name, fn, priority, requirementsTransformer) {
if (!this.validators[name]) {
ParsleyUtils.warn('Validator "' + name + '" is not already defined.');
return this.addValidator(name, fn, priority, requirementsTransformer);
}
return this._setValidator(name, fn, priority, requirementsTransformer);
},
removeValidator: function (name) {
if (!this.validators[name])
ParsleyUtils.warn('Validator "' + name + '" is not defined.');
delete this.validators[name];
return this;
},
_setValidator: function (name, fn, priority, requirementsTransformer) {
this.validators[name] = function (requirements) {
return $.extend(new Validator.Assert().Callback(fn, requirements), {
priority: priority,
requirementsTransformer: requirementsTransformer
});
};
return this;
},
getErrorMessage: function (constraint) {
var message;
// Type constraints are a bit different, we have to match their requirements too to find right error message
if ('type' === constraint.name) {
var typeMessages = this.catalog[this.locale][constraint.name] || {};
message = typeMessages[constraint.requirements];
} else
message = this.formatMessage(this.catalog[this.locale][constraint.name], constraint.requirements);
return message || this.catalog[this.locale].defaultMessage || this.catalog.en.defaultMessage;
},
// Kind of light `sprintf()` implementation
formatMessage: function (string, parameters) {
if ('object' === typeof parameters) {
for (var i in parameters)
string = this.formatMessage(string, parameters[i]);
return string;
}
return 'string' === typeof string ? string.replace(new RegExp('%s', 'i'), parameters) : '';
},
// Here is the Parsley default validators list.
// This is basically Validatorjs validators, with different API for some of them
// and a Parsley priority set
validators: {
notblank: function () {
return $.extend(new Validator.Assert().NotBlank(), { priority: 2 });
},
required: function () {
return $.extend(new Validator.Assert().Required(), { priority: 512 });
},
type: function (type) {
var assert;
switch (type) {
case 'email':
assert = new Validator.Assert().Email();
break;
// range type just ensure we have a number here
case 'range':
case 'number':
assert = new Validator.Assert().Regexp('^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)?(?:\\.\\d+)?$');
break;
case 'integer':
assert = new Validator.Assert().Regexp('^-?\\d+$');
break;
case 'digits':
assert = new Validator.Assert().Regexp('^\\d+$');
break;
case 'alphanum':
assert = new Validator.Assert().Regexp('^\\w+$', 'i');
break;
case 'url':
// Thanks to https://gist.github.com/dperini/729294
// Voted best validator in https://mathiasbynens.be/demo/url-regex
// Modified to make scheme optional and allow local IPs
assert = new Validator.Assert().Regexp(
"^" +
// protocol identifier
"(?:(?:https?|ftp)://)?" + // ** mod: make scheme optional
// user:pass authentication
"(?:\\S+(?::\\S*)?@)?" +
"(?:" +
// IP address exclusion
// private & local networks
// "(?!(?:10|127)(?:\\.\\d{1,3}){3})" + // ** mod: allow local networks
// "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" + // ** mod: allow local networks
// "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + // ** mod: allow local networks
// IP address dotted notation octets
// excludes loopback network 0.0.0.0
// excludes reserved space >= 224.0.0.0
// excludes network & broacast addresses
// (first & last IP address of each class)
"(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
"(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
"(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
"|" +
// host name
"(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" +
// domain name
"(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" +
// TLD identifier
"(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
")" +
// port number
"(?::\\d{2,5})?" +
// resource path
"(?:/\\S*)?" +
"$", 'i');
break;
default:
throw new Error('validator type `' + type + '` is not supported');
}
return $.extend(assert, { priority: 256 });
},
pattern: function (regexp) {
var flags = '';
// Test if RegExp is literal, if not, nothing to be done, otherwise, we need to isolate flags and pattern
if (!!(/^\/.*\/(?:[gimy]*)$/.test(regexp))) {
// Replace the regexp literal string with the first match group: ([gimy]*)
// If no flag is present, this will be a blank string
flags = regexp.replace(/.*\/([gimy]*)$/, '$1');
// Again, replace the regexp literal string with the first match group:
// everything excluding the opening and closing slashes and the flags
regexp = regexp.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
}
return $.extend(new Validator.Assert().Regexp(regexp, flags), { priority: 64 });
},
minlength: function (value) {
return $.extend(new Validator.Assert().Length({ min: value }), {
priority: 30,
requirementsTransformer: function () {
return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value;
}
});
},
maxlength: function (value) {
return $.extend(new Validator.Assert().Length({ max: value }), {
priority: 30,
requirementsTransformer: function () {
return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value;
}
});
},
length: function (array) {
return $.extend(new Validator.Assert().Length({ min: array[0], max: array[1] }), { priority: 32 });
},
mincheck: function (length) {
return this.minlength(length);
},
maxcheck: function (length) {
return this.maxlength(length);
},
check: function (array) {
return this.length(array);
},
min: function (value) {
return $.extend(new Validator.Assert().GreaterThanOrEqual(value), {
priority: 30,
requirementsTransformer: function () {
return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value;
}
});
},
max: function (value) {
return $.extend(new Validator.Assert().LessThanOrEqual(value), {
priority: 30,
requirementsTransformer: function () {
return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value;
}
});
},
range: function (array) {
return $.extend(new Validator.Assert().Range(array[0], array[1]), {
priority: 32,
requirementsTransformer: function () {
for (var i = 0; i < array.length; i++)
array[i] = 'string' === typeof array[i] && !isNaN(array[i]) ? parseInt(array[i], 10) : array[i];
return array;
}
});
},
equalto: function (value) {
return $.extend(new Validator.Assert().EqualTo(value), {
priority: 256,
requirementsTransformer: function () {
return $(value).length ? $(value).val() : value;
}
});
}
}
};
var ParsleyUI = function (options) {
this.__class__ = 'ParsleyUI';
};
ParsleyUI.prototype = {
listen: function () {
var that = this;
window.Parsley
.on('form:init', function () { that.setupForm(this); })
.on('field:init', function () { that.setupField(this); })
.on('field:validated', function () { that.reflow(this); })
.on('form:validated', function () { that.focus(this); })
.on('field:reset', function () { that.reset(this); })
.on('form:destroy', function () { that.destroy(this); })
.on('field:destroy', function () { that.destroy(this); });
return this;
},
reflow: function (fieldInstance) {
// If this field has not an active UI (case for multiples) don't bother doing something
if ('undefined' === typeof fieldInstance._ui || false === fieldInstance._ui.active)
return;
// Diff between two validation results
var diff = this._diff(fieldInstance.validationResult, fieldInstance._ui.lastValidationResult);
// Then store current validation result for next reflow
fieldInstance._ui.lastValidationResult = fieldInstance.validationResult;
// Field have been validated at least once if here. Useful for binded key events...
fieldInstance._ui.validatedOnce = true;
// Handle valid / invalid / none field class
this.manageStatusClass(fieldInstance);
// Add, remove, updated errors messages
this.manageErrorsMessages(fieldInstance, diff);
// Triggers impl
this.actualizeTriggers(fieldInstance);
// If field is not valid for the first time, bind keyup trigger to ease UX and quickly inform user
if ((diff.kept.length || diff.added.length) && true !== fieldInstance._ui.failedOnce)
this.manageFailingFieldTrigger(fieldInstance);
},
// Returns an array of field's error message(s)
getErrorsMessages: function (fieldInstance) {
// No error message, field is valid
if (true === fieldInstance.validationResult)
return [];
var messages = [];
for (var i = 0; i < fieldInstance.validationResult.length; i++)
messages.push(this._getErrorMessage(fieldInstance, fieldInstance.validationResult[i].assert));
return messages;
},
manageStatusClass: function (fieldInstance) {
if (fieldInstance.hasConstraints() && fieldInstance.needsValidation() && true === fieldInstance.validationResult)
this._successClass(fieldInstance);
else if (fieldInstance.validationResult.length > 0)
this._errorClass(fieldInstance);
else
this._resetClass(fieldInstance);
},
manageErrorsMessages: function (fieldInstance, diff) {
if ('undefined' !== typeof fieldInstance.options.errorsMessagesDisabled)
return;
// Case where we have errorMessage option that configure an unique field error message, regardless failing validators
if ('undefined' !== typeof fieldInstance.options.errorMessage) {
if ((diff.added.length || diff.kept.length)) {
this._insertErrorWrapper(fieldInstance);
if (0 === fieldInstance._ui.$errorsWrapper.find('.parsley-custom-error-message').length)
fieldInstance._ui.$errorsWrapper
.append(
$(fieldInstance.options.errorTemplate)
.addClass('parsley-custom-error-message')
);
return fieldInstance._ui.$errorsWrapper
.addClass('filled')
.find('.parsley-custom-error-message')
.html(fieldInstance.options.errorMessage);
}
return fieldInstance._ui.$errorsWrapper
.removeClass('filled')
.find('.parsley-custom-error-message')
.remove();
}
// Show, hide, update failing constraints messages
for (var i = 0; i < diff.removed.length; i++)
this.removeError(fieldInstance, diff.removed[i].assert.name, true);
for (i = 0; i < diff.added.length; i++)
this.addError(fieldInstance, diff.added[i].assert.name, undefined, diff.added[i].assert, true);
for (i = 0; i < diff.kept.length; i++)
this.updateError(fieldInstance, diff.kept[i].assert.name, undefined, diff.kept[i].assert, true);
},
// TODO: strange API here, intuitive for manual usage with addError(pslyInstance, 'foo', 'bar')
// but a little bit complex for above internal usage, with forced undefined parameter...
addError: function (fieldInstance, name, message, assert, doNotUpdateClass) {
this._insertErrorWrapper(fieldInstance);
fieldInstance._ui.$errorsWrapper
.addClass('filled')
.append(
$(fieldInstance.options.errorTemplate)
.addClass('parsley-' + name)
.html(message || this._getErrorMessage(fieldInstance, assert))
);
if (true !== doNotUpdateClass)
this._errorClass(fieldInstance);
},
// Same as above
updateError: function (fieldInstance, name, message, assert, doNotUpdateClass) {
fieldInstance._ui.$errorsWrapper
.addClass('filled')
.find('.parsley-' + name)
.html(message || this._getErrorMessage(fieldInstance, assert));
if (true !== doNotUpdateClass)
this._errorClass(fieldInstance);
},
// Same as above twice
removeError: function (fieldInstance, name, doNotUpdateClass) {
fieldInstance._ui.$errorsWrapper
.removeClass('filled')
.find('.parsley-' + name)
.remove();
// edge case possible here: remove a standard Parsley error that is still failing in fieldInstance.validationResult
// but highly improbable cuz' manually removing a well Parsley handled error makes no sense.
if (true !== doNotUpdateClass)
this.manageStatusClass(fieldInstance);
},
focus: function (formInstance) {
formInstance._focusedField = null;
if (true === formInstance.validationResult || 'none' === formInstance.options.focus)
return null;
for (var i = 0; i < formInstance.fields.length; i++) {
var field = formInstance.fields[i];
if (true !== field.validationResult && field.validationResult.length > 0 && 'undefined' === typeof field.options.noFocus) {
formInstance._focusedField = field.$element;
if ('first' === formInstance.options.focus)
break;
}
}
if (null === formInstance._focusedField)
return null;
return formInstance._focusedField.focus();
},
_getErrorMessage: function (fieldInstance, constraint) {
var customConstraintErrorMessage = constraint.name + 'Message';
if ('undefined' !== typeof fieldInstance.options[customConstraintErrorMessage])
return window.ParsleyValidator.formatMessage(fieldInstance.options[customConstraintErrorMessage], constraint.requirements);
return window.ParsleyValidator.getErrorMessage(constraint);
},
_diff: function (newResult, oldResult, deep) {
var
added = [],
kept = [];
for (var i = 0; i < newResult.length; i++) {
var found = false;
for (var j = 0; j < oldResult.length; j++)
if (newResult[i].assert.name === oldResult[j].assert.name) {
found = true;
break;
}
if (found)
kept.push(newResult[i]);
else
added.push(newResult[i]);
}
return {
kept: kept,
added: added,
removed: !deep ? this._diff(oldResult, newResult, true).added : []
};
},
setupForm: function (formInstance) {
formInstance.$element.on('submit.Parsley', false, $.proxy(formInstance.onSubmitValidate, formInstance));
// UI could be disabled
if (false === formInstance.options.uiEnabled)
return;
formInstance.$element.attr('novalidate', '');
},
setupField: function (fieldInstance) {
var _ui = { active: false };
// UI could be disabled
if (false === fieldInstance.options.uiEnabled)
return;
_ui.active = true;
// Give field its Parsley id in DOM
fieldInstance.$element.attr(fieldInstance.options.namespace + 'id', fieldInstance.__id__);
/** Generate important UI elements and store them in fieldInstance **/
// $errorClassHandler is the $element that woul have parsley-error and parsley-success classes
_ui.$errorClassHandler = this._manageClassHandler(fieldInstance);
// $errorsWrapper is a div that would contain the various field errors, it will be appended into $errorsContainer
_ui.errorsWrapperId = 'parsley-id-' + (fieldInstance.options.multiple ? 'multiple-' + fieldInstance.options.multiple : fieldInstance.__id__);
_ui.$errorsWrapper = $(fieldInstance.options.errorsWrapper).attr('id', _ui.errorsWrapperId);
// ValidationResult UI storage to detect what have changed bwt two validations, and update DOM accordingly
_ui.lastValidationResult = [];
_ui.validatedOnce = false;
_ui.validationInformationVisible = false;
// Store it in fieldInstance for later
fieldInstance._ui = _ui;
// Bind triggers first time
this.actualizeTriggers(fieldInstance);
},
// Determine which element will have `parsley-error` and `parsley-success` classes
_manageClassHandler: function (fieldInstance) {
// An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
if ('string' === typeof fieldInstance.options.classHandler && $(fieldInstance.options.classHandler).length)
return $(fieldInstance.options.classHandler);
// Class handled could also be determined by function given in Parsley options
var $handler = fieldInstance.options.classHandler(fieldInstance);
// If this function returned a valid existing DOM element, go for it
if ('undefined' !== typeof $handler && $handler.length)
return $handler;
// Otherwise, if simple element (input, texatrea, select...) it will perfectly host the classes
if (!fieldInstance.options.multiple || fieldInstance.$element.is('select'))
return fieldInstance.$element;
// But if multiple element (radio, checkbox), that would be their parent
return fieldInstance.$element.parent();
},
_insertErrorWrapper: function (fieldInstance) {
var $errorsContainer;
// Nothing to do if already inserted
if (0 !== fieldInstance._ui.$errorsWrapper.parent().length)
return fieldInstance._ui.$errorsWrapper.parent();
if ('string' === typeof fieldInstance.options.errorsContainer) {
if ($(fieldInstance.options.errorsContainer).length)
return $(fieldInstance.options.errorsContainer).append(fieldInstance._ui.$errorsWrapper);
else
ParsleyUtils.warn('The errors container `' + fieldInstance.options.errorsContainer + '` does not exist in DOM');
}
else if ('function' === typeof fieldInstance.options.errorsContainer)
$errorsContainer = fieldInstance.options.errorsContainer(fieldInstance);
if ('undefined' !== typeof $errorsContainer && $errorsContainer.length)
return $errorsContainer.append(fieldInstance._ui.$errorsWrapper);
var $from = fieldInstance.$element;
if (fieldInstance.options.multiple)
$from = $from.parent();
return $from.after(fieldInstance._ui.$errorsWrapper);
},
actualizeTriggers: function (fieldInstance) {
var $toBind = fieldInstance.$element;
if (fieldInstance.options.multiple)
$toBind = $('[' + fieldInstance.options.namespace + 'multiple="' + fieldInstance.options.multiple + '"]');
// Remove Parsley events already binded on this field
$toBind.off('.Parsley');
// If no trigger is set, all good
if (false === fieldInstance.options.trigger)
return;
var triggers = fieldInstance.options.trigger.replace(/^\s+/g, '').replace(/\s+$/g, '');
if ('' === triggers)
return;
// Bind fieldInstance.eventValidate if exists (for parsley.ajax for example), ParsleyUI.eventValidate otherwise
$toBind.on(
triggers.split(' ').join('.Parsley ') + '.Parsley',
$.proxy('function' === typeof fieldInstance.eventValidate ? fieldInstance.eventValidate : this.eventValidate, fieldInstance));
},
// Called through $.proxy with fieldInstance. `this` context is ParsleyField
eventValidate: function (event) {
// For keyup, keypress, keydown... events that could be a little bit obstrusive
// do not validate if val length < min threshold on first validation. Once field have been validated once and info
// about success or failure have been displayed, always validate with this trigger to reflect every yalidation change.
if (new RegExp('key').test(event.type))
if (!this._ui.validationInformationVisible && this.getValue().length <= this.options.validationThreshold)
return;
this._ui.validatedOnce = true;
this.validate();
},
manageFailingFieldTrigger: function (fieldInstance) {
fieldInstance._ui.failedOnce = true;
// Radio and checkboxes fields must bind every field multiple
if (fieldInstance.options.multiple)
$('[' + fieldInstance.options.namespace + 'multiple="' + fieldInstance.options.multiple + '"]').each(function () {
if (!new RegExp('change', 'i').test($(this).parsley().options.trigger || ''))
return $(this).on('change.ParsleyFailedOnce', false, $.proxy(fieldInstance.validate, fieldInstance));
});
// Select case
if (fieldInstance.$element.is('select'))
if (!new RegExp('change', 'i').test(fieldInstance.options.trigger || ''))
return fieldInstance.$element.on('change.ParsleyFailedOnce', false, $.proxy(fieldInstance.validate, fieldInstance));
// All other inputs fields
if (!new RegExp('keyup', 'i').test(fieldInstance.options.trigger || ''))
return fieldInstance.$element.on('keyup.ParsleyFailedOnce', false, $.proxy(fieldInstance.validate, fieldInstance));
},
reset: function (parsleyInstance) {
// Reset all event listeners
this.actualizeTriggers(parsleyInstance);
parsleyInstance.$element.off('.ParsleyFailedOnce');
// Nothing to do if UI never initialized for this field
if ('undefined' === typeof parsleyInstance._ui)
return;
if ('ParsleyForm' === parsleyInstance.__class__)
return;
// Reset all errors' li
parsleyInstance._ui.$errorsWrapper
.removeClass('filled')
.children()
.remove();
// Reset validation class
this._resetClass(parsleyInstance);
// Reset validation flags and last validation result
parsleyInstance._ui.validatedOnce = false;
parsleyInstance._ui.lastValidationResult = [];
parsleyInstance._ui.validationInformationVisible = false;
parsleyInstance._ui.failedOnce = false;
},
destroy: function (parsleyInstance) {
this.reset(parsleyInstance);
if ('ParsleyForm' === parsleyInstance.__class__)
return;
if ('undefined' !== typeof parsleyInstance._ui)
parsleyInstance._ui.$errorsWrapper.remove();
delete parsleyInstance._ui;
},
_successClass: function (fieldInstance) {
fieldInstance._ui.validationInformationVisible = true;
fieldInstance._ui.$errorClassHandler.removeClass(fieldInstance.options.errorClass).addClass(fieldInstance.options.successClass);
},
_errorClass: function (fieldInstance) {
fieldInstance._ui.validationInformationVisible = true;
fieldInstance._ui.$errorClassHandler.removeClass(fieldInstance.options.successClass).addClass(fieldInstance.options.errorClass);
},
_resetClass: function (fieldInstance) {
fieldInstance._ui.$errorClassHandler.removeClass(fieldInstance.options.successClass).removeClass(fieldInstance.options.errorClass);
}
};
var ParsleyForm = function (element, domOptions, options) {
this.__class__ = 'ParsleyForm';
this.__id__ = ParsleyUtils.generateID();
this.$element = $(element);
this.domOptions = domOptions;
this.options = options;
this.parent = window.Parsley;
this.fields = [];
this.validationResult = null;
};
ParsleyForm.prototype = {
onSubmitValidate: function (event) {
this.validate(undefined, undefined, event);
// prevent form submission if validation fails
if ((false === this.validationResult || !this._trigger('submit')) && event instanceof $.Event) {
event.stopImmediatePropagation();
event.preventDefault();
}
return this;
},
// @returns boolean
validate: function (group, force, event) {
this.submitEvent = event;
this.validationResult = true;
var fieldValidationResult = [];
// fire validate event to eventually modify things before very validation
this._trigger('validate');
// Refresh form DOM options and form's fields that could have changed
this._refreshFields();
this._withoutReactualizingFormOptions(function () {
// loop through fields to validate them one by one
for (var i = 0; i < this.fields.length; i++) {
// do not validate a field if not the same as given validation group
if (group && !this._isFieldInGroup(this.fields[i], group))
continue;
fieldValidationResult = this.fields[i].validate(force);
if (true !== fieldValidationResult && fieldValidationResult.length > 0 && this.validationResult)
this.validationResult = false;
}
});
this._trigger(this.validationResult ? 'success' : 'error');
this._trigger('validated');
return this.validationResult;
},
// Iterate over refreshed fields, and stop on first failure
isValid: function (group, force) {
this._refreshFields();
return this._withoutReactualizingFormOptions(function () {
for (var i = 0; i < this.fields.length; i++) {
// do not validate a field if not the same as given validation group
if (group && !this._isFieldInGroup(this.fields[i], group))
continue;
if (false === this.fields[i].isValid(force))
return false;
}
return true;
});
},
_isFieldInGroup: function (field, group) {
if ($.isArray(field.options.group))
return -1 !== $.inArray(group, field.options.group);
return field.options.group === group;
},
_refreshFields: function () {
return this.actualizeOptions()._bindFields();
},
_bindFields: function () {
var self = this,
oldFields = this.fields;
this.fields = [];
this.fieldsMappedById = {};
this._withoutReactualizingFormOptions(function () {
this.$element
.find(this.options.inputs)
.not(this.options.excluded)
.each(function () {
var fieldInstance = new Parsley.Factory(this, {}, self);
// Only add valid and not excluded `ParsleyField` and `ParsleyFieldMultiple` children
if (('ParsleyField' === fieldInstance.__class__ || 'ParsleyFieldMultiple' === fieldInstance.__class__) && (true !== fieldInstance.options.excluded))
if ('undefined' === typeof self.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__]) {
self.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__] = fieldInstance;
self.fields.push(fieldInstance);
}
});
$(oldFields).not(self.fields).each(function () {
this._trigger('reset');
});
});
return this;
},
// Internal only.
// Looping on a form's fields to do validation or similar
// will trigger reactualizing options on all of them, which
// in turn will reactualize the form's options.
// To avoid calling actualizeOptions so many times on the form
// for nothing, _withoutReactualizingFormOptions temporarily disables
// the method actualizeOptions on this form while `fn` is called.
_withoutReactualizingFormOptions: function (fn) {
var oldActualizeOptions = this.actualizeOptions;
this.actualizeOptions = function () { return this };
var result = fn.call(this); // Keep the current `this`.
this.actualizeOptions = oldActualizeOptions;
return result;
},
// Internal only.
// Shortcut to trigger an event
// Returns true iff event is not interrupted and default not prevented.
_trigger: function (eventName) {
eventName = 'form:' + eventName;
return this.trigger.apply(this, arguments);
}
};
var ConstraintFactory = function (parsleyField, name, requirements, priority, isDomConstraint) {
var assert = {};
if (!new RegExp('ParsleyField').test(parsleyField.__class__))
throw new Error('ParsleyField or ParsleyFieldMultiple instance expected');
if ('function' === typeof window.ParsleyValidator.validators[name])
assert = window.ParsleyValidator.validators[name](requirements);
if ('Assert' !== assert.__parentClass__)
throw new Error('Valid validator expected');
var getPriority = function () {
if ('undefined' !== typeof parsleyField.options[name + 'Priority'])
return parsleyField.options[name + 'Priority'];
return assert.priority || 2;
};
priority = priority || getPriority();
// If validator have a requirementsTransformer, execute it
if ('function' === typeof assert.requirementsTransformer) {
requirements = assert.requirementsTransformer();
// rebuild assert with new requirements
assert = window.ParsleyValidator.validators[name](requirements);
}
return $.extend(assert, {
name: name,
requirements: requirements,
priority: priority,
groups: [priority],
isDomConstraint: isDomConstraint || ParsleyUtils.checkAttr(parsleyField.$element, parsleyField.options.namespace, name)
});
};
var ParsleyField = function (field, domOptions, options, parsleyFormInstance) {
this.__class__ = 'ParsleyField';
this.__id__ = ParsleyUtils.generateID();
this.$element = $(field);
// Set parent if we have one
if ('undefined' !== typeof parsleyFormInstance) {
this.parent = parsleyFormInstance;
}
this.options = options;
this.domOptions = domOptions;
// Initialize some properties
this.constraints = [];
this.constraintsByName = {};
this.validationResult = [];
// Bind constraints
this._bindConstraints();
};
ParsleyField.prototype = {
// # Public API
// Validate field and trigger some events for mainly `ParsleyUI`
// @returns validationResult:
// - `true` if field valid
// - `[Violation, [Violation...]]` if there were validation errors
validate: function (force) {
this.value = this.getValue();
// Field Validate event. `this.value` could be altered for custom needs
this._trigger('validate');
this._trigger(this.isValid(force, this.value) ? 'success' : 'error');
// Field validated event. `this.validationResult` could be altered for custom needs too
this._trigger('validated');
return this.validationResult;
},
hasConstraints: function () {
return 0 !== this.constraints.length;
},
// An empty optional field does not need validation
needsValidation: function (value) {
if ('undefined' === typeof value)
value = this.getValue();
// If a field is empty and not required, it is valid
// Except if `data-parsley-validate-if-empty` explicitely added, useful for some custom validators
if (!value.length && !this._isRequired() && 'undefined' === typeof this.options.validateIfEmpty)
return false;
return true;
},
// Just validate field. Do not trigger any event
// - `false` if there are constraints and at least one of them failed
// - `true` in all other cases
isValid: function (force, value) {
// Recompute options and rebind constraints to have latest changes
this.refreshConstraints();
this.validationResult = true;
// A field without constraint is valid
if (!this.hasConstraints())
return true;
// Value could be passed as argument, needed to add more power to 'parsley:field:validate'
if ('undefined' === typeof value || null === value)
value = this.getValue();
if (!this.needsValidation(value) && true !== force)
return true;
// If we want to validate field against all constraints, just call Validator and let it do the job
var priorities = ['Any'];
if (false !== this.options.priorityEnabled) {
// Sort priorities to validate more important first
priorities = this._getConstraintsSortedPriorities();
}
// Iterate over priorities one by one, and validate related asserts one by one
for (var i = 0; i < priorities.length; i++)
if (true !== (this.validationResult = this.validateThroughValidator(value, this.constraints, priorities[i])))
return false;
return true;
},
// @returns Parsley field computed value that could be overrided or configured in DOM
getValue: function () {
var value;
// Value could be overriden in DOM or with explicit options
if ('function' === typeof this.options.value)
value = this.options.value(this);
else if ('undefined' !== typeof this.options.value)
value = this.options.value;
else
value = this.$element.val();
// Handle wrong DOM or configurations
if ('undefined' === typeof value || null === value)
return '';
// Use `data-parsley-trim-value="true"` to auto trim inputs entry
if (true === this.options.trimValue)
return value.replace(/^\s+|\s+$/g, '');
return value;
},
// Actualize options that could have change since previous validation
// Re-bind accordingly constraints (could be some new, removed or updated)
refreshConstraints: function () {
return this.actualizeOptions()._bindConstraints();
},
/**
* Add a new constraint to a field
*
* @method addConstraint
* @param {String} name
* @param {Mixed} requirements optional
* @param {Number} priority optional
* @param {Boolean} isDomConstraint optional
*/
addConstraint: function (name, requirements, priority, isDomConstraint) {
if ('function' === typeof window.ParsleyValidator.validators[name]) {
var constraint = new ConstraintFactory(this, name, requirements, priority, isDomConstraint);
// if constraint already exist, delete it and push new version
if ('undefined' !== this.constraintsByName[constraint.name])
this.removeConstraint(constraint.name);
this.constraints.push(constraint);
this.constraintsByName[constraint.name] = constraint;
}
return this;
},
// Remove a constraint
removeConstraint: function (name) {
for (var i = 0; i < this.constraints.length; i++)
if (name === this.constraints[i].name) {
this.constraints.splice(i, 1);
break;
}
delete this.constraintsByName[name];
return this;
},
// Update a constraint (Remove + re-add)
updateConstraint: function (name, parameters, priority) {
return this.removeConstraint(name)
.addConstraint(name, parameters, priority);
},
// # Internals
// Internal only.
// Bind constraints from config + options + DOM
_bindConstraints: function () {
var constraints = [], constraintsByName = {};
// clean all existing DOM constraints to only keep javascript user constraints
for (var i = 0; i < this.constraints.length; i++)
if (false === this.constraints[i].isDomConstraint) {
constraints.push(this.constraints[i]);
constraintsByName[this.constraints[i].name] = this.constraints[i];
}
this.constraints = constraints;
this.constraintsByName = constraintsByName;
// then re-add Parsley DOM-API constraints
for (var name in this.options)
this.addConstraint(name, this.options[name]);
// finally, bind special HTML5 constraints
return this._bindHtml5Constraints();
},
// Internal only.
// Bind specific HTML5 constraints to be HTML5 compliant
_bindHtml5Constraints: function () {
// html5 required
if (this.$element.hasClass('required') || this.$element.attr('required'))
this.addConstraint('required', true, undefined, true);
// html5 pattern
if ('string' === typeof this.$element.attr('pattern'))
this.addConstraint('pattern', this.$element.attr('pattern'), undefined, true);
// range
if ('undefined' !== typeof this.$element.attr('min') && 'undefined' !== typeof this.$element.attr('max'))
this.addConstraint('range', [this.$element.attr('min'), this.$element.attr('max')], undefined, true);
// HTML5 min
else if ('undefined' !== typeof this.$element.attr('min'))
this.addConstraint('min', this.$element.attr('min'), undefined, true);
// HTML5 max
else if ('undefined' !== typeof this.$element.attr('max'))
this.addConstraint('max', this.$element.attr('max'), undefined, true);
// length
if ('undefined' !== typeof this.$element.attr('minlength') && 'undefined' !== typeof this.$element.attr('maxlength'))
this.addConstraint('length', [this.$element.attr('minlength'), this.$element.attr('maxlength')], undefined, true);
// HTML5 minlength
else if ('undefined' !== typeof this.$element.attr('minlength'))
this.addConstraint('minlength', this.$element.attr('minlength'), undefined, true);
// HTML5 maxlength
else if ('undefined' !== typeof this.$element.attr('maxlength'))
this.addConstraint('maxlength', this.$element.attr('maxlength'), undefined, true);
// html5 types
var type = this.$element.attr('type');
if ('undefined' === typeof type)
return this;
// Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
if ('number' === type) {
if (('undefined' === typeof this.$element.attr('step')) || (0 === parseFloat(this.$element.attr('step')) % 1)) {
return this.addConstraint('type', 'integer', undefined, true);
} else {
return this.addConstraint('type', 'number', undefined, true);
}
// Regular other HTML5 supported types
} else if (/^(email|url|range)$/i.test(type)) {
return this.addConstraint('type', type, undefined, true);
}
return this;
},
// Internal only.
// Field is required if have required constraint without `false` value
_isRequired: function () {
if ('undefined' === typeof this.constraintsByName.required)
return false;
return false !== this.constraintsByName.required.requirements;
},
// Internal only.
// Shortcut to trigger an event
_trigger: function (eventName) {
eventName = 'field:' + eventName;
return this.trigger.apply(this, arguments);
},
// Internal only.
// Sort constraints by priority DESC
_getConstraintsSortedPriorities: function () {
var priorities = [];
// Create array unique of priorities
for (var i = 0; i < this.constraints.length; i++)
if (-1 === priorities.indexOf(this.constraints[i].priority))
priorities.push(this.constraints[i].priority);
// Sort them by priority DESC
priorities.sort(function (a, b) { return b - a; });
return priorities;
}
};
var ParsleyMultiple = function () {
this.__class__ = 'ParsleyFieldMultiple';
};
ParsleyMultiple.prototype = {
// Add new `$element` sibling for multiple field
addElement: function ($element) {
this.$elements.push($element);
return this;
},
// See `ParsleyField.refreshConstraints()`
refreshConstraints: function () {
var fieldConstraints;
this.constraints = [];
// Select multiple special treatment
if (this.$element.is('select')) {
this.actualizeOptions()._bindConstraints();
return this;
}
// Gather all constraints for each input in the multiple group
for (var i = 0; i < this.$elements.length; i++) {
// Check if element have not been dynamically removed since last binding
if (!$('html').has(this.$elements[i]).length) {
this.$elements.splice(i, 1);
continue;
}
fieldConstraints = this.$elements[i].data('ParsleyFieldMultiple').refreshConstraints().constraints;
for (var j = 0; j < fieldConstraints.length; j++)
this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);
}
return this;
},
// See `ParsleyField.getValue()`
getValue: function () {
// Value could be overriden in DOM
if ('undefined' !== typeof this.options.value)
return this.options.value;
// Radio input case
if (this.$element.is('input[type=radio]'))
return this._findRelatedMultiple().filter(':checked').val() || '';
// checkbox input case
if (this.$element.is('input[type=checkbox]')) {
var values = [];
this._findRelatedMultiple().filter(':checked').each(function () {
values.push($(this).val());
});
return values;
}
// Select multiple case
if (this.$element.is('select') && null === this.$element.val())
return [];
// Default case that should never happen
return this.$element.val();
},
_init: function () {
this.$elements = [this.$element];
return this;
}
};
var ParsleyFactory = function (element, options, parsleyFormInstance) {
this.$element = $(element);
// If the element has already been bound, returns its saved Parsley instance
var savedparsleyFormInstance = this.$element.data('Parsley');
if (savedparsleyFormInstance) {
// If the saved instance has been bound without a ParsleyForm parent and there is one given in this call, add it
if ('undefined' !== typeof parsleyFormInstance && savedparsleyFormInstance.parent === window.Parsley) {
savedparsleyFormInstance.parent = parsleyFormInstance;
savedparsleyFormInstance._resetOptions(savedparsleyFormInstance.options);
}
return savedparsleyFormInstance;
}
// Parsley must be instantiated with a DOM element or jQuery $element
if (!this.$element.length)
throw new Error('You must bind Parsley on an existing element.');
if ('undefined' !== typeof parsleyFormInstance && 'ParsleyForm' !== parsleyFormInstance.__class__)
throw new Error('Parent instance must be a ParsleyForm instance');
this.parent = parsleyFormInstance || window.Parsley;
return this.init(options);
};
ParsleyFactory.prototype = {
init: function (options) {
this.__class__ = 'Parsley';
this.__version__ = '2.1.2';
this.__id__ = ParsleyUtils.generateID();
// Pre-compute options
this._resetOptions(options);
// A ParsleyForm instance is obviously a `