File: /home/epubdjye/www17/wp-content/plugins_bcknd/smart-slider-3/nextend/media/dist/nextend-backend.js
(function(){var N=this;N.N2_=N.N2_||{r:[],d:[]},N.N2R=N.N2R||function(){N.N2_.r.push(arguments)},N.N2D=N.N2D||function(){N.N2_.d.push(arguments)}}).call(window);
N2R('$', function ($) {
$.extend(window.nextend, {
fontManager: null,
styleManager: null,
animationManager: null,
browse: null,
askToSave: true,
cancel: function (url) {
nextend.askToSave = false;
window.location.href = url;
return false;
}
});
window.n2_ = function (text) {
if (typeof nextend.localization[text] !== 'undefined') {
return nextend.localization[text];
}
return text;
};
window.n2_printf = function (text) {
var args = arguments;
var index = 1;
return text.replace(/%s/g, function () {
return args[index++];
});
};
/**
* Helps us to track when the user loaded the page
*/
window.nextendtime = $.now();
window.nextend.roundTo = 5;
window.nextend.roundHelper = function (value) {
if (window.nextend.roundTo <= 1) {
return value;
}
return Math.round(value / window.nextend.roundTo) * window.nextend.roundTo;
};
$.fn.n2opener = function () {
return this.each(function () {
var opener = $(this).on("click", function (e) {
opener.toggleClass("n2-active");
});
opener.siblings('span').on("click", function (e) {
opener.toggleClass("n2-active");
});
opener.parent().on("mouseleave", function () {
opener.removeClass("n2-active");
});
opener.find(".n2-button-menu").on("click", function (e) {
e.stopPropagation();
opener.removeClass("n2-active");
});
});
};
if (typeof jQuery !== 'undefined') {
jQuery(document).on('wp-collapse-menu', function () {
$(window).trigger('resize');
});
}
nextend.deepDiff = function () {
return {
map: function (obj1, obj2) {
if (this.isValue(obj1)) {
if ('undefined' != typeof(obj1) && obj1 != obj2) {
return obj1;
} else {
return undefined;
}
}
for (var key in obj2) {
if (this.isFunction(obj2[key])) {
continue;
}
obj1[key] = this.map(obj1[key], obj2[key]);
if (obj1[key] === undefined || ($.isPlainObject(obj1[key]) && $.isEmptyObject(obj1[key])) || (this.isArray(obj1[key]) && obj1[key].length == 0)) {
delete obj1[key];
}
}
return obj1;
},
isFunction: function (obj) {
return {}.toString.apply(obj) === '[object Function]';
},
isArray: function (obj) {
return {}.toString.apply(obj) === '[object Array]';
},
isObject: function (obj) {
return {}.toString.apply(obj) === '[object Object]';
},
isValue: function (obj) {
return !this.isObject(obj) && !this.isArray(obj);
}
}
}();
nextend.UnicodeToHTMLEntity = function (s) {
try {
var patt = /(?:[\uD800-\uDBFF][\uDC00-\uDFFF])/g,
match;
function surrogatePairToCodePoint(charCode1, charCode2) {
return ((charCode1 & 0x3FF) << 10) + (charCode2 & 0x3FF) + 0x10000;
}
function stringToCodePointArray(str) {
var codePoints = [],
i = 0,
charCode;
while (i < str.length) {
charCode = str.charCodeAt(i);
if ((charCode & 0xF800) == 0xD800) {
codePoints.push(surrogatePairToCodePoint(charCode, str.charCodeAt(++i)));
} else {
codePoints.push(charCode);
}
++i;
}
return '&#' + codePoints + ';';
}
while ((match = patt.exec(s))) {
s = s.substr(0, match.index) + stringToCodePointArray(s.substr(match.index, patt.lastIndex - match.index)) + s.substr(patt.lastIndex);
}
} catch (e) {
console.error(e);
return s;
}
return s;
};
});
N2D('NextendHeadingPane', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param $node
* @param headings
* @param contents
* @param identifier
* @constructor
*/
function NextendHeadingPane($node, headings, contents, identifier) {
this.$node = $node.data('pane', this);
this.headings = headings;
this.contents = contents;
this.tabNames = [];
this.headings.each($.proxy(function (i, el) {
this.tabNames.push($(el).data('tab'));
}, this));
this.identifier = identifier;
this._active = headings.index(headings.filter('.n2-active'));
for (var i = 0; i < headings.length; i++) {
headings.eq(i).on('click', $.proxy(this.switchToPane, this, i));
}
if (identifier) {
var saved = $.jStorage.get(this.identifier + "-pane", -1);
if (saved != -1) {
this.switchToPane(saved);
return;
}
}
this.hideAndShow();
}
NextendHeadingPane.prototype.switchToPane = function (i, e) {
if (e) {
e.preventDefault();
}
this.headings.eq(this._active).removeClass('n2-active');
this.headings.eq(i).addClass('n2-active');
this._active = i;
this.hideAndShow();
this.store(this._active);
this.$node.triggerHandler('changetab');
};
NextendHeadingPane.prototype.hideAndShow = function () {
$(this.contents[this._active]).css('display', 'block').trigger('activate');
for (var i = 0; i < this.contents.length; i++) {
if (i != this._active) {
$(this.contents[i]).css('display', 'none');
}
}
};
NextendHeadingPane.prototype.store = function (i) {
if (this.identifier) {
$.jStorage.set(this.identifier + "-pane", i);
}
};
NextendHeadingPane.prototype.showTabs = function (tabNames) {
var activatedFirst = false;
for (var i = 0; i < this.tabNames.length; i++) {
if ($.inArray(this.tabNames[i], tabNames) != '-1') {
this.headings.eq(i).css('display', '');
$(this.contents[i]).css('display', '');
if (i == this._active) {
activatedFirst = i;
} else if (activatedFirst === false) {
activatedFirst = i;
}
} else {
this.headings.eq(i).css('display', 'none');
$(this.contents[i]).css('display', 'none');
}
}
this.switchToPane(activatedFirst);
};
return NextendHeadingPane;
});
N2D('NextendHeadingScrollToPane', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param headings
* @param contents
* @param identifier
* @constructor
*/
function NextendHeadingScrollToPane(headings, contents, identifier) {
this.headings = headings;
this.contents = contents;
this.identifier = identifier;
for (var i = 0; i < headings.length; i++) {
headings.eq(i).on('click', $.proxy(this.scrollToPane, this, i));
}
}
NextendHeadingScrollToPane.prototype.scrollToPane = function (i, e) {
if (e) {
e.preventDefault();
}
$('html, body').animate({
scrollTop: this.contents[i].offset().top - $('.n2-main-top-bar').height() - $('#wpadminbar, .navbar-fixed-top').height() - 10
}, 1000);
};
return NextendHeadingScrollToPane;
});
N2D('WindowManager', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @constructor
*/
function WindowManager() {
this.window = ['main'];
this.mouseDownArea = false;
this.timeout = null;
this.isPreventDblClick = false;
this.dblClickTimeout = null;
}
WindowManager.prototype.addWindow = function (name) {
this.window.push(name);
};
WindowManager.prototype.removeWindow = function () {
this.window.pop();
};
WindowManager.prototype.getCurrentWindow = function () {
return this.window[this.window.length - 1];
};
WindowManager.prototype.setMouseDownArea = function (area, e) {
this.mouseDownArea = area;
if (this.timeout) {
clearTimeout(this.timeout);
}
this.timeout = setTimeout($.proxy(function () {
this.timeout = null;
this.mouseDownArea = false;
}, this), 50);
};
WindowManager.prototype.preventDblClick = function () {
this.isPreventDblClick = true;
if (this.dblClickTimeout) {
clearTimeout(this.dblClickTimeout);
}
this.dblClickTimeout = setTimeout($.proxy(function () {
this.dblClickTimeout = null;
this.isPreventDblClick = false;
}, this), 200);
};
var windowManagerInstance = new WindowManager();
/**
* @returns {N2Classes.WindowManager}
*/
WindowManager.get = function () {
return windowManagerInstance;
};
WindowManager.setMouseDownArea = function () {
windowManagerInstance.setMouseDownArea.apply(windowManagerInstance, arguments);
};
return WindowManager;
});
N2D('AjaxHelper', function ($, undefined) {
var loader = null;
/**
* @memberOf N2Classes
* @constructor
*/
function AjaxHelper() {
}
AjaxHelper.query = {};
AjaxHelper.addAjaxLoader = function () {
loader = $('<div class="n2-loader-overlay"><div class="n2-loader"></div></div>')
.appendTo('body');
};
AjaxHelper.addAjaxArray = function (parts) {
for (var k in parts) {
AjaxHelper.query[k] = parts[k];
}
};
AjaxHelper.makeAjaxQuery = function (queryArray, isAjax) {
if (isAjax) {
queryArray['mode'] = 'ajax';
queryArray['nextendajax'] = '1';
}
for (var k in AjaxHelper.query) {
queryArray[k] = AjaxHelper.query[k];
}
return N2Classes.N2QueryString.stringify(queryArray);
};
AjaxHelper.makeAjaxUrl = function (url, queries) {
var urlParts = url.split("?");
if (urlParts.length < 2) {
urlParts[1] = '';
}
var parsed = N2Classes.N2QueryString.parse(urlParts[1]);
if (typeof queries != 'undefined') {
for (var k in queries) {
parsed[k] = queries[k];
}
}
return urlParts[0] + '?' + AjaxHelper.makeAjaxQuery(parsed, true);
};
AjaxHelper.makeFallbackUrl = function (url, queries) {
var urlParts = url.split("?");
if (urlParts.length < 2) {
urlParts[1] = '';
}
var parsed = N2Classes.N2QueryString.parse(urlParts[1]);
if (typeof queries != 'undefined') {
for (var k in queries) {
parsed[k] = queries[k];
}
}
return urlParts[0] + '?' + AjaxHelper.makeAjaxQuery(parsed, false);
};
AjaxHelper.ajax = function (ajax) {
AjaxHelper.startLoading();
return $.ajax(ajax).always(function (response, status) {
AjaxHelper.stopLoading();
try {
if (status != 'success') {
response = JSON.parse(response.responseText);
} else if (typeof response === 'string') {
response = JSON.parse(response);
}
if (response.redirect !== undefined) {
AjaxHelper.startLoading();
window.location.href = response.redirect;
return;
}
AjaxHelper.notification(response);
} catch (e) {
var pattern = /<body[^>]*>((.|[\n\r])*)<\/body>/im,
matches = pattern.exec(response.responseText);
if (matches.length) {
N2Classes.NextendModal.SafeHTML(response.status, matches[1]);
} else {
console.error(response.responseText, response);
}
}
});
};
AjaxHelper.notification = function (response) {
if (typeof response.notification !== 'undefined' && response.notification) {
for (var k in response.notification) {
for (var i = 0; i < response.notification[k].length; i++) {
N2Classes.Notification[k](response.notification[k][i][0], response.notification[k][i][1]);
}
}
}
};
AjaxHelper.getJSON = function (ajax) {
AjaxHelper.startLoading();
return $.getJSON(ajax).always(function () {
AjaxHelper.stopLoading();
});
};
AjaxHelper.startLoading = function () {
loader.addClass('n2-active');
};
AjaxHelper.stopLoading = function () {
loader.removeClass('n2-active');
};
N2R('documentReady', function () {
AjaxHelper.addAjaxLoader();
});
return AjaxHelper;
});
N2D('Esc', function ($, undefined) {
/**
* @alias N2Classes.Esc
* @constructor
*/
function Esc() {
this.FiLo = [];
this.doc = $(document);
this.isListening = false;
}
Esc.prototype.add = function (callback) {
this.FiLo.push(callback);
if (!this.isListening) {
this.doc.on('keydown.n2-esc', $.proxy(function (e) {
if ((e.keyCode == 27 || e.keyCode == 8)) {
if (!$(e.target).is("input, textarea")) {
e.preventDefault();
var ret = this.FiLo[this.FiLo.length - 1]();
if (ret) {
this.pop();
}
} else if (e.keyCode == 27) {
e.preventDefault();
$(e.target).blur();
}
}
}, this));
this.isListening = true;
}
};
Esc.prototype.pop = function () {
this.FiLo.pop();
if (this.FiLo.length === 0) {
this.doc.off('keydown.n2-esc');
this.isListening = false;
}
};
return new Esc();
});
N2D('tooltip', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @constructor
*/
function Tooltip() {
this.$element = $('<div class="n2 n2-tooltip n2-radius-m"></div>');
this.timeout = null;
this.$tipFor = null;
$(window).ready($.proxy(this.ready, this));
}
Tooltip.prototype.ready = function () {
this.$element.appendTo('body');
this.add($('body'));
};
Tooltip.prototype.add = function ($parent) {
$parent.find('[data-n2tip]').off('.n2hastip').on({
'mouseenter.n2hastip': $.proxy(this.onEnter, this)
});
};
Tooltip.prototype.addElement = function ($el, title, h, v) {
$el.data({
n2tip: title,
n2tipv: v,
n2tiph: h
}).off('.n2hastip').on({
'mouseenter.n2hastip': $.proxy(this.onEnter, this)
});
};
Tooltip.prototype.onEnter = function (e) {
if (this.timeout) {
clearTimeout(this.timeout);
}
this.$tipFor = $(e.currentTarget).on({
'mousemove.n2tip': $.proxy(this.onMove, this),
'mouseleave.n2tip': $.proxy(this.onLeave, this)
});
this.onMove(e);
this.timeout = setTimeout($.proxy(function () {
var v = this.$tipFor.data('n2tipv'),
h = this.$tipFor.data('n2tiph');
if (typeof v === 'undefined') {
v = 10;
}
if (typeof h === 'undefined') {
h = 10;
}
this.$element.css({
margin: v + 'px ' + h + 'px'
}).html(this.$tipFor.data('n2tip')).addClass('n2-active');
}, this), 500);
};
Tooltip.prototype.onMove = function (e) {
this.$element.css({
left: e.pageX,
top: e.pageY
});
};
Tooltip.prototype.onLeave = function (e) {
if (this.timeout) {
clearTimeout(this.timeout);
}
if (this.$tipFor) {
this.$tipFor.off('.n2tip');
this.$tipFor = null;
this.$element.removeClass('n2-active').css('margin', '');
}
};
function TooltipMouse() {
this.isVisible = false;
this.$body = $('body');
this.$element = $('<div class="n2 n2-tooltip n2-radius-m"></div>').appendTo(this.$body);
}
TooltipMouse.prototype.show = function (text, e) {
if (this.isVisible) {
this.$element.html(text);
} else {
this.isVisible = true;
this.$body.on('mousemove.tooltipMouse', $.proxy(this.mouseMove, this));
this.mouseMove(e);
this.$element.html(text).addClass('n2-active');
}
};
TooltipMouse.prototype.mouseMove = function (e) {
this.$element.css({
left: e.pageX + 10,
top: e.pageY + 10
});
};
TooltipMouse.prototype.hide = function () {
this.$body.off('mousemove.tooltipMouse');
this.$element.removeClass('n2-active').html('');
this.isVisible = false;
};
nextend.tooltip = new Tooltip();
$(window).ready(function () {
nextend.tooltipMouse = new TooltipMouse();
});
return nextend.tooltip;
});
/**
* Convert 8 char hexadecimal color into RGBA color
* @param 8 characters of hexadecimal color value. Last two character stands for alpha 0-255
* @returns RGBA representation string
*/
window.N2Color = {
hex2rgba: function (str) {
var num = parseInt(str, 16); // Convert to a number
return [num >> 24 & 255, num >> 16 & 255, num >> 8 & 255, (num & 255) / 255];
},
hex2rgbaCSS: function (str) {
return 'RGBA(' + N2Color.hex2rgba(str).join(',') + ')';
},
hexdec: function (hex_string) {
hex_string = (hex_string + '').replace(/[^a-f0-9]/gi, '');
return parseInt(hex_string, 16);
},
hex2alpha: function (str) {
var num = parseInt(str, 16); // Convert to a number
return ((num & 255) / 255).toFixed(3);
},
colorizeSVG: function (str, color) {
var parts = str.split('base64,');
if (parts.length == 1) {
return str;
}
parts[1] = N2Classes.Base64.encode(N2Classes.Base64.decode(parts[1]).replace('fill="#FFF"', 'fill="#' + color.substr(0, 6) + '"').replace('opacity="1"', 'opacity="' + N2Color.hex2alpha(color) + '"'));
return parts.join('base64,');
},
colorToSVG: function (str) {
var num = parseInt(str, 16); // Convert to a number
return [str.substr(0, 6), (num & 255) / 255];
}
};
/*!
query-string
Parse and stringify URL query strings
https://github.com/sindresorhus/query-string
by Sindre Sorhus
MIT License
*/
N2D('N2QueryString', function ($, undefined) {
'use strict';
/**
* @memberOf N2Classes
*
* @type {{parse: parse, stringify: function(*=): string}}
*/
var N2QueryString = {
parse: function (str) {
if (typeof str !== 'string') {
return {};
}
str = str.trim().replace(/^(\?|#)/, '');
if (!str) {
return {};
}
return str.trim().split('&').reduce(function (ret, param) {
var parts = param.replace(/\+/g, ' ').split('=');
var key = parts[0];
var val = parts[1];
key = decodeURIComponent(key);
// missing `=` should be `null`:
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
val = val === undefined ? null : decodeURIComponent(val);
if (!ret.hasOwnProperty(key)) {
ret[key] = val;
} else if (Array.isArray(ret[key])) {
ret[key].push(val);
} else {
ret[key] = [ret[key], val];
}
return ret;
}, {});
},
stringify: function (obj) {
return obj ? Object.keys(obj).map(function (key) {
var val = obj[key];
if (Array.isArray(val)) {
return val.map(function (val2) {
return encodeURIComponent(key) + '=' + encodeURIComponent(val2);
}).join('&');
}
return encodeURIComponent(key) + '=' + encodeURIComponent(val);
}).join('&') : '';
}
};
return N2QueryString;
});
!function (g) {
var $0 = [], // result
$1 = [], // tail
$2 = [], // blocks
$3 = [], // s1
$4 = ("0123456789abcdef").split(""), // hex
$5 = [], // s2
$6 = [], // state
$7 = false, // is state created
$8 = 0, // len_cache
$9 = 0, // len
BUF = [];
// use Int32Array if defined
if (g.Int32Array) {
$1 = new Int32Array(16);
$2 = new Int32Array(16);
$3 = new Int32Array(4);
$5 = new Int32Array(4);
$6 = new Int32Array(4);
BUF = new Int32Array(4);
} else {
var i;
for (i = 0; i < 16; i++) $1[i] = $2[i] = 0;
for (i = 0; i < 4; i++) $3[i] = $5[i] = $6[i] = BUF[i] = 0;
}
// fill s1
$3[0] = 128;
$3[1] = 32768;
$3[2] = 8388608;
$3[3] = -2147483648;
// fill s2
$5[0] = 0;
$5[1] = 8;
$5[2] = 16;
$5[3] = 24;
function encode(s) {
var utf = enc = "",
start = end = 0;
for (var i = 0, j = s.length; i < j; i++) {
var c = s.charCodeAt(i);
if (c < 128) {
end++;
continue;
} else if (c > 127 && c < 2048)
enc = String.fromCharCode((c >> 6) | 192, (c & 63) | 128);
else
enc = String.fromCharCode((c >> 12) | 224, ((c >> 6) & 63) | 128, (c & 63) | 128);
if (end > start)
utf += s.slice(start, end);
utf += enc;
start = end = i + 1;
}
if (end > start)
utf += s.slice(start, j);
return utf;
}
function md5_update(s) {
var i, I;
s += "";
$7 = false;
$8 = $9 = s.length;
if ($9 > 63) {
getBlocks(s.substring(0, 64));
md5cycle($2);
$7 = true;
for (i = 128; i <= $9; i += 64) {
getBlocks(s.substring(i - 64, i));
md5cycleAdd($2);
}
s = s.substring(i - 64);
$9 = s.length;
}
$1[0] = 0;
$1[1] = 0;
$1[2] = 0;
$1[3] = 0;
$1[4] = 0;
$1[5] = 0;
$1[6] = 0;
$1[7] = 0;
$1[8] = 0;
$1[9] = 0;
$1[10] = 0;
$1[11] = 0;
$1[12] = 0;
$1[13] = 0;
$1[14] = 0;
$1[15] = 0;
for (i = 0; i < $9; i++) {
I = i % 4;
if (I === 0)
$1[i >> 2] = s.charCodeAt(i);
else
$1[i >> 2] |= s.charCodeAt(i) << $5[I];
}
$1[i >> 2] |= $3[i % 4];
if (i > 55) {
if ($7) md5cycleAdd($1);
else {
md5cycle($1);
$7 = true;
}
return md5cycleAdd([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, $8 << 3, 0]);
}
$1[14] = $8 << 3;
if ($7) md5cycleAdd($1);
else md5cycle($1);
}
function getBlocks(s) {
for (var i = 16; i--;) {
var I = i << 2;
$2[i] = s.charCodeAt(I) + (s.charCodeAt(I + 1) << 8) + (s.charCodeAt(I + 2) << 16) + (s.charCodeAt(I + 3) << 24);
}
}
function md5(data, ascii, arrayOutput) {
md5_update(ascii ? data : encode(data));
var tmp = $6[0];
$0[1] = $4[tmp & 15];
$0[0] = $4[(tmp >>= 4) & 15];
$0[3] = $4[(tmp >>= 4) & 15];
$0[2] = $4[(tmp >>= 4) & 15];
$0[5] = $4[(tmp >>= 4) & 15];
$0[4] = $4[(tmp >>= 4) & 15];
$0[7] = $4[(tmp >>= 4) & 15];
$0[6] = $4[(tmp >>= 4) & 15];
tmp = $6[1];
$0[9] = $4[tmp & 15];
$0[8] = $4[(tmp >>= 4) & 15];
$0[11] = $4[(tmp >>= 4) & 15];
$0[10] = $4[(tmp >>= 4) & 15];
$0[13] = $4[(tmp >>= 4) & 15];
$0[12] = $4[(tmp >>= 4) & 15];
$0[15] = $4[(tmp >>= 4) & 15];
$0[14] = $4[(tmp >>= 4) & 15];
tmp = $6[2];
$0[17] = $4[tmp & 15];
$0[16] = $4[(tmp >>= 4) & 15];
$0[19] = $4[(tmp >>= 4) & 15];
$0[18] = $4[(tmp >>= 4) & 15];
$0[21] = $4[(tmp >>= 4) & 15];
$0[20] = $4[(tmp >>= 4) & 15];
$0[23] = $4[(tmp >>= 4) & 15];
$0[22] = $4[(tmp >>= 4) & 15];
tmp = $6[3];
$0[25] = $4[tmp & 15];
$0[24] = $4[(tmp >>= 4) & 15];
$0[27] = $4[(tmp >>= 4) & 15];
$0[26] = $4[(tmp >>= 4) & 15];
$0[29] = $4[(tmp >>= 4) & 15];
$0[28] = $4[(tmp >>= 4) & 15];
$0[31] = $4[(tmp >>= 4) & 15];
$0[30] = $4[(tmp >>= 4) & 15];
return arrayOutput ? $0 : $0.join("");
}
function R(q, a, b, x, s1, s2, t) {
a += q + x + t;
return ((a << s1 | a >>> s2) + b) << 0;
}
function md5cycle(k) {
md5_rounds(0, 0, 0, 0, k);
$6[0] = (BUF[0] + 1732584193) << 0;
$6[1] = (BUF[1] - 271733879) << 0;
$6[2] = (BUF[2] - 1732584194) << 0;
$6[3] = (BUF[3] + 271733878) << 0;
}
function md5cycleAdd(k) {
md5_rounds($6[0], $6[1], $6[2], $6[3], k);
$6[0] = (BUF[0] + $6[0]) << 0;
$6[1] = (BUF[1] + $6[1]) << 0;
$6[2] = (BUF[2] + $6[2]) << 0;
$6[3] = (BUF[3] + $6[3]) << 0;
}
function md5_rounds(a, b, c, d, k) {
var bc, da;
if ($7) {
a = R(((c ^ d) & b) ^ d, a, b, k[0], 7, 25, -680876936);
d = R(((b ^ c) & a) ^ c, d, a, k[1], 12, 20, -389564586);
c = R(((a ^ b) & d) ^ b, c, d, k[2], 17, 15, 606105819);
b = R(((d ^ a) & c) ^ a, b, c, k[3], 22, 10, -1044525330);
} else {
a = k[0] - 680876937;
a = ((a << 7 | a >>> 25) - 271733879) << 0;
d = k[1] - 117830708 + ((2004318071 & a) ^ -1732584194);
d = ((d << 12 | d >>> 20) + a) << 0;
c = k[2] - 1126478375 + (((a ^ -271733879) & d) ^ -271733879);
c = ((c << 17 | c >>> 15) + d) << 0;
b = k[3] - 1316259209 + (((d ^ a) & c) ^ a);
b = ((b << 22 | b >>> 10) + c) << 0;
}
a = R(((c ^ d) & b) ^ d, a, b, k[4], 7, 25, -176418897);
d = R(((b ^ c) & a) ^ c, d, a, k[5], 12, 20, 1200080426);
c = R(((a ^ b) & d) ^ b, c, d, k[6], 17, 15, -1473231341);
b = R(((d ^ a) & c) ^ a, b, c, k[7], 22, 10, -45705983);
a = R(((c ^ d) & b) ^ d, a, b, k[8], 7, 25, 1770035416);
d = R(((b ^ c) & a) ^ c, d, a, k[9], 12, 20, -1958414417);
c = R(((a ^ b) & d) ^ b, c, d, k[10], 17, 15, -42063);
b = R(((d ^ a) & c) ^ a, b, c, k[11], 22, 10, -1990404162);
a = R(((c ^ d) & b) ^ d, a, b, k[12], 7, 25, 1804603682);
d = R(((b ^ c) & a) ^ c, d, a, k[13], 12, 20, -40341101);
c = R(((a ^ b) & d) ^ b, c, d, k[14], 17, 15, -1502002290);
b = R(((d ^ a) & c) ^ a, b, c, k[15], 22, 10, 1236535329);
a = R(((b ^ c) & d) ^ c, a, b, k[1], 5, 27, -165796510);
d = R(((a ^ b) & c) ^ b, d, a, k[6], 9, 23, -1069501632);
c = R(((d ^ a) & b) ^ a, c, d, k[11], 14, 18, 643717713);
b = R(((c ^ d) & a) ^ d, b, c, k[0], 20, 12, -373897302);
a = R(((b ^ c) & d) ^ c, a, b, k[5], 5, 27, -701558691);
d = R(((a ^ b) & c) ^ b, d, a, k[10], 9, 23, 38016083);
c = R(((d ^ a) & b) ^ a, c, d, k[15], 14, 18, -660478335);
b = R(((c ^ d) & a) ^ d, b, c, k[4], 20, 12, -405537848);
a = R(((b ^ c) & d) ^ c, a, b, k[9], 5, 27, 568446438);
d = R(((a ^ b) & c) ^ b, d, a, k[14], 9, 23, -1019803690);
c = R(((d ^ a) & b) ^ a, c, d, k[3], 14, 18, -187363961);
b = R(((c ^ d) & a) ^ d, b, c, k[8], 20, 12, 1163531501);
a = R(((b ^ c) & d) ^ c, a, b, k[13], 5, 27, -1444681467);
d = R(((a ^ b) & c) ^ b, d, a, k[2], 9, 23, -51403784);
c = R(((d ^ a) & b) ^ a, c, d, k[7], 14, 18, 1735328473);
b = R(((c ^ d) & a) ^ d, b, c, k[12], 20, 12, -1926607734);
bc = b ^ c;
a = R(bc ^ d, a, b, k[5], 4, 28, -378558);
d = R(bc ^ a, d, a, k[8], 11, 21, -2022574463);
da = d ^ a;
c = R(da ^ b, c, d, k[11], 16, 16, 1839030562);
b = R(da ^ c, b, c, k[14], 23, 9, -35309556);
bc = b ^ c;
a = R(bc ^ d, a, b, k[1], 4, 28, -1530992060);
d = R(bc ^ a, d, a, k[4], 11, 21, 1272893353);
da = d ^ a;
c = R(da ^ b, c, d, k[7], 16, 16, -155497632);
b = R(da ^ c, b, c, k[10], 23, 9, -1094730640);
bc = b ^ c;
a = R(bc ^ d, a, b, k[13], 4, 28, 681279174);
d = R(bc ^ a, d, a, k[0], 11, 21, -358537222);
da = d ^ a;
c = R(da ^ b, c, d, k[3], 16, 16, -722521979);
b = R(da ^ c, b, c, k[6], 23, 9, 76029189);
bc = b ^ c;
a = R(bc ^ d, a, b, k[9], 4, 28, -640364487);
d = R(bc ^ a, d, a, k[12], 11, 21, -421815835);
da = d ^ a;
c = R(da ^ b, c, d, k[15], 16, 16, 530742520);
b = R(da ^ c, b, c, k[2], 23, 9, -995338651);
a = R(c ^ (b | ~d), a, b, k[0], 6, 26, -198630844);
d = R(b ^ (a | ~c), d, a, k[7], 10, 22, 1126891415);
c = R(a ^ (d | ~b), c, d, k[14], 15, 17, -1416354905);
b = R(d ^ (c | ~a), b, c, k[5], 21, 11, -57434055);
a = R(c ^ (b | ~d), a, b, k[12], 6, 26, 1700485571);
d = R(b ^ (a | ~c), d, a, k[3], 10, 22, -1894986606);
c = R(a ^ (d | ~b), c, d, k[10], 15, 17, -1051523);
b = R(d ^ (c | ~a), b, c, k[1], 21, 11, -2054922799);
a = R(c ^ (b | ~d), a, b, k[8], 6, 26, 1873313359);
d = R(b ^ (a | ~c), d, a, k[15], 10, 22, -30611744);
c = R(a ^ (d | ~b), c, d, k[6], 15, 17, -1560198380);
b = R(d ^ (c | ~a), b, c, k[13], 21, 11, 1309151649);
a = R(c ^ (b | ~d), a, b, k[4], 6, 26, -145523070);
d = R(b ^ (a | ~c), d, a, k[11], 10, 22, -1120210379);
c = R(a ^ (d | ~b), c, d, k[2], 15, 17, 718787259);
b = R(d ^ (c | ~a), b, c, k[9], 21, 11, -343485551);
BUF[0] = a;
BUF[1] = b;
BUF[2] = c;
BUF[3] = d;
}
g.md5 = g.md5 || md5;
}(window);
N2D('NextendCSS', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @constructor
*/
function NextendCSS() {
this.style = '';
}
NextendCSS.prototype.add = function (css) {
var body = document.body || document.getElementsByTagName('body')[0],
style = document.createElement('style');
body.appendChild(style);
style.type = 'text/css';
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
};
NextendCSS.prototype.deleteRule = function (selectorText) {
var selectorText1 = selectorText.toLowerCase();
var selectorText2 = selectorText1.replace('.', '\\.');
for (var j = document.styleSheets.length - 1; j >= 0; j--) {
var rules = this._getRulesArray(j);
for (var i = 0; rules && i < rules.length; i++) {
if (rules[i].selectorText) {
var lo = rules[i].selectorText.toLowerCase();
if ((lo == selectorText1) || (lo == selectorText2)) {
if (document.styleSheets[j].cssRules) {
document.styleSheets[j].deleteRule(i);
} else {
document.styleSheets[j].removeRule(i);
}
}
}
}
}
return (null);
};
NextendCSS.prototype._getRulesArray = function (i) {
var crossrule = null;
try {
if (document.styleSheets[i].cssRules)
crossrule = document.styleSheets[i].cssRules;
else if (document.styleSheets[i].rules)
crossrule = document.styleSheets[i].rules;
} catch (e) {
}
return (crossrule);
};
/**
* @type {NextendCSS}
*/
window.nextend.css = new NextendCSS();
return window.nextend.css;
});
N2D('ImageHelper', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param parameters
* @param openLightbox
* @param openMultipleLightbox
* @param openFoldersLightbox
* @constructor
*/
function ImageHelper(parameters, openLightbox, openMultipleLightbox, openFoldersLightbox) {
ImageHelper.prototype.openLightbox = openLightbox;
ImageHelper.prototype.openMultipleLightbox = openMultipleLightbox;
ImageHelper.prototype.openFoldersLightbox = openFoldersLightbox;
nextend.imageHelper = this;
this.parameters = $.extend({
siteKeywords: [],
imageUrls: [],
wordpressUrl: '',
placeholderImage: '',
placeholderRepeatedImage: '',
protocolRelative: 1
}, parameters);
}
ImageHelper.prototype.protocolRelative = function (image) {
if (this.parameters.protocolRelative) {
return image.replace(/^http(s)?:\/\//, '//');
}
return image;
};
ImageHelper.prototype.make = function (image) {
return this.dynamic(image);
};
ImageHelper.prototype.dynamic = function (image) {
var imageUrls = this.parameters.imageUrls,
keywords = this.parameters.siteKeywords,
_image = this.protocolRelative(image);
for (var i = 0; i < keywords.length; i++) {
if (_image.indexOf(imageUrls[i]) === 0) {
image = keywords[i] + _image.slice(imageUrls[i].length);
break;
}
}
return image;
};
ImageHelper.prototype.fixed = function (image) {
var imageUrls = this.parameters.imageUrls,
keywords = this.parameters.siteKeywords;
for (var i = 0; i < keywords.length; i++) {
if (image.indexOf(keywords[i]) === 0) {
image = imageUrls[i] + image.slice(keywords[i].length);
break;
}
}
return image;
};
ImageHelper.prototype.openLightbox = function (callback) {
};
ImageHelper.prototype.openMultipleLightbox = function (callback) {
};
ImageHelper.prototype.openFoldersLightbox = function (callback) {
};
ImageHelper.prototype.getPlaceholder = function () {
return this.fixed(this.parameters.placeholderImage);
};
ImageHelper.prototype.getRepeatedPlaceholder = function () {
return this.fixed(this.parameters.placeholderRepeatedImage);
};
return ImageHelper;
});
N2D('NextendModal', function ($, undefined) {
var counter = 0;
/**
* @memberOf N2Classes
*
* @param panes
* @param show
* @param args
* @constructor
*/
function NextendModal(panes, show, args) {
this.inited = false;
this.currentPane = null;
this.customClass = '';
this.$ = $(this);
this.counter = counter++;
this.panes = panes;
if (show) {
this.show(null, args);
}
}
NextendModal.prototype.setCustomClass = function (customClass) {
this.customClass = customClass;
};
NextendModal.prototype.lateInit = function () {
if (!this.inited) {
for (var k in this.panes) {
this.panes[k] = $.extend({
customClass: '',
fit: false,
fitX: true,
overflow: 'hidden',
size: false,
back: false,
close: true,
controlsClass: '',
controls: [],
fn: {}
}, this.panes[k]);
}
var stopClick = false;
this.modal = $('<div class="n2-modal ' + this.customClass + '"/>').css('opacity', 0)
.on('click', $.proxy(function (e) {
if (stopClick == false) {
if (!this.close.hasClass('n2-hidden') && $(e.target).closest('.n2-notification-center-modal').length == 0) {
this.hide(e);
}
}
stopClick = false;
}, this));
this.window = $('<div class="n2-modal-window n2-border-radius"/>')
.on('click', function (e) {
stopClick = true;
}).appendTo(this.modal);
this.notificationStack = new N2Classes.NotificationStackModal(this.modal);
var titleContainer = $('<div class="n2-modal-title n2-content-box-title-bg"/>')
.appendTo(this.window);
this.title = $('<div class="n2-h2 n2-ucf"/>').appendTo(titleContainer);
this.back = $('<i class="n2-i n2-i-a-back"/>')
.on('click', $.proxy(this.goBackButton, this))
.appendTo(titleContainer);
this.close = $('<i class="n2-i n2-i-a-deletes"/>')
.on('click', $.proxy(this.hide, this))
.appendTo(titleContainer);
this.content = $('<div class="n2-modal-content"/>').appendTo(this.window);
this.controls = $('<div class="n2-table n2-table-fixed n2-table-auto"/>');
$('<div class="n2-modal-controls"/>')
.append(this.controls)
.appendTo(this.window);
this.inited = true;
}
};
NextendModal.prototype.show = function (paneId, args) {
this.lateInit();
this.notificationStack.enableStack();
if (typeof paneId === 'undefined' || !paneId) {
paneId = 'zero';
}
N2Classes.WindowManager.get().addWindow("modal");
N2Classes.Esc.add($.proxy(function () {
if (!this.close.hasClass('n2-hidden')) {
this.hide('esc');
return true;
}
return false;
}, this));
this.loadPane(paneId, false, true, args);
NextendTween.fromTo(this.modal, 0.3, {
opacity: 0
}, {
opacity: 1,
ease: 'easeOutCubic'
});
};
NextendModal.prototype.hide = function (e) {
$(window).off('.n2-modal-' + this.counter);
this.notificationStack.popStack();
N2Classes.WindowManager.get().removeWindow();
if (arguments.length > 0 && e != 'esc') {
N2Classes.Esc.pop();
}
this.apply('hide');
this.apply('destroy');
this.currentPane = null;
this.modal.detach();
$(document).off('keyup.n2-esc-modal');
};
NextendModal.prototype.destroy = function () {
this.modal.remove();
};
NextendModal.prototype.loadPane = function (id, backward, isShow, args) {
var end = $.proxy(function () {
var pane = this.panes[id];
this.currentPane = pane;
if (pane.title !== false) {
this.title.html(pane.title);
}
if (pane.back === false) {
this.back.addClass('n2-hidden');
} else {
this.back.removeClass('n2-hidden');
}
if (pane.close === false) {
this.close.addClass('n2-hidden');
} else {
this.close.removeClass('n2-hidden');
}
this.content.find('> *').detach();
this.content.append(pane.content);
var hasControls = false;
var tr = $('<div class="n2-tr" />');
var i = 0;
for (; i < pane.controls.length; i++) {
$('<div class="n2-td"/>')
.addClass('n2-modal-controls-' + i)
.html(pane.controls[i])
.appendTo(tr);
hasControls = true;
}
tr.addClass('n2-modal-controls-' + i);
this.controls.html(tr);
this.controls.attr('class', 'n2-table n2-table-fixed n2-table-auto ' + pane.controlsClass);
if (typeof isShow == 'undefined' || !isShow) {
NextendTween.fromTo(this.window, 0.3, {
x: backward ? -2000 : 2000
}, {
x: 0,
ease: 'easeOutCubic'
});
}
this.modal.appendTo('#n2-admin');
if (pane.fit) {
var $w = $(window),
margin = 40,
resize = $.proxy(function () {
var w = $w.width() - 2 * margin,
h = $w.height() - 2 * margin;
if (!pane.fitX) {
w = pane.size[0];
}
this.window.css({
width: w,
height: h,
marginLeft: w / -2,
marginTop: h / -2
});
this.content.css({
height: h - 60 - (hasControls ? this.controls.parent().outerHeight(true) : 0),
overflow: pane.overflow
});
}, this);
resize();
$w.on('resize.n2-modal-' + this.counter, resize);
} else if (pane.size !== false) {
this.window.css({
width: pane.size[0],
height: pane.size[1],
marginLeft: pane.size[0] / -2,
marginTop: pane.size[1] / -2
});
this.content.css({
height: pane.size[1] - 60 - (hasControls ? this.controls.parent().outerHeight(true) : 0),
overflow: pane.overflow
});
}
this.apply('show', args);
}, this);
if (this.currentPane !== null) {
this.apply('destroy');
NextendTween.to(this.window, 0.3, {
x: backward ? 2000 : -2000,
onComplete: end,
ease: 'easeOutCubic'
});
} else {
end();
}
};
NextendModal.prototype.trigger = function (event, args) {
this.$.trigger(event, args);
};
NextendModal.prototype.on = function (event, fn) {
this.$.on(event, fn);
};
NextendModal.prototype.one = function (event, fn) {
this.$.one(event, fn);
};
NextendModal.prototype.off = function (event, fn) {
this.$.off(event, fn);
};
NextendModal.prototype.goBackButton = function () {
var args = null;
if (typeof this.goBackArgs !== null) {
args = this.goBackArgs;
this.goBackArgs = null;
}
this.goBack(args);
};
NextendModal.prototype.goBack = function (args) {
if (this.apply('goBack', args)) {
this.loadPane(this.currentPane.back, true, false, args);
}
};
NextendModal.prototype.apply = function (event, args) {
if (typeof this.currentPane.fn[event] !== 'undefined') {
return this.currentPane.fn[event].apply(this, args);
}
return true;
};
NextendModal.prototype.createInput = function (label, id) {
var style = '';
if (arguments.length == 3) {
style = arguments[2];
}
return $('<div class="n2-form-element-mixed"><div class="n2-mixed-group"><div class="n2-mixed-label"><label for="' + id + '">' + label + '</label></div><div class="n2-mixed-element"><div class="n2-form-element-text n2-border-radius"><input type="text" id="' + id + '" value="" class="n2-h5" autocomplete="off" style="' + style + '"></div></div></div></div>');
};
NextendModal.prototype.createInputUnit = function (label, id, unit) {
var style = '';
if (arguments.length == 4) {
style = arguments[3];
}
return $('<div class="n2-form-element-mixed"><div class="n2-mixed-group"><div class="n2-mixed-label"><label for="' + id + '">' + label + '</label></div><div class="n2-mixed-element"><div class="n2-form-element-text n2-border-radius"><input type="text" id="' + id + '" value="" class="n2-h5" autocomplete="off" style="' + style + '"><div class="n2-text-unit n2-h5 n2-uc">' + unit + '</div></div></div></div></div>');
};
NextendModal.prototype.createInputSub = function (label, id, sub) {
var style = '';
if (arguments.length == 4) {
style = arguments[3];
}
return $('<div class="n2-form-element-mixed"><div class="n2-mixed-group"><div class="n2-mixed-label"><label for="' + id + '">' + label + '</label></div><div class="n2-mixed-element"><div class="n2-form-element-text n2-border-radius"><div class="n2-text-sub-label n2-h5 n2-uc">' + sub + '</div><input type="text" id="' + id + '" value="" class="n2-h5" autocomplete="off" style="' + style + '"></div></div></div></div>');
};
NextendModal.prototype.createTextarea = function (label, id) {
var style = '';
if (arguments.length == 3) {
style = arguments[2];
}
return $('<div class="n2-form-element-mixed"><div class="n2-mixed-group"><div class="n2-mixed-label"><label for="' + id + '">' + label + '</label></div><div class="n2-mixed-element"><div class="n2-form-element-textarea n2-border-radius"><textarea id="' + id + '" class="n2-h5" autocomplete="off" style="resize:none;' + style + '"></textarea></div></div></div></div>');
};
NextendModal.prototype.createSelect = function (label, id, values) {
var style = '';
if (arguments.length == 4) {
style = arguments[3];
}
$group = $('<div class="n2-form-element-mixed"><div class="n2-mixed-group "><div class="n2-mixed-label"><label for="' + id + '">' + label + '</label></div><div class="n2-mixed-element"><div class="n2-form-element-list" style=""><select id="' + id + '" autocomplete="off" style="' + style + '"></select></div></div></div></div>');
$select = $group.find('select');
for (var k in values) {
$('<option value="' + k + '"></option>').text(values[k]).appendTo($select);
}
$select.prop('selectedIndex', 0);
return $group;
};
NextendModal.prototype.createHeading = function (title) {
return $('<h3 class="n2-h3">' + title + '</h3>');
};
NextendModal.prototype.createSubHeading = function (title) {
return $('<h3 class="n2-h4">' + title + '</h3>');
};
NextendModal.prototype.createCenteredHeading = function (title) {
return $('<h3 class="n2-h3 n2-center">' + title + '</h3>');
};
NextendModal.prototype.createCenteredSubHeading = function (title) {
return $('<h3 class="n2-h4 n2-center">' + title + '</h3>');
};
NextendModal.prototype.createResult = function () {
return $('<div class="n2-result"></div>');
};
NextendModal.prototype.createTable = function (data, style) {
var table = $('<table class="n2-table-fancy"/>');
for (var j = 0; j < data.length; j++) {
var tr = $('<tr />').appendTo(table);
for (var i = 0; i < data[j].length; i++) {
tr.append($('<td style="' + style[i] + '"/>').append(data[j][i]));
}
}
return table;
};
NextendModal.prototype.createTableWrap = function () {
return $('<div class="n2-table-fancy-wrap" style="overflow:auto;height:196px;" />');
};
NextendModal.prototype.createImageRadio = function (options) {
var wrapper = $('<div class="n2-modal-radio" />'),
input = $('<input type="hidden" value="' + options[0].key + '"/>').appendTo(wrapper);
for (var i = 0; i < options.length; i++) {
var url = "'" + nextend.imageHelper.fixed(options[i].image) + "'";
wrapper.append('<div class="n2-modal-radio-option" data-key="' + options[i].key + '" style="background-image: url(' + url + ')"><div class="n2-h4">' + options[i].name + '</div></div>')
}
var options = wrapper.find('.n2-modal-radio-option');
options.eq(0).addClass('n2-active');
options.on('click', function (e) {
options.removeClass('n2-active');
var option = $(e.currentTarget);
option.addClass('n2-active');
input.val(option.data('key'));
});
return wrapper;
};
NextendModal.settings = function (title, url) {
new N2Classes.NextendModal({
zero: {
size: [
1300,
700
],
title: title,
content: '<iframe src="' + url + '" width="1300" height="640" frameborder="0" style="margin:0 -20px -20px -20px;"></iframe>'
}
}, true);
};
NextendModal.documentation = function (title, url) {
new N2Classes.NextendModal({
zero: {
size: [
760,
700
],
title: title,
content: '<iframe src="' + url + '" width="760" height="640" frameborder="0" style="margin:0 -20px -20px -20px;"></iframe>'
}
}, true);
};
NextendModal.newFullWindow = function (url, id) {
var params = [
'height=' + screen.height,
'width=' + screen.width,
'fullscreen=yes'
].join(',');
var popup = window.open(url, id, params);
popup.moveTo(0, 0);
return popup;
};
NextendModal.deleteModal = function (identifier, instanceName, callback) {
if ($.jStorage.get('n2-delete-' + identifier, false)) {
callback();
return true;
}
new N2Classes.NextendModal({
zero: {
size: [
500,
190
],
title: n2_('Delete'),
back: false,
close: true,
content: '',
controls: ['<a href="#" class="n2-button n2-button-normal n2-button-l n2-radius-s n2-button-grey n2-uc n2-h4">' + n2_('Cancel') + '</a>', '<div class="n2-button n2-button-with-actions n2-button-l n2-radius-s n2-button-red"><a href="#" class="n2-button-inner n2-uc n2-h4">' + n2_('Delete') + '</a><div class="n2-button-menu-open"><i class="n2-i n2-i-buttonarrow"></i><div class="n2-button-menu"><div class="n2-button-menu-inner n2-border-radius"><a href="#" class="n2-h4">' + n2_('Delete and never ask for confirmation again') + '</a></div></div></div></div>'],
fn: {
show: function () {
this.createCenteredSubHeading(n2_('Are you sure you want to delete?')).appendTo(this.content);
this.controls.find('.n2-button-grey')
.on('click', $.proxy(function (e) {
e.preventDefault();
this.hide(e);
}, this));
this.controls.find('.n2-button-red a')
.on('click', $.proxy(function (e) {
e.preventDefault();
callback();
this.hide(e);
}, this));
this.controls.find('.n2-button-red .n2-button-menu-inner a')
.on('click', $.proxy(function (e) {
e.preventDefault();
$.jStorage.set('n2-delete-' + identifier, true);
}, this));
this.controls.find(".n2-button-menu-open").n2opener();
},
destroy: function () {
this.destroy();
}
}
}
}, true);
return false;
};
NextendModal.deleteModalLink = function (element, identifier, instanceName) {
N2Classes.NextendModal.deleteModal(identifier, instanceName, function () {
window.location.href = $(element).attr('href');
});
return false;
};
NextendModal.SafeHTML = function (title, html) {
var modal = new N2Classes.NextendModal({
zero: {
fit: true,
size: [
1300,
700
],
title: title,
content: ''
}
}, true);
modal.content.removeClass('n2-modal-content').css('padding', '0 20px 20px');
var $html = $(html.replace(/document\.write/g, 'n2Write')),
$currentNode;
window.n2Write = $.proxy(function (buffer) {
$('<span />').html(buffer).appendTo(modal.content);
}, this);
$html.each($.proxy(function (i, el) {
$currentNode = $(el);
$currentNode.appendTo(modal.content);
}, this));
delete window.n2Write;
};
return NextendModal;
});
N2D('NextendSimpleModal', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param html
* @param options
* @constructor
*/
function NextendSimpleModal(html, options) {
this.$ = $(this);
this.options = $.extend({
'class': ''
}, options);
this.modal = $('<div class="n2-modal n2-modal-simple"/>').addClass(this.options.class).css({
display: 'none'
}).appendTo('#n2-admin');
$('<i class="n2-i n2-i-a-deletes"/>')
.on('click', $.proxy(this.hide, this))
.appendTo(this.modal);
this.window = $('<div class="n2-modal-window"/>')
.on('click', function (e) {
e.stopPropagation();
})
.appendTo(this.modal);
this.notificationStack = new N2Classes.NotificationStackModal(this.modal);
this.content = $(html).appendTo(this.window);
}
NextendSimpleModal.prototype.resize = function () {
this.window.width(this.modal.width());
this.window.height(this.modal.height());
};
NextendSimpleModal.prototype.show = function () {
$('body').addClass('n2-modal-active');
this.modal.css('display', 'block');
this.resize();
$(window).on('resize.n2-simple-modal', $.proxy(this.resize, this));
this.notificationStack.enableStack();
N2Classes.Esc.add($.proxy(function () {
this.hide('esc');
return true;
}, this));
};
NextendSimpleModal.prototype.hide = function (e) {
this.notificationStack.popStack();
if (arguments.length > 0 && e != 'esc') {
N2Classes.Esc.pop();
}
this.modal.css('display', 'none');
$('body').removeClass('n2-modal-active');
$(document).off('keyup.n2-esc-modal');
$(window).off('.n2-simple-modal');
this.modal.trigger('ModalHide');
};
return NextendSimpleModal;
});
// Spectrum Colorpicker v1.0.9
// https://github.com/bgrins/spectrum
// Author: Brian Grinstead
// License: MIT
N2D('Spectrum', function ($, undefined) {
var tinycolor = null;
var defaultOpts = {
// Events
beforeShow: noop,
move: noop,
change: noop,
show: noop,
hide: noop,
// Options
color: false,
flat: false,
showInput: false,
showButtons: true,
clickoutFiresChange: false,
showInitial: false,
showPalette: false,
showPaletteOnly: false,
showSelectionPalette: true,
localStorageKey: false,
maxSelectionSize: 7,
cancelText: "cancel",
chooseText: "choose",
preferredFormat: false,
className: "",
showAlpha: false,
theme: "n2-sp-light",
palette: ['fff', '000'],
selectionPalette: [],
disabled: false
},
spectrums = [],
IE = !!/msie/i.exec(window.navigator.userAgent),
rgbaSupport = (function () {
function contains(str, substr) {
return !!~('' + str).indexOf(substr);
}
var elem = document.createElement('div');
var style = elem.style;
style.cssText = 'background-color:rgba(0,0,0,.5)';
return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');
})(),
replaceInput = [
"<div class='n2-sp-replacer'>",
"<div class='n2-sp-preview'><div class='n2-sp-preview-inner'></div></div>",
"<div class='n2-sp-dd'>▲</div>",
"</div>"
].join(''),
markup = (function () {
// IE does not support gradients with multiple stops, so we need to simulate
// that for the rainbow slider with 8 divs that each have a single gradient
var gradientFix = "";
if (IE) {
for (var i = 1; i <= 6; i++) {
gradientFix += "<div class='n2-sp-" + i + "'></div>";
}
}
return [
"<div class='n2-sp-container'>",
"<div class='n2-sp-palette-container'>",
"<div class='n2-sp-palette n2-sp-thumb n2-sp-cf'></div>",
"</div>",
"<div class='n2-sp-picker-container'>",
"<div class='n2-sp-top n2-sp-cf'>",
"<div class='n2-sp-fill'></div>",
"<div class='n2-sp-top-inner'>",
"<div class='n2-sp-color'>",
"<div class='n2-sp-sat'>",
"<div class='n2-sp-val'>",
"<div class='n2-sp-dragger'></div>",
"</div>",
"</div>",
"</div>",
"<div class='n2-sp-hue'>",
"<div class='n2-sp-slider'></div>",
gradientFix,
"</div>",
"</div>",
"<div class='n2-sp-alpha'><div class='n2-sp-alpha-inner'><div class='n2-sp-alpha-handle'></div></div></div>",
"</div>",
"<div class='n2-sp-input-container n2-sp-cf'>",
"<input class='n2-sp-input' type='text' spellcheck='false' />",
"</div>",
"<div class='n2-sp-initial n2-sp-thumb n2-sp-cf'></div>",
"<div class='n2-sp-button-container n2-sp-cf'>",
"<a class='n2-sp-cancel' href='#'></a>",
"<button class='n2-sp-choose'></button>",
"</div>",
"</div>",
"</div>"
].join("");
})();
function paletteTemplate(p, color, className) {
var html = [];
for (var i = 0; i < p.length; i++) {
var tiny = tinycolor(p[i]);
var c = tiny.toHsl().l < 0.5 ? "n2-sp-thumb-el n2-sp-thumb-dark" : "n2-sp-thumb-el n2-sp-thumb-light";
c += (tinycolor.equals(color, p[i])) ? " n2-sp-thumb-active" : "";
var swatchStyle = "background-color:" + tiny.toRgbString();
html.push('<span title="' + tiny.toRgbString() + '" data-color="' + tiny.toRgbString() + '" class="' + c + '"><span class="n2-sp-thumb-inner" style="' + swatchStyle + ';" /></span>');
}
return "<div class='n2-sp-cf " + className + "'>" + html.join('') + "</div>";
}
function hideAll() {
for (var i = 0; i < spectrums.length; i++) {
if (spectrums[i]) {
spectrums[i].hide();
}
}
}
function instanceOptions(o, callbackContext) {
var opts = $.extend({}, defaultOpts, o);
opts.callbacks = {
'move': bind(opts.move, callbackContext),
'change': bind(opts.change, callbackContext),
'show': bind(opts.show, callbackContext),
'hide': bind(opts.hide, callbackContext),
'beforeShow': bind(opts.beforeShow, callbackContext)
};
return opts;
}
function spectrum(element, o) {
var opts = instanceOptions(o, element),
flat = opts.flat,
showSelectionPalette = opts.showSelectionPalette,
localStorageKey = opts.localStorageKey,
theme = opts.theme,
callbacks = opts.callbacks,
resize = throttle(reflow, 10),
visible = false,
dragWidth = 0,
dragHeight = 0,
dragHelperHeight = 0,
slideHeight = 0,
slideWidth = 0,
alphaWidth = 0,
alphaSlideHelperWidth = 0,
slideHelperHeight = 0,
currentHue = 0,
currentSaturation = 0,
currentValue = 0,
currentAlpha = 1,
palette = opts.palette.slice(0),
paletteArray = $.isArray(palette[0]) ? palette : [palette],
selectionPalette = opts.selectionPalette.slice(0),
draggingClass = "n2-sp-dragging";
var doc = element.ownerDocument,
body = doc.body,
boundElement = $(element),
disabled = false,
container = $(markup, doc).addClass(theme),
dragger = container.find(".n2-sp-color"),
dragHelper = container.find(".n2-sp-dragger"),
slider = container.find(".n2-sp-hue"),
slideHelper = container.find(".n2-sp-slider"),
alphaSliderInner = container.find(".n2-sp-alpha-inner"),
alphaSlider = container.find(".n2-sp-alpha"),
alphaSlideHelper = container.find(".n2-sp-alpha-handle"),
textInput = container.find(".n2-sp-input"),
paletteContainer = container.find(".n2-sp-palette"),
initialColorContainer = container.find(".n2-sp-initial"),
cancelButton = container.find(".n2-sp-cancel"),
chooseButton = container.find(".n2-sp-choose"),
isInput = boundElement.is("input"),
shouldReplace = isInput && !flat,
replacer = null,
offsetElement = null,
previewElement = null,
initialColor = opts.color || (isInput && boundElement.val()),
colorOnShow = false,
preferredFormat = opts.preferredFormat,
currentPreferredFormat = preferredFormat,
clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange;
container.on('mousedown', function (e) {
N2Classes.WindowManager.get().setMouseDownArea('colorpicker', e);
});
function applyOptions(noReflow) {
container.toggleClass("n2-sp-flat", flat);
container.toggleClass("n2-sp-input-disabled", !opts.showInput);
container.toggleClass("n2-sp-alpha-enabled", opts.showAlpha);
container.toggleClass("n2-sp-buttons-disabled", !opts.showButtons || flat);
container.toggleClass("n2-sp-palette-disabled", !opts.showPalette);
container.toggleClass("n2-sp-palette-only", opts.showPaletteOnly);
container.toggleClass("n2-sp-initial-disabled", !opts.showInitial);
container.addClass(opts.className);
if (typeof noReflow === 'undefined') {
reflow();
}
}
function initialize() {
if (IE) {
container.find("*:not(input)").attr("unselectable", "on");
}
var customReplace = boundElement.parent().find('.n2-sp-replacer');
if (customReplace.length) {
replacer = customReplace;
} else {
replacer = (shouldReplace) ? $(replaceInput).addClass(theme) : $([]);
if (shouldReplace) {
//boundElement.hide().after(replacer);
boundElement.parent().after(replacer);
}
}
offsetElement = (shouldReplace) ? replacer : boundElement;
previewElement = replacer.find(".n2-sp-preview-inner");
applyOptions(true);
if (flat) {
boundElement.parent().after(container).hide();
}
else {
$(body).append(container.hide());
}
if (localStorageKey && window.localStorage) {
try {
selectionPalette = window.localStorage[localStorageKey].split(";");
}
catch (e) {
}
}
offsetElement.bind("click.spectrum touchstart.spectrum", function (e) {
if (!disabled) {
toggle();
}
e.stopPropagation();
if (!$(e.target).is("input")) {
e.preventDefault();
}
});
if (boundElement.is(":disabled") || (opts.disabled === true)) {
disable();
}
// Prevent clicks from bubbling up to document. This would cause it to be hidden.
container.click(stopPropagation);
// Handle user typed input
textInput.change(setFromTextInput);
textInput.bind("paste", function () {
setTimeout(setFromTextInput, 1);
});
textInput.keydown(function (e) {
if (e.keyCode == 13) {
setFromTextInput();
}
});
cancelButton.text(opts.cancelText);
cancelButton.bind("click.spectrum", function (e) {
e.stopPropagation();
e.preventDefault();
hide("cancel");
});
chooseButton.text(opts.chooseText);
chooseButton.bind("click.spectrum", function (e) {
e.stopPropagation();
e.preventDefault();
if (isValid()) {
updateOriginalInput(true);
hide();
}
});
draggable(alphaSlider, function (dragX, dragY, e) {
currentAlpha = (dragX / alphaWidth);
if (e.shiftKey) {
currentAlpha = Math.round(currentAlpha * 10) / 10;
}
move();
});
draggable(slider, function (dragX, dragY) {
currentHue = parseFloat(dragY / slideHeight);
move();
}, dragStart, dragStop);
draggable(dragger, function (dragX, dragY) {
currentSaturation = parseFloat(dragX / dragWidth);
currentValue = parseFloat((dragHeight - dragY) / dragHeight);
move();
}, dragStart, dragStop);
if (!!initialColor) {
set(initialColor);
// In case color was black - update the preview UI and set the format
// since the set function will not run (default color is black).
updateUI();
currentPreferredFormat = preferredFormat || tinycolor(initialColor).format;
addColorToSelectionPalette(initialColor);
}
else {
updateUI();
}
if (flat) {
show();
}
function palletElementClick(e) {
if (e.data && e.data.ignore) {
set($(this).data("color"));
move();
}
else {
set($(this).data("color"));
updateOriginalInput(true);
move();
hide();
}
return false;
}
var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum";
paletteContainer.delegate(".n2-sp-thumb-el", paletteEvent, palletElementClick);
initialColorContainer.delegate(".n2-sp-thumb-el:nth-child(1)", paletteEvent, {ignore: true}, palletElementClick);
}
function addColorToSelectionPalette(color) {
if (showSelectionPalette) {
var colorRgb = tinycolor(color).toRgbString();
if ($.inArray(colorRgb, selectionPalette) === -1) {
selectionPalette.push(colorRgb);
}
if (localStorageKey && window.localStorage) {
try {
window.localStorage[localStorageKey] = selectionPalette.join(";");
}
catch (e) {
}
}
}
}
function getUniqueSelectionPalette() {
var unique = [];
var p = selectionPalette;
var paletteLookup = {};
var rgb;
if (opts.showPalette) {
for (var i = 0; i < paletteArray.length; i++) {
for (var j = 0; j < paletteArray[i].length; j++) {
rgb = tinycolor(paletteArray[i][j]).toRgbString();
paletteLookup[rgb] = true;
}
}
for (i = 0; i < p.length; i++) {
rgb = tinycolor(p[i]).toRgbString();
if (!paletteLookup.hasOwnProperty(rgb)) {
unique.push(p[i]);
paletteLookup[rgb] = true;
}
}
}
return unique.reverse().slice(0, opts.maxSelectionSize);
}
function drawPalette() {
var currentColor = get();
var html = $.map(paletteArray, function (palette, i) {
return paletteTemplate(palette, currentColor, "n2-sp-palette-row n2-sp-palette-row-" + i);
});
if (selectionPalette) {
html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "n2-sp-palette-row n2-sp-palette-row-selection"));
}
paletteContainer.html(html.join(""));
}
function drawInitial() {
if (opts.showInitial) {
var initial = colorOnShow;
var current = get();
initialColorContainer.html(paletteTemplate([initial, current], current, "n2-sp-palette-row-initial"));
}
}
function dragStart() {
if (dragHeight === 0 || dragWidth === 0 || slideHeight === 0) {
reflow();
}
container.addClass(draggingClass);
}
function dragStop() {
container.removeClass(draggingClass);
}
function setFromTextInput() {
var tiny = tinycolor(textInput.val());
if (tiny.ok) {
set(tiny);
}
else {
textInput.addClass("n2-sp-validation-error");
}
}
function toggle() {
if (visible) {
hide();
}
else {
show();
}
}
function show() {
if (visible) {
reflow();
return;
}
if (callbacks.beforeShow(get()) === false) return;
hideAll();
visible = true;
$(doc).bind("click.spectrum", hide);
$(window).bind("resize.spectrum", resize);
replacer.addClass("n2-sp-active");
container.show();
if (opts.showPalette) {
drawPalette();
}
reflow();
updateUI();
colorOnShow = get();
drawInitial();
callbacks.show(colorOnShow);
}
function hide(e) {
// Return on right click
if (e && e.type == "click" && e.button == 2) {
return;
}
// Return if hiding is unnecessary
if (!visible || flat) {
return;
}
visible = false;
$(doc).unbind("click.spectrum", hide);
$(window).unbind("resize.spectrum", resize);
replacer.removeClass("n2-sp-active");
container.hide();
var colorHasChanged = !tinycolor.equals(get(), colorOnShow);
if (colorHasChanged) {
if (clickoutFiresChange && e !== "cancel") {
updateOriginalInput(true);
}
else {
revert();
}
}
callbacks.hide(get());
}
function revert() {
set(colorOnShow, true);
}
function set(color, ignoreFormatChange) {
if (tinycolor.equals(color, get())) {
return;
}
var newColor = tinycolor(color);
var newHsv = newColor.toHsv();
currentHue = newHsv.h;
currentSaturation = newHsv.s;
currentValue = newHsv.v;
currentAlpha = newHsv.a;
updateUI();
if (!ignoreFormatChange) {
currentPreferredFormat = preferredFormat || newColor.format;
}
}
function get() {
return tinycolor.fromRatio({
h: currentHue,
s: currentSaturation,
v: currentValue,
a: Math.round(currentAlpha * 100) / 100
});
}
function isValid() {
return !textInput.hasClass("n2-sp-validation-error");
}
function move() {
updateUI();
callbacks.move(get());
}
function updateUI() {
textInput.removeClass("n2-sp-validation-error");
updateHelperLocations();
// Update dragger background color (gradients take care of saturation and value).
var flatColor = tinycolor({h: currentHue, s: "1.0", v: "1.0"});
dragger.css("background-color", '#' + flatColor.toHexString());
// Get a format that alpha will be included in (hex and names ignore alpha)
var format = currentPreferredFormat;
if (currentAlpha < 1) {
if (format === "hex" || format === "name") {
format = "rgb";
}
}
var realColor = get(),
realHex = realColor.toHexString(),
realRgb = realColor.toRgbString();
// Update the replaced elements background color (with actual selected color)
if (rgbaSupport || realColor.alpha === 1) {
previewElement.css("background-color", realRgb);
}
else {
previewElement.css("background-color", "transparent");
previewElement.css("filter", realColor.toFilter());
}
if (opts.showAlpha) {
var rgb = realColor.toRgb();
rgb.a = 0;
var realAlpha = tinycolor(rgb).toRgbString();
var gradient = "linear-gradient(to right, " + realAlpha + ", " + realHex + ")";
alphaSliderInner.css("background", gradient);
}
// Update the text entry input as it changes happen
if (opts.showInput) {
if (currentAlpha < 1) {
if (format === "hex" || format === "name") {
format = "rgb";
}
}
textInput.val(realColor.toString(format));
}
if (opts.showPalette) {
drawPalette();
}
drawInitial();
}
function updateHelperLocations() {
var s = currentSaturation;
var v = currentValue;
// Where to show the little circle in that displays your current selected color
var dragX = s * dragWidth;
var dragY = dragHeight - (v * dragHeight);
dragX = Math.max(
-dragHelperHeight,
Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)
);
dragY = Math.max(
-dragHelperHeight,
Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)
);
dragHelper.css({
"top": dragY,
"left": dragX
});
var alphaX = currentAlpha * alphaWidth;
alphaSlideHelper.css({
"left": alphaX - (alphaSlideHelperWidth / 2)
});
// Where to show the bar that displays your current selected hue
var slideY = (currentHue) * slideHeight;
slideHelper.css({
"top": slideY - slideHelperHeight
});
}
function updateOriginalInput(fireCallback) {
var color = get();
if (isInput) {
boundElement.val(color.toString(currentPreferredFormat)).change();
}
//var hasChanged = !tinycolor.equals(color, colorOnShow);
var hasChanged = 1;
colorOnShow = color;
// Update the selection palette with the current color
addColorToSelectionPalette(color);
if (fireCallback && hasChanged) {
callbacks.change(color);
}
}
function reflow() {
dragWidth = dragger.width();
dragHeight = dragger.height();
dragHelperHeight = dragHelper.height();
slideWidth = slider.width();
slideHeight = slider.height();
slideHelperHeight = slideHelper.height();
alphaWidth = alphaSlider.width();
alphaSlideHelperWidth = alphaSlideHelper.width();
if (!flat) {
container.offset(getOffset(container, offsetElement.parent()));
}
updateHelperLocations();
}
function destroy() {
boundElement.show();
offsetElement.unbind("click.spectrum touchstart.spectrum");
container.remove();
replacer.remove();
spectrums[spect.id] = null;
}
function option(optionName, optionValue) {
if (optionName === undefined) {
return $.extend({}, opts);
}
if (optionValue === undefined) {
return opts[optionName];
}
opts[optionName] = optionValue;
applyOptions();
}
function enable() {
disabled = false;
boundElement.attr("disabled", false);
offsetElement.removeClass("n2-sp-disabled");
}
function disable() {
hide();
disabled = true;
boundElement.attr("disabled", true);
offsetElement.addClass("n2-sp-disabled");
}
initialize();
var spect = {
show: show,
hide: hide,
toggle: toggle,
reflow: reflow,
option: option,
enable: enable,
disable: disable,
set: function (c) {
set(c);
updateOriginalInput();
},
get: get,
destroy: destroy,
container: container
};
spect.id = spectrums.push(spect) - 1;
return spect;
}
/**
* checkOffset - get the offset below/above and left/right element depending on screen position
* Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
*/
function getOffset(picker, input) {
var extraY = 0;
var dpWidth = picker.outerWidth();
var dpHeight = picker.outerHeight();
var inputHeight = input.outerHeight();
var doc = picker[0].ownerDocument;
var docElem = doc.documentElement;
var viewWidth = docElem.clientWidth + $(doc).scrollLeft();
var viewHeight = docElem.clientHeight + $(doc).scrollTop();
var offset = input.offset();
offset.top += inputHeight + 3;
offset.left -=
Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
Math.abs(offset.left + dpWidth - viewWidth) : 0);
offset.top -=
Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
Math.abs(dpHeight + inputHeight + 6 - extraY) : extraY));
return offset;
}
/**
* noop - do nothing
*/
function noop() {
}
/**
* stopPropagation - makes the code only doing this a little easier to read in line
*/
function stopPropagation(e) {
e.stopPropagation();
}
/**
* Create a function bound to a given object
* Thanks to underscore.js
*/
function bind(func, obj) {
var slice = Array.prototype.slice;
var args = slice.call(arguments, 2);
return function () {
return func.apply(obj, args.concat(slice.call(arguments)));
};
}
/**
* Lightweight drag helper. Handles containment within the element, so that
* when dragging, the x is within [0,element.width] and y is within [0,element.height]
*/
function draggable(element, onmove, onstart, onstop) {
onmove = onmove || function () {
};
onstart = onstart || function () {
};
onstop = onstop || function () {
};
var doc = element.ownerDocument || document;
var dragging = false;
var offset = {};
var maxHeight = 0;
var maxWidth = 0;
var hasTouch = false;
var duringDragEvents = {};
duringDragEvents["selectstart"] = prevent;
duringDragEvents["dragstart"] = prevent;
duringDragEvents[(hasTouch ? "touchmove" : "mousemove")] = move;
duringDragEvents[(hasTouch ? "touchend" : "mouseup")] = stop;
function prevent(e) {
if (e.stopPropagation) {
e.stopPropagation();
}
if (e.preventDefault) {
e.preventDefault();
}
e.returnValue = false;
}
function move(e) {
if (dragging) {
// Mouseup happened outside of window
if (IE && document.documentMode < 9 && !e.button) {
return stop();
}
var touches = e.originalEvent.touches;
var pageX = touches ? touches[0].pageX : e.pageX;
var pageY = touches ? touches[0].pageY : e.pageY;
var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));
var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));
if (hasTouch) {
// Stop scrolling in iOS
prevent(e);
}
onmove.apply(element, [dragX, dragY, e]);
}
}
function start(e) {
var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);
var touches = e.originalEvent.touches;
if (!rightclick && !dragging) {
if (onstart.apply(element, arguments) !== false) {
dragging = true;
maxHeight = $(element).height();
maxWidth = $(element).width();
offset = $(element).offset();
$(doc).bind(duringDragEvents);
$(doc.body).addClass("n2-sp-dragging");
if (!hasTouch) {
move(e);
}
prevent(e);
}
}
}
function stop() {
if (dragging) {
$(doc).unbind(duringDragEvents);
$(doc.body).removeClass("n2-sp-dragging");
onstop.apply(element, arguments);
}
dragging = false;
}
$(element).bind(hasTouch ? "touchstart" : "mousedown", start);
}
function throttle(func, wait, debounce) {
var timeout;
return function () {
var context = this, args = arguments;
var throttler = function () {
timeout = null;
func.apply(context, args);
};
if (debounce) clearTimeout(timeout);
if (debounce || !timeout) timeout = setTimeout(throttler, wait);
};
}
/**
* Define a jQuery plugin
*/
var dataID = "spectrum.id";
$.fn.n2spectrum = function (opts, extra) {
if (typeof opts == "string") {
var returnValue = this;
var args = Array.prototype.slice.call(arguments, 1);
this.each(function () {
var spect = spectrums[$(this).data(dataID)];
if (spect) {
var method = spect[opts];
if (!method) {
throw new Error("Spectrum: no such method: '" + opts + "'");
}
if (opts == "get") {
returnValue = spect.get();
}
else if (opts == "container") {
returnValue = spect.container;
}
else if (opts == "option") {
returnValue = spect.option.apply(spect, args);
}
else if (opts == "destroy") {
spect.destroy();
$(this).removeData(dataID);
}
else {
method.apply(spect, args);
}
}
});
return returnValue;
}
// Initializing a new instance of spectrum
return this.n2spectrum("destroy").each(function () {
var spect = spectrum(this, opts);
$(this).data(dataID, spect.id);
});
};
$.fn.n2spectrum.load = true;
$.fn.n2spectrum.loadOpts = {};
$.fn.n2spectrum.draggable = draggable;
$.fn.n2spectrum.defaults = defaultOpts;
$.n2spectrum = {};
$.n2spectrum.localization = {};
$.n2spectrum.palettes = {};
// TinyColor.js - <https://github.com/bgrins/TinyColor> - 2011 Brian Grinstead - v0.5
(function () {
var trimLeft = /^[\s,#]+/,
trimRight = /\s+$/,
tinyCounter = 0,
math = Math,
mathRound = math.round,
mathMin = math.min,
mathMax = math.max,
mathRandom = math.random;
tinycolor = function (color, opts) {
// If input is already a tinycolor, return itself
if (typeof color == "object" && color.hasOwnProperty("_tc_id")) {
return color;
}
var rgb = inputToRGB(color);
var r = rgb.r, g = rgb.g, b = rgb.b, a = parseFloat(rgb.a), format = rgb.format;
return {
ok: rgb.ok,
format: format,
_tc_id: tinyCounter++,
alpha: a,
toHsv: function () {
var hsv = rgbToHsv(r, g, b);
return {h: hsv.h, s: hsv.s, v: hsv.v, a: a};
},
toHsvString: function () {
var hsv = rgbToHsv(r, g, b);
var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
return (a == 1) ?
"hsv(" + h + ", " + s + "%, " + v + "%)" :
"hsva(" + h + ", " + s + "%, " + v + "%, " + a + ")";
},
toHsl: function () {
var hsl = rgbToHsl(r, g, b);
return {h: hsl.h, s: hsl.s, l: hsl.l, a: a};
},
toHslString: function () {
var hsl = rgbToHsl(r, g, b);
var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
return (a == 1) ?
"hsl(" + h + ", " + s + "%, " + l + "%)" :
"hsla(" + h + ", " + s + "%, " + l + "%, " + a + ")";
},
toHex: function () {
return rgbToHex(r, g, b);
},
toHexString: function (force6Char) {
return rgbToHex(r, g, b, force6Char);
},
toHexString8: function () {
return rgbToHex(r, g, b, true) + pad2(mathRound(a * 255).toString(16));
},
toRgb: function () {
return {r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a};
},
toRgbString: function () {
return (a == 1) ?
"rgb(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ")" :
"rgba(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ", " + a + ")";
},
toName: function () {
return hexNames[rgbToHex(r, g, b)] || false;
},
toFilter: function (opts, secondColor) {
var hex = rgbToHex(r, g, b, true);
var secondHex = hex;
var alphaHex = Math.round(parseFloat(a) * 255).toString(16);
var secondAlphaHex = alphaHex;
var gradientType = opts && opts.gradientType ? "GradientType = 1, " : "";
if (secondColor) {
var s = tinycolor(secondColor);
secondHex = s.toHex();
secondAlphaHex = Math.round(parseFloat(s.alpha) * 255).toString(16);
}
return "progid:DXImageTransform.Microsoft.gradient(" + gradientType + "startColorstr=#" + pad2(alphaHex) + hex + ",endColorstr=#" + pad2(secondAlphaHex) + secondHex + ")";
},
toString: function (format) {
format = format || this.format;
var formattedString = false;
if (format === "rgb") {
formattedString = this.toRgbString();
}
if (format === "hex") {
formattedString = this.toHexString();
}
if (format === "hex6") {
formattedString = this.toHexString(true);
}
if (format === "hex8") {
formattedString = this.toHexString8();
}
if (format === "name") {
formattedString = this.toName();
}
if (format === "hsl") {
formattedString = this.toHslString();
}
if (format === "hsv") {
formattedString = this.toHsvString();
}
return formattedString || this.toHexString(true);
}
};
};
// If input is an object, force 1 into "1.0" to handle ratios properly
// String input requires "1.0" as input, so 1 will be treated as 1
tinycolor.fromRatio = function (color) {
if (typeof color == "object") {
for (var i in color) {
if (color[i] === 1) {
color[i] = "1.0";
}
}
}
return tinycolor(color);
};
// Given a string or object, convert that input to RGB
// Possible string inputs:
//
// "red"
// "#f00" or "f00"
// "#ff0000" or "ff0000"
// "rgb 255 0 0" or "rgb (255, 0, 0)"
// "rgb 1.0 0 0" or "rgb (1, 0, 0)"
// "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
// "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
// "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
// "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
// "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
//
function inputToRGB(color) {
var rgb = {r: 0, g: 0, b: 0};
var a = 1;
var ok = false;
var format = false;
if (typeof color == "string") {
color = stringInputToObject(color);
}
if (typeof color == "object") {
if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
rgb = rgbToRgb(color.r, color.g, color.b);
ok = true;
format = "rgb";
}
else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
rgb = hsvToRgb(color.h, color.s, color.v);
ok = true;
format = "hsv";
}
else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
rgb = hslToRgb(color.h, color.s, color.l);
ok = true;
format = "hsl";
}
if (color.hasOwnProperty("a")) {
a = color.a;
}
}
rgb.r = mathMin(255, mathMax(rgb.r, 0));
rgb.g = mathMin(255, mathMax(rgb.g, 0));
rgb.b = mathMin(255, mathMax(rgb.b, 0));
// Don't let the range of [0,255] come back in [0,1].
// Potentially lose a little bit of precision here, but will fix issues where
// .5 gets interpreted as half of the total, instead of half of 1.
// If it was supposed to be 128, this was already taken care of in the conversion function
if (rgb.r < 1) {
rgb.r = mathRound(rgb.r);
}
if (rgb.g < 1) {
rgb.g = mathRound(rgb.g);
}
if (rgb.b < 1) {
rgb.b = mathRound(rgb.b);
}
return {
ok: ok,
format: (color && color.format) || format,
r: rgb.r,
g: rgb.g,
b: rgb.b,
a: a
};
}
// Conversion Functions
// --------------------
// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
// <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
// `rgbToRgb`
// Handle bounds / percentage checking to conform to CSS color spec
// <http://www.w3.org/TR/css3-color/>
// *Assumes:* r, g, b in [0, 255] or [0, 1]
// *Returns:* { r, g, b } in [0, 255]
function rgbToRgb(r, g, b) {
return {
r: bound01(r, 255) * 255,
g: bound01(g, 255) * 255,
b: bound01(b, 255) * 255
};
}
// `rgbToHsl`
// Converts an RGB color value to HSL.
// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
// *Returns:* { h, s, l } in [0,1]
function rgbToHsl(r, g, b) {
r = bound01(r, 255);
g = bound01(g, 255);
b = bound01(b, 255);
var max = mathMax(r, g, b), min = mathMin(r, g, b);
var h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
}
else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return {h: h, s: s, l: l};
}
// `hslToRgb`
// Converts an HSL color value to RGB.
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
// *Returns:* { r, g, b } in the set [0, 255]
function hslToRgb(h, s, l) {
var r, g, b;
h = bound01(h, 360);
s = bound01(s, 100);
l = bound01(l, 100);
function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
if (s === 0) {
r = g = b = l; // achromatic
}
else {
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return {r: r * 255, g: g * 255, b: b * 255};
}
// `rgbToHsv`
// Converts an RGB color value to HSV
// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
// *Returns:* { h, s, v } in [0,1]
function rgbToHsv(r, g, b) {
r = bound01(r, 255);
g = bound01(g, 255);
b = bound01(b, 255);
var max = mathMax(r, g, b), min = mathMin(r, g, b);
var h, s, v = max;
var d = max - min;
s = max === 0 ? 0 : d / max;
if (max == min) {
h = 0; // achromatic
}
else {
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return {h: h, s: s, v: v};
}
// `hsvToRgb`
// Converts an HSV color value to RGB.
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
// *Returns:* { r, g, b } in the set [0, 255]
function hsvToRgb(h, s, v) {
h = bound01(h, 360) * 6;
s = bound01(s, 100);
v = bound01(v, 100);
var i = math.floor(h),
f = h - i,
p = v * (1 - s),
q = v * (1 - f * s),
t = v * (1 - (1 - f) * s),
mod = i % 6,
r = [v, q, p, p, t, v][mod],
g = [t, v, v, q, p, p][mod],
b = [p, p, t, v, v, q][mod];
return {r: r * 255, g: g * 255, b: b * 255};
}
// `rgbToHex`
// Converts an RGB color to hex
// Assumes r, g, and b are contained in the set [0, 255]
// Returns a 3 or 6 character hex
function rgbToHex(r, g, b, force6Char) {
var hex = [
pad2(mathRound(r).toString(16)),
pad2(mathRound(g).toString(16)),
pad2(mathRound(b).toString(16))
];
// Return a 3 character hex if possible
if (!force6Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
}
return hex.join("");
}
// `equals`
// Can be called with any tinycolor input
tinycolor.equals = function (color1, color2) {
if (!color1 || !color2) {
return false;
}
return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
};
tinycolor.random = function () {
return tinycolor.fromRatio({
r: mathRandom(),
g: mathRandom(),
b: mathRandom()
});
};
// Modification Functions
// ----------------------
// Thanks to less.js for some of the basics here
// <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
tinycolor.desaturate = function (color, amount) {
var hsl = tinycolor(color).toHsl();
hsl.s -= ((amount || 10) / 100);
hsl.s = clamp01(hsl.s);
return tinycolor(hsl);
};
tinycolor.saturate = function (color, amount) {
var hsl = tinycolor(color).toHsl();
hsl.s += ((amount || 10) / 100);
hsl.s = clamp01(hsl.s);
return tinycolor(hsl);
};
tinycolor.greyscale = function (color) {
return tinycolor.desaturate(color, 100);
};
tinycolor.lighten = function (color, amount) {
var hsl = tinycolor(color).toHsl();
hsl.l += ((amount || 10) / 100);
hsl.l = clamp01(hsl.l);
return tinycolor(hsl);
};
tinycolor.darken = function (color, amount) {
var hsl = tinycolor(color).toHsl();
hsl.l -= ((amount || 10) / 100);
hsl.l = clamp01(hsl.l);
return tinycolor(hsl);
};
tinycolor.complement = function (color) {
var hsl = tinycolor(color).toHsl();
hsl.h = (hsl.h + 0.5) % 1;
return tinycolor(hsl);
};
// Combination Functions
// ---------------------
// Thanks to jQuery xColor for some of the ideas behind these
// <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
tinycolor.triad = function (color) {
var hsl = tinycolor(color).toHsl();
var h = hsl.h * 360;
return [
tinycolor(color),
tinycolor({h: (h + 120) % 360, s: hsl.s, l: hsl.l}),
tinycolor({h: (h + 240) % 360, s: hsl.s, l: hsl.l})
];
};
tinycolor.tetrad = function (color) {
var hsl = tinycolor(color).toHsl();
var h = hsl.h * 360;
return [
tinycolor(color),
tinycolor({h: (h + 90) % 360, s: hsl.s, l: hsl.l}),
tinycolor({h: (h + 180) % 360, s: hsl.s, l: hsl.l}),
tinycolor({h: (h + 270) % 360, s: hsl.s, l: hsl.l})
];
};
tinycolor.splitcomplement = function (color) {
var hsl = tinycolor(color).toHsl();
var h = hsl.h * 360;
return [
tinycolor(color),
tinycolor({h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
tinycolor({h: (h + 216) % 360, s: hsl.s, l: hsl.l})
];
};
tinycolor.analogous = function (color, results, slices) {
results = results || 6;
slices = slices || 30;
var hsl = tinycolor(color).toHsl();
var part = 360 / slices;
var ret = [tinycolor(color)];
hsl.h *= 360;
for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results;) {
hsl.h = (hsl.h + part) % 360;
ret.push(tinycolor(hsl));
}
return ret;
};
tinycolor.monochromatic = function (color, results) {
results = results || 6;
var hsv = tinycolor(color).toHsv();
var h = hsv.h, s = hsv.s, v = hsv.v;
var ret = [];
var modification = 1 / results;
while (results--) {
ret.push(tinycolor({h: h, s: s, v: v}));
v = (v + modification) % 1;
}
return ret;
};
tinycolor.readable = function (color1, color2) {
var a = tinycolor(color1).toRgb(), b = tinycolor(color2).toRgb();
return (
(b.r - a.r) * (b.r - a.r) +
(b.g - a.g) * (b.g - a.g) +
(b.b - a.b) * (b.b - a.b)
) > 0x28A4;
};
// Big List of Colors
// ---------
// <http://www.w3.org/TR/css3-color/#svg-color>
var names = tinycolor.names = {
aliceblue: "f0f8ff",
antiquewhite: "faebd7",
aqua: "0ff",
aquamarine: "7fffd4",
azure: "f0ffff",
beige: "f5f5dc",
bisque: "ffe4c4",
black: "000",
blanchedalmond: "ffebcd",
blue: "00f",
blueviolet: "8a2be2",
brown: "a52a2a",
burlywood: "deb887",
burntsienna: "ea7e5d",
cadetblue: "5f9ea0",
chartreuse: "7fff00",
chocolate: "d2691e",
coral: "ff7f50",
cornflowerblue: "6495ed",
cornsilk: "fff8dc",
crimson: "dc143c",
cyan: "0ff",
darkblue: "00008b",
darkcyan: "008b8b",
darkgoldenrod: "b8860b",
darkgray: "a9a9a9",
darkgreen: "006400",
darkgrey: "a9a9a9",
darkkhaki: "bdb76b",
darkmagenta: "8b008b",
darkolivegreen: "556b2f",
darkorange: "ff8c00",
darkorchid: "9932cc",
darkred: "8b0000",
darksalmon: "e9967a",
darkseagreen: "8fbc8f",
darkslateblue: "483d8b",
darkslategray: "2f4f4f",
darkslategrey: "2f4f4f",
darkturquoise: "00ced1",
darkviolet: "9400d3",
deeppink: "ff1493",
deepskyblue: "00bfff",
dimgray: "696969",
dimgrey: "696969",
dodgerblue: "1e90ff",
firebrick: "b22222",
floralwhite: "fffaf0",
forestgreen: "228b22",
fuchsia: "f0f",
gainsboro: "dcdcdc",
ghostwhite: "f8f8ff",
gold: "ffd700",
goldenrod: "daa520",
gray: "808080",
green: "008000",
greenyellow: "adff2f",
grey: "808080",
honeydew: "f0fff0",
hotpink: "ff69b4",
indianred: "cd5c5c",
indigo: "4b0082",
ivory: "fffff0",
khaki: "f0e68c",
lavender: "e6e6fa",
lavenderblush: "fff0f5",
lawngreen: "7cfc00",
lemonchiffon: "fffacd",
lightblue: "add8e6",
lightcoral: "f08080",
lightcyan: "e0ffff",
lightgoldenrodyellow: "fafad2",
lightgray: "d3d3d3",
lightgreen: "90ee90",
lightgrey: "d3d3d3",
lightpink: "ffb6c1",
lightsalmon: "ffa07a",
lightseagreen: "20b2aa",
lightskyblue: "87cefa",
lightslategray: "789",
lightslategrey: "789",
lightsteelblue: "b0c4de",
lightyellow: "ffffe0",
lime: "0f0",
limegreen: "32cd32",
linen: "faf0e6",
magenta: "f0f",
maroon: "800000",
mediumaquamarine: "66cdaa",
mediumblue: "0000cd",
mediumorchid: "ba55d3",
mediumpurple: "9370db",
mediumseagreen: "3cb371",
mediumslateblue: "7b68ee",
mediumspringgreen: "00fa9a",
mediumturquoise: "48d1cc",
mediumvioletred: "c71585",
midnightblue: "191970",
mintcream: "f5fffa",
mistyrose: "ffe4e1",
moccasin: "ffe4b5",
navajowhite: "ffdead",
navy: "000080",
oldlace: "fdf5e6",
olive: "808000",
olivedrab: "6b8e23",
orange: "ffa500",
orangered: "ff4500",
orchid: "da70d6",
palegoldenrod: "eee8aa",
palegreen: "98fb98",
paleturquoise: "afeeee",
palevioletred: "db7093",
papayawhip: "ffefd5",
peachpuff: "ffdab9",
peru: "cd853f",
pink: "ffc0cb",
plum: "dda0dd",
powderblue: "b0e0e6",
purple: "800080",
red: "f00",
rosybrown: "bc8f8f",
royalblue: "4169e1",
saddlebrown: "8b4513",
salmon: "fa8072",
sandybrown: "f4a460",
seagreen: "2e8b57",
seashell: "fff5ee",
sienna: "a0522d",
silver: "c0c0c0",
skyblue: "87ceeb",
slateblue: "6a5acd",
slategray: "708090",
slategrey: "708090",
snow: "fffafa",
springgreen: "00ff7f",
steelblue: "4682b4",
tan: "d2b48c",
teal: "008080",
thistle: "d8bfd8",
tomato: "ff6347",
turquoise: "40e0d0",
violet: "ee82ee",
wheat: "f5deb3",
white: "fff",
whitesmoke: "f5f5f5",
yellow: "ff0",
yellowgreen: "9acd32"
};
// Make it easy to access colors via `hexNames[hex]`
var hexNames = tinycolor.hexNames = flip(names);
// Utilities
// ---------
// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
function flip(o) {
var flipped = {};
for (var i in o) {
if (o.hasOwnProperty(i)) {
flipped[o[i]] = i;
}
}
return flipped;
}
// Take input from [0, n] and return it as [0, 1]
function bound01(n, max) {
if (isOnePointZero(n)) {
n = "100%";
}
var processPercent = isPercentage(n);
n = mathMin(max, mathMax(0, parseFloat(n)));
// Automatically convert percentage into number
if (processPercent) {
n = n * (max / 100);
}
// Handle floating point rounding errors
if (math.abs(n - max) < 0.000001) {
return 1;
}
else if (n >= 1) {
return (n % max) / parseFloat(max);
}
return n;
}
// Force a number between 0 and 1
function clamp01(val) {
return mathMin(1, mathMax(0, val));
}
// Parse an integer into hex
function parseHex(val) {
return parseInt(val, 16);
}
// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
// <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
function isOnePointZero(n) {
return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
}
// Check to see if string passed in is a percentage
function isPercentage(n) {
return typeof n === "string" && n.indexOf('%') != -1;
}
// Force a hex value to have 2 characters
function pad2(c) {
return c.length == 1 ? '0' + c : '' + c;
}
var matchers = (function () {
// <http://www.w3.org/TR/css3-values/#integers>
var CSS_INTEGER = "[-\\+]?\\d+%?";
// <http://www.w3.org/TR/css3-values/#number-value>
var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
// Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
// Actual matching.
// Parentheses and commas are optional, but not required.
// Whitespace can take the place of commas or opening paren
var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
return {
rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
};
})();
// `stringInputToObject`
// Permissive string parsing. Take in a number of formats, and output an object
// based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
function stringInputToObject(color) {
color = color.replace(trimLeft, '').replace(trimRight, '').toLowerCase();
var named = false;
if (names[color]) {
color = names[color];
named = true;
}
else if (color == 'transparent') {
return {r: 0, g: 0, b: 0, a: 0};
}
// Try to match string input using regular expressions.
// Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
// Just return an object and let the conversion functions handle that.
// This way the result will be the same whether the tinycolor is initialized with string or object.
var match;
if ((match = matchers.rgb.exec(color))) {
return {r: match[1], g: match[2], b: match[3]};
}
if ((match = matchers.rgba.exec(color))) {
return {r: match[1], g: match[2], b: match[3], a: match[4]};
}
if ((match = matchers.hsl.exec(color))) {
return {h: match[1], s: match[2], l: match[3]};
}
if ((match = matchers.hsla.exec(color))) {
return {h: match[1], s: match[2], l: match[3], a: match[4]};
}
if ((match = matchers.hsv.exec(color))) {
return {h: match[1], s: match[2], v: match[3]};
}
if ((match = matchers.hex6.exec(color))) {
return {
r: parseHex(match[1]),
g: parseHex(match[2]),
b: parseHex(match[3]),
format: named ? "name" : "hex"
};
}
if ((match = matchers.hex8.exec(color))) {
return {
r: parseHex(match[1]),
g: parseHex(match[2]),
b: parseHex(match[3]),
a: parseHex(match[4]) / 255,
format: named ? "name" : "hex"
};
}
if ((match = matchers.hex3.exec(color))) {
return {
r: parseHex(match[1] + '' + match[1]),
g: parseHex(match[2] + '' + match[2]),
b: parseHex(match[3] + '' + match[3]),
format: named ? "name" : "hex"
};
}
return false;
}
// Everything is ready, expose to window
//tinycolor;
})();
return $.fn.n2spectrum;
});
N2D('ExpertMode', function ($, undefined) {
/**
* @param allowed
* @constructor
*/
function ExpertMode(allowed) {
this.app = 'system';
this.key = 'IsExpert';
this.isExpert = 0;
this.style = $('<div style="display: none;"></div>').appendTo('body');
if (!allowed) {
this.switches = $();
this.disable(false);
} else {
this.switches = $('.n2-expert-switch')
.on({
mousedown: $.proxy(N2Classes.WindowManager.setMouseDownArea, null, 'expertClicked'),
click: $.proxy(this.switchExpert, this, true)
});
this.load();
if (!this.isExpert) {
this.disable(false);
}
$.jStorage.listenKeyChange(this.app + this.key, $.proxy(this.load, this));
}
}
ExpertMode.prototype.load = function () {
var isExpert = parseInt($.jStorage.get(this.app + this.key, 0));
if (isExpert != this.isExpert) {
this.switchExpert(false, false);
}
};
ExpertMode.prototype.set = function (value, needSet) {
this.isExpert = value;
if (needSet) {
$.jStorage.set(this.app + this.key, value);
}
};
ExpertMode.prototype.switchExpert = function (needSet, e) {
if (e) {
e.preventDefault();
}
if (!this.isExpert) {
this.enable(needSet);
} else {
this.disable(needSet);
}
};
ExpertMode.prototype.measureElement = function () {
var el = null,
scrollTop = $(window).scrollTop(),
cutoff = scrollTop + 62,
cutoffBottom = scrollTop + $(window).height() - 100;
$('.n2-content-area > .n2-heading-bar,.n2-content-area > .n2-form-tab ,#n2-admin .n2-content-area form > .n2-form > .n2-form-tab').each(function () {
var $el = $(this);
if ($el.offset().top > cutoff) {
if (!$el.hasClass('n2-heading-bar')) {
el = $el;
}
return false;
} else if ($el.offset().top + $el.height() > cutoffBottom) {
if (!$el.hasClass('n2-heading-bar')) {
el = $el;
}
return false;
}
});
this.measuredElement = el;
};
ExpertMode.prototype.scrollToMeasured = function () {
if (this.measuredElement !== null) {
while (this.measuredElement.length && !this.measuredElement.is(':VISIBLE')) {
this.measuredElement = this.measuredElement.prev();
}
if (this.measuredElement.length != 0) {
$('html,body').scrollTop(this.measuredElement.offset().top - 102);
}
}
};
ExpertMode.prototype.enable = function (needSet) {
this.measureElement();
this.changeStyle('');
this.set(1, needSet);
this.switches.addClass('n2-active');
$('html').addClass('n2-in-expert');
if (needSet) {
this.scrollToMeasured();
}
};
ExpertMode.prototype.disable = function (needSet) {
this.measureElement();
this.changeStyle('.n2-expert{display: none !important;}');
this.set(0, needSet);
this.switches.removeClass('n2-active');
$('html').removeClass('n2-in-expert');
if (needSet) {
this.scrollToMeasured();
}
};
ExpertMode.prototype.changeStyle = function (style) {
this.style.html('<style type="text/css">' + style + '</style>');
};
return function (app, allowed) {
return new ExpertMode(app, allowed);
}
});
N2D('Form', function ($, undefined) {
$(window).ready(function () {
$('input[data-disabled]').on('focus', function () {
this.blur();
});
});
var registeredBeforeUnload = false;
/**
* @memberOf N2Classes
*
* @param id
* @param url
* @param values
* @constructor
*/
function Form(id, url, values) {
this.form = $('#' + id)
.on('saved', $.proxy(this.updateSerializedData, this))
.data('form', this);
this.updateSerializedData();
this.url = url;
this.values = values;
// Special fix for Joomla 1.6, 1.7 & 2.5. Speedy save!
if (typeof document.formvalidator !== "undefined") {
document.formvalidator.isValid = function () {
return true;
};
}
$(window).on('n2-before-unload', $.proxy(this.onBeforeUnload, this));
this.registerBeforeUnload();
$('input, textarea').on('keyup', function (e) {
if (e.which === 27) {
e.target.blur();
e.stopPropagation();
}
});
}
Form.prototype.registerBeforeUnload = function () {
if (!registeredBeforeUnload) {
$(window).on('beforeunload', function (e) {
if (nextend.askToSave && registeredBeforeUnload + 180000 < $.now()) {
var data = {
changed: false
};
$(window).triggerHandler('n2-before-unload', data);
if (data.changed) {
var confirmationMessage = n2_('The changes you made will be lost if you navigate away from this page.');
(e || window.event).returnValue = confirmationMessage;
return confirmationMessage;
}
}
});
registeredBeforeUnload = $.now();
}
};
Form.prototype.onBeforeUnload = function (e, data) {
if (!data.changed && this.isChanged()) {
data.changed = true;
}
};
Form.prototype.isChanged = function () {
this.form.triggerHandler('checkChanged');
return this.serialized != this.form.serialize();
};
Form.prototype.updateSerializedData = function () {
this.serialized = this.form.serialize();
};
Form.submit = function (query) {
nextend.askToSave = false;
setTimeout(function () {
$(query).submit();
}, 300);
return false;
};
return Form;
});
N2D('FormElement', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @constructor
*/
function FormElement() {
this.connectedField = null;
this.element.data('field', this);
}
FormElement.prototype.triggerOutsideChange = function () {
this.element.triggerHandler('outsideChange', this);
this.element.triggerHandler('nextendChange', this);
};
FormElement.prototype.triggerInsideChange = function () {
this.element.triggerHandler('insideChange', this);
this.element.triggerHandler('nextendChange', this);
};
FormElement.prototype.focus = function (shouldOpen) {
if (this.connectedField) {
this.connectedField.focus(shouldOpen);
}
};
return FormElement;
});
N2D('FormElementText', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @constructor
*/
function FormElementText(id) {
this.element = $('#' + id).on({
focus: $.proxy(this._focus, this),
blur: $.proxy(this._blur, this),
change: $.proxy(this.change, this)
});
this.tagName = this.element.prop('tagName');
this.parent = this.element.parent();
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementText.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementText.prototype.constructor = FormElementText;
FormElementText.prototype._focus = function () {
this.parent.addClass('focus');
if (this.tagName != 'TEXTAREA') {
this.element.on('keypress.n2-text', $.proxy(function (e) {
if (e.which == 13) {
this.element.off('keypress.n2-text');
this.element.trigger('blur');
}
}, this));
}
};
FormElementText.prototype._blur = function () {
this.parent.removeClass('focus');
};
FormElementText.prototype.change = function () {
this.triggerOutsideChange();
};
FormElementText.prototype.insideChange = function (value) {
this.element.val(value);
this.triggerInsideChange();
};
FormElementText.prototype.focus = function (shouldOpen) {
if (this.connectedField) {
this.connectedField.focus(shouldOpen);
} else if (shouldOpen) {
this.element.focus().select();
}
};
return FormElementText;
});
N2D('Notification', function ($, undefined) {
/**
* @alias N2Classes.notification
* @constructor
*/
function Notification() {
/**
* @type {NotificationStack[]}
*/
this.stack = [];
this.tween = null;
N2R('documentReady', $.proxy(function ($) {
var mainTopBar = $('#n2-admin').find('.n2-main-top-bar');
if (mainTopBar.length > 0) {
var stack = new N2Classes.NotificationStack($('#n2-admin').find('.n2-main-top-bar'));
stack.enableStack();
} else {
var stack = new N2Classes.NotificationStackModal($('#n2-admin'));
stack.enableStack();
}
}, this));
}
Notification.prototype.add = function (stack) {
this.stack.push(stack);
};
Notification.prototype.popStack = function () {
this.stack.pop();
};
/**
*
* @returns {NotificationStack}
*/
Notification.prototype.getCurrentStack = function () {
return this.stack[this.stack.length - 1];
};
Notification.prototype.success = function (message, parameters) {
this.getCurrentStack().success(message, parameters);
};
Notification.prototype.error = function (message, parameters) {
this.getCurrentStack().error(message, parameters);
};
Notification.prototype.notice = function (message, parameters) {
this.getCurrentStack().notice(message, parameters);
};
return new Notification();
});
N2D('NotificationStack', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @constructor
*/
function NotificationStack(bar) {
this.messages = [];
this.isShow = false;
this.importantOnly = 0;
this.importantOnlyNode = $('<div class="n2-notification-important n2-h5 ' + (this.importantOnly ? 'n2-active' : '') + '"><span>' + n2_('Show only errors') + '</span><div class="n2-checkbox n2-light"><i class="n2-i n2-i-tick"></i></div></div>')
.on('click', $.proxy(this.changeImportant, this));
$.jStorage.listenKeyChange('ss-important-only', $.proxy(this.importantOnlyChanged, this));
this.importantOnlyChanged();
this._init(bar);
this.emptyMessage = $('<div class="n2-notification-empty n2-h4">' + n2_('There are no messages to display.') + '</div>');
}
NotificationStack.prototype._init = function (bar) {
this.showButton = bar.find('.n2-notification-button')
.on('click', $.proxy(this.hideOrShow, this));
var settings = $('<div class="n2-notification-settings"></div>')
.append($('<div class="n2-button n2-button-normal n2-button-s n2-button-blue n2-radius-s n2-h5 n2-uc n2-notification-clear">' + n2_('Got it!') + '</div>').on('click', $.proxy(this.clear, this)))
.append(this.importantOnlyNode);
this.container = this.messageContainer = $('<div class="n2-notification-center n2-border-radius-br n2-border-radius-bl"></div>')
.append(settings)
.appendTo(bar);
};
NotificationStack.prototype.enableStack = function () {
N2Classes.Notification.add(this);
};
NotificationStack.prototype.popStack = function () {
N2Classes.Notification.popStack();
};
NotificationStack.prototype.hideOrShow = function (e) {
e.preventDefault();
if (this.isShow) {
this.hide()
} else {
this.show();
}
};
NotificationStack.prototype.show = function () {
if (!this.isShow) {
this.isShow = true;
if (this.messages.length == 0) {
this.showEmptyMessage();
}
if (this.showButton) {
this.showButton.addClass('n2-active');
}
this.container.addClass('n2-active');
this.container.css('display', 'block');
this._animateShow();
}
};
NotificationStack.prototype.hide = function () {
if (this.isShow) {
if (this.showButton) {
this.showButton.removeClass('n2-active');
}
this.container.removeClass('n2-active');
this._animateHide();
this.container.css('display', 'none');
this.isShow = false;
}
};
NotificationStack.prototype._animateShow = function () {
if (this.tween) {
this.tween.pause();
}
this.tween = NextendTween.fromTo(this.container, 0.4, {
opacity: 0
}, {
opacity: 1
});
};
NotificationStack.prototype._animateHide = function () {
if (this.tween) {
this.tween.pause();
}
};
NotificationStack.prototype.success = function (message, parameters) {
this._message('success', n2_('success'), message, parameters);
};
NotificationStack.prototype.error = function (message, parameters) {
this._message('error', n2_('error'), message, parameters);
};
NotificationStack.prototype.notice = function (message, parameters) {
this._message('notice', n2_('notice'), message, parameters);
};
NotificationStack.prototype._message = function (type, label, message, parameters) {
this.hideEmptyMessage();
parameters = $.extend({
timeout: false,
remove: false
}, parameters);
var messageNode = $('<div></div>');
if (parameters.timeout) {
setTimeout($.proxy(function () {
this.hideMessage(messageNode, parameters.remove);
}, this), parameters.timeout * 1000);
}
messageNode
.addClass('n2-table n2-table-fixed n2-h3 n2-border-radius n2-notification-message n2-notification-message-' + type)
.append($('<div class="n2-tr"></div>')
.append('<div class="n2-td n2-first"><i class="n2-i n2-i-n-' + type + '"/></div>')
.append('<div class="n2-td n2-message"><h4 class="n2-h4 n2-uc">' + label + '</h4><p class="n2-h4">' + message + '</p></div>'))
.prependTo(this.messageContainer);
this.messages.push(messageNode);
if (this.messages.length > 3) {
this.messages.shift().remove();
}
if (!this.importantOnly || type == 'error' || type == 'notice') {
this.show();
}
return messageNode;
};
NotificationStack.prototype.hideMessage = function (message, remove) {
if (remove) {
this.deleteMessage(message);
} else {
this.hide();
}
};
NotificationStack.prototype.deleteMessage = function (message) {
var index = $.inArray(message, this.messages);
if (index > -1) {
this.messages.splice(index, 1);
message.remove();
}
if (this.messages.length == 0) {
this.hide();
}
};
NotificationStack.prototype.clear = function () {
for (var i = this.messages.length - 1; i >= 0; i--) {
this.messages.pop().remove();
}
this.showEmptyMessage();
this.hide();
};
NotificationStack.prototype.changeImportant = function () {
if (this.importantOnly) {
$.jStorage.set('ss-important-only', 0);
} else {
$.jStorage.set('ss-important-only', 1);
}
};
NotificationStack.prototype.importantOnlyChanged = function () {
this.importantOnly = parseInt($.jStorage.get('ss-important-only', 0));
if (this.importantOnly) {
this.importantOnlyNode.addClass('n2-active');
} else {
this.importantOnlyNode.removeClass('n2-active');
}
};
NotificationStack.prototype.showEmptyMessage = function () {
this.emptyMessage.prependTo(this.container);
};
NotificationStack.prototype.hideEmptyMessage = function () {
this.emptyMessage.detach();
};
return NotificationStack;
});
N2D('NotificationStackModal', ['NotificationStack'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @constructor
* @augments NotificationStack
*/
function NotificationStackModal() {
N2Classes.NotificationStack.prototype.constructor.apply(this, arguments);
}
NotificationStackModal.prototype = Object.create(N2Classes.NotificationStack.prototype);
NotificationStackModal.prototype.constructor = NotificationStackModal;
NotificationStackModal.prototype._init = function (bar) {
var settings = $('<div class="n2-notification-settings"></div>')
.append($('<div class="n2-button n2-button-normal n2-button-s n2-button-blue n2-radius-s n2-h5 n2-uc n2-notification-clear">'+n2_('Got it!')+'</div>').on('click', $.proxy(this.clear, this)))
.append(this.importantOnlyNode);
this.messageContainer = $('<div class="n2-notification-center n2-border-radius"></div>')
.append(settings);
this.container = $('<div class="n2-notification-center-modal"></div>')
.append(this.messageContainer)
.appendTo(bar);
};
NotificationStackModal.prototype.show = function () {
if (document.activeElement) {
document.activeElement.blur();
}
N2Classes.Esc.add($.proxy(function () {
this.clear();
return false;
}, this));
N2Classes.NotificationStack.prototype.show.apply(this, arguments);
};
NotificationStackModal.prototype.hide = function () {
N2Classes.Esc.pop();
N2Classes.NotificationStack.prototype.hide.apply(this, arguments);
};
NotificationStackModal.prototype._animateShow = function () {
};
NotificationStackModal.prototype._animateHide = function () {
};
return NotificationStackModal;
});
N2D('FormElementAutocompleteSimple', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param values
* @constructor
*/
function FormElementAutocompleteSimple(id, values) {
this.element = $('#' + id).data('autocomplete', this);
this.element.nUIAutocomplete({
positionTo: '.n2-form-element-autocomplete',
y: -2,
appendTo: $.proxy(function () {
return this.element.closest('.n2-scrollable, body')
}, this),
source: function () {
return values;
},
select: function (event, ui) {
$(this).val(ui.value).trigger('change');
}
});
}
return FormElementAutocompleteSimple;
});
N2D('FormElementAutocomplete', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param tags
* @constructor
*/
function FormElementAutocomplete(id, tags) {
this.tags = tags;
this.element = $('#' + id).data('autocomplete', this);
this.element.nUIAutocomplete({
positionTo: '.n2-form-element-autocomplete',
y: -2,
appendTo: $.proxy(function () {
return this.element.closest('.n2-scrollable, body')
}, this),
source: $.proxy(function () {
return this.tags;
}, this),
select: function (event, ui) {
var terms = this.value.split(/,/);
terms.pop();
terms.push(ui.value);
terms.push("");
this.value = terms.join(",");
$(this).trigger('change');
}
});
this.element.siblings('.n2-form-element-clear')
.on('click', $.proxy(this.clear, this));
};
FormElementAutocomplete.prototype.clear = function (e) {
e.preventDefault();
e.stopPropagation();
this.element.val('').trigger('change');
};
FormElementAutocomplete.prototype.setTags = function (tags) {
this.tags = tags;
};
return FormElementAutocomplete;
});
N2D('BasicCSSFont', ['BasicCSSSkeleton'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @constructor
*/
function BasicCSSFont() {
this._singular = 'font';
this._prular = 'fonts';
N2Classes.BasicCSSSkeleton.prototype.constructor.apply(this, arguments);
this.form = {
afont: $('#layerfamily'),
color: $('#layercolor'),
size: $('#layersize'),
weight: $('#layerweight'),
lineheight: $('#layerlineheight'),
align: $('#layertextalign'),
underline: $('#layerdecoration'),
italic: $('#layerdecoration')
};
this.loaded();
}
BasicCSSFont.prototype = Object.create(N2Classes.BasicCSSSkeleton.prototype);
BasicCSSFont.prototype.constructor = BasicCSSFont;
BasicCSSFont.prototype.setValue = function (value) {
for (var i = 0; i < value.length; i++) {
if (value[i].bold !== undefined) {
if (value[i].weight !== undefined) {
delete value[i].bold;
} else {
if (value[i].bold == 1) {
value[i].weight = 700;
} else if (value[i].bold > 0) {
value[i].weight = value[i].bold;
}
delete value[i].bold;
}
}
}
this.value = value;
}
BasicCSSFont.prototype._transformsize = function (value) {
return value.split('||').join('|*|');
};
BasicCSSFont.prototype._setsize = function (tab, value) {
tab.size = value.replace('|*|', '||');
};
BasicCSSFont.prototype._transformweight = function (value) {
return parseInt(value);
};
BasicCSSFont.prototype._setweight = function (tab, value) {
tab.weight = parseInt(value);
};
BasicCSSFont.prototype._transformunderline = function (value) {
return [
this.value[this.activeTab].italic == 1 ? 'italic' : '',
value == 1 ? 'underline' : ''
].join('||');
};
BasicCSSFont.prototype._setunderline = function (tab, value) {
var values = value.split('||');
tab.underline = (values[1] == 'underline' ? 1 : 0);
};
BasicCSSFont.prototype._transformitalic = function (value) {
return [
value == 1 ? 'italic' : '',
this.value[this.activeTab].underline == 1 ? 'underline' : ''
].join('||');
};
BasicCSSFont.prototype._setitalic = function (tab, value) {
var values = value.split('||');
tab.italic = (values[0] == 'italic' ? 1 : 0);
};
return BasicCSSFont;
});
N2D('BasicCSSSkeleton', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param manager
* @constructor
*/
function BasicCSSSkeleton(manager) {
this.hasVisuals = false;
this.isInsideChange = false;
this.isReload = false;
this.manager = manager;
this.$container = manager.$container.find('#n2-tab-basiccss' + this._singular);
this.$visuals = this.$container.find('.n2-css-name');
this.$visualsLabel = this.$visuals.find('.n2-css-name-label');
this.$visualsList = this.$visuals.find('.n2-css-name-list');
this.$tabsContainer = this.$container.find('.n2-css-tab');
this.$reset = this.$container.find('.n2-css-tab-reset').on('click', $.proxy(function (e) {
this.value[this.activeTab] = {};
this._lazySave(e);
this.activateTab(this.activeTab);
}, this));
this.$more = this.$container.find('.n2-basiccss-more').on('click', $.proxy(function (e) {
e.preventDefault();
this.visuals[this.activeVisual].field.show(e);
}, this));
this.activeVisual = 0;
this.activeTab = 0;
this.tabs = [];
}
BasicCSSSkeleton.prototype.loaded = function () {
for (var k in this.form) {
this.form[k].on({
nextendChange: $.proxy(this.changeValue, this, k)
});
}
};
BasicCSSSkeleton.prototype.changeValue = function (name, e) {
if (!this.isReload) {
if (typeof this['_set' + name] == 'function') {
this['_set' + name](this.value[this.activeTab], this.form[name].val());
} else {
this.value[this.activeTab][name] = this.form[name].val();
}
this._lazySave(e);
}
};
BasicCSSSkeleton.prototype._lazySave = NextendDeBounce(function (e) {
this.isInsideChange = true;
var value = this.getBase64();
this.visuals[this.activeVisual].field.save(e, value);
this.visuals[this.activeVisual].value = value;
this.isInsideChange = false;
}, 50);
BasicCSSSkeleton.prototype.save = function (data) {
this.isInsideChange = true;
for (var k in data) {
this.visualsByName[k].field.save({}, data[k]);
this.visualsByName[k].value = data[k];
}
this.isInsideChange = false;
};
BasicCSSSkeleton.prototype.getBase64 = function () {
return N2Classes.Base64.encode(JSON.stringify({
name: n2_('Static'),
data: this.value
}));
};
BasicCSSSkeleton.prototype.load = function (values, visuals) {
this.hasVisuals = visuals.length > 0;
this.$container.toggleClass('n2-css-has-' + this._singular, this.hasVisuals);
if (this.hasVisuals) {
this.visuals = [];
this.visualsByName = {};
this.$visualsList.html('');
this.$visuals.toggleClass('n2-multiple', visuals.length > 1);
for (var i = 0; i < visuals.length; i++) {
var visual = visuals[i];
this.visualsByName[visual.name] = {
value: values[visual.name],
mode: visual.mode,
field: visual.field
};
visual.field.element
.off('.basiccss')
.on('outsideChange.basiccss', $.proxy(this.loadSingleValue, this, i, visual.name));
this.visuals.push(this.visualsByName[visual.name]);
$('<span>' + visual.field.getLabel() + '</span>').on('click', $.proxy(function (i, e) {
this.activateVisual(i);
this.activateTab(0);
}, this, i)).appendTo(this.$visualsList);
}
this.activateVisual(0);
this.activateTab(0);
}
};
BasicCSSSkeleton.prototype.loadSingleValue = function (i, k, e) {
if (!this.isInsideChange) {
this.visuals[i].value = this.visuals[i].field.element.val();
if (this.activeVisual == i) {
this.activateVisual(i);
this.activateTab(this.activeTab);
}
}
};
BasicCSSSkeleton.prototype.activateVisual = function (index) {
this.activeVisual = index;
this.$visualsLabel.html(this.visuals[index].field.getLabel());
nextend[this._singular + 'Manager'].getDataFromController(this.visuals[index].value, {previewMode: this.visuals[index].mode}, $.proxy(function (value, tabs) {
this.setValue(value);
this.setTabs(tabs);
}, this));
};
BasicCSSSkeleton.prototype.setValue = function (value) {
this.value = value;
}
BasicCSSSkeleton.prototype.activateTab = function (index) {
this.isReload = true;
this.activeTab = index;
this.$container.toggleClass('n2-css-show-reset', index != 0);
var value = (index == 0 ? this.value[index] : $.extend({}, this.value[0], this.value[index]));
for (var k in value) {
if (typeof this.form[k] !== 'undefined') {
if (typeof this['_transform' + k] == 'function') {
this.form[k].data('field').insideChange(this['_transform' + k](value[k]));
} else {
this.form[k].data('field').insideChange(value[k]);
}
}
}
this.$tabs.removeClass('n2-active').eq(index).addClass('n2-active');
this.isReload = false;
};
BasicCSSSkeleton.prototype.setTabs = function (tabs) {
this.tabs = tabs;
this.$tabsContainer.html('');
for (var i = 0; i < tabs.length; i++) {
$('<span>' + tabs[i] + '</span>').on('click', $.proxy(function (i, e) {
this.activateTab(i);
}, this, i)).appendTo(this.$tabsContainer);
}
this.$tabs = this.$tabsContainer.find('span');
};
BasicCSSSkeleton.prototype.serialize = function () {
if (this.hasVisuals) {
var serialized = {};
for (var k in this.visualsByName) {
serialized[k] = this.visualsByName[k].value;
}
return serialized;
}
return {};
};
BasicCSSSkeleton.prototype.unSerialize = function (serialized) {
for (var k in serialized) {
if (serialized.hasOwnProperty(k)) {
this.visualsByName[k].field.save({}, serialized[k]);
this.visualsByName[k].value = serialized[k];
}
}
};
return BasicCSSSkeleton;
});
N2D('BasicCSSStyle', ['BasicCSSSkeleton'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @constructor
*/
function BasicCSSStyle() {
this._singular = 'style';
this._prular = 'styles';
N2Classes.BasicCSSSkeleton.prototype.constructor.apply(this, arguments);
this.form = {
backgroundcolor: $('#layerbackgroundcolor'),
opacity: $('#layeropacity'),
padding: $('#layerpadding'),
border: $('#layerborder'),
borderradius: $('#layerborderradius')
};
this.loaded();
}
BasicCSSStyle.prototype = Object.create(N2Classes.BasicCSSSkeleton.prototype);
BasicCSSStyle.prototype.constructor = BasicCSSStyle;
return BasicCSSStyle;
});
N2D('BasicCSS', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param ajaxUrl
* @constructor
*/
function BasicCSS(id, ajaxUrl) {
this.underActivate = false;
this.inPresetList = false;
this.$container = $('#' + id);
this.ajaxUrl = ajaxUrl;
this.throttleSetTimeout = null;
this.throttleExitTimeout = null;
this.storage = {};
this.assets = {
font: new N2Classes.BasicCSSFont(this),
style: new N2Classes.BasicCSSStyle(this)
};
this.$preset = $('<div id="n2-tab-basiccsspreset"><div class="n2-editor-header n2-h2 n2-uc"><span class="n2-css-name n2-css-name-label">' + n2_('Preset') + '</span></div></div>').prependTo(this.$container);
$('<div class="n2-ss-editor-window-notice n2-ss-responsive-helper n2-h5">' + n2_(window.n2_printf('NOTE: Layer design changes apply to each device. Watch <a href="%s" target="_blank">video tutorial</a> to learn responsive tools.', "https://www.youtube.com/watch?v=yGpVsrzwt1U&index=4&list=PLSawiBnEUNfvzcI3pBHs4iKcbtMCQU0dB")) + '</div>').prependTo(this.$container);
var presetRightButtons = $('<div class="n2-ss-button-container"></div>').insertAfter(this.$preset.find('.n2-css-name'));
$('<a class="n2-button n2-button-icon n2-button-s n2-radius-s n2-button-darker n2-h5 n2-uc" href="#" data-n2tip="' + n2_('Reset design to default') + '"><i class="n2-i n2-i-reset2"></i></a>')
.on('click', $.proxy(function (e) {
e.preventDefault();
this.exitPresetList(this.defs, e);
}, this)).appendTo(presetRightButtons);
$('<a class="n2-basiccss-save n2-button n2-button-icon n2-button-s n2-radius-s n2-button-darker n2-h5 n2-uc" href="#" data-n2tip="' + n2_('Save design as new preset') + '"><i class="n2-i n2-i-save"></i></a>')
.on('click', $.proxy(function (e) {
e.preventDefault();
this.saveAsNew();
}, this)).appendTo(presetRightButtons);
this.$presets = $('<div id="n2-tab-basiccsspresets"></div>').appendTo(this.$container);
$('<a class="n2-basiccss-choose n2-button n2-button-icon n2-button-s n2-radius-s n2-button-green n2-h5 n2-uc" data-n2tip="' + n2_('Load design') + '" href="#"><i class="n2-i n2-i-addlayer2"></i></a>')
.on('click', $.proxy(function (e) {
e.preventDefault();
this.showList();
}, this))
.appendTo(presetRightButtons);
$('<a class="n2-basiccss-back n2-button n2-button-icon n2-button-s n2-radius-s n2-button-grey n2-h5 n2-uc" href="#"><i class="n2-i n2-i-closewindow"></i></a>')
.on('click', $.proxy(function (e) {
e.preventDefault();
this.exitPresetList(false, e);
}, this))
.appendTo(presetRightButtons);
nextend.basicCSS = this;
}
BasicCSS.prototype.showList = function () {
this.inPresetList = true;
this.lastState = this.serialize();
$.when(this.loadType()).done($.proxy(function (data) {
this.$presets.append(this.storage[this.type]);
this.$container.addClass('n2-basiccss-show-preset-list');
}, this));
this.$presets.on('mouseleave', $.proxy(function () {
this.throttledUnSerialize(this.lastState);
}, this));
};
BasicCSS.prototype.activate = function (type, values, structure) {
if (this.inPresetList) {
this.exitPresetList(false);
}
this.underActivate = true;
if (this.type && this.type !== type && typeof this.storage[this.type] !== 'undefined') {
this.storage[this.type].detach();
}
var hasVisuals = false;
this.defs = {
font: [],
style: []
};
this.type = type;
for (var k in this.assets) {
for (var i = 0; i < structure[k].length; i++) {
this.defs[k][structure[k][i].name] = structure[k][i].def;
}
this.assets[k].load(values, structure[k]);
hasVisuals = hasVisuals || this.assets[k].hasVisuals;
}
$('#n2-ss-layer-window').toggleClass('n2-ss-has-design-option', hasVisuals);
if (!hasVisuals) {
if ($('#n2-ss-layer-window .n2-sidebar-tab-switcher .n2-td[data-tab="style"]').hasClass('n2-active')) {
$('#n2-ss-layer-window .n2-sidebar-tab-switcher .n2-td[data-tab="item"]').trigger('click');
}
}
this.underActivate = false;
};
BasicCSS.prototype.deActivate = function () {
if (this.inPresetList) {
this.exitPresetList(false);
}
};
BasicCSS.prototype.serialize = function () {
var serialized = {};
for (var k in this.assets) {
serialized[k] = this.assets[k].serialize();
}
return serialized;
};
BasicCSS.prototype.unSerialize = function (serialized) {
for (var k in this.assets) {
this.assets[k].unSerialize(serialized[k]);
}
};
BasicCSS.prototype.throttledUnSerialize = function (serialized) {
this._addThrottledRenderTimeout($.proxy(this.unSerialize, this, serialized));
};
BasicCSS.prototype.saveAsNew = function (name) {
if (typeof this.saveAsModal == 'undefined') {
var that = this;
this.saveAsModal = new N2Classes.NextendModal({
zero: {
size: [
500,
220
],
title: n2_('Save as'),
close: true,
content: '<form class="n2-form"></form>',
controls: ['<a href="#" class="n2-button n2-button-normal n2-button-l n2-radius-s n2-button-green n2-uc n2-h4">' + n2_('Save as new') + '</a>'],
fn: {
show: function () {
var button = this.controls.find('.n2-button'),
form = this.content.find('.n2-form').on('submit', function (e) {
e.preventDefault();
button.trigger('click');
}).append(this.createInput(n2_('Name'), 'n2-visual-name', 'width: 446px;')),
nameField = this.content.find('#n2-visual-name').focus();
button.on('click', $.proxy(function (e) {
e.preventDefault();
var name = nameField.val();
if (name == '') {
N2Classes.Notification.error(n2_('Please fill the name field!'));
} else {
N2Classes.AjaxHelper.ajax({
type: "POST",
url: N2Classes.AjaxHelper.makeAjaxUrl(that.ajaxUrl, {
nextendaction: 'addVisual'
}),
data: {
type: that.type,
value: N2Classes.Base64.encode(JSON.stringify({
name: name,
data: that.serialize()
}))
},
dataType: 'json'
})
.done($.proxy(function (response) {
$.when(that.loadType()).done(function () {
that.addVisual(response.data.visual).prependTo(that.storage[that.type]);
});
this.hide(e);
}, this));
}
}, this));
}
}
}
}, false);
}
this.saveAsModal.show();
};
BasicCSS.prototype.loadType = function () {
if (typeof this.storage[this.type] === 'undefined') {
var deferred = $.Deferred(),
parseVisuals = $.proxy(function (visuals) {
this.storage[this.type] = $('<ul class="n2-list n2-h4"></ul>');
for (var i = 0; i < visuals.length; i++) {
this.addVisual(visuals[i]);
}
deferred.resolve();
}, this);
if (typeof window[this.type] === 'undefined') {
this.storage[this.type] = deferred;
N2Classes.AjaxHelper.ajax({
type: "POST",
url: N2Classes.AjaxHelper.makeAjaxUrl(this.ajaxUrl, {
nextendaction: 'loadVisuals'
}),
data: {
type: this.type
},
dataType: 'json'
}).done($.proxy(function (response) {
parseVisuals(response.data.visuals);
}, this));
} else {
parseVisuals(window[this.type]);
}
}
return this.storage[this.type];
};
/**
* loadType must be called for the actual type to be able to add visual!!!
* @param visual
* @returns {*}
*/
BasicCSS.prototype.addVisual = function (visual) {
var decoded = visual.value;
if (decoded[0] != '{') {
decoded = N2Classes.Base64.decode(decoded)
}
var value = JSON.parse(decoded),
row = $('<li><a href="#">' + value.name + '</a></li>').on({
mouseenter: $.proxy(function (value, e) {
this.throttledUnSerialize(value.data);
}, this, value),
click: $.proxy(function (data, e) {
e.preventDefault();
this.exitPresetList(data, e);
}, this, value.data)
}).appendTo(this.storage[this.type]);
if (visual.id > 10000) {
var actions = $('<span class="n2-actions"></span>').appendTo(row);
$('<div class="n2-button n2-button-icon n2-button-s" data-n2tip="Overwrite preset"><i class="n2-i n2-i-save n2-i-grey-opacity"></i></div>').on('click', $.proxy(function (visualID, name, e) {
e.stopPropagation();
N2Classes.AjaxHelper.ajax({
type: "POST",
url: N2Classes.AjaxHelper.makeAjaxUrl(this.ajaxUrl, {
nextendaction: 'changeVisual'
}),
data: {
visualId: visualID,
value: N2Classes.Base64.encode(JSON.stringify({
name: name,
data: this.lastState
})),
type: this.type
},
dataType: 'json'
}).done($.proxy(function (response) {
row.replaceWith(this.addVisual(response.data.visual));
}, this));
}, this, visual.id, value.name)).appendTo(actions);
$('<div class="n2-button n2-button-icon n2-button-s"><i class="n2-i n2-i-delete n2-i-grey-opacity"></i></div>').on('click', $.proxy(function (visualID, e) {
e.preventDefault();
e.stopPropagation();
N2Classes.AjaxHelper.ajax({
type: "POST",
url: N2Classes.AjaxHelper.makeAjaxUrl(this.ajaxUrl, {
nextendaction: 'deleteVisual'
}),
data: {
visualId: visualID,
type: this.type
},
dataType: 'json'
}).done($.proxy(function (response) {
row.remove();
}, this));
}, this, visual.id)).appendTo(actions);
nextend.tooltip.add(actions);
}
return row;
};
BasicCSS.prototype.exitPresetList = function (data, e) {
if (this.throttleSetTimeout) {
clearTimeout(this.throttleSetTimeout);
}
this.$presets.off('mouseleave');
if (data) {
this.inPresetList = false;
this.unSerialize(data);
} else {
this.unSerialize(this.lastState);
}
this.$container.removeClass('n2-basiccss-show-preset-list');
this.inPresetList = false;
};
BasicCSS.prototype._addThrottledRenderTimeout = function (cb) {
if (this.throttleSetTimeout) {
clearTimeout(this.throttleSetTimeout);
}
this.throttleSetTimeout = setTimeout(cb, 100);
};
BasicCSS.prototype._addThrottledExitTimeout = function (cb) {
if (this.throttleExitTimeout) {
clearTimeout(this.throttleExitTimeout);
}
this.throttleExitTimeout = setTimeout(cb, 100);
};
return BasicCSS;
});
N2D('FormElementCheckbox', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param values
* @constructor
*/
function FormElementCheckbox(id, values) {
this.separator = '||';
this.element = $('#' + id);
this.values = values;
this.checkboxes = this.element.parent().find('.n2-checkbox-option');
this.states = this.element.val().split(this.separator);
for (var i = 0; i < this.checkboxes.length; i++) {
if (typeof this.states[i] === 'undefined' || this.states[i] != this.values[i]) {
this.states[i] = '';
}
this.checkboxes.eq(i).on('click', $.proxy(this.switchCheckbox, this, i));
}
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementCheckbox.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementCheckbox.prototype.constructor = FormElementCheckbox;
FormElementCheckbox.prototype.switchCheckbox = function (i) {
if (this.states[i] == this.values[i]) {
this.states[i] = '';
this.setSelected(i, 0);
} else {
this.states[i] = this.values[i];
this.setSelected(i, 1);
}
this.element.val(this.states.join(this.separator));
this.triggerOutsideChange();
};
FormElementCheckbox.prototype.insideChange = function (values) {
var states = values.split(this.separator);
for (var i = 0; i < this.checkboxes.length; i++) {
if (typeof states[i] === 'undefined' || states[i] != this.values[i]) {
this.states[i] = '';
this.setSelected(i, 0);
} else {
this.states[i] = this.values[i];
this.setSelected(i, 1);
}
}
this.element.val(this.states.join(this.separator));
this.triggerInsideChange();
};
FormElementCheckbox.prototype.setSelected = function (i, state) {
if (state) {
this.checkboxes.eq(i)
.addClass('n2-active');
} else {
this.checkboxes.eq(i)
.removeClass('n2-active');
}
};
return FormElementCheckbox;
});
N2D('FormElementColor', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param alpha
* @constructor
*/
function FormElementColor(id, alpha) {
this.element = $('#' + id);
if (alpha == 1) {
this.alpha = true;
} else {
this.alpha = false;
}
this.element.off('change')
.n2spectrum({
showAlpha: this.alpha,
preferredFormat: (this.alpha == 1 ? "hex8" : "hex6"),
showInput: false,
showButtons: false,
move: $.proxy(this.onMove, this),
showSelectionPalette: true,
showPalette: true,
maxSelectionSize: 6,
localStorageKey: 'color',
palette: [
['000000', '55aa39', '357cbd', 'bb4a28', '8757b2', '000000CC'],
['81898d', '5cba3c', '4594e1', 'd85935', '9e74c2', '00000080'],
['ced3d5', '27ae60', '01add3', 'e79d19', 'e264af', 'FFFFFFCC'],
['ffffff', '2ecc71', '00c1c4', 'ecc31f', 'ec87c0', 'FFFFFF80']
]
})
.on('change', $.proxy(this.onChange, this));
this.text = this.element.data('field');
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
};
FormElementColor.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementColor.prototype.constructor = FormElementColor;
FormElementColor.prototype.onMove = function () {
this.element.val(this.getCurrent());
this.triggerOutsideChange();
};
FormElementColor.prototype.onChange = function (e) {
var current = this.getCurrent(),
value = this.element.val();
if (current != value) {
if (value.length > 0 && value.charAt(0) != '{') {
this.element.n2spectrum("set", value);
} else if (value.length === 0) {
// If the field left blank, we need to fix it
value = (this.alpha == 1 ? "00000000" : "000000");
this.element.val(value);
this.element.n2spectrum("set", value);
}
this.triggerInsideChange();
this.triggerOutsideChange();
}
e.stopImmediatePropagation();
};
FormElementColor.prototype.insideChange = function (value) {
this.element.val(value);
this.element.n2spectrum("set", value);
this.triggerInsideChange();
};
FormElementColor.prototype.getCurrent = function () {
if (this.alpha) {
return this.element.n2spectrum("get").toHexString8();
}
return this.element.n2spectrum("get").toHexString(true);
};
return FormElementColor;
});
N2D('FormElementDevice', ['FormElementOnoff'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @constructor
*/
function FormElementDevice(id) {
N2Classes.FormElementOnoff.prototype.constructor.apply(this, arguments);
}
FormElementDevice.prototype = Object.create(N2Classes.FormElementOnoff.prototype);
FormElementDevice.prototype.constructor = FormElementDevice;
FormElementDevice.prototype.detach = function () {
this.onoff.detach();
};
FormElementDevice.prototype.setSelected = function (state) {
if (state) {
this.onoff.addClass('n2-active');
} else {
this.onoff.removeClass('n2-active');
}
};
return FormElementDevice;
});
N2D('FormElementDevices', ['FormElementDevice'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param values
* @constructor
*/
function FormElementDevices(id, values) {
this.$el = $('#' + id).data('field', this);
this.fields = {};
for (var i = 0; i < values.length; i++) {
this.fields[values[i]] = new N2Classes.FormElementDevice(id + '-' + values[i]);
}
}
FormElementDevices.prototype.setAvailableDevices = function (devices) {
for (var k in devices) {
var field = this.fields[k.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()];
if (!devices[k]) {
field.detach();
}
}
this.$el.children().first().addClass('n2-first');
this.$el.children().last().addClass('n2-last');
};
return FormElementDevices;
});
N2D('FormElementFolders', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param parameters
* @constructor
*/
function FormElementFolders(id, parameters) {
this.element = $('#' + id);
this.field = this.element.data('field');
this.parameters = parameters;
this.editButton = $('#' + id + '_edit')
.on('click', $.proxy(this.edit, this));
this.button = $('#' + id + '_button').on('click', $.proxy(this.open, this));
this.element.siblings('.n2-form-element-clear')
.on('click', $.proxy(this.clear, this));
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementFolders.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementFolders.prototype.constructor = FormElementFolders;
FormElementFolders.prototype.clear = function (e) {
e.preventDefault();
e.stopPropagation();
this.val('');
};
FormElementFolders.prototype.val = function (value) {
this.element.val(value);
this.triggerOutsideChange();
};
FormElementFolders.prototype.open = function (e) {
e.preventDefault();
nextend.imageHelper.openFoldersLightbox($.proxy(this.val, this));
};
return FormElementFolders;
});
N2D('FormElementFont', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param parameters
* @constructor
*/
function FormElementFont(id, parameters) {
this.element = $('#' + id);
this.parameters = parameters;
this.defaultSetId = parameters.set;
this.element.parent()
.on('click', $.proxy(this.show, this));
this.element.siblings('.n2-form-element-clear')
.on('click', $.proxy(this.clear, this));
this.name = this.element.siblings('input');
nextend.fontManager.$.on('visualDelete', $.proxy(this.fontDeleted, this));
this.updateName(this.element.val());
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementFont.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementFont.prototype.constructor = FormElementFont;
FormElementFont.prototype.getLabel = function () {
return this.parameters.label;
};
FormElementFont.prototype.show = function (e) {
e.preventDefault();
if (this.parameters.style != '') {
nextend.fontManager.setConnectedStyle(this.parameters.style);
}
if (this.parameters.style2 != '') {
nextend.fontManager.setConnectedStyle2(this.parameters.style2);
}
if (this.defaultSetId) {
nextend.fontManager.changeSetById(this.defaultSetId);
}
nextend.fontManager.show(this.element.val(), $.proxy(this.save, this), {
previewMode: this.parameters.previewmode,
previewHTML: this.parameters.preview
});
};
FormElementFont.prototype.clear = function (e) {
e.preventDefault();
e.stopPropagation();
this.val('');
};
FormElementFont.prototype.save = function (e, value) {
nextend.fontManager.addVisualUsage(this.parameters.previewmode, value, window.nextend.pre);
this.val(value);
};
FormElementFont.prototype.val = function (value) {
this.element.val(value);
this.updateName(value);
this.triggerOutsideChange();
};
FormElementFont.prototype.insideChange = function (value) {
this.element.val(value);
this.updateName(value);
this.triggerInsideChange();
};
FormElementFont.prototype.updateName = function (value) {
$.when(nextend.fontManager.getVisual(value))
.done($.proxy(function (font) {
this.name.val(font.name);
}, this));
};
FormElementFont.prototype.fontDeleted = function (e, id) {
if (id == this.element.val()) {
this.insideChange('');
}
};
FormElementFont.prototype.renderFont = function () {
var font = this.element.val();
nextend.fontManager.addVisualUsage(this.parameters.previewmode, font, '');
return nextend.fontManager.getClass(font, this.parameters.previewmode);
};
return FormElementFont;
});
N2D('FormElementIcon2Manager', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @constructor
*/
function FormElementIcon2Manager(id) {
this.element = $('#' + id);
this.button = $('#' + id + '_edit').on('click', $.proxy(this.openModal, this));
this.preview = this.element.parent().find('.n2-form-element-preview').on('click', $.proxy(this.openModal, this));
this.element.on('nextendChange', $.proxy(this.makePreview, this));
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
this.element.siblings('.n2-form-element-clear')
.on('click', $.proxy(this.clear, this));
}
FormElementIcon2Manager.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementIcon2Manager.prototype.constructor = FormElementIcon2Manager;
FormElementIcon2Manager.prototype.clear = function (e) {
e.preventDefault();
e.stopPropagation();
this.val('');
};
FormElementIcon2Manager.prototype.insideChange = function (value) {
this.element.val(value);
this.triggerInsideChange();
};
FormElementIcon2Manager.prototype.openModal = function (e) {
if (e) e.preventDefault();
N2Classes.Icons.showModal($.proxy(this.setIcon, this), this.element.val());
};
FormElementIcon2Manager.prototype.val = function (value) {
this.element.val(value);
this.triggerOutsideChange();
};
FormElementIcon2Manager.prototype.setIcon = function (value) {
this.val(value);
};
FormElementIcon2Manager.prototype.makePreview = function () {
var iconData = N2Classes.Icons.render(this.element.val());
if (iconData) {
this.preview.html('<i class="n2i ' + iconData.class + '">' + iconData.ligature + '</i>');
} else {
this.preview.html('');
}
};
FormElementIcon2Manager.prototype.focus = function (shouldOpen) {
if (shouldOpen) {
this.openModal();
}
};
return FormElementIcon2Manager;
});
N2D('FormElementIconManager', ['FormElement'], function ($, undefined) {
var modal = null,
callback = function () {
};
function getIconModal() {
if (!modal) {
var content = '';
modal = new N2Classes.NextendModal({
zero: {
size: [
1200,
600
],
title: 'Icons',
back: false,
close: true,
content: content,
fn: {
show: function () {
var icons = this.content.find('.n2-icon');
icons.on('click', $.proxy(function (e) {
var node = $(e.currentTarget).clone(),
svg = node.find('svg');
if (svg[0].hasChildNodes()) {
var children = svg[0].childNodes;
for (var i = 0; i < children.length; i++) {
children[i].setAttribute("data-style", "{style}");
}
}
callback(node.html());
this.hide(e);
}, this));
}
}
}
}, false);
modal.setCustomClass('n2-icons-modal');
}
return modal;
}
/**
* @memberOf N2Classes
*
* @param id
* @constructor
*/
function FormElementIconManager(id) {
this.element = $('#' + id);
this.button = $('#' + id + '_edit').on('click', $.proxy(this.openModal, this));
this.preview = this.element.parent().find('img').on('click', $.proxy(this.openModal, this));
this.element.on('nextendChange', $.proxy(this.makePreview, this));
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementIconManager.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementIconManager.prototype.constructor = FormElementIconManager;
FormElementIconManager.prototype.insideChange = function (value) {
this.element.val(value);
this.triggerInsideChange();
};
FormElementIconManager.prototype.openModal = function (e) {
if (e) e.preventDefault();
callback = $.proxy(this.setIcon, this);
getIconModal().show();
};
FormElementIconManager.prototype.val = function (value) {
this.element.val(value);
this.triggerOutsideChange();
};
FormElementIconManager.prototype.setIcon = function (svg) {
this.val(svg);
};
FormElementIconManager.prototype.makePreview = function () {
this.preview.attr('src', 'data:image/svg+xml;base64,' + N2Classes.Base64.encode(this.element.val()));
};
FormElementIconManager.prototype.focus = function (shouldOpen) {
if (shouldOpen) {
this.openModal();
}
};
function LZWDecompress(compressed) {
"use strict";
// Build the dictionary.
var i,
dictionary = [],
w,
result,
k,
entry = "",
dictSize = 256;
for (i = 0; i < 256; i += 1) {
dictionary[i] = String.fromCharCode(i);
}
w = String.fromCharCode(compressed[0]);
result = w;
for (i = 1; i < compressed.length; i += 1) {
k = compressed[i];
if (dictionary[k]) {
entry = dictionary[k];
} else {
if (k === dictSize) {
entry = w + w.charAt(0);
} else {
return null;
}
}
result += entry;
// Add w+entry[0] to the dictionary.
dictionary[dictSize++] = w + entry.charAt(0);
w = entry;
}
return result;
}
return FormElementIconManager;
});
N2D('FormElementImage', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param parameters
* @constructor
*/
function FormElementImage(id, parameters) {
this.element = $('#' + id);
this.field = this.element.data('field');
this.field.connectedField = this;
this.parameters = parameters;
this.preview = $('#' + id + '_preview')
.on('click', $.proxy(this.open, this));
this.element.on('nextendChange', $.proxy(this.makePreview, this));
this.button = $('#' + id + '_button').on('click', $.proxy(this.open, this));
this.element.siblings('.n2-form-element-clear')
.on('click', $.proxy(this.clear, this));
}
FormElementImage.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementImage.prototype.constructor = FormElementImage;
FormElementImage.prototype.clear = function (e) {
e.preventDefault();
e.stopPropagation();
this.val('');
};
FormElementImage.prototype.val = function (value, meta) {
meta = $.extend({alt: false}, meta);
if (meta.alt && meta.alt !== '' && this.parameters.alt && this.parameters.alt !== '') {
$('#' + this.parameters.alt).val(meta.alt).trigger('change');
}
this.element.val(value);
this.triggerOutsideChange();
};
FormElementImage.prototype.makePreview = function () {
var image = this.element.val();
if (image.substr(0, 1) === '{') {
this.preview.css('background-image', '');
} else {
this.preview.css('background-image', 'url(' + nextend.imageHelper.fixed(image) + ')');
}
};
FormElementImage.prototype.open = function (e) {
if (e) {
e.preventDefault();
}
nextend.imageHelper.openLightbox($.proxy(this.val, this));
};
FormElementImage.prototype.focus = function (shouldOpen) {
if (shouldOpen) {
this.open();
}
};
return FormElementImage;
});
N2D('FormElementImageManager', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param parameters
* @constructor
*/
function FormElementImageManager(id, parameters) {
this.element = $('#' + id);
$('#' + id + '_manage').on('click', $.proxy(this.show, this));
this.parameters = parameters;
this.imageField = this.element.data('field');
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementImageManager.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementImageManager.prototype.constructor = FormElementImageManager;
FormElementImageManager.prototype.show = function (e) {
e.preventDefault();
nextend.imageManager.show(this.element.val(), $.proxy(this.save, this));
};
FormElementImageManager.prototype.save = function () {
};
FormElementImageManager.prototype.insideChange = function (value) {
this.element.val(value);
this.triggerInsideChange();
};
return FormElementImageManager;
});
N2D('FormElementList', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param multiple
* @param relatedFields
* @constructor
*/
function FormElementList(id, multiple, relatedFields, relatedValueFields) {
this.separator = '||';
this.element = $('#' + id).on('change', $.proxy(this.onHiddenChange, this));
this.select = $('#' + id + '_select').on('change', $.proxy(this.onChange, this));
this.multiple = multiple;
this.relatedFields = false;
if (relatedFields !== undefined && relatedFields.length) {
this.relatedFields = $('');
for (var i = 0; i < relatedFields.length; i++) {
this.relatedFields = this.relatedFields.add($('[data-field="' + relatedFields[i] + '"]'));
}
this.relatedFields.toggleClass('n2-hidden', this.isOff(this.element.val()));
}
this.relatedValueFields = false;
if (relatedValueFields !== undefined && relatedValueFields.length) {
var value = this.element.val();
this.relatedValueFields = $('');
for (var i = 0; i < relatedValueFields.length; i++) {
var $field = $('[data-field="' + relatedValueFields[i].field + '"]')
.data('show-values', relatedValueFields[i].values);
$field.toggleClass('n2-hidden', $.inArray(value, relatedValueFields[i].values) === -1);
this.relatedValueFields = this.relatedValueFields.add($field);
}
}
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementList.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementList.prototype.constructor = FormElementList;
FormElementList.prototype.onHiddenChange = function () {
var value = this.element.val();
if (value && value != this.select.val()) {
this.insideChange(value);
}
};
FormElementList.prototype.onChange = function () {
var value = this.select.val();
if (value !== null && typeof value === 'object') {
value = value.join(this.separator);
}
this.setHiddenValue(value);
this.triggerOutsideChange();
};
FormElementList.prototype.insideChange = function (value) {
if (typeof value === 'object') {
this.select.val(value.split(this.separator));
} else {
this.select.val(value);
}
this.setHiddenValue(value);
this.select.val(value);
this.triggerInsideChange();
};
FormElementList.prototype.setHiddenValue = function (value) {
this.element.val(value);
if (this.relatedFields) {
this.relatedFields.toggleClass('n2-hidden', this.isOff(value));
}
if (this.relatedValueFields) {
this.relatedValueFields.each(function () {
var $el = $(this);
$el.toggleClass('n2-hidden', $.inArray(value, $el.data('show-values')) === -1);
});
}
};
FormElementList.prototype.isOff = function (value) {
return value == '' || value == '0' || value == 'off';
};
return FormElementList;
});
N2D('FormElementMarginPadding', ['FormElementMixed'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param elements
* @param separator
* @constructor
*/
function FormElementMarginPadding(id, elements, separator) {
this.linkedValues = false;
N2Classes.FormElementMixed.prototype.constructor.apply(this, arguments);
this.$field = this.element.parent();
this.$field.find('.n2-text-sub-label').on('click', $.proxy(function (e) {
e.preventDefault();
this.linkedValues = !this.linkedValues;
this.$field.toggleClass('n2-values-linked', this.linkedValues);
if (this.linkedValues) {
this.elements[0].trigger('change');
}
}, this));
}
FormElementMarginPadding.prototype = Object.create(N2Classes.FormElementMixed.prototype);
FormElementMarginPadding.prototype.constructor = FormElementMarginPadding;
FormElementMarginPadding.prototype.onFieldChange = function () {
if (this.linkedValues) {
var value = this.elements[0].val();
for (var i = 1; i < 4; i++) {
this.elements[i].data('field').insideChange(value);
}
}
this.element.val(this.getValue());
this.triggerOutsideChange();
};
FormElementMarginPadding.prototype.insideChange = function (value) {
N2Classes.FormElementMixed.prototype.insideChange.apply(this, arguments);
this.linkedValues = true;
var value = this.elements[0].val();
for (var i = 1; i < 4; i++) {
if (value != this.elements[i].val()) {
this.linkedValues = false;
break;
}
}
this.$field.toggleClass('n2-values-linked', this.linkedValues);
};
return FormElementMarginPadding;
});
N2D('FormElementMixed', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param elements
* @param separator
* @constructor
*/
function FormElementMixed(id, elements, separator) {
this.element = $('#' + id);
this.elements = [];
for (var i = 0; i < elements.length; i++) {
this.elements.push($('#' + elements[i])
.on('outsideChange', $.proxy(this.onFieldChange, this)));
}
this.separator = separator;
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementMixed.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementMixed.prototype.constructor = FormElementMixed;
FormElementMixed.prototype.onFieldChange = function () {
this.element.val(this.getValue());
this.triggerOutsideChange();
};
FormElementMixed.prototype.insideChange = function (value) {
this.element.val(value);
var values = value.split(this.separator);
for (var i = 0; i < this.elements.length; i++) {
this.elements[i].data('field').insideChange(values[i]);
}
this.triggerInsideChange();
};
FormElementMixed.prototype.getValue = function () {
var values = [];
for (var i = 0; i < this.elements.length; i++) {
values.push(this.elements[i].val());
}
return values.join(this.separator);
};
return FormElementMixed;
});
N2D('FormElementNumberSlider', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param properties
* @constructor
*/
function FormElementNumberSlider(id, properties) {
this.localChange = false;
this.element = $('#' + id).data('autocomplete', this);
var $parent = this.element.parent().on({
'mouseenter.n2slider': $.proxy(this.startSlider, this, properties)
});
var $units = $parent.siblings('.n2-form-element-units').find('> input');
if (properties.units && $units.length) {
var units = properties.units;
$units.on('nextendChange', $.proxy(function () {
properties.min = units[$units.val() + 'Min'];
properties.max = units[$units.val() + 'SliderMax'];
if (this.slider) {
this.slider.nUISlider("option", "min", properties.min);
this.slider.nUISlider("option", "max", properties.max);
}
}, this));
}
}
FormElementNumberSlider.prototype.startSlider = function (properties, e) {
this.element.parent().off('.n2slider');
if (!this.slider) {
this.slider = $('<div></div>')
.appendTo($('<div class="nui-slider-container"></div>').insertAfter(this.element))
.removeAttr('slide').prop('slide', false).nUISlider($.extend({
start: $.proxy(function () {
this.element.parent().addClass('n2-active');
}, this),
stop: $.proxy(function () {
this.element.parent().removeClass('n2-active');
}, this),
slide: $.proxy(function (e, ui) {
this.localChange = true;
this.element.val(ui.value).trigger('change');
this.localChange = false;
}, this)
}, properties));
if (typeof this.slider[0].slide !== 'undefined') {
this.slider[0].slide = null;
}
this.element.on('nextendChange', $.proxy(function () {
if (!this.localChange) {
var val = this.element.val();
if (val == parseFloat(val)) {
this.slider.nUISlider("option", 'value', parseFloat(this.element.val()));
}
}
}, this));
}
this.slider.nUISlider("option", 'value', parseFloat(this.element.val()));
};
return FormElementNumberSlider;
});
N2D('FormElementNumber', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param min
* @param max
* @param units
* @constructor
*/
function FormElementNumber(id, min, max, units) {
this.min = min;
this.max = max;
this.element = $('#' + id).on({
focus: $.proxy(this._focus, this),
blur: $.proxy(this.blur, this),
change: $.proxy(this.change, this)
});
this.parent = this.element.parent();
var $units = this.parent.siblings('.n2-form-element-units').find('> input');
if (units && $units.length) {
$units.on('nextendChange', $.proxy(function () {
this.min = units[$units.val() + 'Min'];
this.max = units[$units.val() + 'Max'];
}, this));
}
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementNumber.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementNumber.prototype.constructor = FormElementNumber;
FormElementNumber.prototype._focus = function () {
this.parent.addClass('focus');
this.element.on('keypress.n2-text', $.proxy(function (e) {
if (e.which == 13) {
this.element.off('keypress.n2-text');
this.element.trigger('blur');
}
}, this));
};
FormElementNumber.prototype.blur = function () {
this.parent.removeClass('focus');
};
FormElementNumber.prototype.change = function () {
var validated = this.validate(this.element.val());
if (validated === true) {
this.triggerOutsideChange();
} else {
this.element.val(validated).trigger('change');
}
};
FormElementNumber.prototype.insideChange = function (value) {
var validated = this.validate(value);
if (validated === true) {
this.element.val(value);
} else {
this.element.val(validated);
}
this.triggerInsideChange();
};
FormElementNumber.prototype.validate = function (value) {
var validatedValue = parseFloat(value);
if (isNaN(validatedValue)) {
validatedValue = 0;
}
validatedValue = Math.max(this.min, Math.min(this.max, validatedValue));
if (validatedValue != value) {
return validatedValue;
}
return true;
};
return FormElementNumber;
});
N2D('FormElementOnoff', ['FormElement'], function ($, undefined) {
/**
* @typedef {{relatedFields: array, relatedAttribute: string}} options
*/
/**
* @memberOf N2Classes
*
* @param id
* @param isEnable
* @param {options} options
* @constructor
*/
function FormElementOnoff(id, isEnable, options) {
this.element = $('#' + id);
this.isEnable = !!isEnable;
this.relatedFields = $('');
if (options !== undefined) {
if (options.relatedFields !== undefined && options.relatedFields.length) {
for (var i = 0; i < options.relatedFields.length; i++) {
this.relatedFields = this.relatedFields.add($('[data-field="' + options.relatedFields[i] + '"]'));
}
}
if (options.relatedAttribute !== undefined && options.relatedAttribute !== '') {
var $body = $('#n2-admin');
$body.attr('data-' + options.relatedAttribute, this.element.val());
this.element.on('nextendChange', $.proxy(function () {
$body.attr('data-' + options.relatedAttribute, this.element.val());
}, this))
}
}
this.onoff = this.element.parent()
.on('click', $.proxy(this.switch, this));
if (!this.onoff.hasClass('n2-onoff-on')) {
this.relatedFields.toggleClass('n2-hidden', this.isEnable);
} else {
this.relatedFields.toggleClass('n2-hidden', !this.isEnable);
}
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementOnoff.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementOnoff.prototype.constructor = FormElementOnoff;
FormElementOnoff.prototype.switch = function () {
var value = parseInt(this.element.val());
if (value) {
value = 0;
} else {
value = 1;
}
this.element.val(value);
this.setSelected(value);
this.triggerOutsideChange();
};
FormElementOnoff.prototype.insideChange = function (value) {
value = parseInt(value);
this.element.val(value);
this.setSelected(value);
this.triggerInsideChange();
};
FormElementOnoff.prototype.setSelected = function (state) {
if (state) {
this.onoff.addClass('n2-onoff-on');
this.relatedFields.toggleClass('n2-hidden', !this.isEnable);
} else {
this.onoff.removeClass('n2-onoff-on');
this.relatedFields.toggleClass('n2-hidden', this.isEnable);
}
};
return FormElementOnoff;
});
N2D('FormElementRadio', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param values
* @constructor
*/
function FormElementRadio(id, values, relatedFields) {
this.element = $('#' + id);
this.values = values;
this.relatedFields = false;
if (relatedFields !== undefined && relatedFields.length) {
this.relatedFields = $('');
for (var i = 0; i < relatedFields.length; i++) {
this.relatedFields = this.relatedFields.add($('[data-field="' + relatedFields[i] + '"]'));
}
this.relatedFields.toggleClass('n2-hidden', this.isOff(this.element.val()));
}
this.parent = this.element.parent();
this.options = this.parent.find('.n2-radio-option');
for (var i = 0; i < this.options.length; i++) {
this.options.eq(i).on('click', $.proxy(this.click, this));
}
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementRadio.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementRadio.prototype.constructor = FormElementRadio;
FormElementRadio.prototype.click = function (e) {
this.changeSelectedIndex(this.options.index(e.currentTarget));
};
FormElementRadio.prototype.changeSelectedIndex = function (index) {
var value = this.values[index];
this.setValue(value);
this.setSelected(index);
this.triggerOutsideChange();
};
FormElementRadio.prototype.insideChange = function (value, option) {
var index = $.inArray(value, this.values);
if (index == '-1') {
index = this.partialSearch(value);
}
if (index == '-1' && typeof option !== 'undefined') {
index = this.addOption(value, option);
}
if (index != '-1') {
this.setValue(this.values[index]);
this.setSelected(index);
this.triggerInsideChange();
} else {
// It will reset the state if the preferred value not available
this.options.eq(0).trigger('click');
}
};
FormElementRadio.prototype.setSelected = function (index) {
this.options.removeClass('n2-active');
this.options.eq(index).addClass('n2-active');
};
FormElementRadio.prototype.partialSearch = function (text) {
text = text.replace(/^.*[\\\/]/, '');
for (var i = 0; i < this.values.length; i++) {
if (this.values[i].indexOf(text) != -1) return i;
}
return -1;
};
FormElementRadio.prototype.addOption = function (value, option) {
var i = this.values.push(value) - 1;
option.appendTo(this.parent)
.on('click', $.proxy(this.click, this));
this.options = this.options.add(option);
return i;
};
FormElementRadio.prototype.addTabOption = function (value, label) {
var i = this.values.push(value) - 1;
var option = $('<div class="n2-radio-option n2-h4 n2-last">' + label + '</div>')
.insertAfter(this.options.last().removeClass('n2-last'))
.on('click', $.proxy(this.click, this));
this.options = this.options.add(option);
return i;
};
FormElementRadio.prototype.removeTabOption = function (value) {
var i = $.inArray(value, this.values);
var option = this.options.eq(i);
this.options = this.options.not(option);
option.remove();
if (i == 0) {
this.options.eq(0).addClass('n2-first');
}
if (i == this.options.length) {
this.options.eq(this.options.length - 1).addClass('n2-last');
}
this.values.splice(i, 1);
};
FormElementRadio.prototype.moveTab = function (originalIndex, targetIndex) {
};
FormElementRadio.prototype.setValue = function (value) {
this.element.val(value);
if (this.relatedFields) {
this.relatedFields.toggleClass('n2-hidden', this.isOff(value));
}
};
FormElementRadio.prototype.isOff = function (value) {
return value === '' || value === '0' || value === 0 || value === 'off';
};
return FormElementRadio;
});
N2D('FormRelatedFields', function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param relatedFields
* @constructor
*/
function FormRelatedFields(id, relatedFields) {
this.$field = $('#' + id);
this.field = this.$field.data('field');
if (this.field && this.field.relatedFieldsOff !== undefined) {
this.fieldChanged = this.fieldChangedCallback;
} else {
this.fieldChanged = this.fieldChangedSimple;
}
this.$field.on('nextendChange', $.proxy(this.fieldChanged, this))
this.relatedFields = $('');
for (var i = 0; i < relatedFields.length; i++) {
this.relatedFields = this.relatedFields.add($('[data-field="' + relatedFields[i] + '"]'));
}
this.fieldChanged();
}
FormRelatedFields.prototype.fieldChangedSimple = function () {
var value = this.$field.val();
this.relatedFields.toggleClass('n2-hidden', value === '');
};
FormRelatedFields.prototype.fieldChangedCallback = function () {
this.relatedFields.toggleClass('n2-hidden', this.field.relatedFieldsOff());
};
return FormRelatedFields;
});
N2D('FormElementRichText', ['FormElementText'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @constructor
*/
function FormElementRichText(id) {
N2Classes.FormElementText.prototype.constructor.apply(this, arguments);
this.parent.find('.n2-textarea-rich-bold').on('click', $.proxy(this.bold, this));
this.parent.find('.n2-textarea-rich-italic').on('click', $.proxy(this.italic, this));
this.parent.find('.n2-textarea-rich-link').on('click', $.proxy(this.link, this));
}
FormElementRichText.prototype = Object.create(N2Classes.FormElementText.prototype);
FormElementRichText.prototype.constructor = FormElementRichText;
FormElementRichText.prototype.bold = function () {
this.wrapText('<b>', '</b>');
};
FormElementRichText.prototype.italic = function () {
this.wrapText('<i>', '</i>');
};
FormElementRichText.prototype.link = function () {
this.wrapText('<a href="#">', '</a>');
};
FormElementRichText.prototype.list = function () {
this.wrapText('', "\n<ul>\n<li>#1 Item</li>\n<li>#2 Item</li>\n</ul>\n");
};
FormElementRichText.prototype.wrapText = function (openTag, closeTag) {
var textArea = this.element;
var len = textArea.val().length;
var start = textArea[0].selectionStart;
var end = textArea[0].selectionEnd;
var selectedText = textArea.val().substring(start, end);
var replacement = openTag + selectedText + closeTag;
textArea.val(textArea.val().substring(0, start) + replacement + textArea.val().substring(end, len));
this.triggerOutsideChange();
this.element.focus();
};
return FormElementRichText;
});
N2D('FormElementSkin', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param preId
* @param skins
* @param fixedMode
* @constructor
*/
function FormElementSkin(id, preId, skins, fixedMode) {
this.element = $('#' + id);
this.preId = preId;
this.skins = skins;
this.list = this.element.data('field');
this.fixedMode = fixedMode;
this.firstOption = this.list.select.find('option').eq(0);
this.originalText = this.firstOption.text();
this.element.on('nextendChange', $.proxy(this.onSkinSelect, this));
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementSkin.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementSkin.prototype.constructor = FormElementSkin;
FormElementSkin.prototype.onSkinSelect = function () {
var skin = this.element.val();
if (skin != '0') {
skin = this.skins[skin].settings;
for (var k in skin) {
if (skin.hasOwnProperty(k)) {
var el = $('#' + this.preId + k);
if (el.length) {
var field = el.data('field');
field.insideChange(skin[k]);
}
}
}
if (!this.fixedMode) {
this.changeFirstOptionText(n2_('Done'));
this.list.insideChange('0');
setTimeout($.proxy(this.changeFirstOptionText, this, this.originalText), 3000);
}
}
};
FormElementSkin.prototype.changeFirstOptionText = function (text) {
this.firstOption.text(text);
};
FormElementSkin.prototype.insideChange = function (value) {
this.element.val(value);
this.list.select.val(value);
};
return FormElementSkin;
});
N2D('FormElementStyle', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param parameters
* @constructor
*/
function FormElementStyle(id, parameters) {
this.element = $('#' + id);
this.parameters = parameters;
this.defaultSetId = parameters.set;
this.element.parent()
.on('click', $.proxy(this.show, this));
this.element.siblings('.n2-form-element-clear')
.on('click', $.proxy(this.clear, this));
this.name = this.element.siblings('input');
nextend.styleManager.$.on('visualDelete', $.proxy(this.styleDeleted, this));
this.updateName(this.element.val());
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementStyle.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementStyle.prototype.constructor = FormElementStyle;
FormElementStyle.prototype.getLabel = function () {
return this.parameters.label;
};
FormElementStyle.prototype.show = function (e) {
e.preventDefault();
if (this.parameters.font != '') {
nextend.styleManager.setConnectedFont(this.parameters.font);
}
if (this.parameters.font2 != '') {
nextend.styleManager.setConnectedFont2(this.parameters.font2);
}
if (this.parameters.style2 != '') {
nextend.styleManager.setConnectedStyle(this.parameters.style2);
}
if (this.defaultSetId) {
nextend.styleManager.changeSetById(this.defaultSetId);
}
nextend.styleManager.show(this.element.val(), $.proxy(this.save, this), {
previewMode: this.parameters.previewmode,
previewHTML: this.parameters.preview
});
};
FormElementStyle.prototype.clear = function (e) {
e.preventDefault();
e.stopPropagation();
this.val('');
};
FormElementStyle.prototype.save = function (e, value) {
nextend.styleManager.addVisualUsage(this.parameters.previewmode, value, window.nextend.pre);
this.val(value);
};
FormElementStyle.prototype.val = function (value) {
this.element.val(value);
this.updateName(value);
this.triggerOutsideChange();
};
FormElementStyle.prototype.insideChange = function (value) {
this.element.val(value);
this.updateName(value);
this.triggerInsideChange();
};
FormElementStyle.prototype.updateName = function (value) {
$.when(nextend.styleManager.getVisual(value))
.done($.proxy(function (style) {
this.name.val(style.name);
}, this));
};
FormElementStyle.prototype.styleDeleted = function (e, id) {
if (id == this.element.val()) {
this.insideChange('');
}
};
FormElementStyle.prototype.renderStyle = function () {
var style = this.element.val();
nextend.styleManager.addVisualUsage(this.parameters.previewmode, style, '');
return nextend.styleManager.getClass(style, this.parameters.previewmode);
};
return FormElementStyle;
});
N2D('FormElementSubform', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param ajaxUrl
* @param target
* @param tab
* @param originalValue
* @constructor
*/
function FormElementSubform(id, ajaxUrl, target, tab, originalValue) {
this.id = id;
this.ajaxUrl = ajaxUrl;
this.element = $('#' + id);
this.target = $('#' + target);
this.tab = tab;
this.originalValue = originalValue;
this.form = this.element.closest('form').data('form');
this.list = this.element.data('field');
this.element.on('nextendChange', $.proxy(this.loadSubform, this));
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementSubform.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementSubform.prototype.constructor = FormElementSubform;
FormElementSubform.prototype.loadSubform = function () {
var value = this.element.val();
if (value == 'disabled') {
this.target.html('');
} else {
var values = [];
if (value == this.originalValue) {
values = this.form.values;
}
var data = {
values: values,
value: value
};
N2Classes.AjaxHelper.ajax({
type: "POST",
url: N2Classes.AjaxHelper.makeAjaxUrl(this.ajaxUrl),
data: data,
dataType: 'json'
}).done($.proxy(this.load, this));
}
};
FormElementSubform.prototype.load = function (response) {
this.target.html(response.data.html);
eval(response.data.scripts);
nextend.tooltip.add(this.target);
};
return FormElementSubform;
});
N2D('FormElementSubformImage', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param options
* @constructor
*/
function FormElementSubformImage(id, options) {
this.element = $('#' + id);
this.options = $('#' + options).find('.n2-subform-image-option');
this.subform = this.element.data('field');
this.active = this.getIndex(this.options.filter('.n2-active').get(0));
for (var i = 0; i < this.options.length; i++) {
this.options.eq(i).on('click', $.proxy(this.selectOption, this));
}
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementSubformImage.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementSubformImage.prototype.constructor = FormElementSubformImage;
FormElementSubformImage.prototype.selectOption = function (e) {
var index = this.getIndex(e.currentTarget);
if (index != this.active) {
this.options.eq(index).addClass('n2-active');
this.options.eq(this.active).removeClass('n2-active');
this.active = index;
var value = this.subform.list.select.find('option').eq(index).val();
this.subform.list.insideChange(value);
}
};
FormElementSubformImage.prototype.getIndex = function (option) {
return $.inArray(option, this.options);
};
return FormElementSubformImage;
});
N2D('FormElementSwitcher', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param values
* @constructor
*/
function FormElementSwitcher(id, values) {
this.element = $('#' + id);
this.options = this.element.parent().find('.n2-switcher-unit');
this.active = this.options.index(this.options.filter('.n2-active'));
this.values = values;
for (var i = 0; i < this.options.length; i++) {
this.options.eq(i).on('click', $.proxy(this.switch, this, i));
}
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementSwitcher.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementSwitcher.prototype.constructor = FormElementSwitcher;
FormElementSwitcher.prototype.switch = function (i, e) {
this.element.val(this.values[i]);
this.setSelected(i);
this.triggerOutsideChange();
};
FormElementSwitcher.prototype.insideChange = function (value) {
var i = $.inArray(value, this.values);
this.element.val(this.values[i]);
this.setSelected(i);
this.triggerInsideChange();
};
FormElementSwitcher.prototype.setSelected = function (i) {
this.options.eq(this.active).removeClass('n2-active');
this.options.eq(i).addClass('n2-active');
this.active = i;
};
return FormElementSwitcher;
});
N2D('FormElementUnits', ['FormElement'], function ($, undefined) {
/**
* @memberOf N2Classes
*
* @param id
* @param values
* @constructor
*/
function FormElementUnits(id, values) {
this.element = $('#' + id);
this.options = this.element.parent().find('.n2-element-unit');
this.currentUnit = this.element.parent().find('.n2-element-current-unit');
this.values = values;
for (var i = 0; i < this.options.length; i++) {
this.options.eq(i).on('click', $.proxy(this.switch, this, i));
}
N2Classes.FormElement.prototype.constructor.apply(this, arguments);
}
FormElementUnits.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementUnits.prototype.constructor = FormElementUnits;
FormElementUnits.prototype.switch = function (i, e) {
this.element.val(this.values[i]);
this.setSelected(i);
this.triggerOutsideChange();
};
FormElementUnits.prototype.insideChange = function (value) {
var i = $.inArray(value, this.values);
this.element.val(this.values[i]);
this.setSelected(i);
this.triggerInsideChange();
};
FormElementUnits.prototype.setSelected = function (i) {
this.currentUnit.html(this.options.eq(i).html());
};
return FormElementUnits;
});
N2D('FormElementUrl', ['FormElement'], function ($, undefined) {
var ajaxUrl = '',
modal = null,
cache = {},
callback = function (url) {
},
lastValue = '';
/**
* @memberOf N2Classes
*
* @param id
* @param parameters
* @constructor
*/
function FormElementUrl(id, parameters) {
this.element = $('#' + id);
this.field = this.element.data('field');
this.parameters = parameters;
ajaxUrl = this.parameters.url;
this.button = $('#' + id + '_button').on('click', $.proxy(this.open, this));
this.element.siblings('.n2-form-element-clear')
.on('click', $.proxy(this.clear, this));
}
FormElementUrl.prototype = Object.create(N2Classes.FormElement.prototype);
FormElementUrl.prototype.constructor = FormElementUrl;
FormElementUrl.prototype.clear = function (e) {
e.preventDefault();
e.stopPropagation();
this.val('#');
};
FormElementUrl.prototype.val = function (value) {
this.element.val(value);
this.triggerOutsideChange();
};
FormElementUrl.prototype.open = function (e) {
e.preventDefault();
callback = $.proxy(this.insert, this);
lastValue = this.element.val();
this.getModal().show();
};
FormElementUrl.prototype.insert = function (url) {
this.val(url);
};
FormElementUrl.prototype.getModal = function () {
if (!modal) {
var getLinks = function (search) {
if (typeof cache[search] == 'undefined') {
cache[search] = $.ajax({
type: "POST",
url: N2Classes.AjaxHelper.makeAjaxUrl(ajaxUrl),
data: {
keyword: search
},
dataType: 'json'
});
}
return cache[search];
};
var parameters = this.parameters;
var links = {
size: [
600,
500
],
title: n2_('Link'),
back: 'zero',
close: true,
content: '<div class="n2-form"></div>',
fn: {
show: function () {
this.content.find('.n2-form').append(this.createInput(n2_('Keyword'), 'n2-links-keyword', 'width:546px;'));
var search = $('#n2-links-keyword'),
heading = this.createHeading('').appendTo(this.content),
result = this.createResult().appendTo(this.content),
searchString = '';
search.on('keyup', $.proxy(function () {
searchString = search.val();
getLinks(searchString).done($.proxy(function (r) {
if (search.val() == searchString) {
var links = r.data;
if (searchString == '') {
heading.html(n2_('No search term specified. Showing recent items.'));
} else {
heading.html(n2_printf(n2_('Showing items match for "%s"'), searchString));
}
var data = [],
modal = this;
for (var i = 0; i < links.length; i++) {
data.push([links[i].title, links[i].info, $('<div class="n2-button n2-button-normal n2-button-xs n2-radius-s n2-button-green n2-uc n2-h5">' + n2_('Select') + '</div>')
.on('click', {permalink: links[i].link}, function (e) {
callback(e.data.permalink);
modal.hide();
})]);
}
result.html('');
this.createTable(data, ['width:100%;', '', '']).appendTo(this.createTableWrap().appendTo(result));
}
}, this));
}, this))
.trigger('keyup').focus();
this.content.append('<hr style="margin: 0 -20px;"/>');
var external = $('<div class="n2-input-button"><input placeholder="' + n2_("External url") + '" type="text" id="external-url" name="external-url" value="" /><a href="#" class="n2-button n2-button-normal n2-button-l n2-radius-s n2-button-green n2-uc n2-h4">' + n2_("Insert") + '</a></div>')
.css({
display: 'block',
textAlign: 'center'
})
.appendTo(this.content),
externalInput = external.find('input').val(lastValue);
external.find('.n2-button').on('click', function (e) {
e.preventDefault();
callback(externalInput.val());
modal.hide();
});
}
}
};
links.back = false;
modal = new N2Classes.NextendModal({
zero: links
}, false);
modal.setCustomClass('n2-url-modal');
}
return modal;
};
return FormElementUrl;
});
/*! fixto - v0.5.0 - 2016-06-16
* http://github.com/bbarakaci/fixto/*/
N2R('$', function ($) {
// Start Computed Style. Please do not modify this module here. Modify it from its own repo. See address below.
/*! Computed Style - v0.1.0 - 2012-07-19
* https://github.com/bbarakaci/computed-style
* Copyright (c) 2012 Burak Barakaci; Licensed MIT */
var computedStyle = (function () {
var computedStyle = {
getAll: function (element) {
return document.defaultView.getComputedStyle(element);
},
get: function (element, name) {
return this.getAll(element)[name];
},
toFloat: function (value) {
return parseFloat(value, 10) || 0;
},
getFloat: function (element, name) {
return this.toFloat(this.get(element, name));
},
_getAllCurrentStyle: function (element) {
return element.currentStyle;
}
};
if (document.documentElement.currentStyle) {
computedStyle.getAll = computedStyle._getAllCurrentStyle;
}
return computedStyle;
}());
// End Computed Style. Modify whatever you want to.
var mimicNode = (function () {
/*
Class Mimic Node
Dependency : Computed Style
Tries to mimick a dom node taking his styles, dimensions. May go to his repo if gets mature.
*/
function MimicNode(element) {
this.element = element;
this.replacer = document.createElement('div');
this.replacer.style.visibility = 'hidden';
this.hide();
element.parentNode.insertBefore(this.replacer, element);
}
MimicNode.prototype = {
replace: function () {
var rst = this.replacer.style;
var styles = computedStyle.getAll(this.element);
// rst.width = computedStyle.width(this.element) + 'px';
// rst.height = this.element.offsetHeight + 'px';
// Setting offsetWidth
rst.width = this._width();
rst.height = this._height();
// Adopt margins
rst.marginTop = styles.marginTop;
rst.marginBottom = styles.marginBottom;
rst.marginLeft = styles.marginLeft;
rst.marginRight = styles.marginRight;
// Adopt positioning
rst.cssFloat = styles.cssFloat;
rst.styleFloat = styles.styleFloat; //ie8;
rst.position = styles.position;
rst.top = styles.top;
rst.right = styles.right;
rst.bottom = styles.bottom;
rst.left = styles.left;
// rst.borderStyle = styles.borderStyle;
rst.display = styles.display;
},
hide: function () {
this.replacer.style.display = 'none';
},
_width: function () {
return this.element.getBoundingClientRect().width + 'px';
},
_widthOffset: function () {
return this.element.offsetWidth + 'px';
},
_height: function () {
return this.element.getBoundingClientRect().height + 'px';
},
_heightOffset: function () {
return this.element.offsetHeight + 'px';
},
destroy: function () {
$(this.replacer).remove();
// set properties to null to break references
for (var prop in this) {
if (this.hasOwnProperty(prop)) {
this[prop] = null;
}
}
}
};
var bcr = document.documentElement.getBoundingClientRect();
if (!bcr.width) {
MimicNode.prototype._width = MimicNode.prototype._widthOffset;
MimicNode.prototype._height = MimicNode.prototype._heightOffset;
}
return {
MimicNode: MimicNode,
computedStyle: computedStyle
};
}());
// Class handles vendor prefixes
function Prefix() {
// Cached vendor will be stored when it is detected
this._vendor = null;
//this._dummy = document.createElement('div');
}
Prefix.prototype = {
_vendors: {
webkit: {cssPrefix: '-webkit-', jsPrefix: 'Webkit'},
moz: {cssPrefix: '-moz-', jsPrefix: 'Moz'},
ms: {cssPrefix: '-ms-', jsPrefix: 'ms'},
opera: {cssPrefix: '-o-', jsPrefix: 'O'}
},
_prefixJsProperty: function (vendor, prop) {
return vendor.jsPrefix + prop[0].toUpperCase() + prop.substr(1);
},
_prefixValue: function (vendor, value) {
return vendor.cssPrefix + value;
},
_valueSupported: function (prop, value, dummy) {
// IE8 will throw Illegal Argument when you attempt to set a not supported value.
try {
dummy.style[prop] = value;
return dummy.style[prop] === value;
}
catch (er) {
return false;
}
},
/**
* Returns true if the property is supported
* @param {string} prop Property name
* @returns {boolean}
*/
propertySupported: function (prop) {
// Supported property will return either inine style value or an empty string.
// Undefined means property is not supported.
return document.documentElement.style[prop] !== undefined;
},
/**
* Returns prefixed property name for js usage
* @param {string} prop Property name
* @returns {string|null}
*/
getJsProperty: function (prop) {
// Try native property name first.
if (this.propertySupported(prop)) {
return prop;
}
// Prefix it if we know the vendor already
if (this._vendor) {
return this._prefixJsProperty(this._vendor, prop);
}
// We don't know the vendor, try all the possibilities
var prefixed;
for (var vendor in this._vendors) {
prefixed = this._prefixJsProperty(this._vendors[vendor], prop);
if (this.propertySupported(prefixed)) {
// Vendor detected. Cache it.
this._vendor = this._vendors[vendor];
return prefixed;
}
}
// Nothing worked
return null;
},
/**
* Returns supported css value for css property. Could be used to check support or get prefixed value string.
* @param {string} prop Property
* @param {string} value Value name
* @returns {string|null}
*/
getCssValue: function (prop, value) {
// Create dummy element to test value
var dummy = document.createElement('div');
// Get supported property name
var jsProperty = this.getJsProperty(prop);
// Try unprefixed value
if (this._valueSupported(jsProperty, value, dummy)) {
return value;
}
var prefixedValue;
// If we know the vendor already try prefixed value
if (this._vendor) {
prefixedValue = this._prefixValue(this._vendor, value);
if (this._valueSupported(jsProperty, prefixedValue, dummy)) {
return prefixedValue;
}
}
// Try all vendors
for (var vendor in this._vendors) {
prefixedValue = this._prefixValue(this._vendors[vendor], value);
if (this._valueSupported(jsProperty, prefixedValue, dummy)) {
// Vendor detected. Cache it.
this._vendor = this._vendors[vendor];
return prefixedValue;
}
}
// No support for value
return null;
}
};
var prefix = new Prefix();
// We will need this frequently. Lets have it as a global until we encapsulate properly.
var transformJsProperty = prefix.getJsProperty('transform');
// Will hold if browser creates a positioning context for fixed elements.
var fixedPositioningContext;
// Checks if browser creates a positioning context for fixed elements.
// Transform rule will create a positioning context on browsers who follow the spec.
// Ie for example will fix it according to documentElement
// TODO: Other css rules also effects. perspective creates at chrome but not in firefox. transform-style preserve3d effects.
function checkFixedPositioningContextSupport() {
var support = false;
var parent = document.createElement('div');
var child = document.createElement('div');
parent.appendChild(child);
parent.style[transformJsProperty] = 'translate(0)';
// Make sure there is space on top of parent
parent.style.marginTop = '10px';
parent.style.visibility = 'hidden';
child.style.position = 'fixed';
child.style.top = 0;
document.body.appendChild(parent);
var rect = child.getBoundingClientRect();
// If offset top is greater than 0 meand transformed element created a positioning context.
if (rect.top > 0) {
support = true;
}
// Remove dummy content
document.body.removeChild(parent);
return support;
}
// It will return null if position sticky is not supported
var nativeStickyValue = prefix.getCssValue('position', 'sticky');
// It will return null if position fixed is not supported
var fixedPositionValue = prefix.getCssValue('position', 'fixed');
// Dirty business
var ie = navigator.appName === 'Microsoft Internet Explorer';
var ieversion;
if (ie) {
ieversion = parseFloat(navigator.appVersion.split("MSIE")[1]);
}
function FixTo(child, parent, options) {
this.child = child;
this._$child = $(child);
this.parent = parent;
this.options = {
className: 'fixto-fixed',
top: 0,
mindViewport: false
};
this._setOptions(options);
}
FixTo.prototype = {
// Returns the total outerHeight of the elements passed to mind option. Will return 0 if none.
_mindtop: function () {
var top = 0;
if (this._$mind) {
var el;
var rect;
var height;
for (var i = 0, l = this._$mind.length; i < l; i++) {
el = this._$mind[i];
rect = el.getBoundingClientRect();
if (rect.height) {
top += rect.height;
}
else {
var styles = computedStyle.getAll(el);
top += el.offsetHeight + computedStyle.toFloat(styles.marginTop) + computedStyle.toFloat(styles.marginBottom);
}
}
}
return top;
},
// Public method to stop the behaviour of this instance.
stop: function () {
this._stop();
this._running = false;
},
// Public method starts the behaviour of this instance.
start: function () {
// Start only if it is not running not to attach event listeners multiple times.
if (!this._running) {
this._start();
this._running = true;
}
},
//Public method to destroy fixto behaviour
destroy: function () {
this.stop();
this._destroy();
// Remove jquery data from the element
this._$child.removeData('fixto-instance');
// set properties to null to break references
for (var prop in this) {
if (this.hasOwnProperty(prop)) {
this[prop] = null;
}
}
},
_setOptions: function (options) {
$.extend(this.options, options);
if (this.options.mind) {
this._$mind = $(this.options.mind);
}
if (this.options.zIndex) {
this.child.style.zIndex = this.options.zIndex;
}
},
setOptions: function (options) {
this._setOptions(options);
this.refresh();
},
// Methods could be implemented by subclasses
_stop: function () {
},
_start: function () {
},
_destroy: function () {
},
refresh: function () {
}
};
// Class FixToContainer
function FixToContainer(child, parent, options) {
FixTo.call(this, child, parent, options);
this._replacer = new mimicNode.MimicNode(child);
this._ghostNode = this._replacer.replacer;
this._saveStyles();
this._saveViewportHeight();
// Create anonymous functions and keep references to register and unregister events.
this._proxied_onscroll = this._bind(this._onscroll, this);
this._proxied_onresize = this._bind(this._onresize, this);
this.start();
}
FixToContainer.prototype = new FixTo();
$.extend(FixToContainer.prototype, {
// Returns an anonymous function that will call the given function in the given context
_bind: function (fn, context) {
return function () {
return fn.call(context);
};
},
// at ie8 maybe only in vm window resize event fires everytime an element is resized.
_toresize: ieversion === 8 ? document.documentElement : window,
_onscroll: function _onscroll() {
this._scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
this._parentBottom = (this.parent.offsetHeight + this._fullOffset('offsetTop', this.parent));
if (this.options.mindBottomPadding !== false) {
this._parentBottom -= computedStyle.getFloat(this.parent, 'paddingBottom');
}
if (!this.fixed && this._shouldFix()) {
this._fix();
this._adjust();
} else {
if (this._scrollTop > this._parentBottom || this._scrollTop < (this._fullOffset('offsetTop', this._ghostNode) - this.options.top - this._mindtop())) {
this._unfix();
return;
}
this._adjust();
}
},
_shouldFix: function () {
if (this._scrollTop < this._parentBottom && this._scrollTop > (this._fullOffset('offsetTop', this.child) - this.options.top - this._mindtop())) {
if (this.options.mindViewport && !this._isViewportAvailable()) {
return false;
}
return true;
}
},
_isViewportAvailable: function () {
var childStyles = computedStyle.getAll(this.child);
return this._viewportHeight > (this.child.offsetHeight + computedStyle.toFloat(childStyles.marginTop) + computedStyle.toFloat(childStyles.marginBottom));
},
_adjust: function _adjust() {
var top = 0;
var mindTop = this._mindtop();
var diff = 0;
var childStyles = computedStyle.getAll(this.child);
var context = null;
if (fixedPositioningContext) {
// Get positioning context.
context = this._getContext();
if (context) {
// There is a positioning context. Top should be according to the context.
top = Math.abs(context.getBoundingClientRect().top);
}
}
diff = (this._parentBottom - this._scrollTop) - (this.child.offsetHeight + computedStyle.toFloat(childStyles.marginBottom) + mindTop + this.options.top);
if (diff > 0) {
diff = 0;
}
if (this.fixed) {
this.child.style.top = (diff + mindTop + top + this.options.top) - computedStyle.toFloat(childStyles.marginTop) + 'px';
} else {
this.child.style.top = 'auto';
}
},
// Calculate cumulative offset of the element.
// Optionally according to context
_fullOffset: function _fullOffset(offsetName, elm, context) {
var offset = elm[offsetName];
var offsetParent = elm.offsetParent;
// Add offset of the ascendent tree until we reach to the document root or to the given context
while (offsetParent !== null && offsetParent !== context) {
offset = offset + offsetParent[offsetName];
offsetParent = offsetParent.offsetParent;
}
return offset;
},
// Get positioning context of the element.
// We know that the closest parent that a transform rule applied will create a positioning context.
_getContext: function () {
var parent;
var element = this.child;
var context = null;
var styles;
// Climb up the treee until reaching the context
while (!context) {
parent = element.parentNode;
if (parent === document.documentElement) {
return null;
}
styles = computedStyle.getAll(parent);
// Element has a transform rule
if (styles[transformJsProperty] !== 'none') {
context = parent;
break;
}
element = parent;
}
return context;
},
_fix: function _fix() {
var isRTL = window.n2const.isRTL();
var child = this.child;
var childStyle = child.style;
var childStyles = computedStyle.getAll(child);
var xOffset;
if (isRTL) {
xOffset = document.body.clientWidth - child.getBoundingClientRect().right;
} else {
xOffset = child.getBoundingClientRect().left;
}
var width = childStyles.width;
this._saveStyles();
if (document.documentElement.currentStyle) {
// Function for ie<9. When hasLayout is not triggered in ie7, he will report currentStyle as auto, clientWidth as 0. Thus using offsetWidth.
// Opera also falls here
width = (child.offsetWidth) - (computedStyle.toFloat(childStyles.paddingLeft) + computedStyle.toFloat(childStyles.paddingRight) + computedStyle.toFloat(childStyles.borderLeftWidth) + computedStyle.toFloat(childStyles.borderRightWidth)) + 'px';
}
// Ie still fixes the container according to the viewport.
if (fixedPositioningContext) {
var context = this._getContext();
if (context) {
// There is a positioning context. Left should be according to the context.
if (isRTL) {
xOffset = (document.body.clientWidth - child.getBoundingClientRect().right) - (document.body.clientWidth - context.getBoundingClientRect().right);
} else {
xOffset = child.getBoundingClientRect().left - context.getBoundingClientRect().left;
}
}
}
this._replacer.replace();
if (isRTL) {
childStyle.right = (xOffset - computedStyle.toFloat(childStyles.marginRight)) + 'px';
} else {
childStyle.left = (xOffset - computedStyle.toFloat(childStyles.marginLeft)) + 'px';
}
childStyle.width = width;
childStyle.position = 'fixed';
childStyle.top = this._mindtop() + this.options.top - computedStyle.toFloat(childStyles.marginTop) + 'px';
this._$child.addClass(this.options.className);
this.fixed = true;
},
_unfix: function _unfix() {
var childStyle = this.child.style;
this._replacer.hide();
childStyle.position = this._childOriginalPosition;
childStyle.top = this._childOriginalTop;
childStyle.width = this._childOriginalWidth;
if (window.n2const.isRTL()) {
childStyle.right = this._childOriginalRight;
} else {
childStyle.left = this._childOriginalLeft;
}
this._$child.removeClass(this.options.className);
this.fixed = false;
},
_saveStyles: function () {
var childStyle = this.child.style;
this._childOriginalPosition = childStyle.position;
this._childOriginalTop = childStyle.top;
this._childOriginalWidth = childStyle.width;
if (window.n2const.isRTL()) {
this._childOriginalRight = childStyle.right;
} else {
this._childOriginalLeft = childStyle.left;
}
},
_onresize: function () {
this.refresh();
},
_saveViewportHeight: function () {
// ie8 doesn't support innerHeight
this._viewportHeight = window.innerHeight || document.documentElement.clientHeight;
},
_stop: function () {
// Unfix the container immediately.
this._unfix();
// remove event listeners
$(window).unbind('scroll', this._proxied_onscroll);
$(this._toresize).unbind('resize', this._proxied_onresize);
},
_start: function () {
// Trigger onscroll to have the effect immediately.
this._onscroll();
// Attach event listeners
$(window).bind('scroll', this._proxied_onscroll);
$(this._toresize).bind('resize', this._proxied_onresize);
},
_destroy: function () {
// Destroy mimic node instance
this._replacer.destroy();
},
refresh: function () {
this._saveViewportHeight();
this._unfix();
this._onscroll();
}
});
function NativeSticky(child, parent, options) {
FixTo.call(this, child, parent, options);
this.start();
}
NativeSticky.prototype = new FixTo();
$.extend(NativeSticky.prototype, {
_start: function () {
var childStyles = computedStyle.getAll(this.child);
this._childOriginalPosition = childStyles.position;
this._childOriginalTop = childStyles.top;
this.child.style.position = nativeStickyValue;
this.refresh();
},
_stop: function () {
this.child.style.position = this._childOriginalPosition;
this.child.style.top = this._childOriginalTop;
},
refresh: function () {
this.child.style.top = this._mindtop() + this.options.top + 'px';
}
});
var fixTo = function fixTo(childElement, parentElement, options) {
if ((nativeStickyValue && !options) || (nativeStickyValue && options && options.useNativeSticky !== false)) {
// Position sticky supported and user did not disabled the usage of it.
return new NativeSticky(childElement, parentElement, options);
}
else if (fixedPositionValue) {
// Position fixed supported
if (fixedPositioningContext === undefined) {
// We don't know yet if browser creates fixed positioning contexts. Check it.
fixedPositioningContext = checkFixedPositioningContextSupport();
}
return new FixToContainer(childElement, parentElement, options);
}
else {
return 'Neither fixed nor sticky positioning supported';
}
};
/*
No support for ie lt 8
*/
if (ieversion < 8) {
fixTo = function () {
return 'not supported';
};
}
// Let it be a jQuery Plugin
$.fn.fixTo = function (targetSelector, options) {
var $targets = $(targetSelector);
var i = 0;
return this.each(function () {
// Check the data of the element.
var instance = $(this).data('fixto-instance');
// If the element is not bound to an instance, create the instance and save it to elements data.
if (!instance) {
$(this).data('fixto-instance', fixTo(this, $targets[i], options));
}
else {
// If we already have the instance here, expect that targetSelector parameter will be a string
// equal to a public methods name. Run the method on the instance without checking if
// it exists or it is a public method or not. Cause nasty errors when necessary.
var method = targetSelector;
instance[method].call(instance, options);
}
i++;
});
};
});
/*
* ----------------------------- JSTORAGE -------------------------------------
* Simple local storage wrapper to save data on the browser side, supporting
* all major browsers - IE6+, Firefox2+, Safari4+, Chrome4+ and Opera 10.5+
*
* Author: Andris Reinman, andris.reinman@gmail.com
* Project homepage: www.jstorage.info
*
* Licensed under Unlicense:
*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* 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 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.
*
* For more information, please refer to <http://unlicense.org/>
*/
N2R('$', function ($) {
'use strict';
var
/* jStorage version */
JSTORAGE_VERSION = '0.4.12',
/* check for a JSON handling support */
JSON = {
parse: window.JSON && (window.JSON.parse || window.JSON.decode) ||
String.prototype.evalJSON && function (str) {
return String(str).evalJSON();
} ||
$.parseJSON ||
$.evalJSON,
stringify: Object.toJSON ||
window.JSON && (window.JSON.stringify || window.JSON.encode) ||
$.toJSON
};
// Break if no JSON support was found
if (typeof JSON.parse !== 'function' || typeof JSON.stringify !== 'function') {
throw new Error('No JSON support found, include //cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js to page');
}
var
/* This is the object, that holds the cached values */
_storage = {
__jstorage_meta: {
CRC32: {}
}
},
/* Actual browser storage (localStorage or globalStorage['domain']) */
_storage_service = {
jStorage: '{}'
},
/* DOM element for older IE versions, holds userData behavior */
_storage_elm = null,
/* How much space does the storage take */
_storage_size = 0,
/* which backend is currently used */
_backend = false,
/* onchange observers */
_observers = {},
/* timeout to wait after onchange event */
_observer_timeout = false,
/* last update time */
_observer_update = 0,
/* pubsub observers */
_pubsub_observers = {},
/* skip published items older than current timestamp */
_pubsub_last = +new Date(),
/* Next check for TTL */
_ttl_timeout,
/**
* XML encoding and decoding as XML nodes can't be JSON'ized
* XML nodes are encoded and decoded if the node is the value to be saved
* but not if it's as a property of another object
* Eg. -
* $.jStorage.set('key', xmlNode); // IS OK
* $.jStorage.set('key', {xml: xmlNode}); // NOT OK
*/
_XMLService = {
/**
* Validates a XML node to be XML
* based on jQuery.isXML function
*/
isXML: function (elm) {
var documentElement = (elm ? elm.ownerDocument || elm : 0).documentElement;
return documentElement ? documentElement.nodeName !== 'HTML' : false;
},
/**
* Encodes a XML node to string
* based on http://www.mercurytide.co.uk/news/article/issues-when-working-ajax/
*/
encode: function (xmlNode) {
if (!this.isXML(xmlNode)) {
return false;
}
try { // Mozilla, Webkit, Opera
return new XMLSerializer().serializeToString(xmlNode);
} catch (E1) {
try { // IE
return xmlNode.xml;
} catch (E2) {
}
}
return false;
},
/**
* Decodes a XML node from string
* loosely based on http://outwestmedia.com/jquery-plugins/xmldom/
*/
decode: function (xmlString) {
var dom_parser = ('DOMParser' in window && (new DOMParser()).parseFromString) ||
(window.ActiveXObject && function (_xmlString) {
var xml_doc = new ActiveXObject('Microsoft.XMLDOM');
xml_doc.async = 'false';
xml_doc.loadXML(_xmlString);
return xml_doc;
}),
resultXML;
if (!dom_parser) {
return false;
}
resultXML = dom_parser.call('DOMParser' in window && (new DOMParser()) || window, xmlString, 'text/xml');
return this.isXML(resultXML) ? resultXML : false;
}
};
////////////////////////// PRIVATE METHODS ////////////////////////
/**
* Initialization function. Detects if the browser supports DOM Storage
* or userData behavior and behaves accordingly.
*/
function _init() {
/* Check if browser supports localStorage */
var localStorageReallyWorks = false;
if ('localStorage' in window) {
try {
window.localStorage.setItem('_tmptest', 'tmpval');
localStorageReallyWorks = true;
window.localStorage.removeItem('_tmptest');
} catch (BogusQuotaExceededErrorOnIos5) {
// Thanks be to iOS5 Private Browsing mode which throws
// QUOTA_EXCEEDED_ERRROR DOM Exception 22.
}
}
if (localStorageReallyWorks) {
try {
if (window.localStorage) {
_storage_service = window.localStorage;
_backend = 'localStorage';
_observer_update = _storage_service.jStorage_update;
}
} catch (E3) { /* Firefox fails when touching localStorage and cookies are disabled */
}
}
/* Check if browser supports globalStorage */
else if ('globalStorage' in window) {
try {
if (window.globalStorage) {
if (window.location.hostname == 'localhost') {
_storage_service = window.globalStorage['localhost.localdomain'];
} else {
_storage_service = window.globalStorage[window.location.hostname];
}
_backend = 'globalStorage';
_observer_update = _storage_service.jStorage_update;
}
} catch (E4) { /* Firefox fails when touching localStorage and cookies are disabled */
}
}
/* Check if browser supports userData behavior */
else {
_storage_elm = document.createElement('link');
if (_storage_elm.addBehavior) {
/* Use a DOM element to act as userData storage */
_storage_elm.style.behavior = 'url(#default#userData)';
/* userData element needs to be inserted into the DOM! */
document.getElementsByTagName('head')[0].appendChild(_storage_elm);
try {
_storage_elm.load('jStorage');
} catch (E) {
// try to reset cache
_storage_elm.setAttribute('jStorage', '{}');
_storage_elm.save('jStorage');
_storage_elm.load('jStorage');
}
var data = '{}';
try {
data = _storage_elm.getAttribute('jStorage');
} catch (E5) {
}
try {
_observer_update = _storage_elm.getAttribute('jStorage_update');
} catch (E6) {
}
_storage_service.jStorage = data;
_backend = 'userDataBehavior';
} else {
_storage_elm = null;
return;
}
}
// Load data from storage
_load_storage();
// remove dead keys
_handleTTL();
// start listening for changes
_setupObserver();
// initialize publish-subscribe service
_handlePubSub();
// handle cached navigation
if ('addEventListener' in window) {
window.addEventListener('pageshow', function (event) {
if (event.persisted) {
_storageObserver();
}
}, false);
}
}
/**
* Reload data from storage when needed
*/
function _reloadData() {
var data = '{}';
if (_backend == 'userDataBehavior') {
_storage_elm.load('jStorage');
try {
data = _storage_elm.getAttribute('jStorage');
} catch (E5) {
}
try {
_observer_update = _storage_elm.getAttribute('jStorage_update');
} catch (E6) {
}
_storage_service.jStorage = data;
}
_load_storage();
// remove dead keys
_handleTTL();
_handlePubSub();
}
/**
* Sets up a storage change observer
*/
function _setupObserver() {
if (_backend == 'localStorage' || _backend == 'globalStorage') {
if ('addEventListener' in window) {
window.addEventListener('storage', _storageObserver, false);
} else {
document.attachEvent('onstorage', _storageObserver);
}
} else if (_backend == 'userDataBehavior') {
setInterval(_storageObserver, 1000);
}
}
/**
* Fired on any kind of data change, needs to check if anything has
* really been changed
*/
function _storageObserver() {
var updateTime;
// cumulate change notifications with timeout
clearTimeout(_observer_timeout);
_observer_timeout = setTimeout(function () {
if (_backend == 'localStorage' || _backend == 'globalStorage') {
updateTime = _storage_service.jStorage_update;
} else if (_backend == 'userDataBehavior') {
_storage_elm.load('jStorage');
try {
updateTime = _storage_elm.getAttribute('jStorage_update');
} catch (E5) {
}
}
if (updateTime && updateTime != _observer_update) {
_observer_update = updateTime;
_checkUpdatedKeys();
}
}, 25);
}
/**
* Reloads the data and checks if any keys are changed
*/
function _checkUpdatedKeys() {
var oldCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32)),
newCrc32List;
_reloadData();
newCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32));
var key,
updated = [],
removed = [];
for (key in oldCrc32List) {
if (oldCrc32List.hasOwnProperty(key)) {
if (!newCrc32List[key]) {
removed.push(key);
continue;
}
if (oldCrc32List[key] != newCrc32List[key] && String(oldCrc32List[key]).substr(0, 2) == '2.') {
updated.push(key);
}
}
}
for (key in newCrc32List) {
if (newCrc32List.hasOwnProperty(key)) {
if (!oldCrc32List[key]) {
updated.push(key);
}
}
}
_fireObservers(updated, 'updated');
_fireObservers(removed, 'deleted');
}
/**
* Fires observers for updated keys
*
* @param {Array|String} keys Array of key names or a key
* @param {String} action What happened with the value (updated, deleted, flushed)
*/
function _fireObservers(keys, action) {
keys = [].concat(keys || []);
var i, j, len, jlen;
if (action == 'flushed') {
keys = [];
for (var key in _observers) {
if (_observers.hasOwnProperty(key)) {
keys.push(key);
}
}
action = 'deleted';
}
for (i = 0, len = keys.length; i < len; i++) {
if (_observers[keys[i]]) {
for (j = 0, jlen = _observers[keys[i]].length; j < jlen; j++) {
_observers[keys[i]][j](keys[i], action);
}
}
if (_observers['*']) {
for (j = 0, jlen = _observers['*'].length; j < jlen; j++) {
_observers['*'][j](keys[i], action);
}
}
}
}
/**
* Publishes key change to listeners
*/
function _publishChange() {
var updateTime = (+new Date()).toString();
if (_backend == 'localStorage' || _backend == 'globalStorage') {
try {
_storage_service.jStorage_update = updateTime;
} catch (E8) {
// safari private mode has been enabled after the jStorage initialization
_backend = false;
}
} else if (_backend == 'userDataBehavior') {
_storage_elm.setAttribute('jStorage_update', updateTime);
_storage_elm.save('jStorage');
}
_storageObserver();
}
/**
* Loads the data from the storage based on the supported mechanism
*/
function _load_storage() {
/* if jStorage string is retrieved, then decode it */
if (_storage_service.jStorage) {
try {
_storage = JSON.parse(String(_storage_service.jStorage));
} catch (E6) {
_storage_service.jStorage = '{}';
}
} else {
_storage_service.jStorage = '{}';
}
_storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0;
if (!_storage.__jstorage_meta) {
_storage.__jstorage_meta = {};
}
if (!_storage.__jstorage_meta.CRC32) {
_storage.__jstorage_meta.CRC32 = {};
}
}
/**
* This functions provides the 'save' mechanism to store the jStorage object
*/
function _save() {
_dropOldEvents(); // remove expired events
try {
_storage_service.jStorage = JSON.stringify(_storage);
// If userData is used as the storage engine, additional
if (_storage_elm) {
_storage_elm.setAttribute('jStorage', _storage_service.jStorage);
_storage_elm.save('jStorage');
}
_storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0;
} catch (E7) { /* probably cache is full, nothing is saved this way*/
}
}
/**
* Function checks if a key is set and is string or numberic
*
* @param {String} key Key name
*/
function _checkKey(key) {
if (typeof key != 'string' && typeof key != 'number') {
throw new TypeError('Key name must be string or numeric');
}
if (key == '__jstorage_meta') {
throw new TypeError('Reserved key name');
}
return true;
}
/**
* Removes expired keys
*/
function _handleTTL() {
var curtime, i, TTL, CRC32, nextExpire = Infinity,
changed = false,
deleted = [];
clearTimeout(_ttl_timeout);
if (!_storage.__jstorage_meta || typeof _storage.__jstorage_meta.TTL != 'object') {
// nothing to do here
return;
}
curtime = +new Date();
TTL = _storage.__jstorage_meta.TTL;
CRC32 = _storage.__jstorage_meta.CRC32;
for (i in TTL) {
if (TTL.hasOwnProperty(i)) {
if (TTL[i] <= curtime) {
delete TTL[i];
delete CRC32[i];
delete _storage[i];
changed = true;
deleted.push(i);
} else if (TTL[i] < nextExpire) {
nextExpire = TTL[i];
}
}
}
// set next check
if (nextExpire != Infinity) {
_ttl_timeout = setTimeout(_handleTTL, Math.min(nextExpire - curtime, 0x7FFFFFFF));
}
// save changes
if (changed) {
_save();
_publishChange();
_fireObservers(deleted, 'deleted');
}
}
/**
* Checks if there's any events on hold to be fired to listeners
*/
function _handlePubSub() {
var i, len;
if (!_storage.__jstorage_meta.PubSub) {
return;
}
var pubelm,
_pubsubCurrent = _pubsub_last,
needFired = [];
for (i = len = _storage.__jstorage_meta.PubSub.length - 1; i >= 0; i--) {
pubelm = _storage.__jstorage_meta.PubSub[i];
if (pubelm[0] > _pubsub_last) {
_pubsubCurrent = pubelm[0];
needFired.unshift(pubelm);
}
}
for (i = needFired.length - 1; i >= 0; i--) {
_fireSubscribers(needFired[i][1], needFired[i][2]);
}
_pubsub_last = _pubsubCurrent;
}
/**
* Fires all subscriber listeners for a pubsub channel
*
* @param {String} channel Channel name
* @param {Mixed} payload Payload data to deliver
*/
function _fireSubscribers(channel, payload) {
if (_pubsub_observers[channel]) {
for (var i = 0, len = _pubsub_observers[channel].length; i < len; i++) {
// send immutable data that can't be modified by listeners
try {
_pubsub_observers[channel][i](channel, JSON.parse(JSON.stringify(payload)));
} catch (E) {
}
}
}
}
/**
* Remove old events from the publish stream (at least 2sec old)
*/
function _dropOldEvents() {
if (!_storage.__jstorage_meta.PubSub) {
return;
}
var retire = +new Date() - 2000;
for (var i = 0, len = _storage.__jstorage_meta.PubSub.length; i < len; i++) {
if (_storage.__jstorage_meta.PubSub[i][0] <= retire) {
// deleteCount is needed for IE6
_storage.__jstorage_meta.PubSub.splice(i, _storage.__jstorage_meta.PubSub.length - i);
break;
}
}
if (!_storage.__jstorage_meta.PubSub.length) {
delete _storage.__jstorage_meta.PubSub;
}
}
/**
* Publish payload to a channel
*
* @param {String} channel Channel name
* @param {Mixed} payload Payload to send to the subscribers
*/
function _publish(channel, payload) {
if (!_storage.__jstorage_meta) {
_storage.__jstorage_meta = {};
}
if (!_storage.__jstorage_meta.PubSub) {
_storage.__jstorage_meta.PubSub = [];
}
_storage.__jstorage_meta.PubSub.unshift([+new Date(), channel, payload]);
_save();
_publishChange();
}
/**
* JS Implementation of MurmurHash2
*
* SOURCE: https://github.com/garycourt/murmurhash-js (MIT licensed)
*
* @author <a href='mailto:gary.court@gmail.com'>Gary Court</a>
* @see http://github.com/garycourt/murmurhash-js
* @author <a href='mailto:aappleby@gmail.com'>Austin Appleby</a>
* @see http://sites.google.com/site/murmurhash/
*
* @param {string} str ASCII only
* @param {number} seed Positive integer only
* @return {number} 32-bit positive integer hash
*/
function murmurhash2_32_gc(str, seed) {
var
l = str.length,
h = seed ^ l,
i = 0,
k;
while (l >= 4) {
k =
((str.charCodeAt(i) & 0xff)) |
((str.charCodeAt(++i) & 0xff) << 8) |
((str.charCodeAt(++i) & 0xff) << 16) |
((str.charCodeAt(++i) & 0xff) << 24);
k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
k ^= k >>> 24;
k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
l -= 4;
++i;
}
switch (l) {
case 3:
h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
/* falls through */
case 2:
h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
/* falls through */
case 1:
h ^= (str.charCodeAt(i) & 0xff);
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
}
h ^= h >>> 13;
h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
h ^= h >>> 15;
return h >>> 0;
}
////////////////////////// PUBLIC INTERFACE /////////////////////////
$.jStorage = {
/* Version number */
version: JSTORAGE_VERSION,
/**
* Sets a key's value.
*
* @param {String} key Key to set. If this value is not set or not
* a string an exception is raised.
* @param {Mixed} value Value to set. This can be any value that is JSON
* compatible (Numbers, Strings, Objects etc.).
* @param {Object} [options] - possible options to use
* @param {Number} [options.TTL] - optional TTL value, in milliseconds
* @return {Mixed} the used value
*/
set: function (key, value, options) {
_checkKey(key);
options = options || {};
// undefined values are deleted automatically
if (typeof value == 'undefined') {
this.deleteKey(key);
return value;
}
if (_XMLService.isXML(value)) {
value = {
_is_xml: true,
xml: _XMLService.encode(value)
};
} else if (typeof value == 'function') {
return undefined; // functions can't be saved!
} else if (value && typeof value == 'object') {
// clone the object before saving to _storage tree
value = JSON.parse(JSON.stringify(value));
}
_storage[key] = value;
_storage.__jstorage_meta.CRC32[key] = '2.' + murmurhash2_32_gc(JSON.stringify(value), 0x9747b28c);
this.setTTL(key, options.TTL || 0); // also handles saving and _publishChange
_fireObservers(key, 'updated');
return value;
},
/**
* Looks up a key in cache
*
* @param {String} key - Key to look up.
* @param {mixed} def - Default value to return, if key didn't exist.
* @return {Mixed} the key value, default value or null
*/
get: function (key, def) {
_checkKey(key);
if (key in _storage) {
if (_storage[key] && typeof _storage[key] == 'object' && _storage[key]._is_xml) {
return _XMLService.decode(_storage[key].xml);
} else {
return _storage[key];
}
}
return typeof(def) == 'undefined' ? null : def;
},
/**
* Deletes a key from cache.
*
* @param {String} key - Key to delete.
* @return {Boolean} true if key existed or false if it didn't
*/
deleteKey: function (key) {
_checkKey(key);
if (key in _storage) {
delete _storage[key];
// remove from TTL list
if (typeof _storage.__jstorage_meta.TTL == 'object' &&
key in _storage.__jstorage_meta.TTL) {
delete _storage.__jstorage_meta.TTL[key];
}
delete _storage.__jstorage_meta.CRC32[key];
_save();
_publishChange();
_fireObservers(key, 'deleted');
return true;
}
return false;
},
/**
* Sets a TTL for a key, or remove it if ttl value is 0 or below
*
* @param {String} key - key to set the TTL for
* @param {Number} ttl - TTL timeout in milliseconds
* @return {Boolean} true if key existed or false if it didn't
*/
setTTL: function (key, ttl) {
var curtime = +new Date();
_checkKey(key);
ttl = Number(ttl) || 0;
if (key in _storage) {
if (!_storage.__jstorage_meta.TTL) {
_storage.__jstorage_meta.TTL = {};
}
// Set TTL value for the key
if (ttl > 0) {
_storage.__jstorage_meta.TTL[key] = curtime + ttl;
} else {
delete _storage.__jstorage_meta.TTL[key];
}
_save();
_handleTTL();
_publishChange();
return true;
}
return false;
},
/**
* Gets remaining TTL (in milliseconds) for a key or 0 when no TTL has been set
*
* @param {String} key Key to check
* @return {Number} Remaining TTL in milliseconds
*/
getTTL: function (key) {
var curtime = +new Date(),
ttl;
_checkKey(key);
if (key in _storage && _storage.__jstorage_meta.TTL && _storage.__jstorage_meta.TTL[key]) {
ttl = _storage.__jstorage_meta.TTL[key] - curtime;
return ttl || 0;
}
return 0;
},
/**
* Deletes everything in cache.
*
* @return {Boolean} Always true
*/
flush: function () {
_storage = {
__jstorage_meta: {
CRC32: {}
}
};
_save();
_publishChange();
_fireObservers(null, 'flushed');
return true;
},
/**
* Returns a read-only copy of _storage
*
* @return {Object} Read-only copy of _storage
*/
storageObj: function () {
function F() {
}
F.prototype = _storage;
return new F();
},
/**
* Returns an index of all used keys as an array
* ['key1', 'key2',..'keyN']
*
* @return {Array} Used keys
*/
index: function () {
var index = [],
i;
for (i in _storage) {
if (_storage.hasOwnProperty(i) && i != '__jstorage_meta') {
index.push(i);
}
}
return index;
},
/**
* How much space in bytes does the storage take?
*
* @return {Number} Storage size in chars (not the same as in bytes,
* since some chars may take several bytes)
*/
storageSize: function () {
return _storage_size;
},
/**
* Which backend is currently in use?
*
* @return {String} Backend name
*/
currentBackend: function () {
return _backend;
},
/**
* Test if storage is available
*
* @return {Boolean} True if storage can be used
*/
storageAvailable: function () {
return !!_backend;
},
/**
* Register change listeners
*
* @param {String} key Key name
* @param {Function} callback Function to run when the key changes
*/
listenKeyChange: function (key, callback) {
_checkKey(key);
if (!_observers[key]) {
_observers[key] = [];
}
_observers[key].push(callback);
},
/**
* Remove change listeners
*
* @param {String} key Key name to unregister listeners against
* @param {Function} [callback] If set, unregister the callback, if not - unregister all
*/
stopListening: function (key, callback) {
_checkKey(key);
if (!_observers[key]) {
return;
}
if (!callback) {
delete _observers[key];
return;
}
for (var i = _observers[key].length - 1; i >= 0; i--) {
if (_observers[key][i] == callback) {
_observers[key].splice(i, 1);
}
}
},
/**
* Subscribe to a Publish/Subscribe event stream
*
* @param {String} channel Channel name
* @param {Function} callback Function to run when the something is published to the channel
*/
subscribe: function (channel, callback) {
channel = (channel || '').toString();
if (!channel) {
throw new TypeError('Channel not defined');
}
if (!_pubsub_observers[channel]) {
_pubsub_observers[channel] = [];
}
_pubsub_observers[channel].push(callback);
},
/**
* Publish data to an event stream
*
* @param {String} channel Channel name
* @param {Mixed} payload Payload to deliver
*/
publish: function (channel, payload) {
channel = (channel || '').toString();
if (!channel) {
throw new TypeError('Channel not defined');
}
_publish(channel, payload);
},
/**
* Reloads the data from browser storage
*/
reInit: function () {
_reloadData();
},
/**
* Removes reference from global objects and saves it as jStorage
*
* @param {Boolean} option if needed to save object as simple 'jStorage' in windows context
*/
noConflict: function (saveInGlobal) {
delete window.$.jStorage;
if (saveInGlobal) {
window.jStorage = this;
}
return this;
}
};
// Initialize jStorage
_init();
});
/**
* @preserve jQuery DateTimePicker plugin v2.4.1
* @homepage http://xdsoft.net/jqplugins/datetimepicker/
* (c) 2014, Chupurnov Valeriy.
*/
N2R('$', function ($) {
'use strict';
var default_options = {
i18n: {
ar: { // Arabic
months: [
"كانون الثاني", "شباط", "آذار", "نيسان", "مايو", "حزيران", "تموز", "آب", "أيلول", "تشرين الأول", "تشرين الثاني", "كانون الأول"
],
dayOfWeek: [
"ن", "ث", "ع", "خ", "ج", "س", "ح"
]
},
ro: { // Romanian
months: [
"ianuarie", "februarie", "martie", "aprilie", "mai", "iunie", "iulie", "august", "septembrie", "octombrie", "noiembrie", "decembrie"
],
dayOfWeek: [
"l", "ma", "mi", "j", "v", "s", "d"
]
},
id: { // Indonesian
months: [
"Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"
],
dayOfWeek: [
"Sen", "Sel", "Rab", "Kam", "Jum", "Sab", "Min"
]
},
bg: { // Bulgarian
months: [
"Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември"
],
dayOfWeek: [
"Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"
]
},
fa: { // Persian/Farsi
months: [
'فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور', 'مهر', 'آبان', 'آذر', 'دی', 'بهمن', 'اسفند'
],
dayOfWeek: [
'یکشنبه', 'دوشنبه', 'سه شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'
]
},
ru: { // Russian
months: [
'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'
],
dayOfWeek: [
"Вск", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"
]
},
uk: { // Ukrainian
months: [
'Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень', 'Липень', 'Серпень', 'Вересень', 'Жовтень', 'Листопад', 'Грудень'
],
dayOfWeek: [
"Ндл", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Сбт"
]
},
en: { // English
months: [
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
],
dayOfWeek: [
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
]
},
el: { // Ελληνικά
months: [
"Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος"
],
dayOfWeek: [
"Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ"
]
},
de: { // German
months: [
'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'
],
dayOfWeek: [
"So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"
]
},
nl: { // Dutch
months: [
"januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"
],
dayOfWeek: [
"zo", "ma", "di", "wo", "do", "vr", "za"
]
},
tr: { // Turkish
months: [
"Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"
],
dayOfWeek: [
"Paz", "Pts", "Sal", "Çar", "Per", "Cum", "Cts"
]
},
fr: { //French
months: [
"Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"
],
dayOfWeek: [
"Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"
]
},
es: { // Spanish
months: [
"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"
],
dayOfWeek: [
"Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb"
]
},
th: { // Thai
months: [
'มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน', 'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม'
],
dayOfWeek: [
'อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'
]
},
pl: { // Polish
months: [
"styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień"
],
dayOfWeek: [
"nd", "pn", "wt", "śr", "cz", "pt", "sb"
]
},
pt: { // Portuguese
months: [
"Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"
],
dayOfWeek: [
"Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab"
]
},
ch: { // Simplified Chinese
months: [
"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"
],
dayOfWeek: [
"日", "一", "二", "三", "四", "五", "六"
]
},
se: { // Swedish
months: [
"Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"
],
dayOfWeek: [
"Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör"
]
},
kr: { // Korean
months: [
"1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"
],
dayOfWeek: [
"일", "월", "화", "수", "목", "금", "토"
]
},
it: { // Italian
months: [
"Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"
],
dayOfWeek: [
"Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"
]
},
da: { // Dansk
months: [
"January", "Februar", "Marts", "April", "Maj", "Juni", "July", "August", "September", "Oktober", "November", "December"
],
dayOfWeek: [
"Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"
]
},
no: { // Norwegian
months: [
"Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"
],
dayOfWeek: [
"Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"
]
},
ja: { // Japanese
months: [
"1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"
],
dayOfWeek: [
"日", "月", "火", "水", "木", "金", "土"
]
},
vi: { // Vietnamese
months: [
"Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12"
],
dayOfWeek: [
"CN", "T2", "T3", "T4", "T5", "T6", "T7"
]
},
sl: { // Slovenščina
months: [
"Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "November", "December"
],
dayOfWeek: [
"Ned", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob"
]
},
cs: { // Čeština
months: [
"Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"
],
dayOfWeek: [
"Ne", "Po", "Út", "St", "Čt", "Pá", "So"
]
},
hu: { // Hungarian
months: [
"Január", "Február", "Március", "Április", "Május", "Június", "Július", "Augusztus", "Szeptember", "Október", "November", "December"
],
dayOfWeek: [
"Va", "Hé", "Ke", "Sze", "Cs", "Pé", "Szo"
]
},
az: { //Azerbaijanian (Azeri)
months: [
"Yanvar", "Fevral", "Mart", "Aprel", "May", "Iyun", "Iyul", "Avqust", "Sentyabr", "Oktyabr", "Noyabr", "Dekabr"
],
dayOfWeek: [
"B", "Be", "Ça", "Ç", "Ca", "C", "Ş"
]
},
bs: { //Bosanski
months: [
"Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"
],
dayOfWeek: [
"Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"
]
},
ca: { //Català
months: [
"Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre"
],
dayOfWeek: [
"Dg", "Dl", "Dt", "Dc", "Dj", "Dv", "Ds"
]
},
'en-GB': { //English (British)
months: [
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
],
dayOfWeek: [
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
]
},
et: { //"Eesti"
months: [
"Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni", "Juuli", "August", "September", "Oktoober", "November", "Detsember"
],
dayOfWeek: [
"P", "E", "T", "K", "N", "R", "L"
]
},
eu: { //Euskara
months: [
"Urtarrila", "Otsaila", "Martxoa", "Apirila", "Maiatza", "Ekaina", "Uztaila", "Abuztua", "Iraila", "Urria", "Azaroa", "Abendua"
],
dayOfWeek: [
"Ig.", "Al.", "Ar.", "Az.", "Og.", "Or.", "La."
]
},
fi: { //Finnish (Suomi)
months: [
"Tammikuu", "Helmikuu", "Maaliskuu", "Huhtikuu", "Toukokuu", "Kesäkuu", "Heinäkuu", "Elokuu", "Syyskuu", "Lokakuu", "Marraskuu", "Joulukuu"
],
dayOfWeek: [
"Su", "Ma", "Ti", "Ke", "To", "Pe", "La"
]
},
gl: { //Galego
months: [
"Xan", "Feb", "Maz", "Abr", "Mai", "Xun", "Xul", "Ago", "Set", "Out", "Nov", "Dec"
],
dayOfWeek: [
"Dom", "Lun", "Mar", "Mer", "Xov", "Ven", "Sab"
]
},
hr: { //Hrvatski
months: [
"Siječanj", "Veljača", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac"
],
dayOfWeek: [
"Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"
]
},
ko: { //Korean (한국어)
months: [
"1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"
],
dayOfWeek: [
"일", "월", "화", "수", "목", "금", "토"
]
},
lt: { //Lithuanian (lietuvių)
months: [
"Sausio", "Vasario", "Kovo", "Balandžio", "Gegužės", "Birželio", "Liepos", "Rugpjūčio", "Rugsėjo", "Spalio", "Lapkričio", "Gruodžio"
],
dayOfWeek: [
"Sek", "Pir", "Ant", "Tre", "Ket", "Pen", "Šeš"
]
},
lv: { //Latvian (Latviešu)
months: [
"Janvāris", "Februāris", "Marts", "Aprīlis ", "Maijs", "Jūnijs", "Jūlijs", "Augusts", "Septembris", "Oktobris", "Novembris", "Decembris"
],
dayOfWeek: [
"Sv", "Pr", "Ot", "Tr", "Ct", "Pk", "St"
]
},
mk: { //Macedonian (Македонски)
months: [
"јануари", "февруари", "март", "април", "мај", "јуни", "јули", "август", "септември", "октомври", "ноември", "декември"
],
dayOfWeek: [
"нед", "пон", "вто", "сре", "чет", "пет", "саб"
]
},
mn: { //Mongolian (Монгол)
months: [
"1-р сар", "2-р сар", "3-р сар", "4-р сар", "5-р сар", "6-р сар", "7-р сар", "8-р сар", "9-р сар", "10-р сар", "11-р сар", "12-р сар"
],
dayOfWeek: [
"Дав", "Мяг", "Лха", "Пүр", "Бсн", "Бям", "Ням"
]
},
'pt-BR': { //Português(Brasil)
months: [
"Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"
],
dayOfWeek: [
"Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"
]
},
sk: { //Slovenčina
months: [
"Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December"
],
dayOfWeek: [
"Ne", "Po", "Ut", "St", "Št", "Pi", "So"
]
},
sq: { //Albanian (Shqip)
months: [
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
],
dayOfWeek: [
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
]
},
'sr-YU': { //Serbian (Srpski)
months: [
"Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"
],
dayOfWeek: [
"Ned", "Pon", "Uto", "Sre", "čet", "Pet", "Sub"
]
},
sr: { //Serbian Cyrillic (Српски)
months: [
"јануар", "фебруар", "март", "април", "мај", "јун", "јул", "август", "септембар", "октобар", "новембар", "децембар"
],
dayOfWeek: [
"нед", "пон", "уто", "сре", "чет", "пет", "суб"
]
},
sv: { //Svenska
months: [
"Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"
],
dayOfWeek: [
"Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör"
]
},
'zh-TW': { //Traditional Chinese (繁體中文)
months: [
"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"
],
dayOfWeek: [
"日", "一", "二", "三", "四", "五", "六"
]
},
zh: { //Simplified Chinese (简体中文)
months: [
"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"
],
dayOfWeek: [
"日", "一", "二", "三", "四", "五", "六"
]
},
he: { //Hebrew (עברית)
months: [
'ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'
],
dayOfWeek: [
'א\'', 'ב\'', 'ג\'', 'ד\'', 'ה\'', 'ו\'', 'שבת'
]
}
},
value: '',
lang: 'en',
format: 'Y/m/d H:i',
formatTime: 'H:i',
formatDate: 'Y/m/d',
startDate: false, // new Date(), '1986/12/08', '-1970/01/05','-1970/01/05',
step: 60,
monthChangeSpinner: true,
closeOnDateSelect: false,
closeOnWithoutClick: true,
closeOnInputClick: true,
timepicker: true,
datepicker: true,
weeks: false,
defaultTime: false, // use formatTime format (ex. '10:00' for formatTime: 'H:i')
defaultDate: false, // use formatDate format (ex new Date() or '1986/12/08' or '-1970/01/05' or '-1970/01/05')
minDate: false,
maxDate: false,
minTime: false,
maxTime: false,
allowTimes: [],
opened: false,
initTime: true,
inline: false,
theme: '',
onSelectDate: function () {
},
onSelectTime: function () {
},
onChangeMonth: function () {
},
onChangeYear: function () {
},
onChangeDateTime: function () {
},
onShow: function () {
},
onClose: function () {
},
onGenerate: function () {
},
withoutCopyright: true,
inverseButton: false,
hours12: false,
next: 'xdsoft_next',
prev: 'xdsoft_prev',
dayOfWeekStart: 0,
parentID: 'body',
timeHeightInTimePicker: 25,
timepickerScrollbar: true,
todayButton: true,
defaultSelect: true,
scrollMonth: true,
scrollTime: true,
scrollInput: true,
lazyInit: false,
mask: false,
validateOnBlur: true,
allowBlank: true,
yearStart: 1950,
yearEnd: 2050,
style: '',
id: '',
fixed: false,
roundTime: 'round', // ceil, floor
className: '',
weekends: [],
disabledDates: [],
yearOffset: 0,
beforeShowDay: null,
enterLikeTab: true
};
// fix for ie8
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (obj, start) {
var i, j;
for (i = (start || 0), j = this.length; i < j; i += 1) {
if (this[i] === obj) {
return i;
}
}
return -1;
};
}
Date.prototype.countDaysInMonth = function () {
return new Date(this.getFullYear(), this.getMonth() + 1, 0).getDate();
};
$.fn.xdsoftScroller = function (percent) {
return this.each(function () {
var timeboxparent = $(this),
pointerEventToXY = function (e) {
var out = {x: 0, y: 0},
touch;
if (e.type === 'touchstart' || e.type === 'touchmove' || e.type === 'touchend' || e.type === 'touchcancel') {
touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
out.x = touch.clientX;
out.y = touch.clientY;
} else if (e.type === 'mousedown' || e.type === 'mouseup' || e.type === 'mousemove' || e.type === 'mouseover' || e.type === 'mouseout' || e.type === 'mouseenter' || e.type === 'mouseleave') {
out.x = e.clientX;
out.y = e.clientY;
}
return out;
},
move = 0,
timebox,
parentHeight,
height,
scrollbar,
scroller,
maximumOffset = 100,
start = false,
startY = 0,
startTop = 0,
h1 = 0,
touchStart = false,
startTopScroll = 0,
calcOffset = function () {
};
if (percent === 'hide') {
timeboxparent.find('.xdsoft_scrollbar').hide();
return;
}
if (!$(this).hasClass('xdsoft_scroller_box')) {
timebox = timeboxparent.children().eq(0);
parentHeight = timeboxparent[0].clientHeight;
height = timebox[0].offsetHeight;
scrollbar = $('<div class="xdsoft_scrollbar"></div>');
scroller = $('<div class="xdsoft_scroller"></div>');
scrollbar.append(scroller);
timeboxparent.addClass('xdsoft_scroller_box').append(scrollbar);
calcOffset = function calcOffset(event) {
var offset = pointerEventToXY(event).y - startY + startTopScroll;
if (offset < 0) {
offset = 0;
}
if (offset + scroller[0].offsetHeight > h1) {
offset = h1 - scroller[0].offsetHeight;
}
timeboxparent.trigger('scroll_element.xdsoft_scroller', [maximumOffset ? offset / maximumOffset : 0]);
};
scroller
.on('touchstart.xdsoft_scroller mousedown.xdsoft_scroller', function (event) {
if (!parentHeight) {
timeboxparent.trigger('resize_scroll.xdsoft_scroller', [percent]);
}
startY = pointerEventToXY(event).y;
startTopScroll = parseInt(scroller.css('margin-top'), 10);
h1 = scrollbar[0].offsetHeight;
if (event.type === 'mousedown') {
if (document) {
$(document.body).addClass('xdsoft_noselect');
}
$([document.body, window]).on('mouseup.xdsoft_scroller', function arguments_callee() {
$([document.body, window]).off('mouseup.xdsoft_scroller', arguments_callee)
.off('mousemove.xdsoft_scroller', calcOffset)
.removeClass('xdsoft_noselect');
});
$(document.body).on('mousemove.xdsoft_scroller', calcOffset);
} else {
touchStart = true;
event.stopPropagation();
event.preventDefault();
}
})
.on('touchmove', function (event) {
if (touchStart) {
event.preventDefault();
calcOffset(event);
}
})
.on('touchend touchcancel', function (event) {
touchStart = false;
startTopScroll = 0;
});
timeboxparent
.on('scroll_element.xdsoft_scroller', function (event, percentage) {
if (!parentHeight) {
timeboxparent.trigger('resize_scroll.xdsoft_scroller', [percentage, true]);
}
percentage = percentage > 1 ? 1 : (percentage < 0 || isNaN(percentage)) ? 0 : percentage;
scroller.css('margin-top', maximumOffset * percentage);
setTimeout(function () {
timebox.css('marginTop', -parseInt((timebox[0].offsetHeight - parentHeight) * percentage, 10));
}, 10);
})
.on('resize_scroll.xdsoft_scroller', function (event, percentage, noTriggerScroll) {
var percent, sh;
parentHeight = timeboxparent[0].clientHeight;
height = timebox[0].offsetHeight;
percent = parentHeight / height;
sh = percent * scrollbar[0].offsetHeight;
if (percent > 1) {
scroller.hide();
} else {
scroller.show();
scroller.css('height', parseInt(sh > 10 ? sh : 10, 10));
maximumOffset = scrollbar[0].offsetHeight - scroller[0].offsetHeight;
if (noTriggerScroll !== true) {
timeboxparent.trigger('scroll_element.xdsoft_scroller', [percentage || Math.abs(parseInt(timebox.css('marginTop'), 10)) / (height - parentHeight)]);
}
}
});
timeboxparent.on('wheel', function (event) {
var top = Math.abs(parseInt(timebox.css('marginTop'), 10));
top = top - (event.deltaY * 20);
if (top < 0) {
top = 0;
}
timeboxparent.trigger('scroll_element.xdsoft_scroller', [top / (height - parentHeight)]);
event.stopPropagation();
return false;
});
timeboxparent.on('touchstart', function (event) {
start = pointerEventToXY(event);
startTop = Math.abs(parseInt(timebox.css('marginTop'), 10));
});
timeboxparent.on('touchmove', function (event) {
if (start) {
event.preventDefault();
var coord = pointerEventToXY(event);
timeboxparent.trigger('scroll_element.xdsoft_scroller', [(startTop - (coord.y - start.y)) / (height - parentHeight)]);
}
});
timeboxparent.on('touchend touchcancel', function (event) {
start = false;
startTop = 0;
});
}
timeboxparent.trigger('resize_scroll.xdsoft_scroller', [percent]);
});
};
$.fn.datetimepicker = function (opt) {
var KEY0 = 48,
KEY9 = 57,
_KEY0 = 96,
_KEY9 = 105,
CTRLKEY = 17,
DEL = 46,
ENTER = 13,
ESC = 27,
BACKSPACE = 8,
ARROWLEFT = 37,
ARROWUP = 38,
ARROWRIGHT = 39,
ARROWDOWN = 40,
TAB = 9,
F5 = 116,
AKEY = 65,
CKEY = 67,
VKEY = 86,
ZKEY = 90,
YKEY = 89,
ctrlDown = false,
options = ($.isPlainObject(opt) || !opt) ? $.extend(true, {}, default_options, opt) : $.extend(true, {}, default_options),
lazyInitTimer = 0,
createDateTimePicker,
destroyDateTimePicker,
lazyInit = function (input) {
if (typeof options.i18n[options.lang] === 'undefined') {
options.lang = 'en';
}
input
.on('open.xdsoft focusin.xdsoft mousedown.xdsoft', function initOnActionCallback(event) {
if (input.is(':disabled') || input.data('xdsoft_datetimepicker')) {
return;
}
clearTimeout(lazyInitTimer);
lazyInitTimer = setTimeout(function () {
if (!input.data('xdsoft_datetimepicker')) {
createDateTimePicker(input);
}
input
.off('open.xdsoft focusin.xdsoft mousedown.xdsoft', initOnActionCallback)
.trigger('open.xdsoft');
}, 100);
});
};
createDateTimePicker = function (input) {
var datetimepicker = $('<div ' + (options.id ? 'id="' + options.id + '"' : '') + ' ' + (options.style ? 'style="' + options.style + '"' : '') + ' class="xdsoft_datetimepicker xdsoft_' + options.theme + ' xdsoft_noselect ' + (options.weeks ? ' xdsoft_showweeks' : '') + options.className + '"></div>'),
xdsoft_copyright = $('<div class="xdsoft_copyright"><a target="_blank" href="http://xdsoft.net/jqplugins/datetimepicker/">xdsoft.net</a></div>'),
datepicker = $('<div class="xdsoft_datepicker active"></div>'),
mounth_picker = $('<div class="xdsoft_mounthpicker"><button type="button" class="xdsoft_prev"></button><button type="button" class="xdsoft_today_button"></button>' +
'<div class="xdsoft_label xdsoft_month"><span></span><i></i></div>' +
'<div class="xdsoft_label xdsoft_year"><span></span><i></i></div>' +
'<button type="button" class="xdsoft_next"></button></div>'),
calendar = $('<div class="xdsoft_calendar"></div>'),
timepicker = $('<div class="xdsoft_timepicker active"><button type="button" class="xdsoft_prev"></button><div class="xdsoft_time_box"></div><button type="button" class="xdsoft_next"></button></div>'),
timeboxparent = timepicker.find('.xdsoft_time_box').eq(0),
timebox = $('<div class="xdsoft_time_variant"></div>'),
/*scrollbar = $('<div class="xdsoft_scrollbar"></div>'),
scroller = $('<div class="xdsoft_scroller"></div>'),*/
monthselect = $('<div class="xdsoft_select xdsoft_monthselect"><div></div></div>'),
yearselect = $('<div class="xdsoft_select xdsoft_yearselect"><div></div></div>'),
triggerAfterOpen = false,
XDSoft_datetime,
//scroll_element,
xchangeTimer,
timerclick,
current_time_index,
setPos,
timer = 0,
timer1 = 0,
_xdsoft_datetime;
mounth_picker
.find('.xdsoft_month span')
.after(monthselect);
mounth_picker
.find('.xdsoft_year span')
.after(yearselect);
mounth_picker
.find('.xdsoft_month,.xdsoft_year')
.on('mousedown.xdsoft', function (event) {
var select = $(this).find('.xdsoft_select').eq(0),
val = 0,
top = 0,
visible = select.is(':visible'),
items,
i;
mounth_picker
.find('.xdsoft_select')
.hide();
if (_xdsoft_datetime.currentTime) {
val = _xdsoft_datetime.currentTime[$(this).hasClass('xdsoft_month') ? 'getMonth' : 'getFullYear']();
}
select[visible ? 'hide' : 'show']();
for (items = select.find('div.xdsoft_option'), i = 0; i < items.length; i += 1) {
if (items.eq(i).data('value') === val) {
break;
} else {
top += items[0].offsetHeight;
}
}
select.xdsoftScroller(top / (select.children()[0].offsetHeight - (select[0].clientHeight)));
event.stopPropagation();
return false;
});
mounth_picker
.find('.xdsoft_select')
.xdsoftScroller()
.on('mousedown.xdsoft', function (event) {
event.stopPropagation();
event.preventDefault();
})
.on('mousedown.xdsoft', '.xdsoft_option', function (event) {
var year = _xdsoft_datetime.currentTime.getFullYear();
if (_xdsoft_datetime && _xdsoft_datetime.currentTime) {
_xdsoft_datetime.currentTime[$(this).parent().parent().hasClass('xdsoft_monthselect') ? 'setMonth' : 'setFullYear']($(this).data('value'));
}
$(this).parent().parent().hide();
datetimepicker.trigger('xchange.xdsoft');
if (options.onChangeMonth && $.isFunction(options.onChangeMonth)) {
options.onChangeMonth.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
}
if (year !== _xdsoft_datetime.currentTime.getFullYear() && $.isFunction(options.onChangeYear)) {
options.onChangeYear.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
}
});
datetimepicker.setOptions = function (_options) {
options = $.extend(true, {}, options, _options);
if (_options.allowTimes && $.isArray(_options.allowTimes) && _options.allowTimes.length) {
options.allowTimes = $.extend(true, [], _options.allowTimes);
}
if (_options.weekends && $.isArray(_options.weekends) && _options.weekends.length) {
options.weekends = $.extend(true, [], _options.weekends);
}
if (_options.disabledDates && $.isArray(_options.disabledDates) && _options.disabledDates.length) {
options.disabledDates = $.extend(true, [], _options.disabledDates);
}
if ((options.open || options.opened) && (!options.inline)) {
input.trigger('open.xdsoft');
}
if (options.inline) {
triggerAfterOpen = true;
datetimepicker.addClass('xdsoft_inline');
input.after(datetimepicker).hide();
}
if (options.inverseButton) {
options.next = 'xdsoft_prev';
options.prev = 'xdsoft_next';
}
if (options.datepicker) {
datepicker.addClass('active');
} else {
datepicker.removeClass('active');
}
if (options.timepicker) {
timepicker.addClass('active');
} else {
timepicker.removeClass('active');
}
if (options.value) {
if (input && input.val) {
input.val(options.value);
}
_xdsoft_datetime.setCurrentTime(options.value);
}
if (isNaN(options.dayOfWeekStart)) {
options.dayOfWeekStart = 0;
} else {
options.dayOfWeekStart = parseInt(options.dayOfWeekStart, 10) % 7;
}
if (!options.timepickerScrollbar) {
timeboxparent.xdsoftScroller('hide');
}
if (options.minDate && /^-(.*)$/.test(options.minDate)) {
options.minDate = _xdsoft_datetime.strToDateTime(options.minDate).dateFormat(options.formatDate);
}
if (options.maxDate && /^\+(.*)$/.test(options.maxDate)) {
options.maxDate = _xdsoft_datetime.strToDateTime(options.maxDate).dateFormat(options.formatDate);
}
mounth_picker
.find('.xdsoft_today_button')
.css('visibility', !options.todayButton ? 'hidden' : 'visible');
if (options.mask) {
var e,
getCaretPos = function (input) {
try {
if (document.selection && document.selection.createRange) {
var range = document.selection.createRange();
return range.getBookmark().charCodeAt(2) - 2;
}
if (input.setSelectionRange) {
return input.selectionStart;
}
} catch (e) {
return 0;
}
},
setCaretPos = function (node, pos) {
node = (typeof node === "string" || node instanceof String) ? document.getElementById(node) : node;
if (!node) {
return false;
}
if (node.createTextRange) {
var textRange = node.createTextRange();
textRange.collapse(true);
textRange.moveEnd('character', pos);
textRange.moveStart('character', pos);
textRange.select();
return true;
}
if (node.setSelectionRange) {
node.setSelectionRange(pos, pos);
return true;
}
return false;
},
isValidValue = function (mask, value) {
var reg = mask
.replace(/([\[\]\/\{\}\(\)\-\.\+]{1})/g, '\\$1')
.replace(/_/g, '{digit+}')
.replace(/([0-9]{1})/g, '{digit$1}')
.replace(/\{digit([0-9]{1})\}/g, '[0-$1_]{1}')
.replace(/\{digit[\+]\}/g, '[0-9_]{1}');
return (new RegExp(reg)).test(value);
};
input.off('keydown.xdsoft');
if (options.mask === true) {
options.mask = options.format
.replace(/Y/g, '9999')
.replace(/F/g, '9999')
.replace(/m/g, '19')
.replace(/d/g, '39')
.replace(/H/g, '29')
.replace(/i/g, '59')
.replace(/s/g, '59');
}
if ($.type(options.mask) === 'string') {
if (!isValidValue(options.mask, input.val())) {
input.val(options.mask.replace(/[0-9]/g, '_'));
}
input.on('keydown.xdsoft', function (event) {
var val = this.value,
key = event.which,
pos,
digit;
if (((key >= KEY0 && key <= KEY9) || (key >= _KEY0 && key <= _KEY9)) || (key === BACKSPACE || key === DEL)) {
pos = getCaretPos(this);
digit = (key !== BACKSPACE && key !== DEL) ? String.fromCharCode((_KEY0 <= key && key <= _KEY9) ? key - KEY0 : key) : '_';
if ((key === BACKSPACE || key === DEL) && pos) {
pos -= 1;
digit = '_';
}
while (/[^0-9_]/.test(options.mask.substr(pos, 1)) && pos < options.mask.length && pos > 0) {
pos += (key === BACKSPACE || key === DEL) ? -1 : 1;
}
val = val.substr(0, pos) + digit + val.substr(pos + 1);
if ($.trim(val) === '') {
val = options.mask.replace(/[0-9]/g, '_');
} else {
if (pos === options.mask.length) {
event.preventDefault();
return false;
}
}
pos += (key === BACKSPACE || key === DEL) ? 0 : 1;
while (/[^0-9_]/.test(options.mask.substr(pos, 1)) && pos < options.mask.length && pos > 0) {
pos += (key === BACKSPACE || key === DEL) ? -1 : 1;
}
if (isValidValue(options.mask, val)) {
this.value = val;
setCaretPos(this, pos);
} else if ($.trim(val) === '') {
this.value = options.mask.replace(/[0-9]/g, '_');
} else {
input.trigger('error_input.xdsoft');
}
} else {
if (([AKEY, CKEY, VKEY, ZKEY, YKEY].indexOf(key) !== -1 && ctrlDown) || [ESC, ARROWUP, ARROWDOWN, ARROWLEFT, ARROWRIGHT, F5, CTRLKEY, TAB, ENTER].indexOf(key) !== -1) {
return true;
}
}
event.preventDefault();
return false;
});
}
}
if (options.validateOnBlur) {
input
.off('blur.xdsoft')
.on('blur.xdsoft', function () {
if (options.allowBlank && !$.trim($(this).val()).length) {
$(this).val(null);
datetimepicker.data('xdsoft_datetime').empty();
} else if (!Date.parseDate($(this).val(), options.format)) {
$(this).val((_xdsoft_datetime.now()).dateFormat(options.format));
datetimepicker.data('xdsoft_datetime').setCurrentTime($(this).val());
} else {
datetimepicker.data('xdsoft_datetime').setCurrentTime($(this).val());
}
datetimepicker.trigger('changedatetime.xdsoft');
});
}
options.dayOfWeekStartPrev = (options.dayOfWeekStart === 0) ? 6 : options.dayOfWeekStart - 1;
datetimepicker
.trigger('xchange.xdsoft')
.trigger('afterOpen.xdsoft');
};
datetimepicker
.data('options', options)
.on('mousedown.xdsoft', function (event) {
event.stopPropagation();
event.preventDefault();
yearselect.hide();
monthselect.hide();
return false;
});
//scroll_element = timepicker.find('.xdsoft_time_box');
timeboxparent.append(timebox);
timeboxparent.xdsoftScroller();
datetimepicker.on('afterOpen.xdsoft', function () {
timeboxparent.xdsoftScroller();
});
datetimepicker
.append(datepicker)
.append(timepicker);
if (options.withoutCopyright !== true) {
datetimepicker
.append(xdsoft_copyright);
}
datepicker
.append(mounth_picker)
.append(calendar);
$(options.parentID)
.append(datetimepicker);
XDSoft_datetime = function () {
var _this = this;
_this.now = function (norecursion) {
var d = new Date(),
date,
time;
if (!norecursion && options.defaultDate) {
date = _this.strToDate(options.defaultDate);
d.setFullYear(date.getFullYear());
d.setMonth(date.getMonth());
d.setDate(date.getDate());
}
if (options.yearOffset) {
d.setFullYear(d.getFullYear() + options.yearOffset);
}
if (!norecursion && options.defaultTime) {
time = _this.strtotime(options.defaultTime);
d.setHours(time.getHours());
d.setMinutes(time.getMinutes());
}
return d;
};
_this.isValidDate = function (d) {
if (Object.prototype.toString.call(d) !== "[object Date]") {
return false;
}
return !isNaN(d.getTime());
};
_this.setCurrentTime = function (dTime) {
_this.currentTime = (typeof dTime === 'string') ? _this.strToDateTime(dTime) : _this.isValidDate(dTime) ? dTime : _this.now();
datetimepicker.trigger('xchange.xdsoft');
};
_this.empty = function () {
_this.currentTime = null;
};
_this.getCurrentTime = function (dTime) {
return _this.currentTime;
};
_this.nextMonth = function () {
var month = _this.currentTime.getMonth() + 1,
year;
if (month === 12) {
_this.currentTime.setFullYear(_this.currentTime.getFullYear() + 1);
month = 0;
}
year = _this.currentTime.getFullYear();
_this.currentTime.setDate(
Math.min(
new Date(_this.currentTime.getFullYear(), month + 1, 0).getDate(),
_this.currentTime.getDate()
)
);
_this.currentTime.setMonth(month);
if (options.onChangeMonth && $.isFunction(options.onChangeMonth)) {
options.onChangeMonth.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
}
if (year !== _this.currentTime.getFullYear() && $.isFunction(options.onChangeYear)) {
options.onChangeYear.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
}
datetimepicker.trigger('xchange.xdsoft');
return month;
};
_this.prevMonth = function () {
var month = _this.currentTime.getMonth() - 1;
if (month === -1) {
_this.currentTime.setFullYear(_this.currentTime.getFullYear() - 1);
month = 11;
}
_this.currentTime.setDate(
Math.min(
new Date(_this.currentTime.getFullYear(), month + 1, 0).getDate(),
_this.currentTime.getDate()
)
);
_this.currentTime.setMonth(month);
if (options.onChangeMonth && $.isFunction(options.onChangeMonth)) {
options.onChangeMonth.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
}
datetimepicker.trigger('xchange.xdsoft');
return month;
};
_this.getWeekOfYear = function (datetime) {
var onejan = new Date(datetime.getFullYear(), 0, 1);
return Math.ceil((((datetime - onejan) / 86400000) + onejan.getDay() + 1) / 7);
};
_this.strToDateTime = function (sDateTime) {
var tmpDate = [], timeOffset, currentTime;
if (sDateTime && sDateTime instanceof Date && _this.isValidDate(sDateTime)) {
return sDateTime;
}
tmpDate = /^(\+|\-)(.*)$/.exec(sDateTime);
if (tmpDate) {
tmpDate[2] = Date.parseDate(tmpDate[2], options.formatDate);
}
if (tmpDate && tmpDate[2]) {
timeOffset = tmpDate[2].getTime() - (tmpDate[2].getTimezoneOffset()) * 60000;
currentTime = new Date((_xdsoft_datetime.now()).getTime() + parseInt(tmpDate[1] + '1', 10) * timeOffset);
} else {
currentTime = sDateTime ? Date.parseDate(sDateTime, options.format) : _this.now();
}
if (!_this.isValidDate(currentTime)) {
currentTime = _this.now();
}
return currentTime;
};
_this.strToDate = function (sDate) {
if (sDate && sDate instanceof Date && _this.isValidDate(sDate)) {
return sDate;
}
var currentTime = sDate ? Date.parseDate(sDate, options.formatDate) : _this.now(true);
if (!_this.isValidDate(currentTime)) {
currentTime = _this.now(true);
}
return currentTime;
};
_this.strtotime = function (sTime) {
if (sTime && sTime instanceof Date && _this.isValidDate(sTime)) {
return sTime;
}
var currentTime = sTime ? Date.parseDate(sTime, options.formatTime) : _this.now(true);
if (!_this.isValidDate(currentTime)) {
currentTime = _this.now(true);
}
return currentTime;
};
_this.str = function () {
return _this.currentTime.dateFormat(options.format);
};
_this.currentTime = this.now();
};
_xdsoft_datetime = new XDSoft_datetime();
mounth_picker
.find('.xdsoft_today_button')
.on('mousedown.xdsoft', function () {
datetimepicker.data('changed', true);
_xdsoft_datetime.setCurrentTime(0);
datetimepicker.trigger('afterOpen.xdsoft');
}).on('dblclick.xdsoft', function () {
input.val(_xdsoft_datetime.str());
datetimepicker.trigger('close.xdsoft');
});
mounth_picker
.find('.xdsoft_prev,.xdsoft_next')
.on('mousedown.xdsoft', function () {
var $this = $(this),
timer = 0,
stop = false;
(function arguments_callee1(v) {
var month = _xdsoft_datetime.currentTime.getMonth();
if ($this.hasClass(options.next)) {
_xdsoft_datetime.nextMonth();
} else if ($this.hasClass(options.prev)) {
_xdsoft_datetime.prevMonth();
}
if (options.monthChangeSpinner) {
if (!stop) {
timer = setTimeout(arguments_callee1, v || 100);
}
}
}(500));
$([document.body, window]).on('mouseup.xdsoft', function arguments_callee2() {
clearTimeout(timer);
stop = true;
$([document.body, window]).off('mouseup.xdsoft', arguments_callee2);
});
});
timepicker
.find('.xdsoft_prev,.xdsoft_next')
.on('mousedown.xdsoft', function () {
var $this = $(this),
timer = 0,
stop = false,
period = 110;
(function arguments_callee4(v) {
var pheight = timeboxparent[0].clientHeight,
height = timebox[0].offsetHeight,
top = Math.abs(parseInt(timebox.css('marginTop'), 10));
if ($this.hasClass(options.next) && (height - pheight) - options.timeHeightInTimePicker >= top) {
timebox.css('marginTop', '-' + (top + options.timeHeightInTimePicker) + 'px');
} else if ($this.hasClass(options.prev) && top - options.timeHeightInTimePicker >= 0) {
timebox.css('marginTop', '-' + (top - options.timeHeightInTimePicker) + 'px');
}
timeboxparent.trigger('scroll_element.xdsoft_scroller', [Math.abs(parseInt(timebox.css('marginTop'), 10) / (height - pheight))]);
period = (period > 10) ? 10 : period - 10;
if (!stop) {
timer = setTimeout(arguments_callee4, v || period);
}
}(500));
$([document.body, window]).on('mouseup.xdsoft', function arguments_callee5() {
clearTimeout(timer);
stop = true;
$([document.body, window])
.off('mouseup.xdsoft', arguments_callee5);
});
});
xchangeTimer = 0;
// base handler - generating a calendar and timepicker
datetimepicker
.on('xchange.xdsoft', function (event) {
clearTimeout(xchangeTimer);
xchangeTimer = setTimeout(function () {
var table = '',
start = new Date(_xdsoft_datetime.currentTime.getFullYear(), _xdsoft_datetime.currentTime.getMonth(), 1, 12, 0, 0),
i = 0,
j,
today = _xdsoft_datetime.now(),
maxDate = false,
minDate = false,
d,
y,
m,
w,
classes = [],
customDateSettings,
newRow = true,
time = '',
h = '',
line_time;
while (start.getDay() !== options.dayOfWeekStart) {
start.setDate(start.getDate() - 1);
}
table += '<table><thead><tr>';
if (options.weeks) {
table += '<th></th>';
}
for (j = 0; j < 7; j += 1) {
table += '<th>' + options.i18n[options.lang].dayOfWeek[(j + options.dayOfWeekStart) % 7] + '</th>';
}
table += '</tr></thead>';
table += '<tbody>';
if (options.maxDate !== false) {
maxDate = _xdsoft_datetime.strToDate(options.maxDate);
maxDate = new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate(), 23, 59, 59, 999);
}
if (options.minDate !== false) {
minDate = _xdsoft_datetime.strToDate(options.minDate);
minDate = new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate());
}
while (i < _xdsoft_datetime.currentTime.countDaysInMonth() || start.getDay() !== options.dayOfWeekStart || _xdsoft_datetime.currentTime.getMonth() === start.getMonth()) {
classes = [];
i += 1;
d = start.getDate();
y = start.getFullYear();
m = start.getMonth();
w = _xdsoft_datetime.getWeekOfYear(start);
classes.push('xdsoft_date');
if (options.beforeShowDay && $.isFunction(options.beforeShowDay.call)) {
customDateSettings = options.beforeShowDay.call(datetimepicker, start);
} else {
customDateSettings = null;
}
if ((maxDate !== false && start > maxDate) || (minDate !== false && start < minDate) || (customDateSettings && customDateSettings[0] === false)) {
classes.push('xdsoft_disabled');
} else if (options.disabledDates.indexOf(start.dateFormat(options.formatDate)) !== -1) {
classes.push('xdsoft_disabled');
}
if (customDateSettings && customDateSettings[1] !== "") {
classes.push(customDateSettings[1]);
}
if (_xdsoft_datetime.currentTime.getMonth() !== m) {
classes.push('xdsoft_other_month');
}
if ((options.defaultSelect || datetimepicker.data('changed')) && _xdsoft_datetime.currentTime.dateFormat(options.formatDate) === start.dateFormat(options.formatDate)) {
classes.push('xdsoft_current');
}
if (today.dateFormat(options.formatDate) === start.dateFormat(options.formatDate)) {
classes.push('xdsoft_today');
}
if (start.getDay() === 0 || start.getDay() === 6 || ~options.weekends.indexOf(start.dateFormat(options.formatDate))) {
classes.push('xdsoft_weekend');
}
if (options.beforeShowDay && $.isFunction(options.beforeShowDay)) {
classes.push(options.beforeShowDay(start));
}
if (newRow) {
table += '<tr>';
newRow = false;
if (options.weeks) {
table += '<th>' + w + '</th>';
}
}
table += '<td data-date="' + d + '" data-month="' + m + '" data-year="' + y + '"' + ' class="xdsoft_date xdsoft_day_of_week' + start.getDay() + ' ' + classes.join(' ') + '">' +
'<div>' + d + '</div>' +
'</td>';
if (start.getDay() === options.dayOfWeekStartPrev) {
table += '</tr>';
newRow = true;
}
start.setDate(d + 1);
}
table += '</tbody></table>';
calendar.html(table);
mounth_picker.find('.xdsoft_label span').eq(0).text(options.i18n[options.lang].months[_xdsoft_datetime.currentTime.getMonth()]);
mounth_picker.find('.xdsoft_label span').eq(1).text(_xdsoft_datetime.currentTime.getFullYear());
// generate timebox
time = '';
h = '';
m = '';
line_time = function line_time(h, m) {
var now = _xdsoft_datetime.now();
now.setHours(h);
h = parseInt(now.getHours(), 10);
now.setMinutes(m);
m = parseInt(now.getMinutes(), 10);
var optionDateTime = new Date(_xdsoft_datetime.currentTime);
optionDateTime.setHours(h);
optionDateTime.setMinutes(m);
classes = [];
if ((options.minDateTime !== false && options.minDateTime > optionDateTime) || (options.maxTime !== false && _xdsoft_datetime.strtotime(options.maxTime).getTime() < now.getTime()) || (options.minTime !== false && _xdsoft_datetime.strtotime(options.minTime).getTime() > now.getTime())) {
classes.push('xdsoft_disabled');
}
if ((options.initTime || options.defaultSelect || datetimepicker.data('changed')) && parseInt(_xdsoft_datetime.currentTime.getHours(), 10) === parseInt(h, 10) && (options.step > 59 || Math[options.roundTime](_xdsoft_datetime.currentTime.getMinutes() / options.step) * options.step === parseInt(m, 10))) {
if (options.defaultSelect || datetimepicker.data('changed')) {
classes.push('xdsoft_current');
} else if (options.initTime) {
classes.push('xdsoft_init_time');
}
}
if (parseInt(today.getHours(), 10) === parseInt(h, 10) && parseInt(today.getMinutes(), 10) === parseInt(m, 10)) {
classes.push('xdsoft_today');
}
time += '<div class="xdsoft_time ' + classes.join(' ') + '" data-hour="' + h + '" data-minute="' + m + '">' + now.dateFormat(options.formatTime) + '</div>';
};
if (!options.allowTimes || !$.isArray(options.allowTimes) || !options.allowTimes.length) {
for (i = 0, j = 0; i < (options.hours12 ? 12 : 24); i += 1) {
for (j = 0; j < 60; j += options.step) {
h = (i < 10 ? '0' : '') + i;
m = (j < 10 ? '0' : '') + j;
line_time(h, m);
}
}
} else {
for (i = 0; i < options.allowTimes.length; i += 1) {
h = _xdsoft_datetime.strtotime(options.allowTimes[i]).getHours();
m = _xdsoft_datetime.strtotime(options.allowTimes[i]).getMinutes();
line_time(h, m);
}
}
timebox.html(time);
opt = '';
i = 0;
for (i = parseInt(options.yearStart, 10) + options.yearOffset; i <= parseInt(options.yearEnd, 10) + options.yearOffset; i += 1) {
opt += '<div class="xdsoft_option ' + (_xdsoft_datetime.currentTime.getFullYear() === i ? 'xdsoft_current' : '') + '" data-value="' + i + '">' + i + '</div>';
}
yearselect.children().eq(0)
.html(opt);
for (i = 0, opt = ''; i <= 11; i += 1) {
opt += '<div class="xdsoft_option ' + (_xdsoft_datetime.currentTime.getMonth() === i ? 'xdsoft_current' : '') + '" data-value="' + i + '">' + options.i18n[options.lang].months[i] + '</div>';
}
monthselect.children().eq(0).html(opt);
$(datetimepicker)
.trigger('generate.xdsoft');
}, 10);
event.stopPropagation();
})
.on('afterOpen.xdsoft', function () {
if (options.timepicker) {
var classType, pheight, height, top;
if (timebox.find('.xdsoft_current').length) {
classType = '.xdsoft_current';
} else if (timebox.find('.xdsoft_init_time').length) {
classType = '.xdsoft_init_time';
}
if (classType) {
pheight = timeboxparent[0].clientHeight;
height = timebox[0].offsetHeight;
top = timebox.find(classType).index() * options.timeHeightInTimePicker + 1;
if ((height - pheight) < top) {
top = height - pheight;
}
timeboxparent.trigger('scroll_element.xdsoft_scroller', [parseInt(top, 10) / (height - pheight)]);
} else {
timeboxparent.trigger('scroll_element.xdsoft_scroller', [0]);
}
}
});
timerclick = 0;
calendar
.on('click.xdsoft', 'td', function (xdevent) {
xdevent.stopPropagation(); // Prevents closing of Pop-ups, Modals and Flyouts in Bootstrap
timerclick += 1;
var $this = $(this),
currentTime = _xdsoft_datetime.currentTime;
if (currentTime === undefined || currentTime === null) {
_xdsoft_datetime.currentTime = _xdsoft_datetime.now();
currentTime = _xdsoft_datetime.currentTime;
}
if ($this.hasClass('xdsoft_disabled')) {
return false;
}
currentTime.setDate(1);
currentTime.setFullYear($this.data('year'));
currentTime.setMonth($this.data('month'));
currentTime.setDate($this.data('date'));
datetimepicker.trigger('select.xdsoft', [currentTime]);
input.val(_xdsoft_datetime.str());
if ((timerclick > 1 || (options.closeOnDateSelect === true || (options.closeOnDateSelect === 0 && !options.timepicker))) && !options.inline) {
datetimepicker.trigger('close.xdsoft');
}
if (options.onSelectDate && $.isFunction(options.onSelectDate)) {
options.onSelectDate.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), xdevent);
}
datetimepicker.data('changed', true);
datetimepicker.trigger('xchange.xdsoft');
datetimepicker.trigger('changedatetime.xdsoft');
setTimeout(function () {
timerclick = 0;
}, 200);
});
timebox
.on('click.xdsoft', 'div', function (xdevent) {
xdevent.stopPropagation();
var $this = $(this),
currentTime = _xdsoft_datetime.currentTime;
if (currentTime === undefined || currentTime === null) {
_xdsoft_datetime.currentTime = _xdsoft_datetime.now();
currentTime = _xdsoft_datetime.currentTime;
}
if ($this.hasClass('xdsoft_disabled')) {
return false;
}
currentTime.setHours($this.data('hour'));
currentTime.setMinutes($this.data('minute'));
datetimepicker.trigger('select.xdsoft', [currentTime]);
datetimepicker.data('input').val(_xdsoft_datetime.str());
if (!options.inline) {
datetimepicker.trigger('close.xdsoft');
}
if (options.onSelectTime && $.isFunction(options.onSelectTime)) {
options.onSelectTime.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), xdevent);
}
datetimepicker.data('changed', true);
datetimepicker.trigger('xchange.xdsoft');
datetimepicker.trigger('changedatetime.xdsoft');
});
datepicker
.on('wheel.xdsoft', function (event) {
if (!options.scrollMonth) {
return true;
}
if (event.deltaY < 0) {
_xdsoft_datetime.nextMonth();
} else {
_xdsoft_datetime.prevMonth();
}
return false;
});
input
.on('wheel.xdsoft', function (event) {
if (!options.scrollInput) {
return true;
}
if (!options.datepicker && options.timepicker) {
current_time_index = timebox.find('.xdsoft_current').length ? timebox.find('.xdsoft_current').eq(0).index() : 0;
if (current_time_index + event.deltaY >= 0 && current_time_index + event.deltaY < timebox.children().length) {
current_time_index += event.deltaY;
}
if (timebox.children().eq(current_time_index).length) {
timebox.children().eq(current_time_index).trigger('mousedown');
}
return false;
}
if (options.datepicker && !options.timepicker) {
datepicker.trigger(event, [event.deltaY, event.deltaX, event.deltaY]);
if (input.val) {
input.val(_xdsoft_datetime.str());
}
datetimepicker.trigger('changedatetime.xdsoft');
return false;
}
});
datetimepicker
.on('changedatetime.xdsoft', function (event) {
if (options.onChangeDateTime && $.isFunction(options.onChangeDateTime)) {
var $input = datetimepicker.data('input');
options.onChangeDateTime.call(datetimepicker, _xdsoft_datetime.currentTime, $input, event);
delete options.value;
$input.trigger('change');
}
})
.on('generate.xdsoft', function () {
if (options.onGenerate && $.isFunction(options.onGenerate)) {
options.onGenerate.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'));
}
if (triggerAfterOpen) {
datetimepicker.trigger('afterOpen.xdsoft');
triggerAfterOpen = false;
}
})
.on('click.xdsoft', function (xdevent) {
xdevent.stopPropagation();
});
current_time_index = 0;
setPos = function () {
var offset = datetimepicker.data('input').offset(),
top = offset.top + datetimepicker.data('input')[0].offsetHeight - 1, left = offset.left,
position = "absolute";
if (options.fixed) {
top -= $(window).scrollTop();
left -= $(window).scrollLeft();
position = "fixed";
} else {
if (top + datetimepicker[0].offsetHeight > $(window).height() + $(window).scrollTop()) {
top = offset.top - datetimepicker[0].offsetHeight + 1;
}
if (top < 0) {
top = 0;
}
if (left + datetimepicker[0].offsetWidth > $(window).width()) {
left = $(window).width() - datetimepicker[0].offsetWidth;
}
}
datetimepicker.css({
left: left,
top: top,
position: position
});
};
datetimepicker
.on('open.xdsoft', function (event) {
var onShow = true;
if (options.onShow && $.isFunction(options.onShow)) {
onShow = options.onShow.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), event);
}
if (onShow !== false) {
datetimepicker.show();
setPos();
$(window)
.off('resize.xdsoft', setPos)
.on('resize.xdsoft', setPos);
if (options.closeOnWithoutClick) {
$([document.body, window]).on('mousedown.xdsoft', function arguments_callee6() {
datetimepicker.trigger('close.xdsoft');
$([document.body, window]).off('mousedown.xdsoft', arguments_callee6);
});
}
}
})
.on('close.xdsoft', function (event) {
var onClose = true;
mounth_picker
.find('.xdsoft_month,.xdsoft_year')
.find('.xdsoft_select')
.hide();
if (options.onClose && $.isFunction(options.onClose)) {
onClose = options.onClose.call(datetimepicker, _xdsoft_datetime.currentTime, datetimepicker.data('input'), event);
}
if (onClose !== false && !options.opened && !options.inline) {
datetimepicker.hide();
}
event.stopPropagation();
})
.on('toggle.xdsoft', function (event) {
if (datetimepicker.is(':visible')) {
datetimepicker.trigger('close.xdsoft');
} else {
datetimepicker.trigger('open.xdsoft');
}
})
.data('input', input);
timer = 0;
timer1 = 0;
datetimepicker.data('xdsoft_datetime', _xdsoft_datetime);
datetimepicker.setOptions(options);
function getCurrentValue() {
var ct = false, time;
if (options.startDate) {
ct = _xdsoft_datetime.strToDate(options.startDate);
} else {
ct = options.value || ((input && input.val && input.val()) ? input.val() : '');
if (ct) {
ct = _xdsoft_datetime.strToDateTime(ct);
} else if (options.defaultDate) {
ct = _xdsoft_datetime.strToDate(options.defaultDate);
if (options.defaultTime) {
time = _xdsoft_datetime.strtotime(options.defaultTime);
ct.setHours(time.getHours());
ct.setMinutes(time.getMinutes());
}
}
}
if (ct && _xdsoft_datetime.isValidDate(ct)) {
datetimepicker.data('changed', true);
} else {
ct = '';
}
return ct || 0;
}
_xdsoft_datetime.setCurrentTime(getCurrentValue());
input
.data('xdsoft_datetimepicker', datetimepicker)
.on('open.xdsoft focusin.xdsoft mousedown.xdsoft', function (event) {
if (input.is(':disabled') || (input.data('xdsoft_datetimepicker').is(':visible') && options.closeOnInputClick)) {
return;
}
clearTimeout(timer);
timer = setTimeout(function () {
if (input.is(':disabled')) {
return;
}
triggerAfterOpen = true;
_xdsoft_datetime.setCurrentTime(getCurrentValue());
datetimepicker.trigger('open.xdsoft');
}, 100);
})
.on('keydown.xdsoft', function (event) {
var val = this.value, elementSelector,
key = event.which;
if ([ENTER].indexOf(key) !== -1 && options.enterLikeTab) {
elementSelector = $("input:visible,textarea:visible");
datetimepicker.trigger('close.xdsoft');
elementSelector.eq(elementSelector.index(this) + 1).focus();
return false;
}
if ([TAB].indexOf(key) !== -1) {
datetimepicker.trigger('close.xdsoft');
return true;
}
});
};
destroyDateTimePicker = function (input) {
var datetimepicker = input.data('xdsoft_datetimepicker');
if (datetimepicker) {
datetimepicker.data('xdsoft_datetime', null);
datetimepicker.remove();
input
.data('xdsoft_datetimepicker', null)
.off('.xdsoft');
$(window).off('resize.xdsoft');
$([window, document.body]).off('mousedown.xdsoft');
if (input.unmousewheel) {
input.unmousewheel();
}
}
};
$(document)
.off('keydown.xdsoftctrl keyup.xdsoftctrl')
.on('keydown.xdsoftctrl', function (e) {
if (e.keyCode === CTRLKEY) {
ctrlDown = true;
}
})
.on('keyup.xdsoftctrl', function (e) {
if (e.keyCode === CTRLKEY) {
ctrlDown = false;
}
});
return this.each(function () {
var datetimepicker = $(this).data('xdsoft_datetimepicker');
if (datetimepicker) {
if ($.type(opt) === 'string') {
switch (opt) {
case 'show':
$(this).select().focus();
datetimepicker.trigger('open.xdsoft');
break;
case 'hide':
datetimepicker.trigger('close.xdsoft');
break;
case 'toggle':
datetimepicker.trigger('toggle.xdsoft');
break;
case 'destroy':
destroyDateTimePicker($(this));
break;
case 'reset':
this.value = this.defaultValue;
if (!this.value || !datetimepicker.data('xdsoft_datetime').isValidDate(Date.parseDate(this.value, options.format))) {
datetimepicker.data('changed', false);
}
datetimepicker.data('xdsoft_datetime').setCurrentTime(this.value);
break;
}
} else {
datetimepicker
.setOptions(opt);
}
return 0;
}
if ($.type(opt) !== 'string') {
if (!options.lazyInit || options.open || options.inline) {
createDateTimePicker($(this));
} else {
lazyInit($(this));
}
}
});
};
$.fn.datetimepicker.defaults = default_options;
/*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh)
* Licensed under the MIT License (LICENSE.txt).
*
* Version: 3.1.12
*
* Requires: jQuery 1.2.2+
*/
(function (a) {
function b(b) {
var g = b || window.event, h = i.call(arguments, 1), j = 0, l = 0, m = 0, n = 0, o = 0, p = 0;
if (b = a.event.fix(g), b.type = "mousewheel", "detail" in g && (m = -1 * g.detail), "wheelDelta" in g && (m = g.wheelDelta), "wheelDeltaY" in g && (m = g.wheelDeltaY), "wheelDeltaX" in g && (l = -1 * g.wheelDeltaX), "axis" in g && g.axis === g.HORIZONTAL_AXIS && (l = -1 * m, m = 0), j = 0 === m ? l : m, "deltaY" in g && (m = -1 * g.deltaY, j = m), "deltaX" in g && (l = g.deltaX, 0 === m && (j = -1 * l)), 0 !== m || 0 !== l) {
if (1 === g.deltaMode) {
var q = a.data(this, "mousewheel-line-height");
j *= q, m *= q, l *= q
} else if (2 === g.deltaMode) {
var r = a.data(this, "mousewheel-page-height");
j *= r, m *= r, l *= r
}
if (n = Math.max(Math.abs(m), Math.abs(l)), (!f || f > n) && (f = n, d(g, n) && (f /= 40)), d(g, n) && (j /= 40, l /= 40, m /= 40), j = Math[j >= 1 ? "floor" : "ceil"](j / f), l = Math[l >= 1 ? "floor" : "ceil"](l / f), m = Math[m >= 1 ? "floor" : "ceil"](m / f), k.settings.normalizeOffset && this.getBoundingClientRect) {
var s = this.getBoundingClientRect();
o = b.clientX - s.left, p = b.clientY - s.top
}
return b.deltaX = l, b.deltaY = m, b.deltaFactor = f, b.offsetX = o, b.offsetY = p, b.deltaMode = 0, h.unshift(b, j, l, m), e && clearTimeout(e), e = setTimeout(c, 200), (a.event.dispatch || a.event.handle).apply(this, h)
}
}
function c() {
f = null
}
function d(a, b) {
return k.settings.adjustOldDeltas && "mousewheel" === a.type && b % 120 === 0
}
var e, f, g = ["wheel", "mousewheel", "DOMMouseScroll", "MozMousePixelScroll"],
h = "onwheel" in document || document.documentMode >= 9 ? ["wheel"] : ["mousewheel", "DomMouseScroll", "MozMousePixelScroll"],
i = Array.prototype.slice;
if (a.event.fixHooks) for (var j = g.length; j;) a.event.fixHooks[g[--j]] = a.event.mouseHooks;
var k = a.event.special.mousewheel = {
version: "3.1.12", setup: function () {
if (this.addEventListener) for (var c = h.length; c;) this.addEventListener(h[--c], b, !1); else this.onmousewheel = b;
a.data(this, "mousewheel-line-height", k.getLineHeight(this)), a.data(this, "mousewheel-page-height", k.getPageHeight(this))
}, teardown: function () {
if (this.removeEventListener) for (var c = h.length; c;) this.removeEventListener(h[--c], b, !1); else this.onmousewheel = null;
a.removeData(this, "mousewheel-line-height"), a.removeData(this, "mousewheel-page-height")
}, getLineHeight: function (b) {
var c = a(b), d = c["offsetParent" in a.fn ? "offsetParent" : "parent"]();
return d.length || (d = a("body")), parseInt(d.css("fontSize"), 10) || parseInt(c.css("fontSize"), 10) || 16
}, getPageHeight: function (b) {
return a(b).height()
}, settings: {adjustOldDeltas: !0, normalizeOffset: !0}
};
a.fn.extend({
mousewheel: function (a) {
return a ? this.bind("mousewheel", a) : this.trigger("mousewheel")
}, unmousewheel: function (a) {
return this.unbind("mousewheel", a)
}
})
})($);
// Parse and Format Library
//http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
/*
* Copyright (C) 2004 Baron Schwartz <baron at sequent dot org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
Date.parseFunctions = {count: 0};
Date.parseRegexes = [];
Date.formatFunctions = {count: 0};
Date.prototype.dateFormat = function (b) {
if (b == "unixtime") {
return parseInt(this.getTime() / 1000);
}
if (Date.formatFunctions[b] == null) {
Date.createNewFormat(b);
}
var a = Date.formatFunctions[b];
return this[a]();
};
Date.createNewFormat = function (format) {
var funcName = "format" + Date.formatFunctions.count++;
Date.formatFunctions[format] = funcName;
var code = "Date.prototype." + funcName + " = function() {return ";
var special = false;
var ch = "";
for (var i = 0; i < format.length; ++i) {
ch = format.charAt(i);
if (!special && ch == "\\") {
special = true;
} else {
if (special) {
special = false;
code += "'" + String.escape(ch) + "' + ";
} else {
code += Date.getFormatCode(ch);
}
}
}
eval(code.substring(0, code.length - 3) + ";}");
};
Date.getFormatCode = function (a) {
switch (a) {
case"d":
return "String.leftPad(this.getDate(), 2, '0') + ";
case"D":
return "Date.dayNames[this.getDay()].substring(0, 3) + ";
case"j":
return "this.getDate() + ";
case"l":
return "Date.dayNames[this.getDay()] + ";
case"S":
return "this.getSuffix() + ";
case"w":
return "this.getDay() + ";
case"z":
return "this.getDayOfYear() + ";
case"W":
return "this.getWeekOfYear() + ";
case"F":
return "Date.monthNames[this.getMonth()] + ";
case"m":
return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
case"M":
return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
case"n":
return "(this.getMonth() + 1) + ";
case"t":
return "this.getDaysInMonth() + ";
case"L":
return "(this.isLeapYear() ? 1 : 0) + ";
case"Y":
return "this.getFullYear() + ";
case"y":
return "('' + this.getFullYear()).substring(2, 4) + ";
case"a":
return "(this.getHours() < 12 ? 'am' : 'pm') + ";
case"A":
return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
case"g":
return "((this.getHours() %12) ? this.getHours() % 12 : 12) + ";
case"G":
return "this.getHours() + ";
case"h":
return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + ";
case"H":
return "String.leftPad(this.getHours(), 2, '0') + ";
case"i":
return "String.leftPad(this.getMinutes(), 2, '0') + ";
case"s":
return "String.leftPad(this.getSeconds(), 2, '0') + ";
case"O":
return "this.getGMTOffset() + ";
case"T":
return "this.getTimezone() + ";
case"Z":
return "(this.getTimezoneOffset() * -60) + ";
default:
return "'" + String.escape(a) + "' + ";
}
};
Date.parseDate = function (a, c) {
if (c == "unixtime") {
return new Date(!isNaN(parseInt(a)) ? parseInt(a) * 1000 : 0);
}
if (Date.parseFunctions[c] == null) {
Date.createParser(c);
}
var b = Date.parseFunctions[c];
return Date[b](a);
};
Date.createParser = function (format) {
var funcName = "parse" + Date.parseFunctions.count++;
var regexNum = Date.parseRegexes.length;
var currentGroup = 1;
Date.parseFunctions[format] = funcName;
var code = "Date." + funcName + " = function(input) {\nvar y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, z = -1;\nvar d = new Date();\ny = d.getFullYear();\nm = d.getMonth();\nd = d.getDate();\nvar results = input.match(Date.parseRegexes[" + regexNum + "]);\nif (results && results.length > 0) {";
var regex = "";
var special = false;
var ch = "";
for (var i = 0; i < format.length; ++i) {
ch = format.charAt(i);
if (!special && ch == "\\") {
special = true;
} else {
if (special) {
special = false;
regex += String.escape(ch);
} else {
var obj = Date.formatCodeToRegex(ch, currentGroup);
currentGroup += obj.g;
regex += obj.s;
if (obj.g && obj.c) {
code += obj.c;
}
}
}
}
code += "if (y > 0 && z > 0){\nvar doyDate = new Date(y,0);\ndoyDate.setDate(z);\nm = doyDate.getMonth();\nd = doyDate.getDate();\n}";
code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n{return new Date(y, m, d, h, i, s);}\nelse if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n{return new Date(y, m, d, h, i);}\nelse if (y > 0 && m >= 0 && d > 0 && h >= 0)\n{return new Date(y, m, d, h);}\nelse if (y > 0 && m >= 0 && d > 0)\n{return new Date(y, m, d);}\nelse if (y > 0 && m >= 0)\n{return new Date(y, m);}\nelse if (y > 0)\n{return new Date(y);}\n}return null;}";
Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
eval(code);
};
Date.formatCodeToRegex = function (b, a) {
switch (b) {
case"D":
return {g: 0, c: null, s: "(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
case"j":
case"d":
return {g: 1, c: "d = parseInt(results[" + a + "], 10);\n", s: "(\\d{1,2})"};
case"l":
return {g: 0, c: null, s: "(?:" + Date.dayNames.join("|") + ")"};
case"S":
return {g: 0, c: null, s: "(?:st|nd|rd|th)"};
case"w":
return {g: 0, c: null, s: "\\d"};
case"z":
return {g: 1, c: "z = parseInt(results[" + a + "], 10);\n", s: "(\\d{1,3})"};
case"W":
return {g: 0, c: null, s: "(?:\\d{2})"};
case"F":
return {
g: 1,
c: "m = parseInt(Date.monthNumbers[results[" + a + "].substring(0, 3)], 10);\n",
s: "(" + Date.monthNames.join("|") + ")"
};
case"M":
return {
g: 1,
c: "m = parseInt(Date.monthNumbers[results[" + a + "]], 10);\n",
s: "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"
};
case"n":
case"m":
return {g: 1, c: "m = parseInt(results[" + a + "], 10) - 1;\n", s: "(\\d{1,2})"};
case"t":
return {g: 0, c: null, s: "\\d{1,2}"};
case"L":
return {g: 0, c: null, s: "(?:1|0)"};
case"Y":
return {g: 1, c: "y = parseInt(results[" + a + "], 10);\n", s: "(\\d{4})"};
case"y":
return {
g: 1,
c: "var ty = parseInt(results[" + a + "], 10);\ny = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
s: "(\\d{1,2})"
};
case"a":
return {
g: 1,
c: "if (results[" + a + "] == 'am') {\nif (h == 12) { h = 0; }\n} else { if (h < 12) { h += 12; }}",
s: "(am|pm)"
};
case"A":
return {
g: 1,
c: "if (results[" + a + "] == 'AM') {\nif (h == 12) { h = 0; }\n} else { if (h < 12) { h += 12; }}",
s: "(AM|PM)"
};
case"g":
case"G":
case"h":
case"H":
return {g: 1, c: "h = parseInt(results[" + a + "], 10);\n", s: "(\\d{1,2})"};
case"i":
return {g: 1, c: "i = parseInt(results[" + a + "], 10);\n", s: "(\\d{2})"};
case"s":
return {g: 1, c: "s = parseInt(results[" + a + "], 10);\n", s: "(\\d{2})"};
case"O":
return {g: 0, c: null, s: "[+-]\\d{4}"};
case"T":
return {g: 0, c: null, s: "[A-Z]{3}"};
case"Z":
return {g: 0, c: null, s: "[+-]\\d{1,5}"};
default:
return {g: 0, c: null, s: String.escape(b)};
}
};
Date.prototype.getTimezone = function () {
return this.toString().replace(/^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3");
};
Date.prototype.getGMTOffset = function () {
return (this.getTimezoneOffset() > 0 ? "-" : "+") + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, "0") + String.leftPad(Math.abs(this.getTimezoneOffset()) % 60, 2, "0");
};
Date.prototype.getDayOfYear = function () {
var a = 0;
Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
for (var b = 0; b < this.getMonth(); ++b) {
a += Date.daysInMonth[b];
}
return a + this.getDate();
};
Date.prototype.getWeekOfYear = function () {
var b = this.getDayOfYear() + (4 - this.getDay());
var a = new Date(this.getFullYear(), 0, 1);
var c = (7 - a.getDay() + 4);
return String.leftPad(Math.ceil((b - c) / 7) + 1, 2, "0");
};
Date.prototype.isLeapYear = function () {
var a = this.getFullYear();
return ((a & 3) == 0 && (a % 100 || (a % 400 == 0 && a)));
};
Date.prototype.getFirstDayOfMonth = function () {
var a = (this.getDay() - (this.getDate() - 1)) % 7;
return (a < 0) ? (a + 7) : a;
};
Date.prototype.getLastDayOfMonth = function () {
var a = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
return (a < 0) ? (a + 7) : a;
};
Date.prototype.getDaysInMonth = function () {
Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
return Date.daysInMonth[this.getMonth()];
};
Date.prototype.getSuffix = function () {
switch (this.getDate()) {
case 1:
case 21:
case 31:
return "st";
case 2:
case 22:
return "nd";
case 3:
case 23:
return "rd";
default:
return "th";
}
};
String.escape = function (a) {
return a.replace(/('|\\)/g, "\\$1");
};
String.leftPad = function (d, b, c) {
var a = new String(d);
if (c == null) {
c = " ";
}
while (a.length < b) {
a = c + a;
}
return a;
};
Date.daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
Date.monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
Date.dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
Date.y2kYear = 50;
Date.monthNumbers = {
Jan: 0,
Feb: 1,
Mar: 2,
Apr: 3,
May: 4,
Jun: 5,
Jul: 6,
Aug: 7,
Sep: 8,
Oct: 9,
Nov: 10,
Dec: 11
};
Date.patterns = {
ISO8601LongPattern: "Y-m-d H:i:s",
ISO8601ShortPattern: "Y-m-d",
ShortDatePattern: "n/j/Y",
LongDatePattern: "l, F d, Y",
FullDateTimePattern: "l, F d, Y g:i:s A",
MonthDayPattern: "F d",
ShortTimePattern: "g:i A",
LongTimePattern: "g:i:s A",
SortableDateTimePattern: "Y-m-d\\TH:i:s",
UniversalSortableDateTimePattern: "Y-m-d H:i:sO",
YearMonthPattern: "F, Y"
};
});
/**
* jquery.unique-element-id.js
*
* A simple jQuery plugin to get a unique ID for
* any HTML element
*
* Usage:
* $('some_element_selector').uid();
*
* by Jamie Rumbelow <jamie@jamierumbelow.net>
* http://jamieonsoftware.com
* Copyright (c)2011 Jamie Rumbelow
*
* Licensed under the MIT license (http://www.opensource.org/licenses/MIT)
*/
N2R('$', function ($) {
/**
* Generate a new unqiue ID
*/
function generateUniqueId(prefix) {
// Return a unique ID
return prefix + Math.floor((1 + Math.random()) * 0x1000000000000)
.toString(16);
}
/**
* Get a unique ID for an element, ensuring that the
* element has an id="" attribute
*/
$.fn.uid = function (prefix) {
var id = null;
prefix = prefix || "n";
do {
id = generateUniqueId(prefix);
} while ($('#' + id).length > 0);
return id;
};
$.fn.generateUniqueClass = function (prefix) {
var id = null;
prefix = prefix || "n";
do {
id = generateUniqueId(prefix);
} while ($('.' + id).length > 0);
return id;
};
});
N2D('nUIAutocomplete', ['nUIWidgetBase'], function ($, undefined) {
"use strict";
/**
* @memberOf N2Classes
*
* @constructor
* @augments nUIWidgetBase
* @this nUIAutocomplete
*/
function nUIAutocomplete(element, options) {
this.isRendered = false;
this.element = $(element);
this.widgetName = this.widgetName || 'nUIAutocomplete';
this.widgetEventPrefix = "autocomplete";
this.isActive = false;
this.allowBlur = true;
this.options = $.extend({
appendTo: 'body',
source: null,
select: null,
positionTo: 'self',
x: 0,
y: 0
}, this.options, options);
N2Classes.nUIWidgetBase.prototype.constructor.apply(this, arguments);
this.element.on({
focus: $.proxy(this.focus, this),
blur: $.proxy(this.blur, this)
});
if (this.options.positionTo === 'self') {
this.positionTo = this.element;
} else {
this.positionTo = this.element.closest(this.options.positionTo);
}
}
nUIAutocomplete.prototype = Object.create(N2Classes.nUIWidgetBase.prototype);
nUIAutocomplete.prototype.constructor = nUIAutocomplete;
nUIAutocomplete.prototype.focus = function (e) {
if (this.isActive === false) {
this.showList(e);
this.element.on('click.' + this.widgetEventPrefix, $.proxy(this.showList, this));
this.isActive = true;
}
};
nUIAutocomplete.prototype.showList = function (e) {
if (typeof this.options.appendTo === 'function') {
this.options.appendTo = this.options.appendTo.call(window);
} else {
this.options.appendTo = $(this.options.appendTo);
}
var $list = this.getList().appendTo(this.options.appendTo);
var appendToOffset = {
left: 0,
top: 0
},
offset = this.positionTo.offset();
if (!this.options.appendTo.is($('body'))) {
appendToOffset = this.options.appendTo.offset();
appendToOffset.top -= this.options.appendTo.scrollTop();
$list.css('height', '');
var listHeight = $list.height();
var paneRect = this.options.appendTo[0].getBoundingClientRect(),
fieldRect = this.positionTo[0].getBoundingClientRect(),
newListHeight = Math.min(paneRect.top + paneRect.height - fieldRect.top - fieldRect.height - 10, listHeight);
if (newListHeight < 100 && newListHeight < listHeight) {
newListHeight = Math.min(fieldRect.top - paneRect.top - 10, listHeight);
appendToOffset.top = appendToOffset.top + fieldRect.height + newListHeight;
}
$list.css('height', newListHeight);
}
$list.css({
left: offset.left - appendToOffset.left + this.element.position().left + this.options.x,
top: offset.top + this.positionTo.outerHeight() - appendToOffset.top + this.options.y,
minWidth: this.element.outerWidth(true) + 'px'
});
/**
* If scrollbar dragged with mouse prevent the list to disappear
*/
$list.off('.' + this.widgetEventPrefix)
.on('mousedown.' + this.widgetEventPrefix, $.proxy(function (e) {
if ($(e.target).is($list)) {
this.element.parent().addClass('focus2');
this.allowBlur = false;
}
}, this))
.on('mouseup.' + this.widgetEventPrefix, $.proxy(function (e) {
if ($(e.target).is($list)) {
this.allowBlur = true;
this.element.focus();
this.element.parent().removeClass('focus2');
}
}, this));
};
nUIAutocomplete.prototype.blur = function (e) {
if (this.allowBlur) {
this.hide();
this.element.off('.' + this.widgetEventPrefix);
}
};
nUIAutocomplete.prototype.hide = function () {
this.$list.detach();
this.isActive = false;
};
nUIAutocomplete.prototype.getList = function () {
if (!this.isRendered) {
this.$list = $('<ul class="n2 nui-autocomplete"></ul>')
.attr({
"unselectable": "on"
})
.on({
mousedown: $.proxy(N2Classes.WindowManager.setMouseDownArea, null, 'nUIAutocomplete'),
'wheel': function (e) {
e.stopPropagation();
}
});
var options = this.options.source.call(this, this.ui());
for (var i = 0; i < options.length; i++) {
$('<li class="nui-menu-item"><div tabindex="-1">' + options[i] + '</div></li>')
.on({
mousedown: function (e) {
e.preventDefault();
},
click: $.proxy(function (value, e) {
this._trigger('select', e, {
value: value
});
this.hide();
}, this, options[i])
})
.appendTo(this.$list);
}
this.isRendered = true;
}
return this.$list;
};
nUIAutocomplete.prototype.ui = function () {
return {};
};
N2Classes.nUIWidgetBase.register('nUIAutocomplete');
return nUIAutocomplete;
});
N2D('nUIDraggableBar', ['nUIMouse'], function ($, undefined) {
"use strict";
/**
* @memberOf N2Classes
*
* @param element
* @param options
*/
function nUIDraggableBar(element, options) {
this.element = $(element);
this.widgetName = this.widgetName || 'nUIDraggable';
this.widgetEventPrefix = "drag";
this.options = $.extend({
// Callbacks
drag: null,
start: null,
stop: null
}, this.options, options);
N2Classes.nUIMouse.prototype.constructor.apply(this, arguments);
this._mouseInit();
}
nUIDraggableBar.prototype = Object.create(N2Classes.nUIMouse.prototype);
nUIDraggableBar.prototype.constructor = nUIDraggableBar;
nUIDraggableBar.prototype._mouseStart = function (event) {
this.currentData = this.originalData = {
margin: parseInt(this.element.css(n2const.rtl.marginLeft))
};
this.originalMousePosition = {left: event.pageX};
this.element.addClass("nui-draggable-dragging");
this._trigger("start", event, this.ui());
this._mouseDrag(event);
return true;
};
nUIDraggableBar.prototype._mouseDrag = function (event) {
var dx = (event.pageX - this.originalMousePosition.left) || 0;
this.currentData = {};
if (!n2const.rtl.isRtl) {
this.currentData.margin = Math.max(0, this.originalData.margin + dx);
} else {
this.currentData.margin = Math.max(0, this.originalData.margin - dx);
}
this._trigger("drag", event, this.ui());
this.element.css(n2const.rtl.marginLeft, this.currentData.margin);
return true;
};
nUIDraggableBar.prototype._mouseStop = function (event) {
this._trigger("stop", event, this.ui());
return true;
};
nUIDraggableBar.prototype.ui = function () {
return {
currentData: this.currentData
};
};
N2Classes.nUIWidgetBase.register('nUIDraggableBar');
return nUIDraggableBar;
});
N2D('nUIDraggableDelay', ['nUIMouse'], function ($, undefined) {
"use strict";
/**
* @memberOf N2Classes
*
* @param element
* @param options
*/
function nUIDraggableDelay(element, options) {
this.element = $(element);
this.widgetName = this.widgetName || 'nUIDraggable';
this.widgetEventPrefix = "drag";
this.options = $.extend({
// Callbacks
drag: null,
start: null,
stop: null
}, this.options, options);
N2Classes.nUIMouse.prototype.constructor.apply(this, arguments);
this._mouseInit();
}
nUIDraggableDelay.prototype = Object.create(N2Classes.nUIMouse.prototype);
nUIDraggableDelay.prototype.constructor = nUIDraggableDelay;
nUIDraggableDelay.prototype._mouseStart = function (event) {
this.currentData = this.originalData = {
width: parseInt(this.element.width())
};
this.originalMousePosition = {left: event.pageX};
this.element.addClass("nui-draggable-dragging");
this._trigger("start", event, this.ui());
this._mouseDrag(event);
return true;
};
nUIDraggableDelay.prototype._mouseDrag = function (event) {
var dx = (event.pageX - this.originalMousePosition.left) || 0;
this.currentData = {};
if (!n2const.rtl.isRtl) {
this.currentData.width = Math.max(0, this.originalData.width + dx);
} else {
this.currentData.width = Math.max(0, this.originalData.width - dx);
}
this._trigger("drag", event, this.ui());
this.element.width(this.currentData.width);
return true;
};
nUIDraggableDelay.prototype._mouseStop = function (event) {
this._trigger("stop", event, this.ui());
return true;
};
nUIDraggableDelay.prototype.ui = function () {
return {
currentData: this.currentData
};
};
N2Classes.nUIWidgetBase.register('nUIDraggableDelay');
return nUIDraggableDelay;
});
N2D('nUIDraggable', ['nUIMouse'], function ($, undefined) {
"use strict";
/**
* @memberOf N2Classes
*
* @constructor
* @augments nUIMouse
* @this nUIDraggable
*/
function nUIDraggable(element, options) {
this.element = $(element);
this.widgetName = this.widgetName || 'nUIDraggable';
this.widgetEventPrefix = "drag";
this.options = $.extend({
addClasses: true,
appendTo: "parent",
axis: false,
containment: false,
cursor: "auto",
cursorAt: false,
handle: false,
helper: "original",
scroll: true,
scrollSensitivity: 20,
scrollSpeed: 20,
// Callbacks
drag: null,
start: null,
stop: null
}, this.options, options);
N2Classes.nUIMouse.prototype.constructor.apply(this, arguments);
this.create();
}
nUIDraggable.prototype = Object.create(N2Classes.nUIMouse.prototype);
nUIDraggable.prototype.constructor = nUIDraggable;
nUIDraggable.prototype.create = function () {
if (this.options.helper === "original") {
this._setPositionRelative();
}
if (this.options.addClasses) {
this.element.addClass("nui-draggable");
}
this._setHandleClassName();
this._mouseInit();
};
nUIDraggable.prototype._setPositionRelative = function () {
if (!( /^(?:r|a|f)/ ).test(this.element.css("position"))) {
this.element[0].style.position = "relative";
}
};
nUIDraggable.prototype._getHandle = function (event) {
return this.options.handle ?
!!$(event.target).closest(this.element.find(this.options.handle)).length :
true;
};
nUIDraggable.prototype._setHandleClassName = function () {
this.handleElement = this.options.handle ?
this.element.find(this.options.handle) : this.element;
this.handleElement.addClass("nui-draggable-handle");
};
nUIDraggable.prototype._mouseCapture = function (event) {
var o = this.options;
// Among others, prevent a drag on a resizable-handle
if (this.helper || o.disabled ||
$(event.target).closest(".nui-resizable-handle").length > 0) {
return false;
}
//Quit if we're not on a valid handle
this.handle = this._getHandle(event);
if (!this.handle) {
return false;
}
this._blurActiveElement(event);
return true;
};
nUIDraggable.prototype.cancel = function () {
if (this.helper.is(".nui-draggable-dragging")) {
this._mouseUp(new $.Event("mouseup", {target: this.element[0]}));
} else {
this._clear();
}
return this;
};
$.fn.nuiScrollParent = function (includeHidden) {
var position = this.css("position"),
excludeStaticParent = position === "absolute",
overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
scrollParent = this.parents().filter(function () {
var parent = $(this);
if (excludeStaticParent && parent.css("position") === "static") {
return false;
}
return overflowRegex.test(parent.css("overflow") + parent.css("overflow-y") +
parent.css("overflow-x"));
}).eq(0);
return position === "fixed" || !scrollParent.length ?
$(this[0].ownerDocument || document) :
scrollParent;
};
nUIDraggable.prototype._mouseStart = function (event) {
var o = this.options;
//Create and append the visible helper
this.helper = this._createHelper(event);
this.helper.addClass("nui-draggable-dragging");
//Cache the helper size
this._cacheHelperProportions();
/*
* - Position generation -
* This block generates everything position related - it's the core of draggables.
*/
//Cache the margins of the original element
this._cacheMargins();
//Store the helper's css position
this.cssPosition = this.helper.css("position");
this.scrollParent = this.helper.nuiScrollParent(true);
this.offsetParent = this.helper.offsetParent();
this.hasFixedAncestor = this.helper.parents().filter(function () {
return $(this).css("position") === "fixed";
}).length > 0;
//The element's absolute position on the page minus margins
this.positionAbs = this.element.offset();
this._refreshOffsets(event);
//Generate the original position
this.originalPosition = this.position = this._generatePosition(event, false);
this.originalPageX = event.pageX;
this.originalPageY = event.pageY;
//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
( o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt) );
//Set a containment if given in the options
this._setContainment();
//Trigger event + callbacks
if (this._trigger("start", event) === false) {
this._clear();
return false;
}
//Recache the helper size
this._cacheHelperProportions();
// Execute the drag once - this causes the helper not to be visible before getting its
// correct position
this._mouseDrag(event, true);
return true;
};
nUIDraggable.prototype._mouseDrag = function (event, noPropagation) {
// reset any necessary cached properties (see #5009)
if (this.hasFixedAncestor) {
this.offset.parent = this._getParentOffset();
}
//Compute the helpers position
this.position = this._generatePosition(event, true);
this.positionAbs = this._convertPositionTo("absolute");
//Call plugins and callbacks and use the resulting position if something is returned
if (!noPropagation) {
var ui = this._uiHash();
if (this._trigger("drag", event, ui) === false) {
this._mouseUp(new $.Event("mouseup", event));
return false;
}
this.position = ui.position;
}
this.helper[0].style.left = this.position.left + "px";
this.helper[0].style.top = this.position.top + "px";
return false;
};
nUIDraggable.prototype._mouseStop = function (event) {
if (this._trigger("stop", event) !== false) {
this._clear();
}
return false;
};
nUIDraggable.prototype._mouseUp = function (event) {
// Only need to focus if the event occurred on the draggable itself, see #10527
if (this.handleElement.is(event.target)) {
// The interaction is over; whether or not the click resulted in a drag,
// focus the element
this.element.trigger("focus");
}
return N2Classes.nUIMouse.prototype._mouseUp.call(this, event);
};
nUIDraggable.prototype._trigger = function (type, event, ui) {
ui = ui || this._uiHash();
return N2Classes.nUIWidgetBase.prototype._trigger.call(this, type, event, ui);
};
nUIDraggable.prototype._uiHash = function () {
return {
helper: this.helper,
position: this.position,
originalPosition: this.originalPosition
};
};
nUIDraggable.prototype._createHelper = function (event) {
var o = this.options,
helperIsFunction = $.isFunction(o.helper),
helper = helperIsFunction ?
$(o.helper.apply(this.element[0], [event])) :
( o.helper === "clone" ?
this.element.clone().removeAttr("id") :
this.element );
if (!helper.parents("body").length) {
helper.appendTo(( o.appendTo === "parent" ?
this.element[0].parentNode :
o.appendTo ));
}
// Http://bugs.jqueryui.com/ticket/9446
// a helper function can return the original element
// which wouldn't have been set to relative in _create
if (helperIsFunction && helper[0] === this.element[0]) {
this._setPositionRelative();
}
if (helper[0] !== this.element[0] && !( /(fixed|absolute)/ ).test(helper.css("position"))) {
helper.css("position", "absolute");
}
return helper;
};
nUIDraggable.prototype._cacheHelperProportions = function () {
this.helperProportions = {
width: this.helper.outerWidth(),
height: this.helper.outerHeight()
};
};
nUIDraggable.prototype._cacheMargins = function () {
this.margins = {
left: ( parseInt(this.element.css("marginLeft"), 10) || 0 ),
top: ( parseInt(this.element.css("marginTop"), 10) || 0 ),
right: ( parseInt(this.element.css("marginRight"), 10) || 0 ),
bottom: ( parseInt(this.element.css("marginBottom"), 10) || 0 )
};
};
nUIDraggable.prototype._refreshOffsets = function (event) {
this.offset = {
top: this.positionAbs.top - this.margins.top,
left: this.positionAbs.left - this.margins.left,
scroll: false,
parent: this._getParentOffset(),
relative: this._getRelativeOffset()
};
this.offset.click = {
left: event.pageX - this.offset.left,
top: event.pageY - this.offset.top
};
};
nUIDraggable.prototype._getParentOffset = function () {
//Get the offsetParent and cache its position
var po = this.offsetParent.offset(),
document = this.document[0];
// This is a special case where we need to modify a offset calculated on start, since the
// following happened:
// 1. The position of the helper is absolute, so it's position is calculated based on the
// next positioned parent
// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
// the document, which means that the scroll is included in the initial calculation of the
// offset of the parent, and never recalculated upon drag
if (this.cssPosition === "absolute" && this.scrollParent[0] !== document &&
$.contains(this.scrollParent[0], this.offsetParent[0])) {
po.left += this.scrollParent.scrollLeft();
po.top += this.scrollParent.scrollTop();
}
if (this._isRootNode(this.offsetParent[0])) {
po = {top: 0, left: 0};
}
return {
top: po.top + ( parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0 ),
left: po.left + ( parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0 )
};
};
nUIDraggable.prototype._getRelativeOffset = function () {
if (this.cssPosition !== "relative") {
return {top: 0, left: 0};
}
var p = this.element.position(),
scrollIsRootNode = this._isRootNode(this.scrollParent[0]);
return {
top: p.top - ( parseInt(this.helper.css("top"), 10) || 0 ) +
( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
left: p.left - ( parseInt(this.helper.css("left"), 10) || 0 ) +
( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
};
};
nUIDraggable.prototype._convertPositionTo = function (d, pos) {
if (!pos) {
pos = this.position;
}
var mod = d === "absolute" ? 1 : -1,
scrollIsRootNode = this._isRootNode(this.scrollParent[0]);
return {
top: (
// The absolute mouse position
pos.top +
// Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.relative.top * mod +
// The offsetParent's offset without borders (offset + border)
this.offset.parent.top * mod -
( ( this.cssPosition === "fixed" ?
-this.offset.scroll.top :
( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
),
left: (
// The absolute mouse position
pos.left +
// Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.relative.left * mod +
// The offsetParent's offset without borders (offset + border)
this.offset.parent.left * mod -
( ( this.cssPosition === "fixed" ?
-this.offset.scroll.left :
( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
)
};
};
nUIDraggable.prototype._setContainment = function () {
var isUserScrollable, c, ce,
o = this.options,
document = this.document[0];
this.relativeContainer = null;
if (!o.containment) {
this.containment = null;
return;
}
if (o.containment === "window") {
this.containment = [
$(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
$(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
$(window).scrollLeft() + $(window).width() -
this.helperProportions.width - this.margins.left,
$(window).scrollTop() +
( $(window).height() || document.body.parentNode.scrollHeight ) -
this.helperProportions.height - this.margins.top
];
return;
}
if (o.containment === "document") {
this.containment = [
0,
0,
$(document).width() - this.helperProportions.width - this.margins.left,
( $(document).height() || document.body.parentNode.scrollHeight ) -
this.helperProportions.height - this.margins.top
];
return;
}
if (o.containment.constructor === Array) {
this.containment = o.containment;
return;
}
if (o.containment === "parent") {
o.containment = this.helper[0].parentNode;
}
c = $(o.containment);
ce = c[0];
if (!ce) {
return;
}
isUserScrollable = /(scroll|auto)/.test(c.css("overflow"));
this.containment = [
( parseInt(c.css("borderLeftWidth"), 10) || 0 ) +
( parseInt(c.css("paddingLeft"), 10) || 0 ),
( parseInt(c.css("borderTopWidth"), 10) || 0 ) +
( parseInt(c.css("paddingTop"), 10) || 0 ),
( isUserScrollable ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth ) -
( parseInt(c.css("borderRightWidth"), 10) || 0 ) -
( parseInt(c.css("paddingRight"), 10) || 0 ) -
this.helperProportions.width -
this.margins.left -
this.margins.right,
( isUserScrollable ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight ) -
( parseInt(c.css("borderBottomWidth"), 10) || 0 ) -
( parseInt(c.css("paddingBottom"), 10) || 0 ) -
this.helperProportions.height -
this.margins.top -
this.margins.bottom
];
this.relativeContainer = c;
};
nUIDraggable.prototype._adjustOffsetFromHelper = function (obj) {
if (typeof obj === "string") {
obj = obj.split(" ");
}
if ($.isArray(obj)) {
obj = {left: +obj[0], top: +obj[1] || 0};
}
if ("left" in obj) {
this.offset.click.left = obj.left + this.margins.left;
}
if ("right" in obj) {
this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
}
if ("top" in obj) {
this.offset.click.top = obj.top + this.margins.top;
}
if ("bottom" in obj) {
this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
}
};
nUIDraggable.prototype._isRootNode = function (element) {
return ( /(html|body)/i ).test(element.tagName) || element === this.document[0];
};
nUIDraggable.prototype._generatePosition = function (event, constrainPosition) {
var containment, co,
o = this.options,
scrollIsRootNode = this._isRootNode(this.scrollParent[0]),
pageX = event.pageX,
pageY = event.pageY;
// Cache the scroll
if (!scrollIsRootNode || !this.offset.scroll) {
this.offset.scroll = {
top: this.scrollParent.scrollTop(),
left: this.scrollParent.scrollLeft()
};
}
/*
* - Position constraining -
* Constrain the position to containment.
*/
// If we are not dragging yet, we won't check for options
if (constrainPosition) {
if (this.containment) {
if (this.relativeContainer) {
co = this.relativeContainer.offset();
containment = [
this.containment[0] + co.left,
this.containment[1] + co.top,
this.containment[2] + co.left,
this.containment[3] + co.top
];
} else {
containment = this.containment;
}
if (event.pageX - this.offset.click.left < containment[0]) {
pageX = containment[0] + this.offset.click.left;
}
if (event.pageY - this.offset.click.top < containment[1]) {
pageY = containment[1] + this.offset.click.top;
}
if (event.pageX - this.offset.click.left > containment[2]) {
pageX = containment[2] + this.offset.click.left;
}
if (event.pageY - this.offset.click.top > containment[3]) {
pageY = containment[3] + this.offset.click.top;
}
}
if (o.axis === "y") {
pageX = this.originalPageX;
}
if (o.axis === "x") {
pageY = this.originalPageY;
}
}
return {
top: (
// The absolute mouse position
pageY -
// Click offset (relative to the element)
this.offset.click.top -
// Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.relative.top -
// The offsetParent's offset without borders (offset + border)
this.offset.parent.top +
( this.cssPosition === "fixed" ?
-this.offset.scroll.top :
( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
),
left: (
// The absolute mouse position
pageX -
// Click offset (relative to the element)
this.offset.click.left -
// Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.relative.left -
// The offsetParent's offset without borders (offset + border)
this.offset.parent.left +
( this.cssPosition === "fixed" ?
-this.offset.scroll.left :
( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
)
};
};
nUIDraggable.prototype._clear = function () {
this.helper.removeClass("nui-draggable-dragging");
if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
this.helper.remove();
}
this.helper = null;
this.cancelHelperRemoval = false;
if (this.destroyOnClear) {
this.destroy();
}
};
var safeActiveElement = function (document) {
var activeElement;
// Support: IE 9 only
// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
try {
activeElement = document.activeElement;
} catch (error) {
activeElement = document.body;
}
// Support: IE 9 - 11 only
// IE may return null instead of an element
// Interestingly, this only seems to occur when NOT in an iframe
if (!activeElement) {
activeElement = document.body;
}
// Support: IE 11 only
// IE11 returns a seemingly empty object in some cases when accessing
// document.activeElement from an <iframe>
if (!activeElement.nodeName) {
activeElement = document.body;
}
return activeElement;
},
safeBlur = function (element) {
// Support: IE9 - 10 only
// If the <body> is blurred, IE will switch windows, see #9420
if (element && element.nodeName.toLowerCase() !== "body") {
$(element).trigger("blur");
}
};
nUIDraggable.prototype._blurActiveElement = function (event) {
var activeElement = safeActiveElement(this.document[0]),
target = $(event.target);
// Don't blur if the event occurred on an element that is within
// the currently focused element
// See #10527, #12472
if (target.closest(activeElement).length) {
return;
}
// Blur any element that currently has focus, see #4261
safeBlur(activeElement);
};
N2Classes.nUIWidgetBase.register('nUIDraggable');
return nUIDraggable;
});
/*
* jQuery File Upload Plugin 5.42.3
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
*/
/* jshint nomen:false */
/* global define, require, window, document, location, Blob, FormData */
N2D('nUIFileUpload', ["nUIWidgetBase"], function ($, undefined) {
'use strict';
// Detect file input support, based on
// http://viljamis.com/blog/2012/file-upload-support-on-mobile/
$.support.fileInput = !(new RegExp(
// Handle devices which give false positives for the feature detection:
'(Android (1\\.[0156]|2\\.[01]))' +
'|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' +
'|(w(eb)?OSBrowser)|(webOS)' +
'|(Kindle/(1\\.0|2\\.[05]|3\\.0))'
).test(window.navigator.userAgent) ||
// Feature detection for all other devices:
$('<input type="file">').prop('disabled'));
// The FileReader API is not actually used, but works as feature detection,
// as some Safari versions (5?) support XHR file uploads via the FormData API,
// but not non-multipart XHR file uploads.
// window.XMLHttpRequestUpload is not available on IE10, so we check for
// window.ProgressEvent instead to detect XHR2 file upload capability:
$.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader);
$.support.xhrFormDataFileUpload = !!window.FormData;
// Detect support for Blob slicing (required for chunked uploads):
$.support.blobSlice = window.Blob && (Blob.prototype.slice ||
Blob.prototype.webkitSlice || Blob.prototype.mozSlice);
// Helper function to create drag handlers for dragover/dragenter/dragleave:
function getDragHandler(type) {
var isDragOver = type === 'dragover';
return function (e) {
e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
var dataTransfer = e.dataTransfer;
if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 &&
this._trigger(
type,
$.Event(type, {delegatedEvent: e})
) !== false) {
e.preventDefault();
if (isDragOver) {
dataTransfer.dropEffect = 'copy';
}
}
};
}
// The fileupload widget listens for change events on file input fields defined
// via fileInput setting and paste or drop events of the given dropZone.
// In addition to the default jQuery Widget methods, the fileupload widget
// exposes the "add" and "send" methods, to add or directly send files using
// the fileupload API.
// By default, files added via file input selection, paste, drag & drop or
// "add" method are uploaded immediately, but it is possible to override
// the "add" callback option to queue file uploads.
/**
* @class
* @constructor
* @augments nUIWidgetBase
* @this nUIFileUpload
*/
function nUIFileUpload(element, options) {
this.element = $(element);
this.widgetName = this.widgetName || 'nUIFileUpload';
this.options = $.extend({
// The drop target element(s), by the default the complete document.
// Set to null to disable drag & drop support:
dropZone: $(document),
// The paste target element(s), by the default undefined.
// Set to a DOM node or jQuery object to enable file pasting:
pasteZone: undefined,
// The file input field(s), that are listened to for change events.
// If undefined, it is set to the file input fields inside
// of the widget element on plugin initialization.
// Set to null to disable the change listener.
fileInput: undefined,
// By default, the file input field is replaced with a clone after
// each input field change event. This is required for iframe transport
// queues and allows change events to be fired for the same file
// selection, but can be disabled by setting the following option to false:
replaceFileInput: true,
// The parameter name for the file form data (the request argument name).
// If undefined or empty, the name property of the file input field is
// used, or "files[]" if the file input name property is also empty,
// can be a string or an array of strings:
paramName: undefined,
// By default, each file of a selection is uploaded using an individual
// request for XHR type uploads. Set to false to upload file
// selections in one request each:
singleFileUploads: true,
// To limit the number of files uploaded with one XHR request,
// set the following option to an integer greater than 0:
limitMultiFileUploads: undefined,
// The following option limits the number of files uploaded with one
// XHR request to keep the request size under or equal to the defined
// limit in bytes:
limitMultiFileUploadSize: undefined,
// Multipart file uploads add a number of bytes to each uploaded file,
// therefore the following option adds an overhead for each file used
// in the limitMultiFileUploadSize configuration:
limitMultiFileUploadSizeOverhead: 512,
// Set the following option to true to issue all file upload requests
// in a sequential order:
sequentialUploads: false,
// To limit the number of concurrent uploads,
// set the following option to an integer greater than 0:
limitConcurrentUploads: undefined,
// Set the following option to true to force iframe transport uploads:
forceIframeTransport: false,
// Set the following option to the location of a redirect url on the
// origin server, for cross-domain iframe transport uploads:
redirect: undefined,
// The parameter name for the redirect url, sent as part of the form
// data and set to 'redirect' if this option is empty:
redirectParamName: undefined,
// Set the following option to the location of a postMessage window,
// to enable postMessage transport uploads:
postMessage: undefined,
// By default, XHR file uploads are sent as multipart/form-data.
// The iframe transport is always using multipart/form-data.
// Set to false to enable non-multipart XHR uploads:
multipart: true,
// To upload large files in smaller chunks, set the following option
// to a preferred maximum chunk size. If set to 0, null or undefined,
// or the browser does not support the required Blob API, files will
// be uploaded as a whole.
maxChunkSize: undefined,
// When a non-multipart upload or a chunked multipart upload has been
// aborted, this option can be used to resume the upload by setting
// it to the size of the already uploaded bytes. This option is most
// useful when modifying the options object inside of the "add" or
// "send" callbacks, as the options are cloned for each file upload.
uploadedBytes: undefined,
// By default, failed (abort or error) file uploads are removed from the
// global progress calculation. Set the following option to false to
// prevent recalculating the global progress data:
recalculateProgress: true,
// Interval in milliseconds to calculate and trigger progress events:
progressInterval: 100,
// Interval in milliseconds to calculate progress bitrate:
bitrateInterval: 500,
// By default, uploads are started automatically when adding files:
autoUpload: true,
// Error and info messages:
messages: {
uploadedBytes: 'Uploaded bytes exceed file size'
},
// Translation function, gets the message key to be translated
// and an object with context specific data as arguments:
i18n: function (message, context) {
message = this.messages[message] || message.toString();
if (context) {
$.each(context, function (key, value) {
message = message.replace('{' + key + '}', value);
});
}
return message;
},
// Additional form data to be sent along with the file uploads can be set
// using this option, which accepts an array of objects with name and
// value properties, a function returning such an array, a FormData
// object (for XHR file uploads), or a simple object.
// The form of the first fileInput is given as parameter to the function:
formData: function (form) {
return form.serializeArray();
},
// The add callback is invoked as soon as files are added to the fileupload
// widget (via file input selection, drag & drop, paste or add API call).
// If the singleFileUploads option is enabled, this callback will be
// called once for each file in the selection for XHR file uploads, else
// once for each file selection.
//
// The upload starts when the submit method is invoked on the data parameter.
// The data object contains a files property holding the added files
// and allows you to override plugin options as well as define ajax settings.
//
// Listeners for this callback can also be bound the following way:
// .bind('fileuploadadd', func);
//
// data.submit() returns a Promise object and allows to attach additional
// handlers using jQuery's Deferred callbacks:
// data.submit().done(func).fail(func).always(func);
add: function (e, data) {
if (e.isDefaultPrevented()) {
return false;
}
if (data.autoUpload || (data.autoUpload !== false &&
$(this).nUIFileUpload('option', 'autoUpload'))) {
data.process().done(function () {
data.submit();
});
}
},
// Other callbacks:
// Callback for the submit event of each file upload:
// submit: function (e, data) {}, // .bind('fileuploadsubmit', func);
// Callback for the start of each file upload request:
// send: function (e, data) {}, // .bind('fileuploadsend', func);
// Callback for successful uploads:
// done: function (e, data) {}, // .bind('fileuploaddone', func);
// Callback for failed (abort or error) uploads:
// fail: function (e, data) {}, // .bind('fileuploadfail', func);
// Callback for completed (success, abort or error) requests:
// always: function (e, data) {}, // .bind('fileuploadalways', func);
// Callback for upload progress events:
// progress: function (e, data) {}, // .bind('fileuploadprogress', func);
// Callback for global upload progress events:
// progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);
// Callback for uploads start, equivalent to the global ajaxStart event:
// start: function (e) {}, // .bind('fileuploadstart', func);
// Callback for uploads stop, equivalent to the global ajaxStop event:
// stop: function (e) {}, // .bind('fileuploadstop', func);
// Callback for change events of the fileInput(s):
// change: function (e, data) {}, // .bind('fileuploadchange', func);
// Callback for paste events to the pasteZone(s):
// paste: function (e, data) {}, // .bind('fileuploadpaste', func);
// Callback for drop events of the dropZone(s):
// drop: function (e, data) {}, // .bind('fileuploaddrop', func);
// Callback for dragover events of the dropZone(s):
// dragover: function (e) {}, // .bind('fileuploaddragover', func);
// Callback for the start of each chunk upload request:
// chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func);
// Callback for successful chunk uploads:
// chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func);
// Callback for failed (abort or error) chunk uploads:
// chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func);
// Callback for completed (success, abort or error) chunk upload requests:
// chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func);
// The plugin options are used as settings object for the ajax calls.
// The following are jQuery ajax settings required for the file uploads:
processData: false,
contentType: false,
cache: false
}, this.options, options);
N2Classes.nUIWidgetBase.prototype.constructor.apply(this, arguments);
this._specialOptions = [
'fileInput',
'dropZone',
'pasteZone',
'multipart',
'forceIframeTransport'
];
this.create();
}
nUIFileUpload.prototype = Object.create(N2Classes.nUIWidgetBase.prototype);
nUIFileUpload.prototype.constructor = nUIFileUpload;
nUIFileUpload.prototype._blobSlice = $.support.blobSlice && function () {
var slice = this.slice || this.webkitSlice || this.mozSlice;
return slice.apply(this, arguments);
};
nUIFileUpload.prototype._BitrateTimer = function () {
this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime());
this.loaded = 0;
this.bitrate = 0;
this.getBitrate = function (now, loaded, interval) {
var timeDiff = now - this.timestamp;
if (!this.bitrate || !interval || timeDiff > interval) {
this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8;
this.loaded = loaded;
this.timestamp = now;
}
return this.bitrate;
};
};
nUIFileUpload.prototype._isXHRUpload = function (options) {
return !options.forceIframeTransport &&
((!options.multipart && $.support.xhrFileUpload) ||
$.support.xhrFormDataFileUpload);
};
nUIFileUpload.prototype._getFormData = function (options) {
var formData;
if ($.type(options.formData) === 'function') {
return options.formData(options.form);
}
if ($.isArray(options.formData)) {
return options.formData;
}
if ($.type(options.formData) === 'object') {
formData = [];
$.each(options.formData, function (name, value) {
formData.push({name: name, value: value});
});
return formData;
}
return [];
};
nUIFileUpload.prototype._getTotal = function (files) {
var total = 0;
$.each(files, function (index, file) {
total += file.size || 1;
});
return total;
};
nUIFileUpload.prototype._initProgressObject = function (obj) {
var progress = {
loaded: 0,
total: 0,
bitrate: 0
};
if (obj._progress) {
$.extend(obj._progress, progress);
} else {
obj._progress = progress;
}
};
nUIFileUpload.prototype._initResponseObject = function (obj) {
var prop;
if (obj._response) {
for (prop in obj._response) {
if (obj._response.hasOwnProperty(prop)) {
delete obj._response[prop];
}
}
} else {
obj._response = {};
}
};
nUIFileUpload.prototype._onProgress = function (e, data) {
if (e.lengthComputable) {
var now = ((Date.now) ? Date.now() : (new Date()).getTime()),
loaded;
if (data._time && data.progressInterval &&
(now - data._time < data.progressInterval) &&
e.loaded !== e.total) {
return;
}
data._time = now;
loaded = Math.floor(
e.loaded / e.total * (data.chunkSize || data._progress.total)
) + (data.uploadedBytes || 0);
// Add the difference from the previously loaded state
// to the global loaded counter:
this._progress.loaded += (loaded - data._progress.loaded);
this._progress.bitrate = this._bitrateTimer.getBitrate(
now,
this._progress.loaded,
data.bitrateInterval
);
data._progress.loaded = data.loaded = loaded;
data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate(
now,
loaded,
data.bitrateInterval
);
// Trigger a custom progress event with a total data property set
// to the file size(s) of the current upload and a loaded data
// property calculated accordingly:
this._trigger(
'progress',
$.Event('progress', {delegatedEvent: e}),
data
);
// Trigger a global progress event for all current file uploads,
// including ajax calls queued for sequential file uploads:
this._trigger(
'progressall',
$.Event('progressall', {delegatedEvent: e}),
this._progress
);
}
};
nUIFileUpload.prototype._initProgressListener = function (options) {
var that = this,
xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();
// Accesss to the native XHR object is required to add event listeners
// for the upload progress event:
if (xhr.upload) {
$(xhr.upload).bind('progress', function (e) {
var oe = e.originalEvent;
// Make sure the progress event properties get copied over:
e.lengthComputable = oe.lengthComputable;
e.loaded = oe.loaded;
e.total = oe.total;
that._onProgress(e, options);
});
options.xhr = function () {
return xhr;
};
}
};
nUIFileUpload.prototype._isInstanceOf = function (type, obj) {
// Cross-frame instanceof check
return Object.prototype.toString.call(obj) === '[object ' + type + ']';
};
nUIFileUpload.prototype._initXHRData = function (options) {
var that = this,
formData,
file = options.files[0],
// Ignore non-multipart setting if not supported:
multipart = options.multipart || !$.support.xhrFileUpload,
paramName = $.type(options.paramName) === 'array' ?
options.paramName[0] : options.paramName;
options.headers = $.extend({}, options.headers);
if (options.contentRange) {
options.headers['Content-Range'] = options.contentRange;
}
if (!multipart || options.blob || !this._isInstanceOf('File', file)) {
options.headers['Content-Disposition'] = 'attachment; filename="' +
encodeURI(file.name) + '"';
}
if (!multipart) {
options.contentType = file.type || 'application/octet-stream';
options.data = options.blob || file;
} else if ($.support.xhrFormDataFileUpload) {
if (options.postMessage) {
// window.postMessage does not allow sending FormData
// objects, so we just add the File/Blob objects to
// the formData array and let the postMessage window
// create the FormData object out of this array:
formData = this._getFormData(options);
if (options.blob) {
formData.push({
name: paramName,
value: options.blob
});
} else {
$.each(options.files, function (index, file) {
formData.push({
name: ($.type(options.paramName) === 'array' &&
options.paramName[index]) || paramName,
value: file
});
});
}
} else {
if (that._isInstanceOf('FormData', options.formData)) {
formData = options.formData;
} else {
formData = new FormData();
$.each(this._getFormData(options), function (index, field) {
formData.append(field.name, field.value);
});
}
if (options.blob) {
formData.append(paramName, options.blob, file.name);
} else {
$.each(options.files, function (index, file) {
// This check allows the tests to run with
// dummy objects:
if (that._isInstanceOf('File', file) ||
that._isInstanceOf('Blob', file)) {
formData.append(
($.type(options.paramName) === 'array' &&
options.paramName[index]) || paramName,
file,
file.uploadName || file.name
);
}
});
}
}
options.data = formData;
}
// Blob reference is not needed anymore, free memory:
options.blob = null;
};
nUIFileUpload.prototype._initIframeSettings = function (options) {
var targetHost = $('<a></a>').prop('href', options.url).prop('host');
// Setting the dataType to iframe enables the iframe transport:
options.dataType = 'iframe ' + (options.dataType || '');
// The iframe transport accepts a serialized array as form data:
options.formData = this._getFormData(options);
// Add redirect url to form data on cross-domain uploads:
if (options.redirect && targetHost && targetHost !== location.host) {
options.formData.push({
name: options.redirectParamName || 'redirect',
value: options.redirect
});
}
};
nUIFileUpload.prototype._initDataSettings = function (options) {
if (this._isXHRUpload(options)) {
if (!this._chunkedUpload(options, true)) {
if (!options.data) {
this._initXHRData(options);
}
this._initProgressListener(options);
}
if (options.postMessage) {
// Setting the dataType to postmessage enables the
// postMessage transport:
options.dataType = 'postmessage ' + (options.dataType || '');
}
} else {
this._initIframeSettings(options);
}
};
nUIFileUpload.prototype._getParamName = function (options) {
var fileInput = $(options.fileInput),
paramName = options.paramName;
if (!paramName) {
paramName = [];
fileInput.each(function () {
var input = $(this),
name = input.prop('name') || 'files[]',
i = (input.prop('files') || [1]).length;
while (i) {
paramName.push(name);
i -= 1;
}
});
if (!paramName.length) {
paramName = [fileInput.prop('name') || 'files[]'];
}
} else if (!$.isArray(paramName)) {
paramName = [paramName];
}
return paramName;
};
nUIFileUpload.prototype._initFormSettings = function (options) {
// Retrieve missing options from the input field and the
// associated form, if available:
if (!options.form || !options.form.length) {
options.form = $(options.fileInput.prop('form'));
// If the given file input doesn't have an associated form,
// use the default widget file input's form:
if (!options.form.length) {
options.form = $(this.options.fileInput.prop('form'));
}
}
options.paramName = this._getParamName(options);
if (!options.url) {
options.url = options.form.prop('action') || location.href;
}
// The HTTP request method must be "POST" or "PUT":
options.type = (options.type ||
($.type(options.form.prop('method')) === 'string' &&
options.form.prop('method')) || ''
).toUpperCase();
if (options.type !== 'POST' && options.type !== 'PUT' &&
options.type !== 'PATCH') {
options.type = 'POST';
}
if (!options.formAcceptCharset) {
options.formAcceptCharset = options.form.attr('accept-charset');
}
};
nUIFileUpload.prototype._getAJAXSettings = function (data) {
var options = $.extend({}, this.options, data);
this._initFormSettings(options);
this._initDataSettings(options);
return options;
};
// jQuery 1.6 doesn't provide .state(),
// while jQuery 1.8+ removed .isRejected() and .isResolved():
nUIFileUpload.prototype._getDeferredState = function (deferred) {
if (deferred.state) {
return deferred.state();
}
if (deferred.isResolved()) {
return 'resolved';
}
if (deferred.isRejected()) {
return 'rejected';
}
return 'pending';
};
// Maps jqXHR callbacks to the equivalent
// methods of the given Promise object:
nUIFileUpload.prototype._enhancePromise = function (promise) {
promise.success = promise.done;
promise.error = promise.fail;
promise.complete = promise.always;
return promise;
};
// Creates and returns a Promise object enhanced with
// the jqXHR methods abort, success, error and complete:
nUIFileUpload.prototype._getXHRPromise = function (resolveOrReject, context, args) {
var dfd = $.Deferred(),
promise = dfd.promise();
context = context || this.options.context || promise;
if (resolveOrReject === true) {
dfd.resolveWith(context, args);
} else if (resolveOrReject === false) {
dfd.rejectWith(context, args);
}
promise.abort = dfd.promise;
return this._enhancePromise(promise);
};
// Adds convenience methods to the data callback argument:
nUIFileUpload.prototype._addConvenienceMethods = function (e, data) {
var that = this,
getPromise = function (args) {
return $.Deferred().resolveWith(that, args).promise();
};
data.process = function (resolveFunc, rejectFunc) {
if (resolveFunc || rejectFunc) {
data._processQueue = this._processQueue =
(this._processQueue || getPromise([this])).pipe(
function () {
if (data.errorThrown) {
return $.Deferred()
.rejectWith(that, [data]).promise();
}
return getPromise(arguments);
}
).pipe(resolveFunc, rejectFunc);
}
return this._processQueue || getPromise([this]);
};
data.submit = function () {
if (this.state() !== 'pending') {
data.jqXHR = this.jqXHR =
(that._trigger(
'submit',
$.Event('submit', {delegatedEvent: e}),
this
) !== false) && that._onSend(e, this);
}
return this.jqXHR || that._getXHRPromise();
};
data.abort = function () {
if (this.jqXHR) {
return this.jqXHR.abort();
}
this.errorThrown = 'abort';
that._trigger('fail', null, this);
return that._getXHRPromise(false);
};
data.state = function () {
if (this.jqXHR) {
return that._getDeferredState(this.jqXHR);
}
if (this._processQueue) {
return that._getDeferredState(this._processQueue);
}
};
data.processing = function () {
return !this.jqXHR && this._processQueue && that
._getDeferredState(this._processQueue) === 'pending';
};
data.progress = function () {
return this._progress;
};
data.response = function () {
return this._response;
};
};
// Parses the Range header from the server response
// and returns the uploaded bytes:
nUIFileUpload.prototype._getUploadedBytes = function (jqXHR) {
var range = jqXHR.getResponseHeader('Range'),
parts = range && range.split('-'),
upperBytesPos = parts && parts.length > 1 &&
parseInt(parts[1], 10);
return upperBytesPos && upperBytesPos + 1;
};
// Uploads a file in multiple, sequential requests
// by splitting the file up in multiple blob chunks.
// If the second parameter is true, only tests if the file
// should be uploaded in chunks, but does not invoke any
// upload requests:
nUIFileUpload.prototype._chunkedUpload = function (options, testOnly) {
options.uploadedBytes = options.uploadedBytes || 0;
var that = this,
file = options.files[0],
fs = file.size,
ub = options.uploadedBytes,
mcs = options.maxChunkSize || fs,
slice = this._blobSlice,
dfd = $.Deferred(),
promise = dfd.promise(),
jqXHR,
upload;
if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) ||
options.data) {
return false;
}
if (testOnly) {
return true;
}
if (ub >= fs) {
file.error = options.i18n('uploadedBytes');
return this._getXHRPromise(
false,
options.context,
[null, 'error', file.error]
);
}
// The chunk upload method:
upload = function () {
// Clone the options object for each chunk upload:
var o = $.extend({}, options),
currentLoaded = o._progress.loaded;
o.blob = slice.call(
file,
ub,
ub + mcs,
file.type
);
// Store the current chunk size, as the blob itself
// will be dereferenced after data processing:
o.chunkSize = o.blob.size;
// Expose the chunk bytes position range:
o.contentRange = 'bytes ' + ub + '-' +
(ub + o.chunkSize - 1) + '/' + fs;
// Process the upload data (the blob and potential form data):
that._initXHRData(o);
// Add progress listeners for this chunk upload:
that._initProgressListener(o);
jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) ||
that._getXHRPromise(false, o.context))
.done(function (result, textStatus, jqXHR) {
ub = that._getUploadedBytes(jqXHR) ||
(ub + o.chunkSize);
// Create a progress event if no final progress event
// with loaded equaling total has been triggered
// for this chunk:
if (currentLoaded + o.chunkSize - o._progress.loaded) {
that._onProgress($.Event('progress', {
lengthComputable: true,
loaded: ub - o.uploadedBytes,
total: ub - o.uploadedBytes
}), o);
}
options.uploadedBytes = o.uploadedBytes = ub;
o.result = result;
o.textStatus = textStatus;
o.jqXHR = jqXHR;
that._trigger('chunkdone', null, o);
that._trigger('chunkalways', null, o);
if (ub < fs) {
// File upload not yet complete,
// continue with the next chunk:
upload();
} else {
dfd.resolveWith(
o.context,
[result, textStatus, jqXHR]
);
}
})
.fail(function (jqXHR, textStatus, errorThrown) {
o.jqXHR = jqXHR;
o.textStatus = textStatus;
o.errorThrown = errorThrown;
that._trigger('chunkfail', null, o);
that._trigger('chunkalways', null, o);
dfd.rejectWith(
o.context,
[jqXHR, textStatus, errorThrown]
);
});
};
this._enhancePromise(promise);
promise.abort = function () {
return jqXHR.abort();
};
upload();
return promise;
};
nUIFileUpload.prototype._beforeSend = function (e, data) {
if (this._active === 0) {
// the start callback is triggered when an upload starts
// and no other uploads are currently running,
// equivalent to the global ajaxStart event:
this._trigger('start');
// Set timer for global bitrate progress calculation:
this._bitrateTimer = new this._BitrateTimer();
// Reset the global progress values:
this._progress.loaded = this._progress.total = 0;
this._progress.bitrate = 0;
}
// Make sure the container objects for the .response() and
// .progress() methods on the data object are available
// and reset to their initial state:
this._initResponseObject(data);
this._initProgressObject(data);
data._progress.loaded = data.loaded = data.uploadedBytes || 0;
data._progress.total = data.total = this._getTotal(data.files) || 1;
data._progress.bitrate = data.bitrate = 0;
this._active += 1;
// Initialize the global progress values:
this._progress.loaded += data.loaded;
this._progress.total += data.total;
};
nUIFileUpload.prototype._onDone = function (result, textStatus, jqXHR, options) {
var total = options._progress.total,
response = options._response;
if (options._progress.loaded < total) {
// Create a progress event if no final progress event
// with loaded equaling total has been triggered:
this._onProgress($.Event('progress', {
lengthComputable: true,
loaded: total,
total: total
}), options);
}
response.result = options.result = result;
response.textStatus = options.textStatus = textStatus;
response.jqXHR = options.jqXHR = jqXHR;
this._trigger('done', null, options);
};
nUIFileUpload.prototype._onFail = function (jqXHR, textStatus, errorThrown, options) {
var response = options._response;
if (options.recalculateProgress) {
// Remove the failed (error or abort) file upload from
// the global progress calculation:
this._progress.loaded -= options._progress.loaded;
this._progress.total -= options._progress.total;
}
response.jqXHR = options.jqXHR = jqXHR;
response.textStatus = options.textStatus = textStatus;
response.errorThrown = options.errorThrown = errorThrown;
this._trigger('fail', null, options);
};
nUIFileUpload.prototype._onAlways = function (jqXHRorResult, textStatus, jqXHRorError, options) {
// jqXHRorResult, textStatus and jqXHRorError are added to the
// options object via done and fail callbacks
this._trigger('always', null, options);
};
nUIFileUpload.prototype._onSend = function (e, data) {
if (!data.submit) {
this._addConvenienceMethods(e, data);
}
var that = this,
jqXHR,
aborted,
slot,
pipe,
options = that._getAJAXSettings(data),
send = function () {
that._sending += 1;
// Set timer for bitrate progress calculation:
options._bitrateTimer = new that._BitrateTimer();
jqXHR = jqXHR || (
((aborted || that._trigger(
'send',
$.Event('send', {delegatedEvent: e}),
options
) === false) &&
that._getXHRPromise(false, options.context, aborted)) ||
that._chunkedUpload(options) || $.ajax(options)
).done(function (result, textStatus, jqXHR) {
that._onDone(result, textStatus, jqXHR, options);
}).fail(function (jqXHR, textStatus, errorThrown) {
that._onFail(jqXHR, textStatus, errorThrown, options);
}).always(function (jqXHRorResult, textStatus, jqXHRorError) {
that._onAlways(
jqXHRorResult,
textStatus,
jqXHRorError,
options
);
that._sending -= 1;
that._active -= 1;
if (options.limitConcurrentUploads &&
options.limitConcurrentUploads > that._sending) {
// Start the next queued upload,
// that has not been aborted:
var nextSlot = that._slots.shift();
while (nextSlot) {
if (that._getDeferredState(nextSlot) === 'pending') {
nextSlot.resolve();
break;
}
nextSlot = that._slots.shift();
}
}
if (that._active === 0) {
// The stop callback is triggered when all uploads have
// been completed, equivalent to the global ajaxStop event:
that._trigger('stop');
}
});
return jqXHR;
};
this._beforeSend(e, options);
if (this.options.sequentialUploads ||
(this.options.limitConcurrentUploads &&
this.options.limitConcurrentUploads <= this._sending)) {
if (this.options.limitConcurrentUploads > 1) {
slot = $.Deferred();
this._slots.push(slot);
pipe = slot.pipe(send);
} else {
this._sequence = this._sequence.pipe(send, send);
pipe = this._sequence;
}
// Return the piped Promise object, enhanced with an abort method,
// which is delegated to the jqXHR object of the current upload,
// and jqXHR callbacks mapped to the equivalent Promise methods:
pipe.abort = function () {
aborted = [undefined, 'abort', 'abort'];
if (!jqXHR) {
if (slot) {
slot.rejectWith(options.context, aborted);
}
return send();
}
return jqXHR.abort();
};
return this._enhancePromise(pipe);
}
return send();
};
nUIFileUpload.prototype._onAdd = function (e, data) {
var that = this,
result = true,
options = $.extend({}, this.options, data),
files = data.files,
filesLength = files.length,
limit = options.limitMultiFileUploads,
limitSize = options.limitMultiFileUploadSize,
overhead = options.limitMultiFileUploadSizeOverhead,
batchSize = 0,
paramName = this._getParamName(options),
paramNameSet,
paramNameSlice,
fileSet,
i,
j = 0;
if (limitSize && (!filesLength || files[0].size === undefined)) {
limitSize = undefined;
}
if (!(options.singleFileUploads || limit || limitSize) || !this._isXHRUpload(options)) {
fileSet = [files];
paramNameSet = [paramName];
} else if (!(options.singleFileUploads || limitSize) && limit) {
fileSet = [];
paramNameSet = [];
for (i = 0; i < filesLength; i += limit) {
fileSet.push(files.slice(i, i + limit));
paramNameSlice = paramName.slice(i, i + limit);
if (!paramNameSlice.length) {
paramNameSlice = paramName;
}
paramNameSet.push(paramNameSlice);
}
} else if (!options.singleFileUploads && limitSize) {
fileSet = [];
paramNameSet = [];
for (i = 0; i < filesLength; i = i + 1) {
batchSize += files[i].size + overhead;
if (i + 1 === filesLength ||
((batchSize + files[i + 1].size + overhead) > limitSize) ||
(limit && i + 1 - j >= limit)) {
fileSet.push(files.slice(j, i + 1));
paramNameSlice = paramName.slice(j, i + 1);
if (!paramNameSlice.length) {
paramNameSlice = paramName;
}
paramNameSet.push(paramNameSlice);
j = i + 1;
batchSize = 0;
}
}
} else {
paramNameSet = paramName;
}
data.originalFiles = files;
$.each(fileSet || files, function (index, element) {
var newData = $.extend({}, data);
newData.files = fileSet ? element : [element];
newData.paramName = paramNameSet[index];
that._initResponseObject(newData);
that._initProgressObject(newData);
that._addConvenienceMethods(e, newData);
result = that._trigger(
'add',
$.Event('add', {delegatedEvent: e}),
newData
);
return result;
});
return result;
};
nUIFileUpload.prototype._replaceFileInput = function (data) {
var input = data.fileInput,
inputClone = input.clone(true);
// Add a reference for the new cloned file input to the data argument:
data.fileInputClone = inputClone;
$('<form></form>').append(inputClone)[0].reset();
// Detaching allows to insert the fileInput on another form
// without loosing the file input value:
input.after(inputClone).detach();
// Avoid memory leaks with the detached file input:
$.cleanData(input.unbind('remove'));
// Replace the original file input element in the fileInput
// elements set with the clone, which has been copied including
// event handlers:
this.options.fileInput = this.options.fileInput.map(function (i, el) {
if (el === input[0]) {
return inputClone[0];
}
return el;
});
// If the widget has been initialized on the file input itself,
// override this.element with the file input clone:
if (input[0] === this.element[0]) {
this.element = inputClone;
}
};
nUIFileUpload.prototype._handleFileTreeEntry = function (entry, path) {
var that = this,
dfd = $.Deferred(),
errorHandler = function (e) {
if (e && !e.entry) {
e.entry = entry;
}
// Since $.when returns immediately if one
// Deferred is rejected, we use resolve instead.
// This allows valid files and invalid items
// to be returned together in one set:
dfd.resolve([e]);
},
successHandler = function (entries) {
that._handleFileTreeEntries(
entries,
path + entry.name + '/'
).done(function (files) {
dfd.resolve(files);
}).fail(errorHandler);
},
readEntries = function () {
dirReader.readEntries(function (results) {
if (!results.length) {
successHandler(entries);
} else {
entries = entries.concat(results);
readEntries();
}
}, errorHandler);
},
dirReader, entries = [];
path = path || '';
if (entry.isFile) {
if (entry._file) {
// Workaround for Chrome bug #149735
entry._file.relativePath = path;
dfd.resolve(entry._file);
} else {
entry.file(function (file) {
file.relativePath = path;
dfd.resolve(file);
}, errorHandler);
}
} else if (entry.isDirectory) {
dirReader = entry.createReader();
readEntries();
} else {
// Return an empy list for file system items
// other than files or directories:
dfd.resolve([]);
}
return dfd.promise();
};
nUIFileUpload.prototype._handleFileTreeEntries = function (entries, path) {
var that = this;
return $.when.apply(
$,
$.map(entries, function (entry) {
return that._handleFileTreeEntry(entry, path);
})
).pipe(function () {
return Array.prototype.concat.apply(
[],
arguments
);
});
};
nUIFileUpload.prototype._getDroppedFiles = function (dataTransfer) {
dataTransfer = dataTransfer || {};
var items = dataTransfer.items;
if (items && items.length && (items[0].webkitGetAsEntry ||
items[0].getAsEntry)) {
return this._handleFileTreeEntries(
$.map(items, function (item) {
var entry;
if (item.webkitGetAsEntry) {
entry = item.webkitGetAsEntry();
if (entry) {
// Workaround for Chrome bug #149735:
entry._file = item.getAsFile();
}
return entry;
}
return item.getAsEntry();
})
);
}
return $.Deferred().resolve(
$.makeArray(dataTransfer.files)
).promise();
};
nUIFileUpload.prototype._getSingleFileInputFiles = function (fileInput) {
fileInput = $(fileInput);
var entries = fileInput.prop('webkitEntries') ||
fileInput.prop('entries'),
files,
value;
if (entries && entries.length) {
return this._handleFileTreeEntries(entries);
}
files = $.makeArray(fileInput.prop('files'));
if (!files.length) {
value = fileInput.prop('value');
if (!value) {
return $.Deferred().resolve([]).promise();
}
// If the files property is not available, the browser does not
// support the File API and we add a pseudo File object with
// the input value as name with path information removed:
files = [{name: value.replace(/^.*\\/, '')}];
} else if (files[0].name === undefined && files[0].fileName) {
// File normalization for Safari 4 and Firefox 3:
$.each(files, function (index, file) {
file.name = file.fileName;
file.size = file.fileSize;
});
}
return $.Deferred().resolve(files).promise();
};
nUIFileUpload.prototype._getFileInputFiles = function (fileInput) {
if (!(fileInput instanceof $) || fileInput.length === 1) {
return this._getSingleFileInputFiles(fileInput);
}
return $.when.apply(
$,
$.map(fileInput, this._getSingleFileInputFiles)
).pipe(function () {
return Array.prototype.concat.apply(
[],
arguments
);
});
};
nUIFileUpload.prototype._onChange = function (e) {
var that = this,
data = {
fileInput: $(e.target),
form: $(e.target.form)
};
this._getFileInputFiles(data.fileInput).always(function (files) {
data.files = files;
if (that.options.replaceFileInput) {
that._replaceFileInput(data);
}
if (that._trigger(
'change',
$.Event('change', {delegatedEvent: e}),
data
) !== false) {
that._onAdd(e, data);
}
});
};
nUIFileUpload.prototype._onPaste = function (e) {
var items = e.originalEvent && e.originalEvent.clipboardData &&
e.originalEvent.clipboardData.items,
data = {files: []};
if (items && items.length) {
$.each(items, function (index, item) {
var file = item.getAsFile && item.getAsFile();
if (file) {
data.files.push(file);
}
});
if (this._trigger(
'paste',
$.Event('paste', {delegatedEvent: e}),
data
) !== false) {
this._onAdd(e, data);
}
}
}
;
nUIFileUpload.prototype._onDrop = function (e) {
e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
var that = this,
dataTransfer = e.dataTransfer,
data = {};
if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
e.preventDefault();
e.stopPropagation();
this._getDroppedFiles(dataTransfer).always(function (files) {
data.files = files;
if (that._trigger(
'drop',
$.Event('drop', {delegatedEvent: e}),
data
) !== false) {
that._onAdd(e, data);
}
});
}
};
nUIFileUpload.prototype._onDragOver = getDragHandler('dragover');
nUIFileUpload.prototype._onDragEnter = getDragHandler('dragenter');
nUIFileUpload.prototype._onDragLeave = getDragHandler('dragleave');
nUIFileUpload.prototype._initEventHandlers = function () {
if (this._isXHRUpload(this.options)) {
$(this.options.dropZone).on({
dragover: $.proxy(this._onDragOver, this),
drop: $.proxy(this._onDrop, this),
// event.preventDefault() on dragenter is required for IE10+:
dragenter: $.proxy(this._onDragEnter, this),
// dragleave is not required, but added for completeness:
dragleave: $.proxy(this._onDragLeave, this)
});
$(this.options.pasteZone).on({
paste: $.proxy(this._onPaste, this)
});
}
if ($.support.fileInput) {
$(this.options.fileInput).on({
change: $.proxy(this._onChange, this)
});
}
};
nUIFileUpload.prototype._destroyEventHandlers = function () {
$(this.options.dropZone).off('dragenter dragleave dragover drop');
$(this.options.pasteZone).off('paste');
$(this.options.fileInput).off('change');
};
nUIFileUpload.prototype.setOption = function (key, value) {
var reinit = $.inArray(key, this._specialOptions) !== -1;
if (reinit) {
this._destroyEventHandlers();
}
N2Classes.nUIWidgetBase.prototype.setOption.apply(this, arguments);
if (reinit) {
this._initSpecialOptions();
this._initEventHandlers();
}
};
nUIFileUpload.prototype._initSpecialOptions = function () {
var options = this.options;
if (options.fileInput === undefined) {
options.fileInput = this.element.is('input[type="file"]') ?
this.element : this.element.find('input[type="file"]');
} else if (!(options.fileInput instanceof $)) {
options.fileInput = $(options.fileInput);
}
if (!(options.dropZone instanceof $)) {
options.dropZone = $(options.dropZone);
}
if (!(options.pasteZone instanceof $)) {
options.pasteZone = $(options.pasteZone);
}
};
nUIFileUpload.prototype._getRegExp = function (str) {
var parts = str.split('/'),
modifiers = parts.pop();
parts.shift();
return new RegExp(parts.join('/'), modifiers);
};
nUIFileUpload.prototype._isRegExpOption = function (key, value) {
return key !== 'url' && $.type(value) === 'string' && /^\/.*\/[igm]{0,3}$/.test(value);
};
nUIFileUpload.prototype._initDataAttributes = function () {
var that = this,
options = this.options,
data = this.element.data();
// Initialize options set via HTML5 data-attributes:
$.each(
this.element[0].attributes,
function (index, attr) {
var key = attr.name.toLowerCase(),
value;
if (/^data-/.test(key)) {
// Convert hyphen-ated key to camelCase:
key = key.slice(5).replace(/-[a-z]/g, function (str) {
return str.charAt(1).toUpperCase();
});
value = data[key];
if (that._isRegExpOption(key, value)) {
value = that._getRegExp(value);
}
options[key] = value;
}
}
);
};
nUIFileUpload.prototype.create = function () {
this._initDataAttributes();
this._initSpecialOptions();
this._slots = [];
this._sequence = this._getXHRPromise(true);
this._sending = this._active = 0;
this._initProgressObject(this);
this._initEventHandlers();
};
// This method is exposed to the widget API and allows to query
// the number of active uploads:
nUIFileUpload.prototype.active = function () {
return this._active;
};
// This method is exposed to the widget API and allows to query
// the widget upload progress.
// It returns an object with loaded, total and bitrate properties
// for the running uploads:
nUIFileUpload.prototype.progress = function () {
return this._progress;
};
// This method is exposed to the widget API and allows adding files
// using the fileupload API. The data parameter accepts an object which
// must have a files property and can contain additional options:
// .nUIFileUpload('add', {files: filesList});
nUIFileUpload.prototype.add = function (data) {
var that = this;
if (!data || this.options.disabled) {
return;
}
if (data.fileInput && !data.files) {
this._getFileInputFiles(data.fileInput).always(function (files) {
data.files = files;
that._onAdd(null, data);
});
} else {
data.files = $.makeArray(data.files);
this._onAdd(null, data);
}
};
// This method is exposed to the widget API and allows sending files
// using the nUIFileUpload API. The data parameter accepts an object which
// must have a files or fileInput property and can contain additional options:
// .nUIFileUpload('send', {files: filesList});
// The method returns a Promise object for the file upload call.
nUIFileUpload.prototype.send = function (data) {
if (data && !this.options.disabled) {
if (data.fileInput && !data.files) {
var that = this,
dfd = $.Deferred(),
promise = dfd.promise(),
jqXHR,
aborted;
promise.abort = function () {
aborted = true;
if (jqXHR) {
return jqXHR.abort();
}
dfd.reject(null, 'abort', 'abort');
return promise;
};
this._getFileInputFiles(data.fileInput).always(
function (files) {
if (aborted) {
return;
}
if (!files.length) {
dfd.reject();
return;
}
data.files = files;
jqXHR = that._onSend(null, data);
jqXHR.then(
function (result, textStatus, jqXHR) {
dfd.resolve(result, textStatus, jqXHR);
},
function (jqXHR, textStatus, errorThrown) {
dfd.reject(jqXHR, textStatus, errorThrown);
}
);
}
);
return this._enhancePromise(promise);
}
data.files = $.makeArray(data.files);
if (data.files.length) {
return this._onSend(null, data);
}
}
return this._getXHRPromise(false, data && data.context);
};
N2Classes.nUIWidgetBase.register('nUIFileUpload');
return nUIFileUpload;
});
N2D('HorizontalScrollBar', function ($) {
"use strict";
/**
* @memberOf N2Classes
*
* @param $container
* @constructor
*/
function HorizontalScrollBar($container) {
this.$container = $container;
this.$document = $(document);
this.currentLeft = 0;
this.$viewport = $container.find('.n2-scroll-viewport');
this.$content = $container.find('.n2-scroll-content');
this.$track = $container.find('.n2-scroll-track');
this.$grip = $container.find('.n2-scroll-grip');
this.side = window.n2const.isRTL() ? "right" : "left";
this.modifier = window.n2const.isRTL() ? -1 : 1;
this.$grip.on('mousedown.scrollbar', $.proxy(this.mouseDown, this));
this.update();
$(window).resize($.proxy(this.update, this));
}
HorizontalScrollBar.prototype.update = function () {
this.viewportWidth = this.$viewport.width();
this.contentWidth = this.$content.outerWidth();
this.trackWidth = this.$track.width();
this.ratio = Math.min(1, this.viewportWidth / this.contentWidth);
this.gripWidth = Math.max(20, Math.floor(this.ratio * this.trackWidth));
this.$grip.width(this.gripWidth);
this.setLeft(this.currentLeft);
this.$container.toggleClass("n2-scroll-disable", this.ratio === 1);
};
HorizontalScrollBar.prototype.setLeft = function (left) {
left = Math.max(0, Math.min(this.trackWidth - this.gripWidth, left));
this.$grip.css(this.side, left);
this.$content.css(this.side, -1 * Math.ceil(left / this.ratio));
this.currentLeft = left;
};
HorizontalScrollBar.prototype.mouseDown = function (e) {
this.context = {
pageX: e.pageX,
left: this.currentLeft
};
this.$document.on({
'mousemove.scrollbar': $.proxy(this.mouseMove, this),
'mouseup.scrollbar': $.proxy(this.mouseUp, this)
});
};
HorizontalScrollBar.prototype.mouseMove = function (e) {
this.setLeft(this.context.left + (e.pageX - this.context.pageX) * this.modifier);
};
HorizontalScrollBar.prototype.mouseUp = function (e) {
this.mouseMove(e);
/**
* Cleanup when the interaction ends.
*/
this.$document.off('.scrollbar');
delete this.context;
};
return HorizontalScrollBar;
});
/*
* jQuery Iframe Transport Plugin 1.8.3
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2011, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
*/
/* global define, require, window, document */
N2D('ajaxTransportIframe', function ($, undefined) {
'use strict';
// Helper variable to create unique names for the transport iframes:
var counter = 0;
// The iframe transport accepts four additional options:
// options.fileInput: a jQuery collection of file input fields
// options.paramName: the parameter name for the file form data,
// overrides the name property of the file input field(s),
// can be a string or an array of strings.
// options.formData: an array of objects with name and value properties,
// equivalent to the return data of .serializeArray(), e.g.:
// [{name: 'a', value: 1}, {name: 'b', value: 2}]
// options.initialIframeSrc: the URL of the initial iframe src,
// by default set to "javascript:false;"
$.ajaxTransport('iframe', function (options) {
if (options.async) {
// javascript:false as initial iframe src
// prevents warning popups on HTTPS in IE6:
/*jshint scripturl: true */
var initialIframeSrc = options.initialIframeSrc || 'javascript:false;',
/*jshint scripturl: false */
form,
iframe,
addParamChar;
return {
send: function (_, completeCallback) {
form = $('<form style="display:none;"></form>');
form.attr('accept-charset', options.formAcceptCharset);
addParamChar = /\?/.test(options.url) ? '&' : '?';
// XDomainRequest only supports GET and POST:
if (options.type === 'DELETE') {
options.url = options.url + addParamChar + '_method=DELETE';
options.type = 'POST';
} else if (options.type === 'PUT') {
options.url = options.url + addParamChar + '_method=PUT';
options.type = 'POST';
} else if (options.type === 'PATCH') {
options.url = options.url + addParamChar + '_method=PATCH';
options.type = 'POST';
}
// IE versions below IE8 cannot set the name property of
// elements that have already been added to the DOM,
// so we set the name along with the iframe HTML markup:
counter += 1;
iframe = $(
'<iframe src="' + initialIframeSrc +
'" name="iframe-transport-' + counter + '"></iframe>'
).bind('load', function () {
var fileInputClones,
paramNames = $.isArray(options.paramName) ?
options.paramName : [options.paramName];
iframe
.unbind('load')
.bind('load', function () {
var response;
// Wrap in a try/catch block to catch exceptions thrown
// when trying to access cross-domain iframe contents:
try {
response = iframe.contents();
// Google Chrome and Firefox do not throw an
// exception when calling iframe.contents() on
// cross-domain requests, so we unify the response:
if (!response.length || !response[0].firstChild) {
throw new Error();
}
} catch (e) {
response = undefined;
}
// The complete callback returns the
// iframe content document as response object:
completeCallback(
200,
'success',
{'iframe': response}
);
// Fix for IE endless progress bar activity bug
// (happens on form submits to iframe targets):
$('<iframe src="' + initialIframeSrc + '"></iframe>')
.appendTo(form);
window.setTimeout(function () {
// Removing the form in a setTimeout call
// allows Chrome's developer tools to display
// the response result
form.remove();
}, 0);
});
form
.prop('target', iframe.prop('name'))
.prop('action', options.url)
.prop('method', options.type);
if (options.formData) {
$.each(options.formData, function (index, field) {
$('<input type="hidden"/>')
.prop('name', field.name)
.val(field.value)
.appendTo(form);
});
}
if (options.fileInput && options.fileInput.length &&
options.type === 'POST') {
fileInputClones = options.fileInput.clone();
// Insert a clone for each file input field:
options.fileInput.after(function (index) {
return fileInputClones[index];
});
if (options.paramName) {
options.fileInput.each(function (index) {
$(this).prop(
'name',
paramNames[index] || options.paramName
);
});
}
// Appending the file input fields to the hidden form
// removes them from their original location:
form
.append(options.fileInput)
.prop('enctype', 'multipart/form-data')
// enctype must be set as encoding for IE:
.prop('encoding', 'multipart/form-data');
// Remove the HTML5 form attribute from the input(s):
options.fileInput.removeAttr('form');
}
form.submit();
// Insert the file input fields at their original location
// by replacing the clones with the originals:
if (fileInputClones && fileInputClones.length) {
options.fileInput.each(function (index, input) {
var clone = $(fileInputClones[index]);
// Restore the original name and form properties:
$(input)
.prop('name', clone.prop('name'))
.attr('form', clone.attr('form'));
clone.replaceWith(input);
});
}
});
form.append(iframe).appendTo(document.body);
},
abort: function () {
if (iframe) {
// javascript:false as iframe src aborts the request
// and prevents warning popups on HTTPS in IE6.
// concat is used to avoid the "Script URL" JSLint error:
iframe
.unbind('load')
.prop('src', initialIframeSrc);
}
if (form) {
form.remove();
}
}
};
}
});
// The iframe transport returns the iframe content document as response.
// The following adds converters from iframe to text, json, html, xml
// and script.
// Please note that the Content-Type for JSON responses has to be text/plain
// or text/html, if the browser doesn't include application/json in the
// Accept header, else IE will show a download dialog.
// The Content-Type for XML responses on the other hand has to be always
// application/xml or text/xml, so IE properly parses the XML response.
// See also
// https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation
$.ajaxSetup({
converters: {
'iframe text': function (iframe) {
return iframe && $(iframe[0].body).text();
},
'iframe json': function (iframe) {
return iframe && $.parseJSON($(iframe[0].body).text());
},
'iframe html': function (iframe) {
return iframe && $(iframe[0].body).html();
},
'iframe xml': function (iframe) {
var xmlDoc = iframe && iframe[0];
return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc :
$.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) ||
$(xmlDoc.body).html());
},
'iframe script': function (iframe) {
return iframe && $.globalEval($(iframe[0].body).text());
}
}
});
});
N2D('nUIMouse', ['nUIWidgetBase'], function ($, undefined) {
"use strict";
var ie = !!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());
var mouseHandled = false;
$(document).on("mouseup", function () {
mouseHandled = false;
});
/**
* @memberOf N2Classes
*
* @abstract
* @constructor
* @augments nUIWidgetBase
*/
function nUIMouse(element, options) {
this.widgetName = this.widgetName || 'nUIMouse';
this.options = $.extend({}, {
cancel: "input, textarea, button, select, option",
distance: 1,
delay: 0
}, this.options);
N2Classes.nUIWidgetBase.prototype.constructor.apply(this, arguments);
}
nUIMouse.prototype = Object.create(N2Classes.nUIWidgetBase.prototype);
nUIMouse.prototype.constructor = nUIMouse;
nUIMouse.prototype._mouseInit = function () {
var that = this;
this.element
.on("mousedown." + this.widgetName, function (event) {
return that._mouseDown(event);
})
.on("click." + this.widgetName, function (event) {
if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
$.removeData(event.target, that.widgetName + ".preventClickEvent");
event.stopImmediatePropagation();
return false;
}
});
this.started = false;
};
nUIMouse.prototype._mouseDestroy = function () {
this.element.off("." + this.widgetName);
if (this._mouseMoveDelegate) {
this.document
.off("mousemove." + this.widgetName, this._mouseMoveDelegate)
.off("mouseup." + this.widgetName, this._mouseUpDelegate);
}
};
nUIMouse.prototype._mouseDown = function (event) {
// don't let more than one widget handle mouseStart
if (mouseHandled) {
return;
}
this._mouseMoved = false;
// We may have missed mouseup (out of window)
( this._mouseStarted && this._mouseUp(event) );
this._mouseDownEvent = event;
var that = this,
btnIsLeft = ( event.which === 1 ),
// event.target.nodeName works around a bug in IE 8 with
// disabled inputs (#7620)
elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ?
$(event.target).closest(this.options.cancel).length : false );
if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
return true;
}
this.mouseDelayMet = !this.options.delay;
if (!this.mouseDelayMet) {
this._mouseDelayTimer = setTimeout(function () {
that.mouseDelayMet = true;
}, this.options.delay);
}
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
this._mouseStarted = ( this._mouseStart(event) !== false );
if (!this._mouseStarted) {
event.preventDefault();
return true;
}
}
// Click event may never have fired (Gecko & Opera)
if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
$.removeData(event.target, this.widgetName + ".preventClickEvent");
}
// These delegates are required to keep context
this._mouseMoveDelegate = function (event) {
return that._mouseMove(event);
};
this._mouseUpDelegate = function (event) {
return that._mouseUp(event);
};
this.document
.on("mousemove." + this.widgetName, this._mouseMoveDelegate)
.on("mouseup." + this.widgetName, this._mouseUpDelegate);
event.preventDefault();
mouseHandled = true;
return true;
};
nUIMouse.prototype._mouseMove = function (event) {
// Only check for mouseups outside the document if you've moved inside the document
// at least once. This prevents the firing of mouseup in the case of IE<9, which will
// fire a mousemove event if content is placed under the cursor. See #7778
// Support: IE <9
if (this._mouseMoved) {
// IE mouseup check - mouseup happened when mouse was out of window
if (ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
return this._mouseUp(event);
// Iframe mouseup check - mouseup occurred in another document
} else if (!event.which) {
// Support: Safari <=8 - 9
// Safari sets which to 0 if you press any of the following keys
// during a drag (#14461)
if (event.originalEvent.altKey || event.originalEvent.ctrlKey ||
event.originalEvent.metaKey || event.originalEvent.shiftKey) {
this.ignoreMissingWhich = true;
} else if (!this.ignoreMissingWhich) {
return this._mouseUp(event);
}
}
}
if (event.which || event.button) {
this._mouseMoved = true;
}
if (this._mouseStarted) {
this._mouseDrag(event);
return event.preventDefault();
}
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
this._mouseStarted =
( this._mouseStart(this._mouseDownEvent, event) !== false );
( this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event) );
}
return !this._mouseStarted;
};
nUIMouse.prototype._mouseUp = function (event) {
this.document
.off("mousemove." + this.widgetName, this._mouseMoveDelegate)
.off("mouseup." + this.widgetName, this._mouseUpDelegate);
if (this._mouseStarted) {
this._mouseStarted = false;
if (event.target === this._mouseDownEvent.target) {
$.data(event.target, this.widgetName + ".preventClickEvent", true);
}
this._mouseStop(event);
}
if (this._mouseDelayTimer) {
clearTimeout(this._mouseDelayTimer);
delete this._mouseDelayTimer;
}
this.ignoreMissingWhich = false;
mouseHandled = false;
event.preventDefault();
};
nUIMouse.prototype._mouseDistanceMet = function (event) {
return ( Math.max(
Math.abs(this._mouseDownEvent.pageX - event.pageX),
Math.abs(this._mouseDownEvent.pageY - event.pageY)
) >= this.options.distance
);
};
nUIMouse.prototype._mouseDelayMet = function (/* event */) {
return this.mouseDelayMet;
};
// These are placeholder methods, to be overriden by extending plugin
nUIMouse.prototype._mouseStart = function (/* event */) {
};
nUIMouse.prototype._mouseDrag = function (/* event */) {
};
nUIMouse.prototype._mouseStop = function (/* event */) {
};
nUIMouse.prototype._mouseCapture = function (/* event */) {
return true;
};
return nUIMouse;
});
N2D('nUINormalSizing', ['nUIMouse'], function ($, undefined) {
"use strict";
/**
* @memberOf N2Classes
*
* @constructor
* @augments nUIMouse
* @this nUINormalSizing
*/
function nUINormalSizing(element, options) {
this.element = $(element);
this.widgetName = this.widgetName || 'nUINormalSizing';
this.widgetEventPrefix = "normalsizing";
this.multiplier = 1;
this.options = $.extend({
maxWidth: true,
height: false,
syncWidth: false,
start: null,
resizeMaxWidth: null,
resizeHeight: null,
stopMaxWidth: null,
stopHeight: null
}, this.options, options);
N2Classes.nUIMouse.prototype.constructor.apply(this, arguments);
this.create();
}
nUINormalSizing.prototype = Object.create(N2Classes.nUIMouse.prototype);
nUINormalSizing.prototype.constructor = nUINormalSizing;
nUINormalSizing.prototype.create = function () {
this._setupHandles();
this._mouseInit();
};
nUINormalSizing.prototype._destroy = function () {
this._mouseDestroy();
this.element
.removeData(this.widgetName);
for (var k in this.handles) {
this.handles[k].remove();
}
return this;
};
nUINormalSizing.prototype._setupHandles = function () {
var o = this.options, i, n = [], hname, axis;
if (o.maxWidth) {
n.push('w');
n.push('e');
}
if (o.height) {
n.push('s');
}
this.handles = {};
for (i = 0; i < n.length; i++) {
var handle = n[i];
axis = $('<div class="nui-normal-sizing-handle nui-normal-sizing-' + handle + '">').css('zIndex', 90);
this.handles[handle] = axis;
this.element.append(axis);
}
if (o.maxWidth) {
nextend.tooltip.addElement(this.handles.e, 'Max width');
nextend.tooltip.addElement(this.handles.w, 'Max width');
}
if (o.height) {
nextend.tooltip.addElement(this.handles.s, 'Height');
}
this._handles = this.element.find("> .nui-normal-sizing-handle");
this._handles.addClass('n2-unselectable');
};
nUINormalSizing.prototype._removeHandles = function () {
this._handles.remove();
};
nUINormalSizing.prototype._mouseCapture = function (event) {
var handle,
capture = false;
for (handle in this.handles) {
if (this.handles[handle][0] === event.target) {
this.currentHandle = handle;
return !this.options.disabled;
}
}
return false;
};
nUINormalSizing.prototype._mouseStart = function (event) {
var o = this.options,
el = this.element;
this.resizing = true;
this.originalMousePosition = {left: event.pageX, top: event.pageY};
switch (this.currentHandle) {
case 'w':
case 'e':
this.originalValue = this.element.width();
this.maxWidth = this.element.parent().width();
this._trigger("start", event, 'maxwidth');
if (this.element.css('align-self') == 'center') {
this.multiplier = 2;
} else {
this.multiplier = 1;
}
break;
case 's':
this.originalValue = this.element.height();
this._trigger("start", event, 'height');
break;
}
this.element.addClass("nui-normal-sizing-resizing");
$("body").addClass('n2-ss-normal-sizing-element');
return true;
};
nUINormalSizing.prototype._parse_movement_s = function (e) {
return e.pageY - this.originalMousePosition.top;
};
nUINormalSizing.prototype._parse_movement_e = function (e) {
return (e.pageX - this.originalMousePosition.left) * this.multiplier;
};
nUINormalSizing.prototype._parse_movement_w = function (e) {
return (this.originalMousePosition.left - e.pageX) * this.multiplier;
};
nUINormalSizing.prototype._mouseDrag = function (event) {
var o = this.options;
this.currentValue = nextend.roundHelper(this.originalValue + this['_parse_movement_' + this.currentHandle].call(this, event));
switch (this.currentHandle) {
case 'w':
case 'e':
if (this.currentValue <= this.maxWidth) {
this.element.css('maxWidth', this.currentValue + 'px');
if (o.syncWidth) {
this.element.css('width', this.currentValue + 'px');
}
} else {
this.element.css('maxWidth', 'none');
if (o.syncWidth) {
this.element.css('width', '');
}
this.currentValue = 0;
}
this._trigger("resizeMaxWidth", event, {value: this.currentValue});
break;
case 's':
this.currentValue = Math.max(1, this.currentValue);
this.element.height(this.currentValue);
this._trigger("resizeHeight", event, {value: this.currentValue});
break;
}
};
nUINormalSizing.prototype._mouseStop = function (event) {
var o = this.options;
this.currentValue = nextend.roundHelper(this.originalValue + this['_parse_movement_' + this.currentHandle].call(this, event));
switch (this.currentHandle) {
case 'w':
case 'e':
if (this.currentValue <= this.maxWidth) {
this.element.css('maxWidth', this.currentValue + 'px');
if (o.syncWidth) {
this.element.css('width', '');
}
} else {
this.element.css('maxWidth', 'none');
if (o.syncWidth) {
this.element.css('width', '');
}
this.currentValue = 0;
}
this._trigger("stopMaxWidth", event, {value: this.currentValue});
break;
case 's':
this.currentValue = Math.max(1, this.currentValue);
this.element.height(this.currentValue);
this._trigger("stopHeight", event, {value: this.currentValue});
break;
}
this.resizing = false;
$("body").off('.uiNextendNormalSizing')
.removeClass('n2-ss-normal-sizing-element');
this.element.removeClass("nui-normal-sizing-resizing");
nextend.preventMouseUp();
return false;
};
N2Classes.nUIWidgetBase.register('nUINormalSizing');
return nUINormalSizing;
});
N2D('nUIResizableBar', ['nUIMouse'], function ($, undefined) {
"use strict";
/**
* @memberOf N2Classes
*
* @param element
* @param options
*/
function nUIResizableBar(element, options) {
this.element = $(element);
this.widgetName = this.widgetName || 'nUIResizable';
this.widgetEventPrefix = "resize";
this.options = $.extend({
zIndex: 90,
// Callbacks
resize: null,
start: null,
stop: null
}, this.options, options);
N2Classes.nUIMouse.prototype.constructor.apply(this, arguments);
this.create();
}
nUIResizableBar.prototype = Object.create(N2Classes.nUIMouse.prototype);
nUIResizableBar.prototype.constructor = nUIResizableBar;
nUIResizableBar.prototype.create = function () {
var o = this.options;
this.element.addClass("nui-resizable");
this._setupHandles();
this._mouseInit();
this._trigger('create', null, {});
};
nUIResizableBar.prototype._setupHandles = function () {
var o = this.options, handle, i, n, hname, axis, that = this;
this._handles = $();
n = ["e", "w"];
this.handles = {};
for (i = 0; i < n.length; i++) {
handle = $.trim(n[i]);
hname = "nui-resizable-" + handle;
axis = $("<div>")
.addClass("nui-resizable-handle " + hname)
.css({zIndex: o.zIndex});
this.handles[handle] = ".nui-resizable-" + handle;
this.element.append(axis);
axis.on({
"mousedown": $.proxy(function (handleName, e) {
this.currentHandle = handleName;
this._mouseDown(e);
}, this, handle)
});
this._handles = this._handles.add(axis);
}
this._handles.css({
'-ms-user-select': 'none',
'-moz-user-select': '-moz-none',
'-khtml-user-select': 'none',
'-webkit-user-select': 'none',
'user-select': 'none'
});
};
nUIResizableBar.prototype._mouseStart = function (event) {
this.currentData = this.originalData = {
margin: parseInt(this.element.css(n2const.rtl.marginLeft)),
width: parseInt(this.element.width())
};
this.originalMousePosition = {left: event.pageX};
var cursor = $(".nui-resizable-" + this.axis).css("cursor");
$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
this.element.addClass("nui-resizable-resizing");
this._trigger("start", event, this.ui());
return true;
};
nUIResizableBar.prototype._mouseDrag = function (event) {
var dx = (event.pageX - this.originalMousePosition.left) || 0;
this.currentData = {};
if (!n2const.rtl.isRtl) {
if (this.currentHandle === 'e') {
this.currentData.margin = this.originalData.margin;
this.currentData.width = Math.max(0, this.originalData.width + dx);
} else if (this.currentHandle === 'w') {
this.currentData.margin = Math.max(0, this.originalData.margin + dx);
this.currentData.width = Math.max(0, this.originalData.width - dx);
}
} else {
if (this.currentHandle === 'e') {
this.currentData.margin = Math.max(0, this.originalData.margin - dx);
this.currentData.width = Math.max(0, this.originalData.width + dx);
} else if (this.currentHandle === 'w') {
this.currentData.margin = this.originalData.margin;
this.currentData.width = Math.max(0, this.originalData.width - dx);
}
}
this._trigger("resize", event, this.ui());
this.element.css(n2const.rtl.marginLeft, this.currentData.margin);
this.element.css('width', this.currentData.width);
};
nUIResizableBar.prototype._mouseStop = function (event) {
$("body").css("cursor", "auto");
this.element.removeClass("nui-resizable-resizing");
this._trigger("stop", event, this.ui());
};
nUIResizableBar.prototype.ui = function () {
return {
currentData: this.currentData
};
};
N2Classes.nUIWidgetBase.register('nUIResizableBar');
return nUIResizableBar;
});
N2D('nUIResizable', ['nUIMouse'], function ($, undefined) {
"use strict";
/**
* @memberOf N2Classes
*
* @param element
* @param options
*/
function nUIResizable(element, options) {
this.element = $(element);
this.widgetName = this.widgetName || 'nUIResizable';
this.widgetEventPrefix = "resize";
this.options = $.extend({
alsoResize: false,
containment: false,
handles: "e,s,se",
helper: false,
maxHeight: null,
maxWidth: null,
minHeight: 10,
minWidth: 10,
// See #7960
zIndex: 90,
// Callbacks
resize: null,
start: null,
stop: null
}, this.options, options);
N2Classes.nUIMouse.prototype.constructor.apply(this, arguments);
this.create();
}
nUIResizable.prototype = Object.create(N2Classes.nUIMouse.prototype);
nUIResizable.prototype.constructor = nUIResizable;
nUIResizable.plugins = {};
nUIResizable.prototype._num = function (value) {
return parseFloat(value) || 0;
};
nUIResizable.prototype._isNumber = function (value) {
return !isNaN(parseFloat(value));
};
nUIResizable.prototype._hasScroll = function (el, a) {
if ($(el).css("overflow") === "hidden") {
return false;
}
var scroll = (a && a === "left") ? "scrollLeft" : "scrollTop",
has = false;
if (el[scroll] > 0) {
return true;
}
// TODO: determine which cases actually cause this to happen
// if the element doesn't have the scroll set, see if it's possible to
// set the scroll
el[scroll] = 1;
has = (el[scroll] > 0);
el[scroll] = 0;
return has;
};
nUIResizable.prototype.create = function () {
var o = this.options;
this.element.addClass("nui-resizable");
$.extend(this, {
originalElement: this.element,
_helper: o.helper ? o.helper || "nui-resizable-helper" : null
});
this._setupHandles();
this._mouseInit();
this._trigger('create', null, {});
};
nUIResizable.prototype._setupHandles = function () {
var o = this.options, handle, i, n, hname, axis, that = this;
this.handles = o.handles ||
(!$(".nui-resizable-handle", this.element).length ?
"e,s,se" : {
n: ".nui-resizable-n",
e: ".nui-resizable-e",
s: ".nui-resizable-s",
w: ".nui-resizable-w",
se: ".nui-resizable-se",
sw: ".nui-resizable-sw",
ne: ".nui-resizable-ne",
nw: ".nui-resizable-nw"
});
this._handles = $();
if (this.handles.constructor === String) {
if (this.handles === "all") {
this.handles = "n,e,s,w,se,sw,ne,nw";
}
n = this.handles.split(",");
this.handles = {};
for (i = 0; i < n.length; i++) {
handle = $.trim(n[i]);
hname = "nui-resizable-" + handle;
axis = $("<div>")
.addClass("nui-resizable-handle " + hname);
axis.css({zIndex: o.zIndex});
this.handles[handle] = ".nui-resizable-" + handle;
this.element.append(axis);
}
}
this._renderAxis = function () {
var i;
for (i in this.handles) {
if (this.handles[i].constructor === String) {
this.handles[i] = this.element.children(this.handles[i]).first().show();
} else if (this.handles[i].jquery || this.handles[i].nodeType) {
this.handles[i] = $(this.handles[i]);
this._on(this.handles[i], {"mousedown": that._mouseDown});
}
this._handles = this._handles.add(this.handles[i]);
}
};
// TODO: make renderAxis a prototype function
this._renderAxis(this.element);
this._handles = this._handles.add(this.element.find(".nui-resizable-handle"));
this._handles.addClass('n2-unselectable');
this._handles.on("mouseover", function () {
if (!that.resizing) {
if (this.className) {
axis = this.className.match(/nui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
}
that.axis = axis && axis[1] ? axis[1] : "se";
}
});
};
nUIResizable.prototype._mouseCapture = function (event) {
var i, handle,
capture = false;
for (i in this.handles) {
handle = $(this.handles[i])[0];
if (handle === event.target || $.contains(handle, event.target)) {
capture = true;
}
}
return !this.options.disabled && capture;
};
nUIResizable.prototype._removeHandles = function () {
this._handles.remove();
};
nUIResizable.prototype._mouseStart = function (event) {
var position = this.element.position();
this.element.css({
left: position.left,
top: position.top,
right: 'auto',
bottom: 'auto'
});
var curleft, curtop, cursor,
o = this.options,
el = this.element;
this.resizing = true;
this._renderProxy();
curleft = this._num(this.helper.css("left"));
curtop = this._num(this.helper.css("top"));
if (o.containment) {
curleft += $(o.containment).scrollLeft() || 0;
curtop += $(o.containment).scrollTop() || 0;
}
this.offset = this.helper.offset();
this.position = {left: curleft, top: curtop};
this.size = this._helper ? {
width: this.helper.width(),
height: this.helper.height()
} : {
width: el.width(),
height: el.height()
};
this.originalSize = this._helper ? {
width: el.outerWidth(),
height: el.outerHeight()
} : {
width: el.width(),
height: el.height()
};
this.sizeDiff = {
width: el.outerWidth() - el.width(),
height: el.outerHeight() - el.height()
};
this.originalPosition = {left: curleft, top: curtop};
this.originalMousePosition = {left: event.pageX, top: event.pageY};
cursor = $(".nui-resizable-" + this.axis).css("cursor");
$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
this.element.addClass("nui-resizable-resizing");
this._propagate("start", event);
return true;
};
nUIResizable.prototype._mouseDrag = function (event) {
var data, props,
smp = this.originalMousePosition,
a = this.axis,
dx = (event.pageX - smp.left) || 0,
dy = (event.pageY - smp.top) || 0,
trigger = this._change[a];
this._updatePrevProperties();
if (!trigger) {
return false;
}
data = trigger.apply(this, [event, dx, dy]);
this._updateVirtualBoundaries();
data = this._respectSize(data, event);
this._updateCache(data);
this._propagate("resize", event);
props = this._applyChanges();
if (!$.isEmptyObject(props)) {
this._updatePrevProperties();
this._trigger("resize", event, this.ui());
this._applyChanges();
}
return false;
};
nUIResizable.prototype._mouseStop = function (event) {
this.resizing = false;
var s, left, top, that = this;
if (this._helper) {
s = {
width: that.helper.width(),
height: that.helper.height()
};
left = (parseFloat(that.element.css("left")) +
(that.position.left - that.originalPosition.left)) || null;
top = (parseFloat(that.element.css("top")) +
(that.position.top - that.originalPosition.top)) || null;
this.element.css($.extend(s, {top: top, left: left}));
that.helper.height(that.size.height);
that.helper.width(that.size.width);
}
$("body").css("cursor", "auto");
this.element.removeClass("nui-resizable-resizing");
this._propagate("stop", event);
if (this._helper) {
this.helper.remove();
}
return false;
};
nUIResizable.prototype._updatePrevProperties = function () {
this.prevPosition = {
top: this.position.top,
left: this.position.left
};
this.prevSize = {
width: this.size.width,
height: this.size.height
};
};
nUIResizable.prototype._applyChanges = function () {
var props = {};
if (this.position.top !== this.prevPosition.top) {
props.top = this.position.top + "px";
}
if (this.position.left !== this.prevPosition.left) {
props.left = this.position.left + "px";
}
if (this.size.width !== this.prevSize.width) {
props.width = this.size.width + "px";
}
if (this.size.height !== this.prevSize.height) {
props.height = this.size.height + "px";
}
this.helper.css(props);
return props;
};
nUIResizable.prototype._updateVirtualBoundaries = function () {
var b,
o = this.options;
b = {
minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
};
this._vBoundaries = b;
};
nUIResizable.prototype._updateCache = function (data) {
this.offset = this.helper.offset();
if (this._isNumber(data.left)) {
this.position.left = data.left;
}
if (this._isNumber(data.top)) {
this.position.top = data.top;
}
if (this._isNumber(data.height)) {
this.size.height = data.height;
}
if (this._isNumber(data.width)) {
this.size.width = data.width;
}
};
nUIResizable.prototype._respectSize = function (data) {
var o = this._vBoundaries,
a = this.axis,
ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width),
ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width),
isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
dw = this.originalPosition.left + this.originalSize.width,
dh = this.originalPosition.top + this.originalSize.height,
cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
if (isminw) {
data.width = o.minWidth;
}
if (isminh) {
data.height = o.minHeight;
}
if (ismaxw) {
data.width = o.maxWidth;
}
if (ismaxh) {
data.height = o.maxHeight;
}
if (isminw && cw) {
data.left = dw - o.minWidth;
}
if (ismaxw && cw) {
data.left = dw - o.maxWidth;
}
if (isminh && ch) {
data.top = dh - o.minHeight;
}
if (ismaxh && ch) {
data.top = dh - o.maxHeight;
}
// Fixing jump error on top/left - bug #2330
if (!data.width && !data.height && !data.left && data.top) {
data.top = null;
} else if (!data.width && !data.height && !data.top && data.left) {
data.left = null;
}
return data;
};
nUIResizable.prototype._renderProxy = function () {
var el = this.element, o = this.options;
this.elementOffset = el.offset();
if (this._helper) {
this.helper = this.helper || $("<div style='overflow:hidden;'></div>")
.addClass(this._helper);
this.helper.css({
width: this.element.outerWidth(),
height: this.element.outerHeight(),
position: "absolute",
left: this.elementOffset.left + "px",
top: this.elementOffset.top + "px",
zIndex: ++o.zIndex //TODO: Don't modify option
});
this.helper
.addClass('n2-unselectable')
.appendTo("body");
} else {
this.helper = this.element;
}
};
nUIResizable.prototype._change = {
e: function (event, dx) {
return {width: this.originalSize.width + dx};
},
w: function (event, dx) {
var cs = this.originalSize, sp = this.originalPosition;
return {left: sp.left + dx, width: cs.width - dx};
},
n: function (event, dx, dy) {
var cs = this.originalSize, sp = this.originalPosition;
return {top: sp.top + dy, height: cs.height - dy};
},
s: function (event, dx, dy) {
return {height: this.originalSize.height + dy};
},
se: function (event, dx, dy) {
return $.extend(this._change.s.apply(this, arguments),
this._change.e.apply(this, [event, dx, dy]));
},
sw: function (event, dx, dy) {
return $.extend(this._change.s.apply(this, arguments),
this._change.w.apply(this, [event, dx, dy]));
},
ne: function (event, dx, dy) {
return $.extend(this._change.n.apply(this, arguments),
this._change.e.apply(this, [event, dx, dy]));
},
nw: function (event, dx, dy) {
return $.extend(this._change.n.apply(this, arguments),
this._change.w.apply(this, [event, dx, dy]));
}
};
nUIResizable.prototype._propagate = function (n, event) {
this.callPlugin(n, [event, this.ui()]);
(n !== "resize" && this._trigger(n, event, this.ui()));
};
nUIResizable.prototype.ui = function () {
return {
originalElement: this.originalElement,
element: this.element,
helper: this.helper,
position: this.position,
size: this.size,
originalSize: this.originalSize,
originalPosition: this.originalPosition,
axis: this.axis
};
};
nUIResizable.prototype._destroy = function () {
this._mouseDestroy();
this.element
.removeClass("nui-resizable")
.removeData(this.widgetName);
for (var k in this.handles) {
this.handles[k].remove();
}
return this;
};
N2Classes.nUIWidgetBase.addPlugin(nUIResizable, "smartguides", {
start: function (event, ui) {
var i = $(this).data("nUIResizable"), o = i.options;
i.gridH = $('<div class="n2-grid n2-grid-h"></div>').appendTo(o._containment);
i.gridV = $('<div class="n2-grid n2-grid-v"></div>').appendTo(o._containment);
i.gridH2 = $('<div class="n2-grid n2-grid-h"></div>').appendTo(o._containment);
i.gridV2 = $('<div class="n2-grid n2-grid-v"></div>').appendTo(o._containment);
i.elements = [];
if (typeof o.smartguides == 'function') {
var guides = o.smartguides();
if (guides) {
var containmentOffset = o._containment.offset();
guides.each(function () {
var $t = $(this);
var $o = $t.offset();
if (this != i.element[0]) i.elements.push({
item: this,
width: $t.outerWidth(),
height: $t.outerHeight(),
top: Math.round($o.top - containmentOffset.top),
left: Math.round($o.left - containmentOffset.left)
});
});
i.elements.push({
item: o._containment,
width: o._containment.width(), height: o._containment.height(),
top: 0, left: 0
});
}
}
},
stop: function (event, ui) {
var i = $(this).data("nUIResizable");
i.gridH.remove();
i.gridV.remove();
i.gridH2.remove();
i.gridV2.remove();
},
resize: function (event, ui) {
var inst = $(this).data("nUIResizable"), o = inst.options;
var d = o.tolerance;
inst.gridV.css({"display": "none"});
inst.gridH.css({"display": "none"});
inst.gridV2.css({"display": "none"});
inst.gridH2.css({"display": "none"});
var container = inst.elements[inst.elements.length - 1];
function setGridV(left) {
inst.gridV.css({left: Math.min(left, container.width - 1), display: "block"});
};
function setGridV2(left) {
inst.gridV2.css({left: Math.min(left, container.width - 1), display: "block"});
};
function setGridH(top) {
inst.gridH.css({top: Math.min(top, container.height - 1), display: "block"});
};
function setGridH2(top) {
inst.gridH2.css({top: Math.min(top, container.height - 1), display: "block"});
};
var ctrlKey = event.ctrlKey || event.metaKey,
altKey = event.altKey;
if (ctrlKey && altKey) {
return;
}
var x1 = ui.position.left, x2 = x1 + ui.size.width,
y1 = ui.position.top, y2 = y1 + ui.size.height;
for (var i = inst.elements.length - 1; i >= 0; i--) {
var l = inst.elements[i].left, r = l + inst.elements[i].width,
t = inst.elements[i].top, b = t + inst.elements[i].height;
if (!ctrlKey) {
var hc = (l + r) / 2;
if (Math.abs(l - x2) <= d) {
ui.size.width = l - ui.position.left;
setGridV(ui.position.left + ui.size.width);
} else if (Math.abs(l - x1) <= d) {
var diff = ui.position.left - l;
ui.position.left = l;
ui.size.width += diff;
setGridV(ui.position.left);
} else if (Math.abs(hc - x1) <= d) {
var diff = ui.position.left - hc;
ui.position.left = hc;
ui.size.width += diff;
setGridV(ui.position.left);
}
if (Math.abs(r - x1) <= d) {
var diff = ui.position.left - r;
ui.position.left = r;
ui.size.width += diff;
setGridV2(ui.position.left);
} else if (Math.abs(r - x2) <= d) {
ui.size.width = r - ui.position.left;
setGridV2(ui.position.left + ui.size.width);
} else if (Math.abs(hc - x2) <= d) {
ui.size.width = hc - ui.position.left;
setGridV2(ui.position.left + ui.size.width);
}
}
if (!altKey) {
var vc = (t + b) / 2;
if (Math.abs(t - y2) <= d) {
ui.size.height = t - ui.position.top;
setGridH(t);
} else if (Math.abs(t - y1) <= d) {
var diff = ui.position.top - t;
ui.position.top = t;
ui.size.height += diff;
setGridH(ui.position.top);
} else if (Math.abs(vc - y1) <= d) {
var diff = ui.position.top - vc;
ui.position.top = vc;
ui.size.height += diff;
setGridH(ui.position.top);
}
if (Math.abs(b - y1) <= d) {
var diff = ui.position.top - b;
ui.position.top = b;
ui.size.height += diff;
setGridH2(ui.position.top);
} else if (Math.abs(b - y2) <= d) {
ui.size.height = b - ui.position.top;
setGridH2(ui.position.top + ui.size.height);
} else if (Math.abs(vc - y2) <= d) {
ui.size.height = vc - ui.position.top;
setGridH2(ui.position.top + ui.size.height);
}
}
}
}
});
N2Classes.nUIWidgetBase.register('nUIResizable');
return nUIResizable;
});
N2D('nUISlider', ['nUIMouse'], function ($, undefined) {
"use strict";
/**
* @memberOf N2Classes
*
* @constructor
* @augments nUIMouse
* @this nUISlider
*/
function nUISlider(element, options) {
this.element = $(element);
this.widgetName = this.widgetName || 'nUISlider';
this.widgetEventPrefix = "slide";
this.options = $.extend({
min: 0,
max: 100,
step: 1,
value: 0,
// Callbacks
change: null,
slide: null,
start: null,
stop: null
}, this.options, options);
N2Classes.nUIMouse.prototype.constructor.apply(this, arguments);
this.create();
}
nUISlider.prototype = Object.create(N2Classes.nUIMouse.prototype);
nUISlider.prototype.constructor = nUISlider;
N2Classes.nUIWidgetBase.register('nUISlider');
nUISlider.prototype.create = function () {
this._mouseSliding = false;
this._mouseInit();
this._calculateNewMax();
this.element.addClass("nui-slider nui-slider-horizontal");
this._refresh();
};
nUISlider.prototype.doAction = function (action) {
N2Classes.nUIWidgetBase.prototype.doAction.apply(this, arguments);
switch (action) {
case 'value':
return this._value();
}
};
nUISlider.prototype.setOption = function (key, value) {
N2Classes.nUIWidgetBase.prototype.setOption.call(this, key, value);
switch (key) {
case "value":
this._refreshValue();
this._change(null, 0);
break;
case "step":
case "min":
case "max":
this._calculateNewMax();
this._refreshValue();
break;
}
};
nUISlider.prototype._refresh = function () {
this._createHandle();
this._refreshValue();
};
nUISlider.prototype._createHandle = function () {
var existingHandle = this.element.find(".nui-slider-handle");
if (existingHandle.length) {
this.handle = existingHandle;
} else {
this.handle = $("<span tabindex='0'></span>");
}
this.handle.attr("tabIndex", 0)
.addClass("nui-slider-handle")
.appendTo(this.element);
};
nUISlider.prototype._mouseCapture = function (event) {
var position, normValue, distance, handle = this.handle, allowed, offset, mouseOverHandle,
o = this.options;
if (o.disabled) {
return false;
}
this.elementSize = {
width: this.element.outerWidth(),
height: this.element.outerHeight()
};
this.elementOffset = this.element.offset();
position = {x: event.pageX, y: event.pageY};
normValue = this._normValueFromMouse(position);
allowed = this._start(event);
if (allowed === false) {
return false;
}
this._mouseSliding = true;
handle.trigger("focus");
this._slide(event, normValue);
return true;
};
nUISlider.prototype._mouseStart = function () {
this.lastValue = Number.MAX_VALUE;
return true;
};
nUISlider.prototype._mouseDrag = function (event) {
var position = {x: event.pageX, y: event.pageY},
normValue = this._normValueFromMouse(position);
if (this.lastValue != normValue) {
this._slide(event, normValue);
this.lastValue = normValue;
}
return false;
};
nUISlider.prototype._mouseStop = function (event) {
this._mouseSliding = false;
this._stop(event);
this._change(event);
return false;
};
nUISlider.prototype._normValueFromMouse = function (position) {
var pixelTotal,
pixelMouse,
percentMouse,
valueTotal,
valueMouse;
pixelTotal = this.elementSize.width;
pixelMouse = position.x - this.elementOffset.left;
percentMouse = ( pixelMouse / pixelTotal );
if (percentMouse > 1) {
percentMouse = 1;
}
if (percentMouse < 0) {
percentMouse = 0;
}
valueTotal = this._valueMax() - this._valueMin();
valueMouse = this._valueMin() + percentMouse * valueTotal;
return this._trimAlignValue(valueMouse);
};
nUISlider.prototype._trimAlignValue = function (val) {
if (val <= this._valueMin()) {
return this._valueMin();
}
if (val >= this._valueMax()) {
return this._valueMax();
}
var step = ( this.options.step > 0 ) ? this.options.step : 1,
valModStep = ( val - this._valueMin() ) % step,
alignValue = val - valModStep;
if (Math.abs(valModStep) * 2 >= step) {
alignValue += ( valModStep > 0 ) ? step : ( -step );
}
// Since JavaScript has problems with large floats, round
// the final value to 5 digits after the decimal point (see #4124)
return parseFloat(alignValue.toFixed(5));
};
nUISlider.prototype._calculateNewMax = function () {
var max = this.options.max,
min = this._valueMin(),
step = this.options.step,
aboveMin = Math.round(( max - min ) / step) * step;
max = aboveMin + min;
if (max > this.options.max) {
//If max is not divisible by step, rounding off may increase its value
max -= step;
}
this.max = parseFloat(max.toFixed(this._precision()));
};
nUISlider.prototype._precision = function () {
var precision = this._precisionOf(this.options.step);
if (this.options.min !== null) {
precision = Math.max(precision, this._precisionOf(this.options.min));
}
return precision;
};
nUISlider.prototype._precisionOf = function (num) {
var str = num.toString(),
decimal = str.indexOf(".");
return decimal === -1 ? 0 : str.length - decimal - 1;
};
nUISlider.prototype._change = function (event) {
if (!this._mouseSliding) {
this._trigger("change", event, this._uiHash());
}
};
nUISlider.prototype.value = function (newValue) {
if (arguments.length) {
this.options.value = this._trimAlignValue(newValue);
this._refreshValue();
this._change(null, 0);
return;
}
return this._value();
};
//internal value getter
// _value() returns value trimmed by min and max, aligned by step
nUISlider.prototype._value = function () {
var val = this.options.value;
val = this._trimAlignValue(val);
return val;
};
nUISlider.prototype._valueMin = function () {
return this.options.min;
};
nUISlider.prototype._valueMax = function () {
return this.max;
};
nUISlider.prototype._refreshValue = function () {
var value = this.value(),
valueMin = this._valueMin(),
valueMax = this._valueMax(),
valPercent = ( valueMax !== valueMin ) ? ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 0;
this.handle.css('left', valPercent + "%");
};
nUISlider.prototype._uiHash = function (value) {
return {
handle: this.handle[0],
value: value !== undefined ? value : this.value()
};
};
nUISlider.prototype._start = function (event) {
return this._trigger("start", event, this._uiHash());
};
nUISlider.prototype._slide = function (event, newVal) {
var allowed,
currentValue = this.value();
if (newVal === currentValue) {
return;
}
allowed = this._trigger("slide", event, this._uiHash(newVal));
// A slide can be canceled by returning false from the slide callback
if (allowed === false) {
return;
}
this.value(newVal);
};
nUISlider.prototype._stop = function (event) {
this._trigger("stop", event, this._uiHash());
};
return nUISlider;
});
N2D('nUISortable', ['nUIMouse'], function ($, undefined) {
"use strict";
/**
* @memberOf N2Classes
*
* @constructor
* @augments nUIMouse
*/
function nUISortable(element, options) {
this.element = $(element);
this.widgetName = this.widgetName || 'nUISortable';
this.widgetEventPrefix = "sortable";
this.options = $.extend({
items: '> *',
handle: '',
placeholder: false,
helper: 'original',
forcePlaceholderSize: false,
forceHelperSize: false,
axis: false,
droppables: false
}, this.options, options);
this.isOver = false;
N2Classes.nUIMouse.prototype.constructor.apply(this, arguments);
this.create();
}
nUISortable.prototype = Object.create(N2Classes.nUIMouse.prototype);
nUISortable.prototype.constructor = nUISortable;
nUISortable.prototype.create = function () {
this._mouseInit();
};
nUISortable.prototype._mouseCapture = function (e) {
if (this.options.disabled) {
return false;
}
var currentItem = null,
$target = $(e.target);
if (this.options.handle !== '') {
var handles = this.element.find(this.options.items + ' ' + this.options.handle);
if (handles.index($target) === -1 && !handles.has($target).length) {
//Item not dragged by the handle
return false;
}
}
var items = this.element.find(this.options.items);
if (items.index($target) !== -1) {
currentItem = $target;
} else {
currentItem = items.has($target);
}
if (!currentItem.length) {
return false;
}
this.currentItem = currentItem;
return true;
};
nUISortable.prototype._mouseStart = function (e) {
this._trigger('beforestart', e, {
currentItem: this.currentItem
});
this.context = {
e: e,
original: {
pageX: e.pageX,
pageY: e.pageY,
clientX: e.clientX,
clientY: e.clientY,
elementBCR: this.element[0].getBoundingClientRect(),
currentItemBCR: this.currentItem[0].getBoundingClientRect()
},
offsetShift: {
top: 0,
left: 0
},
scrollCB: $.proxy(this._mouseScroll, this)
};
this.element.addClass('n2-ui-sortable-in-progress');
this._cacheItems();
this.placeholder = $('<div/>')
.addClass(this.options.placeholder || this.currentItem[0].className);
var size = {
width: this.currentItem.width(),
height: this.currentItem.height()
};
if (this.options.helper === 'clone') {
this.helper = this.currentItem.clone();
} else if (this.options.helper === 'clone_hide') {
this.helper = this.currentItem.clone();
this.currentItem.css('display', 'none');
} else {
this.helper = this.currentItem
}
if (this.options.forceHelperSize) {
this.helper.css(size);
}
if (this.options.forcePlaceholderSize) {
this.placeholder.css(size);
}
this.helper.addClass('n2-ui-sortable-helper')
.css({
position: 'absolute',
zIndex: 1000
})
.appendTo(this.element);
this._trigger('start', e, this.ui());
/**
* Trigger mousemove event on scroll to update the helper position
*/
window.addEventListener('scroll', this.context.scrollCB, {
capture: true,
passive: true
});
};
nUISortable.prototype._mouseDrag = function (e) {
this.context.e = e;
var elementBDR = this.element[0].getBoundingClientRect(),
helperPosition = {};
if (!this.options.axis || this.options.axis === 'x') {
var modifierX = elementBDR.left + this.context.original.clientX - e.clientX;
this.context.offsetShift.left = e.pageX - this.context.original.pageX - this.context.original.elementBCR.left + modifierX;
helperPosition.left = this.context.original.currentItemBCR.left - modifierX;
}
if (!this.options.axis || this.options.axis === 'y') {
var modifierY = elementBDR.top + this.context.original.clientY - e.clientY;
this.context.offsetShift.top = e.pageY - this.context.original.pageY - this.context.original.elementBCR.top + modifierY;
helperPosition.top = this.context.original.currentItemBCR.top - modifierY;
}
this.helper.css(helperPosition);
var closestData = this._findClosestItem(e),
nearestItem = closestData[1] === 'before' ? this.items[Math.max(0, closestData[2] - 1)] : this.items[Math.min(this.items.length - 1, closestData[2])];
if (this.options.helper === 'clone' && (closestData[0].is(this.currentItem) || $(nearestItem).is(this.currentItem))) {
this.placeholder.detach();
} else {
this.positionPlaceholder(closestData);
}
if (this.options.droppables) {
if (closestData[1] !== 'over') {
if (this.isOver) {
this._trigger('out', e, this.ui());
this.isOver = false;
}
} else {
if (this.isOver && !this.isOver.is(closestData[0])) {
this._trigger('out', e, this.ui());
this.isOver = false;
}
if (!this.isOver) {
this.isOver = closestData[0];
this._trigger('over', e, this.ui());
}
}
}
};
nUISortable.prototype.positionPlaceholder = function (closestData) {
switch (closestData[1]) {
case 'before':
this.placeholder.insertBefore(closestData[0]);
break;
case 'after':
this.placeholder.insertAfter(closestData[0]);
break;
case 'over':
this.placeholder.detach();
break;
}
};
nUISortable.prototype._mouseStop = function (e) {
this.context.e = e;
this._trigger('beforestop', e, this.ui());
window.removeEventListener('scroll', this.context.scrollCB, {
capture: true,
passive: true
});
this.placeholder.remove();
var closestData = this._findClosestItem(e);
switch (closestData[1]) {
case 'before':
this.currentItem.insertBefore(closestData[0]);
break;
case 'after':
this.currentItem.insertAfter(closestData[0]);
break;
}
this.helper
.removeClass('n2-ui-sortable-helper')
.css({
position: '',
zIndex: '',
left: '',
top: ''
});
if (this.options.helper === 'clone' || this.options.helper === 'clone_hide') {
this.helper.remove();
}
if (this.options.helper === 'clone_hide') {
this.currentItem.css('display', '');
}
this.element.removeClass('n2-ui-sortable-in-progress');
if (closestData[1] === 'over') {
this._trigger('drop', e, this.ui());
this._trigger('out', e, this.ui());
} else {
this._trigger('stop', e, this.ui());
}
this.currentItem = null;
};
nUISortable.prototype._findClosestItem = function (e) {
var distance = Number.MAX_VALUE,
left = e.pageX - this.context.offsetShift.left,
top = e.pageY - this.context.offsetShift.top,
closestItem, closestItemSide, closestItemIndex;
for (var i = 0; i < this.itemsData.length; i++) {
var item = this.itemsData[i];
for (var k in item.side) {
var localDistance = Math.sqrt(Math.pow((left - item.side[k].left) / item.width, 2) + Math.pow((top - item.side[k].top) / item.height, 2));
if (localDistance < distance) {
distance = localDistance;
closestItem = item.item;
closestItemSide = k;
if (k === 'after') {
closestItemIndex = i + 1;
} else if (k === 'before') {
closestItemIndex = i;
}
}
}
}
return [closestItem, closestItemSide, closestItemIndex];
};
nUISortable.prototype.getItems = function () {
return this.element.find(this.options.items);
};
nUISortable.prototype._cacheItems = function () {
this.items = this.getItems();
this.itemsData = [];
for (var i = 0; i < this.items.length; i++) {
if (this.options.helper === 'original' && this.items[i] === this.currentItem[0]) {
continue;
}
var offset = this.items.eq(i).offset(),
width = this.items.eq(i).width(),
height = this.items.eq(i).height(),
side = {};
if (this.options.droppables && !this.currentItem.hasClass(this.options.droppables) && this.items.eq(i).hasClass(this.options.droppables)) {
side.before = {
left: offset.left + width / 6,
top: offset.top + height / 6
};
side.over = {
left: offset.left + 3 * width / 6,
top: offset.top + 3 * height / 6
};
side.after = {
left: offset.left + 5 * width / 6,
top: offset.top + 5 * height / 6
};
} else {
side.before = {
left: offset.left + width / 4,
top: offset.top + height / 4
};
side.after = {
left: offset.left + 3 * width / 4,
top: offset.top + 3 * height / 4
};
}
if (window.n2const.isRTL()) {
var after = side.after;
side.after = side.before;
side.before = after;
}
this.itemsData.push({
item: this.items.eq(i),
side: side,
width: width,
height: height
});
}
};
nUISortable.prototype._mouseScroll = function () {
var e = this.context.e;
document.dispatchEvent(new MouseEvent('mousemove', {
clientX: e.clientX,
clientY: e.clientY
}));
};
nUISortable.prototype.ui = function () {
return {
placeholder: this.placeholder,
helper: this.helper,
item: this.currentItem,
droppable: this.isOver
};
};
N2Classes.nUIWidgetBase.register('nUISortable');
return nUISortable;
});
N2D('nUISortableRow', ['nUISortable'], function ($, undefined) {
"use strict";
/**
* @memberOf N2Classes
*
* @param element
* @param options
*/
function nUISortableRow(element, options) {
N2Classes.nUISortable.prototype.constructor.apply(this, arguments);
this.lastPosition = null;
}
nUISortableRow.prototype = Object.create(N2Classes.nUISortable.prototype);
nUISortableRow.prototype.constructor = nUISortableRow;
nUISortableRow.prototype.getItems = function () {
var items = this.element.find(this.options.items);
if (items.eq(0).attr('style').indexOf('order:') !== -1) {
items.sort(function (a, b) {
var aOrder = $(a).css('order'),
bOrder = $(b).css('order');
return ((aOrder < bOrder) ? -1 : ((aOrder > bOrder) ? 1 : 0));
});
this.hasOrder = true;
} else {
this.hasOrder = false;
}
this.lastPosition = null;
return items;
};
nUISortableRow.prototype.positionPlaceholder = function (closestData) {
switch (closestData[1]) {
case 'before':
this.placeholder.insertBefore(closestData[0]);
if (this.hasOrder) {
this.placeholder.css('order', closestData[0].css('order') - 1);
}
break;
case 'after':
this.placeholder.insertAfter(closestData[0]);
if (this.hasOrder) {
this.placeholder.css('order', closestData[0].css('order') + 1);
}
break;
case 'over':
this.placeholder.detach();
break;
}
this.lastPosition = closestData;
};
nUISortableRow.prototype.ui = function () {
return {
placeholder: this.placeholder,
helper: this.helper,
item: this.currentItem,
droppable: this.isOver,
lastPosition: this.lastPosition
};
};
N2Classes.nUIWidgetBase.register('nUISortableRow');
return nUISortableRow;
});
N2D('nUISpacing', ['nUIMouse'], function ($, undefined) {
"use strict";
/**
* @memberOf N2Classes
*
* @constructor
* @augments nUIMouse
* @this nUISpacing
*/
function nUISpacing(element, options) {
this.element = $(element);
this.widgetName = this.widgetName || 'nUISpacing';
this.widgetEventPrefix = "spacing";
this.options = $.extend({
handles: '',
mode: 'padding',
sync: {
n: 'padding-top',
e: 'padding-right',
s: 'padding-bottom',
w: 'padding-left'
},
syncInv: {
n: 's',
e: 'w',
s: 'n',
w: 'e'
},
side: {
n: 'top',
e: 'right',
s: 'bottom',
w: 'left'
},
size: {
n: 'height',
e: 'width',
s: 'height',
w: 'width'
},
// Callbacks
drag: null,
start: null,
stop: null
}, this.options, options);
N2Classes.nUIMouse.prototype.constructor.apply(this, arguments);
this.create();
}
nUISpacing.prototype = Object.create(N2Classes.nUIMouse.prototype);
nUISpacing.prototype.constructor = nUISpacing;
nUISpacing.prototype.create = function () {
this._setupHandles();
this._mouseInit();
};
nUISpacing.prototype._destroy = function () {
this._mouseDestroy();
this.element
.removeData(this.widgetName);
for (var k in this.handles) {
this.handles[k].remove();
}
return this;
};
nUISpacing.prototype._setupHandles = function () {
var o = this.options, handle, i, n, hname, axis;
n = "n,e,s,w".split(",");
this.handles = {};
for (i = 0; i < n.length; i++) {
handle = $.trim(n[i]);
hname = "nui-spacing-" + handle;
this.handles[handle] = axis = $("<div>")
.addClass("nui-spacing-handle nui-spacing-handle-" + o.mode + " nui-spacing-handle " + hname)
.addClass('n2-unselectable')
.on('mousedown', $.proxy(this._mouseDown, this))
.appendTo(this.element);
nextend.tooltip.addElement(this.handles[handle], N2Classes.StringHelper.capitalize(o.mode) + ' ' + o.side[handle]);
}
};
nUISpacing.prototype._removeHandles = function () {
this.element.find("> .nui-spacing-handle").remove();
};
nUISpacing.prototype._parse_movement_n = function (e) {
return e.pageY - this.originalMousePosition.top;
};
nUISpacing.prototype._parse_movement_w = function (e) {
return e.pageX - this.originalMousePosition.left;
};
nUISpacing.prototype._parse_movement_s = function (e) {
return e.pageY - this.originalMousePosition.top;
};
nUISpacing.prototype._parse_movement_e = function (e) {
return this.originalMousePosition.left - e.pageX;
};
nUISpacing.prototype._mouseCapture = function (e) {
var i, handle,
capture = false;
for (i in this.handles) {
handle = $(this.handles[i])[0];
if (handle === e.target || $.contains(handle, e.target)) {
capture = true;
}
}
return !this.options.disabled && capture;
};
nUISpacing.prototype._mouseStart = function (e) {
this.wasShiftPressed = false;
var handle;
for (var d in this.handles) {
handle = this.handles[d][0];
if (handle === e.target || $.contains(handle, e.target)) {
this.direction = d;
break;
}
}
this.syncProperty = this.options.sync[this.direction];
this.originalValue = parseInt(this.element.css(this.syncProperty));
this.invSyncProperty = this.options.sync[this.options.syncInv[this.direction]];
this.invOriginalValue = parseInt(this.element.css(this.invSyncProperty));
this.resizing = true;
this.originalMousePosition = {left: e.pageX, top: e.pageY};
this.currentValue = this.originalValue;
this.handles[this.direction].addClass('nui-spacing-under-spacing');
this.element.addClass("nui-spacing-resizing");
$("body")
.on('keydown.' + this.widgetEventPrefix, $.proxy(this._keyDown, this))
.on('keyup.' + this.widgetEventPrefix, $.proxy(this._keyUp, this))
.addClass('n2-ss-spacing-element');
this._trigger("start", e, this.ui());
return true;
};
nUISpacing.prototype._keyDown = function (e) {
if (e.shiftKey && !this.wasShiftPressed) {
this.wasShiftPressed = true;
this.element.css(this.invSyncProperty, this.currentValue);
this.handles[this.options.syncInv[this.direction]].css(this.options.size[this.options.syncInv[this.direction]], this.currentValue);
this._trigger("spacing", e, this.ui());
}
};
nUISpacing.prototype._keyUp = function (e) {
if (!e.shiftKey && this.wasShiftPressed) {
this.wasShiftPressed = false;
this.element.css(this.invSyncProperty, this.invOriginalValue);
this.handles[this.options.syncInv[this.direction]].css(this.options.size[this.options.syncInv[this.direction]], '');
this._trigger("spacing", e, this.ui());
}
};
nUISpacing.prototype._mouseDrag = function (e) {
this.movement = this['_parse_movement_' + this.direction].call(this, e);
this.currentValue = nextend.roundHelper(this.originalValue + this.movement);
if (this.options.mode == 'padding') {
this.currentValue = Math.max(0, this.currentValue);
}
this.element.css(this.syncProperty, this.currentValue);
this.handles[this.direction].css(this.options.size[this.direction], this.currentValue);
if (e.shiftKey) {
this.wasShiftPressed = true;
this.element.css(this.invSyncProperty, this.currentValue);
this.handles[this.options.syncInv[this.direction]].css(this.options.size[this.options.syncInv[this.direction]], this.currentValue);
} else if (this.wasShiftPressed) {
this.wasShiftPressed = false;
this.element.css(this.invSyncProperty, this.invOriginalValue);
this.handles[this.options.syncInv[this.direction]].css(this.options.size[this.options.syncInv[this.direction]], '');
}
this._trigger("spacing", e, this.ui());
};
nUISpacing.prototype._mouseStop = function (e) {
this.movement = this['_parse_movement_' + this.direction].call(this, e);
this.currentValue = nextend.roundHelper(this.originalValue + this.movement);
if (this.options.mode == 'padding') {
this.currentValue = Math.max(0, this.currentValue);
}
this.element.css(this.syncProperty, this.currentValue);
if (e.shiftKey) {
this.element.css(this.invSyncProperty, this.currentValue);
} else if (this.wasShiftPressed) {
this.element.css(this.invSyncProperty, this.invOriginalValue);
}
this.resizing = false;
$("body").off('.' + this.widgetEventPrefix)
.removeClass('n2-ss-spacing-element');
this.handles[this.direction].removeClass('nui-spacing-under-spacing');
this.element.removeClass("nui-spacing-resizing");
this._trigger("stop", e, this.ui());
nextend.preventMouseUp();
return false;
};
nUISpacing.prototype.ui = function () {
var changed = {};
changed[this.options.side[this.direction]] = this.currentValue;
if (this.wasShiftPressed) {
changed[this.options.side[this.options.syncInv[this.direction]]] = this.currentValue;
}
return {
element: this.element,
changed: changed
};
};
nUISpacing.prototype.setOption = function (key, value) {
N2Classes.nUIWidgetBase.prototype.setOption.apply(this, arguments);
if (key === "current") {
var values = value.split(' ');
this.handles.n.css('height', values[0]);
this.handles.e.css('width', values[1]);
this.handles.s.css('height', values[2]);
this.handles.w.css('width', values[3]);
}
};
N2Classes.nUIWidgetBase.register('nUISpacing');
return nUISpacing;
});
N2D('nUIWidgetBase', function ($, undefined) {
"use strict";
/**
* @memberOf N2Classes
*
* @abstract
* @constructor
*/
function nUIWidgetBase(element, options) {
this.document = $(element.style ?
// Element within the document
element.ownerDocument :
// Element is window or document
element.document || element);
this.window = $(this.document[0].defaultView || this.document[0].parentWindow);
this.disabled = false;
this.plugins = [];
}
nUIWidgetBase.prototype.doAction = function (action) {
switch (action) {
case 'option':
return this.setOption.apply(this, Array.prototype.slice.call(arguments, 1));
break;
case 'instance':
return this;
case 'destroy':
return this._destroy();
}
};
nUIWidgetBase.prototype.setOption = function (key, value) {
this.options[key] = value;
return this;
};
/**
* @abstract
* @returns {N2Classes.nUIWidgetBase}
*/
nUIWidgetBase.prototype._destroy = function () {
return this;
};
nUIWidgetBase.prototype._trigger = function (type, event, data) {
var prop, orig;
var callback = this.options[type];
data = data || {};
event = $.Event(event);
event.type = ( type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type ).toLowerCase();
// The original event may come from any element
// so we need to reset the target on the new event
event.target = this.element[0];
// Copy original event properties over to the new event
orig = event.originalEvent;
if (orig) {
for (prop in orig) {
if (!( prop in event )) {
event[prop] = orig[prop];
}
}
}
this.element.trigger(event, data);
return !( $.isFunction(callback) &&
callback.apply(this.element[0], [event].concat(data)) === false ||
event.isDefaultPrevented() );
};
nUIWidgetBase.register = function (name, className) {
className = className || name;
$.fn[name] = function () {
if (arguments.length && typeof arguments[0] === 'string') {
var o = this.eq(0).data(name);
if (!o) {
return false;
}
return o.doAction.apply(o, arguments);
}
var options = {};
if (arguments.length == 1) {
options = arguments[0];
}
this.each(function () {
var o = $(this).data(name);
if (!o) {
$(this).data(name, new N2Classes[className](this, options))
}
});
return this;
};
};
nUIWidgetBase.addPlugin = function (_class, option, set) {
for (var key in set) {
_class.plugins[key] = _class.plugins[key] || [];
_class.plugins[key].push([option, set[key]]);
}
};
nUIWidgetBase.prototype.callPlugin = function (name, args, allowDisconnected) {
var set = this.constructor.plugins[name];
if (!set) {
return;
}
if (!allowDisconnected && ( !this.element[0].parentNode ||
this.element[0].parentNode.nodeType === 11 )) {
return;
}
for (var i = 0; i < set.length; i++) {
if (this.options[set[i][0]]) {
set[i][1].apply(this.element, args);
}
}
};
return nUIWidgetBase;
});
N2D('nextend-backend')