44820 lines (38233 with data), 1.5 MB
/**
* @license
* webix UI v.9.0.0
* This software is allowed to use under GPL or you need to obtain Commercial License
* to use it in non-GPL project. Please contact sales@webix.com for details
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.webix = {})));
}(this, (function (exports) { 'use strict';
function _typeof(obj) {
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function (obj) {
return typeof obj;
};
} else {
_typeof = function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof(obj);
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
}
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
}
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArray(iter) {
if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
}
function _iterableToArrayLimit(arr, i) {
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance");
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
var global = window;
var queueId = 1;
var queue = {};
var isRunningTask = false;
if (!global.setImmediate && global.addEventListener) global.addEventListener("message", function (e) {
if (e.source == global) {
if (isRunningTask) nextTick(queue[e.data]);else {
isRunningTask = true;
try {
queue[e.data]();
} catch (e) {// eslint-disable-line
}
delete queue[e.data];
isRunningTask = false;
}
}
});
function nextTick(fn) {
if (global.setImmediate) global.setImmediate(fn); // if inside of web worker
else if (global.importScripts || !global.addEventListener) setTimeout(fn);else {
queueId++;
queue[queueId] = fn;
global.postMessage(queueId, "*");
}
}
Deferred.resolve = function (value) {
if (!(this._d == 1)) throw TypeError();
if (value instanceof Deferred) return value;
return new Deferred(function (resolve) {
resolve(value);
});
};
Deferred.reject = function (value) {
if (!(this._d == 1)) throw TypeError();
return new Deferred(function (resolve, reject) {
reject(value);
});
};
Deferred.all = function (arr) {
if (!(this._d == 1)) throw TypeError();
if (!(arr instanceof Array)) return Deferred.reject(TypeError());
var d = new Deferred();
function done(e, v) {
if (v) return d.resolve(v);
if (e) return d.reject(e);
var unresolved = arr.reduce(function (cnt, v) {
if (v && v.then) return cnt + 1;
return cnt;
}, 0);
if (unresolved == 0) d.resolve(arr);
arr.map(function (v, i) {
if (v && v.then) v.then(function (r) {
arr[i] = r;
done();
return r;
}, done);
});
}
done();
return d;
};
Deferred.race = function (arr) {
if (!(this._d == 1)) throw TypeError();
if (!(arr instanceof Array)) return Deferred.reject(TypeError());
if (arr.length == 0) return new Deferred();
var d = new Deferred();
function done(e, v) {
if (v) return d.resolve(v);
if (e) return d.reject(e);
var unresolved = arr.reduce(function (cnt, v) {
if (v && v.then) return cnt + 1;
return cnt;
}, 0);
if (unresolved == 0) d.resolve(arr);
arr.map(function (v) {
if (v && v.then) v.then(function (r) {
done(null, r);
}, done);
});
}
done();
return d;
};
Deferred._d = 1;
/**
* @constructor
*/
function Deferred(resolver) {
if (typeof resolver != "function" && resolver != undefined) throw TypeError();
if (_typeof(this) != "object" || this && this.then) throw TypeError(); // states
// 0: pending
// 1: resolving
// 2: rejecting
// 3: resolved
// 4: rejected
var self = this,
state = 0,
val = 0,
next = [],
fn,
er;
self["promise"] = self;
self["resolve"] = function (v) {
fn = self.fn;
er = self.er;
if (!state) {
val = v;
state = 1;
nextTick(fire);
}
return self;
};
self["reject"] = function (v) {
fn = self.fn;
er = self.er;
if (!state) {
val = v;
state = 2;
nextTick(fire);
}
return self;
};
self["_d"] = 1;
self["then"] = function (_fn, _er) {
if (!(this._d == 1)) throw TypeError();
var d = new Deferred();
d.fn = _fn;
d.er = _er;
if (state == 3) {
d.resolve(val);
} else if (state == 4) {
d.reject(val);
} else {
next.push(d);
}
return d;
};
self["finally"] = function (_handler) {
var _value;
var handler = function (value) {
_value = value;
return _handler();
};
var value = function () {
var d = new Deferred();
if (state == 4) return d.reject(_value);else return d.resolve(_value);
};
return self.then(handler, handler).then(value, value);
};
self["catch"] = function (_er) {
return self["then"](null, _er);
}; //compatibility with old version of promiz lib
self["fail"] = function (_er) {
return self["then"](null, _er);
};
var finish = function (type) {
state = type || 4;
for (var i = 0; i < next.length; i++) {
var p = next[i];
state == 3 && p.resolve(val) || p.reject(val);
}
};
try {
if (typeof resolver == "function") resolver(self["resolve"], self["reject"]);
} catch (e) {
self["reject"](e);
}
return self; // ref : reference to 'then' function
// cb, ec, cn : successCallback, failureCallback, notThennableCallback
function thennable(ref, cb, ec, cn) {
// Promises can be rejected with other promises, which should pass through
if (state == 2) {
return cn();
}
if ((_typeof(val) == "object" || typeof val == "function") && typeof ref == "function") {
try {
// cnt protects against abuse calls from spec checker
var cnt = 0;
ref.call(val, function (v) {
if (cnt++) return;
val = v;
cb();
}, function (v) {
if (cnt++) return;
val = v;
ec();
});
} catch (e) {
val = e;
ec();
}
} else {
cn();
}
}
function fire() {
// check if it's a thenable
var ref;
try {
ref = val && val.then;
} catch (e) {
val = e;
state = 2;
return fire();
}
thennable(ref, function () {
state = 1;
fire();
}, function () {
state = 2;
fire();
}, function () {
try {
if (state == 1 && typeof fn == "function") {
val = fn(val);
} else if (state == 2 && typeof er == "function") {
val = er(val);
state = 1;
}
} catch (e) {
val = e;
return finish();
}
if (val == self) {
val = TypeError();
finish();
} else thennable(ref, function () {
finish(3);
}, finish, function () {
finish(state == 1 && 3);
});
});
}
} // promise factory
Deferred.defer = function () {
return new Deferred(null);
};
// resolves circular dependencies
// quick solution, must be removed in the next versions
var services = {};
function define(name, value) {
services[name] = value;
}
function use(name) {
return services[name];
}
function assert(test, msg) {
if (!test) {
log("error", msg);
var message = use("message");
if (message && typeof msg == "string") message({
type: "debug",
text: msg,
expire: -1
});
debugger; // eslint-disable-line
}
} //show log message
function log(type, message, details) {
if (arguments.length == 1) {
message = type;
type = "log";
}
if (window.console && window.console.log) {
type = type.toLowerCase();
if (window.console[type]) window.console[type](message || "unknown error");else window.console.log(type + ": " + message);
if (details) window.console.log(details);
}
}
var debug_mode = {};
function debug(mode) {
if (!mode) debug_mode = {};else if (_typeof(mode) !== "object") debug_mode = {
events: true
};else for (var key in mode) {
debug_mode[key] = mode[key];
}
}
var debug_size_indent = 0;
function debug_size_step() {
var str = "";
for (var i = 0; i < debug_size_indent; i++) {
str += "| ";
}
return str;
}
function debug_size_box_start(comp, get) {
if (!debug_mode.size) return;
if (!debug_size_indent) log(get ? "--- get sizes ---" : "--- set sizes ---");
log(debug_size_step() + comp.name + "@" + comp.config.id);
debug_size_indent++;
}
function debug_size_box_end(comp, sizes) {
if (!debug_mode.size) return;
debug_size_indent--;
log(debug_size_step() + sizes.join(","));
}
function debug_size_box(comp, sizes, get) {
if (!debug_mode.size) return;
if (!debug_size_indent) log(get ? "--- get sizes ---" : "--- set sizes ---");
log(debug_size_step() + comp.name + "@" + comp.config.id + " " + sizes.join(","));
}
var level = 0;
function level_in() {
level++;
assert(level !== 100, "Attempt to copy object with self reference");
}
function level_out() {
level--;
} //coding helpers
function clone(source) {
var f = clone._function;
f.prototype = source;
return new f();
}
clone._function = function () {}; //copies methods and properties from source to the target
exports.extend = function (base, source, force) {
assert(base, "Invalid mixing target");
assert(source, "Invalid mixing source");
if (base.$protoWait) {
_power_array.insertAt.call(base.$protoWait, source, 1);
return base;
} //copy methods, overwrite existing ones in case of conflict
for (var method in source) {
if (!(method in base) || force) base[method] = source[method];
} //in case of defaults - preffer top one
if (source.defaults) exports.extend(base.defaults, source.defaults); //if source object has init code - call init against target
if (source.$init) source.$init.call(base);
return base;
}; //copies methods and properties from source to the target from all levels
function copy(source) {
assert(source, "Invalid mixing target");
level_in();
var esModern = !!window.Map && !!window.Set && !!window.WeakMap && !!window.WeakSet;
var target;
if (arguments.length > 1) {
target = arguments[0];
source = arguments[1];
} else target = isArray(source) ? [] : {};
for (var method in source) {
var from = source[method];
if (from && _typeof(from) == "object" && !(from instanceof RegExp)) {
if (isDate(from)) target[method] = new Date(from);
/* jshint ignore:start */
else if (esModern && (from instanceof Map || from instanceof Set || from instanceof WeakMap || from instanceof WeakSet)) target[method] = from;
/* jshint ignore:end */
else {
target[method] = isArray(from) ? [] : {};
copy(target[method], from);
}
} else {
target[method] = from;
}
}
level_out();
return target;
}
function single(source) {
var instance = null;
var t = function () {
if (!instance) instance = new source({});
if (instance._reinit) instance._reinit.apply(instance, arguments);
return instance;
};
return t;
} //creates function with specified "this" pointer
function bind(functor, object) {
return function () {
return functor.apply(object, arguments);
};
} //evaluate javascript code in the global scoope
function exec(code) {
if (window.execScript) //special handling for IE
window.execScript(code);else window.eval(code);
}
function wrap(code, wrap) {
if (!code) return wrap;
return function () {
var result = code.apply(this, arguments);
wrap.apply(this, arguments);
return result;
};
} //check === undefined
function isUndefined(a) {
return typeof a == "undefined";
} //delay call to after-render time
function delay(method, obj, params, delay) {
return window.setTimeout(function () {
if (!(obj && obj.$destructed)) {
var ret = method.apply(obj, params || []);
method = obj = params = null;
return ret;
}
}, delay || 1);
}
function once(method) {
var flag = true;
return function () {
if (flag) {
flag = false;
method.apply(this, arguments);
}
};
} //common helpers
//generates unique ID (unique per window, nog GUID)
var _seed = new Date().valueOf();
function uid() {
_seed++;
return _seed;
} //resolve ID as html object
function toNode(node) {
if (typeof node == "string") return document.getElementById(node);
return node;
} //resolve function name
function toFunctor(str, scope) {
if (typeof str == "string") {
var method = str.replace("()", "");
if (scope && scope[method]) return scope[method];
return window[method] || window.eval(str);
}
return str;
}
/*checks where an object is instance of Array*/
function isArray(obj) {
return Array.isArray ? Array.isArray(obj) : Object.prototype.toString.call(obj) === "[object Array]";
}
function isDate(obj) {
return obj instanceof Date;
} //adds extra methods for the array
function _to_array(array) {
return exports.extend(array || [], _power_array, true);
} //can be used by _to_array()
var _power_array = {
//remove element at specified position
removeAt: function (pos, len) {
if (pos >= 0) this.splice(pos, len || 1);
},
//find element in collection and remove it
remove: function (value) {
this.removeAt(this.find(value));
},
//add element to collection at specific position
insertAt: function (data, pos) {
if (!pos && pos !== 0) //add to the end by default
this.push(data);else {
this.splice(pos, 0, data);
}
},
//return index of element, -1 if it doesn't exists
find: function (data) {
for (var i = 0; i < this.length; i++) {
if (data == this[i]) return i;
}
return -1;
},
//execute some method for each element of array
each: function (functor, master) {
for (var i = 0; i < this.length; i++) {
functor.call(master || this, this[i]);
}
},
//create new array from source, by using results of functor
map: function (functor, master) {
for (var i = 0; i < this.length; i++) {
this[i] = functor.call(master || this, this[i]);
}
return this;
},
filter: function (functor, master) {
for (var i = 0; i < this.length; i++) {
if (!functor.call(master || this, this[i])) {
this.splice(i, 1);
i--;
}
}
return this;
}
}; //hook for documentation generator
{
if (window.webix_on_core_ready) {
exports.extend = window.webix_on_core_ready({
extend: exports.extend
}).extend;
}
}
var i18n = {
parseFormat: "%Y-%m-%d %H:%i:%s",
parseTimeFormat: "%H:%i:%s"
};
function stringify(obj) {
var origin = Date.prototype.toJSON;
Date.prototype.toJSON = function () {
return i18n.parseFormatStr(this);
};
var result;
if (obj instanceof Date) result = obj.toJSON();else result = JSON.stringify(obj);
Date.prototype.toJSON = origin;
return result;
}
var EventSystem = {
$init: function () {
if (!this._evs_events) {
this._evs_events = {}; //hash of event handlers, name => handler
this._evs_handlers = {}; //hash of event handlers, ID => handler
this._evs_map = {};
}
},
//temporary block event triggering
blockEvent: function () {
this._evs_events._block = true;
},
//re-enable event triggering
unblockEvent: function () {
this._evs_events._block = false;
},
mapEvent: function (map) {
exports.extend(this._evs_map, map, true);
},
on_setter: function (config) {
if (config) {
for (var i in config) {
var method = toFunctor(config[i], this.$scope);
var sub = i.indexOf("->");
if (sub !== -1) {
this[i.substr(0, sub)].attachEvent(i.substr(sub + 2), bind(method, this));
} else this.attachEvent(i, method);
}
}
},
//trigger event
callEvent: function (type, params) {
var master = this._event_master || this;
if (this._evs_events._block) return true;
type = type.toLowerCase();
var event_stack = this._evs_events[type.toLowerCase()]; //all events for provided name
var return_value = true;
if ((debug_mode.events || this.debug) && type !== "onmousemoving") //can slowdown a lot
log("info", "[" + this.name + "@" + (this._settings || {}).id + "] event:" + type, params);
if (event_stack) for (var i = 0; i < event_stack.length; i++) {
/*
Call events one by one
If any event return false - result of whole event will be false
Handlers which are not returning anything - counted as positive
*/
if (event_stack[i].apply(master, params || []) === false) return_value = false;
}
if (this._evs_map[type]) {
var target = this._evs_map[type];
target.$eventSource = this;
if (!target.callEvent(type, params)) return_value = false;
target.$eventSource = null;
}
return return_value;
},
//assign handler for some named event
attachEvent: function (type, functor, id) {
assert(functor, "Invalid event handler for " + type);
type = type.toLowerCase();
id = id || uid(); //ID can be used for detachEvent
functor = toFunctor(functor, this.$scope); //functor can be a name of method
var event_stack = this._evs_events[type] || _to_array(); //save new event handler
if (arguments[3]) event_stack.unshift(functor);else event_stack.push(functor);
this._evs_events[type] = event_stack;
this._evs_handlers[id] = {
f: functor,
t: type
};
return id;
},
//remove event handler
detachEvent: function (id) {
if (!this._evs_handlers[id]) {
var name = (id + "").toLowerCase();
if (this._evs_events[name]) {
this._evs_events[name] = _to_array();
}
return;
}
var type = this._evs_handlers[id].t;
var functor = this._evs_handlers[id].f; //remove from all collections
var event_stack = this._evs_events[type];
event_stack.remove(functor);
delete this._evs_handlers[id];
},
hasEvent: function (type) {
type = type.toLowerCase();
var stack = this._evs_events[type];
if (stack && stack.length) return true;
var parent = this._evs_map[type];
if (parent) return parent.hasEvent(type);
return false;
}
};
var evs = {};
exports.extend(evs, EventSystem, true);
var callEvent = function (a, b) {
return evs.callEvent(a, b);
};
var attachEvent = function (a, b, c, d) {
return evs.attachEvent(a, b, c, d);
};
var detachEvent = function (a) {
return evs.detachEvent(a);
};
var blockEvent = function () {
return evs.blockEvent();
};
var unblockEvent = function () {
return evs.unblockEvent();
};
var mapEvent = function (map) {
return evs.mapEvent(map);
};
var hasEvent = function (type) {
return evs.hasEvent(type);
};
var xml = {
_isValidXML: function (data) {
if (!data || !data.documentElement) return null;
if (data.getElementsByTagName("parsererror").length) return null;
return data;
},
//convert xml string to xml object if necessary
toObject: function (text, response) {
var data = response ? response.rawxml ? response.rawxml() : response : null;
if (this._isValidXML(data)) return data;
if (typeof text == "string") data = this.fromString(text.replace(/^[\s]+/, ""));else data = text;
if (this._isValidXML(data)) return data;
return null;
},
//get array of records
getRecords: function (data) {
return this.xpath(data, this.records);
},
records: "/*/item",
child: "item",
config: "/*/config",
//get hash of properties for single record
getDetails: function (data) {
return this.tagToObject(data, {});
},
getOptions: function () {
return false;
},
//get count of data and position at which new data_loading need to be inserted
getInfo: function (data) {
var config = this.xpath(data, this.config);
if (config.length) config = this.assignTypes(this.tagToObject(config[0], {}));else config = null;
return {
size: data.documentElement.getAttribute("total_count") || 0,
from: data.documentElement.getAttribute("pos"),
parent: data.documentElement.getAttribute("parent") || 0,
config: config
};
},
//xpath helper
xpath: function (xml, path) {
if (window.XPathResult) {
//FF, KHTML, Opera
var node = xml;
if (xml.nodeName.indexOf("document") == -1) xml = xml.ownerDocument;
var res = [];
var col = xml.evaluate(path, node, null, XPathResult.ANY_TYPE, null);
var temp = col.iterateNext();
while (temp) {
res.push(temp);
temp = col.iterateNext();
}
return res;
} else {
var test = true;
try {
if (typeof xml.selectNodes == "undefined") test = false;
} catch (e) {}
/*IE7 and below can't operate with xml object*/
//IE
if (test) return xml.selectNodes(path);else {
//there is no interface to do XPath
//use naive approach
var name = path.split("/").pop();
return xml.getElementsByTagName(name);
}
}
},
assignTypes: function (obj) {
for (var k in obj) {
var test = obj[k];
if (_typeof(test) == "object") this.assignTypes(test);else if (typeof test == "string") {
if (test === "") continue;
if (test == "true") obj[k] = true;else if (test == "false") obj[k] = false;else if (test == test * 1) obj[k] = obj[k] * 1;
}
}
return obj;
},
//convert xml tag to js object, all subtags and attributes are mapped to the properties of result object
tagToObject: function (tag, z) {
var isArray = tag.nodeType == 1 && tag.getAttribute("stack");
var hasSubTags = 0;
if (!isArray) {
z = z || {}; //map attributes
var a = tag.attributes;
if (a && a.length) for (var i = 0; i < a.length; i++) {
z[a[i].name] = a[i].value;
hasSubTags = 1;
} //map subtags
var b = tag.childNodes;
for (var _i = 0; _i < b.length; _i++) {
if (b[_i].nodeType == 1) {
var name = b[_i].tagName;
if (z[name]) {
if (typeof z[name].push != "function") z[name] = [z[name]];
z[name].push(this.tagToObject(b[_i], {}));
} else z[name] = this.tagToObject(b[_i], {}); //sub-object for complex subtags
hasSubTags = 2;
}
}
if (!hasSubTags) return this.nodeValue(tag); //each object will have its text content as "value" property
//only if has not sub tags
if (hasSubTags < 2) z.value = z.value || this.nodeValue(tag);
} else {
z = [];
var _b = tag.childNodes;
for (var _i2 = 0; _i2 < _b.length; _i2++) {
if (_b[_i2].nodeType == 1) z.push(this.tagToObject(_b[_i2], {}));
}
}
return z;
},
//get value of xml node
nodeValue: function (node) {
if (node.firstChild) {
return node.firstChild.wholeText || node.firstChild.data;
}
return "";
},
//convert XML string to XML object
fromString: function (xmlString) {
try {
if (window.DOMParser) // FF, KHTML, Opera
return new DOMParser().parseFromString(xmlString, "text/xml");
/* global ActiveXObject */
if (window.ActiveXObject) {
// IE, utf-8 only
var temp = new ActiveXObject("Microsoft.xmlDOM");
temp.loadXML(xmlString);
return temp;
}
} catch (e) {
assert(0, e);
return null;
}
assert(0, "Load from xml string is not supported");
}
};
var json = {
//convert json string to json object if necessary
toObject: function (data) {
if (!data) return null;
if (typeof data == "string") {
try {
if (this.parseDates) {
var isodate = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(.\d{1-3})?Z/;
data = JSON.parse(data, function (key, value) {
if (typeof value == "string") {
if (isodate.test(value)) return new Date(value);
}
return value;
});
} else {
data = JSON.parse(data);
}
} catch (e) {
log(e);
log(data);
assert(0, "Invalid JSON data for parsing");
return null;
}
}
return data;
},
//get array of records
getRecords: function (data) {
if (data && data.data) data = data.data;
if (data && !isArray(data)) return [data];
return data;
},
//get hash of properties for single record
getDetails: function (data) {
if (typeof data == "string") return {
id: data || uid(),
value: data
};
return data;
},
getOptions: function (data) {
return data.collections;
},
//get count of data and position at which new data need to be inserted
getInfo: function (data) {
return {
size: data.total_count || 0,
from: data.pos,
parent: data.parent || 0,
config: data.config
};
},
child: "data",
parseDates: false
};
function ajax(url, params, call) {
//if parameters was provided - made fast call
if (arguments.length !== 0) {
return new ajax().get(url, params, call);
}
if (!this || !this.getXHR) return new ajax(); //allow to create new instance without direct new declaration
return this;
}
ajax.count = 0;
ajax.prototype = {
master: null,
//creates xmlHTTP object
getXHR: function () {
return new XMLHttpRequest();
},
stringify: function (obj) {
return stringify(obj);
},
/*
send data to the server
params - hash of properties which will be added to the url
call - callback, can be an object with success and error functions
*/
_send: function (url, params, call, mode) {
var master; //webix.ajax(url, callback) - can be called only by user
if (params && (isArray(params) || typeof (params.success || params.error || params) == "function")) {
master = call;
call = params;
params = null;
}
var defer = Deferred.defer();
var x = this.getXHR();
var headers = this._header || {};
if (!callEvent("onBeforeAjax", [mode, url, params, x, headers, null, defer])) {
return defer.reject(x);
} //add content-type to POST|PUT|DELETE
var json_mode = false;
if (mode !== "GET") {
var found = false;
for (var key in headers) {
if (key.toString().toLowerCase() == "content-type") {
found = true;
if (headers[key] == "application/json") json_mode = true;
}
}
if (!found && !(window.FormData && params instanceof window.FormData)) headers["Content-Type"] = "application/x-www-form-urlencoded";
} //add extra params to the url
if (_typeof(params) == "object" && !(window.FormData && params instanceof window.FormData)) {
if (json_mode) params = this.stringify(params);else {
var t = [];
for (var a in params) {
var value = params[a];
if (value === null || value === undefined) value = "";
if (_typeof(value) === "object") value = this.stringify(value);
t.push(a + "=" + encodeURIComponent(value)); // utf-8 escaping
}
params = t.join("&");
}
}
if (params && mode === "GET") {
url = url + (url.indexOf("?") != -1 ? "&" : "?") + params;
params = null;
}
x.open(mode, url, !this._sync);
var type = this._response;
if (type) x.responseType = type; //if header was provided - use it
for (var _key in headers) {
x.setRequestHeader(_key, headers[_key]);
} //async mode, define loading callback
var self = this;
this.master = this.master || master;
x.onreadystatechange = function () {
if (!x.readyState || x.readyState == 4) {
ajax.count++;
var is_error = x.status >= 400 || x.status === 0;
var text, data;
if (x.responseType == "blob" || x.responseType == "arraybuffer") {
text = "";
data = x.response;
} else {
text = x.responseText || "";
data = self._data(x);
}
if (is_error) {
callEvent("onAjaxError", [x]);
defer.reject(x);
if (call) ajax.$callback(self.master || window, call, text, data, x, is_error);
} else {
defer.resolve(data);
if (call) ajax.$callback(self.master || window, call, text, data, x, is_error);
}
}
};
if (this._timeout) x.timeout = this._timeout; //IE can use sync mode sometimes, fix it
if (!this._sync) setTimeout(function () {
x.send(params || null);
}, 0);else x.send(params || null);
if (this.master && !this._sync) {
defer.then(function (data) {
//anti-leak
self.master = null;
call = self = master = null;
return data;
});
}
return this._sync ? x : defer; //return XHR, which can be used in case of sync. mode
},
_data: function (x) {
return {
xml: function () {
try {
return xml.tagToObject(xml.toObject(x.responseText, this));
} catch (e) {
log(x.responseText);
log(e.toString());
assert(0, "Invalid xml data for parsing");
}
},
rawxml: function () {
if (!window.XPathResult) return xml.fromString(x.responseText);
return x.responseXML;
},
text: function () {
return x.responseText;
},
json: function () {
return json.toObject(x.responseText, false);
}
};
},
//GET request
get: function (url, params, call) {
return this._send(url, params, call, "GET");
},
//POST request
post: function (url, params, call) {
return this._send(url, params, call, "POST");
},
//PUT request
put: function (url, params, call) {
return this._send(url, params, call, "PUT");
},
//DELETE request
del: function (url, params, call) {
return this._send(url, params, call, "DELETE");
},
//PATCH request
patch: function (url, params, call) {
return this._send(url, params, call, "PATCH");
},
sync: function () {
this._sync = true;
return this;
},
timeout: function (num) {
this._timeout = num;
return this;
},
response: function (value) {
this._response = value;
return this;
},
headers: function (header) {
this._header = exports.extend(this._header || {}, header);
return this;
},
bind: function (master) {
this.master = master;
return this;
}
};
ajax.$callback = function (owner, call, text, data, x, is_error) {
if (owner.$destructed) return;
if (is_error) callEvent("onAjaxError", [x]);
if (call) {
var method = call.success || call;
if (is_error) method = call.error;
if (method && method.call) method.call(owner, text, data, x);
}
};
var proxy = {
$proxy: true,
load: function () {
var parts = this.source.split("@");
var ext = parts[0].split(".").pop();
return ajax().response("arraybuffer").get(parts[0]).then(function (res) {
var options = {
ext: ext,
dataurl: parts[1]
};
return {
data: res,
options: options
};
});
}
};
var proxy$1 = {
$proxy: true,
load: function () {},
save: function (v, u, d) {
delay(function () {
window.console.log("[DP] " + u.id + " -> " + u.operation, u.data);
var data = {
id: u.data.id,
newid: u.data.id,
status: u.data.operation
};
d.processResult(data, data);
});
}
};
var proxy$2 = {
$proxy: true,
load: function () {
return ajax(this.source);
},
save: function (view, update) {
return proxy$2._save_logic.call(this, update, ajax());
},
_save_logic: function (update, ajax$$1) {
var url = this.source;
var query = "";
var mark = url.indexOf("?");
if (mark !== -1) {
query = url.substr(mark);
url = url.substr(0, mark);
}
url += url.charAt(url.length - 1) == "/" ? "" : "/";
var mode = update.operation;
var data = update.data;
if (mode == "insert") delete data.id; //call rest URI
if (mode == "update") {
return ajax$$1.put(url + data.id + query, data);
} else if (mode == "delete") {
return ajax$$1.del(url + data.id + query, data);
} else {
return ajax$$1.post(url + query, data);
}
}
};
var proxy$3 = {
$proxy: true,
load: function () {
return ajax(this.source);
},
save: function (view, update) {
var xhr = ajax().headers({
"Content-Type": "application/json"
});
return proxy$2._save_logic.call(this, update, xhr);
}
};
var proxy$4 = {
$proxy: true,
load: function (view, params) {
params = exports.extend(params || {}, this.params || {}, true);
return ajax().post(this.source, params);
}
};
function unbox(data) {
if (!data || !_typeof(data) === "object" || Array.isArray(data)) return data;
var lkey = "";
var count = 0;
for (var key in data) {
count++;
if (count == 2) return data;
lkey = key;
}
return data[lkey];
}
var GraphQL = {
$proxy: true,
save: function (data) {
return this.load(data);
},
load: function (view) {
var params = {
query: this.source
};
if (arguments.length === 1) {
params.variables = view;
}
return ajax().headers({
"Content-type": "application/json"
}).post(this.url, params).then(function (data) {
return unbox(data.json().data);
});
}
};
function proxy$5(name, source, extra) {
assert(proxy$5[name], "Invalid proxy name: " + name);
var copy$$1 = copy(proxy$5[name]);
copy$$1.source = source;
if (extra) exports.extend(copy$$1, extra, true);
if (copy$$1.init) copy$$1.init();
return copy$$1;
}
proxy$5.$parse = function (value) {
if (typeof value == "string" && value.indexOf("->") != -1) {
var parts = value.split("->");
return proxy$5(parts[0], parts[1]);
}
return value;
};
proxy$5.binary = proxy;
proxy$5.debug = proxy$1;
proxy$5.json = proxy$3;
proxy$5.post = proxy$4;
proxy$5.rest = proxy$2;
proxy$5.GraphQL = GraphQL;
var jsarray = {
//parse jsarray string to jsarray object if necessary
toObject: function (data) {
if (typeof data == "string") return JSON.parse(data);
return data;
},
//get array of records
getRecords: function (data) {
if (data && data.data) data = data.data;
return data;
},
//get hash of properties for single record, in case of array they will have names as "data{index}"
getDetails: function (data) {
var result = {};
for (var i = 0; i < data.length; i++) {
result["data" + i] = data[i];
}
if (this.idColumn !== null) result.id = data[this.idColumn];
return result;
},
getOptions: function () {
return false;
},
//dyn loading is not supported by js-array data source
getInfo: function () {
return {
size: 0
};
},
idColumn: null
};
var csv = {
//incoming data always a string
toObject: function (data) {
return data;
},
//get array of records
getRecords: function (data) {
return data.split(this.row);
},
//get hash of properties for single record, data named as "data{index}"
getDetails: function (data) {
data = this.stringToArray(data);
var result = {};
for (var i = 0; i < data.length; i++) {
result["data" + i] = data[i];
}
if (this.idColumn !== null) result.id = data[this.idColumn];
return result;
},
getOptions: function () {
return false;
},
//dyn loading is not supported by csv data source
getInfo: function () {
return {
size: 0
};
},
//split string in array, takes string surrounding quotes in account
stringToArray: function (data) {
data = data.split(this.cell);
for (var i = 0; i < data.length; i++) {
data[i] = data[i].replace(/^[ \t\n\r]*("|)/g, "").replace(/("|)[ \t\n\r]*$/g, "");
}
return data;
},
idColumn: null,
row: "\n",
//default row separator
cell: "," //default cell separator
};
var html = {
/*
incoming data can be
- ID of parent container
- HTML text
*/
toObject: function (data) {
if (typeof data == "string") {
var t = null;
if (data.indexOf("<") == -1) //if no tags inside - probably its an ID
t = toNode(data);
if (!t) {
t = document.createElement("DIV");
t.innerHTML = data;
}
return t.firstChild;
}
return data;
},
//get array of records
getRecords: function (node) {
return node.getElementsByTagName(this.tag);
},
//get hash of properties for single record
getDetails: function (data) {
return xml.tagToObject(data);
},
getOptions: function () {
return false;
},
//dyn loading is not supported by HTML data source
getInfo: function () {
return {
size: 0
};
},
tag: "LI"
};
var env = {};
env.cdn = "//cdn.webix.com";
env.codebase = "";
env.zIndexBase = 100;
env.scrollSize = 17;
env.strict = !!window.webix_strict;
env.https = document.location.protocol === "https:";
var agent = navigator.userAgent;
env.isMac = agent.indexOf("Mac") != -1;
if (agent.indexOf("Mobile") != -1 || agent.indexOf("Windows Phone") != -1) env.mobile = true;
if (env.mobile || agent.indexOf("iPad") != -1 || agent.indexOf("Android") != -1) env.touch = true;
if (!env.touch && navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1) env.touch = true;
if (agent.indexOf("Opera") != -1) env.isOpera = true;else {
//very rough detection, but it is enough for current goals
env.isIE = !!document.all || agent.indexOf("Trident") !== -1;
if (env.isIE) {
var version = parseFloat(navigator.appVersion.split("MSIE")[1]);
if (version == 8) env.isIE8 = true;
}
env.isEdge = agent.indexOf("Edge") != -1;
env.isFF = agent.indexOf("Firefox") != -1;
env.isWebKit = agent.indexOf("KHTML") != -1;
env.isSafari = env.isWebKit && env.isMac && agent.indexOf("Chrome") == -1; //maximum height/width for HTML elements in pixels (rough), bigger values will be ignored by browser
if (env.isIE || env.isEdge || env.isFF) env.maxHTMLElementSize = 10000000;
if (env.isSafari) env.maxHTMLElementSize = 100000000;
}
if (agent.toLowerCase().indexOf("android") != -1) {
env.isAndroid = true;
if (agent.toLowerCase().indexOf("trident") != -1) {
env.isAndroid = false;
env.isIEMobile = true;
}
}
env.transform = false;
env.transition = false;
var found_index = -1;
var js_list = ["", "webkit", "Moz", "O", "ms"];
var css_list = ["", "-webkit-", "-Moz-", "-o-", "-ms-"];
var d = document.createElement("DIV");
for (var j = 0; j < js_list.length; j++) {
var name = js_list[j] ? js_list[j] + "Transform" : "transform";
if (typeof d.style[name] != "undefined") {
found_index = j;
break;
}
}
if (found_index > -1) {
env.cssPrefix = css_list[found_index];
var jp = env.jsPrefix = js_list[found_index];
env.transform = jp ? jp + "Transform" : "transform";
env.transition = jp ? jp + "Transition" : "transition";
env.transitionDuration = jp ? jp + "TransitionDuration" : "transitionDuration";
d.style[env.transform] = "translate3d(0,0,0)";
env.translate = d.style[env.transform] ? "translate3d" : "translate";
env.transitionEnd = env.cssPrefix == "-Moz-" ? "transitionend" : jp ? jp + "TransitionEnd" : "transitionend";
}
env.pointerevents = !env.isIE || new RegExp("Trident/.*rv:11").exec(agent) !== null; //touch events that can be prevented
env.passiveEventListeners = false;
try {
var opts = Object.defineProperty({}, "passive", {
get: function () {
// eslint-disable-line
env.passiveEventListeners = true;
}
});
window.addEventListener("testPassive", null, opts);
window.removeEventListener("testPassive", null, opts);
} catch (e) {} // eslint-disable-line
env.svg = function () {
return document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1");
}();
env.svganimation = function () {
return document.implementation.hasFeature("https://www.w3.org/TR/SVG11/feature#SVG-animation", "1.1");
}();
var _native_on_selectstart = 0;
var _style_element = {};
var _style_cache = {};
function denySelect() {
if (!_native_on_selectstart) _native_on_selectstart = document.onselectstart;
document.onselectstart = stopEvent;
}
function allowSelect() {
if (_native_on_selectstart !== 0) {
document.onselectstart = _native_on_selectstart || null;
}
_native_on_selectstart = 0;
}
function index(node) {
var k = 0; //must be =, it is not a comparation!
while (node = node.previousSibling) {
k++;
}
return k;
}
function createCss(rule, sufix) {
var text = "";
sufix = sufix || "";
for (var key in rule) {
text += key + ":" + rule[key] + ";";
}
var name = _style_cache[text + sufix];
if (!name) {
name = "s" + uid();
addStyle("." + name + (sufix || "") + "{" + text + "}");
_style_cache[text + sufix] = name;
}
return name;
}
function addStyle(rule, group) {
var style = group ? _style_element[group] : _style_element["default"];
if (!style) {
style = document.createElement("style");
style.setAttribute("type", "text/css");
style.setAttribute("media", "screen,print");
document.getElementsByTagName("head")[0].appendChild(style);
if (group) _style_element[group] = style;else _style_element["default"] = style;
}
/*IE8*/
if (style.styleSheet) style.styleSheet.cssText += rule;else style.appendChild(document.createTextNode(rule));
}
function removeStyle(group) {
var box = _style_element[group || "default"];
if (box) box.innerHTML = "";
}
function create(name, attrs, html) {
attrs = attrs || {};
var node = document.createElement(name);
for (var attr_name in attrs) {
node.setAttribute(attr_name, attrs[attr_name]);
}
if (attrs.style) node.style.cssText = attrs.style;
if (attrs["class"]) node.className = attrs["class"];
if (html) node.innerHTML = html;
return node;
} //return node value, different logic for different html elements
function getValue(node) {
node = toNode(node);
if (!node) return "";
return isUndefined(node.value) ? node.innerHTML : node.value;
} //remove html node, can process an array of nodes at once
function remove(node) {
if (node instanceof Array) for (var i = 0; i < node.length; i++) {
remove(node[i]);
} else if (node && node.parentNode) node.parentNode.removeChild(node);
} //insert new node before sibling, or at the end if sibling doesn't exist
function insertBefore(node, before, rescue) {
if (!node) return;
if (before && before.parentNode) before.parentNode.insertBefore(node, before);else rescue.appendChild(node);
} //return custom ID from html element
//will check all parents starting from event's target
function locate(e, id) {
var trg;
if (e.tagName) trg = e;else {
e = e || event;
trg = e.target;
}
while (trg) {
if (trg.getAttribute) {
//text nodes has not getAttribute
var test = trg.getAttribute(id);
if (test) return test;
}
trg = trg.parentNode;
}
return null;
} //returns position of html element on the page
function offset(elem) {
if (elem.getBoundingClientRect) {
//HTML5 method
var box = elem.getBoundingClientRect();
var body = document.body;
var docElem = document.documentElement;
var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
var clientTop = docElem.clientTop || body.clientTop || 0;
var clientLeft = docElem.clientLeft || body.clientLeft || 0;
var top = box.top + scrollTop - clientTop;
var left = box.left + scrollLeft - clientLeft;
return {
y: Math.round(top),
x: Math.round(left),
width: elem.offsetWidth,
height: elem.offsetHeight
};
} else {
//fallback to naive approach
var _top = 0,
_left = 0;
while (elem) {
_top = _top + parseInt(elem.offsetTop, 10);
_left = _left + parseInt(elem.offsetLeft, 10);
elem = elem.offsetParent;
}
return {
y: _top,
x: _left,
width: elem.offsetHeight,
height: elem.offsetWidth
};
}
} //returns relative position of event
function posRelative(ev) {
ev = ev || event;
if (!isUndefined(ev.offsetX)) return {
x: ev.offsetX,
y: ev.offsetY
}; //ie, webkit
else return {
x: ev.layerX,
y: ev.layerY
}; //firefox
} //returns position of event
function pos(ev) {
ev = ev || event;
if (ev.touches && ev.touches[0]) ev = ev.touches[0];
if (ev.pageX || ev.pageY) //FF, KHTML
return {
x: ev.pageX,
y: ev.pageY
}; //IE
var d = env.isIE && document.compatMode != "BackCompat" ? document.documentElement : document.body;
return {
x: ev.clientX + d.scrollLeft - d.clientLeft,
y: ev.clientY + d.scrollTop - d.clientTop
};
} //prevent event action
function preventEvent(e) {
if (e && e.preventDefault) e.preventDefault();
if (e) e.returnValue = false;
return stopEvent(e);
} //stop event bubbling
function stopEvent(e) {
e = e || event;
if (e.stopPropagation) e.stopPropagation();
e.cancelBubble = true;
return false;
}
function triggerEvent(node, type, name) {
if (document.createEventObject) {
var ev = document.createEventObject();
if (node.fireEvent) node.fireEvent("on" + name, ev);
} else {
var _ev = document.createEvent(type);
_ev.initEvent(name, true, true);
if (node.dispatchEvent) node.dispatchEvent(_ev);
}
} //add css class to the node
function addCss(node, name, check) {
if (!check || node.className.indexOf(name) === -1) node.className += " " + name;
} //remove css class from the node
function removeCss(node, name) {
node.className = node.className.replace(RegExp(" " + name, "g"), "");
}
function getTextSize(text, css, basewidth) {
var d = create("DIV", {
"class": "webix_view webix_measure_size " + (css || "")
}, "");
d.style.cssText = "height:auto;visibility:hidden; position:absolute; top:0px; left:0px; overflow:hidden;" + (basewidth ? "width:" + basewidth + "px;" : "width:auto;white-space:nowrap;");
document.body.appendChild(d);
var all = _typeof(text) !== "object" ? [text] : text;
var width = 0;
var height = 0;
for (var i = 0; i < all.length; i++) {
d.innerHTML = all[i]; //we need to add 1 to offsetWidth/Height because these methods return value as an integer
//we can use ie9+ d.getBoundingClientRect().width
width = Math.max(width, d.offsetWidth + 1);
height = Math.max(height, d.offsetHeight + 1);
}
remove(d);
return {
width: width,
height: height
};
}
function download(data, filename) {
var objUrl = false;
if (_typeof(data) == "object") {
//blob
if (window.navigator.msSaveBlob) return window.navigator.msSaveBlob(data, filename);else {
data = window.URL.createObjectURL(data);
objUrl = true;
}
} //data url or blob url
var link = document.createElement("a");
link.href = data;
link.download = filename;
document.body.appendChild(link);
link.click();
delay(function () {
if (objUrl) window.URL.revokeObjectURL(data);
document.body.removeChild(link);
link.remove();
});
}
function _getClassName(node) {
if (!node) return "";
var className = node.className || "";
if (className.baseVal) //'className' exist but not a string - IE svg element in DOM
className = className.baseVal;
if (!className.indexOf) className = "";
return className;
}
function setSelectionRange(node, start, end) {
start = start || 0;
end = end || start;
node.focus();
if (node.setSelectionRange) node.setSelectionRange(start, end);else {
//ie8
var textRange = node.createTextRange();
textRange.collapse(true);
textRange.moveEnd("character", end);
textRange.moveStart("character", start);
textRange.select();
}
}
function getSelectionRange(node) {
if ("selectionStart" in node) return {
start: node.selectionStart || 0,
end: node.selectionEnd || 0
};else {
//ie8
node.focus();
var selection = document.selection.createRange();
var bookmark = selection.getBookmark();
var textRange = node.createTextRange();
textRange.moveToBookmark(bookmark);
var length = textRange.text.length;
textRange.collapse(true);
textRange.moveStart("character", -node.value.length);
var start = textRange.text.length;
return {
start: start,
end: start + length
};
}
}
function addMeta(name, value) {
document.getElementsByTagName("head").item(0).appendChild(create("meta", {
name: name,
content: value
}));
}
var htmltable = {
//convert json string to json object if necessary
toObject: function (data) {
data = toNode(data);
assert(data, "table is not found");
assert(data.tagName.toLowerCase() === "table", "Incorrect table object");
var tr = data.rows;
remove(data);
return tr;
},
//get array of records
getRecords: function (data) {
var new_data = []; //skip header rows if necessary
var i = data[0] && data[0]._webix_skip ? 1 : 0;
for (; i < data.length; i++) {
new_data.push(data[i]);
}
return new_data;
},
//get hash of properties for single record
getDetails: function (data) {
var td = data.getElementsByTagName("td");
data = {}; //get hash of properties for single record, data named as "data{index}"
for (var i = 0; i < td.length; i++) {
data["data" + i] = td[i].innerHTML;
}
return data;
},
//get count of data and position at which new data need to be inserted
getInfo: function () {
// dyn loading is not supported for htmltable
return {
size: 0
};
},
getOptions: function () {},
/*! gets header from first table row
**/
getConfig: function (data) {
var columns = [];
var td = data[0].getElementsByTagName("th");
if (td.length) data[0]._webix_skip = true;
for (var i = 0; i < td.length; i++) {
var col = {
id: "data" + i,
header: this._de_json(td[i].innerHTML)
};
var attrs = this._get_attrs(td[i]);
col = exports.extend(col, attrs);
columns.push(col);
}
return columns;
},
_de_json: function (str) {
var pos$$1 = str.indexOf("json://");
if (pos$$1 != -1) str = JSON.parse(str.substr(pos$$1 + 7));
return str;
},
/*! gets hash of html-element attributes
**/
_get_attrs: function (el) {
var attr = el.attributes;
var hash = {};
for (var i = 0; i < attr.length; i++) {
hash[attr[i].nodeName] = this._de_json(attr[i].nodeValue);
}
hash.width = parseInt(hash.width, 10);
return hash;
}
};
var _modules = {}; //hash of already loaded modules
//loads module from external js file
function require(module, callback, master) {
var promise = Deferred.defer();
if (callback && callback !== true) promise = promise.then(function () {
callback.call(master || this);
});
if (require.disabled) {
promise.resolve();
return promise;
} //multiple files required at once
if (typeof module != "string") {
var count = module.length || 0;
if (!count) {
// { file: true, other: true }
for (var file in module) {
count++;
} // eslint-disable-line
var callback2 = function () {
count--;
if (count === 0) promise.resolve();
};
for (var _file in module) {
require(_file).then(callback2, function () {
return promise.reject();
});
}
} else {
// [ file, other ]
var _callback = function () {
if (count) {
count--;
require(module[module.length - count - 1]).then(_callback, function () {
return promise.reject();
});
} else {
promise.resolve();
}
};
_callback();
}
return promise;
}
if (_modules[module] !== true) {
var fullpath = module;
if (callback === true) {
//sync mode
exec(ajax().sync().get(fullpath).responseText);
_modules[module] = true;
return promise.resolve();
}
if (!_modules[module]) //first call
_modules[module] = [promise];else {
_modules[module].push(promise);
return promise;
}
var onerror = function () {
var calls = _modules[module];
_modules[module] = false;
for (var i = 0; i < calls.length; i++) {
calls[i].reject();
}
};
var onload = function () {
var calls = _modules[module];
_modules[module] = true;
for (var i = 0; i < calls.length; i++) {
calls[i].resolve();
}
}; //css, async, no waiting
var parts = module.split("?");
if (parts[0].substr(parts[0].length - 4) == ".css") {
var link = create("LINK", {
type: "text/css",
rel: "stylesheet",
href: fullpath
});
link.onload = onload;
link.onerror = onerror;
document.getElementsByTagName("head")[0].appendChild(link);
} else {
var newScript = document.createElement("script");
newScript.onload = onload;
newScript.onerror = onerror;
document.getElementsByTagName("head")[0].appendChild(newScript);
newScript.src = fullpath;
}
} else promise.resolve();
return promise;
}
var excel = exports.extend({
toObject: function (data) {
if (!data.excel) {
var opts = data.options || {};
if (opts.dataurl) exports.extend(opts, this._urlToOptions(opts.dataurl));
data = data.data || data;
var promise = Deferred.defer();
if (data.name) {
//file
opts.ext = data.name.split(".").pop();
var reader = new FileReader();
reader.onload = bind(function (e) {
promise.resolve(this.parseData(e.target.result, opts));
}, this);
reader.readAsArrayBuffer(data);
} else //arraybuffer
promise.resolve(this.parseData(data, opts));
return promise;
} //plain jsarray or hash
return data;
},
parseData: function (data, options) {
data = new Uint8Array(data);
var arr = [];
for (var i = 0; i != data.length; ++i) {
arr[i] = String.fromCharCode(data[i]);
}
var ext = (options.ext || options).toLowerCase();
if (ext != "xls") ext = "xlsx";
return require(env.cdn + "/extras/xlsx.core.styles.min.js").then(bind(function () {
/* global XLS, XLSX */
var wb = ext == "xls" ? XLS.read(arr.join(""), {
type: "binary",
cellStyles: true,
cellDates: true
}) : XLSX.read(arr.join(""), {
type: "binary",
cellStyles: true,
cellDates: true
});
var res = {
sheets: wb.Sheets,
names: wb.SheetNames,
options: options,
ranges: wb.Workbook ? wb.Workbook.Names || [] : []
};
return exports.extend(this.getSheet(res, options), res);
}, this));
},
getSheet: function (data, options) {
var name = options.name || data.names[0];
data = this.sheetToArray(data.sheets[name], options);
if (options.rows && options.rows.length) data.data = data.data.splice(options.rows[0], Math.min(options.rows[1], data.data.length) - options.rows[0]);
return data;
},
sheetToArray: function (sheet, options) {
var all = [];
var spans = [];
var styles = [];
var sizes = [];
var types = [];
var hidden = [];
var cellTypes = {
n: "number",
d: "date",
s: "string",
b: "boolean"
};
if (sheet && sheet["!ref"]) {
var range = XLS.utils.decode_range(sheet["!ref"]),
row,
col,
cellCoord,
cell,
xCorrection = range.s.c,
yCorrection = range.s.r + (options.rows ? options.rows[0] : 0);
for (row = range.s.r; row <= range.e.r; row++) {
var nrow = [];
for (col = range.s.c; col <= range.e.c; col++) {
cellCoord = XLS.utils.encode_cell({
r: row,
c: col
});
cell = sheet[cellCoord];
if (!cell) nrow.push("");else {
var ncell = "";
if (options.math && cell.f) // get formula
ncell = cell.f.charAt(0) == "=" ? cell.f : "=" + cell.f;else if (cell.t == "d" && isDate(cell.v)) ncell = i18n.dateFormatStr(cell.v);else ncell = cell.v;
nrow.push(ncell);
if (cell.s) styles.push([row - yCorrection, col - xCorrection, cell.s]);
if (cell.t) types.push([row - yCorrection, col - xCorrection, cellTypes[cell.t]]);
}
}
all.push(nrow);
}
if (sheet["!merges"]) {
var merges = sheet["!merges"];
for (var i = 0; i < merges.length; i++) {
var s = merges[i].s;
var e = merges[i].e;
if (!options.rows || s.r - yCorrection >= 0 && e.r - yCorrection <= options.rows[1]) spans.push([s.r - yCorrection, s.c - xCorrection, e.c - s.c + 1, e.r - s.r + 1]);
}
}
if (sheet["!cols"]) {
var widths = sheet["!cols"];
for (var _i = 0; _i < widths.length; _i++) {
var item = widths[_i];
if (item) {
var index = _i - xCorrection;
sizes.push(["column", index, Math.round(item.wch / (8.43 / 70))]); //mode, colind, value
if (item.hidden) hidden.push(["column", index]);
}
}
}
if (sheet["!rows"]) {
var heights = sheet["!rows"];
for (var _i2 = 0; _i2 < heights.length; _i2++) {
var _item = heights[_i2];
if (_item) {
var _index = _i2 - yCorrection;
sizes.push(["row", _index, _item.hpx]); //mode ("row", "column"), rowind, value
if (_item.hidden) hidden.push(["row", _index]);
}
}
}
}
return {
data: all,
spans: spans,
styles: styles,
sizes: sizes,
types: types,
hidden: hidden,
excel: true
};
},
_urlToOptions: function (details) {
var parts = details.split("[");
var options = {};
options.name = parts[0];
if (parts[1]) {
var rows = parts[1].split(/[^0-9]+/g);
rows[0] = rows[0] * 1 || 0;
rows[1] = rows[1] * 1 || 9999999;
options.rows = rows;
}
return options;
}
}, jsarray);
var DataDriver = {
json: json,
jsarray: jsarray,
xml: xml,
csv: csv,
html: html,
htmltable: htmltable,
excel: excel
};
var silentErrorMarker = {};
var AtomDataLoader = {
$init: function (config) {
//prepare data store
this.data = {};
this.waitData = Deferred.defer();
if (config) this._settings.datatype = config.datatype || "json";
this.$ready.push(this._load_when_ready);
},
_load_when_ready: function () {
this._ready_for_data = true;
if (this._settings.url) this.url_setter(this._settings.url);
if (this._settings.data) this.data_setter(this._settings.data);
},
url_setter: function (value) {
value = proxy$5.$parse(value);
if (!this._ready_for_data) return value;
this.load(value, this._settings.datatype);
return value;
},
data_setter: function (value) {
if (!this._ready_for_data) return value;
this.parse(value, this._settings.datatype);
return true;
},
//loads data from external URL
load: function (url, call, details, clear) {
var _this = this;
var type;
if (typeof call == "string") {
//second parameter can be a loading type or callback
//we are not using setDriver as data may be a non-datastore here
type = call;
call = arguments[2];
}
var d = this._fetch(url, type, details || null);
if (d && d.then) return d.then(function (data) {
_this._onLoad(data, clear);
if (call) ajax.$callback(_this, call, "", data, -1);
return data;
}, function (x) {
return _this._onLoadError(x);
});
},
_fetch: function (url, type, details) {
var _this2 = this;
var result;
if (type || !this.data.driver) this.data.driver = DataDriver[type || "json"];
if (!this.callEvent("onBeforeLoad", [])) return Deferred.reject(); //proxy
url = proxy$5.$parse(url);
if (url.$proxy && url.load) {
result = url.load(this, details);
} //promize
else if (typeof url === "function") {
result = url.call(this, details);
} //normal url
else {
result = ajax().bind(this).get(url);
} //we wrap plain data in promise to keep the same processing for it
if (result && !result.then) {
result = Deferred.resolve(result);
}
var gen = this._data_generation;
if (result && result.then) {
return result.then(function (data) {
// component destroyed, or clearAll was issued
if (_this2.$destructed || gen && _this2._data_generation !== gen) // by returning rejection we are preventing the further executing chain
// if user have used list.load(data).then(do_something)
// the do_something will not be executed
// the error handler may be triggered though
return Deferred.reject(silentErrorMarker);
return data;
});
}
return result;
},
//loads data from object
parse: function (data, type, clear) {
if (data && typeof data.then == "function") {
var generation = this._data_generation; // component destroyed, or clearAll was issued
return data.then(bind(function (data) {
if (this.$destructed || generation && this._data_generation !== generation) return Deferred.reject();
this.parse(data, type, clear);
}, this));
} //loading data from other component
if (data && data.sync && this.sync) this._syncData(data);else if (!this.callEvent("onBeforeLoad", [])) return Deferred.reject();else {
if (type || !this.data.driver) this.data.driver = DataDriver[type || "json"];
this._onLoad(data, clear);
}
return Deferred.resolve();
},
_syncData: function (data) {
if (this.data && this.data.attachEvent) this.data.attachEvent("onSyncApply", bind(function () {
if (this._call_onready) this._call_onready();
}, this));
this.sync(data);
},
_parse: function (data) {
var parsed,
record,
driver = this.data.driver;
record = driver.getRecords(data)[0];
parsed = record ? driver.getDetails(record) : {};
if (this.setValues) this.setValues(parsed, false, "auto");else this.data = parsed;
},
_onLoadContinue: function (data, clear) {
if (data) {
if (!this.$onLoad || !this.$onLoad(data, this.data.driver, clear)) {
if (this.data && this.data._parse) {
if (clear) this.data.clearAll(true);
this.data._parse(data); //datastore
} else {
if (clear) this.clearAll(true);
this._parse(data);
}
}
} else this._onLoadError(data); //data loaded, view rendered, call onready handler
if (this._call_onready) this._call_onready();
this.callEvent("onAfterLoad", []);
this.waitData.resolve();
},
//default after loading callback
_onLoad: function (data, clear) {
var _this3 = this;
// webix loading object or uploaded file structure
if (data && typeof data.text === "function" && !data.name) {
data = data.text();
}
data = this.data.driver.toObject(data);
if (data && data.then) data.then(function (data) {
return _this3._onLoadContinue(data, clear);
});else this._onLoadContinue(data, clear);
},
_onLoadError: function (xhttp) {
if (xhttp !== silentErrorMarker) {
//ignore error for dead components
if (!this.$destructed) {
this.callEvent("onAfterLoad", []);
this.callEvent("onLoadError", arguments);
}
callEvent("onLoadError", [xhttp, this]);
}
return Deferred.reject(xhttp);
},
_check_data_feed: function (data) {
if (!this._settings.dataFeed || this._ignore_feed || !data) return true;
var url = this._settings.dataFeed;
if (typeof url == "function") return url.call(this, data.id || data, data);
url = url + (url.indexOf("?") == -1 ? "?" : "&") + "action=get&id=" + encodeURIComponent(data.id || data);
if (!this.callEvent("onBeforeLoad", [])) return false;
ajax(url, function (text, xml, loader) {
this._ignore_feed = true;
var driver = DataDriver.json;
var data = driver.toObject(text, xml);
if (data) this.setValues(driver.getDetails(driver.getRecords(data)[0]), false, "auto");else this._onLoadError(loader);
this._ignore_feed = false;
this.callEvent("onAfterLoad", []);
}, this);
return false;
}
};
var CodeParser = {
//converts a complex object into an object with primitives properties
collapseNames: function (base, prefix, data, filter) {
data = data || {};
prefix = prefix || "";
filter = filter || function () {
return true;
};
if (!base || _typeof(base) != "object") return null;
for (var prop in base) {
var value = base[prop];
var name = prefix + prop;
if (value && _typeof(value) == "object" && !isDate(value) && !isArray(value) && filter(name)) {
CodeParser.collapseNames(value, name + ".", data, filter);
} else {
data[name] = value;
}
}
return data;
},
//converts an object with primitive properties into an object with complex properties
expandNames: function (base) {
var data = {},
i,
lastIndex,
name,
obj,
prop;
for (prop in base) {
name = prop.split(".");
lastIndex = name.length - 1;
obj = data;
for (i = 0; i < lastIndex; i++) {
if (!obj[name[i]]) obj[name[i]] = {};
obj = obj[name[i]];
}
obj[name[lastIndex]] = base[prop];
}
return data;
}
};
/*
Template - handles html templates
*/
var _cache = {};
var _csp_cache = {};
var newlines = new RegExp("(\\r\\n|\\n)", "g");
var quotes = new RegExp("(\\\")", "g");
var slashes = new RegExp("(\\\\)", "g");
var escape$1 = {
"&": "&",
"<": "<",
">": ">",
"\"": """,
"'": "'",
"`": "`"
};
var badChars = /[&<>"'`]/g;
var escapeChar = function (chr) {
return escape$1[chr] || "&";
};
function template(str) {
if (typeof str == "function") return str;
if (_cache[str]) return _cache[str];
str = (str || "").toString();
if (str.indexOf("->") != -1) {
var teststr = str.split("->");
switch (teststr[0]) {
case "html":
//load from some container on the page
str = getValue(teststr[1]);
break;
case "http":
//load from external file
str = new ajax().sync().get(teststr[1], {
uid: uid()
}).responseText;
break;
default:
//do nothing, will use template as is
break;
}
} //supported idioms
// {obj.attr} => named attribute or value of sub-tag in case of xml
str = (str || "").toString(); // Content Security Policy enabled
if (env.strict) {
if (!_csp_cache[str]) {
_csp_cache[str] = []; // get an array of objects (not sorted by position)
var temp_res = [];
str.replace(/\{obj\.([^}?]+)\?([^:]*):([^}]*)\}/g, function (search, s1, s2, s3, pos$$1) {
temp_res.push({
pos: pos$$1,
str: search,
fn: function (obj) {
return obj[s1] ? s2 : s3;
}
});
});
str.replace(/\{common\.([^}(]*)\}/g, function (search, s, pos$$1) {
temp_res.push({
pos: pos$$1,
str: search,
fn: function (_, common) {
return common[s] || "";
}
});
});
str.replace(/\{common\.([^}(]*)\(\)\}/g, function (search, s, pos$$1) {
temp_res.push({
pos: pos$$1,
str: search,
fn: function (obj, common) {
return common[s] ? common[s].apply(this, arguments) : "";
}
});
});
str.replace(/\{obj\.([^:}]*)\}/g, function (search, s, pos$$1) {
temp_res.push({
pos: pos$$1,
str: search,
fn: function (obj) {
return obj[s];
}
});
});
str.replace("{obj}", function (search, pos$$1) {
temp_res.push({
pos: pos$$1,
str: search,
fn: function (obj) {
return obj;
}
});
});
str.replace(/#([^#'";, ]+)#/gi, function (search, s, pos$$1) {
if (s.charAt(0) == "!") {
s = s.substr(1);
temp_res.push({
pos: pos$$1,
str: search,
fn: function (obj) {
if (s.indexOf(".") != -1) obj = CodeParser.collapseNames(obj); // apply complex properties
return template.escape(obj[s]);
}
});
} else {
temp_res.push({
pos: pos$$1,
str: search,
fn: function (obj) {
if (s.indexOf(".") != -1) obj = CodeParser.collapseNames(obj); // apply complex properties
return obj[s];
}
});
}
}); // sort template parts by position
temp_res.sort(function (a, b) {
return a.pos > b.pos ? 1 : -1;
}); // create an array of functions that return parts of html string
if (temp_res.length) {
var lastPos = 0;
var addStr = function (str, n0, n1) {
_csp_cache[str].push(function () {
return str.slice(n0, n1);
});
};
for (var i = 0; i < temp_res.length; i++) {
var pos$$1 = temp_res[i].pos;
addStr(str, lastPos, pos$$1);
_csp_cache[str].push(temp_res[i].fn);
lastPos = pos$$1 + temp_res[i].str.length;
}
addStr(str, lastPos, str.length);
} else _csp_cache[str].push(function () {
return str;
});
}
return function () {
var s = "";
for (var i = 0; i < _csp_cache[str].length; i++) {
s += _csp_cache[str][i].apply(this, arguments);
}
return s;
};
}
var helpers = false;
str = str.replace(slashes, "\\\\");
str = str.replace(newlines, "\\n");
str = str.replace(quotes, "\\\"");
str = str.replace(/\{obj\.([^}?]+)\?([^:]*):([^}]*)\}/g, "\"+(obj.$1?\"$2\":\"$3\")+\"");
str = str.replace(/\{common\.([^}(]*)\}/g, "\"+(common.$1||'')+\"");
str = str.replace(/\{common\.([^}(]*)\(\)\}/g, "\"+(common.$1?common.$1.apply(this, arguments):\"\")+\"");
str = str.replace(/\{obj\.([^}]*)\}/g, "\"+(obj.$1)+\"");
str = str.replace("{obj}", "\"+obj+\"");
str = str.replace(/#([^#'";, ]+)#/gi, function (str, key) {
if (key.charAt(0) == "!") {
helpers = true;
return "\"+template.escape(obj." + key.substr(1) + ")+\"";
} else return "\"+(obj." + key + ")+\"";
});
try {
if (helpers) {
var temp = Function("obj", "common", "marks", "value", "template", "return \"" + str + "\";");
_cache[str] = function (a, b, c, d) {
return temp(a, b, c, d, template);
};
} else {
_cache[str] = Function("obj", "common", "return \"" + str + "\";");
}
} catch (e) {
assert(0, "Invalid template:" + str);
}
return _cache[str];
}
template.escape = function (str) {
if (str === undefined || str === null) return "";
return (str.toString() || "").replace(badChars, escapeChar);
};
template.empty = function () {
return "";
};
var AtomRender = {
//convert item to the HTML text
_toHTML: function (obj) {
if (obj.$empty) return "";
return this._settings.template(obj, this);
},
//render self, by templating data object
render: function () {
var cfg = this._settings;
if (this.isVisible(cfg.id)) {
if (!this.callEvent || this.callEvent("onBeforeRender", [this.data])) {
if (this.data && !cfg.content) {
//it is critical to have this as two commands
//its prevent destruction race in Chrome
this._dataobj.innerHTML = "";
this._dataobj.innerHTML = this._toHTML(this.data);
}
if (this.callEvent) this.callEvent("onAfterRender", []);
}
return true;
}
return false;
},
sync: function (source) {
this._backbone_sync = false;
if (source.name != "DataStore") {
if (source.data && source.data.name == "DataStore") {
source = source.data;
} else {
this._backbone_sync = true;
}
}
if (this._backbone_sync) source.bind("change", bind(function (data) {
if (data.id == this.data.id) {
this.data = data.attributes;
this.refresh();
}
}, this));else source.attachEvent("onStoreUpdated", bind(function (id) {
if (!id || id == this.data.id) {
this.data = source.pull[id];
this.refresh();
}
}, this));
},
template_setter: template
};
var AutoScroll = {
_auto_scroll: function (pos$$1) {
var yScroll, xScroll;
var mode = this._settings.dragscroll;
if (typeof mode !== "string") mode = this._settings.layout || "xy";
xScroll = mode.indexOf("x") !== -1;
yScroll = mode.indexOf("y") !== -1;
var data = this._body || this.$view;
var box = offset(data);
var sense = Math.max((this._settings.rowHeight || (this.type && !isNaN(parseFloat(this.type.height)) ? this.type.height : 0)) + 5, 40); //dnd auto-scroll sensivity
var reset = false;
if (yScroll && this._auto_y_scroll(pos$$1, box, sense)) reset = true;
if (xScroll && this._auto_x_scroll(pos$$1, box, sense)) reset = true;
if (reset) this._auto_scroll_delay = delay(this._auto_scroll, this, [pos$$1], 100);
},
_auto_scroll_column: function (pos$$1) {
var mode = this._settings.dragscroll;
if (typeof mode === "string" && mode.indexOf("x") === -1) return;
var data = this._header || this.$view;
var box = offset(data);
var sense = Math.max(this._settings.headerRowHeight || 0, 40);
if (this._auto_x_scroll(pos$$1, box, sense)) this._auto_scroll_delay = delay(this._auto_scroll_column, this, [pos$$1], 100);
},
_auto_y_scroll: function (pos$$1, box, sense) {
var top = box.y;
var bottom = top + box.height;
var scroll = this.getScrollState();
var config = this._settings;
if (config.topSplit) {
var topSplitPos = this._cellPosition(this.getIdByIndex(config.topSplit - 1), this.columnId(0));
top += topSplitPos.top + topSplitPos.height;
}
if (pos$$1.y < top + sense) {
return this._auto_scrollTo(scroll.x, scroll.y - sense * 2, pos$$1, "y");
} else if (pos$$1.y > bottom - sense) {
return this._auto_scrollTo(scroll.x, scroll.y + sense * 2, pos$$1, "y");
}
return false;
},
_auto_x_scroll: function (pos$$1, box, sense) {
var left = box.x;
var right = left + box.width;
var scroll = this.getScrollState();
if (pos$$1.x < left + sense) {
return this._auto_scrollTo(scroll.x - sense * 2, scroll.y, pos$$1, "x");
} else if (pos$$1.x > right - sense) {
return this._auto_scrollTo(scroll.x + sense * 2, scroll.y, pos$$1, "x");
}
return false;
},
_auto_scrollTo: function (x, y, pos$$1, mode) {
if (this.callEvent("onBeforeAutoScroll", [pos$$1])) {
this.scrollTo(x, y);
this.callEvent("onAfterAutoScroll", []);
var scroll = this.getScrollState();
return Math.abs((mode === "x" ? x : y) - scroll[mode]) < 1;
}
return false;
}
};
var _events = {};
function _events_final_destructor() {
//detach all known DOM events
for (var a in _events) {
eventRemove(a);
}
} //private version of API, do not register ID for event detaching
function _event(a, b, c, d) {
d = d || {};
d.inner = true;
event$1(a, b, c, d);
} //attach event to the DOM element
function event$1(node, event, handler, context) {
context = context || {};
node = toNode(node);
assert(node, "Invalid node as target for webix.event");
var id = context.id || uid();
if (context.bind) handler = bind(handler, context.bind);
var info = [node, event, handler, context.capture];
if (!context.inner) _events[id] = info; //store event info, for detaching
var capture = !!context.capture;
if (!isUndefined(context.passive) && env.passiveEventListeners) //blockable touch events
capture = {
passive: context.passive,
capture: capture
}; //use IE's of FF's way of event's attaching
if (node.addEventListener) node.addEventListener(event, handler, capture);else if (node.attachEvent) node.attachEvent("on" + event, info[2] = function () {
return handler.apply(node, arguments); //IE8 fix
});
return id; //return id of newly created event, can be used in eventRemove
} //remove previously attached event
function eventRemove(id) {
if (!id) return;
assert(_events[id], "Removing non-existing event");
var ev = _events[id]; //browser specific event removing
if (ev[0].removeEventListener) ev[0].removeEventListener(ev[1], ev[2], !!ev[3]);else if (ev[0].detachEvent) ev[0].detachEvent("on" + ev[1], ev[2]);
delete _events[id]; //delete all traces
}
/*
adds new template-type
obj - object to which template will be added
data - properties of template
*/
function type(obj, data) {
if (obj.$protoWait) {
if (!obj._webix_type_wait) obj._webix_type_wait = [];
obj._webix_type_wait.push(data);
return;
} //auto switch to prototype, if name of class was provided
if (typeof obj == "function") obj = obj.prototype;
if (!obj.types) {
obj.types = {
"default": obj.type
};
obj.type.name = "default";
}
var name = data.name;
var type = obj.type;
if (name) type = obj.types[name] = clone(data.baseType ? obj.types[data.baseType] : obj.type);
for (var key in data) {
if (key.indexOf("template") === 0) type[key] = template(data[key]);else type[key] = data[key];
}
return name;
}
var state = {
top_views: [],
_global_scope: null,
_global_collection: null,
_child_sizing_active: null,
_responsive_exception: null,
_responsive_tinkery: null,
_freeze_resize: null,
_parent_cell: null,
_focus_time: null,
_ui_creation: 0,
_edit_open_time: null,
_final_destruction: null,
_events: [],
destructors: [],
_noselect_element: null,
_modality: [],
_popups: _to_array(),
_wait_animate: null
};
var views = {};
function ui(config, parent, id) {
var res;
state._ui_creation++; // save old value of global scope
var temp = state._global_scope; // set global scope to the scope of new UI or to previous value
// as result inner webix.ui calls will have access the scope of master view
// mainly necessary for suggests
state._global_scope = config.$scope || temp;
try {
res = _ui_creator(config, parent, id);
} finally {
state._ui_creation--; // restore global scope
state._global_scope = temp;
}
return res;
}
ui.views = views;
function _ui_creator(config, parent, id) {
var multiset = isArray(config);
var node = toNode(config.container || parent || document.body); // solve problem with non-unique ids
if (node._settings) id = _correctId(node, multiset, id);
var top_node;
var moving = false;
var body_child = node == document.body;
if (config._settings || node && multiset) {
top_node = config;
moving = true;
} else {
if (node && body_child) config.$topView = true;
if (!config._inner) config._inner = {};
if (parent && parent.getParentView) {
state._parent_cell = !id && id !== 0 ? parent.getParentView() : parent;
}
top_node = _view(config);
}
if (body_child && !top_node.setPosition && !top_node.$apiOnly) use("_fixHeight")();
if (top_node._settings && top_node._settings._hidden && !node.$view) {
top_node._settings._container = node;
} else if (!top_node.$apiOnly) {
if (node.appendChild) _appendDom(node, top_node, config);else if (node.destructor) {
var target = node; //addView or view moving with target id
if (!id && id !== 0 && !isArray(top_node)) {
id = node;
node = node.getParentView();
} //if target supports view adding
if (node && node._replace) {
if (moving && top_node.getParentView) {
//if source supports view removing
var _parent = top_node.getParentView();
if (_parent && _parent._remove) {
_parent._remove(top_node);
} //adjust parent link and scope
top_node._parent_cell = node;
top_node.$scope = node.$scope;
}
node._replace(top_node, id);
} else {
var _parent2 = target.$view.parentNode;
target.destructor();
_appendDom(_parent2, top_node, config);
}
} else assert(0, "Not existing parent:" + config.container);
}
return top_node;
}
function _appendDom(node, top_node, config) {
node.appendChild(top_node._viewobj);
if (top_node.getParentView()) return; //resize window with position center or top
//do not resize other windows and elements
// which are attached to custom html containers
if ((!top_node.setPosition || top_node._settings.fullscreen) && node == document.body || top_node._settings.position) state.top_views.push(top_node._destructor_handler);
if (!config.skipResize) top_node.adjust();
}
function _correctId(target, multiset, id) {
//replace view
var views = [target]; //replace content of layout
if (multiset) views = target.getChildViews(); //replace content of window
else if (target._body_cell) views = [target._body_cell]; //add cell in layout by number
else if (typeof id == "number") {
return id; //replace cell in layout by id
} else if (id) {
views = [$$(id)];
_deleteIds(views);
return views[0].config.id;
}
_deleteIds(views);
return id;
}
function _deleteIds(uis) {
for (var i = uis.length - 1; i >= 0; i--) {
var current = uis[i]; //remove original id
delete views[current.config.id]; //create temp id
current.config.id = "x" + uid();
views[current.config.id] = current; //process childs
if (current.getChildViews) _deleteIds(current.getChildViews()); //process related UI
if (current._destroy_with_me) _deleteIds(current._destroy_with_me);
}
}
function _view(config) {
{
// check for trailing comma
var coll = config.cells || config.rows || config.elements || config.cols;
if (coll) for (var i = 0; i < coll.length; i++) {
if (coll[i] === null || typeof coll[i] === "undefined") assert(0, "You have trailing comma or Null element in collection's configuration");
}
}
if (config.view) {
var view = config.view;
assert(ui[view], "unknown view:" + view);
return new ui[view](config);
} else if (config.rows || config.cols) {
var cells = config.rows || config.cols;
var accordion = false;
for (var _i = 0; _i < cells.length; _i++) {
if (cells[_i].body && !cells[_i].view && !cells[_i].align) accordion = true;
}
if (accordion) {
return new ui.headerlayout(config);
} else return new ui.layout(config);
} else if (config.cells) return new ui.multiview(config);else if (config.template || config.content) return new ui.template(config);else if (config.align && config.body) {
return new ui.align(config);
} else return new ui.spacer(config);
} //FIXME
ui._view = _view;
function $$(id) {
if (!id) return null;
if (views[id]) return views[id];
var name = id;
if (_typeof(id) == "object") {
if (id._settings) return id;
name = id.target || id;
}
return views[locate({
target: toNode(name)
},
/*@attr*/
"view_id")];
}
if (typeof window.$$ === "undefined") window.$$ = $$;
exports.protoUI = function () {
var origins = arguments;
var selfname = origins[0].name;
var t = function (data) {
if (!t) return ui[selfname].prototype;
var origins = t.$protoWait;
if (origins) {
var params = [origins[0]];
for (var i = 1; i < origins.length; i++) {
params[i] = origins[i];
if (params[i].$protoWait) params[i] = params[i].call(-1, params[i].name);
if (params[i].prototype && params[i].prototype.name) ui[params[i].prototype.name] = params[i];
}
ui[selfname] = exports.proto.apply(-1, params);
if (t._webix_type_wait) for (var _i2 = 0; _i2 < t._webix_type_wait.length; _i2++) {
type(ui[selfname], t._webix_type_wait[_i2]);
}
t = origins = null;
}
if (this != -1) return new ui[selfname](data);else return ui[selfname];
};
t.$protoWait = Array.prototype.slice.call(arguments, 0);
return ui[selfname] = t;
};
exports.proto = function () {
var origins = arguments;
var compilation = origins[0];
var has_constructor = !!compilation.$init;
var construct = [];
assert(compilation, "Invalid mixing target");
for (var i = origins.length - 1; i > 0; i--) {
assert(origins[i], "Invalid mixing source");
if (typeof origins[i] == "function") origins[i] = origins[i].prototype;
if (origins[i].$init) construct.push(origins[i].$init);
if (origins[i].defaults) {
var defaults = origins[i].defaults;
if (!compilation.defaults) compilation.defaults = {};
for (var def in defaults) {
if (isUndefined(compilation.defaults[def])) compilation.defaults[def] = defaults[def];
}
}
if (origins[i].type && compilation.type) {
for (var _def in origins[i].type) {
if (!compilation.type[_def]) compilation.type[_def] = origins[i].type[_def];
}
}
for (var key in origins[i]) {
if (!compilation[key] && compilation[key] !== false) compilation[key] = origins[i][key];
}
}
if (has_constructor) construct.push(compilation.$init);
compilation.$init = function () {
for (var i = 0; i < construct.length; i++) {
construct[i].apply(this, arguments);
}
};
if (compilation.$skin) compilation.$skin();
var result = function (config) {
this.$ready = [];
assert(this.$init, "object without init method");
this.$init(config);
if (this._parseSettings) this._parseSettings(config, this.defaults);
for (var i = 0; i < this.$ready.length; i++) {
this.$ready[i].call(this);
}
};
result.prototype = compilation;
compilation = origins = null;
return result;
};
attachEvent("onClick", function (e) {
var element = $$(e);
if (element && element.touchable) {
use("UIManager").applyChanges(element); //for inline elements - restore pointer to the master element
element.getNode(e); //reaction on custom css elements in buttons
var trg = e.target;
if (element.config.disabled) return;
var css = "";
if (trg.className && trg.className.toString().indexOf("webix_view") === 0) return;
if (element) use("UIManager")._focus_action(element); //loop through all parents
while (trg && trg.parentNode) {
if (trg.getAttribute) {
if (trg.getAttribute(
/*@attr*/
"view_id")) break;
css = trg.className;
if (css) {
css = css.toString().split(" ");
for (var i = 0; i < css.length; i++) {
if (element.on_click[css[i]]) {
var res = element.on_click[css[i]].call(element, e, element._settings.id, trg);
if (res === false) return;
}
}
}
}
trg = trg.parentNode;
}
if (element._settings.click) {
var code = toFunctor(element._settings.click, element.$scope);
if (code && code.call) code.call(element, element._settings.id, e);
}
var popup = element._settings.popup;
if (popup && !element._settings.readonly) {
if (_typeof(popup) == "object" && !popup.name) {
popup = element._settings.popup = ui(popup)._settings.id;
element._destroy_with_me.push($$(popup));
}
popup = $$(popup);
assert(popup, "Unknown popup");
if (!popup.isVisible()) {
popup._settings.master = element._settings.id;
popup.show(element.getInputNode() || element.getNode(), null, true);
}
}
element.callEvent("onItemClick", [element._settings.id, e]);
}
}); //hook for documentation generator
{
if (window.webix_on_core_ready) {
var mod = window.webix_on_core_ready({
proto: exports.proto,
protoUI: exports.protoUI
});
exports.proto = mod.proto;
exports.protoUI = mod.protoUI;
}
}
var TooltipControl = {
_tooltip_masters: _to_array(["dummy"]),
_tooltip_exist: 0,
overflow: false,
delay: 400,
addTooltip: function (target, config) {
var _this = this;
var node, ctrl;
target = toNode(target);
assert(target, "Target isn't defined");
if (target instanceof Element) {
node = target;
if (typeof config === "string") node.setAttribute("webix_tooltip", config);else ctrl = config;
} else {
node = target.$view;
ctrl = target;
}
ctrl = ctrl || this;
var index$$1 = this._tooltip_masters.find(ctrl);
if (index$$1 === -1) {
index$$1 = this._tooltip_masters.length;
this._tooltip_masters.push(ctrl);
}
node.webix_tooltip = index$$1;
this._tooltip_exist++;
if (!this._tooltip) {
this._tooltip = new ui.tooltip({});
this._tooltip._css_name = "webix_tooltip webix_global_tooltip";
this._webix_tooltip_mm = event$1(document, "mousemove", this._move_tooltip, {
bind: this
});
this._webix_tooltip_ml = event$1(document, "mouseleave", this._hide_tooltip, {
bind: this
});
this._drag_event = attachEvent("onDragMode", function () {
return _this._hide_tooltip();
});
this._click_event = attachEvent("onClick", function () {
return _this._hide_tooltip();
});
}
},
getTooltip: function () {
return this._tooltip;
},
_move_tooltip: function (e) {
var c = {};
var node = e.target;
while (node instanceof Element && node.tagName != "HTML") {
// find `webix_tooltip` marker
if (!c.first || !c.overflow) {
var text = node.getAttribute("webix_tooltip");
c.first = c.first || text;
if (text && node.scrollWidth > node.clientWidth) c.overflow = text;
} // find tooltip master
if (this._tooltip_masters[node.webix_tooltip]) {
if (this._last && this._last != node) {
this.$tooltipOut(this._last, node, e);
this._last = null;
return;
}
if (!this._last) this._last = this.$tooltipIn(node, e);
return this.$tooltipMove(node, e, c);
}
node = node.parentElement;
}
if (this._last) this._last = this.$tooltipOut(this._last, null, e);
},
_hide_tooltip: function () {
clearTimeout(this._before_show_delay);
this._tooltip.hide();
},
getMaster: function (t) {
return this._tooltip_masters[t.webix_tooltip];
},
removeTooltip: function (target) {
var node;
assert(target, "Target isn't defined");
target = toNode(target);
if (target instanceof Element) node = target;else node = target.$view;
var tip = node.webix_tooltip;
if (tip) {
if (this._last == node) {
this._hide_tooltip();
this._last = null;
}
delete node.webix_tooltip;
this._tooltip_exist--;
this._tooltip_masters[tip] = null;
}
if (!this._tooltip_exist && this._tooltip) {
// detach events first
this._webix_tooltip_mm = eventRemove(this._webix_tooltip_mm);
this._webix_tooltip_ml = eventRemove(this._webix_tooltip_ml);
this._drag_event = detachEvent(this._drag_event);
this._click_event = detachEvent(this._click_event); // then destroy the tooltip
this._tooltip.destructor();
this._tooltip = this._last = null;
this._tooltip_masters = _to_array(["dummy"]);
}
},
$tooltipIn: function (t, e) {
var m = this._tooltip_masters[t.webix_tooltip];
if (m.$tooltipIn && m != this) return m.$tooltipIn(t, e);
this._tooltip.define({
dx: 20,
dy: 0,
template: "",
css: ""
});
return t;
},
$tooltipOut: function (t, n, e) {
var m = this._tooltip_masters[t.webix_tooltip];
if (m.$tooltipOut && m != this) return m.$tooltipOut(t, n, e);
this._hide_tooltip();
return null;
},
$tooltipMove: function (t, e, c) {
var m = this._tooltip_masters[t.webix_tooltip];
if (m.$tooltipMove && m != this) return m.$tooltipMove(t, e, c);
var overflow = isUndefined(m.overflow) ? this.overflow : m.overflow;
var time = isUndefined(m.delay) ? this.delay : m.delay;
var text = overflow ? c.overflow : c.first;
if (time > 0) this._hide_tooltip();
this._before_show_delay = delay(this._tooltip.show, this._tooltip, [text || {}, pos(e)], time);
}
};
function _uid(name) {
return "$" + name + (_namecount[name] = (_namecount[name] || 0) + 1);
}
var _namecount = {};
var _freeze_resize = false;
function freeze(handler, trigger) {
_freeze_resize = true;
var res = handler();
if (res && res.then) {
res = res.then(function (any) {
_freeze_resize = false;
if (trigger !== false) resize();
return any;
});
} else {
_freeze_resize = false;
if (trigger !== false) resize();
}
return res;
}
function resize() {
use("UIManager").applyChanges();
callEvent("onClick", []);
state._force_resize = true;
if (!_freeze_resize) for (var i = state.top_views.length - 1; i >= 0; i--) {
if (state.top_views[i].obj) state.top_views[i].obj.resize();
}
state._force_resize = false;
}
function _each(parent, logic, master, include) {
if (parent) {
var children = include ? [parent] : parent.getChildViews();
for (var i = 0; i < children.length; i++) {
if (logic.call(master, children[i]) !== false) _each(children[i], logic, master);
}
}
}
function zIndex(index) {
if (!isUndefined(index)) {
env.zIndexBase = Math.max(env.zIndexBase, index + 1);
return index;
}
return env.zIndexBase++;
}
event$1(window, "resize", function () {
// check for virtual keyboard
if (env.touch && (state._focus_time && new Date() - state._focus_time < 1000)) {
return;
} else {
resize();
}
});
function ready(code) {
if (_ready) code.call();else _ready_code.push(code);
}
var _ready = false;
var _ready_code = []; //autodetect codebase folder
var temp = document.getElementsByTagName("SCRIPT"); //current script, most probably
assert(temp.length, "Can't locate codebase");
if (temp.length) {
//full path to script
temp = (temp[temp.length - 1].getAttribute("src") || "").split("/"); //get folder name
temp.splice(temp.length - 1, 1);
env.codebase = temp.slice(0, temp.length).join("/") + "/";
}
var handler = function () {
if (env.isIE) document.body.className += " webix_ie";
callEvent("onReady", []);
};
var doit = function () {
_ready = true;
/* global webix_ready */
if (window.webix_ready && isArray(webix_ready)) _ready_code = webix_ready.concat(_ready_code);
for (var i = 0; i < _ready_code.length; i++) {
_ready_code[i].call();
}
_ready_code = [];
};
attachEvent("onReady", function (force) {
if (force) doit();else delay(doit);
});
if (document.readyState == "complete") handler();else event$1(window, "load", handler);
ready(function () {
event$1(document.body, "click", function (e) {
callEvent("onClick", [e || window.event]);
});
});
var rules = {
isEmail: function (value) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test((value || "").toString());
},
isNumber: function (value) {
return parseFloat(value) == value;
},
isChecked: function (value) {
return !!value || value === "0";
},
isNotEmpty: function (value) {
return value === 0 || value;
}
};
function callback(config, result) {
// prompt
if (config.type.indexOf("prompt") != -1) {
if (result === false) {
config._promise.reject();
} else {
var inputBox = config._box.querySelector(".webix_popup_input");
var _input = inputBox.querySelector("input");
if (config.input.required && !_input.value) {
config.input.invalid = true;
addCss(inputBox, "webix_popup_invalid");
return;
} else {
result = _input.value || "";
config._promise.resolve(result);
}
}
}
config.type.indexOf("confirm") != -1 && result === false ? config._promise.reject() : config._promise.resolve(result);
var usercall = config.callback;
if (usercall) usercall(result, config.details);
modalbox.hide(config.id);
}
function modal_key(e) {
var order = modalbox.order;
var count = order.length;
var source = e.target;
if (count > 0 && message.keyboard) {
e = e || window.event;
var code = e.which || e.keyCode;
if (code != 13 && code != 32 && code != 27) return;
var activeBox;
for (var i = count - 1; i >= 0; i--) {
var box = modalbox.pull[order[i]];
if (box._box != source && box._box.contains(source) && code == 32) // ignore space inside input
return;
if (box.container && box.container.contains(source)) {
activeBox = box;
break;
}
}
if (!activeBox) activeBox = modalbox.pull[order[order.length - 1]];
if (code == 13 || code == 32) callback(activeBox, true);else if (code == 27) callback(activeBox, false);
preventEvent(e);
return !(e.cancelBubble = true);
}
}
event$1(document, "keydown", modal_key, {
capture: true
});
function modality(mode, container) {
var node = container || document.body;
var cover;
if (isUndefined(node.modality)) {
cover = create("DIV", {
"class": "webix_modal_cover",
style: "position:" + (container ? "absolute" : "fixed") + ";"
});
cover.onkeydown = modal_key;
if (container) {
var position = window.getComputedStyle(container).position;
if (position != "fixed" && position != "absolute" && position != "sticky" && position != "relative") node.style.position = "relative";
}
node.appendChild(cover);
node.modality = 1;
} else mode ? node.modality++ : node.modality--; //trigger visibility only if necessary
if (mode && node.modality === 1 || node.modality === 0) {
cover = cover || Array.prototype.slice.call(node.querySelectorAll(".webix_modal_cover")).filter(function (el) {
return el.parentNode == node;
})[0];
if (cover) {
if (!node.modality) {
cover.style.display = "none";
removeCss(node, "webix_modalbox_inside");
} else if (node.modality == 1) {
cover.style.display = "inline-block";
addCss(node, "webix_modalbox_inside");
}
}
}
return cover;
}
function button(text, result, className) {
return "<div role='button' tabindex='0' aria-label='" + text + "' class='webix_popup_button" + (className ? " " + className : "") + "' result='" + result + "' ><div>" + text + "</div></div>";
}
function input(config) {
return "<div tabindex='0' class='webix_popup_input webix_el_text" + (config.required ? " webix_required" : "") + "'><input value='" + template.escape(config.value || "") + "' placeholder='" + template.escape(config.placeholder || "") + "'></input></div>";
}
function info(text) {
if (!t.area) {
t.area = document.createElement("DIV");
t.area.className = "webix_message_area";
t.area.style[t.position] = "5px";
document.body.appendChild(t.area);
}
t.area.setAttribute("role", "alert");
t.area.setAttribute("aria-atomic", true);
t.hide(text.id);
var message = document.createElement("DIV");
message.innerHTML = "<div>" + text.text + "</div>";
message.className = "webix_message webix_" + text.type;
message.onclick = function () {
if (text) t.hide(text.id);
text = null;
};
if (t.position == "bottom" && t.area.firstChild) t.area.insertBefore(message, t.area.firstChild);else t.area.appendChild(message);
if (text.expire > 0) t.timers[text.id] = window.setTimeout(function () {
t.hide(text.id);
}, text.expire); //styling for animation
message.style.height = message.offsetHeight - 2 + "px";
t.pull[text.id] = message;
message = null;
return text.id;
}
function _boxStructure(config, ok, cancel, hasInput) {
var box = document.createElement("DIV");
var css = config.css ? " " + config.css : "";
box.className = "webix_modal_box webix_" + config.type + css;
box.setAttribute("webixbox", 1);
box.setAttribute("role", "alertdialog");
box.setAttribute("aria-label", config.title || "");
box.setAttribute("tabindex", "0");
var inner = "";
if (config.width) box.style.width = config.width + (rules.isNumber(config.width) ? "px" : "");
if (config.height) box.style.height = config.height + (rules.isNumber(config.height) ? "px" : "");
if (config.title) inner += "<div class=\"webix_popup_title\">" + config.title + "</div>";
inner += "<div class=\"webix_popup_text" + (hasInput ? " webix_popup_label" : "") + "\"><span>" + (config.content ? "" : config.text || "") + "</span></div>";
inner += "<div class=\"webix_popup_controls\">";
if (hasInput) inner += input(config.input);
if (cancel) inner += button(config.cancel || i18n.message.cancel, false);
if (ok) inner += button(config.ok || i18n.message.ok, true, "confirm");
if (config.buttons && !ok && !cancel) {
for (var i = 0; i < config.buttons.length; i++) {
inner += button(config.buttons[i], i);
}
}
inner += "</div>";
box.innerHTML = inner;
if (config.content) {
var node = config.content;
if (typeof node == "string") node = document.getElementById(node);
if (node.style.display == "none") node.style.display = "";
box.childNodes[config.title ? 1 : 0].appendChild(node);
}
if (config.type.indexOf("prompt") != -1) {
var inputBox = box.querySelector(".webix_popup_input");
var _input2 = inputBox.querySelector("input");
_input2.oninput = function () {
if (config.input.invalid) {
removeCss(inputBox, "webix_popup_invalid");
config.input.invalid = false;
}
};
}
box.onclick = function (e) {
e = e || window.event;
var source = e.target;
if (!source.className) source = source.parentNode;
if (source.className.indexOf("webix_popup_button") != -1) {
var result = source.getAttribute("result");
result = result == "true" || (result == "false" ? false : result);
callback(config, result);
}
e.cancelBubble = true;
};
config._box = box;
return box;
}
modalbox.pull = {};
modalbox.order = [];
function _createBox(config, ok, cancel, hasInput) {
var box = config.tagName ? config : _boxStructure(config, ok, cancel, hasInput);
var container = config.container;
var containerWidth = container ? container.offsetWidth : window.innerWidth || document.documentElement.offsetWidth;
var containerHeight = container ? container.offsetHeight : window.innerHeight || document.documentElement.offsetHeight;
var containerLeft = container ? container.scrollLeft : 0;
var containerTop = container ? container.scrollTop : 0;
if (config.container) box.style.position = "absolute";
toNode((config.container || document.body).appendChild(box));
var cover = modality(true, config.container);
var x = config.left || Math.abs(containerLeft + Math.floor((containerWidth - box.offsetWidth) / 2));
var y = config.top || Math.abs(containerTop + Math.floor((containerHeight - box.offsetHeight) / 2));
if (config.position == "top") box.style.top = "-3px";else {
box.style.top = y + "px";
if (cover) {
cover.style.top = containerTop + "px";
cover.style.left = containerLeft + "px";
}
}
box.style.left = x + "px"; //necessary for IE only
box.onkeydown = modal_key;
box.focus();
if (!config.id) config.id = _uid("modalbox");else if (modalbox.pull[config.id]) {
modalbox.hide(config.id);
}
modalbox.order.push(config.id);
modalbox.pull[config.id] = config;
config._promise = Deferred.defer();
return config._promise;
}
function alertPopup(config) {
return _createBox(config, true);
}
function confirmPopup(config) {
return _createBox(config, true, true);
}
function boxPopup(config) {
return _createBox(config);
}
function promptPopup(config) {
return _createBox(config, true, true, true);
}
function box_params(text, type, callback) {
if (_typeof(text) != "object") {
if (typeof type == "function") {
callback = type;
type = "";
}
text = {
text: text,
type: type,
callback: callback
};
}
return text;
}
function params(text, type, expire, id) {
if (_typeof(text) != "object") text = {
text: text,
type: type,
expire: expire,
id: id
};
text.id = text.id || _uid("message");
text.expire = text.expire || t.expire;
return text;
}
function alert() {
var text = box_params.apply(this, arguments);
text.type = text.type || "alert";
return alertPopup(text);
}
function confirm() {
var text = box_params.apply(this, arguments);
text.type = text.type || "confirm";
return confirmPopup(text);
}
function modalbox() {
var text = box_params.apply(this, arguments);
text.type = text.type || "alert";
return boxPopup(text);
}
function prompt() {
var text = box_params.apply(this, arguments);
text.type = text.type || "prompt";
text.input = text.input || {};
return promptPopup(text);
}
modalbox.hide = function (id) {
if (id && modalbox.pull[id]) {
var node = modalbox.pull[id]._box;
if (node) {
node.parentNode.removeChild(node);
modalbox.order.splice(modalbox.order.indexOf(id), 1);
modality(false, modalbox.pull[id].container);
delete modalbox.pull[id];
}
}
};
modalbox.hideAll = function () {
for (var id in modalbox.pull) {
this.hide(id);
}
};
function message(text, type, expire, id) {
//eslint-disable-line
text = params.apply(this, arguments);
text.type = text.type || "info";
var subtype = text.type.split("-")[0];
switch (subtype) {
case "alert":
return alertPopup(text);
case "confirm":
return confirmPopup(text);
case "modalbox":
return boxPopup(text);
case "prompt":
return promptPopup(text);
default:
return info(text);
}
}
var t = message;
t.expire = 4000;
t.keyboard = true;
t.position = "top";
t.pull = {};
t.timers = {};
t.hideAll = function () {
for (var key in t.pull) {
t.hide(key);
}
};
t.hide = function (id) {
var obj = t.pull[id];
if (obj && obj.parentNode) {
window.setTimeout(function () {
obj.parentNode.removeChild(obj);
obj = null;
}, 2000); //styling for animation
obj.style.height = 0;
obj.className += " hidden";
t.area.removeAttribute("role");
if (t.timers[id]) window.clearTimeout(t.timers[id]);
delete t.pull[id];
}
}; //override circualr dependencies
define("message", message);
var fullscreen = {
set: function (view, config) {
config = config || {};
if (this._view) this.exit();
if ($$(view)) view = $$(view);else {
if (typeof view == "string") view = document.getElementById(view);
if (view instanceof Element) view = {
$view: view,
$html: true
};
assert(view, "Incorrect view for fullscreen mode");
}
this._view = view;
this._pos = this._setPosition();
var viewConfig = view.config;
if (view.setPosition) {
viewConfig.fullscreen = true;
view.resize();
return view;
} else {
this._fullscreen = ui({
view: "window",
head: this._getHeadConfig(config),
css: config.css || "",
fullscreen: true,
borderless: true,
//better resize logic
body: {
rows: []
}
});
if (viewConfig) this._sizes = {
width: viewConfig.width,
minWidth: viewConfig.minWidth,
maxWidth: viewConfig.maxWidth,
height: viewConfig.height,
minHeight: viewConfig.minHeight,
maxHeight: viewConfig.maxHeight
};
if (view.getParentView && view.getParentView()) {
this._parent = view.getParentView();
if (this._parent.index) {
this._pos.index = this._parent.index(view);
this._pos.active = this._parent.getActiveId ? this._parent.getActiveId() == viewConfig.id : false;
}
} else {
this._parent = view.$view.parentNode;
this._pos.node = create("div"); //save old position
this._parent.replaceChild(this._pos.node, view.$view);
}
this._fullscreen.getBody().addView(view.$html ? {
view: "template",
content: view.$view,
css: "webix_fullscreen_html"
} : view);
this._fullscreen.show();
this._setSizes(view);
return this._fullscreen;
}
},
exit: function () {
if (this._view) {
var viewConfig = this._view.config;
this._setPosition(true);
if (this._view.setPosition) {
viewConfig.fullscreen = false;
this._view.resize();
} else {
if (this._parent instanceof Element) {
this._view._parent_cell = null;
if (this._view._set_inner) this._view._set_inner(this._view.config);
this._parent.replaceChild(this._view.$view, this._pos.node);
} else {
if (!isUndefined(this._pos.index)) {
this._parent.addView(this._view, this._pos.index);
if (this._pos.active) this._view.show(false, false);
} else {
this._view._parent_cell = this._parent;
this._parent._replace(this._view);
}
}
this._setSizes(this._view, this._sizes); //prevent view destruction (with layout)
if (!this._view.$html) this._fullscreen.getBody()._cells = []; //we can't set head false with replace, so we need to close win
this._fullscreen.close();
}
this._clearValues();
}
},
_clearValues: function () {
delete this._parent;
delete this._view;
delete this._sizes;
delete this._pos;
delete this._fullscreen;
},
_setPosition: function (restore) {
var _this = this;
var view = this._view;
var oldStyles = {};
if (view.setPosition) {
if (restore) view.setPosition(this._pos.left, this._pos.top);else {
oldStyles.left = view.config.left;
oldStyles.top = view.config.top;
view.setPosition(0, 0);
}
} else {
var rules = ["position", "top", "bottom", "left", "right"];
var style = view.$view.style;
rules.forEach(function (rule) {
if (restore) style[rule] = _this._pos[rule];else {
oldStyles[rule] = style[rule];
style[rule] = rule == "position" ? "relative" : 0;
}
});
}
return oldStyles;
},
_setSizes: function (view, sizes) {
if (!view.$html) {
sizes = sizes || {
height: 0,
minHeight: 0,
maxHeight: 0,
width: 0,
minWidth: 0,
maxWidth: 0
};
view.define(sizes);
view.resize();
}
},
_getHeadConfig: function (config) {
var _this2 = this;
if (config.head === false || _typeof(config.head) == "object") return config.head;else {
return {
cols: [{
template: config.head || "",
type: "header",
borderless: true
}, {
view: "icon",
icon: "wxi-close",
click: function () {
_this2.exit();
}
}]
};
}
}
};
var UIManager = {
_view: null,
_hotkeys: {},
_focus_time: 0,
_tab_time: 0,
_mouse_time: 0,
_controls: {
"esc": "escape",
"up": "arrowup",
"down": "arrowdown",
"left": "arrowleft",
"right": "arrowright",
"pgdown": "pagedown",
"pgup": "pageup",
"space": " ",
"multiply": "*",
"add": "+",
"subtract": "-",
"decimal": ".",
"divide": "/",
"pausebreak": "pause",
"5numlocked": "clear"
},
_inputs: {
"input": 1,
"button": 1,
"textarea": 1,
"select": 1
},
_enable: function () {
// attaching events here
event$1(document, "keydown", this._keypress, {
bind: this
});
event$1(document.body, "click", this._focus_click, {
capture: true,
bind: this
});
event$1(document.body, "mousedown", function () {
this._mouse_time = new Date();
}, {
bind: this
});
event$1(document.body, "focus", this._focus_tab, {
capture: true,
bind: this
});
state.destructors.push({
obj: this
});
},
destructor: function () {
UIManager._view = null;
},
getFocus: function () {
return this._view;
},
_focus_action: function (view) {
this._focus_was_there = this._focus_was_there || view._settings.id;
},
setFocus: function (view, only_api, tab) {
//view can be empty
view = $$(view); //unfocus if view is hidden
if (view && !view.$view) view = null; //store last click time, it is necessary to prevent refocusing
//for example when user moves focus from onclick handler somewher
//and we want to prevent autofocusing, when event will reach document.body
this._focus_time = state._focus_time = new Date();
if (this._view === view) return true;
if (this._view && this._view.callEvent) this._view.callEvent("onBlur", [this._view]);
if (view && view.callEvent) {
view.callEvent("onFocus", [view, this._view]);
if (tab) view.callEvent("onTabFocus", [view, this._view]);
}
callEvent("onFocusChange", [view, this._view]);
if (this._view && this._view.blur && !only_api) this._view.blur();
this._view = view;
if (view && view.focus && !only_api) view.focus();
return true;
},
applyChanges: function (element) {
var view = this.getFocus();
if (view && view != element && view._applyChanges) view._applyChanges(element);
},
hasFocus: function (view) {
return view === this._view ? true : false;
},
_focus: function (e) {
for (var i = 0; i < modalbox.order.length; i++) {
if (modalbox.pull[modalbox.order[i]]._box.contains(e.target)) return;
}
var view = locate(e,
/*@attr*/
"view_id") || this._focus_was_there; //if html was repainted we can miss the view, so checking last processed one
view = $$(view);
this._focus_was_there = null; //set timer, to fix issue with Android input focusin
state._focus_time = new Date();
if (view == this._view) return true;
if (view) {
if (this.canFocus(view)) {
// keep form focus
if (this._view && this._view.getFormView() == view && this._view.focus) this._view.focus();else this.setFocus(view);
} //remove focus from an unreachable view
else if (view.$view.contains(e.target)) e.target.blur();
} else this.setFocus(null);
return true;
},
_focus_click: function (e) {
// if it was onfocus/onclick less then 100ms behore then we ignore it
if (new Date() - this._focus_time < 100) {
this._focus_was_there = null;
return false;
}
return this._focus(e);
},
_focus_tab: function (e) {
if (!this._inputs[e.target.nodeName.toLowerCase()]) return false;
return this._focus(e);
},
_top_modal: function (view) {
var modality = state._modality;
if (!modality.length) return true;
var top = view.queryView(function (a) {
return !a.getParentView();
}, "parent") || view;
return (top.$view.style.zIndex || 0) >= Math.max.apply(Math, _toConsumableArray(modality));
},
canFocus: function (view) {
if (document.body.modality || view.$view.modality || view.queryView(function (view) {
return view.$view.modality;
}, "parent")) //modalbox
return false;
return view.isVisible() && view.isEnabled() && !view.config.disabled && this._top_modal(view) && !view.queryView({
disabled: true
}, "parent");
},
_moveChildFocus: function (check_view) {
var focus = this.getFocus(); //we have not focus inside of closing item
if (check_view && !this._is_child_of(check_view, focus)) return false;
if (!this._focus_logic("getPrev", check_view)) this._view = null;
},
_is_child_of: function (parent, child) {
if (!parent) return false;
if (!child) return false;
while (child) {
if (child === parent) return true;
child = child.getParentView();
}
return false;
},
_keypress_timed: function () {
if (this && this.callEvent) this.callEvent("onTimedKeyPress", []);
},
_keypress: function (e) {
var code = e.which || e.keyCode; // numpad keys
if (code > 95 && code < 106) code -= 48;
var view = this.getFocus();
if (view && view.callEvent) {
if (view.callEvent("onKeyPress", [code, e]) === false) preventEvent(e);
if (view.hasEvent("onTimedKeyPress")) {
clearTimeout(view._key_press_timeout);
view._key_press_timeout = delay(this._keypress_timed, view, [], view._settings.keyPressTimeout || 250);
}
}
if (this._check_keycode(e) === false) {
preventEvent(e);
return false;
}
},
// dir - getNext or getPrev
_focus_logic: function (dir, focus) {
var next = focus || this.getFocus();
if (next) {
dir = dir || "getNext";
var start = next;
var marker = uid();
while (true) {
// eslint-disable-line
next = this[dir](next); // view with focus ability
if (next && this.canFocus(next)) return this.setFocus(next); // elements with focus ability not found
if (next === start || next.$fmarker == marker) {
if (focus) document.activeElement.blur();
return null;
} //prevents infinity loop
next.$fmarker = marker;
}
}
},
_tab_logic: function (view, e) {
var mode = !e.shiftKey;
UIManager._tab_time = new Date();
if (view && view._custom_tab_handler && !view._custom_tab_handler(mode, e)) return false;
if (view && view._in_edit_mode) {
if (view.editNext) return view.editNext(mode);else if (view.editStop) {
view.editStop();
return true;
}
} else delay(function () {
view = $$(document.activeElement);
if (view && !UIManager.canFocus(view)) return UIManager._focus_logic(mode ? "getNext" : "getPrev", view);
UIManager.setFocus(view, true, true);
});
},
getTop: function (id) {
var next,
view = $$(id);
while (view && (next = view.getParentView())) {
view = next;
}
return view;
},
getNext: function (view, _inner_call) {
var cells = view.getChildViews(); //tab to first children
if (cells.length && !_inner_call) for (var i = 0; i < cells.length; i++) {
if (this.canFocus(cells[i])) return cells[i];
} //unique case - single view without child and parent
var parent = view.getParentView();
if (!parent) return view;
var p_cells = parent.getChildViews();
if (p_cells.length) {
var index$$1 = _power_array.find.call(p_cells, view) + 1;
while (index$$1 < p_cells.length) {
//next visible child
if (this.canFocus(p_cells[index$$1])) return p_cells[index$$1];
index$$1++;
}
} //sibling of parent
return this.getNext(parent, true);
},
getPrev: function (view, _inner_call) {
var cells = view.getChildViews(); //last child of last child
if (cells.length && _inner_call) for (var i = cells.length - 1; i >= 0; i--) {
if (this.canFocus(cells[i])) return this.getPrev(cells[i], true);
}
if (_inner_call && this.canFocus(view)) return view; //fallback from top to bottom
var parent = view.getParentView();
if (!parent) return this.canFocus(view) ? this.getPrev(view, true) : view;
var p_cells = parent.getChildViews();
if (p_cells) {
var index$$1 = _power_array.find.call(p_cells, view) - 1;
while (index$$1 >= 0) {
if (this.canFocus(p_cells[index$$1])) return this.getPrev(p_cells[index$$1], true);
index$$1--;
}
}
return this.getPrev(parent, true);
},
addHotKey: function (keys, handler, view) {
assert(handler, "Hot key handler is not defined");
var code = this._parse_keys(keys);
if (!view) view = null;
if (!this._hotkeys[code]) this._hotkeys[code] = [];
this._hotkeys[code].push({
handler: handler,
view: view
});
return keys;
},
removeHotKey: function (keys, func, view) {
var code = this._parse_keys(keys);
if (!func && !view) delete this._hotkeys[code];else {
var t = this._hotkeys[code];
if (t) {
for (var i = t.length - 1; i >= 0; i--) {
if (view && t[i].view !== view) continue;
if (func && t[i].handler !== func) continue;
t.splice(i, 1);
}
if (!t.length) delete this._hotkeys[code];
}
}
},
_keycode: function (key, ctrl, shift, alt, meta) {
//key can be undefined (browser autofill)
return (key || "").toLowerCase() + "_" + ["", ctrl ? "1" : "0", shift ? "1" : "0", alt ? "1" : "0", meta ? "1" : "0"].join("");
},
_check_keycode: function (e) {
var keyCode = e.which || e.keyCode;
var is_any = !e.ctrlKey && !e.altKey && !e.metaKey && keyCode != 9 && keyCode != 27 && keyCode != 13;
var code = this._keycode(e.key, e.ctrlKey, e.shiftKey, e.altKey, e.metaKey);
var focus = this.getFocus();
if (this._hotkeys[code]) return this._process_calls(this._hotkeys[code], focus, e);else if (is_any && this._hotkeys["any_0000"]) return this._process_calls(this._hotkeys["any_0000"], focus, e);
return true;
},
_process_calls: function (calls, focus, e) {
for (var i = 0; i < calls.length; i++) {
var key = calls[i];
if (key.view !== null && //common hot-key
focus !== key.view && ( //hot-key for current view
//hotkey for current type of view
typeof key.view !== "string" || !focus || focus.name !== key.view)) continue;
var temp_result = key.handler(focus, e);
if (!!temp_result === temp_result) return temp_result;
}
return true;
},
_parse_keys: function (keys) {
var controls = this._controls;
var parts = keys.toLowerCase().split(/[ +\-_]/);
var ctrl, shift, alt, meta;
ctrl = shift = alt = meta = 0;
var letter = "";
for (var i = 0; i < parts.length; i++) {
if (parts[i] === "ctrl") ctrl = 1;else if (parts[i] === "shift") shift = 1;else if (parts[i] === "alt") alt = 1;else if (parts[i] === "command") meta = 1;else {
letter = controls[parts[i]] || parts[i];
}
}
return this._keycode(letter, ctrl, shift, alt, meta);
},
getState: function (node, children) {
children = children || false;
node = $$(node);
var state$$1 = {
id: node.config.id,
width: node.config.width,
height: node.config.height,
gravity: node.config.gravity
};
if (!isUndefined(node.config.collapsed)) state$$1.collapsed = node.config.collapsed;
if (node.name === "tabs" || node.name === "tabbar") state$$1.activeCell = node.getValue();
if (children) {
state$$1 = [state$$1];
if (node._cells) {
for (var i = 0; i < node._cells.length; i++) {
state$$1 = state$$1.concat(this.getState(node._cells[i], children));
}
}
}
return state$$1;
},
setState: function (states) {
if (!isArray(states)) states = [states];
for (var i = 0; i < states.length; i++) {
var state$$1 = states[i];
var node = $$(state$$1.id);
if (!node) continue;
if (!isUndefined(state$$1.collapsed)) node.define("collapsed", state$$1.collapsed);
if (!isUndefined(state$$1.activeCell)) node.setValue(state$$1.activeCell, "auto");
node.define("width", state$$1.width);
node.define("height", state$$1.height);
node.define("gravity", state$$1.gravity);
}
var top = $$(states[0].id);
if (top) top.resize();
}
};
ready(function () {
UIManager._enable();
UIManager.addHotKey("enter", function (view, ev) {
if (view && view.callEvent) view.callEvent("onEnter", [ev]);
if (view && view.editStop && view._in_edit_mode) {
view.editStop();
return true;
} else if (view && view.touchable) {
var form = view.getFormView();
if (form && !view._skipSubmit) form.callEvent("onSubmit", [view, ev]);
}
});
UIManager.addHotKey("esc", function (view) {
if (view) {
if (view.editCancel && view._in_edit_mode) {
view.editCancel();
return true;
}
var top = view.getTopParentView();
if (top && top.setPosition) {
if (fullscreen._fullscreen == top) fullscreen.exit();
top._hide();
}
}
});
UIManager.addHotKey("shift+tab", UIManager._tab_logic);
UIManager.addHotKey("tab", UIManager._tab_logic);
});
define("UIManager", UIManager);
var Settings = {
$init: function () {
/*
property can be accessed as this.config.some
in same time for inner call it have sense to use _settings
because it will be minified in final version
*/
this._settings = this.config = {};
},
define: function (property, value) {
if (_typeof(property) == "object") return this._parseSeetingColl(property);
return this._define(property, value);
},
_define: function (property, value) {
//method with name {prop}_setter will be used as property setter
//setter is optional
var setter = this[property + "_setter"];
return this._settings[property] = setter ? setter.call(this, value, property) : value;
},
//process configuration object
_parseSeetingColl: function (coll) {
if (coll) {
for (var a in coll) {
//for each setting
this._define(a, coll[a]);
} //set value through config
}
},
//helper for object initialization
_parseSettings: function (obj, initial) {
//initial - set of default values
var settings = {};
if (initial) settings = exports.extend(settings, initial); //code below will copy all properties over default one
if (_typeof(obj) == "object" && !obj.tagName) exports.extend(settings, obj, true); //call config for each setting
this._parseSeetingColl(settings);
},
_mergeSettings: function (config, defaults) {
for (var key in defaults) {
switch (_typeof(config[key])) {
case "object":
config[key] = this._mergeSettings(config[key] || {}, defaults[key]);
break;
case "undefined":
config[key] = defaults[key];
break;
default:
//do nothing
break;
}
}
return config;
}
};
var Destruction = {
$init: function () {
//wrap in object to simplify removing self-reference
//submenu can trigger this handler two times, preserve a single destructor reference
var t = this._destructor_handler = this._destructor_handler || {
obj: this
}; //register self in global list of destructors
state.destructors.push(t);
},
//will be called automatically on unload, can be called manually
//simplifies job of GC
destructor: function () {
var config = this._settings;
if (this._last_editor) this.editCancel();
if (this.callEvent) this.callEvent("onDestruct", []); //destructor can be called only once
this.destructor = function () {}; //remove self reference from global destructions collection
this._destructor_handler.obj = null; //destroy child and related cells
if (this.getChildViews) {
var cells = this.getChildViews();
if (cells) for (var i = 0; i < cells.length; i++) {
cells[i].destructor();
}
if (this._destroy_with_me) for (var _i = 0; _i < this._destroy_with_me.length; _i++) {
this._destroy_with_me[_i].destructor();
}
}
delete ui.views[config.id];
if (config.$id) {
var top = this.getTopParentView();
if (top && top._destroy_child) top._destroy_child(config.$id);
} //html collection
this._htmlmap = null;
this._htmlrows = null;
this._html = null;
if (this._contentobj) {
this._contentobj.innerHTML = "";
this._contentobj._htmlmap = null;
} //removes view container
if (this._viewobj && this._viewobj.parentNode) {
this._viewobj.parentNode.removeChild(this._viewobj);
}
if (this.data && this.data.destructor) this.data.destructor();
if (this.unbind) this.unbind();
this.data = null;
this._parent_cell = null;
this._viewobj = this.$view = this._contentobj = this._dataobj = null;
this._evs_events = this._evs_handlers = this._evs_map = {}; //remove focus from destructed view
if (UIManager._view == this) UIManager._view = null;
var url = config.url;
if (url && url.$proxy && url.release) url.release();
this.$scope = null; // this flag is checked in delay method
this.$destructed = true;
}
}; //global list of destructors
event$1(window, "unload", function () {
callEvent("unload", []);
state._final_destruction = true; //call all registered destructors
for (var i = 0; i < state.destructors.length; i++) {
var obj = state.destructors[i].obj;
if (obj) obj.destructor();
}
state.destructors = [];
state._popups = _to_array();
_events_final_destructor();
});
var CollectionBind = {
$init: function () {
this._cursor = null;
this.attachEvent("onSelectChange", function () {
var sel = this.getSelectedId();
this.setCursor(sel ? sel.id || sel : null);
});
this.attachEvent("onAfterCursorChange", this._update_binds);
this.attachEvent("onAfterDelete", function (id) {
if (id == this.getCursor()) this.setCursor(null);
});
this.data.attachEvent("onStoreUpdated", bind(function (id, data, mode) {
//paint - ignored
//delete - handled by onAfterDelete above
if (id && id == this.getCursor() && mode != "paint" && mode != "delete") this._update_binds();
}, this));
this.data.attachEvent("onClearAll", bind(function () {
this._cursor = null;
}, this));
this.data.attachEvent("onIdChange", bind(function (oldid, newid) {
if (this._cursor == oldid) {
this._cursor = newid;
this._update_binds();
}
}, this));
},
refreshCursor: function () {
if (this._cursor) this.callEvent("onAfterCursorChange", [this._cursor]);
},
setCursor: function (id) {
if (id == this._cursor || id !== null && !this.getItem(id)) return;
this.callEvent("onBeforeCursorChange", [this._cursor]);
this._cursor = id;
this.callEvent("onAfterCursorChange", [id]);
},
getCursor: function () {
return this._cursor;
},
_bind_update: function (target, rule, format) {
if (rule == "$level" && this.data.getBranch) return (target.data || target).importData(this.data.getBranch(this.getCursor()));
var data = this.getItem(this.getCursor()) || this._settings.defaultData || null;
if (rule == "$data") {
if (typeof format === "function") format.call(target, data, this);else target.data.importData(data ? data[format] : []);
target.callEvent("onBindApply", [data, rule, this]);
} else {
if (format) data = format(data);
this._bind_update_common(target, rule, data);
}
}
};
var ValueBind = {
$init: function () {
this.attachEvent("onChange", this._update_binds);
},
_bind_update: function (target, rule, format) {
rule = rule || "value";
var data = this.getValue() || "";
if (format) data = format(data);
if (target.setValue) target.setValue(data, "auto");else if (!target.filter) {
var pod = {};
pod[rule] = data;
if (target._check_data_feed(data)) target.setValues(pod, false, "auto");
} else {
target.data.silent(function () {
this.filter(rule, data);
});
}
target.callEvent("onBindApply", [data, rule, this]);
}
};
var RecordBind = {
$init: function () {
this.attachEvent("onChange", this._update_binds);
},
_bind_update: function (target, rule, format) {
var data = this.getValues() || null;
if (format) data = format(data);
this._bind_update_common(target, rule, data);
}
};
var BindSource = {
$init: function () {
this._bind_hash = {}; //rules per target
this._bind_updated = {}; //update flags
this._ignore_binds = {}; //apply specific bind extension
this._bind_specific_rules(this);
},
saveBatch: function (code) {
this._do_not_update_binds = true;
code.call(this);
this._do_not_update_binds = false;
this._update_binds();
},
setBindData: function (data, key) {
//save called, updating master data
if (key) this._ignore_binds[key] = true;
if (this.setValue) this.setValue(data, "auto");else if (this.setValues) this.setValues(data, false, "auto");else {
var id = this.getCursor();
if (id) this.updateItem(id, data);else this.add(data);
}
this.callEvent("onBindUpdate", [data, key]);
if (this.save) this.save();
if (key) this._ignore_binds[key] = false;
},
//fill target with data
getBindData: function (key, update) {
//fire only if we have data updates from the last time
if (this._bind_updated[key]) return false;
var target = $$(key); //fill target only when it visible
if (target.isVisible(target._settings.id)) {
this._bind_updated[key] = true;
this._bind_update(target, this._bind_hash[key][0], this._bind_hash[key][1]); //trigger component specific updating logic
if (update && target.filter) target.refresh();
}
},
//add one more bind target
addBind: function (source, rule, format) {
this._bind_hash[source] = [rule, format];
},
removeBind: function (source) {
delete this._bind_hash[source];
delete this._bind_updated[source];
delete this._ignore_binds[source];
},
//returns true if object belong to "collection" type
_bind_specific_rules: function (obj) {
if (obj.filter) exports.extend(this, CollectionBind);else if (obj.setValue) exports.extend(this, ValueBind);else exports.extend(this, RecordBind);
},
//inform all binded objects, that source data was updated
_update_binds: function () {
if (!this._do_not_update_binds) for (var key in this._bind_hash) {
if (this._ignore_binds[key]) continue;
this._bind_updated[key] = false;
this.getBindData(key, true);
}
},
//copy data from source to the target
_bind_update_common: function (target, rule, data) {
if (target.setValue) target.setValue(data && rule ? data[rule] : data, "auto");else if (!target.filter) {
if (!data && target.clear) target.clear("auto");else {
if (target._check_data_feed(data)) target.setValues(clone(data), false, "auto");
}
} else {
target.data.silent(function () {
this.filter(rule, data);
});
}
target.callEvent("onBindApply", [data, rule, this]);
}
};
var BaseBind = {
bind: function (target, rule, format) {
if (!this.attachEvent) exports.extend(this, EventSystem);
if (typeof target == "string") target = $$(target);
if (target._initBindSource) target._initBindSource();
if (this._initBindSource) this._initBindSource();
if (!target.getBindData) exports.extend(target, BindSource);
this._bind_ready();
target.addBind(this._settings.id, rule, format);
this._bind_source = target._settings.id;
this._bind_id = this._settings.id; //FIXME - check for touchable is not the best solution, to detect necessary event
this._bind_refresh_handler = this.attachEvent(this.touchable ? "onAfterRender" : "onBindRequest", function () {
return target.getBindData(this._bind_id);
});
if (this.refresh && this.isVisible(this._bind_id)) this.refresh();
},
unbind: function () {
if (this._bind_source) {
var target = $$(this._bind_source);
if (target) target.removeBind(this._bind_id);
this.detachEvent(this._bind_refresh_handler);
this._bind_source = this._bind_refresh_handler = null;
}
},
_bind_ready: function () {
var config = this._settings;
if (this.filter) {
var key = config.id;
this.data._on_sync = bind(function () {
$$(this._bind_source)._bind_updated[key] = false;
}, this);
}
var old_render = this.render;
this.render = function () {
if (this._in_bind_processing) return;
this._in_bind_processing = true;
var result = this.callEvent("onBindRequest");
this._in_bind_processing = false;
return old_render.apply(this, result === false ? arguments : []);
};
if (this.getValue || this.getValues) this.save = function (data) {
var source = $$(this._bind_source);
if (data) source.setBindData(data);else {
if (this.validate && !this.validate()) return false;
var values = this.getValue ? this.getValue : this.getValues();
source.setBindData(values, this._settings.id); //reset form, so it will be counted as saved
if (this.setDirty) this.setDirty(false);
}
};
this._bind_ready = function () {};
}
};
var UIExtension = window.webix_view || {};
var api = {
name: "baseview",
//attribute , which will be used for ID storing
$init: function (config) {
if (!config.id) config.id = _uid(this.name);
this._parent_cell = state._parent_cell;
state._parent_cell = null; // if scope not provided directly, and there is no parent view
// check if we have a global scope
this.$scope = config.$scope || (this._parent_cell ? this._parent_cell.$scope : state._global_scope);
if (!this._viewobj) {
this._contentobj = this._viewobj = create("DIV", {
"class": "webix_view"
});
this.$view = this._viewobj;
}
},
$skin: false,
defaults: {
width: 0,
height: 0,
gravity: 1
},
getNode: function () {
return this._viewobj;
},
// needed only to maintain the deprecated ActiveContent module
// do not use it anywhere else
$setNode: function (node) {
this._viewobj = this._dataobj = this.$view = node;
},
getParentView: function () {
return this._parent_cell || null;
},
getTopParentView: function () {
var parent = this.getParentView();
return parent ? parent.getTopParentView() : this;
},
getFormView: function () {
var parent = this.getParentView();
return !parent || parent._recollect_elements ? parent : parent.getFormView();
},
getChildViews: function () {
return [];
},
queryView: function (search, all) {
var confirm;
if (typeof search === "string") search = {
view: search
};
if (_typeof(search) === "object") {
//IE8 compatibility
confirm = function (test) {
var config = test.config;
for (var key in search) {
if (config[key] != search[key]) return false;
}
return true;
};
} else confirm = search;
if (all === "self" && confirm(this)) return this;
var results = all === "all" ? [] : false;
var direction = all === "parent" ? this._queryGoUp : this._queryGoDown;
var found = this._queryView(confirm, direction, results);
return all === "all" ? results : found;
},
_queryGoDown: function (node) {
return node.getChildViews();
},
_queryGoUp: function (node) {
var parent = node.getParentView();
return parent ? [parent] : [];
},
_queryView: function (confirm, next, all) {
var kids = next(this);
for (var i = 0; i < kids.length; i++) {
if (confirm(kids[i])) {
if (all) all.push(kids[i]);else return kids[i];
}
var sub = kids[i]._queryView(confirm, next, all);
if (sub && !all) {
return sub;
}
}
return null;
},
isVisible: function (base_id) {
if (this._settings.hidden) {
if (base_id) {
if (!this._hidden_render) {
this._hidden_render = [];
this._hidden_hash = {};
}
if (!this._hidden_hash[base_id]) {
this._hidden_hash[base_id] = true;
this._hidden_render.push(base_id);
}
}
return false;
}
var parent = this.getParentView();
if (parent) return parent.isVisible(base_id, this._settings.id);
return true;
},
isEnabled: function () {
if (this._disable_cover) return false;
var parent = this.getParentView();
if (parent) return parent.isEnabled();
return true;
},
_fix_cover: function () {
if (this._disable_cover && !this._disable_cover.parentNode) this._viewobj.appendChild(this._disable_cover);
},
disable: function () {
remove(this._disable_cover);
this._settings.disabled = true;
this._disable_cover = create("div", {
"class": "webix_disabled"
});
this._viewobj.appendChild(this._disable_cover);
this._viewobj.setAttribute("aria-disabled", "true");
addCss(this._viewobj, "webix_disabled_view", true);
UIManager._moveChildFocus(this);
},
enable: function () {
this._settings.disabled = false;
if (this._disable_cover) {
remove(this._disable_cover);
removeCss(this._viewobj, "webix_disabled_view");
this._viewobj.removeAttribute("aria-disabled");
this._disable_cover = null;
}
},
disabled_setter: function (value) {
if (value) this.disable();else this.enable();
return value;
},
container_setter: function (value) {
assert(toNode(value), "Invalid container");
return true;
},
css_setter: function (value) {
if (_typeof(value) == "object") value = createCss(value);
this._viewobj.className += " " + value;
return value;
},
id_setter: function (value) {
if (state._global_collection && (state._global_collection != this || this._prev_global_col)) {
var oldvalue = this.config.$id = value;
(this._prev_global_col || state._global_collection)._elements[value] = this;
value = _uid(this.name);
(this._prev_global_col || state._global_collection)._translate_ids[value] = oldvalue;
}
assert(!ui.views[value], "Non unique view id: " + value);
ui.views[value] = this;
this._viewobj.setAttribute(
/*@attr*/
"view_id", value);
return value;
},
$setSize: function (x, y) {
var last = this._last_size;
if (last && last[0] == x && last[1] == y) {
debug_size_box(this, [x, y, "not changed"]);
return false;
}
debug_size_box(this, [x, y]);
this._last_size = [x, y];
this.$width = this._content_width = x - (this._scroll_y ? env.scrollSize : 0);
this.$height = this._content_height = y - (this._scroll_x ? env.scrollSize : 0);
var config = this._settings;
if (!config.flex) {
this._viewobj.style.width = x + "px";
this._viewobj.style.height = y + "px";
}
return true;
},
$getSize: function (dx, dy) {
var s = this._settings;
var size = [(s.width || s.minWidth || 0) * 1, (s.width || s.maxWidth || 100000) * 1, (s.height || s.minHeight || 0) * 1, (s.height || s.maxHeight || 100000) * 1, s.gravity];
if (assert) {
var check = isNaN(size[0]) || isNaN(size[1]) || isNaN(size[2]) || isNaN(size[3]);
if (check) {
assert(false, "Size is not a number " + this._settings.id);
s.width = s.height = s.maxWidth = s.maxHeight = s.minWidth = s.minHeight = 0;
size = [0, 0, 100000, 100000, 1];
}
}
size[0] += dx;
size[1] += dx;
size[2] += dy;
size[3] += dy;
return size;
},
show: function (force, animate_settings) {
var parent = this.getParentView();
var show = !arguments[2];
if (parent) {
if (!animate_settings && animate_settings !== false && this._settings.animate) if (parent._settings.animate) animate_settings = exports.extend(parent._settings.animate ? exports.extend({}, parent._settings.animate) : {}, this._settings.animate, true);
if (show ? parent._show : parent._hide) (show ? parent._show : parent._hide).call(parent, this, animate_settings);
if (show) this._render_hidden_views(); //force show of parent view
//stop further processing is view is a part of isolated scope
if (force && show) parent.show(parent.$$ ? false : force);
} else {
if (this._settings.hidden) {
if (show) {
var node = toNode(this._settings._container || document.body);
node.appendChild(this._viewobj);
this._settings.hidden = false;
this.adjust();
if (this.callEvent) {
this.callEvent("onViewShow", []);
if (this._signal_hidden_cells) _each(this, this._signal_hidden_cells);
}
this._render_hidden_views();
}
} else {
if (!show) {
this._settings.hidden = this._settings._hidden = true;
if (this._viewobj) {
this._settings._container = this._viewobj.parentNode;
remove(this._viewobj);
}
}
}
}
},
_render_hidden_views: function () {
if (this._hidden_render) {
for (var i = 0; i < this._hidden_render.length; i++) {
var ui_to_render = $$(this._hidden_render[i]);
if (ui_to_render) ui_to_render.render();
}
this._hidden_render = [];
this._hidden_hash = {};
}
},
_onKeyPress: function (code, e) {
var target = e.target,
role = target.getAttribute("role");
if ((code === 13 || code === 32) && (role == "button" || role == "tab") && !this._settings.disabled) {
triggerEvent(target, "MouseEvents", "click");
preventEvent(e);
}
},
hidden_setter: function (value) {
if (value) this.hide();
return this._settings.hidden;
},
hide: function () {
this.show(null, null, true);
UIManager._moveChildFocus(this);
},
adjust: function () {
if (!this._viewobj.parentNode) return false;
var x = this._viewobj.parentNode.clientWidth || 0;
var y = this._viewobj.parentNode.clientHeight || 0;
var sizes = this.$getSize(0, 0);
var fullscreen = this._viewobj.parentNode == document.body && !this.setPosition; //minWidth
if (sizes[0] > x) x = sizes[0]; //minHeight
if (sizes[2] > y) y = sizes[2]; //maxWidth rule
if ((!fullscreen || this._settings.width) && x > sizes[1]) x = sizes[1]; //maxHeight rule
if ((!fullscreen || this._settings.height) && y > sizes[3]) y = sizes[3];
this.$setSize(x, y);
if (state._responsive_exception) {
state._responsive_exception = false;
this.adjust();
}
},
resize: function () {
if (state._child_sizing_active || state._freeze_resize || state._responsive_tinkery) return;
var parent = this.getParentView();
if (parent) {
if (parent.resizeChildren) parent.resizeChildren();else parent.resize();
} else {
this.adjust();
callEvent("onResize", []);
}
}
};
var view = exports.protoUI(api, Settings, Destruction, BaseBind, UIExtension);
var base = {
api: api,
view: view
};
var api$1 = {
name: "view",
$init: function (config) {
this._set_inner(config);
},
//deside, will component use borders or not
_set_inner: function (config) {
var border_not_set = isUndefined(config.borderless);
if (border_not_set && !this.setPosition && config.$topView) {
config.borderless = true;
border_not_set = false;
}
if (border_not_set && this.defaults.borderless || config.borderless) {
//button and custom borderless
config._inner = {
top: true,
left: true,
bottom: true,
right: true
};
} else {
//default borders
if (!config._inner) config._inner = {};
this._contentobj.style.borderWidth = "1px";
}
},
$getSize: function (dx, dy) {
var _borders = this._settings._inner;
if (_borders) {
dx += (_borders.left ? 0 : 1) + (_borders.right ? 0 : 1);
dy += (_borders.top ? 0 : 1) + (_borders.bottom ? 0 : 1);
}
var size = base.api.$getSize.call(this, dx, dy);
debug_size_box(this, size, true);
return size;
},
$setSize: function (x, y) {
debug_size_box(this, [x, y]);
var _borders = this._settings._inner;
if (_borders) {
x -= (_borders.left ? 0 : 1) + (_borders.right ? 0 : 1);
y -= (_borders.top ? 0 : 1) + (_borders.bottom ? 0 : 1);
}
return base.api.$setSize.call(this, x, y);
}
};
var view$1 = exports.protoUI(api$1, base.view);
var base$1 = {
api: api$1,
view: view$1
}; //not necessary anymore
//preserving for backward compatibility
view$1.call(-1);
/*
REnders single item.
Can be used for elements without datastore, or with complex custom rendering logic
@export
render
*/
var SingleRender = exports.proto({
$init: function () {
this.type = clone(this.type);
},
customize: function (obj) {
type(this, obj);
},
template_setter: function (value) {
this.type.template = template(value);
},
//convert item to the HTML text
_toHTML: function (obj) {
var type$$1 = this.type;
return (type$$1.templateStart ? type$$1.templateStart(obj, type$$1) : "") + type$$1.template(obj, type$$1) + (type$$1.templateEnd ? type$$1.templateEnd(obj, type$$1) : "");
}
}, AtomRender);
/*
UI: Tooltip
@export
show
hide
*/
// #include core/template.js
// #include core/single_render.js
var api$2 = {
name: "tooltip",
defaults: {
dy: 0,
dx: 20
},
$init: function (config) {
if (typeof config == "string") {
config = {
template: config
};
} //create container for future tooltip
this.$view = this._viewobj = this._contentobj = this._dataobj = create("DIV", {
role: "alert",
"aria-atomic": "true"
});
this._viewobj.className = this._css_name;
insertBefore(this._contentobj, document.body.firstChild, document.body);
},
adjust: function () {},
isVisible: function () {
return this._visible;
},
_alt_render: function (text) {
if (this.callEvent("onBeforeRender", [text])) {
//it is critical to have this as two commands
//its prevent destruction race in Chrome
this._dataobj.innerHTML = "";
this._dataobj.innerHTML = text;
this.callEvent("onAfterRender", []);
}
},
_css_name: "webix_tooltip",
css_setter: function (value) {
if (_typeof(value) === "object") value = createCss(value);
this._viewobj.className = this._css_name + " " + value;
return value;
},
//show tooltip
//pos - object, pos.x - left, pox.y - top
show: function (data, pos$$1) {
if (this._disabled) return;
this._visible = true;
if (typeof data === "string") this._alt_render(data);else {
this.data = exports.extend({}, data);
this.render();
}
if (this._dataobj.firstChild) {
//show at specified position
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
var positionX = w - pos$$1.x;
var positionY = h - pos$$1.y;
this._contentobj.style.display = "block";
if (positionX - this._settings.dx > this._contentobj.offsetWidth) positionX = pos$$1.x;else {
positionX = pos$$1.x - this._settings.dx * 2 - this._contentobj.offsetWidth;
if (positionX < 0) positionX = 0;
}
if (positionY - this._settings.dy > this._contentobj.offsetHeight) positionY = pos$$1.y;else {
positionY = pos$$1.y - this._settings.dy * 2 - this._contentobj.offsetHeight;
if (positionY < 0) positionY = 0;
}
this._contentobj.style.left = positionX + this._settings.dx + "px";
this._contentobj.style.top = positionY + this._settings.dy + "px";
} else this.hide();
},
//hide tooltip
hide: function () {
if (this._visible) {
this.data = null; //nulify, to be sure that on next show it will be fresh-rendered
this._contentobj.style.display = "none";
this._visible = false;
}
},
disable: function () {
this._disabled = true;
},
enable: function () {
this._disabled = false;
},
type: {
template: template("{obj.value}"),
templateStart: template.empty,
templateEnd: template.empty
}
};
var view$2 = exports.protoUI(api$2, SingleRender, Settings, EventSystem, base$1.view);
/*
Behavior: AutoTooltip - links tooltip to data driven item
*/
var AutoTooltip = {
tooltip_setter: function (value) {
if (value) {
if (typeof value === "function" || typeof value === "string") value = {
template: value
};
if (_typeof(value) !== "object") value = {};
if (value.overflow && isUndefined(value.template)) value.template = "";
this._init_tooltip_once();
return value;
} else if (this._settings.tooltip) return {
template: ""
};
},
_init_tooltip_once: function () {
TooltipControl.addTooltip(this);
this.attachEvent("onDestruct", function () {
TooltipControl.removeTooltip(this);
});
this.attachEvent("onAfterScroll", function () {
if (TooltipControl._tooltip_exist) TooltipControl._hide_tooltip();
});
this._init_tooltip_once = function () {};
},
$tooltipIn: function (t) {
var tooltip = TooltipControl._tooltip;
var def = exports.extend({
dx: 20,
dy: 0,
template: "{obj.value}",
css: ""
}, this._settings.tooltip, true);
tooltip.define(def);
return t;
},
$tooltipOut: function () {
TooltipControl._hide_tooltip();
return null;
},
$tooltipMove: function (t, e, c) {
var tooltip = this._settings.tooltip;
var overflow = !tooltip || isUndefined(tooltip.overflow) ? TooltipControl.overflow : tooltip.overflow;
var time = !tooltip || isUndefined(tooltip.delay) ? TooltipControl.delay : tooltip.delay;
var text = overflow ? c.overflow : c.first;
if (time > 0) TooltipControl._hide_tooltip();
TooltipControl._before_show_delay = delay(this._show_tooltip, this, [t, e, text], time);
},
_show_tooltip: function (t, e, text) {
var data = text || this._get_tooltip_data(t, e);
if (!data || !this.isVisible()) return;
TooltipControl._tooltip.show(data, pos(e));
},
_get_tooltip_data: function (t, e) {
if (this.locate && this.getItem) {
var id = this.locate(e);
if (!id) return null;
return this.getItem(id);
}
return this._settings;
}
};
var Canvas = exports.proto({
$init: function (container) {
this._canvas_labels = [];
this._canvas_series = !isUndefined(container.series) ? container.series : container.name;
this._obj = toNode(container.container || container);
var width = container.width * (window.devicePixelRatio || 1);
var height = container.height * (window.devicePixelRatio || 1);
var style = container.style || "";
style += ";width:" + container.width + "px;height:" + container.height + "px;";
this._prepareCanvas(container.name, style, width, height, container.title);
},
_prepareCanvas: function (name, style, x, y, title) {
//canvas has the same size as master object
this._canvas = create("canvas", {
title: title,
width: x,
height: y,
canvas_id: name,
style: style || ""
});
this._obj.appendChild(this._canvas);
return this._canvas;
},
getCanvas: function (context) {
var ctx = (this._canvas || this._prepareCanvas(this._contentobj)).getContext(context || "2d");
if (!this._webixDevicePixelRatio) {
this._webixDevicePixelRatio = true;
ctx.scale(window.devicePixelRatio || 1, window.devicePixelRatio || 1);
}
return ctx;
},
_resizeCanvas: function (x, y) {
if (this._canvas) {
this._canvas.setAttribute("width", x * (window.devicePixelRatio || 1));
this._canvas.setAttribute("height", y * (window.devicePixelRatio || 1));
this._canvas.style.width = x + "px";
this._canvas.style.height = y + "px";
this._webixDevicePixelRatio = false;
}
},
renderText: function (x, y, text, css, w) {
if (!text) return; //ignore empty text
if (w) w = Math.max(w, 0);
if (y) y = Math.max(y, 0);
var t = create("DIV", {
"class": "webix_canvas_text" + (css ? " " + css : ""),
"style": "left:" + x + "px; top:" + y + "px;",
"aria-hidden": "true"
}, text);
this._obj.appendChild(t);
this._canvas_labels.push(t); //destructor?
if (w) t.style.width = w + "px";
return t;
},
renderTextAt: function (valign, align, x, y, t, c, w) {
var text = this.renderText.call(this, x, y, t, c, w);
if (text) {
if (valign) {
if (valign == "middle") text.style.top = parseInt(y - text.offsetHeight / 2, 10) + "px";else text.style.top = y - text.offsetHeight + "px";
}
if (align) {
if (align == "left") text.style.left = x - text.offsetWidth + "px";else text.style.left = parseInt(x - text.offsetWidth / 2, 10) + "px";
}
}
return text;
},
clearCanvas: function (skipMap) {
var areas = [];
remove(this._canvas_labels);
this._canvas_labels = [];
if (!skipMap && this._obj._htmlmap) {
//areas that correspond this canvas layer
areas = this._getMapAreas(); //removes areas of this canvas
while (areas.length) {
areas[0].parentNode.removeChild(areas[0]);
areas.splice(0, 1);
}
areas = null; //removes _htmlmap object if all its child nodes are removed
if (!this._obj._htmlmap.getElementsByTagName("AREA").length) {
this._obj._htmlmap.parentNode.removeChild(this._obj._htmlmap);
this._obj._htmlmap = null;
}
} //FF breaks, when we are using clear canvas and call clearRect without parameters
//width|height are used insead of offsetWidth|offsetHeight for hidden canvas (series)
this.getCanvas().clearRect(0, 0, this._canvas.offsetWidth || Math.floor(this._canvas.width / (window.devicePixelRatio || 1)), this._canvas.offsetHeight || Math.floor(this._canvas.height / (window.devicePixelRatio || 1)));
},
toggleCanvas: function () {
this._toggleCanvas(this._canvas.style.display == "none");
},
showCanvas: function () {
this._toggleCanvas(true);
},
hideCanvas: function () {
this._toggleCanvas(false);
},
_toggleCanvas: function (show) {
var areas, i;
for (i = 0; i < this._canvas_labels.length; i++) {
this._canvas_labels[i].style.display = show ? "" : "none";
}
if (this._obj._htmlmap) {
areas = this._getMapAreas();
for (i = 0; i < areas.length; i++) {
if (show) areas[i].removeAttribute("disabled");else areas[i].setAttribute("disabled", "true");
}
} //FF breaks, when we are using clear canvas and call clearRect without parameters
this._canvas.style.display = show ? "" : "none";
},
_getMapAreas: function () {
var res = [],
areas,
i;
areas = this._obj._htmlmap.getElementsByTagName("AREA");
for (i = 0; i < areas.length; i++) {
if (areas[i].getAttribute("userdata") == this._canvas_series) {
res.push(areas[i]);
}
}
return res;
}
});
var animate = function (html_element, config) {
var animation = config;
if (isArray(html_element)) {
for (var i = 0; i < html_element.length; i++) {
if (isArray(config)) animation = config[i];
if (animation.type == "slide") {
if (animation.subtype == "out" && i === 0) {
// next
continue;
}
if (animation.subtype == "in" && i == 1) {
// current
continue;
}
}
if (animation.type == "flip") {
var animation_copy = clone(animation);
if (i === 0) {
// next
animation_copy.type = "flipback";
}
if (i == 1) {
// current
animation_copy.callback = null;
}
animate(html_element[i], animation_copy);
continue;
}
animate(html_element[i], animation);
}
return;
}
var node = toNode(html_element);
if (node._has_animation) animate.end(node, animation);else animate.start(node, animation);
};
animate.end = function (node, animation) {
//stop animation
node.style[env.transitionDuration] = "1ms";
node._has_animation = null; //clear animation wait order, if any
if (state._wait_animate) window.clearTimeout(state._wait_animate); //plan next animation, if any
state._wait_animate = delay(animate, this, [node, animation], 10);
};
animate.isSupported = function () {
return env.transform && env.transition && !env.isOpera;
};
animate.formLine = function (next, current, animation) {
var direction = animation.direction; //sometimes user can initiate animation multiple times ( fast clicking )
//as result animation may be called against already removed from the dom node
if (current.parentNode) current.parentNode.style.position = "relative";
current.style.position = "absolute";
next.style.position = "absolute"; //this is initial shift of second view in animation
//normally we need to have this value as 0
//but FF has bug with animation initially invisible elements
//so we are adjusting this value, to make 1px of second view visible
var defAniPos = env.isFF ? direction == "top" || direction == "left" ? -1 : 1 : 0;
if (direction == "top" || direction == "bottom") {
next.style.left = "0px";
next.style.top = (animation.top || defAniPos) + (direction == "top" ? 1 : -1) * current.offsetHeight + "px";
} else {
next.style.top = (animation.top || 0) + "px";
next.style.left = defAniPos + (direction == "left" ? 1 : -1) * current.offsetWidth + "px";
} // apply 'keepViews' mode, iframe, datatable with x scroll solution
//( keepViews won't work in case of "in" and "out" subtypes )
if (current.parentNode == next.parentNode && animation.keepViews) next.style.display = "";else insertBefore(next, current.nextSibling, current.parentNode);
if (animation.type == "slide" && animation.subtype == "out") {
next.style.left = "0px";
next.style.top = (animation.top || 0) + "px";
current.parentNode.removeChild(current);
insertBefore(current, next.nextSibling, next.parentNode);
}
return [next, current];
};
animate.breakLine = function (line) {
if (arguments[1]) line[1].style.display = "none"; // 'keepViews' multiview mode
else remove(line[1]); // 1 = current
animate.clear(line[0]);
animate.clear(line[1]);
line[0].style.position = "";
};
animate.clear = function (node) {
node.style[env.transform] = "none";
node.style[env.transition] = "none";
node.style.top = node.style.left = "";
};
animate.defaults = {
type: "slide",
delay: "0",
duration: "500",
timing: "ease-in-out",
x: 0,
y: 0
};
animate.start = function (node, animation) {
//getting config object by merging specified and default options
if (typeof animation == "string") animation = {
type: animation
};
animation = Settings._mergeSettings(animation, animate.defaults);
var prefix = env.cssPrefix;
var settings = node._has_animation = animation;
var skew_options, scale_type; //jshint -W086:true
switch (settings.type == "slide" && settings.direction) {
// getting new x, y in case it is slide with direction
case "right":
settings.x = node.offsetWidth;
break;
case "left":
settings.x = -node.offsetWidth;
break;
case "top":
settings.y = -node.offsetHeight;
break;
case "bottom":
default:
settings.y = settings.y || node.offsetHeight;
break;
}
if (settings.type == "flip" || settings.type == "flipback") {
skew_options = [0, 0];
scale_type = "scaleX";
if (settings.subtype == "vertical") {
skew_options[0] = 20;
scale_type = "scaleY";
} else skew_options[1] = 20;
if (settings.direction == "right" || settings.direction == "bottom") {
skew_options[0] *= -1;
skew_options[1] *= -1;
}
}
var duration = settings.duration + "ms " + settings.timing + " " + settings.delay + "ms";
var css_general = prefix + "TransformStyle: preserve-3d;"; // general css rules
var css_transition = "";
var css_transform = "";
switch (settings.type) {
case "fade":
// changes opacity to 0
css_transition = "opacity " + duration;
css_general = "opacity: 0;";
break;
case "show":
// changes opacity to 1
css_transition = "opacity " + duration;
css_general = "opacity: 1;";
break;
case "flip":
duration = settings.duration / 2 + "ms " + settings.timing + " " + settings.delay + "ms";
css_transform = "skew(" + skew_options[0] + "deg, " + skew_options[1] + "deg) " + scale_type + "(0.00001)";
css_transition = "all " + duration;
break;
case "flipback":
settings.delay += settings.duration / 2;
duration = settings.duration / 2 + "ms " + settings.timing + " " + settings.delay + "ms";
node.style[env.transform] = "skew(" + -1 * skew_options[0] + "deg, " + -1 * skew_options[1] + "deg) " + scale_type + "(0.00001)";
node.style.left = "0";
css_transform = "skew(0deg, 0deg) " + scale_type + "(1)";
css_transition = "all " + duration;
break;
case "slide":
// moves object to specified location
var x = settings.x + "px";
var y = settings.y + "px"; // translate(x, y) OR translate3d(x, y, 0)
css_transform = env.translate + "(" + x + ", " + y + (env.translate == "translate3d" ? ", 0" : "") + ")";
css_transition = prefix + "transform " + duration;
break;
default:
break;
} //set styles only after applying transition settings
delay(function () {
node.style[env.transition] = css_transition;
delay(function () {
if (css_general) node.style.cssText += css_general;
if (css_transform) node.style[env.transform] = css_transform;
var transitionEnded = false;
var tid = event$1(node, env.transitionEnd, function (ev) {
node._has_animation = null;
if (settings.callback) settings.callback.call(settings.master || window, node, settings, ev);
transitionEnded = true;
eventRemove(tid);
});
window.setTimeout(function () {
if (!transitionEnded) {
var master = settings.master || window;
node._has_animation = null;
if (!master.$destructed && settings.callback) settings.callback.call(master, node, settings);
transitionEnded = true;
eventRemove(tid);
}
}, (settings.duration * 1 + settings.delay * 1) * 1.3);
});
});
};
var skin = {
topLayout: "space",
//bar in accordion
barHeight: 44,
//!!!Set the same in skin.less!!!
tabbarHeight: 42,
sidebarTitleHeight: 44,
rowHeight: 36,
toolbarHeight: 44,
listItemHeight: 36,
//list, grouplist, dataview, etc.
inputHeight: 38,
buttonHeight: 38,
inputPadding: 3,
menuHeight: 36,
labelTopHeight: 22,
propertyItemHeight: 28,
timelineItemHeight: 70,
unitHeaderHeight: 36,
inputSpacing: 4,
borderWidth: 1,
sliderHandleWidth: 14,
sliderPadding: 10,
sliderBorder: 1,
vSliderPadding: 15,
vSliderHeight: 100,
switchHeight: 22,
switchWidth: 50,
//margin - distance between cells
layoutMargin: {
space: 10,
wide: 10,
clean: 0,
head: 4,
line: -1,
toolbar: 4,
form: 8,
accordion: 2
},
//padding - distance inside cell between cell border and cell content
layoutPadding: {
space: 10,
wide: 0,
clean: 0,
head: 0,
line: 0,
toolbar: 2,
form: 17,
accordion: 0
},
//space between tabs in tabbar
tabMargin: 0,
tabOffset: 0,
tabBottomOffset: 0,
tabTopOffset: 0,
tabBorder: true,
customCheckbox: true,
customRadio: true,
sidebarMarkAll: true,
popupNoPoint: true,
borderlessPopup: true,
popupPadding: 0,
dataPadding: 12,
calendarWeekHeaderHeight: 18,
padding: 0,
accordionType: "accordion",
optionHeight: 32,
timelineColor: "#1CA1C1",
backColor: "#ffffff",
//colorboard
colorPadding: 4
};
var skin$1 = {
topLayout: "space",
//bar in accordion
barHeight: 36,
//!!!Set the same in skin.less!!!
tabbarHeight: 34,
sidebarTitleHeight: 36,
rowHeight: 28,
toolbarHeight: 36,
listItemHeight: 28,
//list, grouplist, dataview, etc.
inputHeight: 30,
buttonHeight: 30,
inputPadding: 3,
menuHeight: 28,
labelTopHeight: 16,
propertyItemHeight: 24,
unitHeaderHeight: 28,
timelineItemHeight: 50,
inputSpacing: 4,
borderWidth: 1,
sliderHandleWidth: 12,
sliderPadding: 10,
sliderBorder: 1,
vSliderPadding: 13,
vSliderHeight: 100,
switchHeight: 20,
switchWidth: 40,
//margin - distance between cells
layoutMargin: {
space: 5,
wide: 5,
clean: 0,
head: 4,
line: -1,
toolbar: 4,
form: 8,
accordion: 2
},
//padding - distance inside cell between cell border and cell content
layoutPadding: {
space: 5,
wide: 0,
clean: 0,
head: 0,
line: 0,
toolbar: 2,
form: 12,
accordion: 0
},
//space between tabs in tabbar
tabMargin: 0,
tabOffset: 0,
tabBottomOffset: 0,
tabTopOffset: 0,
tabBorder: true,
customCheckbox: true,
customRadio: true,
sidebarMarkAll: true,
popupNoPoint: true,
borderlessPopup: true,
popupPadding: 0,
dataPadding: 12,
calendarWeekHeaderHeight: 18,
padding: 0,
accordionType: "accordion",
optionHeight: 24,
timelineColor: "#1CA1C1",
backColor: "#ffffff",
//colorboard
colorPadding: 4
};
var skin$2 = {
topLayout: "space",
//bar in accordion
barHeight: 46,
//!!!Set the same in skin.less!!!
tabbarHeight: 46,
rowHeight: 34,
toolbarHeight: 46,
sidebarTitleHeight: 45,
listItemHeight: 34,
//list, grouplist, dataview, etc.
inputHeight: 38,
buttonHeight: 38,
inputPadding: 3,
menuHeight: 34,
labelTopHeight: 22,
unitHeaderHeight: 20,
propertyItemHeight: 28,
timelineItemHeight: 70,
inputSpacing: 4,
borderWidth: 1,
sliderHandleWidth: 14,
sliderPadding: 10,
sliderBorder: 1,
vSliderPadding: 15,
vSliderHeight: 100,
switchHeight: 22,
switchWidth: 50,
//margin - distance between cells
layoutMargin: {
space: 10,
wide: 10,
clean: 0,
head: 4,
line: -1,
toolbar: 4,
form: 8,
accordion: 10
},
//padding - distance insede cell between cell border and cell content
layoutPadding: {
space: 10,
wide: 0,
clean: 0,
head: 0,
line: 0,
toolbar: 3,
form: 17,
accordion: 0
},
//space between tabs in tabbar
tabMargin: 4,
tabOffset: 0,
tabBottomOffset: 6,
tabTopOffset: 1,
customCheckbox: true,
customRadio: true,
popupPadding: 8,
dataPadding: 10,
calendarWeekHeaderHeight: 24,
padding: 0,
accordionType: "accordion",
optionHeight: 32,
timelineColor: "#3498db",
backColor: "#ffffff",
//colorboard
colorPadding: 4
};
var skin$3 = {
topLayout: "space",
//bar in accordion
barHeight: 34,
//!!!Set the same in skin.less!!!
tabbarHeight: 34,
sidebarTitleHeight: 34,
rowHeight: 24,
toolbarHeight: 34,
listItemHeight: 28,
//list, grouplist, dataview, etc.
unitHeaderHeight: 20,
propertyItemHeight: 24,
timelineItemHeight: 50,
inputHeight: 30,
buttonHeight: 30,
inputPadding: 3,
menuHeight: 28,
labelTopHeight: 16,
inputSpacing: 4,
borderWidth: 1,
sliderHandleWidth: 10,
sliderPadding: 10,
sliderBorder: 1,
vSliderPadding: 13,
vSliderHeight: 100,
switchHeight: 20,
switchWidth: 40,
//margin - distance between cells
layoutMargin: {
space: 5,
wide: 5,
clean: 0,
head: 4,
line: -1,
toolbar: 4,
form: 4,
accordion: 5
},
//padding - distance inside cell between cell border and cell content
layoutPadding: {
space: 5,
wide: 0,
clean: 0,
head: 0,
line: 0,
toolbar: 1,
form: 12,
accordion: 0
},
//space between tabs in tabbar
tabMargin: 3,
tabOffset: 0,
tabBottomOffset: 3,
tabTopOffset: 1,
customCheckbox: true,
customRadio: true,
popupPadding: 8,
dataPadding: 10,
calendarWeekHeaderHeight: 24,
padding: 0,
accordionType: "accordion",
optionHeight: 23,
timelineColor: "#3498db",
backColor: "#ffffff",
//colorboard
colorPadding: 4
};
var skin$4 = {
topLayout: "space",
//bar in accordion
barHeight: 46,
// !!!Set the same in skin.less!!!
tabbarHeight: 46,
rowHeight: 34,
toolbarHeight: 46,
sidebarTitleHeight: 45,
listItemHeight: 34,
// list, grouplist, dataview, etc.
unitHeaderHeight: 20,
inputHeight: 38,
buttonHeight: 38,
inputPadding: 3,
menuHeight: 34,
labelTopHeight: 22,
propertyItemHeight: 28,
timelineItemHeight: 70,
inputSpacing: 4,
borderWidth: 1,
sliderHandleWidth: 14,
sliderPadding: 10,
sliderBorder: 1,
vSliderPadding: 15,
vSliderHeight: 100,
switchHeight: 22,
switchWidth: 50,
//margin - distance between cells
layoutMargin: {
space: 10,
wide: 10,
clean: 0,
head: 4,
line: -1,
toolbar: 8,
form: 8,
accordion: 10
},
//padding - distance inside cell between cell border and cell content
layoutPadding: {
space: 10,
wide: 0,
clean: 0,
head: 0,
line: 0,
toolbar: 3,
form: 17,
accordion: 0
},
//space between tabs in tabbar
tabMargin: 4,
tabOffset: 0,
tabBottomOffset: 6,
tabTopOffset: 1,
customCheckbox: true,
customRadio: true,
popupPadding: 8,
dataPadding: 10,
calendarWeekHeaderHeight: 24,
padding: 0,
accordionType: "accordion",
optionHeight: 32,
timelineColor: "#b300b3",
backColor: "#393939",
//colorboard
colorPadding: 4
};
var $active, $name;
function set$1(name) {
assert(skin$5[name], "Incorrect skin name: " + name);
if ($name === name) return;
skin$5.$active = $active = skin$5[name];
skin$5.$name = $name = name;
if (ui) {
for (var key in ui) {
var view = ui[key];
if (view && view.prototype && view.prototype.$skin) view.prototype.$skin(view.prototype);
}
}
}
var skin$5 = {
set: set$1,
material: skin,
mini: skin$1,
flat: skin$2,
compact: skin$3,
contrast: skin$4
};
set$1(window.webix_skin || "material"); //necessary for skin builder
var Touch = {
config: {
longTouchDelay: 1000,
scrollDelay: 150,
gravity: 500,
deltaStep: 30,
speed: "0ms",
finish: 1500,
ellastic: true
},
limit: function (value) {
Touch._limited = value !== false;
},
disable: function () {
Touch._disabled = true;
},
enable: function () {
Touch._disabled = false;
},
$init: function () {
Touch.$init = function () {};
event$1(document.body, mouse.down, Touch._touchstart, {
passive: false
});
event$1(document.body, mouse.move, Touch._touchmove, {
passive: false
});
event$1(document.body, mouse.up, Touch._touchend);
event$1(document.body, "dragstart", function (e) {
if (Touch._disabled || Touch._limited) return;
return preventEvent(e);
});
Touch._clear_artefacts();
Touch._scroll = [null, null];
Touch.$active = true;
},
_clear_artefacts: function () {
Touch._start_context = Touch._current_context = Touch._prev_context = Touch._scroll_context = null;
Touch._scroll_mode = Touch._scroll_node = Touch._scroll_stat = Touch._long_touched = null; //remove(Touch._scroll);
//Touch._scroll = [null, null];
Touch._delta = {
_x_moment: 0,
_y_moment: 0,
_time: 0
};
if (Touch._css_button_remove) {
removeCss(Touch._css_button_remove, "webix_touch");
Touch._css_button_remove = null;
}
window.clearTimeout(Touch._long_touch_timer);
Touch._was_not_moved = true;
Touch._axis_x = true;
Touch._axis_y = true;
if (!Touch._active_transion) Touch._scroll_end();
},
_touchend: function (e) {
if (Touch._start_context) {
if (!Touch._scroll_mode) {
if (!Touch._long_touched) {
if (Touch._axis_y && !Touch._axis_x) {
Touch._translate_event("onSwipeX");
} else if (Touch._axis_x && !Touch._axis_y) {
Touch._translate_event("onSwipeY");
}
}
} else {
var temp = Touch._get_matrix(Touch._scroll_node);
var x = temp.e;
var y = temp.f;
var finish = Touch.config.finish;
var delta = Touch._get_delta(e, true);
var view = $$(Touch._scroll_node);
var gravity = view && view.$scroll ? view.$scroll.gravity : Touch.config.gravity;
if (delta._time) {
var nx = x + gravity * delta._x_moment / delta._time;
var ny = y + gravity * delta._y_moment / delta._time;
var cnx = Touch._scroll[0] ? Touch._correct_minmax(nx, false, false, Touch._scroll_stat.dx, Touch._scroll_stat.px) : x;
var cny = Touch._scroll[1] ? Touch._correct_minmax(ny, false, false, Touch._scroll_stat.dy, Touch._scroll_stat.py) : y;
var size = Math.max(Math.abs(cnx - x), Math.abs(cny - y));
if (size < 150) finish = finish * size / 150;
if (cnx != x || cny != y) finish = Math.round(finish * Math.max((cnx - x) / (nx - x), (cny - y) / (ny - y)));
var result = {
e: cnx,
f: cny
};
view = $$(Touch._scroll_node);
if (view && view.adjustScroll) view.adjustScroll(result); //finish = Math.max(100,(Touch._fast_correction?100:finish));
finish = Math.max(100, finish);
if (x != result.e || y != result.f) {
Touch._set_matrix(Touch._scroll_node, result.e, result.f, finish + "ms");
if (Touch._scroll_master) Touch._scroll_master._sync_scroll(result.e, result.f, finish + "ms");
Touch._set_scroll(result.e, result.f, finish + "ms");
} else {
Touch._scroll_end();
}
} else Touch._scroll_end();
}
Touch._translate_event("onTouchEnd");
Touch._clear_artefacts();
}
},
_touchmove: function (e) {
if (!Touch._scroll_context || !Touch._start_context) return;
var delta = Touch._get_delta(e);
Touch._translate_event("onTouchMove");
if (Touch._scroll_mode) {
Touch._set_scroll_pos(delta);
} else {
Touch._axis_x = Touch._axis_check(delta._x, "x", Touch._axis_x);
Touch._axis_y = Touch._axis_check(delta._y, "y", Touch._axis_y);
if (Touch._scroll_mode) {
var view = Touch._get_event_view("onBeforeScroll", true);
if (view) {
var data = {};
view.callEvent("onBeforeScroll", [data]);
if (data.update) {
Touch.config.speed = data.speed;
Touch.config.scale = data.scale;
}
}
Touch._init_scroller(delta); //apply scrolling
} else if (env.isMac) {
var _view = $$(Touch._start_context);
if (_view && _view.$hasYScroll && _view.$hasYScroll() && e.cancelable) {
return preventEvent(e);
}
}
}
if (Touch._scroll_mode && e.cancelable) return preventEvent(e);
},
_set_scroll_pos: function () {
if (!Touch._scroll_node) return;
var temp = Touch._get_matrix(Touch._scroll_node);
var prev = Touch._prev_context || Touch._start_context;
var view = $$(Touch._scroll_node);
var ellastic = view && view.$scroll ? view.$scroll.ellastic : Touch.config.ellastic;
if (Touch._scroll[0]) temp.e = Touch._correct_minmax(temp.e - prev.x + Touch._current_context.x, ellastic, temp.e, Touch._scroll_stat.dx, Touch._scroll_stat.px);
if (Touch._scroll[1]) temp.f = Touch._correct_minmax(temp.f - prev.y + Touch._current_context.y, ellastic, temp.f, Touch._scroll_stat.dy, Touch._scroll_stat.py);
Touch._set_matrix(Touch._scroll_node, temp.e, temp.f, "0ms");
if (Touch._scroll_master) Touch._scroll_master._sync_scroll(temp.e, temp.f, "0ms");
Touch._set_scroll(temp.e, temp.f, "0ms");
},
_set_scroll: function (dx, dy, speed) {
var edx = Touch._scroll_stat.px / Touch._scroll_stat.dx * -dx;
var edy = Touch._scroll_stat.py / Touch._scroll_stat.dy * -dy;
if (Touch._scroll[0]) Touch._set_matrix(Touch._scroll[0], edx, 0, speed);
if (Touch._scroll[1]) Touch._set_matrix(Touch._scroll[1], 0, edy, speed);
},
scrollTo: function (node, x, y, speed) {
Touch._set_matrix(node, x, y, speed);
},
_set_matrix: function (node, xv, yv, speed) {
if (!speed) {
node.style[env.transform] = "";
return;
}
Touch._active_transion = true;
if (node) {
var trans = Touch.config.translate || env.translate;
node.style[env.transform] = trans + "(" + Math.round(xv) + "px, " + Math.round(yv) + "px" + (trans == "translate3d" ? ", 0" : "") + ")";
node.style[env.transitionDuration] = speed;
}
},
_get_matrix: function (node) {
var matrix = window.getComputedStyle(node)[env.transform];
var tmatrix;
if (matrix == "none") tmatrix = {
e: 0,
f: 0
};else {
if (window.WebKitCSSMatrix)
/* global WebKitCSSMatrix */
tmatrix = new WebKitCSSMatrix(matrix);else if (window.MSCSSMatrix)
/* global MSCSSMatrix */
tmatrix = new MSCSSMatrix(matrix);else {
// matrix(1, 0, 0, 1, 0, 0) --> 1, 0, 0, 1, 0, 0
var _tmatrix = matrix.replace(/(matrix\()(.*)(\))/gi, "$2"); // 1, 0, 0, 1, 0, 0 --> 1,0,0,1,0,0
_tmatrix = _tmatrix.replace(/\s/gi, "");
_tmatrix = _tmatrix.split(",");
tmatrix = {};
var tkey = ["a", "b", "c", "d", "e", "f"];
for (var i = 0; i < tkey.length; i++) {
tmatrix[tkey[i]] = parseInt(_tmatrix[i], 10);
}
}
}
if (Touch._scroll_master) Touch._scroll_master._sync_pos(tmatrix);
return tmatrix;
},
_correct_minmax: function (value, allow, current, dx, px) {
if (value === current) return value;
var delta = Math.abs(value - current);
var sign = delta / (value - current); // Touch._fast_correction = true;
if (value > 0) return allow ? current + sign * Math.sqrt(delta) : 0;
var max = dx - px;
if (max + value < 0) return allow ? current - Math.sqrt(-(value - current)) : -max; // Touch._fast_correction = false;
return value;
},
_init_scroll_node: function (node) {
if (!node.scroll_enabled) {
node.scroll_enabled = true;
node.parentNode.style.position = "relative";
var prefix = env.cssPrefix;
node.style.cssText += prefix + "transition: " + prefix + "transform; " + prefix + "user-select:none; " + prefix + "transform-style:flat;";
node.addEventListener(env.transitionEnd, Touch._scroll_end, false);
}
},
_init_scroller: function () {
if (Touch._scroll_mode.indexOf("x") != -1) Touch._scroll[0] = Touch._create_scroll("x", Touch._scroll_stat.dx, Touch._scroll_stat.px, "width");
if (Touch._scroll_mode.indexOf("y") != -1) Touch._scroll[1] = Touch._create_scroll("y", Touch._scroll_stat.dy, Touch._scroll_stat.py, "height");
Touch._init_scroll_node(Touch._scroll_node);
window.setTimeout(function () {
Touch._set_scroll_pos();
if (Touch._scroll_stat && !Touch._scroll_stat.hidden) {
if (Touch._scroll[0]) Touch._scroll[0].style.visibility = "visible";
if (Touch._scroll[1]) Touch._scroll[1].style.visibility = "visible";
}
}, 0);
},
_create_scroll: function (mode, dy, py, dim) {
if (dy - py < 2) {
var matrix = Touch._get_matrix(Touch._scroll_node);
var e = mode == "y" ? matrix.e : 0;
var f = mode == "y" ? 0 : matrix.f;
if (!Touch._scroll_master) Touch._set_matrix(Touch._scroll_node, e, f, "0ms");
Touch._scroll_mode = Touch._scroll_mode.replace(mode, "");
return "";
}
var scroll = create("DIV", {
"class": "webix_scroll_" + mode
}, "");
scroll.style.visibility = "hidden";
scroll.style[dim] = Math.max(py * py / dy - 7, 10) + "px";
if (Touch._scroll_stat.left) {
if (mode === "x") scroll.style.left = Touch._scroll_stat.left + "px";else scroll.style.right = -Touch._scroll_stat.left + "px";
}
Touch._scroll_node.parentNode.appendChild(scroll);
return scroll;
},
_axis_check: function (value, mode, old) {
if (value > Touch.config.deltaStep) {
if (Touch._was_not_moved) {
Touch._long_move(mode);
Touch._locate(mode);
if ((Touch._scroll_mode || "").indexOf(mode) == -1) Touch._scroll_mode = "";
}
return false;
}
return old;
},
_scroll_end: function () {
//sending event to the owner of the scroll only
var result, state, view;
view = $$(Touch._scroll_node || this);
if (view) {
if (Touch._scroll_node) result = Touch._get_matrix(Touch._scroll_node);else if (view.getScrollState) {
state = view.getScrollState();
result = {
e: -state.x,
f: -state.y
};
}
callEvent("onAfterScroll", [result]);
if (view.callEvent) view.callEvent("onAfterScroll", [result]);
}
if (!Touch._scroll_mode) {
remove(Touch._scroll);
Touch._scroll = [null, null];
}
Touch._active_transion = false;
},
_long_move: function () {
window.clearTimeout(Touch._long_touch_timer);
Touch._was_not_moved = false;
},
_stop_old_scroll: function (e) {
if (Touch._scroll[0] || Touch._scroll[1]) {
Touch._stop_scroll(e, Touch._scroll[0] ? "x" : "y");
} else return true;
},
_touchstart: function (e) {
var target = e.target;
if (Touch._disabled) return;
Touch._long_touched = null;
Touch._scroll_context = Touch._start_context = mouse.context(e); // in "limited" mode we should have possibility to use slider
var element = $$(e);
if (Touch._limited && !Touch._is_scroll() && !(element && element.$touchCapture)) {
Touch._scroll_context = null;
}
Touch._translate_event("onTouchStart");
if (Touch._stop_old_scroll(e)) Touch._long_touch_timer = window.setTimeout(Touch._long_touch, Touch.config.longTouchDelay);
if (element && element.touchable && (!target.className || target.className.indexOf("webix_view") !== 0)) {
Touch._css_button_remove = element.getNode(e);
addCss(Touch._css_button_remove, "webix_touch");
}
},
_long_touch: function () {
if (Touch._start_context) {
Touch._long_touched = true;
Touch._translate_event("onLongTouch");
callEvent("onClick", [Touch._start_context]); //Touch._clear_artefacts();
}
},
_stop_scroll: function (e, stop_mode) {
Touch._locate(stop_mode);
var scroll = Touch._scroll[0] || Touch._scroll[1];
if (scroll) {
var view = Touch._get_event_view("onBeforeScroll", true);
if (view) view.callEvent("onBeforeScroll", [Touch._start_context, Touch._current_context]);
}
if (scroll && (!Touch._scroll_node || scroll.parentNode != Touch._scroll_node.parentNode)) {
Touch._clear_artefacts();
Touch._scroll_end();
Touch._start_context = mouse.context(e);
}
Touch._touchmove(e);
},
_get_delta: function (e) {
Touch._prev_context = Touch._current_context;
Touch._current_context = mouse.context(e);
Touch._delta._x = Math.abs(Touch._start_context.x - Touch._current_context.x);
Touch._delta._y = Math.abs(Touch._start_context.y - Touch._current_context.y);
if (Touch._prev_context) {
if (Touch._current_context.time - Touch._prev_context.time < Touch.config.scrollDelay) {
Touch._delta._x_moment = Touch._delta._x_moment / 1.3 + Touch._current_context.x - Touch._prev_context.x;
Touch._delta._y_moment = Touch._delta._y_moment / 1.3 + Touch._current_context.y - Touch._prev_context.y;
} else {
Touch._delta._y_moment = Touch._delta._x_moment = 0;
}
Touch._delta._time = Touch._delta._time / 1.3 + (Touch._current_context.time - Touch._prev_context.time);
}
return Touch._delta;
},
_get_sizes: function (node) {
Touch._scroll_stat = {
dx: node.offsetWidth,
dy: node.offsetHeight,
px: node.parentNode.offsetWidth,
py: node.parentNode.offsetHeight
};
},
_is_scroll: function (locate_mode) {
var node = Touch._start_context.target;
if (!env.touch && !env.transition && !env.transform) return null;
while (node && node.tagName != "BODY") {
if (node.getAttribute) {
var mode = node.getAttribute("touch_scroll");
if (mode && (!locate_mode || mode.indexOf(locate_mode) != -1)) return [node, mode];
}
node = node.parentNode;
}
return null;
},
_locate: function (locate_mode) {
var state = this._is_scroll(locate_mode);
if (state) {
Touch._scroll_mode = state[1];
Touch._scroll_node = state[0];
Touch._get_sizes(state[0]);
}
return state;
},
_translate_event: function (name) {
callEvent(name, [Touch._start_context, Touch._current_context]);
var view = Touch._get_event_view(name);
if (view) view.callEvent(name, [Touch._start_context, Touch._current_context]);
},
_get_event_view: function (name, active) {
var view = $$(active ? Touch._scroll_node : Touch._start_context);
if (!view) return null;
while (view) {
if (view.hasEvent && view.hasEvent(name)) return view;
view = view.getParentView();
}
return null;
},
_get_context: function (e) {
if (!e.touches[0]) {
var temp = Touch._current_context;
temp.time = new Date();
return temp;
}
return {
target: e.target,
x: e.touches[0].pageX,
y: e.touches[0].pageY,
time: new Date()
};
},
_get_context_m: function (e) {
return {
target: e.target,
x: e.pageX,
y: e.pageY,
time: new Date()
};
}
};
function touchInit() {
if (env.touch) {
Touch.$init(); //not full screen mode
if (document.body.className.indexOf("webix_full_screen") == -1) Touch.limit(true);
if (env.isSafari) addStyle(".webix_view{ -webkit-overflow-scrolling: touch; }");
if (window.MSCSSMatrix) addStyle(".webix_view{ -ms-touch-action: none; }");
} else {
var id = event$1(document.body, "touchstart", function (ev) {
if (ev.touches.length && ev.touches[0].radiusX > 4) {
env.touch = true;
setMouse(mouse);
touchInit();
for (var key in ui.views) {
var view = ui.views[key];
if (view && view.$touch) view.$touch();
}
}
eventRemove(id);
}, {
capture: true
});
}
}
function setMouse(mouse) {
mouse.down = "touchstart";
mouse.move = "touchmove";
mouse.up = "touchend";
mouse.context = Touch._get_context;
}
ready(touchInit);
var mouse = env.mouse = {
down: "mousedown",
up: "mouseup",
move: "mousemove",
context: Touch._get_context_m
};
if (window.navigator.pointerEnabled) {
mouse.down = "pointerdown";
mouse.move = "pointermove";
mouse.up = "pointerup";
} else if (window.navigator.msPointerEnabled) {
mouse.down = "MSPointerDown";
mouse.move = "MSPointerMove";
mouse.up = "MSPointerUp";
} else if (env.touch) setMouse(mouse);
/*
Behavior:DND - low-level dnd handling
@export
getContext
addDrop
addDrag
DND master can define next handlers
onCreateDrag
onDragIng
onDragOut
onDrag
onDrop
all are optional
*/
var DragControl = {
//has of known dnd masters
_drag_masters: _to_array(["dummy"]),
/*
register drop area
@param node html node or ID
@param ctrl options dnd master
@param master_mode true if you have complex drag-area rules
*/
addDrop: function (node, ctrl, master_mode) {
node = toNode(node);
node.webix_drop = this._getCtrl(ctrl);
if (master_mode) node.webix_master = true;
},
//return index of master in collection
//it done in such way to prevent dnd master duplication
//probably useless, used only by addDrop and addDrag methods
_getCtrl: function (ctrl) {
ctrl = ctrl || DragControl;
var index$$1 = this._drag_masters.find(ctrl);
if (index$$1 < 0) {
index$$1 = this._drag_masters.length;
this._drag_masters.push(ctrl);
if (ctrl.attachEvent) ctrl.attachEvent("onDestruct", function () {
return DragControl.unlink(ctrl);
});
}
return index$$1;
},
unlink: function (ctrl) {
var index$$1 = this._drag_masters.find(ctrl);
if (index$$1 > -1) {
// if active view was destroyed, stop dnd
if (DragControl._active && DragControl._active.webix_drag == index$$1) DragControl._stopDrag(); // if last target was destroyed, reset it and continue dnd
if (DragControl._last && DragControl._last.webix_drop == index$$1) DragControl._last = null;
this._drag_masters[index$$1] = null;
}
},
_createTouchDrag: function (e) {
var dragCtrl = DragControl;
var master = this._getActiveDragMaster(); // for data items only
if (master && master.$longTouchLimit) {
if (!dragCtrl._html && !dragCtrl.createDrag(e)) return;
e.longtouch_drag = true;
var pos$$1 = {
x: e.x,
y: e.y
};
var customPos = dragCtrl.$dragPos(pos$$1, e);
var ctx = dragCtrl._drag_context;
dragCtrl._html.style.top = pos$$1.y + dragCtrl.top + (customPos || !ctx.y_offset ? 0 : ctx.y_offset) + "px";
dragCtrl._html.style.left = pos$$1.x + dragCtrl.left + (customPos || !ctx.x_offset ? 0 : ctx.x_offset) + "px";
}
},
/*
register drag area
@param node html node or ID
@param ctrl options dnd master
*/
addDrag: function (node, ctrl) {
node = toNode(node);
node.webix_drag = this._getCtrl(ctrl);
_event(node, env.mouse.down, this._preStart, {
bind: node
});
_event(node, "dragstart", preventEvent);
},
//logic of drag - start, we are not creating drag immediately, instead of that we hears mouse moving
_preStart: function (e) {
if (DragControl._active) {
//if we have nested drag areas, use the top one and ignore the inner one
if (DragControl._saved_event == e) return;
DragControl._preStartFalse(e);
DragControl.destroyDrag(e);
}
DragControl._active = this;
var evobj = env.mouse.context(e);
DragControl._start_pos = evobj;
DragControl._saved_event = e;
var passive = env.touch ? {
passive: false
} : null;
DragControl._webix_drag_mm = event$1(document.body, env.mouse.move, DragControl._startDrag, passive);
DragControl._webix_drag_mu = event$1(document, env.mouse.up, DragControl._preStartFalse); //need to run here, or will not work in IE
addCss(document.body, "webix_noselect", 1);
},
//if mouse was released before moving - this is not a dnd, remove event handlers
_preStartFalse: function (e) {
DragControl._clean_dom_after_drag();
DragControl._touch_animation = !e.cancelable;
},
//mouse was moved without button released - dnd started, update event handlers
_startDrag: function (e) {
// check touch scroll animation
DragControl._touch_animation = !e.cancelable;
if (env.touch && DragControl._touch_animation) {
DragControl._clean_dom_after_drag();
return DragControl.destroyDrag(e);
} //prevent unwanted dnd
var pos$$1 = env.mouse.context(e);
var master = DragControl._getActiveDragMaster(); // only long-touched elements can be dragged
var longTouchLimit = env.touch && master && master.$longTouchLimit && !Touch._long_touched;
if (longTouchLimit || Math.abs(pos$$1.x - DragControl._start_pos.x) < 5 && Math.abs(pos$$1.y - DragControl._start_pos.y) < 5) return;
if (!DragControl._html && !DragControl.createDrag(DragControl._saved_event)) return DragControl._clean_dom_after_drag();
DragControl._clean_dom_after_drag(true);
DragControl.sendSignal("start"); //useless for now
var passive = env.touch ? {
passive: false
} : null;
DragControl._webix_drag_mm = event$1(document.body, env.mouse.move, DragControl._moveDrag, passive);
DragControl._webix_drag_mu = event$1(document, env.mouse.up, DragControl._stopDrag);
DragControl._moveDrag(e);
},
//mouse was released while dnd is active - process target
_stopDrag: function (e) {
DragControl._clean_dom_after_drag();
DragControl._saved_event = null;
if (DragControl._last && e) {
//if some drop target was confirmed
DragControl.$drop(DragControl._active, DragControl._last, e);
DragControl.$dragOut(DragControl._active, DragControl._last, null, e);
}
DragControl.destroyDrag(e);
DragControl.sendSignal("stop"); //useless for now
},
_clean_dom_after_drag: function (still_drag) {
this._webix_drag_mm = eventRemove(this._webix_drag_mm);
this._webix_drag_mu = eventRemove(this._webix_drag_mu);
if (!still_drag) removeCss(document.body, "webix_noselect");
},
//dnd is active and mouse position was changed
_moveDrag: function (e) {
var dragCtrl = DragControl;
var pos$$1 = pos(e); //give possibility to customize drag position
var customPos = dragCtrl.$dragPos(pos$$1, e); //adjust drag marker position
var ctx = dragCtrl._drag_context;
dragCtrl._html.style.top = pos$$1.y + dragCtrl.top + (customPos || !ctx.y_offset ? 0 : ctx.y_offset) + "px";
dragCtrl._html.style.left = pos$$1.x + dragCtrl.left + (customPos || !ctx.x_offset ? 0 : ctx.x_offset) + "px";
var evobj = e;
if (dragCtrl._skip) dragCtrl._skip = false;else {
if (env.touch) {
var context = env.mouse.context(e);
var target = document.elementFromPoint(context.x, context.y);
evobj = new Proxy(e, {
get: function (obj, prop) {
if (prop === "target") {
return target;
}
var res = obj[prop];
if (typeof res === "function") {
return res.bind(e);
}
return res;
}
});
}
dragCtrl._checkLand(evobj.target, evobj);
}
return preventEvent(e);
},
//check if item under mouse can be used as drop landing
_checkLand: function (node, e) {
while (node && node.tagName != "BODY") {
if (node.webix_drop) {
//if drop area registered
if (this._last && (this._last != node || node.webix_master)) //if this area with complex dnd master
this.$dragOut(this._active, this._last, node, e); //inform master about possible mouse-out
if (!this._last || this._last != node || node.webix_master) {
//if this is new are or area with complex dnd master
this._last = null; //inform master about possible mouse-in
this._landing = this.$dragIn(DragControl._active, node, e);
if (this._landing) //landing was rejected
this._last = node;
return;
}
return;
}
node = node.parentNode;
}
if (this._last) //mouse was moved out of previous landing, and without finding new one
this._last = this._landing = this.$dragOut(this._active, this._last, null, e);
},
//mostly useless for now, can be used to add cross-frame dnd
sendSignal: function (signal) {
DragControl.active = signal == "start";
callEvent("onDragMode", [signal]);
},
//return master for html area
getMaster: function (t) {
return this._drag_masters[t.webix_drag || t.webix_drop];
},
//return dhd-context object
getContext: function () {
return this._drag_context;
},
getNode: function () {
return this._html;
},
//called when dnd is initiated, must create drag representation
createDrag: function (e) {
var dragCtl = DragControl;
var a = dragCtl._active;
dragCtl._drag_context = {};
var master = this._drag_masters[a.webix_drag];
var drag_container; //if custom method is defined - use it
if (master.$dragCreate) {
drag_container = master.$dragCreate(a, e);
if (!drag_container) return false;
this._setDragOffset(e);
drag_container.style.position = "absolute";
} else {
//overvise use default one
var text = dragCtl.$drag(a, e);
dragCtl._setDragOffset(e);
if (!text) return false;
drag_container = document.createElement("DIV");
drag_container.innerHTML = text;
drag_container.className = "webix_drag_zone";
document.body.appendChild(drag_container);
var context = dragCtl._drag_context;
if (context.html && env.pointerevents) {
context.x_offset = -Math.round(drag_container.offsetWidth * 0.5);
context.y_offset = -Math.round(drag_container.offsetHeight * 0.75);
}
}
/*
dragged item must have topmost z-index
in some cases item already have z-index
so we will preserve it if possible
*/
drag_container.style.zIndex = Math.max(drag_container.style.zIndex, zIndex());
DragControl._skipDropH = event$1(drag_container, env.mouse.move, DragControl._skip_mark);
if (!DragControl._drag_context.from) DragControl._drag_context = {
source: a,
from: a
};
DragControl._html = drag_container;
return true;
},
//helper, prevents unwanted mouse-out events
_skip_mark: function () {
DragControl._skip = true;
},
//after dnd end, remove all traces and used html elements
destroyDrag: function (e) {
var a = DragControl._active;
var master = this._drag_masters[a.webix_drag];
if (master && master.$dragDestroy) {
DragControl._skipDropH = eventRemove(DragControl._skipDropH);
if (DragControl._html) master.$dragDestroy(a, DragControl._html, e);
} else remove(DragControl._html);
if (master && master._auto_scroll_delay) master._auto_scroll_delay = window.clearTimeout(master._auto_scroll_delay);
if (DragControl._dropHTML) remove(DragControl._dropHTML);
DragControl._landing = DragControl._active = DragControl._last = DragControl._html = DragControl._dropHTML = null;
DragControl._drag_context = null;
},
_getActiveDragMaster: function () {
return DragControl._drag_masters[DragControl._active.webix_drag];
},
top: 0,
//relative position of drag marker to mouse cursor
left: 0,
_setDragOffset: function (e) {
var dragCtl = DragControl;
var pos$$1 = dragCtl._start_pos;
var ctx = dragCtl._drag_context;
if (typeof ctx.x_offset != "undefined" && typeof ctx.y_offset != "undefined") return null;
ctx.x_offset = ctx.y_offset = 0;
if (env.pointerevents) {
var m = DragControl._getActiveDragMaster();
if (m._getDragItemPos && m !== this) {
var itemPos = m._getDragItemPos(pos$$1, e);
if (itemPos) {
ctx.x_offset = itemPos.x - pos$$1.x;
ctx.y_offset = itemPos.y - pos$$1.y;
}
}
}
},
$dragPos: function (pos$$1, e) {
var m = this._drag_masters[DragControl._active.webix_drag];
if (m.$dragPos && m != this) {
m.$dragPos(pos$$1, e, DragControl._html);
return true;
}
},
//called when mouse was moved in drop area
$dragIn: function (s, t, e) {
var m = this._drag_masters[t.webix_drop];
if (m.$dragIn && m != this) return m.$dragIn(s, t, e);
t.className = t.className + " webix_drop_zone";
return t;
},
//called when mouse was moved out drop area
$dragOut: function (s, t, n, e) {
var m = this._drag_masters[t.webix_drop];
if (m.$dragOut && m != this) return m.$dragOut(s, t, n, e);
t.className = t.className.replace("webix_drop_zone", "");
return null;
},
//called when mouse was released over drop area
$drop: function (s, t, e) {
var m = this._drag_masters[t.webix_drop];
DragControl._drag_context.from = DragControl.getMaster(s);
if (m.$drop && m != this) return m.$drop(s, t, e);
t.appendChild(s);
},
//called when dnd just started
$drag: function (s, e) {
var m = this._drag_masters[s.webix_drag];
if (m.$drag && m != this) return m.$drag(s, e);
return "<div style='" + s.style.cssText + "'>" + s.innerHTML + "</div>";
}
}; //global touch-drag handler
attachEvent("onLongTouch", function (ev) {
if (DragControl._active && !DragControl._touch_animation) DragControl._createTouchDrag(ev);
});
var Movable = {
move_setter: function (value) {
if (value) {
exports.extend(this, Move, true);
DragControl.addDrag(this._headobj ? this._headobj : this.$view, this);
delete this.move_setter; //prevent double initialization
}
return value;
}
};
var Move = {
$dragCreate: function (object, e) {
if (this.config.move) {
var elOffset = offset(object);
var elPos = pos(e);
DragControl.top = elOffset.y - elPos.y;
DragControl.left = elOffset.x - elPos.x;
return toNode(this._viewobj);
}
},
$dragDestroy: function (node, drag) {
var view = this;
if (view._settings) {
view._settings.top = parseInt(drag.style.top, 10);
view._settings.left = parseInt(drag.style.left, 10);
}
DragControl.top = DragControl.left = 0;
this.callEvent("onViewMoveEnd", []);
return;
},
$dragPos: function (pos$$1, e) {
this.callEvent("onViewMove", [pos$$1, e]);
}
};
var Modality = {
_modal_set: function (value) {
if (value) {
if (!this._modal_cover) {
this._modal_cover = create("div", {
"class": "webix_modal"
});
/* with below code we will have the same zIndex for modal layer as for the previous
abs positioned element, but because of attaching order modal layer will be on top anyway
*/
var index$$1 = this._modality = zIndex(this._settings.zIndex);
state._modality.push(index$$1);
this._modal_cover.style.zIndex = index$$1 - 1;
this._viewobj.style.zIndex = index$$1;
document.body.appendChild(this._modal_cover);
document.body.style.overflow = "hidden";
_event(this._modal_cover, "click", bind(this._ignore_clicks, this));
}
} else {
if (this._modal_cover) {
remove(this._modal_cover);
this._modal_cover = null;
var modality = state._modality;
modality.splice(modality.indexOf(this._modality), 1);
if (!modality.length) document.body.style.overflow = "";
}
}
return value;
}
};
var ResizeArea = {
resize_setter: function (value) {
if (value && !this._resizeHandlers) this._renderResizeHandler();
return value;
},
_renderResizeHandler: function () {
if (!this._rwHandle) {
var rp = this._viewobj;
if (rp.firstChild) {
rp = rp.firstChild;
rp.style.position = "relative";
}
this._rwHandle = create("DIV", {
"class": "webix_resize_handle",
/*@attr*/
"webix_disable_drag": "true"
});
rp.appendChild(this._rwHandle);
_event(this._rwHandle, env.mouse.down, this._wrDown, {
bind: this
});
}
},
_showResizeFrame: function (width, height) {
if (!this._resizeFrame) {
this._resizeFrame = create("div", {
"class": "webix_resize_frame"
}, "");
document.body.appendChild(this._resizeFrame);
var elPos = offset(this._viewobj);
this._resizeFrame.style.left = elPos.x + "px";
this._resizeFrame.style.top = elPos.y + "px";
this._resizeFrame.style.zIndex = zIndex();
}
this._resizeFrame.style.width = width + "px";
this._resizeFrame.style.height = height + "px";
},
_wrDown: function () {
if (this.config.resize) {
addCss(document.body, "webix_noselect webix_resize_cursor");
this._wsReady = offset(this._viewobj);
this._resizeHandlersMove = event$1(document.body, env.mouse.move, this._wrMove, {
bind: this
});
this._resizeHandlersUp = event$1(document.body, env.mouse.up, this._wrUp, {
bind: this
});
}
},
_wrMove: function (e) {
if (this._wsReady !== false) {
var elPos = pos(e);
var progress = {
x: elPos.x - this._wsReady.x,
y: elPos.y - this._wsReady.y
};
if (this.$resizeMove) this.$resizeMove(progress);else {
var config = this.config;
var minWidth = config.minWidth || 100;
var minHeight = config.minHeight || 100;
if (progress.x < minWidth) progress.x = minWidth;else if (progress.x > config.maxWidth) progress.x = config.maxWidth;
if (progress.y < minHeight) progress.y = minHeight;else if (progress.y > config.maxHeight) progress.y = config.maxHeight;
}
this._wsProgress = progress;
this._showResizeFrame(progress.x, progress.y);
}
},
_wrUp: function () {
// remove resize frame and css styles
if (this._resizeFrame) this._resizeFrame = remove(this._resizeFrame);
removeCss(document.body, "webix_resize_cursor");
removeCss(document.body, "webix_noselect");
eventRemove(this._resizeHandlersMove);
eventRemove(this._resizeHandlersUp); // set Window sizes
if (this._wsProgress) {
if (this.$resizeEnd) this.$resizeEnd(this._wsProgress);else {
this.config.width = this._wsProgress.x;
this.config.height = this._wsProgress.y;
this.resize();
}
}
this._wsReady = this._wsProgress = false;
this.callEvent("onViewResize", []);
}
};
var api$3 = {
name: "window",
$init: function (config) {
this._viewobj.innerHTML = "<div class='webix_win_content'><div class='webix_win_head'></div><div class='webix_win_body'></div></div>";
this._contentobj = this._viewobj.firstChild;
this._headobj = this._contentobj.childNodes[0];
this._dataobj = this._bodyobj = this._contentobj.childNodes[1];
this._viewobj.className += " webix_window";
this._viewobj.setAttribute("role", "dialog");
this._viewobj.setAttribute("tabindex", "0");
this._head_cell = this._body_cell = null;
this._settings._inner = {
top: false,
left: false,
right: false,
bottom: false
}; //set border flags
if (!config.id) config.id = uid();
_event(this._contentobj, "click", this._ignore_clicks, {
bind: this
});
_event(this._contentobj, "click", function () {
// brings a window to the front of other windows
if (!this._settings.zIndex && this._settings.toFront) {
this._viewobj.style.zIndex = zIndex();
}
}, {
bind: this,
capture: true
}); // hidden_setter handling
if (config.modal) this._modal = true; // head_setter handling
if (config.headHeight) this._settings.headHeight = config.headHeight;
if (config.close) this._settings.close = config.close;
this.attachEvent("onViewMoveEnd", function () {
if (this._settings.position) delete this._settings.position;
});
},
_ignore_clicks: function (e) {
var popups = state._popups;
var index$$1 = popups.find(this);
if (index$$1 == -1) index$$1 = popups.length - 1;
e.click_view = index$$1;
},
getChildViews: function () {
if (this._head_cell) return [this._head_cell, this._body_cell];else return [this._body_cell];
},
zIndex_setter: function (value) {
this._viewobj.style.zIndex = value;
return value;
},
_remove: function () {
this.body_setter();
},
_replace: function (new_view, old_view) {
old_view = old_view || this._body_cell;
var isBody = old_view == this._body_cell;
old_view.destructor();
if (isBody) this._body_cell = new_view;else this._head_cell = new_view;
(isBody ? this._bodyobj : this._headobj).appendChild(new_view._viewobj);
var cell = new_view._viewobj.style;
var settings = {
top: true,
left: true,
right: true,
bottom: true
};
var size = "0px";
if (new_view.config.borderless === false) {
settings = clone(this._settings._inner);
size = "1px";
}
new_view._settings._inner = settings;
cell.borderTopWidth = cell.borderBottomWidth = cell.borderLeftWidth = cell.borderRightWidth = size;
this.resize(true);
},
show: function (node, mode, point) {
if (node === true) {
//recursive call from some child item
if (!this._settings.hidden) return;
node = null;
}
if (!this.callEvent("onBeforeShow", arguments)) return false;
this._settings.hidden = false;
this._viewobj.style.zIndex = zIndex(this._settings.zIndex);
if (this._settings.modal || this._modal) {
this._modal_set(true);
this._modal = null; // hidden_setter handling
}
var elPos, dx, dy;
mode = mode || {};
if (!mode.pos) mode.pos = this._settings.relative; //get position of source html node
//we need to show popup which pointing to that node
if (node) {
//if event was provided - get node info from it
if (_typeof(node) == "object" && !node.tagName) {
/*below logic is far from ideal*/
if (node.target) {
elPos = pos(node);
dx = 20;
dy = 5;
} else elPos = node;
} else {
node = toNode(node);
assert(node, "Not existing target for window:show");
elPos = offset(node);
} //size of body, we need to fit popup inside
var x = Math.max(window.innerWidth || 0, document.body.offsetWidth);
var y = Math.max(window.innerHeight || 0, document.body.offsetHeight); //size of node, near which popup will be rendered
dx = dx || node.offsetWidth || 0;
dy = dy || node.offsetHeight || 0; //size of popup element
var size = this._last_size;
var fin_x = elPos.x;
var fin_y = elPos.y;
var point_y = 0;
var point_x = 0;
var scrollLeft = 0,
scrollTop = 0;
var fit = this._settings.autofit;
if (fit) {
var nochange = fit === "node";
var delta_x = 6,
delta_y = 6,
delta_point = 6;
if (!this._settings.point) delta_x = delta_y = delta_point = 0; //default pointer position - top
point = "top";
fin_y = 0;
fin_x = 0;
scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft; //if we want to place menu at righ, but there is no place move it to left instead
if (x - elPos.x - dx < size[0] && mode.pos == "right" && !nochange) mode.pos = "left";
if (mode.pos == "right") {
fin_x = elPos.x + delta_x + dx;
delta_y = -dy;
point = "left";
point_y = Math.round(elPos.y + dy / 2);
point_x = fin_x - delta_point;
} else if (mode.pos == "left") {
fin_x = elPos.x - delta_x - size[0] - 1;
delta_y = -dy;
point = "right";
point_y = Math.round(elPos.y + dy / 2);
point_x = fin_x + size[0] + 1;
} else {
//left border of screen
if (elPos.x < scrollLeft) {
fin_x = scrollLeft; //popup exceed the right border of screen
} else if (x + scrollLeft - elPos.x > size[0]) {
fin_x = elPos.x; //aligned
} else {
fin_x = x + scrollLeft - delta_x - size[0]; //not aligned
}
point_x = Math.round(elPos.x + dx / 2); //when we have a small popup, point need to be rendered at center of popup
point_x = Math.min(point_x, fin_x + size[0] - delta_point * 3);
} //if height is not fixed - use default position
scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
if ((!size[1] || y + scrollTop - dy - elPos.y - delta_y > size[1] || nochange) && mode.pos != "top") {
//bottom
fin_y = dy + elPos.y + delta_y - (!this._settings.point ? 0 : 4);
if (!point_y) {
point = "top";
point_y = fin_y - delta_point;
}
} else {
//top
fin_y = elPos.y - delta_y - size[1];
if (fin_y < 0) {
fin_y = 0; //left|right point can be used, but there is no place for top point
if (point == "top") point = false;
} else if (!point_y) {
point = "bottom";
fin_y--;
point_y = fin_y + size[1] + 1;
}
}
}
var deltax = mode.x || 0;
var deltay = mode.y || 0;
var fixed = this._checkFixedPosition();
this.$view.style.position = fixed ? "fixed" : "absolute";
if (fixed) {
fin_y = fin_y - scrollTop;
point_y = point_y - scrollTop;
}
this.setPosition(fin_x + deltax, fin_y + deltay);
if (this._set_point) {
if (point && this._settings.point) this._set_point(point, point_x + deltax, point_y + deltay, fixed);else this._hide_point();
}
} else this._setPosition(this._settings.left, this._settings.top);
this._viewobj.style.display = "block";
this._hide_timer = 1;
delay(function () {
this._hide_timer = 0;
}, this, [], env.touch ? 400 : 100);
this._render_hidden_views();
if (this.config.autofocus) {
this._prev_focus = UIManager.getFocus();
UIManager.setFocus(this);
}
if (-1 == state._popups.find(this)) state._popups.push(this);
this.callEvent("onShow", []);
},
_hide: function (e) {
//do not hide modal windows
if (this._settings.hidden || this._settings.modal || !this._settings.escHide || this._hide_timer) return; //do not hide submenu when clicking on menu folder
if (e && e.showpopup && (e.showpopup == this._settings.id || this.getTopMenu && this.getTopMenu()._settings.id == e.showpopup)) return; //do not hide popup, when starting dnd with a long touch
if (e && env.touch && e.longtouch_drag) return; //do not hide popup, when we have modal layer above the popup
if (state._modality.length && this._viewobj.style.zIndex <= Math.max.apply(Math, _toConsumableArray(state._modality))) return; //ignore inside clicks and clicks in child-popups
if (e) {
var index$$1 = e.click_view;
if (!index$$1 && index$$1 !== 0) index$$1 = -1;
var myindex = state._popups.find(this);
if (myindex <= index$$1) return;
}
this._hide_single();
},
hidden_setter: function (value) {
if (value) this.hide();else this.show();
return !!value;
},
hide: function () {
var index$$1 = this._hide_single();
this._hide_sub_popups(index$$1);
},
_hide_single: function () {
if (this.$destructed || this._settings.hidden) return;
if (this._settings.modal) this._modal_set(false);
this._hiding_process();
if (this._settings.autofocus) {
var el = document.activeElement; //as result of hotkey, we can have a activeElement set to document.body
if (el && this._viewobj && (this._viewobj.contains(el) || el === document.body)) {
UIManager.setFocus(this._prev_focus);
this._prev_focus = null;
}
} // clear state
var index$$1 = state._popups.find(this);
if (index$$1 > -1) state._popups.removeAt(index$$1);
return index$$1;
},
_hiding_process: function () {
if (this._settings.position == "top") {
animate(this._viewobj, {
type: "slide",
x: 0,
y: -(this._content_height + 20),
duration: 300,
callback: this._hide_callback,
master: this
});
} else this._hide_callback();
},
//hide all child-popups
_hide_sub_popups: function (index$$1) {
if (index$$1 > -1) {
var order = state._popups;
for (var i = order.length - 1; i >= index$$1; i--) {
if (order[i]._hide_point) //hide only popups, skip windows
order[i]._hide_single();
}
}
},
destructor: function () {
this.hide();
Destruction.destructor.apply(this, []);
},
_hide_callback: function () {
if (!this.$destructed) {
this._viewobj.style.display = "none";
this._settings.hidden = true;
this.callEvent("onHide", []);
}
},
close: function () {
this.destructor();
},
_inner_body_set: function (value) {
if (typeof value.borderless == "undefined") value.borderless = true;
},
body_setter: function (value) {
if (_typeof(value) != "object") value = {
template: value
};
this._inner_body_set(value);
state._parent_cell = this;
this._body_cell = ui._view(value);
this._bodyobj.appendChild(this._body_cell._viewobj);
return value;
},
head_setter: function (value) {
var _this = this;
if (value === false) return value;
var height = this._settings.headHeight;
var text = typeof value == "string";
var config = {
height: height,
padding: 0,
css: "webix_win_title",
type: "header",
borderless: true
};
if (text) {
this._viewobj.setAttribute("aria-label", value);
value = {
template: value
};
}
if (value.view == "template" || !value.view && value.template) {
exports.extend(value, config);
}
if (text && this.config.close) {
value = {
padding: {
left: $active.inputHeight + 2,
right: 2
},
cols: [value, {
height: height,
view: "icon",
icon: "wxi-close",
click: function () {
_this.hide();
}
}]
};
} else exports.extend(value, {
borderless: true
});
state._parent_cell = this;
this._head_cell = ui._view(value);
var template = this._head_cell._viewobj.querySelector(".webix_win_title>div");
if (template) template.style.lineHeight = height + "px";
this._headobj.appendChild(this._head_cell._viewobj);
return value;
},
getBody: function () {
return this._body_cell;
},
getHead: function () {
return this._head_cell;
},
adjust: function () {
return this.resize();
},
resizeChildren: function () {
if (this._body_cell) this.resize();
},
resize: function () {
base.api.adjust.call(this);
callEvent("onResize", []);
if (this.isVisible()) {
this._setPosition(this._settings.left, this._settings.top);
}
},
_checkFixedPosition: function () {
if (this._settings.master) {
var top = $$(this._settings.master).getTopParentView().$view;
return top && top.style.position === "fixed";
}
return false;
},
_setPosition: function (x, y) {
if (this._settings.position || this._checkFixedPosition()) {
this.$view.style.position = "fixed";
var width = this._content_width;
var height = this._content_height;
if (width <= 0 || height <= 0) return;
var maxWidth = window.innerWidth || document.documentElement.offsetWidth;
var maxHeight = window.innerHeight || document.documentElement.offsetHeight;
var left = Math.round((maxWidth - width) / 2);
var top = Math.round((maxHeight - height) / 2);
if (typeof this._settings.position == "function") {
var _state = {
left: left,
top: top,
width: width,
height: height,
maxWidth: maxWidth,
maxHeight: maxHeight
};
this._settings.position.call(this, _state);
if (_state.width != width || _state.height != height) this.$setSize(_state.width, _state.height);
this.setPosition(_state.left, _state.top);
} else {
if (this._settings.position == "top") {
if (animate.isSupported()) top = -1 * height;else top = 10;
} //popup inside a fixed win
if (!this._settings.position) {
left = this._settings.left || left;
top = this._settings.top || top;
}
this.setPosition(left, top);
}
if (this._settings.position == "top") animate(this._viewobj, {
type: "slide",
x: 0,
y: height - (this._settings.padding || 0) * 2,
duration: 300,
callback: this._topPositionCallback,
master: this
});
} else this.setPosition(x, y);
},
_topPositionCallback: function (node) {
animate.clear(node);
this._settings.top = -((this._settings.padding || 0) * 2);
this.setPosition(this._settings.left, this._settings.top);
},
setPosition: function (x, y) {
this._viewobj.style.top = y + "px";
this._viewobj.style.left = x + "px";
this._settings.left = x;
this._settings.top = y;
},
$getSize: function (dx, dy) {
var _borders = this._settings._inner;
if (_borders) {
dx += (_borders.left ? 0 : 1) + (_borders.right ? 0 : 1);
dy += (_borders.top ? 0 : 1) + (_borders.bottom ? 0 : 1);
} //line between head and body
if (this._settings.head) dy += 1;
var size = this._body_cell.$getSize(0, 0);
var headMinWidth = 0;
if (this._head_cell) {
var head_size = this._head_cell.$getSize(0, 0);
if (head_size[3] == head_size[2]) this._settings.headHeight = head_size[3];
dy += this._settings.headHeight;
headMinWidth = head_size[0];
}
if (this._settings.fullscreen) {
var width = window.innerWidth || document.body.clientWidth;
var height = window.innerHeight || document.body.clientHeight;
return [width, width, height, height];
} //get layout sizes
var self_size = base$1.api.$getSize.call(this, 0, 0); //use child settings if layout's one was not defined
if (headMinWidth && size[1] > 100000) size[0] = Math.max(headMinWidth, size[0]);
self_size[1] = Math.min(self_size[1], (size[1] >= 100000 && self_size[1] >= 100000 ? Math.max(size[0], self_size[0]) : size[1]) + dx);
self_size[3] = Math.min(self_size[3], (size[3] >= 100000 && self_size[3] >= 100000 ? Math.max(size[2], self_size[2]) : size[3]) + dy);
self_size[0] = Math.min(Math.max(self_size[0], size[0] + dx), self_size[1]);
self_size[2] = Math.min(Math.max(self_size[2], size[2] + dy), self_size[3]);
return self_size;
},
$setSize: function (x, y) {
base$1.api.$setSize.call(this, x, y);
x = this._content_width;
y = this._content_height;
if (this._settings.head === false) {
this._headobj.style.display = "none";
this._body_cell.$setSize(x, y);
} else {
this._head_cell.$setSize(x, this._settings.headHeight);
this._body_cell.$setSize(x, y - this._settings.headHeight);
}
},
$skin: function () {
this.defaults.headHeight = $active.barHeight;
},
defaults: {
top: 0,
left: 0,
autofit: true,
relative: "bottom",
body: "",
head: "",
hidden: true,
autofocus: true,
minWidth: 300,
minHeight: 200,
escHide: true
}
}; //global longtouch handler
attachEvent("onLongTouch", function (ev) {
if (!ev || !ev.target) return;
var view = $$(ev.target);
if (view) {
view = view.queryView(function (a) {
return !a.getParentView();
}, "parent") || view;
var popups = state._popups;
var index$$1 = popups.find(view);
if (index$$1 !== -1) ev.click_view = index$$1;
}
});
var view$3 = exports.protoUI(api$3, base$1.view, Movable, Modality, EventSystem, ResizeArea);
var window$1 = {
api: api$3,
view: view$3
};
var ContextHelper = {
defaults: {
padding: "4",
hidden: true
},
body_setter: function (value) {
value = window$1.api.body_setter.call(this, value);
this._body_cell._viewobj.style.borderWidth = "0px";
return value;
},
attachTo: function (obj) {
assert(obj, "Invalid target for Context::attach");
var id;
if (obj.on_context) id = obj.attachEvent("onAfterContextMenu", bind(this._show_at_ui, this));else id = event$1(obj, "contextmenu", this._show_at_node, {
bind: this
});
this.attachEvent("onDestruct", function () {
if (obj.callEvent) obj.detachEvent(id);else eventRemove(id);
obj = null;
});
},
getContext: function () {
return this._area;
},
setContext: function (area) {
this._area = area;
},
_show_at_node: function (e) {
this._area = toNode(e || window$1.event);
return this._show_at(e);
},
_show_at_ui: function (id, e) {
this._area = {
obj: $$(e),
id: id
};
return this._show_at(e);
},
_show_at: function (e) {
var result = this.show(e, null, true);
if (result === false) return result; // ignore contexmenu clicks for the popup or its body
var view = $$(e);
if (view) {
var top = view.queryView(function (a) {
return !a.getParentView();
}, "parent") || view;
if (top._ignore_clicks) top._ignore_clicks(e);
} //event forced to close other popups|context menus
callEvent("onClick", [e]);
return preventEvent(e);
},
_show_on_mouse_out: true,
master_setter: function (value) {
this.attachTo(value);
return null;
}
};
var clipbuffer = {
_area: null,
_blur_id: null,
_ctrl: 0,
/*! create textarea or returns existing
**/
init: function () {
// returns existing textarea
if (this._area !== null) return this._area;
state.destructors.push({
obj: this
}); // creates new textarea
this._area = document.createElement("textarea");
this._area.className = "webix_clipbuffer";
this._area.setAttribute(
/*@attr*/
"webixignore", 1);
this._area.setAttribute("spellcheck", "false");
this._area.setAttribute("autocapitalize", "off");
this._area.setAttribute("autocorrect", "off");
this._area.setAttribute("autocomplete", "off");
document.body.appendChild(this._area);
event$1(document.body, "keydown", bind(function (e) {
var key = e.keyCode;
var ctrl = !!(e.ctrlKey || e.metaKey);
if (key === 86 && ctrl) {
this._area.value = "";
delay(this._paste, this, [e], 100);
}
}, this));
return this._area;
},
destructor: function () {
this._area = null;
},
/*! set text into buffer
**/
set: function (text) {
this.init();
text = text === "" ? "\n" : text;
this._area.value = text;
this.focus();
},
/*! select text in textarea
**/
focus: function () {
// if there is native browser selection, skip focus
if (!this._isSelectRange()) {
this.init();
this._area.focus();
this._area.select();
}
},
/*! checks document selection
**/
_isSelectRange: function () {
var text = "";
if (typeof window.getSelection != "undefined") {
text = window.getSelection().toString();
} else if (typeof document.selection != "undefined" && document.selection.type == "Text") {
text = document.selection.createRange().text;
}
return !!text;
},
/*! process ctrl+V pressing
**/
_paste: function (e) {
var trg = e.target;
if (trg === this._area) {
var text = this._area.value;
var last_active = UIManager.getFocus();
if (last_active && (!last_active.getEditor || !last_active.getEditor())) {
last_active.callEvent("onPaste", [text]);
this._area.select();
}
}
}
};
var csv$1 = {
escape: true,
delimiter: {
rows: "\n",
cols: "\t"
},
parse: function (text, sep) {
sep = sep || this.delimiter;
if (!this.escape) return this._split_clip_data(text, sep);
var lines = text.replace(/\n$/, "").split(sep.rows);
var i = 0;
while (i < lines.length - 1) {
if (this._substr_count(lines[i], "\"") % 2 === 1) {
lines[i] += sep.rows + lines[i + 1];
delete lines[i + 1];
i++;
}
i++;
}
var csv = [];
for (i = 0; i < lines.length; i++) {
if (typeof lines[i] !== "undefined") {
var tline = lines[i];
var start = 0;
var line = [];
var quoted = false;
for (var j = 0; j <= tline.length; j++) {
if (!quoted && tline[j] === sep.cols || j === tline.length) {
var chunk = tline.substr(start, j - start);
if (chunk[0] === chunk[chunk.length - 1] && chunk[0] === "\"") {
chunk = chunk.substr(1, chunk.length - 2).replace("\"\"", "\"");
}
line.push(chunk);
start = j + 1;
}
if (tline[j] === "\"") {
quoted = !quoted;
continue;
}
}
csv.push(line);
}
}
return csv;
},
_split_clip_data: function (text, sep) {
var lines = text.split(sep.rows);
for (var i = 0; i < lines.length; i++) {
lines[i] = lines[i].split(sep.cols);
}
return lines;
},
/*! counts how many occurances substring in string **/
_substr_count: function (string, substring) {
var arr = string.split(substring);
return arr.length - 1;
},
stringify: function (data, sep) {
sep = sep || this.delimiter;
if (!this.escape) {
for (var i = 0; i < data.length; i++) {
data[i] = data[i].join(sep.cols);
}
return data.join(sep.rows);
}
var reg = /\n|"|;|,/;
for (var _i = 0; _i < data.length; _i++) {
for (var j = 0; j < data[_i].length; j++) {
var chunk = data[_i][j];
if (chunk instanceof Date) data[_i][j] = i18n.parseFormatStr(chunk);else if (reg.test(chunk)) data[_i][j] = "\"" + chunk.toString().replace(/"/g, "\"\"") + "\"";
}
data[_i] = data[_i].join(sep.cols);
}
data = data.join(sep.rows);
return data;
}
};
var CopyPaste = {
clipboard_setter: function (value) {
if (env.touch) return value;
if (value === true || value === 1) value = "modify";
this.attachEvent("onAfterSelect", this._sel_to_clip);
this.attachEvent("onAfterEditStop", function (v, ed) {
var sel = this.getSelectedId(true);
if (sel.length == 1 && ed.id == sel[0]) this._sel_to_clip();
});
this.attachEvent("onPaste", function (text) {
if (!isUndefined(this._paste[this._settings.clipboard])) {
var data = csv$1.parse(text, this._settings.delimiter);
this._paste[this._settings.clipboard].call(this, data);
}
});
this.attachEvent("onFocus", function () {
clipbuffer.focus();
}); // solution for clicks on selected items
this.attachEvent("onItemClick", function (id) {
if (!this._selected || this._selected.find(id) !== -1) {
clipbuffer.focus();
UIManager.setFocus(this);
}
});
return value;
},
_sel_to_clip: function () {
var _this = this;
delay(function () {
//wait until editor is closed
if (!_this.getEditor || !_this.getEditor()) {
var sel = _this.getSelectedId(true);
var data = [];
for (var i = 0; i < sel.length; i++) {
var id = sel[i];
var item = _this.getItem(id);
data.push([_this.type.templateCopy(item)]);
}
var text = data.length === 1 ? data[0][0] : csv$1.stringify(data, _this._settings.delimiter);
clipbuffer.set(text, _this);
clipbuffer.focus();
UIManager.setFocus(_this);
}
});
},
_paste: {
// insert new item with pasted value
insert: function (text) {
var _this2 = this;
text.forEach(function (value) {
return _this2.add({
value: value
});
});
},
// change value of each selected item
modify: function (text) {
var sel = this.getSelectedId(true);
for (var i = 0; i < sel.length; i++) {
if (isUndefined(text[i])) return;
this.getItem(sel[i]).value = text[i];
this.refresh(sel[i]);
}
},
// do nothing
custom: function () {}
},
templateCopy_setter: function (value) {
this.type.templateCopy = template(value);
},
type: {
templateCopy: function (item) {
return this.template(item);
}
}
};
var CustomPrint = {
$customPrint: function (options, htmlOnly) {
if (this._prePrint(options, htmlOnly)) return true;
var tableData = this._getTableArray(options);
var table = this._getTableHTML(tableData, options);
if (htmlOnly) return table;
var doc = create("div", {
"class": "webix_ui_print"
});
doc.appendChild(table);
insertBefore(doc, options.docFooter, document.body);
window.print();
remove(doc);
},
_prePrint: function (options, htmlOnly) {
if (!htmlOnly && (this.config.layout == "y" || options.scroll || this.config.prerender || this.config.autoheight)) return true;
if (this.config.layout == "x") exports.extend(options || {}, {
xCount: this.count(),
nobreaks: true
}, true);
},
_getPageWidth: function (options) {
var size = options.size;
var width = size[options.mode == "portrait" ? "width" : "height"];
return Math.min(width * env.printPPI - 2 * env.printMargin);
},
_getTableArray: function (options, base, start) {
var maxWidth = options.fit == "page" ? Infinity : this._getPageWidth(options);
var xCount = options.xCount || this._getVisibleRange()._dx;
var tableArray = [];
var colrow = [];
var width = 0;
var newTableStart, rownum, colnum;
start = start || 0;
base = base || [];
for (var i = 0; i < this.data.order.length;) {
var obj = this.data.pull[this.data.order[i]];
rownum = parseInt(i / xCount);
colnum = i - rownum * xCount;
if (obj && colnum >= start) {
width += this.type.width; //start a new table, if cells do not fit page width
if (width > maxWidth && colnum > start) {
// 'colnum>start' ensures that a single long cell will have to fit the page
newTableStart = colrow.length + start;
tableArray.push(colrow);
i = i + (xCount - colrow.length);
colrow = [];
width = 0;
continue;
}
var cellValue = this.type.template(obj, this.type);
var className = this._itemClassName;
var style = {
display: "table-cell",
height: this.type.height + "px",
width: this.type.width + "px"
}; //push a cell to a row
colrow.push({
txt: cellValue,
className: className + " " + (obj.$css || ""),
style: style
}); //push a row to a table and start a new row
if ((i + 1) % xCount === 0) {
tableArray.push(colrow);
colrow = [];
width = 0;
}
}
i++;
}
base.push(tableArray);
if (newTableStart) this._getTableArray(options, base, newTableStart);
return base;
},
_getTableHTML: function (tableData, options) {
var container = create("div");
tableData.forEach(bind(function (table, i) {
var tableHTML = create("table", {
"class": "webix_table_print " + this.$view.className,
"style": "border-collapse:collapse"
});
table.forEach(function (row) {
var tr = create("tr");
row.forEach(function (column) {
var td = create("td");
if (column.txt) td.innerHTML = column.txt;
if (column.className) td.className = column.className;
if (column.style) {
var keys = Object.keys(column.style);
keys.forEach(function (key) {
if (column.style[key]) td.style[key] = column.style[key];
});
}
if (column.span) {
if (column.span.colspan > 1) td.colSpan = column.span.colspan;
if (column.span.rowspan > 1) td.rowSpan = column.span.rowspan;
}
tr.appendChild(td);
});
tableHTML.appendChild(tr);
});
container.appendChild(tableHTML);
if (!options.nobreaks && i + 1 < tableData.length) {
var br = create("DIV", {
"class": "webix_print_pagebreak"
});
container.appendChild(br);
}
}, this));
return container;
}
};
var temp$1 = null;
var DataMarks = {
addCss: function (id, css, silent) {
if (!this.addRowCss && !silent) {
if (!this.hasCss(id, css)) {
var node = this.getItemNode(id);
if (node) {
node.className += " " + css;
silent = true;
}
}
}
return this.data.addMark(id, css, 1, 1, silent);
},
removeCss: function (id, css, silent) {
if (!this.addRowCss && !silent) {
if (this.hasCss(id, css)) {
var node = this.getItemNode(id);
if (node) {
node.className = node.className.replace(css, "").replace(" ", " ");
silent = true;
}
}
}
return this.data.removeMark(id, css, 1, silent);
},
hasCss: function (id, mark) {
return this.data.getMark(id, mark);
},
clearCss: function (css, silent) {
return this.data.clearMark(css, 1, silent);
}
};
/*
Behavior:DataMove - allows to move and copy elements, heavily relays on DataStore.move
@export
copy
move
*/
var DataMove = {
//creates a copy of the item
copy: function (sid, tindex, tobj, details) {
details = details || {};
var new_id = details.newId || sid;
tobj = tobj || this;
var data = this.getItem(sid);
assert(data, "Incorrect ID in DataMove::copy"); //make data conversion between objects
if (tobj) data = tobj._externalData(data); //adds new element same as original
return tobj.data.add(tobj._externalData(data, new_id), tindex, details.parent || 0);
},
_next_move_index: function (nid, next, source) {
if (next && nid) {
var new_index = this.getIndexById(nid);
return new_index + (source == this && source.getIndexById(next) < new_index ? 0 : 1);
}
},
//move item to the new position
move: function (sid, tindex, tobj, details) {
details = details || {};
var new_id = details.newId || sid;
tobj = tobj || this;
assert(tobj.data, "moving attempt to component without datastore");
if (!tobj.data) return; //can process an arrya - it allows to use it from onDrag
if (isArray(sid)) {
//block separate repaint operations
if (sid.length > 3) //heuristic value, duplicated below
this.$blockRender = tobj.$blockRender = true;
for (var i = 0; i < sid.length; i++) {
//increase index for each next item in the set, so order of insertion will be equal to order in the array
var _nid = this.move(sid[i], tindex, tobj, details);
tindex = tobj._next_move_index(_nid, sid[i + 1], this);
}
this.$blockRender = tobj.$blockRender = false;
if (sid.length > 3) {
//repaint whole component
this.refresh();
if (tobj != this) tobj.refresh();
}
return;
}
var nid = sid; //id after moving
var data = this.getItem(sid);
assert(data, "Incorrect ID in DataMove::move");
if (!tobj || tobj == this) {
if (tindex < 0) tindex = this.data.order.length - 1;
this.data.move(this.getIndexById(sid), tindex); //move inside the same object
this.data.callEvent("onDataMove", [sid, tindex, null, this.data.order[tindex + 1]]);
} else {
//copy to the new object
nid = tobj.data.add(tobj._externalData(data, new_id), tindex, details.parent || 0);
this.data.remove(sid); //delete in old object
}
return nid; //return ID of item after moving
},
//move item on one position up
moveUp: function (id, step) {
var index = this.getIndexById(id) - (step || 1);
return this.move(id, index < 0 ? 0 : index);
},
//move item on one position down
moveDown: function (id, step) {
return this.moveUp(id, (step || 1) * -1);
},
//move item to the first position
moveTop: function (id) {
return this.move(id, 0);
},
//move item to the last position
moveBottom: function (id) {
return this.move(id, this.data.count() - 1);
},
/*
this is a stub for future functionality
currently it just makes a copy of data object, which is enough for current situation
*/
_externalData: function (data, id) {
var newdata = exports.extend({}, data);
newdata.id = !id || this.data.pull[id] ? uid() : id;
newdata.$template = null;
if (this._settings.externalData) newdata = this._settings.externalData.call(this, newdata, id, data);
return newdata;
}
};
var ValidateData = {
$init: function () {
if (this._events) this.attachEvent("onChange", this.clearValidation);
},
clearValidation: function () {
if (this.elements) {
for (var id in this.elements) {
this._clear_invalid(id);
}
}
},
validate: function (mode, obj) {
assert(this.callEvent, "using validate for eventless object");
this.callEvent("onBeforeValidate", []);
var failed = this._validate_details = {}; //optimistic by default :)
var result = true;
var rules$$1 = this._settings.rules;
var isHidden = this.isVisible && !this.isVisible();
var validateHidden = mode && mode.hidden;
var validateDisabled = mode && mode.disabled; //prevent validation of hidden elements
var elements = {},
hidden = {};
for (var i in this.elements) {
var name = this.elements[i].config.name; //we are ignoring hidden and disabled fields during validation
//if mode doesn not instruct us otherwise
//if form itself is hidden, we can't separate hidden fiels,
//so we will vaidate all fields
if ((isHidden || this.elements[i].isVisible() || validateHidden) && (this.elements[i].isEnabled() || validateDisabled)) elements[name] = this.elements[i];else {
hidden[name] = true;
}
}
if (rules$$1 || elements) if (!obj && this.getValues) obj = this.getValues();
if (rules$$1) {
//complex rule, which may chcek all properties of object
if (rules$$1.$obj) result = this._validate(rules$$1.$obj, obj, obj, "") && result; //all - applied to all fields
var all = rules$$1.$all;
var data = obj;
if (this._settings.complexData) data = CodeParser.collapseNames(obj, "", {}, function (v) {
return !rules$$1[v];
});
if (all) for (var _key in obj) {
if (hidden[_key]) continue;
var subresult = this._validate(all, data[_key], obj, _key);
if (!subresult) failed[_key] = true;
result = subresult && result;
} //per-field rules
for (var _key2 in rules$$1) {
if (hidden[_key2]) continue;
if (_key2.indexOf("$") !== 0 && !failed[_key2]) {
assert(rules$$1[_key2], "Invalid rule for:" + _key2);
var _subresult = this._validate(rules$$1[_key2], data[_key2], obj, _key2);
if (!_subresult) failed[_key2] = true;
result = _subresult && result;
}
}
} //check personal validation rules
if (elements) {
for (var key in elements) {
if (failed[key]) continue;
var subview = elements[key];
if (subview.validate) {
var _subresult2 = subview.validate();
result = _subresult2 && result;
if (!_subresult2) failed[key] = true;
} else {
var input = subview._settings;
if (input) {
//ignore non webix inputs
var validator = input.validate;
if (!validator && input.required) validator = rules$$1.isNotEmpty;
if (validator) {
var _subresult3 = this._validate(validator, obj[key], obj, key);
if (!_subresult3) failed[key] = true;
result = _subresult3 && result;
}
}
}
}
}
this.callEvent("onAfterValidation", [result, this._validate_details]);
return result;
},
_validate: function (rule, data, obj, key) {
if (typeof rule == "string") rule = rules[rule];
if (rule.call(this, data, obj, key)) {
if (this.callEvent("onValidationSuccess", [key, obj]) && this._clear_invalid) this._clear_invalid(key);
return true;
} else {
if (this.callEvent("onValidationError", [key, obj]) && this._mark_invalid) this._mark_invalid(key);
}
return false;
}
};
var _pull = {};
function dp(name, getOnly) {
if (_typeof(name) == "object" && name._settings) name = name._settings.id;
if (_pull[name] || getOnly) return _pull[name];
if (typeof name == "string" || typeof name == "number") name = {
master: $$(name)
};
var dp = new DataProcessor(name);
var masterId = dp._settings.master._settings.id;
_pull[masterId] = dp;
$$(masterId).attachEvent("onDestruct", function () {
_pull[this._settings.id] = null;
delete _pull[this._settings.id];
});
return dp;
}
define("dp", dp);
dp.$$ = function (id) {
return _pull[id];
};
var DataProcessor = exports.proto({
defaults: {
autoupdate: true,
updateFromResponse: false,
mode: "post",
operationName: "webix_operation",
trackMove: false
},
/*! constructor
**/
$init: function () {
this.reset();
this._ignore = false;
this.name = "DataProcessor";
this.$ready.push(this._after_init_call);
},
reset: function () {
this._updates = [];
},
url_setter: function (value) {
/*
we can use simple url or mode->url
*/
var mode = "";
if (typeof value == "string") {
var parts = value.split("->");
if (parts.length > 1) {
value = parts[1];
mode = parts[0];
}
} else if (value && value.mode) {
mode = value.mode;
value = value.url;
}
if (mode) return proxy$5(mode, value);
return value;
},
master_setter: function (value) {
var store = value;
if (value.name != "DataStore") store = value.data;
this._settings.store = store;
return value;
},
_promise: function (handler) {
var prev = this._waitSave;
this._waitSave = [];
handler();
var result = Promise.all(this._waitSave);
this._waitSave = prev;
if (prev) prev.push(result);
return result;
},
/*! attaching onStoreUpdated event
**/
_after_init_call: function () {
var store = this._settings.store;
if (store) {
store.attachEvent("onStoreUpdated", bind(this._onStoreUpdated, this));
store.attachEvent("onDataMove", bind(this._onDataMove, this));
}
},
ignore: function (code, master) {
var temp = this._ignore;
this._ignore = true;
code.call(master || this);
this._ignore = temp;
},
off: function () {
this._ignore = true;
},
on: function () {
this._ignore = false;
},
_copy_data: function (source) {
var obj = {};
for (var key in source) {
if (key.indexOf("$") !== 0) obj[key] = source[key];
}
return obj;
},
save: function (id, operation, obj) {
operation = operation || "update";
return this._save_inner(id, obj, operation, true);
},
_save_inner: function (id, obj, operation, now) {
if (_typeof(id) == "object") id = id.toString();
if (!id || this._ignore === true || !operation || operation == "paint") return;
var store = this._settings.store;
if (store) {
obj = obj || this._settings.store.getItem(id);
if (store._scheme_serialize) obj = store._scheme_serialize(obj);
}
var update = {
id: id,
data: this._copy_data(obj),
operation: operation
}; //save parent id
if (!isUndefined(obj.$parent)) update.data.parent = obj.$parent;
if (update.operation != "delete") {
//prevent saving of not-validated records
var master = this._settings.master;
if (master && master.data && master.data.getMark && master.data.getMark(id, "webix_invalid")) update._invalid = true;
if (!this.validate(null, update.data)) update._invalid = true;
}
if (this._check_unique(update)) this._updates.push(update);
if (this._settings.autoupdate || now) return this._sendData(id);
return;
},
_onDataMove: function (sid, tindex, parent, targetid) {
if (this._settings.trackMove) {
var obj = copy(this._settings.store.getItem(sid));
obj.webix_move_index = tindex;
obj.webix_move_id = targetid;
obj.webix_move_parent = parent;
this._save_inner(sid, obj, "order");
}
},
_onStoreUpdated: function (id, obj, operation) {
switch (operation) {
case "save":
operation = "update";
break;
case "update":
operation = "update";
break;
case "add":
operation = "insert";
break;
case "delete":
operation = "delete";
break;
default:
return true;
}
return this._save_inner(id, obj, operation);
},
_check_unique: function (check) {
for (var i = 0; i < this._updates.length; i++) {
var one = this._updates[i];
if (one.id == check.id && !one._in_progress) {
if (check.operation == "delete") {
if (one.operation == "insert") this._updates.splice(i, 1);else one.operation = "delete";
}
one.data = check.data;
one._invalid = check._invalid;
return false;
}
}
return true;
},
send: function () {
return this._sendData();
},
_sendData: function (triggerId) {
if (!this._settings.url) return;
var wait;
var marked = this._updates;
var to_send = [];
var url = this._settings.url;
for (var i = 0; i < marked.length; i++) {
var tosave = marked[i];
if (tosave._in_progress) continue;
if (tosave._invalid) continue;
var id = tosave.id; // call to .save(id) without autoupdate mode will send the specific object only
if (!this._settings.autoupdate && triggerId && triggerId != id) continue;
var operation = tosave.operation;
var precise_url = proxy$5.$parse(_typeof(url) == "object" && !url.$proxy ? url[operation] : url);
var custom = precise_url && (precise_url.$proxy || typeof precise_url === "function");
if (!precise_url) continue;
var store = this._settings.store;
if (store && store._scheme_save) store._scheme_save(tosave.data);
if (!this.callEvent("onBefore" + operation, [id, tosave])) continue;
tosave._in_progress = true;
if (!this.callEvent("onBeforeDataSend", [tosave])) return;
tosave.data = this._updatesData(tosave.data);
var result = void 0;
if (precise_url.$proxy) {
if (precise_url.save) {
//proxy
result = precise_url.save(this.config.master, tosave, this);
}
to_send.push(tosave);
} else {
if (operation == "insert") delete tosave.data.id;
if (custom) {
//save function
result = precise_url.call(this.config.master, tosave.id, tosave.operation, tosave.data);
} else {
//normal url
tosave.data[this._settings.operationName] = operation;
result = this._send(precise_url, tosave.data, this._settings.mode);
}
}
if (result) {
result = this._proxy_on_save(result, {
id: tosave.id,
status: tosave.operation
});
if (triggerId && id === triggerId) {
wait = result;
}
}
this.callEvent("onAfterDataSend", [tosave]);
}
if (url.$proxy && url.saveAll && to_send.length) {
var _result = url.saveAll(this.config.master, to_send, this);
if (_result) {
_result = this._proxy_on_save(_result, null);
if (!wait) wait = _result;
}
}
return wait;
},
_proxy_on_save: function (result, state) {
var _this = this;
if (result) {
if (!result.then) result = Deferred.resolve(result);
result = result.then(function (data) {
if (data && typeof data.json == "function") data = data.json();
var processed;
if (state === null) {
processed = _this._processResult(data); //array of responses
} else {
processed = _this._processResult(state, "", data, -1); //text, data, loader
}
if (!processed) throw processed; // trigger rejection
return processed;
}, function (x) {
_this._processError(state, "", null, x);
throw x;
});
if (this._waitSave) this._waitSave.push(result);
return result;
}
},
/*! process updates list to POST and GET params according dataprocessor protocol
* @param updates
* list of objects { id: "item id", data: "data hash", operation: "type of operation"}
* @return
* object { post: { hash of post params as name: value }, get: { hash of get params as name: value } }
**/
_updatesData: function (source) {
var target = {};
for (var j in source) {
if (j.indexOf("$") !== 0) target[j] = source[j];
}
return target;
},
/*! send dataprocessor query to server
* and attach event to process result
* @param url
* server url
* @param get
* hash of get params
* @param post
* hash of post params
* @mode
* 'post' or 'get'
**/
_send: function (url, post, mode) {
assert(url, "url was not set for DataProcessor");
return ajax()[mode](url, post);
},
attachProgress: function (start, end, error) {
this.attachEvent("onBeforeDataSend", start);
this.attachEvent("onAfterSync", end);
this.attachEvent("onAfterSaveError", error);
this.attachEvent("onLoadError", error);
},
_processError: function (id, text, data, loader) {
if (id) this._innerProcessResult(true, id.id, false, id.status, false, {
text: text,
data: data,
loader: loader
});else {
this.callEvent("onLoadError", arguments);
callEvent("onLoadError", [text, data, loader, this]);
}
},
_innerProcessResult: function (error, id, newid, status, obj, details) {
var master = this._settings.master;
var update = this.getItemState(id);
update._in_progress = false;
if (error) {
if (this.callEvent("onBeforeSaveError", [id, status, obj, details])) {
update._invalid = true;
if (this._settings.undoOnError && master._settings.undo) {
this.ignore(function () {
master.undo(id);
});
this.setItemState(id, false);
}
this.callEvent("onAfterSaveError", [id, status, obj, details]);
}
return;
} else this.setItemState(id, false);
var store = this._settings.store;
if (store && store.exists(id)) {
//update from response
if (newid && id != newid) store.changeId(id, newid);
if (obj && status != "delete" && this._settings.updateFromResponse) this.ignore(function () {
store.updateItem(newid || id, obj);
});
} //clean undo history, for the saved record
if (this._settings.undoOnError && master._settings.undo) master.removeUndo(newid || id);
this.callEvent("onAfterSave", [obj, id, details]);
this.callEvent("onAfter" + status, [obj, id, details]);
return obj || {};
},
processResult: function (state, hash, details) {
//compatibility with custom json response
var error = hash && (hash.status == "error" || hash.status == "invalid");
var newid = hash ? hash.newid || hash.id : false;
return this._innerProcessResult(error, state.id, newid, state.status, hash, details);
},
// process saving from result
_processResult: function (state, text, data, loader) {
var _this2 = this;
var finalResult;
this.callEvent("onBeforeSync", [state, text, data, loader]);
if (isArray(state)) {
//saveAll results
finalResult = [];
state.forEach(function (one) {
finalResult.push(_this2.processResult(one, one, {}));
});
} else {
if (loader === -1) {
//callback from promise
finalResult = this.processResult(state, data, {});
} else {
var proxy = this._settings.url;
if (proxy.$proxy && proxy.result) {
finalResult = proxy.result(state, this._settings.master, this, text, data, loader) || {};
} else {
var hash;
if (text) {
hash = data.json(); //invalid response
if (text && (hash === null || typeof hash == "undefined")) hash = {
status: "error"
};
}
finalResult = this.processResult(state, hash, {
text: text,
data: data,
loader: loader
});
}
}
}
this.callEvent("onAfterSync", [state, text, data, loader]);
return finalResult;
},
/*! if it's defined escape function - call it
* @param value
* value to escape
* @return
* escaped value
**/
escape: function (value) {
if (this._settings.escape) return this._settings.escape(value);else return encodeURIComponent(value);
},
getState: function () {
if (!this._updates.length) return false;
for (var i = this._updates.length - 1; i >= 0; i--) {
if (this._updates[i]._in_progress) return "saving";
}
return true;
},
getItemState: function (id) {
var index = this._get_stack_index(id);
return this._updates[index] || null;
},
setItemState: function (id, state) {
if (state) {
this._save_inner(id, null, "update");
} else {
var index = this._get_stack_index(id);
if (index > -1) this._updates.splice(index, 1);
}
},
_get_stack_index: function (id) {
var index = -1;
for (var i = 0; i < this._updates.length; i++) {
if (this._updates[i].id == id) {
index = i;
break;
}
}
return index;
}
}, Settings, EventSystem, ValidateData);
/*
DataStore is not a behavior, it standalone object, which represents collection of data.
Call provideAPI to map data API
@export
exists
getIdByIndex
getIndexById
get
set
refresh
count
sort
filter
next
previous
clearAll
first
last
*/
function DataStore() {
this.name = "DataStore";
exports.extend(this, EventSystem);
this.setDriver("json"); //default data source is an
this.pull = {}; //hash of IDs
this.order = _to_array(); //order of IDs
this._marks = {};
}
DataStore.prototype = {
//defines type of used data driver
//data driver is an abstraction other different data formats - xml, json, csv, etc.
setDriver: function (type) {
assert(DataDriver[type], "incorrect DataDriver");
this.driver = DataDriver[type];
},
//process incoming raw data
_parse: function (data) {
this.callEvent("onParse", [this.driver, data]);
if (this._filter_order) this.filter(); //get size and position of data
var info = this.driver.getInfo(data);
if (info.config) this.callEvent("onServerConfig", [info.config]);
var options = this.driver.getOptions(data);
if (options) this.callEvent("onServerOptions", [options]); //get array of records
var recs = this.driver.getRecords(data);
this._inner_parse(info, recs); //in case of tree store we may want to group data
if (this._scheme_group && this._group_processing && !this._not_grouped_order) this._group_processing(this._scheme_group); //optional data sorting
if (this._scheme_sort) {
this.blockEvent();
this.sort(this._scheme_sort);
this.unblockEvent();
}
this.callEvent("onStoreLoad", [this.driver, data]); //repaint self after data loading
this.refresh();
},
_inner_parse: function (info, recs) {
var from = info.from;
var subload = true;
var marks = false; //some data is loaded and new data doesn't have "pos" - assuming update
if (!from && from !== 0 && this.order[0]) {
if (this._removeMissed) {
//update mode, create kill list
marks = {};
for (var i = 0; i < this.order.length; i++) {
marks[this.order[i]] = true;
}
}
subload = false;
from = this.order.length;
} else from = (from || 0) * 1;
var j = 0;
for (var _i = 0; _i < recs.length; _i++) {
//get hash of details for each record
var temp = this.driver.getDetails(recs[_i]);
var id = this.id(temp); //generate ID for the record
if (!this.pull[id]) {
//if such ID already exists - update instead of insert
this.order[j + from] = id;
j++;
} else if (subload && this.order[j + from]) j++;
if (this.pull[id]) {
exports.extend(this.pull[id], temp, true); //add only new properties
if (this._scheme_update) this._scheme_update(this.pull[id]); //update mode, remove item from kill list
if (marks) delete marks[id];
} else {
this.pull[id] = temp;
if (this._scheme_init) this._scheme_init(temp);
}
} //update mode, delete items which are not existing in the new xml
if (marks) {
this.blockEvent();
for (var delid in marks) {
this.remove(delid);
}
this.unblockEvent();
}
var endpos = info.size * 1;
if (endpos) {
if (!this.order[endpos - 1]) this.order[endpos - 1] = undefined;
if (endpos < this.order.length) this.order = _to_array(this.order.slice(0, endpos));
}
},
//generate id for data object
id: function (data) {
return data.id || (data.id = uid());
},
changeId: function (old, newid) {
//assert(this.pull[old],"Can't change id, for non existing item: "+old);
if (old == newid) return;
if (this.pull[old]) this.pull[newid] = this.pull[old];
this.pull[newid].id = newid;
this.order[this.order.find(old)] = newid;
if (this._filter_order) this._filter_order[this._filter_order.find(old)] = newid;
if (this._marks[old]) {
this._marks[newid] = this._marks[old];
delete this._marks[old];
}
this.callEvent("onIdChange", [old, newid]);
if (this._render_change_id) this._render_change_id(old, newid);
delete this.pull[old];
},
//get data from hash by id
getItem: function (id) {
return this.pull[id];
},
//assigns data by id
updateItem: function (id, update, mode) {
if (_typeof(id) === "object") id = id.toString();
var data = this.getItem(id);
var old = null; //check is change tracking active
var changeTrack = this.hasEvent("onDataUpdate");
assert(data, "Invalid ID for updateItem");
assert(!update || !update.id || update.id == id, "Attempt to change ID in updateItem");
if (!isUndefined(update) && data !== update) {
//preserve original object
if (changeTrack) old = copy(data);
id = data.id; //preserve id
exports.extend(data, update, true);
data.id = id;
}
if (this._scheme_update) this._scheme_update(data);
this.callEvent("onStoreUpdated", [id, data, mode || "update"]);
if (changeTrack) this.callEvent("onDataUpdate", [id, data, old]);
},
//sends repainting signal
refresh: function (id) {
if (this._skip_refresh) return;
if (id) {
if (this.exists(id)) this.callEvent("onStoreUpdated", [id, this.pull[id], "paint"]);
} else this.callEvent("onStoreUpdated", [null, null, null]);
},
silent: function (code, master) {
this._skip_refresh = true;
code.call(master || this);
this._skip_refresh = false;
},
//converts range IDs to array of all IDs between them
getRange: function (from, to) {
//if some point is not defined - use first or last id
//BEWARE - do not use empty or null ID
if (from) from = this.getIndexById(from);else from = this.$min || this.startOffset || 0;
if (to) to = this.getIndexById(to);else {
to = this.$max === 0 ? 0 : Math.min(this.$max ? this.$max - 1 : this.endOffset || Infinity, this.count() - 1);
if (to < 0) to = 0; //we have not data in the store
}
if (from > to) {
//can be in case of backward shift-selection
var a = to;
to = from;
from = a;
}
return this.getIndexRange(from, to);
},
//converts range of indexes to array of all IDs between them
getIndexRange: function (from, to) {
to = Math.min(to === 0 ? 0 : to || Infinity, this.count() - 1);
var ret = _to_array(); //result of method is rich-array
for (var i = from || 0; i <= to; i++) {
ret.push(this.getItem(this.order[i]));
}
return ret;
},
//returns total count of elements
count: function () {
return this.order.length;
},
//returns truy if item with such ID exists
exists: function (id) {
return !!this.pull[id];
},
//nextmethod is not visible on component level, check DataMove.move
//moves item from source index to the target index
move: function (sindex, tindex) {
assert(sindex >= 0 && tindex >= 0, "DataStore::move", "Incorrect indexes");
if (sindex == tindex) return;
var id = this.getIdByIndex(sindex);
var obj = this.getItem(id);
if (this._filter_order) this._move_inner(this._filter_order, 0, 0, this.getIdByIndex(sindex), this.getIdByIndex(tindex));
this._move_inner(this.order, sindex, tindex); //repaint signal
this.callEvent("onStoreUpdated", [id, obj, "move"]);
},
_move_inner: function (col, sindex, tindex, sid, tid) {
if (sid || tid) {
sindex = tindex = -1;
for (var i = 0; i < col.length; i++) {
if (col[i] == sid && sindex < 0) sindex = i;
if (col[i] == tid && tindex < 0) tindex = i;
}
}
var id = col[sindex];
col.removeAt(sindex); //remove at old position
col.insertAt(id, Math.min(col.length, tindex)); //insert at new position
},
scheme: function (config) {
this._scheme = {};
this._scheme_save = config.$save;
this._scheme_init = config.$init || config.$change;
this._scheme_update = config.$update || config.$change;
this._scheme_serialize = config.$serialize;
this._scheme_group = config.$group;
this._scheme_sort = config.$sort;
this._scheme_export = config.$export; //ignore $-starting properties, as they have special meaning
for (var key in config) {
if (key.substr(0, 1) != "$") this._scheme[key] = config[key];
}
},
importData: function (target, silent) {
var data = target ? target.data || target : [];
this._filter_order = null;
if (typeof data.serialize == "function") {
this.order = _to_array([].concat(data.order)); //make full copy, to preserve object properties
//[WE-CAN-DO-BETTER]
if (this._make_full_copy) {
this._make_full_copy = false;
var oldpull = this.pull;
this.pull = {};
for (var _key in data.pull) {
var old = oldpull[_key];
this.pull[_key] = copy(data.pull[_key]);
if (old && old.open) this.pull[_key].open = true;
}
} else {
this.pull = {};
for (var _key2 in data.pull) {
this.pull[_key2] = data.pull[_key2];
}
}
if (data.branch && this.branch) {
this.branch = copy(data.branch);
this._filter_branch = null;
}
} else {
this.order = _to_array();
this.pull = {};
var id, obj;
if (isArray(target)) for (var _key3 = 0; _key3 < target.length; _key3++) {
obj = id = target[_key3];
if (_typeof(obj) == "object") obj.id = obj.id || uid();else obj = {
id: id,
value: id
};
this.order.push(obj.id);
if (this._scheme_init) this._scheme_init(obj);
this.pull[obj.id] = obj;
} else for (var _key4 in data) {
this.order.push(_key4);
this.pull[_key4] = {
id: _key4,
value: data[_key4]
};
}
}
if (this._extraParser && !data.branch) {
this.branch = {
0: []
};
if (!this._datadriver_child) this._set_child_scheme("data");
for (var i = 0; i < this.order.length; i++) {
var key = this.order[i];
this._extraParser(this.pull[key], 0, 0, false);
}
}
this.callEvent("onStoreLoad", []);
if (!silent) this.callEvent("onStoreUpdated", []);
},
sync: function (source, filter, silent) {
this.unsync();
var type = _typeof(source);
if (type == "string") source = $$(source);
if (type != "function" && type != "object") {
silent = filter;
filter = null;
}
if (source.name != "DataStore" && source.name != "TreeStore") {
if (source.data && (source.data.name === "DataStore" || source.data.name === "TreeStore")) source = source.data;else {
this._sync_source = source;
return callEvent("onSyncUnknown", [this, source, filter]);
}
}
var sync_logic = bind(function (id, data, mode) {
if (this._skip_next_sync) return; //sync of tree-structure with after-filtering
//we need to make a full copy, to preserve $count
//[WE-CAN-DO-BETTER]
if (filter && this.branch) this._make_full_copy = true;
this.importData(source, true);
if (filter) this.silent(filter);
if (this._on_sync) this._on_sync();
if (!(id && data && mode) && !this.count()) //clearall
this._marks = {};
if (mode == "delete" && this._marks[id]) delete this._marks[id];
this.callEvent("onSyncApply", []);
if (!silent) this.refresh();else silent = false;
}, this);
this._sync_events = [source.attachEvent("onStoreUpdated", sync_logic), source.attachEvent("onIdChange", bind(function (old, nid) {
this.changeId(old, nid);
this.refresh(nid);
}, this))];
this._sync_source = source; //backward data saving
this._back_sync_handler = this.attachEvent("onStoreUpdated", function (id, data, mode) {
if (mode == "update" || mode == "save") {
this._skip_next_sync = 1;
source.updateItem(id, data);
this._skip_next_sync = 0;
}
});
sync_logic();
},
unsync: function () {
if (this._sync_source) {
var source = this._sync_source;
if (source.name != "DataStore" && source.name != "TreeStore" && (!source.data || source.data.name != "DataStore" || source.data.name != "TreeStore")) {
//data sync with external component
callEvent("onUnSyncUnknown", [this, source]);
} else {
//data sync with webix component
for (var i = 0; i < this._sync_events.length; i++) {
source.detachEvent(this._sync_events[i]);
}
this.detachEvent(this._back_sync_handler);
}
this._sync_source = null;
}
},
destructor: function () {
this.unsync();
this.pull = this.order = this._marks = null;
this._evs_events = this._evs_handlers = {};
},
//adds item to the store
add: function (obj, index) {
//default values
if (this._scheme) for (var key in this._scheme) {
if (isUndefined(obj[key])) obj[key] = this._scheme[key];
}
if (this._scheme_init) this._scheme_init(obj); //generate id for the item
var id = this.id(obj); //in case of treetable order is sent as 3rd parameter
var order = arguments[2] || this.order; //by default item is added to the end of the list
var data_size = order.length;
if (isUndefined(index) || index < 0) index = data_size; //check to prevent too big indexes
if (index > data_size) {
assert(0, "Warning", "DataStore:add", "Index of out of bounds");
index = Math.min(order.length, index);
}
if (this.callEvent("onBeforeAdd", [id, obj, index]) === false) return false;
assert(!this.exists(id), "Not unique ID");
this.pull[id] = obj;
order.insertAt(id, index);
if (this._filter_order) {
//adding during filtering
//we can't know the location of new item in full dataset, making suggestion
//put at end of original dataset by default
var original_index = this._filter_order.length; //if some data exists, put at the same position in original and filtered lists
if (this.order.length) original_index = Math.min(index || 0, original_index);
this._filter_order.insertAt(id, original_index);
} //repaint signal
this.callEvent("onStoreUpdated", [id, obj, "add"]);
this.callEvent("onAfterAdd", [id, index]);
return obj.id;
},
//removes element from datastore
remove: function (id) {
//id can be an array of IDs - result of getSelect, for example
if (isArray(id)) {
for (var i = 0; i < id.length; i++) {
this.remove(id[i]);
}
return;
}
if (this.callEvent("onBeforeDelete", [id]) === false) return false;
assert(this.exists(id), "Not existing ID in remove command" + id);
var obj = this.getItem(id); //save for later event
//clear from collections
this.order.remove(id);
if (this._filter_order) this._filter_order.remove(id);
delete this.pull[id];
if (this._marks[id]) delete this._marks[id]; //repaint signal
this.callEvent("onStoreUpdated", [id, obj, "delete"]);
this.callEvent("onAfterDelete", [id]);
},
//deletes all records in datastore
clearAll: function (soft) {
//instead of deleting one by one - just reset inner collections
this.pull = {};
this._marks = {};
this.order = _to_array(); //this.feed = null;
this._filter_order = null;
if (!soft) this.url = null;
this.callEvent("onClearAll", [soft]);
this.refresh();
},
//converts index to id
getIdByIndex: function (index) {
assert(index >= 0, "DataStore::getIdByIndex Incorrect index");
return this.order[index];
},
//converts id to index
getIndexById: function (id) {
if (!this.pull[id]) return -1;else return this.order.find(id); //slower than getIdByIndex
},
//returns ID of next element
getNextId: function (id, step) {
return this.order[this.getIndexById(id) + (step || 1)];
},
//returns ID of first element
getFirstId: function () {
return this.order[0];
},
//returns ID of last element
getLastId: function () {
return this.order[this.order.length - 1];
},
//returns ID of previous element
getPrevId: function (id, step) {
return this.order[this.getIndexById(id) - (step || 1)];
},
/*
sort data in collection
by - settings of sorting
or
by - array of settings
or
by - sorting function
dir - "asc" or "desc"
or
by - property
dir - "asc" or "desc"
as - type of sortings
Sorting function will accept 2 parameters and must return 1,0,-1, based on desired order
*/
sort: function (by, dir, as) {
var _this = this;
var parameters;
var sort = by;
if (isArray(sort)) {
sort = sort.map(function (a) {
return _this._sort_init(a);
});
parameters = [sort];
} else {
sort = this._sort_init(by, dir, as);
parameters = [sort.by, sort.dir, sort.as, sort];
}
if (!this.callEvent("onBeforeSort", parameters)) return;
var sorter = this.sorting.create(sort);
this.order = this._sort_core(sorter, this.order);
if (this._filter_order) this._filter_order = this._sort_core(sorter, this._filter_order); //repaint self
this.refresh();
this.callEvent("onAfterSort", parameters);
},
_sort_init: function (by, dir, as) {
var sort = by;
if (typeof by == "function") sort = {
as: by,
dir: dir
};else if (typeof by == "string") sort = {
by: by,
dir: dir,
as: as
};
if (typeof sort.by == "string") sort.by = sort.by.replace(/#/g, "");
return sort;
},
_sort_core: function (sorter, order) {
if (this.order.length) {
var pre = order.splice(0, this.$freeze); //get array of IDs
var neworder = _to_array();
for (var i = order.length - 1; i >= 0; i--) {
neworder[i] = this.pull[order[i]];
}
neworder.sort(sorter);
return _to_array(pre.concat(neworder.map(function (obj) {
assert(obj, "Client sorting can't be used with dynamic loading");
return this.id(obj);
}, this)));
}
return order;
},
/*
Filter datasource
text - property, by which filter
value - filter mask
or
text - filter method
Filter method will receive data object and must return true or false
*/
_filter_reset: function (preserve) {
//remove previous filtering , if any
if (this._filter_order && !preserve) {
this.order = this._filter_order;
delete this._filter_order;
}
},
_filter_core: function (filter, value, preserve) {
var neworder = _to_array();
var freeze = this.$freeze || 0;
for (var i = 0; i < this.order.length; i++) {
var id = this.order[i];
if (i < freeze || filter(this.getItem(id), value)) neworder.push(id);
} //set new order of items, store original
if (!preserve || !this._filter_order) this._filter_order = this.order;
this.order = neworder;
},
find: function (config, first) {
var result = [];
for (var i in this.pull) {
var data = this.pull[i];
var match = true;
if (_typeof(config) == "object") {
for (var key in config) {
if (data[key] != config[key]) {
match = false;
break;
}
}
} else if (!config(data)) match = false;
if (match) result.push(data);
if (first && result.length) return result[0];
}
return first ? null : result;
},
filter: function (text, value, preserve) {
//unfilter call but we already in not-filtered state
if (!text && !this._filter_order && !this._filter_branch) return;
if (!this.callEvent("onBeforeFilter", [text, value])) return;
this._filter_reset(preserve);
if (!this.order.length) return; //if text not define -just unfilter previous state and exit
if (text) {
var filter = text;
value = value || "";
if (typeof text == "string") {
text = text.replace(/#/g, "");
if (typeof value == "function") filter = function (obj) {
return value(obj[text]);
};else {
value = value.toString().toLowerCase();
filter = function (obj, value) {
//default filter - string start from, case in-sensitive
assert(obj, "Client side filtering can't be used with dynamic loading");
return (obj[text] || "").toString().toLowerCase().indexOf(value) != -1;
};
}
}
this._filter_core(filter, value, preserve, this._filterMode);
} //repaint self
this.refresh();
this.callEvent("onAfterFilter", []);
},
/*
Iterate through collection
*/
_obj_array: function () {
var data = [];
for (var i = this.order.length - 1; i >= 0; i--) {
data[i] = this.pull[this.order[i]];
}
return data;
},
each: function (method, master, all) {
var order = this.order;
if (all) order = this._filter_order || order;
for (var i = 0; i < order.length; i++) {
if (order[i]) method.call(master || this, this.getItem(order[i]), i);
}
},
_methodPush: function (object, method) {
return function () {
return object[method].apply(object, arguments);
};
},
/*
map inner methods to some distant object
*/
provideApi: function (target, eventable) {
if (eventable) {
this.mapEvent({
onbeforesort: target,
onaftersort: target,
onbeforeadd: target,
onafteradd: target,
onbeforedelete: target,
onafterdelete: target,
ondataupdate: target
/*,
onafterfilter: target,
onbeforefilter: target*/
});
}
var list = ["sort", "add", "remove", "exists", "getIdByIndex", "getIndexById", "getItem", "updateItem", "refresh", "count", "filter", "find", "getNextId", "getPrevId", "clearAll", "getFirstId", "getLastId", "serialize", "sync"];
for (var i = 0; i < list.length; i++) {
target[list[i]] = this._methodPush(this, list[i]);
}
},
addMark: function (id, mark, css, value, silent) {
var obj = this._marks[id] || {};
this._marks[id] = obj;
if (!obj[mark]) {
obj[mark] = value || true;
if (css) {
var old_css = obj.$css || "";
obj.$css = old_css + " " + mark;
}
if (!silent) this.refresh(id);
}
return obj[mark];
},
removeMark: function (id, mark, css, silent) {
var obj = this._marks[id];
if (obj) {
if (obj[mark]) delete obj[mark];
if (css) {
var current_css = obj.$css;
if (current_css) {
obj.$css = current_css.replace(mark, "").replace(" ", " ");
}
}
if (!silent) this.refresh(id);
}
},
getMark: function (id, mark) {
var obj = this._marks[id];
return obj ? obj[mark] : false;
},
clearMark: function (name, css, silent) {
for (var id in this._marks) {
var obj = this._marks[id];
if (obj[name]) {
delete obj[name];
if (css && obj.$css) obj.$css = obj.$css.replace(name, "").replace(" ", " ");
if (!silent) this.refresh(id);
}
}
},
/*
serializes data to a json object
*/
serialize: function (all) {
var ids = this.order;
if (all && this._filter_order) ids = this._filter_order;
var result = [];
for (var i = 0; i < ids.length; i++) {
var el = this.pull[ids[i]];
if (this._scheme_serialize) {
el = this._scheme_serialize(el);
if (el === false) continue;
}
result.push(el);
}
return result;
},
sorting: {
create: function (config) {
if (isArray(config)) return this._multi(config);
return this._dir(config.dir, this._by(config.by, config.as));
},
as: {
//handled by dataFeed
"server": function () {
return false;
},
"date": function (a, b) {
a = a - 0;
b = b - 0;
if (isNaN(b)) return 1;
if (isNaN(a)) return -1;
return a > b ? 1 : a < b ? -1 : 0;
},
"int": function (a, b) {
a = a * 1;
b = b * 1;
if (isNaN(b)) return 1;
if (isNaN(a)) return -1;
return a > b ? 1 : a < b ? -1 : 0;
},
"string_strict": function (a, b) {
if (!b) return 1;
if (!a) return -1;
a = a.toString();
b = b.toString();
return a > b ? 1 : a < b ? -1 : 0;
},
"string": function (a, b) {
if (!b) return 1;
if (!a) return -1;
a = a.toString().toLowerCase();
b = b.toString().toLowerCase();
return a > b ? 1 : a < b ? -1 : 0;
},
"raw": function (a, b) {
return a > b ? 1 : a < b ? -1 : 0;
}
},
_multi: function (methods) {
var _this2 = this;
methods = methods.map(function (c) {
return _this2._dir(c.dir, _this2._by(c.by, c.as));
});
return function (a, b) {
var result,
i = 0;
do {
result = methods[i](a, b);
} while (!result && methods[++i]);
return result;
};
},
_by: function (prop, method) {
if (!prop) return method;
if (typeof method != "function") method = this.as[method || "string"];
assert(method, "Invalid sorting method");
return function (a, b) {
return method(a[prop], b[prop]);
};
},
_dir: function (prop, method) {
if (prop == "asc" || !prop) return method;
return function (a, b) {
return method(a, b) * -1;
};
}
}
};
/*
Behavior:DataLoader - load data in the component
@export
load
parse
*/
var DataLoader = exports.proto({
$init: function (config) {
//prepare data store
config = config || "";
this._feed_last = {};
this._data_generation = 1;
this.data = new DataStore();
this.data.attachEvent("onClearAll", bind(this._call_onclearall, this));
this.data.attachEvent("onServerConfig", bind(this._call_on_config, this));
this.attachEvent("onDestruct", this._call_onclearall);
this.data.feed = this._feed;
this.data.owner = config.id;
},
_feed: function (from, count, callback, defer, clear) {
//allow only single request at same time
if (this._load_count) {
defer = Deferred.defer();
this._load_count = [from, count, callback, defer, clear]; //save last ignored request
return defer;
} else this._load_count = true;
this._feed_last.from = from;
this._feed_last.count = count;
return this._feed_common.call(this, from, count, callback, defer, false, clear);
},
_feed_common: function (from, count, callback, defer, details, clear) {
var _this = this;
var url = this.data.url;
if (from < 0) from = 0;
if (!details) details = {
start: from,
count: count
};
if (this.count()) details["continue"] = "true";
var state = this.getState ? this.getState() : null; // proxy
if (url && typeof url != "string") {
if (state) {
if (state.sort) details.sort = state.sort;
if (state.filter) details.filter = state.filter;
}
return this.load(url, 0, details, clear).then(function (data) {
return _this._feed_on_load(data, callback, defer);
}, function () {
return _this._feed_callback();
});
} else {
// GET
url = url + (url.indexOf("?") == -1 ? "?" : "&");
var params = [];
for (var d in details) {
params.push(d + "=" + details[d]);
}
if (state) {
if (state.sort) {
var sort = isArray(state.sort) ? state.sort : [state.sort];
for (var i = 0; i < sort.length; i++) {
params.push("sort[" + sort[i].id + "]=" + encodeURIComponent(sort[i].dir));
}
}
if (state.filter) for (var key in state.filter) {
var filterValue = state.filter[key];
if (_typeof(filterValue) == "object") filterValue = ajax().stringify(filterValue); //server daterangefilter
params.push("filter[" + key + "]=" + encodeURIComponent(filterValue));
}
}
url += params.join("&");
if (this._feed_last.url !== url) {
this._feed_last.url = url;
return this.load(url, 0, null, clear).then(function (data) {
return _this._feed_on_load(data, callback, defer);
}, function () {
return _this._feed_callback();
});
} else {
this._load_count = false;
return Deferred.reject();
}
}
},
_feed_on_load: function (data, callback, defer) {
var _this2 = this;
delay(function () {
return _this2._feed_callback();
}, "", "", 100);
if (callback) ajax.$callback(this, callback, data);
if (defer) defer.resolve(data);
return data;
},
_feed_callback: function () {
//after loading check if we have some ignored requests
var temp = this._load_count;
this._load_count = false;
if (_typeof(temp) == "object") this.data.feed.apply(this, temp); //load last ignored request
},
//loads data from external URL
load: function (url) {
url = proxy$5.$parse(url);
var ajax$$1 = AtomDataLoader.load.apply(this, arguments); //prepare data feed for dyn. loading
if (!this.data.url) this.data.url = url;
return ajax$$1;
},
//load next set of data rows
loadNext: function (count, start, callback, url, now, clear) {
var config = this._settings;
if (config.datathrottle && !now) {
if (this._throttle_request) window.clearTimeout(this._throttle_request);
var defer = Deferred.defer();
this._throttle_request = delay(function () {
defer.resolve(this.loadNext(count, start, callback, url, true, clear));
}, this, 0, config.datathrottle);
return defer;
}
if (!start && start !== 0) start = this.count();
if (!count) count = config.datafetch || this.count();
this.data.url = url || this.data.url;
if (this.callEvent("onDataRequest", [start, count, callback, url]) && this.data.url) return this.data.feed.call(this, start, count, callback, false, clear);
return Deferred.reject();
},
_maybe_loading_already: function (count, from) {
var last = this._feed_last;
if (this._load_count && last.url) {
if (last.from <= from && last.count + last.from >= count + from) return true;
}
return false;
},
removeMissed_setter: function (value) {
return this.data._removeMissed = value;
},
//init of dataprocessor delayed after all settings processing
//because it need to be the last in the event processing chain
//to get valid validation state
_init_dataprocessor: function () {
var url = this._settings.save;
if (url === true) url = this._settings.save = this._settings.url;
var obj = {
master: this
};
if (url && url.url) exports.extend(obj, url);else obj.url = url;
dp(obj);
},
save_setter: function (value) {
if (value) this.$ready.push(this._init_dataprocessor);
return value;
},
waitSave: function (handler) {
var _this3 = this;
return dp(this)._promise(function () {
handler.call(_this3);
}).then(function (many) {
return many.length == 1 ? many[0] : many;
});
},
scheme_setter: function (value) {
this.data.scheme(value);
},
dataFeed_setter: function (value) {
value = proxy$5.$parse(value);
this.data.attachEvent("onBeforeFilter", bind(function (text, filtervalue) {
var _this4 = this;
var result; //complex filtering, can't be routed to dataFeed
if (typeof text == "function") return true; //we have dataFeed and some text
if (this._settings.dataFeed && (text || filtervalue)) {
text = text || "id";
if (filtervalue && _typeof(filtervalue) == "object") filtervalue = filtervalue.id;
var url = this._settings.dataFeed; //url data feed
if (typeof url == "string") {
var urldata = "filter[" + text + "]=" + encodeURIComponent(filtervalue);
result = this._fetch(url + (url.indexOf("?") < 0 ? "?" : "&") + urldata, this._settings.datatype);
} //js data feed
else {
var filter = {};
filter[text] = filtervalue;
if (typeof url == "function") {
result = url.call(this, filtervalue, filter);
} else if (url.$proxy && url.load) {
result = url.load(this, {
filter: filter
});
}
}
if (result) {
if (!result.then) result = Deferred.resolve(result);
result.then(function (data) {
_this4._onLoad(data, true);
_this4.data.callEvent("onAfterFilter", []);
}, function (x) {
return _this4._onLoadError(x);
});
}
return false;
}
}, this));
return value;
},
_call_onready: function () {
if (this._settings.ready && !this._ready_was_used) {
var code = toFunctor(this._settings.ready, this.$scope);
if (code) delay(code, this, arguments);
if (this.callEvent) delay(this.callEvent, this, ["onReady", []]);
this._ready_was_used = true;
}
},
_call_onclearall: function (soft) {
this._data_generation++;
if (!soft) {
this._load_count = false;
this._feed_last = {};
this.waitData = Deferred.defer();
}
},
_call_on_config: function (config) {
this._parseSeetingColl(config);
}
}, AtomDataLoader);
var DataState = {
getState: function () {
var _this = this;
var cols_n = this.config.columns.length;
var columns = this.config.columns;
var settings = {
ids: [],
size: [],
select: this.getSelectedId(true),
scroll: this.getScrollState()
};
for (var i = 0; i < cols_n; i++) {
var col = columns[i];
settings.ids.push(col.id);
settings.size.push(col.fillspace || col.adjust ? -1 : col.width);
}
settings.order = [].concat(this._hidden_column_order.length ? this._hidden_column_order : settings.ids);
if (this._last_order.length) {
var sort = this._last_order.map(function (id) {
return {
id: id,
dir: _this._last_sorted[id].dir
};
});
settings.sort = sort.length == 1 ? sort[0] : sort;
} //this method will try to access the rendered values
//just ignore it if grid is not rendered yet
if (this._filter_elements && this._dtable_fully_ready) {
var filter = {};
var any_filter = 0;
for (var key in this._filter_elements) {
if (this._hidden_column_hash[key]) continue;
var f = this._filter_elements[key];
f[1].value = filter[key] = f[2].getValue(f[0]);
any_filter = 1;
}
if (any_filter) settings.filter = filter;
}
settings.hidden = [];
for (var _key in this._hidden_column_hash) {
settings.hidden.push(_key);
}
return settings;
},
setState: function (obj) {
var _this2 = this;
var columns = this.config.columns;
if (!obj) return;
this.markSorting();
this._last_order = [];
this._last_sorted = {};
this.blockEvent();
if (obj.order && obj.order.length) {
this._hidden_column_order = _to_array([].concat(obj.order));
var rs = obj.order.length - this._settings.rightSplit;
this._hidden_split = [this._settings.leftSplit, rs, this._settings.rightSplit];
}
if (obj.hidden) {
var hihash = {};
for (var i = 0; i < obj.hidden.length; i++) {
hihash[obj.hidden[i]] = true;
if (!this._hidden_column_order.length) this.hideColumn(obj.hidden[i]);
}
if (this._hidden_column_order.length) {
for (var _i = 0; _i < this._hidden_column_order.length; _i++) {
var hikey = this._hidden_column_order[_i];
if (!!hihash[hikey] == !this._hidden_column_hash[hikey]) this.hideColumn(hikey, {}, false, !!hihash[hikey]);
}
}
}
if (obj.ids) {
var reorder = false;
for (var _i2 = 0; _i2 < columns.length; _i2++) {
if (columns[_i2].id != obj.ids[_i2]) reorder = true;
}
if (reorder) {
for (var _i3 = 0; _i3 < obj.ids.length; _i3++) {
columns[_i3] = this.getColumnConfig(obj.ids[_i3]) || columns[_i3];
}
this.refreshColumns();
}
}
if (obj.size) {
var cols_n = Math.min(obj.size.length, columns.length);
for (var _i4 = 0; _i4 < cols_n; _i4++) {
var col = columns[_i4];
if (col && obj.size[_i4] > 0 && col.width != obj.size[_i4]) {
delete col.fillspace;
delete col.adjust;
this._setColumnWidth(_i4, obj.size[_i4], true);
}
}
}
this.unblockEvent();
var silent = !(this._settings.leftSplit || this._settings.rightSplit);
this._updateColsSizeSettings(silent);
this.callEvent("onStructureUpdate", []);
var server = this._skip_server_op = {};
if (obj.sort) {
var sort = obj.sort,
multi = true;
if (!isArray(sort)) {
sort = [sort];
multi = false;
}
for (var _i5 = 0; _i5 < sort.length; _i5++) {
var _col = this.getColumnConfig(sort[_i5].id);
if (_col) {
this._sort(_col.id, sort[_i5].dir, _col.sort, multi);
if (_col.sort == "server") server.sort = true;
}
}
}
if (obj.filter) {
//temporary disable filtering
var temp = this.filterByAll;
this.filterByAll = function () {}; //apply defined filters
for (var key in obj.filter) {
var value = obj.filter[key];
var f = this._filter_elements[key];
if (!value || !f) continue;
f[2].setValue(f[0], value);
var contentid = f[1].contentId;
if (contentid) this._active_headers[contentid].value = value;
} //remove old filters
for (var _key2 in this._filter_elements) {
if (!obj.filter[_key2]) {
var _f = this._filter_elements[_key2];
_f[2].setValue(_f[0], "");
}
} //restore and apply filtering
this.filterByAll = temp;
this.filterByAll();
} // apply server filter\sort once
delete this._skip_server_op;
if (server.sort || server.filter) this.loadNext(0, 0, 0, 0, true, true).then(function () {
if (server.sort) _this2._on_after_sort(server.$params);
if (server.filter) _this2._on_after_filter();
});
if (obj.select && this.select) {
var select = obj.select;
this.unselect();
for (var _i6 = 0; _i6 < select.length; _i6++) {
if (!select[_i6].row || this.exists(select[_i6].row)) this._select(select[_i6], true);
}
}
if (obj.scroll) this.scrollTo(obj.scroll.x, obj.scroll.y);
}
};
/*
Behavior:DragItem - adds ability to move items by dnd
dnd context can have next properties
from - source object
to - target object
source - id of dragged item(s)
target - id of drop target, null for drop on empty space
start - id from which DND was started
*/
var DragItem = {
//helper - defines component's container as active zone for dragging and for dropping
_initHandlers: function (obj, source, target) {
if (!source) DragControl.addDrop(obj._contentobj, obj, true);
if (!target) DragControl.addDrag(obj._contentobj, obj);
this.attachEvent("onDragOut", function (a, b) {
this.$dragMark(a, b);
});
this.attachEvent("onBeforeAutoScroll", function () {
var context = DragControl.getContext();
return !!(DragControl._active && context && (context.to === this || this._auto_scroll_force));
});
},
drag_setter: function (value) {
if (value) {
exports.extend(this, AutoScroll, true);
if (value == "order" || value == "move") exports.extend(this, use("DragOrder"), true);
if (value == "inner" || value == "order") this._inner_drag_only = true;
this._initHandlers(this, value == "source", value == "target");
delete this.drag_setter; //prevent double initialization
}
return value;
},
/*
s - source html element
t - target html element
d - drop-on html element ( can be not equal to the target )
e - native html event
*/
//called when drag moved over possible target
$dragIn: function (s, t, e) {
var id = this.locate(e) || null;
var context = DragControl._drag_context; //in inner drag mode - ignore dnd from other components
if ((this._inner_drag_only || context.from._inner_drag_only) && context.from !== this) return false;
var to = DragControl.getMaster(t); //previous target
var html = this.getItemNode(id, e) || this._dataobj; //prevent double processing of same target
if (html == DragControl._landing) return html;
context.target = id;
context.to = to;
if (this._auto_scroll_delay) this._auto_scroll_delay = window.clearTimeout(this._auto_scroll_delay);
var fragile = this.addRowCss && env.touch && !this._settings.prerender;
if (this._settings.dragscroll !== false && !fragile) this._auto_scroll_delay = delay(function (pos$$1, id) {
this._drag_pause(id);
this._auto_scroll(pos$$1, id);
}, this, [pos(e), id], 250);
if (!this.$dropAllow(context, e) || !this.callEvent("onBeforeDragIn", [context, e])) {
context.to = context.target = null;
if (this._auto_scroll_delay) this._auto_scroll_delay = window.clearTimeout(this._auto_scroll_delay);
return null;
} //mark target only when landing confirmed
this.$dragMark(context, e);
return html;
},
$dropAllow: function () {
return true;
},
_drag_pause: function () {//may be reimplemented in some components
// tree for example
},
_target_to_id: function (target) {
return target && _typeof(target) === "object" ? target.toString() : target;
},
//called when drag moved out from possible target
$dragOut: function (s, t, n, e) {
var id = (this._viewobj.contains(n) ? this.locate(e) : null) || null;
var context = DragControl._drag_context; //still over previous target
if ((context.target || "").toString() == (id || "").toString()) return null;
if (this._auto_scroll_delay) this._auto_scroll_delay = window.clearTimeout(this._auto_scroll_delay); //unmark previous target
context.target = context.to = null;
this.callEvent("onDragOut", [context, e]);
return null;
},
//called when drag moved on target and button is released
$drop: function (s, t, e) {
var context = DragControl._drag_context; //finalize context details
context.to = this;
this._define_index(s, t, context); //unmark last target
this.$dragMark({}, e);
if (context.from && context.from != context.to && context.from.callEvent) {
if (!context.from.callEvent("onBeforeDropOut", [context, e])) return;
}
if (!this.callEvent("onBeforeDrop", [context, e])) return; //moving
this._context_to_move(context, e);
this.callEvent("onAfterDrop", [context, e]);
},
_define_index: function (s, t, context) {
var target = this._target_to_id(context.target);
if (this.getBranchIndex) {
if (target) {
context.parent = this.getParentId(target);
context.index = this.getBranchIndex(target);
} else context.index = -1;
} else context.index = target ? this.getIndexById(target) : this.count();
},
_context_to_move: function (context) {
assert(context.from, "Unsopported d-n-d combination");
if (context.from && context.from.move) {
//from different component with item dnd
var details = {
parent: context.parent,
mode: context.pos
};
context.from.move(context.source, context.index, context.to, details);
}
},
$longTouchLimit: true,
_getDragItemPos: function (pos$$1, e) {
if (this.getItemNode) {
var id = this.locate(e, true); //in some case, node may be outiside of dom ( spans in datatable for example )
//so getItemNode can return null
var node = id ? this.getItemNode(id) : null;
return node ? offset(node) : node;
}
},
//called when drag action started
$drag: function (s, e) {
var id = this.locate(e, true);
if (id) {
var list = [id];
if (this.getSelectedId) {
//has selection model
//if dragged item is one of selected - drag all selected
var selection = this.getSelectedId(true, true);
if (selection && selection.length > 1 && _power_array.find.call(selection, id) != -1) {
var hash = {};
list = [];
for (var i = 0; i < selection.length; i++) {
hash[selection[i]] = true;
}
for (var _i = 0; _i < this.data.order.length; _i++) {
var hash_id = this.data.order[_i];
if (hash[hash_id]) list.push(hash_id);
}
}
} //save initial dnd params
var context = DragControl._drag_context = {
source: list,
start: id
};
context.from = this;
if (this.callEvent("onBeforeDrag", [context, e])) {
if (env.touch && this._touch_scroll == "touch") delay(function () {
Touch._start_context = null;
}); //set drag representation
return context.html || this.$dragHTML(this.getItem(id), e, context);
}
}
return null;
},
$dragHTML: function (obj, e, context) {
var html = this._toHTML(obj);
if (isArray(context.source) && context.source.length > 1) html = this._toMultipleHTML(html, context.source.length);
return html;
},
_toMultipleHTML: function (html, len) {
html = "<div class='webix_drag_main'>" + html + "</div>";
var multiple = "<div class='webix_drag_multiple'></div>";
if (len > 2) multiple = "<div class='webix_drag_multiple_last'></div>" + multiple;
return multiple + html + "<span class='webix_badge'>" + len + "</span>";
},
$dragMark: function (context) {
var target = null;
if (context.target) target = this._target_to_id(context.target); //touch webkit will stop touchmove event if source node removed
if (this._marked && this._marked != target) {
this._remove_css([this._marked], "webix_drag_over", true);
this._marked = null;
}
if (!this._marked && target) {
this._marked = target;
this._add_css([target], "webix_drag_over", true);
return target;
}
return !!context.to;
},
_add_css: function (source, css) {
for (var i = 0; i < source.length; i++) {
this.addCss(source[i], css);
}
},
_remove_css: function (source, css) {
for (var i = 0; i < source.length; i++) {
this.removeCss(source[i], css);
}
},
// methods used in order/move modes
$dropHTML: function () {
return "";
},
_set_drop_area: function (target, t) {
var node = this.getItemNode(target);
if (node) {
node.parentNode.insertBefore(DragControl._dropHTML[0], node);
} else t.children[0].appendChild(DragControl._dropHTML[0]);
}
};
var DragOrder = {
$drag: function (s, e) {
var html = DragItem.$drag.apply(this, arguments);
if (!html) return html;
var context = DragControl._drag_context;
if (this._close_branches) this._close_branches(context);
if (this._inner_drag_only && this.getBranchIndex) this._drag_order_stored_left = this._drag_order_complex ? (this.getItem(context.start).$level + 1) * 20 + 8 : 0;
if (isArray(context.source)) {
DragControl._setDragOffset(e);
this._add_css(context.source, "webix_invisible");
}
return html;
},
$dragIn: function (s, t, e) {
var html = DragItem.$dragIn.apply(this, arguments);
if (!html) return html;
if (!DragControl._dropHTML) DragControl._dropHTML = this._init_drop_area();
var context = DragControl._drag_context;
var target = "$webix-last";
if (context.target) target = this._target_to_id(context.target);
if (target != "$webix-last" && target != "$webix-drop") {
var settings = {
direction: this._settings.layout || this._drag_direction || "y",
x: "width",
y: "height"
};
var ofs = offset(html);
var direction = pos(e)[settings.direction] - ofs[settings.direction];
if (direction * 2 > ofs[settings[settings.direction]]) target = this.getNextId(target) || "$webix-last";
}
if (target == this._marked_item_id || target == "$webix-drop") return html;
this._marked_item_id = target;
this._set_drop_area(target, t);
return html;
},
$dragPos: function (pos$$1) {
if (!this._inner_drag_only) {
var context = DragControl._drag_context;
pos$$1.y += context.y_offset;
pos$$1.x += context.x_offset;
return;
}
var box = offset(this.$view);
var xdrag = this._settings.layout == "x";
if (xdrag) {
box.x -= 12;
pos$$1.y = box.y - 8;
pos$$1.x = pos$$1.x - 18;
if (pos$$1.x < box.x) pos$$1.x = box.x;else {
var max = box.x + box.width;
if (pos$$1.x > max) pos$$1.x = max;
}
} else {
box.y += (this._header_height || 0) - 12;
pos$$1.x = box.x + 8 + (this._drag_order_stored_left || 0);
pos$$1.y = pos$$1.y - 18;
if (pos$$1.y < box.y) pos$$1.y = box.y;else {
var _max = box.y + box.height - (this._header_height || 0);
if (pos$$1.y > _max) pos$$1.y = _max;
}
}
},
$dragOut: function (s, ot, nt) {
if (ot != nt) {
if (this._remove_drop_area) this._remove_drop_area();else remove(DragControl._dropHTML);
this._marked_item_id = DragControl._dropHTML = null;
}
return DragItem.$dragOut.apply(this, arguments);
},
_define_index: function (s, t, context) {
var target = this._marked_item_id == "$webix-last" ? null : this._marked_item_id;
if (this.getBranchIndex) {
if (target) {
context.parent = this.getParentId(target);
context.index = this.getBranchIndex(target);
if (s == t && this.getParentId(context.start) == context.parent && this.getBranchIndex(context.start) < context.index) context.index -= 1;
} else context.index = -1;
} else {
context.index = target ? this.getIndexById(target) : this.count();
context.index -= s == t && this.getIndexById(context.start) < context.index ? 1 : 0;
}
},
$dragDestroy: function () {
var context = DragControl._drag_context;
if (isArray(context.source)) this._remove_css(context.source, "webix_invisible");
remove(DragControl._html);
},
_init_drop_area: function () {
var node = document.createElement("div");
node.className = "webix_drop_area";
node.style.width = this.type.width + "px";
node.style.height = this.type.height + "px";
node.innerHTML = this.$dropHTML();
node.setAttribute(this._id, "$webix-drop");
return [node];
},
$dragMark: function () {
return false;
}
};
define("DragOrder", DragOrder);
var Undo = {
$init: function () {
this._undoHistory = exports.extend([], _power_array, true);
this._undoCursor = -1;
},
undo_setter: function (value) {
if (value) {
this._init_undo();
this._init_undo = function () {};
}
return value;
},
_init_undo: function () {
var view = this; // drag-n-drop
this.attachEvent("onBeforeDrop", function (context) {
if (context.from == context.to) {
var item = view._draggedItem = copy(this.getItem(context.start));
if (this.data.branch) {
item.$index = this.getBranchIndex(item.id);
} else item.$index = this.getIndexById(item.id);
}
});
this.data.attachEvent("onDataMove", function (sid) {
if (view._draggedItem && view._draggedItem.id == sid) {
var data = view._draggedItem;
view._draggedItem = null;
view._addToHistory(sid, data, "move");
}
}); // add, remove
this.data.attachEvent("onBeforeDelete", function (id) {
if (this.getItem(id)) {
var item = view._deletedItem = copy(this.getItem(id));
if (this.branch) {
item.$index = this.getBranchIndex(id);
if (this.branch[id]) item.$branch = copy(this.serialize(id));
} else item.$index = this.getIndexById(id);
}
});
this.data.attachEvent("onDataUpdate", function (id, data, old) {
view._addToHistory(id + "", old, "update");
});
this.data.attachEvent("onStoreUpdated", function (id, item, mode) {
var data = null;
if (id) {
if (mode == "add") {
data = copy(item);
} else if (mode == "delete") {
data = view._deletedItem;
}
if (data) view._addToHistory(id, data, mode);
}
}); // id change
this.data.attachEvent("onIdChange", function (oldId, newId) {
if (_typeof(oldId) == "object") oldId = oldId.row;
for (var i = 0; i < view._undoHistory.length; i++) {
if (view._undoHistory[i].id == oldId) {
view._undoHistory[i].id = newId;
}
}
});
},
_addToHistory: function (id, data, action) {
if (!this._skipHistory && this._settings.undo) {
this._undoHistory.push({
id: id,
action: action,
data: data
});
if (this._undoHistory.length == 20) this._undoHistory.splice(0, 1);
if (!this._skipCursorInc) this._undoCursor = this._undoHistory.length - 1;
}
},
ignoreUndo: function (func, master) {
this._skipHistory = true;
func.call(master || this);
this._skipHistory = false;
},
removeUndo: function (id) {
for (var i = this._undoHistory.length - 1; i >= 0; i--) {
if (this._undoHistory[i].id == id) {
if (this._undoHistory[i].action == "id") {
id = this._undoHistory[i].data;
}
this._undoHistory.removeAt(i);
}
}
this._undoCursor = this._undoHistory.length - 1;
},
undo: function (id) {
if (id) {
this.ignoreUndo(function () {
var data, i;
for (i = this._undoHistory.length - 1; !data && i >= 0; i--) {
if (this._undoHistory[i].id == id) data = this._undoHistory[i];
}
if (data) {
/*if(data.action == "id")
id = data.data;*/
this._undoAction(data);
this._undoHistory.removeAt(i + 1);
this._undoCursor = this._undoHistory.length - 1;
}
});
} else {
var data = this._undoHistory[this._undoCursor];
if (data) {
this.ignoreUndo(function () {
this._undoAction(data);
this._undoHistory.removeAt(this._undoCursor);
});
this._undoCursor--;
/*if(data.action == "id")
this.undo();*/
}
}
},
_undoAction: function (obj) {
if (obj.action == "delete") {
var branch = null,
parentId = obj.data.$parent;
if (obj.data.$branch) {
branch = {
parent: obj.id,
data: copy(obj.data.$branch)
};
delete obj.data.$branch;
if (parentId && !this.data.pull[parentId]) parentId = 0;
}
this.add(obj.data, obj.data.$index, parentId);
if (branch) {
this.parse(branch);
}
} else if (obj.action == "add") {
this.remove(obj.id);
} else if (obj.action == "update") {
this.updateItem(obj.id, obj.data);
} else if (obj.action == "move") {
if (obj.data.$parent) {
if (this.getItem(obj.data.$parent)) this.move(obj.id, obj.data.$index, null, {
parent: obj.data.$parent
});
} else this.move(obj.id, obj.data.$index);
}
/*else if(obj.action == "id"){
this.data.changeId(obj.id, obj.data);
}*/
}
};
function init_suggest(editor, input) {
var suggest = editor.config.suggest;
if (suggest) {
var box = editor.config.suggest = create_suggest(suggest);
var boxobj = $$(box);
if (boxobj && input) boxobj.linkInput(input);
return boxobj;
}
}
function attach_editend(suggest) {
if (suggest && suggest.setMasterValue && !suggest._editor_initialized) {
suggest._editor_initialized = true;
suggest.attachEvent("onValueSuggest", function () {
delay(function () {
callEvent("onEditEnd", []);
});
});
}
}
function create_suggest(config) {
if (typeof config == "string") return config;
if (config.linkInput) return config._settings.id;
if (_typeof(config) == "object") {
if (isArray(config)) config = {
data: config
};
config.view = config.view || "suggest";
} else if (config === true) config = {
view: "suggest"
};
var obj = ui(config);
return obj.config.id;
}
function getLabel(config) {
var text = config.header && config.header[0] ? config.header[0].text : config.editValue || config.label;
return (text || "").toString().replace(/<[^>]*>/g, "");
}
/*
this.node - html node, available after render call
this.config - editor config
this.value - original value
this.popup - id of popup
*/
var editors = {
"text": {
focus: function () {
this.getInputNode(this.node).focus();
this.getInputNode(this.node).select();
},
getValue: function () {
return this.getInputNode(this.node).value;
},
setValue: function (value) {
var input = this.getInputNode(this.node);
input.value = value;
var suggest = init_suggest(this, input);
attach_editend(suggest);
},
getInputNode: function () {
return this.node.firstChild;
},
render: function () {
return create("div", {
"class": "webix_dt_editor"
}, "<input type='text' aria-label='" + getLabel(this.config) + "'>");
}
},
"inline-checkbox": {
render: function () {
return {};
},
getValue: function () {
return this.node.checked;
},
setValue: function () {},
focus: function () {
this.node.focus();
},
getInputNode: function () {},
$inline: true
},
"inline-text": {
render: function () {
return {};
},
getValue: function () {
return this.node.value;
},
setValue: function () {},
focus: function () {
try {
//IE9
this.node.select();
this.node.focus();
} catch (e) {} //eslint-disable-line
},
getInputNode: function () {},
$inline: true
},
"checkbox": {
focus: function () {
this.getInputNode().focus();
},
getValue: function () {
return this.getInputNode().checked;
},
setValue: function (value) {
this.getInputNode().checked = !!value;
},
getInputNode: function () {
return this.node.firstChild.firstChild;
},
render: function () {
return create("div", {
"class": "webix_dt_editor"
}, "<div><input type='checkbox' aria-label='" + getLabel(this.config) + "'></div>");
}
},
"select": {
focus: function () {
this.getInputNode().focus();
},
getValue: function () {
return this.getInputNode().value;
},
setValue: function (value) {
this.getInputNode().value = value;
},
getInputNode: function () {
return this.node.firstChild;
},
render: function () {
var html = "";
var options = this.config.options || this.config.collection;
assert(options, "options not defined for select editor");
if (options.data && options.data.each) options.data.each(function (obj) {
html += "<option value='" + obj.id + "'>" + obj.value + "</option>";
});else {
if (isArray(options)) {
for (var i = 0; i < options.length; i++) {
var rec = options[i];
var isplain = isUndefined(rec.id);
var id = isplain ? rec : rec.id;
var label = isplain ? rec : rec.value;
html += "<option value='" + id + "'>" + label + "</option>";
}
} else for (var key in options) {
html += "<option value='" + key + "'>" + options[key] + "</option>";
}
}
return create("div", {
"class": "webix_dt_editor"
}, "<select aria-label='" + getLabel(this.config) + "'>" + html + "</select>");
}
},
popup: {
focus: function () {
this.getInputNode().focus();
},
destroy: function () {
this.getPopup().hide();
},
getValue: function () {
return this.getInputNode().getValue() || "";
},
setValue: function (value) {
this.getPopup().show(this.node);
this.getInputNode().setValue(value);
},
getInputNode: function () {
return this.getPopup().getChildViews()[0];
},
getPopup: function () {
if (!this.config.$popup) this.config.$popup = this.createPopup();
return $$(this.config.$popup);
},
createPopup: function () {
var popup = this.config.popup || this.config.suggest;
if (popup) {
var pobj;
if (_typeof(popup) == "object" && !popup.name) {
popup.view = popup.view || "suggest";
pobj = ui(copy(popup));
} else pobj = $$(popup); //custom popup may be linked already
if (!pobj._linked) {
if (pobj.linkInput) pobj.linkInput(document.body);else if (this.linkInput) this.linkInput(document.body);
pobj._linked = true;
}
attach_editend(pobj);
return pobj;
}
var type = editors.$popup[this.popupType];
if (typeof type != "string" && !type.name) {
type = editors.$popup[this.popupType] = ui(type);
this.popupInit(type);
if (!type.linkInput) this.linkInput(document.body);
}
return type._settings.id;
},
linkInput: function (node) {
_event(toNode(node), "keydown", bind(function (e) {
//abort, when editor was not initialized yet
if (!this.config.$popup) return;
var code = e.which || e.keyCode,
list = this.getInputNode();
if (!list.isVisible()) return;
if (list.moveSelection && code < 41 && code > 32) {
var dir;
if (code == 33) dir = "pgup";
if (code == 34) dir = "pgdown";
if (code == 35) dir = "bottom";
if (code == 36) dir = "top";
if (code == 37) dir = "left";
if (code == 38) dir = "up";
if (code == 39) dir = "right";
if (code == 40) dir = "down";
list.moveSelection(dir);
} // shift+enter support for 'popup' editor
else if (code === 13 && (e.target.nodeName !== "TEXTAREA" || !e.shiftKey)) callEvent("onEditEnd", []);
}, this));
},
popupInit: function () {},
popupType: "text",
render: function () {
return {};
},
$inline: true
}
};
editors.color = exports.extend({
focus: function () {},
popupType: "color",
popupInit: function (popup) {
popup.getChildViews()[0].attachEvent("onItemClick", function (value) {
callEvent("onEditEnd", [value]);
});
}
}, editors.popup);
editors.date = exports.extend({
focus: function () {},
popupType: "date",
setValue: function (value) {
this._is_string = this.config.stringResult || value && typeof value == "string";
editors.popup.setValue.call(this, value);
},
getValue: function () {
return this.getInputNode().getValue(this._is_string ? i18n.parseFormatStr : "") || "";
},
popupInit: function (popup) {
popup.getChildViews()[0].attachEvent("onAfterDateSelect", function (value) {
callEvent("onEditEnd", [value]);
});
}
}, editors.popup);
editors.combo = exports.extend({
_create_suggest: function (config) {
var suggest, id;
if (this.config.popup) {
suggest = this.config.popup;
id = suggest.config.id;
} else if (config) {
id = create_suggest(config);
suggest = $$(id);
} else id = this._shared_suggest(config);
attach_editend(suggest);
return id;
},
_shared_suggest: function () {
var e = editors.combo;
return e._suggest = e._suggest || this._create_suggest(true);
},
render: function () {
var node = create("div", {
"class": "webix_dt_editor"
}, "<input type='text' role='combobox' aria-label='" + getLabel(this.config) + "'>"); //save suggest id for future reference
var suggest = this.config.suggest = this._create_suggest(this.config.suggest);
if (suggest) {
$$(suggest).linkInput(node.firstChild, true);
_event(node.firstChild, "click", bind(this.showPopup, this));
}
return node;
},
getPopup: function () {
return $$(this.config.suggest);
},
showPopup: function () {
var popup = this.getPopup();
var list = popup.getList();
var input = this.getInputNode();
var value = this._initial_value;
popup.show(input);
input.setAttribute("aria-expanded", "true");
if (value) {
assert(list.exists(value), "Option with ID " + value + " doesn't exist");
if (list.exists(value)) {
list.select(value);
list.showItem(value);
}
} else {
list.unselect();
list.showItem(list.getFirstId());
}
popup._last_input_target = input;
},
afterRender: function () {
this.showPopup();
},
setValue: function (value) {
this._initial_value = value;
if (this.config.suggest) {
var sobj = $$(this.config.suggest);
var data = this.config.collection || this.config.options;
if (data) sobj.getList().data.importData(data);
this.getInputNode(this.node).value = sobj.getItemText(value);
}
},
getValue: function () {
var value = this.getInputNode().value;
if (this.config.suggest) {
var suggest = $$(this.config.suggest),
list = suggest.getList();
if (value || list.getSelectedId && list.getSelectedId()) value = suggest.getSuggestion(value);
}
return value;
}
}, editors.text);
editors.richselect = exports.extend({
focus: function () {},
getValue: function () {
return this.getPopup().getValue();
},
setValue: function (value) {
var suggest = this.config.collection || this.config.options;
this.getInputNode();
if (suggest) this.getPopup().getList().data.importData(suggest);
this.getPopup().show(this.node);
this.getPopup().setValue(value);
},
getInputNode: function () {
return this.getPopup().getList();
},
popupInit: function (popup) {
popup.linkInput(document.body);
attach_editend(popup);
},
popupType: "richselect"
}, editors.popup);
editors.password = exports.extend({
render: function () {
var _this = this;
var node = create("div", {
"class": "webix_dt_editor webix_password_editor"
}, "<input type='password' aria-label='" + getLabel(this.config) + "'><span class='webix_icon wxi-eye'></span>");
var icon = node.querySelector(".webix_icon");
_event(icon, "click", function () {
_this.toggleInput();
_this.getInputNode(_this.node).focus();
});
return node;
},
toggleInput: function () {
var input = this.getInputNode(this.node);
var isPassword = input.getAttribute("type") === "password";
input.setAttribute("type", isPassword ? "text" : "password");
var icon = input.nextSibling;
icon.className = "webix_icon wxi-eye".concat(isPassword ? "-slash" : "");
}
}, editors.text);
editors.$popup = {
text: {
view: "popup",
width: 250,
height: 150,
body: {
view: "textarea"
}
},
color: {
view: "popup",
body: {
view: "colorboard"
}
},
date: {
view: "popup",
width: 250,
height: 250,
padding: 0,
body: {
view: "calendar",
icons: true,
borderless: true
}
},
richselect: {
view: "suggest",
body: {
view: "list",
select: true
}
},
multiselect: {
view: "multisuggest",
suggest: {
button: true
}
}
};
/*
Behavior:EditAbility - enables item operation for the items
@export
edit
stopEdit
*/
var EditAbility = {
defaults: {
editaction: "click"
},
$init: function (config) {
this._editors = {};
this._in_edit_mode = 0;
this._edit_open_time = 0;
this._contentobj.style.position = "relative";
if (config) config.onDblClick = config.onDblClick || {};
this.attachEvent("onAfterRender", this._refocus_inline_editor); //when we call extend the editable prop can be already set
if (this._settings.editable) this._init_edit_events_once();
exports.extend(this, Undo);
},
_refocus_try: function (newnode) {
try {
//Chrome throws an error if selectionStart is not accessible
if (typeof newnode.selectionStart == "number") {
newnode.selectionStart = newnode.selectionEnd = newnode.value.length;
} else if (typeof newnode.createTextRange != "undefined") {
var range = newnode.createTextRange();
range.collapse(false);
range.select();
}
} catch (e) {} // eslint-disable-line
},
_refocus_inline_editor: function () {
var editor = this.getEditor();
if (editor && editor.$inline && !editor.getPopup) {
var newnode = this._locateInput(editor);
if (newnode && newnode != editor.node) {
var text = editor.node.value;
editor.node = newnode;
newnode.value = text;
newnode.focus();
this._refocus_try(newnode);
} else this.editStop();
}
},
editable_setter: function (value) {
if (value) this._init_edit_events_once();
return value;
},
_init_edit_events_once: function () {
//will close editor on any click outside
var e1 = attachEvent("onEditEnd", bind(function () {
if (this._in_edit_mode) this.editStop();
}, this));
var e2 = attachEvent("onClick", bind(function (e) {
//but ignore click which opens editor
if (this._in_edit_mode && new Date() - this._edit_open_time > 200) {
if (!this._last_editor || this._last_editor.popupType || !e || !this._last_editor.node || !this._last_editor.node.contains(e.target)) this.editStop();
}
}, this));
this.attachEvent("onDestruct", function () {
detachEvent(e1);
detachEvent(e2);
}); //property sheet has simple data object, without events
if (this.data.attachEvent) this.data.attachEvent("onIdChange", bind(function (oldid, newid) {
this._changeEditorId(oldid, newid);
}, this)); //when clicking on row - will start editor
this.attachEvent("onItemClick", function (id) {
if (this._settings.editable && this._settings.editaction == "click") this.edit(id);
});
this.attachEvent("onItemDblClick", function (id) {
if (this._settings.editable && this._settings.editaction == "dblclick") this.edit(id);
}); //each time when we clicking on input, reset timer to prevent self-closing
this._reset_active_editor = bind(function () {
this._edit_open_time = new Date();
}, this);
this._init_edit_events_once = function () {};
if (this._component_specific_edit_init) this._component_specific_edit_init();
},
_handle_live_edits: function () {
delay(function () {
var editor = this.getEditor();
if (editor && editor.config.liveEdit) {
var state$$1 = {
value: editor.getValue(),
old: editor.value
};
if (state$$1.value == state$$1.old) return;
editor.value = state$$1.value;
this._set_new_value(editor, state$$1.value, false);
this.callEvent("onLiveEdit", [state$$1, editor]);
}
}, this);
},
_show_editor_form: function (id) {
var form = this._settings.form;
if (typeof form != "string") this._settings.form = form = ui(form).config.id;
form = $$(form);
var realform = form.setValues ? form : form.getChildViews()[0];
realform.setValues(this.getItem(id.row || id), false, "auto");
form.config.master = this.config.id;
form.show(this.getItemNode(id));
var first = realform.getChildViews()[0];
if (first.focus) first.focus();
},
edit: function (id, preserve, show) {
if (!this._settings.editable || !this.callEvent("onBeforeEditStart", [id])) return;
if (this._settings.form) return this._show_editor_form(id);
var editor = this._get_editor_type(id);
if (editor) {
if (this.getEditor(id)) return;
if (!preserve) this.editStop(); //render html input
assert(editors[editor], "Invalid editor type: " + editor);
var type = exports.extend({}, editors[editor]);
var node = this._init_editor(id, type, show);
if (type.config.liveEdit) this._live_edits_handler = this.attachEvent("onKeyPress", this._handle_live_edits);
var area = type.getPopup ? type.getPopup(node)._viewobj : node;
if (area) _event(area, "click", this._reset_active_editor);
if (node) _event(node, "change", this._on_editor_change, {
bind: {
view: this,
id: id
}
});
if (show !== false) type.focus();
if (this.$fixEditor) this.$fixEditor(type); //save time of creation to prevent instant closing from the same click
this._edit_open_time = state.edit_open_time = new Date();
UIManager.setFocus(this, true);
this.callEvent("onAfterEditStart", [id]);
return type;
}
return null;
},
getEditor: function (id) {
if (!id) return this._last_editor;
return this._editors[id];
},
_changeEditorId: function (oldid, newid) {
var editor = this._editors[oldid];
if (editor) {
this._editors[newid] = editor;
editor.id = newid;
delete this._editors[oldid];
}
},
_on_editor_change: function () {
if (this.view.hasEvent("onEditorChange")) this.view.callEvent("onEditorChange", [this.id, this.view.getEditorValue(this.id)]);
},
_get_edit_config: function () {
return this._settings;
},
_init_editor: function (id, type, show) {
type.config = this._get_edit_config(id);
var node = type.render();
if (type.$inline) node = this._locateInput(id);
type.node = node;
var item = this.getItem(id); //value can be configured by editValue option
var value = item[this._settings.editValue || "value"]; //if property was not defined - use empty value
if (isUndefined(value)) value = "";
type.setValue(value, item);
type.value = value;
this._addEditor(id, type); //show it over cell
if (show !== false) this.showItem(id);
if (!type.$inline) this._sizeToCell(id, node, true);
if (type.afterRender) type.afterRender();
return node;
},
_locate_cell: function (id) {
return this.getItemNode(id);
},
_locateInput: function (id) {
var cell = this._locate_cell(id);
if (cell) cell = cell.getElementsByTagName("input")[0] || cell;
return cell;
},
_get_editor_type: function () {
return this._settings.editor;
},
_addEditor: function (id, type) {
type.id = id;
this._editors[id] = this._last_editor = type;
this._in_edit_mode++;
},
_removeEditor: function (editor) {
if (this._last_editor == editor) this._last_editor = 0;
if (editor.destroy) editor.destroy();
delete editor.popup;
delete editor.node;
delete this._editors[editor.id];
this._in_edit_mode--;
},
focusEditor: function () {
var editor = this.getEditor.apply(this, arguments);
if (editor && editor.focus) editor.focus();
},
editCancel: function () {
this.editStop(null, null, true);
},
_applyChanges: function (el) {
if (el) {
var ed = this.getEditor();
if (ed && ed.getPopup && ed.getPopup() == el.getTopParentView()) return;
}
this.editStop();
},
editStop: function (id) {
if (this._edit_stop) return;
this._edit_stop = 1;
var cancel = arguments[2];
var result = 1;
if (!id) {
this._for_each_editor(function (editor) {
result = result * this._editStop(editor, cancel);
});
} else result = this._editStop(this._editors[id], cancel);
this._edit_stop = 0;
return result;
},
_cellPosition: function (id) {
var html = this.getItemNode(id);
return {
left: html.offsetLeft,
top: html.offsetTop,
height: html.offsetHeight,
width: html.offsetWidth,
parent: this._contentobj
};
},
_sizeToCell: function (id, node, inline) {
//fake inputs
if (!node.style) return;
var pos$$1 = this._cellPosition(id, null, true);
node.style.top = pos$$1.top + "px";
node.style.left = pos$$1.left + "px";
node.style.width = pos$$1.width - 1 + "px";
node.style.height = pos$$1.height - 1 + "px";
node.top = pos$$1.top; //later will be used during y-scrolling
if (inline) pos$$1.parent.appendChild(node);
return pos$$1;
},
_for_each_editor: function (handler) {
for (var editor in this._editors) {
handler.call(this, this._editors[editor]);
}
},
_editStop: function (editor, ignore) {
if (!editor || state._final_destruction) return;
var state$$1 = {
value: this._get_new_value(editor),
old: editor.value
};
if (this.callEvent("onBeforeEditStop", [state$$1, editor, ignore])) {
if (!ignore) {
//special case, state.old = 0, state.value = ""
//we need to state.old to string, to detect the change
var old = state$$1.old;
if (typeof state$$1.value == "string") old += "";
if (old != state$$1.value || editor.config.liveEdit) {
var item = this._set_new_value(editor, state$$1.value, true);
this.updateItem(editor.row || editor.id, item);
}
}
if (editor.$inline) editor.node = null;else remove(editor.node);
var popup = editor.config.suggest;
if (popup && typeof popup == "string") $$(popup).hide();
this._removeEditor(editor);
if (this._live_edits_handler) this.detachEvent(this._live_edits_handler);
this.callEvent("onAfterEditStop", [state$$1, editor, ignore]);
return 1;
}
return 0;
},
validateEditor: function (id) {
var result = true;
if (this._settings.rules) {
var editor = this.getEditor(id);
var key = editor.column || this._settings.editValue || "value";
var rule = this._settings.rules[key];
var all = this._settings.rules.$all;
var input = editor.getInputNode();
if ((rule || all) && !input._viewobj) {
//only for html inputs
var obj = this.data.getItem(editor.row || editor.id);
var value = editor.getValue();
if (rule) result = rule.call(this, value, obj, key);
if (all) result = all.call(this, value, obj, key) && result;
if (result) removeCss(input, "webix_invalid");else addCss(input, "webix_invalid");
callEvent("onLiveValidation", [editor, result, obj, value]);
}
}
return result;
},
getEditorValue: function (id) {
var editor;
if (arguments.length === 0) editor = this._last_editor;else editor = this.getEditor(id);
if (editor) return editor.getValue();
},
getEditState: function () {
return this._last_editor || false;
},
editNext: function (next, from) {
next = next !== false; //true by default
if (this._in_edit_mode == 1 || from) {
//only if one editor is active
var editor_next = this._find_cell_next(this._last_editor || from, function (id) {
if (this._get_editor_type(id)) return true;
return false;
}, next);
if (this.editStop()) {
//if we was able to close previous editor
if (editor_next) {
//and there is a new target
this.edit(editor_next); //init new editor
this._after_edit_next(editor_next);
}
return false;
}
}
},
//stab, used in datatable
_after_edit_next: function () {},
_find_cell_next: function (start, check, direction) {
var row = this.getIndexById(start.id);
var order = this.data.order;
if (direction) {
for (var i = row + 1; i < order.length; i++) {
if (check.call(this, order[i])) return order[i];
}
} else {
for (var _i = row - 1; _i >= 0; _i--) {
if (check.call(this, order[_i])) return order[_i];
}
}
return null;
},
_get_new_value: function (editor) {
return editor.getValue();
},
_set_new_value: function (editor, new_value, copy$$1) {
var item = copy$$1 ? {} : this.getItem(editor.id);
item[this._settings.editValue || "value"] = new_value;
return item;
}
};
var FlexLayout = {
$init: function () {
this.$view.className += " webix_flexlayout";
},
_fix_vertical_layout: function () {},
_beforeResetBorders: function () {},
_afterResetBorders: function () {},
$getSize: function () {
debug_size_box_start(this, true);
var w = 0,
h = 0,
g = this._settings.gravity;
this._sizes = [];
for (var i = 0; i < this._cells.length; i++) {
var size = this._cells[i].$getSize(0, 0);
this._sizes.push(size);
w = Math.max(w, size[0]);
h = Math.max(h, size[2]);
}
w += this._padding.left + this._padding.right;
h += this._padding.top + this._padding.bottom;
if (this._settings.width) w = Math.max(w, this._settings.width);
if (this._settings.height) h = Math.max(h, this._settings.height);
var self_size = [w, 100000, h, 100000, g];
debug_size_box_end(this, self_size);
return self_size;
},
render: function () {
this.resize();
},
_set_child_size: function () {
if (!this.isVisible(this._settings.id)) return;
var st = this.$view.style;
var margin = Math.round(this._margin / 2);
st.paddingTop = this._padding.top - margin + "px";
st.paddingBottom = this._padding.bottom - margin + "px";
st.paddingLeft = this._padding.left - margin + "px";
st.paddingRight = this._padding.right - margin + "px";
for (var i = 0; i < this._cells.length; i++) {
if (this._cells[i]._settings.hidden) continue;
var view = this._cells[i].$view;
var size = this._sizes[i];
var config = this._cells[i]._settings;
if (view) {
view.style.minWidth = size[0] + "px";
if (size[1] < 100000 && size[1] != size[0]) view.style.maxWidth = size[1] + "px";
view.style.flexBasis = config.flexBasis || size[0] + "px";
view.style.flexGrow = config.flexGrow || (size[1] != size[0] ? size[4] : 0);
view.style.height = size[3] != size[2] ? "auto" : size[2] + "px";
view.style.minHeight = size[2] + "px";
if (size[3] < 100000 && size[3] != size[2]) view.style.maxHeight = size[3] + "px";
view.style.margin = margin + "px";
}
}
var whs = [];
for (var _i = 0; _i < this._cells.length; _i++) {
if (this._cells[_i]._settings.hidden) continue;
var _view = this._cells[_i].$view;
whs[_i] = [_view.offsetWidth, _view.offsetHeight];
}
for (var _i2 = 0; _i2 < this._cells.length; _i2++) {
if (this._cells[_i2]._settings.hidden) continue;
var cell = this._cells[_i2];
var _view2 = cell.$view;
if (_view2) {
cell._settings.flex = true;
var _size = this._sizes[_i2];
var h = _size[2] == _size[3] ? _size[2] : whs[_i2][1];
cell.$setSize(whs[_i2][0], h);
cell._settings.flex = false;
}
}
this.$view.style.height = "";
this.$height = this._content_height = this.$view.scrollHeight;
this.$view.style.height = this._content_height + "px";
}
};
var GroupMethods = {
sum: function (property, data) {
data = data || this;
var summ = 0;
for (var i = 0; i < data.length; i++) {
var num = parseFloat(property(data[i]), 10);
if (!isNaN(num)) summ += num;
}
return summ;
},
min: function (property, data) {
data = data || this;
var min = Infinity;
for (var i = 0; i < data.length; i++) {
var num = parseFloat(property(data[i]), 10);
if (isNaN(num)) continue;
if (num < min) min = num;
}
return min === Infinity ? 0 : min * 1;
},
max: function (property, data) {
data = data || this;
var max = -Infinity;
for (var i = 0; i < data.length; i++) {
var num = parseFloat(property(data[i]), 10);
if (isNaN(num)) continue;
if (num > max) max = num;
}
return max === -Infinity ? 0 : max * 1;
},
count: function (property, data) {
var count = 0;
for (var i = 0; i < data.length; i++) {
var some = property(data[i]);
if (some !== null && typeof some !== "undefined") count++;
}
return count;
},
any: function (property, data) {
return property(data[0]);
},
string: function (property) {
return property.$name;
}
};
var GroupStore = {
$init: function () {
var _this = this;
this.attachEvent("onClearAll", function () {
return _this._not_grouped_order = null;
});
this.attachEvent("onSyncApply", function () {
return _this._not_grouped_order = null;
});
},
ungroup: function (target) {
if (this.getBranchIndex) {
if (!this._ungroupLevel(target)) return;
} else {
if (!this._not_grouped_order) return;
this.order = this._not_grouped_order;
this.pull = this._not_grouped_pull;
}
this.callEvent("onStoreUpdated", []);
},
_ungroupLevel: function (target) {
var _this2 = this;
var parent = target || 0;
var level = parent == "0" ? 1 : this.getItem(parent).$level + 1;
var changed = false;
var top = this.branch[parent];
var order = [];
for (var i = 0; i < top.length; i++) {
var id = top[i];
if (this.pull[id].$group) {
changed = true;
var group = this.branch[id];
if (group) this.branch[id] = group.filter(function (a) {
if (!_this2.pull[a].$footer) return a;
_this2._unregisterItem(a);
});
order = order.concat(this.branch[id] || []);
this._unregisterItem(id);
} else order.push(id);
}
if (!changed) return false;
this.branch[parent] = order;
this._fix_group_levels(this.branch[parent], parent, level);
if (typeof target === "undefined") this._ungroupLevel();
return true;
},
_unregisterItem: function (id) {
delete this.pull[id];
delete this.branch[id];
},
_group_processing: function (scheme) {
this.blockEvent();
this.group(scheme);
this.unblockEvent();
},
_group_prop_accessor: function (val) {
if (typeof val == "function") return val;
var acc = function (obj) {
return obj[val];
};
acc.$name = val;
return acc;
},
group: function (config, target) {
assert(config, "Empty config");
var input;
if (typeof config === "string") {
input = config;
config = {
by: this._group_prop_accessor(config),
map: {}
};
} else if (typeof config === "function") {
config = {
by: config,
map: {}
};
} else if (typeof config.by === "string") {
input = config.by;
config.by = this._group_prop_accessor(config.by);
}
config.map = config.map || {};
if (input && !config.map[input]) config.map[input] = [input];
config.missing = config.missing === undefined ? true : config.missing;
if (this.getBranchIndex) return this._group_tree(config, target);
if (!this._not_grouped_order) {
this._not_grouped_order = this.order;
this._not_grouped_pull = this.pull;
}
var groups = {};
var labels = [];
var missed = [];
var misGroup = config.missing;
this.each(function (data) {
var current = config.by(data);
if (!current && current !== 0) {
if (misGroup === false) return;
if (misGroup === true) {
missed.push(data);
return;
}
current = misGroup;
}
if (!groups[current]) {
labels.push({
id: current,
value: current,
$group: true,
$row: config.row
});
groups[current] = _to_array();
}
groups[current].push(data);
});
for (var i = 0; i < labels.length; i++) {
var group = labels[i];
this._map_group(config.map, group, groups[labels[i].id]);
if (this.hasEvent("onGroupCreated")) this.callEvent("onGroupCreated", [group.id, group.value, groups[labels[i].id]]);
}
this.order = _to_array();
this.pull = {};
this._fill_pull(labels);
this._fill_pull(missed);
this.callEvent("onStoreUpdated", []);
},
_fill_pull: function (arr) {
for (var i = 0; i < arr.length; i++) {
var id = this.id(arr[i]);
if (this.pull[id]) id = arr[i].id = uid();
this.pull[id] = arr[i];
this.order.push(id);
if (this._scheme_init) this._scheme_init(arr[i]);
}
},
_map_group: function (map, group, data) {
for (var prop in map) {
var functor = map[prop][1] || "any";
var property = this._group_prop_accessor(map[prop][0]);
if (typeof functor != "function") {
assert(GroupMethods[functor], "Unknown grouping rule: " + functor);
functor = GroupMethods[functor];
}
group[prop] = functor.call(this, property, data);
}
},
_group_tree: function (config, parent) {
//prepare
var level = 0;
if (parent) level = this.getItem(parent).$level;else parent = 0; //run
var topbranch = [];
var labels = [];
var missed = [];
var order = this.branch[parent];
var groups = {};
for (var i = 0; i < order.length; i++) {
var data = this.getItem(order[i]);
var current = config.by(data);
if (!current && current !== 0) if (config.missing === false) continue;else if (config.missing === true) {
missed.push(data.id);
continue;
} else current = config.missing;
var ancestor = groups[current];
if (!ancestor) {
var id = uid();
var newitem = this.pull[id] = {
id: id,
value: current,
$group: true,
$row: config.row
};
if (this._scheme_init) this._scheme_init(newitem);
labels.push(newitem);
ancestor = groups[current] = this.branch[id] = [];
ancestor._formath = [];
topbranch.push(id);
}
ancestor.push(data.id);
ancestor._formath.push(data);
}
this.branch[parent] = topbranch.concat(missed);
for (var _i = 0; _i < labels.length; _i++) {
var group = labels[_i];
this._map_group(config.map, group, this.branch[labels[_i].id]._formath);
if (this.hasEvent("onGroupCreated")) this.callEvent("onGroupCreated", [group.id, group.value, this.branch[group.id]._formath]);
if (config.footer) {
var _id = "footer$" + group.id;
var footer = this.pull[_id] = {
id: _id,
$footer: true,
value: group.value,
$level: level,
$count: 0,
$parent: group.id,
$row: config.footer.row
};
this._map_group(config.footer, footer, this.branch[labels[_i].id]._formath);
this.branch[group.id].push(footer.id);
this.callEvent("onGroupFooter", [footer.id, footer.value, this.branch[group.id]._formath]);
}
delete this.branch[group.id]._formath;
}
this._fix_group_levels(this.branch[parent], parent, level + 1);
this.callEvent("onStoreUpdated", []);
},
_fix_group_levels: function (branch, parent, level) {
if (parent) this.getItem(parent).$count = branch.length;
for (var i = 0; i < branch.length; i++) {
var item = this.pull[branch[i]];
item.$level = level;
item.$parent = parent;
var next = this.branch[item.id];
if (next) this._fix_group_levels(next, item.id, level + 1);
}
}
};
var Group = {
$init: function () {
exports.extend(this.data, GroupStore);
},
group: function (config, target) {
if (!target && target !== 0) {
this.$blockRender = true;
this.data.ungroup();
this.$blockRender = false;
}
this.data.group(config, target);
},
ungroup: function (target) {
this.data.ungroup(target);
}
};
/*aria-style handling for options of multiple-value controls (radio, segmented, tabbar)*/
var HTMLOptions = {
$init: function () {
var _this = this;
this.$ready.push(function () {
if (!_this.customRadio_setter || _this.config.customRadio) _event(_this.$view, "keydown", _this._moveSelection, {
bind: _this
});
});
},
_focus: function () {
if (!UIManager.canFocus(this)) return false;
var input = this._getInputNode();
if (input) for (var i = 0; i < input.length; i++) {
if (input[i].getAttribute("tabindex") == "0") return input[i].focus();
}
},
_blur: function () {
var input = this._getInputNode();
if (input) for (var i = 0; i < input.length; i++) {
if (input[i].getAttribute("tabindex") == "0") return input[i].blur();
}
},
_moveSelection: function (e) {
var code = e.which || e.keyCode;
if (code > 34 && code < 41) {
var inp = this._getInputNode();
var index$$1 = false;
if (!inp.length) return;
preventEvent(e);
var dir = code === 37 || code === 38 || code === 35 ? -1 : 1;
if (code === 35) index$$1 = inp.length - 1;else if (code === 36) index$$1 = 0;else {
for (var i = 0; i < inp.length; i++) {
if (inp[i].getAttribute("tabindex") == "0") {
index$$1 = i + dir;
break;
}
}
}
if (index$$1 !== false) {
var _i = index$$1;
do {
if (_i >= inp.length) _i = 0;
if (_i < 0) _i = inp.length - 1;
if (!inp[_i].getAttribute("webix_disabled")) {
var id = inp[_i].getAttribute(
/*@attr*/
"button_id");
this.setValue(id, "user");
inp[_i].focus();
_i = "success";
} else _i += dir;
} while (_i !== "success" && _i !== index$$1);
}
}
},
_get_tooltip_data: function (t, e) {
var id,
node = e.target;
while (node && !node.webix_tooltip) {
id = node.getAttribute("webix_t_id");
if (id) return this.getOption(id);
node = node.parentNode;
}
return null;
},
optionIndex: function (id) {
var options = this._settings.options;
for (var i = 0; i < options.length; i++) {
if (options[i].id == id) return i;
}
return -1;
},
getOption: function (id) {
var index$$1 = this.optionIndex(id);
if (index$$1 !== -1) return this._settings.options[index$$1];
return null;
},
addOption: function (id, value, show, index$$1) {
var obj = id;
if (_typeof(id) != "object") {
value = value || id;
obj = {
id: id,
value: value
};
} else {
id = obj.id;
index$$1 = show;
show = value;
}
if (this.optionIndex(id) === -1) {
_power_array.insertAt.call(this._settings.options, obj, index$$1);
this.refresh();
this.callEvent("onOptionAdd", [id, obj]);
}
if (show) {
if (this._settings.options.length === 1) this._settings.value = "";
this.setValue(id, "auto");
}
},
removeOption: function (id) {
var index$$1 = this.optionIndex(id);
if (index$$1 !== -1) {
var options = this._settings.options;
_power_array.removeAt.call(options, index$$1);
this.refresh(); // if we remove a selected option
if (this._settings.value == id) this._setNextVisible(options, index$$1);
this.callEvent("onOptionRemove", [id, this._settings.value]);
}
},
_setNextVisible: function (options, index$$1) {
var size = options.length;
if (size && !this.customRadio_setter) {
index$$1 = Math.min(index$$1, size - 1); //forward search
for (var i = index$$1; i < size; i++) {
if (!options[i].hidden) return this.setValue(options[i].id, "auto");
} //backward search
for (var _i2 = index$$1; _i2 >= 0; _i2--) {
if (!options[_i2].hidden) return this.setValue(options[_i2].id, "auto");
}
} //nothing found
this.setValue("", "auto");
},
_getFirstActive: function (first) {
var options = this._settings.options;
if (options.length) {
for (var i = 0; i < options.length; i++) {
if (!options[i].hidden && !options[i].disabled) return options[i].id;
}
if (first) return options[0].id;
}
return "";
},
_filterOptions: function (options) {
var copy$$1 = [];
for (var i = 0; i < options.length; i++) {
if (!options[i].hidden) copy$$1.push(options[i]);
}
return copy$$1;
},
_setOptionState: function (id, field, state) {
var options = this._settings.options;
var index$$1 = this.optionIndex(id);
if (options[index$$1] && state != !!options[index$$1][field]) {
//new state differs from previous one
options[index$$1][field] = state;
if (state && field === "hidden" && this._settings.value == id) //switch to next visible one
this._setNextVisible(options, index$$1);
this.refresh();
}
},
hideOption: function (id) {
this._setOptionState(id, "hidden", true);
},
showOption: function (id) {
this._setOptionState(id, "hidden", false);
},
disableOption: function (id) {
this._setOptionState(id, "disabled", true);
},
enableOption: function (id) {
this._setOptionState(id, "disabled", false);
}
};
var HtmlMap = exports.proto({
$init: function (key) {
this._id = "map_" + uid();
this._key = key;
this._map = [];
this._areas = [];
},
addRect: function (id, points, userdata) {
this._createMapArea(id, "RECT", points, userdata);
},
addPoly: function (id, points, userdata) {
this._createMapArea(id, "POLY", points, userdata);
},
_createMapArea: function (id, shape, coords, userdata) {
var extra_data = "";
if (arguments.length == 4) extra_data = "userdata='" + userdata + "'";
this._map.push("<area " + this._key + "='" + id + "' shape='" + shape + "' coords='" + coords.join() + "' " + extra_data + "></area>");
this._areas.push({
index: userdata,
points: coords
});
},
addSector: function (id, alpha0, alpha1, x, y, R, ky, userdata) {
var points = [];
points.push(x);
points.push(Math.floor(y * ky));
for (var i = alpha0; i < alpha1; i += Math.PI / 18) {
points.push(Math.floor(x + R * Math.cos(i)));
points.push(Math.floor((y + R * Math.sin(i)) * ky));
}
points.push(Math.floor(x + R * Math.cos(alpha1)));
points.push(Math.floor((y + R * Math.sin(alpha1)) * ky));
points.push(x);
points.push(Math.floor(y * ky));
return this.addPoly(id, points, userdata);
},
hide: function (obj, data, mode) {
if (obj.querySelectorAll) {
var nodes = obj.querySelectorAll("area[userdata=\"" + data + "\"]");
for (var i = 0; i < nodes.length; i++) {
var nod = nodes[i];
if (mode) {
if (nod.getAttribute("coords")) {
nod.coordsdis = nod.getAttribute("coords");
nod.setAttribute("coords", "");
nod.coords = "";
}
} else if (!mode) {
if (nod.coordsdis) {
nod.setAttribute("coords", nod.coordsdis);
nod.coords = nod.coordsdis;
nod.coordsdis = "";
}
}
nodes[i].style.display = mode ? "none" : "";
}
}
},
render: function (obj) {
var d = create("DIV");
d.style.cssText = "position:absolute; width:100%; height:100%; top:0px; left:0px;";
obj.appendChild(d);
var src = env.isIE ? "" : "src='data:image/gif;base64,R0lGODlhEgASAIAAAP///////yH5BAUUAAEALAAAAAASABIAAAIPjI+py+0Po5y02ouz3pwXADs='";
d.innerHTML = "<map id='" + this._id + "' name='" + this._id + "'>" + this._map.join("\n") + "</map><img " + src + " class='webix_map_img' usemap='#" + this._id + "'>";
obj._htmlmap = d; //for clearing routine
this._map = [];
}
});
var IdSpace = {
$init: function () {
this._elements = {};
this._translate_ids = {};
this.getTopParentView = this._get_self = bind(function () {
return this;
}, this);
this._run_inner_init_logic();
this.$ready.push(this._run_after_inner_init_logic);
},
$$: function (id) {
return this._elements[id];
},
innerId: function (id) {
return this._translate_ids[id];
},
_run_inner_init_logic: function () {
this._prev_global_col = state._global_collection;
state._global_collection = this;
},
_run_after_inner_init_logic: function () {
for (var name in this._elements) {
var input = this._elements[name];
if (this.callEvent && input.mapEvent && !input._evs_map.onitemclick) input.mapEvent({
onitemclick: this
});
input.getTopParentView = this._get_self;
}
state._global_collection = this._prev_global_col;
this._prev_global_col = 0;
},
_destroy_child: function (id) {
delete this._elements[id];
},
ui: function () {
this._run_inner_init_logic();
var temp = ui.apply(this, arguments);
this._run_after_inner_init_logic();
return temp;
}
};
var KeysNavigation = {
$init: function () {
if (this.getSelectedId) this.attachEvent("onAfterRender", this._set_focusable_item);
if (this.moveSelection) this.attachEvent("onTabFocus", this._set_item_focus);
},
_set_item_focus: function () {
if (this.getSelectedId) {
var sel = this.getSelectedId(true);
if (!sel.length || !this.getItemNode(sel[0])) this.moveSelection("down"); //select and show
}
},
_set_focusable_item: function () {
var sel = this.getSelectedId(true);
if (!sel.length || !this.getItemNode(sel[0])) {
var node = this._dataobj.querySelector("[" + this._id + "]");
if (node) node.setAttribute("tabindex", "0");
}
},
_navigation_helper: function (mode) {
return function (view, e) {
var tag = e.target; //ignore clipboard listener
if (!tag.getAttribute(
/*@attr*/
"webixignore")) {
//ignore hotkeys if focus in the common input
//to allow normal text edit operations
var name = tag.tagName;
if (name == "INPUT" || name == "TEXTAREA" || name == "SELECT") return true;
}
if (view && view.moveSelection && view.config.navigation && !view._in_edit_mode) {
preventEvent(e);
return view.moveSelection(mode, {
shift: e.shiftKey,
ctrl: e.ctrlKey,
e: e
});
}
};
},
moveSelection: function (mode, details, focus) {
var config = this._settings;
if (config.disabled) return; //get existing selection
var selected = this.getSelectedId(true);
var x_layout = this.count && (config.layout == "x" || config.xCount > 1);
if ((mode == "right" || mode == "left") && this._parent_menu) {
var parent = $$(this._parent_menu);
parent._hide_sub_menu(true);
if (parent.config.layout === "x") parent.moveSelection(mode);else UIManager.setFocus(parent);
return;
}
if (!selected.length && this.count()) {
if (mode == "down" || mode == "right" && x_layout) mode = "top";else if (mode == "up" || mode == "left" && x_layout) mode = "bottom";else return;
selected = [this.getFirstId()];
}
if (selected.length == 1) {
//if we have a selection
selected = selected[0];
var prev = selected;
if (mode == "left" && this.close) return this.close(selected);
if (mode == "right" && this.open) return this.open(selected);else if (mode == "top") {
selected = this.getFirstId();
} else if (mode == "bottom") {
selected = this.getLastId();
} else if (mode == "up" || mode == "left" || mode == "pgup") {
var index$$1 = this.getIndexById(selected);
var step = mode == "pgup" ? 10 : 1;
selected = this.getIdByIndex(Math.max(0, index$$1 - step));
} else if (mode == "down" || mode == "right" || mode == "pgdown") {
var _index = this.getIndexById(selected);
var _step = mode == "pgdown" ? 10 : 1;
selected = this.getIdByIndex(Math.min(this.count() - 1, _index + _step));
} else {
assert(false, "Not supported selection moving mode");
return;
}
var dir = mode == "up" || mode == "left" || mode == "pgdown" || mode == "bottom" ? -1 : 1;
if (this._skip_item) selected = this._skip_item(selected, prev, dir);
this.showItem(selected);
this.select(selected);
if (this.getSubMenu && this.getSubMenu(selected)) this._mouse_move_activation(selected, this.getItemNode(selected));
if (!this.config.clipboard && focus !== false) {
var node = this.getItemNode(selected);
if (node) node.focus();
}
}
return false;
},
navigation_setter: function (value) {
//using global flag to apply hotkey only once
if (value && !UIManager._global_nav_grid_hotkeys) {
UIManager._global_nav_grid_hotkeys = true; //hotkeys will react on any component but will not work in edit mode
//you can define moveSelection method to handle navigation keys
UIManager.addHotKey("up", this._navigation_helper("up"));
UIManager.addHotKey("down", this._navigation_helper("down"));
UIManager.addHotKey("right", this._navigation_helper("right"));
UIManager.addHotKey("left", this._navigation_helper("left"));
UIManager.addHotKey("shift+up", this._navigation_helper("up"));
UIManager.addHotKey("shift+down", this._navigation_helper("down"));
UIManager.addHotKey("shift+right", this._navigation_helper("right"));
UIManager.addHotKey("shift+left", this._navigation_helper("left"));
UIManager.addHotKey("ctrl+shift+up", this._navigation_helper("up"));
UIManager.addHotKey("ctrl+shift+down", this._navigation_helper("down"));
UIManager.addHotKey("ctrl+shift+right", this._navigation_helper("right"));
UIManager.addHotKey("ctrl+shift+left", this._navigation_helper("left"));
UIManager.addHotKey("pageup", this._navigation_helper("pgup"));
UIManager.addHotKey("pagedown", this._navigation_helper("pgdown"));
UIManager.addHotKey("home", this._navigation_helper("top"));
UIManager.addHotKey("end", this._navigation_helper("bottom"));
}
return value;
}
};
/*Data collection mapping logic */
var MapCollection = {
$init: function () {
this.$ready.push(this._create_scheme_init);
this.attachEvent("onStructureUpdate", this._create_scheme_init);
this.attachEvent("onStructureLoad", function () {
if (!this._scheme_init_order.length) this._create_scheme_init();
});
},
_create_scheme_init: function () {
var stack = this._scheme_init_order = [];
var config = this._settings;
if (config.columns) this._build_data_map(config.columns);
if (this._settings.map) this._process_field_map(config.map);
if (stack.length) {
this.data._scheme_init = function (obj) {
for (var i = 0; i < stack.length; i++) {
stack[i](obj);
}
};
}
},
_process_field_map: function (map) {
for (var key in map) {
this._scheme_init_order.push(this._process_single_map(key, map[key]));
}
},
_process_single_map: function (target, map, extra) {
var source = map.replace(/^(\s|)\((date|number)\)/, "");
var getSource;
if (source === "") {
getSource = function (a) {
return a[target];
};
} else {
if (source.indexOf("#") === -1 && source.indexOf("{") === -1) {
source = "#" + source + "#";
}
getSource = template(source);
}
if (map.indexOf("(date)") === 0) {
if (extra && !extra.format) extra.format = i18n.dateFormatStr;
return function (obj) {
var dateStr = (getSource(obj) || "").toString();
obj[target] = i18n.parseFormatDate(dateStr);
};
} else if (map.indexOf("(number)") === 0) {
return function (obj) {
obj[target] = getSource(obj) * 1;
};
} else {
return function (obj) {
obj[target] = getSource(obj) || "";
};
}
},
_build_data_map: function (columns) {
//for datatable
for (var i = 0; i < columns.length; i++) {
var col = columns[i];
if (!col.id) {
col.id = "i" + uid();
if (!col.header) col.header = "";
}
if (col.map) this._scheme_init_order.push(this._process_single_map(col.id, col.map, columns[i]));
this._map_options(columns[i]);
}
},
_create_collection: function (options) {
if (typeof options === "string") {
var options_view = $$(options); //id of some other view
if (!options_view) {
//or url
options = new (use("DataCollection"))({
url: options
});
this._destroy_with_me.push(options);
} else options = options_view;
if (options.getBody) //if it was a view, special check for suggests
options = options_view.getBody();
} else if (typeof options === "function" || options.$proxy) {
//proxy or function
options = new (use("DataCollection"))({
url: options
});
this._destroy_with_me.push(options);
} else if (!options.loadNext) {
var array = isArray(options);
var data = [];
if (array && _typeof(options[0]) !== "object") {
//["one", "two"]
for (var i = 0; i < options.length; i++) {
data.push({
id: options[i],
value: options[i]
});
}
options = data;
} else if (!array) {
//{ 1:"one", 2:"two" }
for (var _i in options) {
data.push({
id: _i,
value: options[_i]
});
}
options = data;
} // else [{ id:1, value:"one"}, ...]
options = new (use("DataCollection"))({
data: options
});
this._destroy_with_me.push(options);
} // else data collection or view
return options;
},
_map_options: function (column) {
var options = column.options || column.collection;
if (options) {
options = this._create_collection(options);
this._bind_collection(options, column);
}
if (column.header) {
this._map_header_options(column.header);
this._map_header_options(column.footer);
}
},
_map_header_options: function (arr) {
var _this = this;
arr = arr || [];
var _loop = function (i) {
var config = arr[i];
if (config && config.options) {
var options = config.options;
if (!options.loadNext) options = config.options = _this._create_collection(options);
var id = options.data.attachEvent("onStoreUpdated", function () {
if (_this.refreshFilter) _this.refreshFilter(config.columnId);
});
_this.attachEvent("onDestruct", function () {
if (!options.$destructed) options.data.detachEvent(id);
});
}
};
for (var i = 0; i < arr.length; i++) {
_loop(i);
}
},
_bind_collection: function (options, column) {
var _this2 = this;
if (column) {
delete column.options;
column.collection = options;
column.template = column.template || this._bind_template(options, column.id, column.optionslist);
var id = options.data.attachEvent("onStoreUpdated", function () {
_this2.refresh();
if (_this2.refreshFilter) _this2.refreshFilter(column.id);
});
this.attachEvent("onDestruct", function () {
if (!options.$destructed) options.data.detachEvent(id);
});
}
},
_bind_template: function (options, columnId, multi) {
columnId = this.getColumnConfig ? columnId : "value";
if (multi) {
var separator = typeof multi == "string" ? multi : ",";
return function (obj) {
var value = obj[columnId];
if (!value) return "";
var ids = value.toString().split(separator);
for (var i = 0; i < ids.length; i++) {
var data = options.data.pull[ids[i]];
ids[i] = data ? data.value || "" : "";
}
return ids.join(", ");
};
} else {
return function (obj) {
var data = options.data.pull[obj[columnId]];
if (data && (data.value || data.value === 0)) return data.value;
return "";
};
}
}
};
var MouseEvents = {
$init: function (config) {
config = config || {};
this._clickstamp = 0;
this._dbl_sensetive = 300;
this._item_clicked = null;
this._mouse_action_extend(config.onClick, "on_click");
this._mouse_action_extend(config.onContext, "on_context");
this._mouse_action_extend(config.onDblClick, "on_dblclick");
this._mouse_action_extend(config.onMouseMove, "on_mouse_move"); //attach dom events if related collection is defined
if (this.on_click) {
_event(this._contentobj, "click", this._onClick, {
bind: this
});
if (env.isIE8 && this.on_dblclick) _event(this._contentobj, "dblclick", this._onDblClick, {
bind: this
});
}
if (this.on_context) _event(this._contentobj, "contextmenu", this._onContext, {
bind: this
});
if (this.on_mouse_move) this._enable_mouse_move();
},
_enable_mouse_move: function () {
if (!this._mouse_move_enabled) {
this.on_mouse_move = this.on_mouse_move || {};
_event(this._contentobj, "mousemove", this._onMouse, {
bind: this
});
_event(this._contentobj, env.isIE ? "mouseleave" : "mouseout", this._onMouse, {
bind: this
});
this._mouse_move_enabled = 1;
this.attachEvent("onDestruct", function () {
if (this._mouse_move_timer) window.clearTimeout(this._mouse_move_timer);
});
}
},
_mouse_action_extend: function (config, key) {
if (config) {
var now = this[key];
var step = now ? exports.extend({}, now) : {};
this[key] = exports.extend(step, config);
}
},
//inner onclick object handler
_onClick: function (e) {
if (!this.isEnabled()) return false;
UIManager._focus_action(this);
if (this.on_dblclick) {
// emulates double click
var stamp = new Date().valueOf();
if (stamp - this._clickstamp <= this._dbl_sensetive && this.locate) {
var item = this.locate(e);
if ("" + item == "" + this._item_clicked) {
this._clickstamp = 0;
return this._onDblClick(e);
}
}
this._clickstamp = stamp;
}
var result = this._mouseEvent(e, this.on_click, "ItemClick");
return result;
},
//inner ondblclick object handler
_onDblClick: function (e) {
return this._mouseEvent(e, this.on_dblclick, "ItemDblClick");
},
//process oncontextmenu events
_onContext: function (e) {
this._mouseEvent(e, this.on_context, "BeforeContextMenu", "AfterContextMenu");
},
/*
event throttler - ignore events which occurs too fast
during mouse moving there are a lot of event firing - we need no so much
also, mouseout can fire when moving inside the same html container - we need to ignore such fake calls
*/
_onMouse: function (e) {
if (this.$destructed) return;
if (document.createEventObject) //make a copy of event, will be used in timed call
e = document.createEventObject(event);
if (this._mouse_move_timer) //clear old event timer
window.clearTimeout(this._mouse_move_timer); //this event just inform about moving operation, we don't care about details
this.callEvent("onMouseMoving", [e]); //set new event timer
this._mouse_move_timer = delay(function (e) {
//called only when we have at least 100ms after previous event
if (e.type == "mousemove") this._onMouseMove(e);else this._onMouseOut(e);
}, this, [e], this._settings.mouseEventDelay || 500);
},
//inner mousemove object handler
_onMouseMove: function (e) {
if (!this._mouseEvent(e, this.on_mouse_move, "MouseMove")) this._onMouseOut(e);
},
//inner mouseout object handler
_onMouseOut: function (e) {
this.callEvent("onMouseOut", [e || event]);
},
//common logic for click and dbl-click processing
_mouseEvent: function (e, hash, name, pair) {
e = e || event;
if (e.processed || !this._viewobj) return;
e.processed = true;
var trg = e.target; //IE8 can't modify event object
//so we need to stop event bubbling to prevent double processing
if (env.isIE8) {
var vid = this._settings.id;
var wid = trg.w_view;
if (!wid) trg.w_view = vid;else if (wid !== vid) return;
}
var css = "";
var id = null;
var found = false; //loop through all parents
//we need to check for this._viewobj as some handler can destroy the view
while (trg && trg.parentNode && this._viewobj && trg != this._viewobj.parentNode) {
if (!found && trg.getAttribute) {
//if element with ID mark is not detected yet
id = trg.getAttribute(this._id); //check id of current one
if (id) {
// prevent clicking on disabled items
if (trg.getAttribute("webix_disabled")) {
this._item_clicked = null;
return;
}
this._item_clicked = id;
if (this.callEvent) {
//it will be triggered only for first detected ID, in case of nested elements
if (!this.callEvent("on" + name, [id, e, trg])) return;
if (pair) this.callEvent("on" + pair, [id, e, trg]);
} //set found flag
found = true;
}
}
css = _getClassName(trg);
if (css) {
//check if pre-defined reaction for element's css name exists
css = css.toString().split(" ");
for (var i = 0; i < css.length; i++) {
if (hash[css[i]]) {
var functor = toFunctor(hash[css[i]], this.$scope);
var res = functor.call(this, e, id || locate(e, this._id), trg);
if (res === false) return found;
}
}
}
trg = trg.parentNode;
}
return found; //returns true if item was located and event was triggered
}
};
/*
UI: navigation control
*/
var NavigationButtons = {
$init: function () {
this.$ready.push(function () {
this.attachEvent("onKeyPress", this._onKeyPress);
});
},
_moveActive: function (code, e) {
if (code === 37 || code === 39) {
preventEvent(e);
this._showNavItem(code === 37 ? -1 : 1);
var node = this._navPanel.querySelector("[tabindex='0']");
if (node) node.focus();
}
},
_renderPanel: function () {
remove(this._navPanel);
this._navPanel = create("DIV", {
"class": "webix_nav_panel " + "webix_nav_panel_" + this._settings.navigation.type,
"role": "tablist"
}, "");
this._viewobj.appendChild(this._navPanel);
this._renderNavItems();
this._renderNavButtons();
this._setLinkEventHandler();
},
_setLinkEventHandler: function () {
var h = [];
if (this._navPanel) h[0] = event$1(this._navPanel, "click", bind(function (e) {
var elem = e.target;
var found = false;
while (elem != this._navPanel && !found) {
var bindId = elem.getAttribute(this._linkAttr);
if (bindId) {
found = true;
this._showPanelBind(bindId);
}
elem = elem.parentNode;
}
}, this));
if (this._prevNavButton) h[1] = event$1(this._prevNavButton, "click", bind(function () {
this._showNavItem(-1);
}, this));
if (this._nextNavButton) h[1] = event$1(this._nextNavButton, "click", bind(function () {
this._showNavItem(1);
}, this));
this.attachEvent("onDestruct", function () {
for (var i = 0; i < h.length; i++) {
this.detachEvent(h[i]);
}
h = null;
});
},
_showNavItem: function (inc) {
if (this._cells) {
var index$$1 = this._active_cell + inc;
if (index$$1 >= this._cells.length || index$$1 < 0) {
index$$1 = index$$1 < 0 ? this._cells.length - 1 : 0;
}
this.setActiveIndex(index$$1);
}
},
_showPanelBind: function (id) {
if (this._cells) $$(id).show();
},
_renderNavItems: function () {
var item, config;
config = this._settings.navigation;
if (config.items) {
this._linkAttr = config.linkAttr ||
/*@attr*/
"bind_id";
if (!this._navPanel) this._renderPanel();else this._clearPanel();
var data = this._cells ? this._cells : this.data.order;
if (data.length > 1) {
for (var i = 0; i < data.length; i++) {
item = create("DIV", {
"class": "webix_nav_item webix_nav_" + (i == this._active_cell ? "active" : "inactive"),
"role": "tab",
"tabindex": i == this._active_cell ? "0" : "-1"
});
var id = this._cells ? this._cells[i]._settings.id : data[i];
if (id) item.setAttribute(this._linkAttr, id);
this._navPanel.appendChild(item);
}
}
}
},
_clearPanel: function () {
if (this._navPanel) {
var coll = this._navPanel.childNodes;
for (var i = coll.length - 1; i >= 0; i--) {
remove(coll[i]);
}
}
},
_renderNavButtons: function () {
var config = this._settings.navigation;
if (config.buttons) {
if (this._prevNavButton) remove(this._prevNavButton);
if (this._prevNavButton) remove(this._nextNavButton);
this._prevNavButton = create("DIV", {
"class": "webix_nav_button_" + config.type + " webix_nav_button_prev "
}, "<div role=\"button\" tabindex=\"0\" aria-label=\"" + i18n.aria.prevTab + "\" class=\"webix_nav_button_inner\"></div>");
this._viewobj.appendChild(this._prevNavButton);
this._nextNavButton = create("DIV", {
"class": "webix_nav_button_" + config.type + " webix_nav_button_next "
}, "<div role=\"button\" tabindex=\"0\" aria-label=\"" + i18n.aria.prevTab + "\" class=\"webix_nav_button_inner\"></div>");
this._viewobj.appendChild(this._nextNavButton);
}
}
};
var OverlayBox = {
showOverlay: function (message) {
if (!this._overlay) {
this._overlay = create("DIV", {
"class": "webix_overlay"
}, message || "");
insertBefore(this._overlay, this._viewobj.firstChild, this._viewobj);
this._viewobj.style.position = "relative";
} else this._overlay.innerHTML = message;
},
hideOverlay: function () {
if (this._overlay) {
remove(this._overlay);
this._overlay = null;
}
}
};
var PagingAbility = {
pager_setter: function (pager) {
if (typeof pager == "string") {
var ui_pager = $$(pager);
if (!ui_pager) {
this.$blockRender = true;
delay(function () {
var obj = $$(pager);
this._settings.pager = this.pager_setter(obj);
var s = obj._settings;
s.count = this.data._count_pager_total(s.level);
obj.refresh();
this.$blockRender = false;
this.render();
}, this);
return null;
}
pager = ui_pager;
}
function check_pager_sizes(repeat) {
// reset topSplit - since now the pager is responsible for rendering
if (this.config.topSplit) this.config.topSplit = 0;
if (pager.config.autosize && this.getVisibleCount) {
var count = this.getVisibleCount();
if (isNaN(count)) {
pager.config.size = 1;
delay(check_pager_sizes, this, [true]);
} else if (count != pager.config.size) {
pager.config.size = count;
pager.refresh();
if (repeat === true) this.refresh();
}
}
var s = this._settings.pager; //initial value of pager = -1, waiting for real value
if (s.page == -1) return false;
this.data.$min = this._count_pager_index(0, s.page * s.size); //affect data.getRange
this.data.$max = this._count_pager_index(this.data.$min, s.size);
this.data.$pagesize = this.data.$max - this.data.$min;
return true;
}
this.attachEvent("onBeforeRender", check_pager_sizes);
if (!pager.$view) {
pager.view = "pager";
pager = ui(pager);
}
this._pager = pager;
pager.$master = this;
this.data.attachEvent("onStoreUpdated", function () {
var s = pager._settings;
s.count = this._count_pager_total(s.level);
pager.refresh();
});
this.data._count_pager_total = this._count_pager_total;
return pager._settings;
},
_count_pager_total: function (level) {
if (level && level !== 0) {
var count = 0;
this.each(function (obj) {
if (obj.$level == level) count++;
});
return count;
} else return this.count();
},
_count_pager_index: function (start, count) {
var s = this._settings.pager;
if (s.level && s.level !== 0) {
var end = start;
var max = this.data.order.length;
if (count) while (end < max) {
if (this.data.order[end] && this.data.getItem(this.data.order[end]).$level == s.level) {
if (count === 0) break;else count--;
}
end++;
}
return end;
} else return start + count;
},
setPage: function (value) {
if (this._pager) this._pager.select(value);
},
getPage: function () {
return this._pager._settings.page;
},
getPager: function () {
return this._pager;
}
};
var ProgressBar = {
$init: function () {
var _this = this;
if (isUndefined(this._progress) && this.attachEvent) {
this.attachEvent("onBeforeLoad", function () {
return _this.showProgress();
});
this.attachEvent("onAfterLoad", function () {
return _this.hideProgress();
});
this._progress = null;
}
},
showProgress: function (config) {
// { position: 0 - 1, delay: 2000ms by default, css : name of css class to use }
var width;
if (!this._progress) {
config = exports.extend({
position: 0,
delay: 2000,
type: "icon",
icon: "wxi-sync",
hide: false
}, config || {}, true);
var incss = config.type == "icon" ? config.icon + " webix_spin" : "";
this._progress = create("DIV", {
"class": "webix_progress_" + config.type,
"role": "progressbar",
"aria-valuemin": "0",
"aria-valuemax": "100",
"tabindex": "0"
}, "<div class='webix_progress_state " + incss + "'></div>");
if (!this.setPosition) this._viewobj.style.position = "relative";
insertBefore(this._progress, this._viewobj.firstChild, this._viewobj);
this._viewobj.setAttribute("aria-busy", "true");
if (!Touch.$active || this._touch_scroll == "native") {
if (this.getScrollState) {
var scroll = this.getScrollState();
if (this._viewobj.scrollWidth != this.$width) {
this._progress.style.left = scroll.x + "px";
}
if (this._viewobj.scrollHeight != this.$height) {
if (config.type != "bottom") {
this._progress.style.top = scroll.y + "px";
} else {
this._progress.style.top = scroll.y + this.$height - this._progress.offsetHeight + "px";
}
}
}
}
this._progress_animate = config.type != "icon";
}
if (!config) return;
if (this._progress_animate) {
var position = config.position || 1; //check for css-transition support
if (this._progress.style[env.transitionDuration] !== undefined || !config.delay) {
if (config.delay) {
// force reflow
width = this._viewobj.firstChild.offsetWidth;
this._progress.firstChild.style[env.transitionDuration] = config.delay + "ms";
} // animate to new value
this._progress.firstChild.style.width = position * 100 + "%";
} else {
//if animation is not supported fallback to timeouts [IE9]
var count = 0,
start = 0,
step = position / config.delay * 30,
view = this;
if (this._progressTimer) {
//reset the existing progress
window.clearInterval(this._progressTimer);
start = this._progress.firstChild.offsetWidth / this._progress.offsetWidth * 100;
}
this._progressTimer = window.setInterval(function () {
if (count * 30 == config.delay) {
window.clearInterval(view._progressTimer);
} else {
if (view._progress && view._progress.firstChild) view._progress.firstChild.style.width = start + count * step * position * 100 + "%";
count++;
}
}, 30);
}
}
if (this._progress_hide) clearTimeout(this._progress_hide);
if (config.hide) this._progress_hide = delay(this.hideProgress, this, [1], config.delay); // necessary to prevent code optimization
return width;
},
hideProgress: function (now) {
if (this._progress) {
if (now || !this._progress_animate) {
if (this._progressTimer) window.clearInterval(this._progressTimer);
remove(this._progress);
this._progress = null;
this._viewobj.removeAttribute("aria-busy");
} else {
this.showProgress({
position: 1.1,
delay: 300,
hide: true
});
}
}
}
};
var RenderStack = {
$init: function () {
assert(this.data, "RenderStack :: Component doesn't have DataStore");
assert(template, "template :: template is not accessible"); //used for temporary HTML elements
//automatically nulified during destruction
this._html = document.createElement("DIV");
this.data.attachEvent("onIdChange", bind(this._render_change_id, this));
this.attachEvent("onItemClick", this._call_onclick); //create copy of default type, and set it as active one
if (!this.types) {
this.types = {
"default": this.type
};
this.type.name = "default";
}
this.type = clone(this.type);
},
customize: function (obj) {
type(this, obj);
},
item_setter: function (value) {
return this.type_setter(value);
},
type_setter: function (value) {
if (!this.types[value]) this.customize(value);else {
this.type = clone(this.types[value]);
if (this.type.css) this._contentobj.className += " " + this.type.css;
}
if (this.type.on_click) exports.extend(this.on_click, this.type.on_click);
return value;
},
template_setter: function (value) {
this.type.template = template(value);
},
//convert single item to HTML text (templating)
_toHTML: function (obj) {
var mark = this.data._marks[obj.id]; //check if related template exist
assert(!obj.$template || this.type["template" + obj.$template], "RenderStack :: Unknown template: " + obj.$template);
this.callEvent("onItemRender", [obj]);
return this.type.templateStart(obj, this.type, mark) + (obj.$template ? this.type["template" + obj.$template] : this.type.template)(obj, this.type, mark) + this.type.templateEnd(obj, this.type, mark);
},
//convert item to HTML object (templating)
_toHTMLObject: function (obj) {
this._html.innerHTML = this._toHTML(obj);
return this._html.firstChild;
},
_render_change_id: function (old, newid) {
var obj = this.getItemNode(old);
if (obj) {
obj.setAttribute(this._id, newid);
this._htmlmap[newid] = this._htmlmap[old];
delete this._htmlmap[old];
}
},
//calls function that is set in onclick property
_call_onclick: function () {
if (this._settings.click) {
var code = toFunctor(this._settings.click, this.$scope);
if (code && code.call) code.apply(this, arguments);
}
},
//return html container by its ID
//can return undefined if container doesn't exists
getItemNode: function (search_id) {
if (this._htmlmap) return this._htmlmap[search_id]; //fill map if it doesn't created yet
this._htmlmap = {};
var t = this._dataobj.childNodes;
for (var i = 0; i < t.length; i++) {
var id = t[i].getAttribute(this._id); //get item's
if (id) this._htmlmap[id] = t[i];
} //call locator again, when map is filled
return this.getItemNode(search_id);
},
//return id of item from html event
locate: function (e) {
return locate(e, this._id);
},
/*change scrolling state of top level container, so related item will be in visible part*/
showItem: function (id) {
var html = this.getItemNode(id);
if (html && this.scrollTo) {
var txmin = html.offsetLeft;
var txmax = txmin + html.offsetWidth;
var tymin = html.offsetTop;
var tymax = tymin + html.offsetHeight;
var state = this.getScrollState();
var x = state.x;
if (x > txmin || x + this._content_width < txmax) x = txmin;
var y = state.y;
if (y > tymin || y + this._content_height < tymax) y = tymin;
this.scrollTo(x, y);
if (this._setItemActive) this._setItemActive(id);
}
},
//update view after data update
//method calls low-level rendering for related items
//when called without parameters - all view refreshed
render: function (id, data, type$$1) {
if (!this.isVisible(this._settings.id) || this.$blockRender) return;
if (id) {
var cont = this.getItemNode(id); //get html element of updated item
switch (type$$1) {
case "paint":
case "update":
//in case of update - replace existing html with updated one
if (!cont) return;
var t1 = this._htmlmap[id] = this._toHTMLObject(data);
insertBefore(t1, cont);
remove(cont);
break;
case "delete":
//in case of delete - remove related html
if (!cont) return;
remove(cont);
delete this._htmlmap[id];
break;
case "add":
//in case of add - put new html at necessary position
var t2 = this._htmlmap[id] = this._toHTMLObject(data);
insertBefore(t2, this.getItemNode(this.data.getNextId(id)), this._dataobj);
break;
case "move":
//moving without repainting the item
insertBefore(this.getItemNode(id), this.getItemNode(this.data.getNextId(id)), this._dataobj);
break;
default:
assert(0, "Unknown render command: " + type$$1);
break;
}
} else {
//full reset
if (this.callEvent("onBeforeRender", [this.data])) {
//getRange - returns all elements
(this._renderobj || this._dataobj).innerHTML = this.data.getRange().map(this._toHTML, this).join("");
this._htmlmap = null; //clear map, it will be filled at first getItemNode
this.callEvent("onAfterRender", []);
}
}
}
};
var Scrollable = {
$init: function (config) {
//do not spam unwanted scroll containers for templates
if (config && !config.scroll && this._one_time_scroll) return this._dataobj = this._dataobj || this._contentobj;
(this._dataobj || this._contentobj).appendChild(create("DIV", {
"class": "webix_scroll_cont"
}, ""));
this._dataobj = (this._dataobj || this._contentobj).firstChild;
if (this.callEvent && (!env.touch || this._touch_scroll == "native")) _event(this._viewobj, "scroll", function () {
delay(function () {
this.callEvent("onAfterScroll", []);
}, this);
}, {
bind: this
});
},
_touch_scroll: "native",
scroll_setter: function (value) {
if (!value) return false;
var auto = value === "auto";
var marker = value == "x" ? "x" : value == "xy" ? "xy" : auto ? "xy" : "y";
if (env.$customScroll) {
temp$1.enable(this, marker);
} else {
var node = this._dataobj.parentNode.style;
if (auto) {
node.overflowX = node.overflowY = "auto";
} else {
if (marker.indexOf("x") != -1) {
this._scroll_x = true;
node.overflowX = "scroll";
}
if (marker.indexOf("y") != -1) {
this._scroll_y = true;
node.overflowY = "scroll";
}
}
}
return marker;
},
_onoff_scroll: function (mode, dir) {
if (!!this._settings.scroll == !!mode) return;
if (!env.$customScroll) {
var style = this._dataobj.parentNode.style;
style[dir === "x" ? "overflowX" : "overflowY"] = mode ? "auto" : "hidden";
}
if (dir === "x") {
this._scroll_x = mode;
} else {
this._scroll_y = mode;
}
this._settings.scroll = mode ? dir : false;
},
getScrollState: function () {
return {
x: this._dataobj.parentNode.scrollLeft,
y: this._dataobj.parentNode.scrollTop
};
},
scrollTo: function (x, y) {
this._dataobj.parentNode.scrollLeft = x;
this._dataobj.parentNode.scrollTop = y;
}
};
/*
Behavior:SelectionModel - manage selection states
@export
select
unselect
selectAll
unselectAll
isSelected
getSelectedId
*/
var SelectionModel = {
$init: function () {
//collection of selected IDs
this._selected = _to_array();
assert(this.data, "SelectionModel :: Component doesn't have DataStore"); //remove selection from deleted items
this.data.attachEvent("onStoreUpdated", bind(this._data_updated, this));
this.data.attachEvent("onStoreLoad", bind(this._data_loaded, this));
this.data.attachEvent("onAfterFilter", bind(this._data_filtered, this));
this.data.attachEvent("onSyncApply", bind(this._select_check, this));
this.data.attachEvent("onIdChange", bind(this._id_changed, this));
this.$ready.push(this._set_noselect);
},
_set_noselect: function () {
if (this._settings.select == "multiselect" || this._settings.multiselect || this._settings.select == "area") _event(this.$view, "mousedown", function (e) {
var shiftKey = (e || window.event).shiftKey;
if (shiftKey) {
state._noselect_element = this;
addCss(this, "webix_noselect", 1);
}
});
},
_id_changed: function (oldid, newid) {
for (var i = this._selected.length - 1; i >= 0; i--) {
if (this._selected[i] == oldid) this._selected[i] = newid;
}
},
_data_filtered: function () {
for (var i = this._selected.length - 1; i >= 0; i--) {
if (this.data.getIndexById(this._selected[i]) < 0) {
var id = this._selected[i];
this.removeCss(id, "webix_selected", true);
this._selected.splice(i, 1);
this.callEvent("onSelectChange", [id]);
}
}
},
//helper - linked to onStoreUpdated
_data_updated: function (id, obj, type) {
if (type == "delete") {
//remove selection from deleted items
if (this.loadBranch) {
//hierarchy, need to check all
this._select_check();
} else this._selected.remove(id);
} else if (!id && !this.data.count() && !this.data._filter_order && !this.data._filter_branch) {
//remove selection for clearAll
this._selected = _to_array();
}
},
_data_loaded: function () {
if (this._settings.select) this.data.each(function (obj) {
if (obj && obj.$selected) this.select(obj.id);
}, this);
},
_select_check: function () {
for (var i = this._selected.length - 1; i >= 0; i--) {
if (!this.exists(this._selected[i])) this._selected.splice(i, 1);
}
},
//helper - changes state of selection for some item
_select_mark: function (id, state$$1, refresh, need_unselect) {
var sname = state$$1 ? "onBeforeSelect" : "onBeforeUnSelect";
if (!this.callEvent(sname, [id, state$$1])) return false;
if (need_unselect) {
this._silent_selection = true;
this.unselectAll();
this._silent_selection = false;
}
if (state$$1) this.addCss(id, "webix_selected", true);else this.removeCss(id, "webix_selected", true);
if (refresh) refresh.push(id); //if we in the mass-select mode - collect all changed IDs
else {
if (state$$1) this._selected.push(id); //then add to list of selected items
else this._selected.remove(id);
this._refresh_selection(id); //othervise trigger repainting
}
var ename = state$$1 ? "onAfterSelect" : "onAfterUnSelect";
this.callEvent(ename, [id]);
return true;
},
//select some item
select: function (id, preserve) {
var ctrlKey = arguments[2];
var shiftKey = arguments[3]; //if id not provide - works as selectAll
if (!id) return this.selectAll(); //allow an array of ids as parameter
if (isArray(id)) {
for (var i = 0; i < id.length; i++) {
this.select(id[i], i ? 1 : preserve, ctrlKey, shiftKey);
}
return;
}
assert(this.data.exists(id), "Incorrect id in select command: " + id); //block selection mode
if (shiftKey && this._selected.length) return this.selectAll(this._selected[this._selected.length - 1], id); //single selection mode
var need_unselect = false;
if (!ctrlKey && !preserve && (this._selected.length != 1 || this._selected[0] != id)) need_unselect = true;
if (!need_unselect && this.isSelected(id)) {
if (ctrlKey) this.unselect(id); //ctrl-selection of already selected item
return;
}
this._select_mark(id, true, null, need_unselect);
},
//unselect some item
unselect: function (id) {
//if id is not provided - unselect all items
if (!id) return this.unselectAll();
if (!this.isSelected(id)) return;
this._select_mark(id, false);
},
//select all items, or all in defined range
selectAll: function (from, to) {
var range;
var refresh = [];
if (from || to) range = this.data.getRange(from || null, to || null); //get limited set if bounds defined
else range = this.data.getRange(); //get all items in other case
//in case of paging - it will be current page only
range.each(function (obj) {
if (!this.data.getMark(obj.id, "webix_selected")) {
this._selected.push(obj.id);
this._select_mark(obj.id, true, refresh);
}
}, this); //repaint self
this._refresh_selection(refresh);
},
//remove selection from all items
unselectAll: function () {
var refresh = [];
this._selected.each(function (id) {
this._select_mark(id, false, refresh); //unmark selected only
}, this);
this._selected = _to_array();
this._refresh_selection(refresh); //repaint self
},
//returns true if item is selected
isSelected: function (id) {
return this._selected.find(id) != -1;
},
/*
returns ID of selected items or array of IDs
to make result predictable - as_array can be used,
with such flag command will always return an array
empty array in case when no item was selected
*/
getSelectedId: function (as_array) {
switch (this._selected.length) {
case 0:
return as_array ? [] : "";
case 1:
return as_array ? [this._selected[0]] : this._selected[0];
default:
return [].concat(this._selected);
//isolation
}
},
getSelectedItem: function (as_array) {
var sel = this.getSelectedId(true);
if (sel.length > 1 || as_array) {
for (var i = sel.length - 1; i >= 0; i--) {
sel[i] = this.getItem(sel[i]);
}
return sel;
} else if (sel.length) return this.getItem(sel[0]);
},
//detects which repainting mode need to be used
_is_mass_selection: function (obj) {
// crappy heuristic, but will do the job
return obj.length > 100 || obj.length > this.data.count / 2;
},
_refresh_selection: function (refresh) {
if (_typeof(refresh) != "object") refresh = [refresh];
if (!refresh.length) return; //nothing to repaint
if (this._is_mass_selection(refresh)) this.data.refresh(); //many items was selected - repaint whole view
else for (var i = 0; i < refresh.length; i++) {
//repaint only selected
this.render(refresh[i], this.data.getItem(refresh[i]), "update");
}
if (!this._silent_selection) this.callEvent("onSelectChange", [refresh]);
}
};
ready(function () {
event$1(document.body, "mouseup", function () {
if (state._noselect_element) {
removeCss(state._noselect_element, "webix_noselect");
state._noselect_element = null;
}
});
});
var color = {
_toHex: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"],
toHex: function (number, length) {
number = parseInt(number, 10);
var str = "";
while (number > 0) {
str = this._toHex[number % 16] + str;
number = Math.floor(number / 16);
}
while (str.length < length) {
str = "0" + str;
}
return str;
},
rgbToHex: function (rgb) {
var arr = [];
if (typeof rgb === "string") rgb.replace(/[\d+.]+/g, function (v) {
arr.push(parseFloat(v));
});else if (isArray(rgb)) arr = rgb; //transparent
if (arr[3] === 0) return "";
return arr.slice(0, 3).map(function (n) {
return color.toHex(Math.floor(n), 2);
}).join("");
},
hexToDec: function (hex) {
return parseInt(hex, 16);
},
toRgb: function (rgb) {
var r, g, b, rgbArr;
if (typeof rgb != "string") {
r = rgb[0];
g = rgb[1];
b = rgb[2];
} else if (rgb.indexOf("rgb") != -1) {
rgbArr = rgb.substr(rgb.indexOf("(") + 1, rgb.lastIndexOf(")") - rgb.indexOf("(") - 1).split(",");
r = rgbArr[0];
g = rgbArr[1];
b = rgbArr[2];
} else {
if (rgb.substr(0, 1) == "#") {
rgb = rgb.substr(1);
}
r = this.hexToDec(rgb.substr(0, 2));
g = this.hexToDec(rgb.substr(2, 2));
b = this.hexToDec(rgb.substr(4, 2));
}
r = parseInt(r, 10) || 0;
g = parseInt(g, 10) || 0;
b = parseInt(b, 10) || 0;
if (r < 0 || r > 255) r = 0;
if (g < 0 || g > 255) g = 0;
if (b < 0 || b > 255) b = 0;
return [r, g, b];
},
hsvToRgb: function (h, s, v) {
var hi, f, p, q, t, r, g, b;
hi = Math.floor(h / 60) % 6;
f = h / 60 - hi;
p = v * (1 - s);
q = v * (1 - f * s);
t = v * (1 - (1 - f) * s);
r = 0;
g = 0;
b = 0;
switch (hi) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
default:
break;
}
r = Math.floor(r * 255);
g = Math.floor(g * 255);
b = Math.floor(b * 255);
return [r, g, b];
},
rgbToHsv: function (r, g, b) {
var r0, g0, b0, min0, max0, s, h, v;
r0 = r / 255;
g0 = g / 255;
b0 = b / 255;
min0 = Math.min(r0, g0, b0);
max0 = Math.max(r0, g0, b0);
h = 0;
s = max0 === 0 ? 0 : 1 - min0 / max0;
v = max0;
if (max0 == min0) {
h = 0;
} else if (max0 == r0 && g0 >= b0) {
h = 60 * (g0 - b0) / (max0 - min0) + 0;
} else if (max0 == r0 && g0 < b0) {
h = 60 * (g0 - b0) / (max0 - min0) + 360;
} else if (max0 == g0) {
h = 60 * (b0 - r0) / (max0 - min0) + 120;
} else if (max0 == b0) {
h = 60 * (r0 - g0) / (max0 - min0) + 240;
}
return [h, s, v];
}
};
function joinAttributes(attrs) {
var result = " ";
if (attrs) for (var a in attrs) {
result += a + "=\"" + attrs[a] + "\" ";
}
return result;
} // SVG
var SVG = {};
SVG.draw = function (content, width, height, css) {
var attrs = {
xmlns: "http://www.w3.org/2000/svg",
version: "1.1",
height: "100%",
width: "100%",
viewBox: "0 0 " + width + " " + height,
"class": css || ""
};
return "<svg " + joinAttributes(attrs) + ">" + content + "</svg>";
};
SVG.styleMap = {
"lineColor": "stroke",
"color": "fill"
};
SVG.group = function (path) {
return "<g>" + path + "</g>";
};
SVG._handlers = {
// MoveTo: {x:px,y:py}
"M": function (p) {
return " M " + p.x + " " + p.y;
},
// LineTo: {x:px,y:py}
"L": function (p) {
return " L " + p.x + " " + p.y;
},
// Curve: 3 points {x:px,y:py}: two control points and an end point
"C": function (cp0, cp1, p) {
return " C " + cp0.x + " " + cp0.y + " " + cp1.x + " " + cp1.y + " " + p.x + " " + p.y;
},
// Arc: center point {x:px,y:py}, radius, angle0, angle1
"A": function (p, radius, angle0, angle1) {
var x = p.x + Math.cos(angle1) * radius;
var y = p.y + Math.sin(angle1) * radius;
var bigCircle = angle1 - angle0 >= Math.PI;
return " A " + radius + " " + radius + " 0 " + (bigCircle ? 1 : 0) + " 1 " + x + " " + y;
}
}; // points is an array of an array with two elements: {string} line type, {array}
SVG.definePath = function (points, close) {
var path = "";
for (var i = 0; i < points.length; i++) {
assert(points[i][0] && typeof points[i][0] == "string", "Path type must be a string");
var type = points[i][0].toUpperCase();
assert(this._handlers[type], "Incorrect path type");
path += this._handlers[type].apply(this, points[i].slice(1));
}
if (close) path += " Z";
return path;
};
SVG._linePoints = function (points) {
var result = [];
for (var i = 0; i < points.length; i++) {
result.push([i ? "L" : "M", points[i]]);
}
return result;
};
SVG.setOpacity = function (rawColor, opacity) {
var rgbColor = color.toRgb(rawColor);
rgbColor.push(opacity);
return "rgba(" + rgbColor.join(",") + ")";
};
SVG._curvePoints = function (points) {
var result = [];
for (var i = 0; i < points.length; i++) {
var p = points[i];
if (!i) {
result.push(["M", p[0]]);
}
result.push(["C", p[1], p[2], p[3]]);
}
return result;
};
SVG.getPath = function (path, css, attrs) {
attrs = joinAttributes(attrs);
return "<path class=\"" + css + "\" vector-effect=\"non-scaling-stroke\" d=\"" + path + "\" " + attrs + "/>";
};
SVG.getSector = function (p, radius, angle0, angle1, css, attrs) {
attrs = joinAttributes(attrs);
var x0 = p.x + Math.cos(angle0) * radius;
var y0 = p.y + Math.sin(angle0) * radius;
var lines = [["M", p], ["L", {
x: x0,
y: y0
}], ["A", p, radius, angle0, angle1], ["L", p]];
return "<path class=\"" + css + "\" vector-effect=\"non-scaling-stroke\" d=\"" + SVG.definePath(lines, true) + "\" " + attrs + "/>";
};
SVG.getCurve = function (points, css, attrs) {
attrs = joinAttributes(attrs);
var path = this.definePath(this._curvePoints(points));
return "<path fill=\"none\" class=\"" + css + "\" vector-effect=\"non-scaling-stroke\" d=\"" + path + "\" " + attrs + "/>";
};
SVG.getLine = function (p0, p1, css, attrs) {
return this.getPath(this.definePath(this._linePoints([p0, p1]), true), css, attrs);
};
SVG.getCircle = function (p, radius, css, attrs) {
attrs = joinAttributes(attrs);
return "<circle class=\"" + css + "\" cx=\"" + p.x + "\" cy=\"" + p.y + "\" r=\"" + radius + "\" " + attrs + "/>";
};
SVG.getRect = function (x, y, width, height, css, attrs) {
attrs = joinAttributes(attrs);
return "<rect class=\"" + css + "\" rx=\"0\" ry=\"0\" x=\"" + x + "\" y=\"" + y + "\" width=\"" + width + "\" height=\"" + height + "\" " + attrs + "/>";
};
var defaults = {
paddingX: 6,
paddingY: 6,
radius: 2,
minHeight: 4,
eventRadius: 8
};
function Line(config) {
this.config = exports.extend(copy(defaults), config || {}, true);
}
Line.prototype.draw = function (data, width, height) {
var points = this.getPoints(data, width, height);
var config = this.config;
var renderer = SVG;
var styles = config.color ? this._applyColor(renderer, config.color) : null; // draw line
var path = renderer.definePath(this._getLinePoints(points));
var graph = renderer.group(renderer.getPath(path, "webix_sparklines_line" + (styles ? " " + styles.line : ""))); // draw items
graph += this._drawItems(renderer, points, config.radius, "webix_sparklines_item" + (styles ? " " + styles.item : "")); // draw event items
var eventRadius = Math.min(data.length ? (width - 2 * (config.paddingX || 0)) / data.length : 0, config.eventRadius);
graph += this._drawEventItems(renderer, points, eventRadius);
return renderer.draw(graph, width, height, "webix_sparklines_line_chart" + (config.css ? " " + config.css : ""));
};
Line.prototype._applyColor = function (renderer, color) {
var config = {
"line": {},
"item": {}
},
map = renderer.styleMap;
if (color) {
config.line[map.lineColor] = color;
config.item[map.color] = color;
for (var name in config) {
config[name] = createCss(config[name]);
}
}
return config;
};
Line.prototype._drawItems = function (renderer, points, radius, css, attrs) {
var items = [];
for (var i = 0; i < points.length; i++) {
items.push(renderer.getCircle(points[i], radius, css, attrs));
}
return renderer.group(items.join(""));
};
Line.prototype._drawEventItems = function (renderer, points, radius) {
var items = [];
for (var i = 0; i < points.length; i++) {
items.push(renderer.getCircle(points[i], radius, "webix_sparklines_event_area", {
webix_area: i
}));
}
return renderer.group(items.join(""));
};
Line.prototype._getLinePoints = function (points) {
var i,
type,
result = [];
for (i = 0; i < points.length; i++) {
type = i ? "L" : "M";
result.push([type, points[i]]);
}
return result;
};
Line.prototype.getPoints = function (data, width, height) {
var config = this.config;
var minValue = Math.min.apply(null, data);
if (typeof config.origin !== "undefined") minValue = Math.min(config.origin, minValue);
var maxValue = Math.max.apply(null, data);
var result = [];
var x = config.paddingX || 0;
var y = config.paddingY || 0;
width = (width || 100) - x * 2;
var minHeight = config.minHeight || 0;
height = (height || 100) - y * 2;
if (data.length) {
if (data.length == 1) result.push({
x: width / 2 + x,
y: height / 2 + x
});else {
var unitX = width / (data.length - 1);
var yNum = config.scale || maxValue - minValue;
var unitY = (height - minHeight) / (yNum ? yNum : 1);
if (!yNum) height /= 2;
for (var i = 0; i < data.length; i++) {
result.push({
x: Math.ceil(unitX * i) + x,
y: height - Math.ceil(unitY * (data[i] - minValue)) + y - minHeight
});
}
}
}
return result;
};
var defaults$1 = {
paddingX: 3,
paddingY: 4,
radius: 1,
minHeight: 4,
eventRadius: 8
};
function Area(config) {
this.config = exports.extend(copy(defaults$1), config || {}, true);
}
Area.prototype.draw = function (data, width, height) {
var eventRadius,
graph,
path,
points,
styles,
config = this.config,
Line$$1 = Line.prototype,
renderer = SVG; // draw area
points = this.getPoints(data, width, height);
path = renderer.definePath(Line$$1._getLinePoints(points), true);
if (config.color) styles = this._applyColor(renderer, config.color);
graph = renderer.group(renderer.getPath(path, "webix_sparklines_area" + (styles ? " " + styles.area : ""))); // draw line
points.splice(points.length - 3, 3);
path = renderer.definePath(Line$$1._getLinePoints(points));
graph += renderer.group(renderer.getPath(path, "webix_sparklines_line" + (styles ? " " + styles.line : ""))); // draw items
graph += Line$$1._drawItems(renderer, points, config.radius, "webix_sparklines_item" + (styles ? " " + styles.item : "")); // draw event areas
eventRadius = Math.min(data.length ? (width - 2 * (config.paddingX || 0)) / data.length : 0, config.eventRadius);
graph += Line$$1._drawEventItems(renderer, points, eventRadius);
return renderer.draw(graph, width, height, "webix_sparklines_area_chart" + (config.css ? " " + config.css : ""));
};
Area.prototype._applyColor = function (renderer, color) {
var config = {
"area": {},
"line": {},
"item": {}
},
map = renderer.styleMap;
if (color) {
config.area[map.color] = renderer.setOpacity(color, 0.2);
config.line[map.lineColor] = color;
config.item[map.color] = color;
for (var name in config) {
config[name] = createCss(config[name]);
}
}
return config;
};
Area.prototype.getPoints = function (data, width, height) {
var Line$$1 = Line.prototype;
var points = Line$$1.getPoints.call(this, data, width, height);
var x = this.config.paddingX || 0;
var y = this.config.paddingY || 0;
points.push({
x: width - x,
y: height - y
}, {
x: x,
y: height - y
}, {
x: x,
y: points[0].y
});
return points;
};
var defaults$2 = {
paddingX: 3,
paddingY: 4,
width: 20,
margin: 4,
minHeight: 4,
eventRadius: 8,
origin: 0,
itemCss: function (value) {
return value < (this.config.origin || 0) ? " webix_sparklines_bar_negative" : "";
}
};
function Bar(config) {
this.config = exports.extend(copy(defaults$2), config || {}, true);
}
Bar.prototype.draw = function (data, width, height) {
var i,
css,
p,
y,
padding,
config = this.config,
graph = "",
items = [],
points = this.getPoints(data, width, height),
renderer = SVG; // draw bars
for (i = 0; i < points.length; i++) {
css = typeof config.itemCss == "function" ? config.itemCss.call(this, data[i]) : config.itemCss || "";
if (config.negativeColor && data[i] < config.origin) css += " " + this._applyColor(renderer, config.negativeColor);else if (config.color) css += " " + this._applyColor(renderer, config.color);
p = points[i];
items.push(renderer.getRect(p.x, p.y, p.width, p.height, "webix_sparklines_bar " + css));
}
graph += renderer.group(items.join("")); // origin)
y = parseInt(this._getOrigin(data, width, height), 10) + 0.5;
padding = config.paddingX || 0;
graph += renderer.group(renderer.getLine({
x: padding,
y: y
}, {
x: width - padding,
y: y
}, "webix_sparklines_origin")); // event areas
var evPoints = this._getEventPoints(data, width, height);
var evItems = [];
for (i = 0; i < evPoints.length; i++) {
p = evPoints[i];
evItems.push(renderer.getRect(p.x, p.y, p.width, p.height, "webix_sparklines_event_area ", {
"webix_area": i
}));
}
graph += renderer.group(evItems.join(""));
return renderer.draw(graph, width, height, "webix_sparklines_bar_chart" + (config.css ? " " + config.css : ""));
};
Bar.prototype._applyColor = function (renderer, color) {
var config = {},
map = renderer.styleMap;
if (color) config[map.color] = color;
return createCss(config);
};
Bar.prototype._getOrigin = function (data, width, height) {
var config = this.config;
var y = config.paddingY || 0;
height = (height || 100) - y * 2;
var pos$$1 = y + height;
if (config.origin !== false) {
var minValue = Math.min.apply(null, data);
var maxValue = Math.max.apply(null, data);
var origin = config.origin || -0.000001;
if (origin >= maxValue) {
pos$$1 = y;
} else if (origin > minValue) {
var unitY = height / (maxValue - minValue);
pos$$1 -= unitY * (origin - minValue);
}
}
return pos$$1;
};
Bar.prototype._getEventPoints = function (data, width, height) {
var result = [];
var x = this.config.paddingX || 0;
var y = this.config.paddingY || 0;
width = (width || 100) - x * 2;
height = (height || 100) - y * 2;
if (data.length) {
var unitX = width / data.length;
for (var i = 0; i < data.length; i++) {
result.push({
x: Math.ceil(unitX * i) + x,
y: y,
height: height,
width: unitX
});
}
}
return result;
};
Bar.prototype.getPoints = function (data, width, height) {
var config = this.config;
var minValue = Math.min.apply(null, data);
if (config.origin < minValue) minValue = config.origin;
var maxValue = Math.max.apply(null, data);
var result = [];
var x = config.paddingX;
var y = config.paddingY;
var margin = config.margin;
var barWidth = config.width || 20;
var originY = this._getOrigin(data, width, height);
width = (width || 100) - x * 2;
height = (height || 100) - y * 2;
if (data.length) {
var unitX = width / data.length;
var yNum = config.scale || maxValue - minValue;
barWidth = Math.min(unitX - margin, barWidth);
margin = unitX - barWidth;
var minHeight = 0;
var origin = minValue;
if (config.origin !== false && config.origin > minValue) origin = config.origin || 0;else minHeight = config.minHeight;
var unitY = (height - minHeight) / (yNum ? yNum : 1);
for (var i = 0; i < data.length; i++) {
var h = Math.ceil(unitY * (data[i] - origin));
result.push({
x: Math.ceil(unitX * i) + x + margin / 2,
y: originY - (data[i] >= origin ? h : 0) - minHeight,
height: Math.abs(h) + minHeight,
width: barWidth
});
}
}
return result;
};
var defaults$3 = {
paddingY: 2
};
function Pie(config) {
this.config = exports.extend(defaults$3, config || {}, true);
}
Pie.prototype._defColorsCursor = 0;
Pie.prototype._defColors = ["#f55b50", "#ff6d3f", "#ffa521", "#ffc927", "#ffee54", "#d3e153", "#9acb61", "#63b967", "#21a497", "#21c5da", "#3ea4f5", "#5868bf", "#7b53c0", "#a943ba", "#ec3b77", "#9eb0b8"];
Pie.prototype._getColor = function (i, data) {
var count = data.length;
var colorsCount = this._defColors.length;
if (colorsCount > count) {
if (i) {
if (i < colorsCount - count) i = this._defColorsCursor + 2;else i = this._defColorsCursor + 1;
}
this._defColorsCursor = i;
} else i = i % colorsCount;
return this._defColors[i];
};
Pie.prototype.draw = function (data, width, height) {
var attrs,
graph,
i,
sectors,
config = this.config,
color = config.color || this._getColor,
points = this.getAngles(data),
renderer = SVG,
y = config.paddingY || 0,
// radius
r = height / 2 - y,
// center
x0 = width / 2,
y0 = height / 2; // draw sectors
if (typeof color != "function") color = function () {
return color;
};
sectors = "";
for (i = 0; i < points.length; i++) {
attrs = {};
attrs[renderer.styleMap["color"]] = color.call(this, i, data, this._context);
sectors += renderer.getSector({
x: x0,
y: y0
}, r, points[i][0], points[i][1], "webix_sparklines_sector", attrs);
}
graph = renderer.group(sectors); // draw event areas
sectors = "";
for (i = 0; i < points.length; i++) {
sectors += renderer.getSector({
x: x0,
y: y0
}, r, points[i][0], points[i][1], "webix_sparklines_event_area", {
"webix_area": i
});
}
graph += renderer.group(sectors);
return renderer.draw(graph, width, height, "webix_sparklines_pie_chart" + (config.css ? " " + config.css : ""));
};
Pie.prototype.getAngles = function (data) {
var a0 = -Math.PI / 2,
a1,
i,
result = [];
var ratios = this._getRatios(data);
for (i = 0; i < data.length; i++) {
a1 = -Math.PI / 2 + ratios[i] - 0.0001;
result.push([a0, a1]);
a0 = a1;
}
return result;
};
Pie.prototype._getTotalValue = function (data) {
var t = 0;
for (var i = 0; i < data.length; i++) {
t += data[i] * 1;
}
return t;
};
Pie.prototype._getRatios = function (data) {
var i,
value,
ratios = [],
prevSum = 0,
totalValue = this._getTotalValue(data);
for (i = 0; i < data.length; i++) {
value = data[i] * 1;
ratios[i] = Math.PI * 2 * (totalValue ? (value + prevSum) / totalValue : 1 / data.length);
prevSum += value;
}
return ratios;
};
var defaults$4 = {
paddingX: 3,
paddingY: 6,
radius: 2,
minHeight: 4,
eventRadius: 8
};
function Spline(config) {
this.config = exports.extend(copy(defaults$4), config || {}, true);
}
Spline.prototype.draw = function (data, width, height) {
var config = this.config,
graph = "",
Line$$1 = Line.prototype,
points = this.getPoints(data, width, height),
renderer = SVG,
styles = config.color ? this._applyColor(renderer, config.color) : null; // draw spline
graph += renderer.group(renderer.getCurve(points, "webix_sparklines_line" + (styles ? " " + styles.line : "")));
var linePoints = Line$$1.getPoints.call(this, data, width, height); // draw items
graph += Line$$1._drawItems(renderer, linePoints, config.radius, "webix_sparklines_item" + (styles ? " " + styles.item : "")); // draw event items
var eventRadius = Math.min(data.length ? (width - 2 * (config.paddingX || 0)) / data.length : 0, config.eventRadius);
graph += Line$$1._drawEventItems(renderer, linePoints, eventRadius);
return renderer.draw(graph, width, height, "webix_sparklines_line_chart" + (config.css ? " " + config.css : ""));
};
Spline.prototype._applyColor = function (renderer, color) {
var config = {
"line": {},
"item": {}
},
map = renderer.styleMap;
if (color) {
config.line[map.lineColor] = color;
config.item[map.color] = color;
for (var name in config) {
config[name] = createCss(config[name]);
}
}
return config;
};
Spline.prototype.getPoints = function (data, width, height) {
var i,
points,
px,
py,
result = [],
x = [],
y = [],
Line$$1 = Line.prototype;
points = Line$$1.getPoints.call(this, data, width, height);
for (i = 0; i < points.length; i++) {
x.push(points[i].x);
y.push(points[i].y);
}
px = this._getControlPoints(x);
py = this._getControlPoints(y);
/*updates path settings, the browser will draw the new spline*/
for (i = 0; i < points.length - 1; i++) {
result.push([points[i], {
x: px[0][i],
y: py[0][i]
}, {
x: px[1][i],
y: py[1][i]
}, points[i + 1]]);
}
return result;
};
/* code from https://www.particleincell.com/2012/bezier-splines/ */
Spline.prototype._getControlPoints = function (points) {
var a = [],
b = [],
c = [],
r = [],
p1 = [],
p2 = [],
i,
m,
n = points.length - 1;
a[0] = 0;
b[0] = 2;
c[0] = 1;
r[0] = points[0] + 2 * points[1];
for (i = 1; i < n - 1; i++) {
a[i] = 1;
b[i] = 4;
c[i] = 1;
r[i] = 4 * points[i] + 2 * points[i + 1];
}
a[n - 1] = 2;
b[n - 1] = 7;
c[n - 1] = 0;
r[n - 1] = 8 * points[n - 1] + points[n];
for (i = 1; i < n; i++) {
m = a[i] / b[i - 1];
b[i] = b[i] - m * c[i - 1];
r[i] = r[i] - m * r[i - 1];
}
p1[n - 1] = r[n - 1] / b[n - 1];
for (i = n - 2; i >= 0; --i) {
p1[i] = (r[i] - c[i] * p1[i + 1]) / b[i];
}
for (i = 0; i < n - 1; i++) {
p2[i] = 2 * points[i + 1] - p1[i + 1];
}
p2[n - 1] = 0.5 * (points[n] + p1[n - 1]);
return [p1, p2];
};
var defaultsArea = {
paddingX: 3,
paddingY: 6,
radius: 1,
minHeight: 4,
eventRadius: 8
}; // spline area
function SplineArea(config) {
this.config = exports.extend(copy(defaultsArea), config || {}, true);
}
SplineArea.prototype = copy(Spline.prototype);
SplineArea.prototype.draw = function (data, width, height) {
var config = this.config,
Line$$1 = Line.prototype,
renderer = SVG,
styles = config.color ? this._applyColor(renderer, config.color) : null;
var points = this.getPoints(data, width, height); // draw area
var linePoints = points.splice(points.length - 3, 3);
var linePath = renderer._linePoints(linePoints);
linePath[0][0] = "L";
var areaPoints = renderer._curvePoints(points).concat(linePath);
var graph = renderer.group(renderer.getPath(renderer.definePath(areaPoints), "webix_sparklines_area" + (styles ? " " + styles.area : ""), true)); // draw line
graph += renderer.group(renderer.getPath(renderer.definePath(renderer._curvePoints(points)), "webix_sparklines_line" + (styles ? " " + styles.line : "")));
var itemPoints = Line$$1.getPoints.call(this, data, width, height); // draw items
graph += Line$$1._drawItems(renderer, itemPoints, config.radius, "webix_sparklines_item" + (styles ? " " + styles.item : "")); // draw event items
var eventRadius = Math.min(data.length ? (width - 2 * (config.paddingX || 0)) / data.length : 0, config.eventRadius);
graph += Line$$1._drawEventItems(renderer, itemPoints, eventRadius);
return renderer.draw(graph, width, height, "webix_sparklines_splinearea_chart" + (config.css ? " " + config.css : ""));
};
SplineArea.prototype._applyColor = function (renderer, color) {
var config = {
"area": {},
"line": {},
"item": {}
},
map = renderer.styleMap;
if (color) {
config.area[map.color] = renderer.setOpacity(color, 0.2);
config.line[map.lineColor] = color;
config.item[map.color] = color;
for (var name in config) {
config[name] = createCss(config[name]);
}
}
return config;
};
SplineArea.prototype.getPoints = function (data, width, height) {
var points = Spline.prototype.getPoints.call(this, data, width, height);
var x = this.config.paddingX || 0;
var y = this.config.paddingY || 0;
points.push({
x: width - x,
y: height - y
}, {
x: x,
y: height - y
}, {
x: x,
y: points[0][0].y
});
return points;
};
function Sparklines() {}
function getData(data) {
var values = [];
for (var i = data.length - 1; i >= 0; i--) {
var value = data[i];
values[i] = _typeof(value) === "object" ? value.value : value;
}
return values;
}
Sparklines.types = {};
Sparklines.getTemplate = function (customConfig) {
var config = customConfig || {};
if (typeof customConfig == "string") config = {
type: customConfig
};
exports.extend(config, {
type: "line"
});
var slConstructor = this.types[config.type];
assert(slConstructor, "Unknown sparkline type");
return bind(this._template, new slConstructor(config));
};
Sparklines._template = function (item, common, data, column) {
if (column) return this.draw(getData(data), column.width, 33);else return this.draw(item.data || item, common.width, common.height);
}; // add "sparklines" type
attachEvent("onDataTable", function (table) {
table.type.sparklines = Sparklines.getTemplate();
});
Sparklines.types["area"] = Area;
Sparklines.types["bar"] = Bar;
Sparklines.types["line"] = Line;
Sparklines.types["pie"] = Pie;
Sparklines.types["spline"] = Spline;
Sparklines.types["splineArea"] = SplineArea;
var TablePaste = {
clipboard_setter: function (value) {
if (env.touch) return value;
if (value === true || value === 1) value = "block";
clipbuffer.init();
this.attachEvent("onSelectChange", this._sel_to_clip);
this.attachEvent("onAfterEditStop", function (v, ed) {
var sel = this.getSelectedId(true);
if (sel.length == 1 && ed.row == sel[0].row) this._sel_to_clip();
}); // solution for clicks on selected items
this.attachEvent("onItemClick", function () {
if (document.activeElement && this.$view.contains(document.activeElement)) {
clipbuffer.focus();
UIManager.setFocus(this);
}
});
this.attachEvent("onPaste", this._clip_to_sel);
return value;
},
templateCopy_setter: template,
_sel_to_clip: function () {
var _this = this;
delay(function () {
//wait until editor is closed
if (!_this.getEditor || !_this.getEditor()) {
var data = _this._get_sel_text();
clipbuffer.set(data);
UIManager.setFocus(_this);
}
});
},
_get_sel_text: function () {
var data = [];
var filter = this._settings.templateCopy;
this.mapSelection(function (value, row, col, row_ind) {
if (!data[row_ind]) data[row_ind] = [];
var newvalue = filter ? filter(value, row, col) : value;
data[row_ind].push(newvalue);
return value;
});
var value = data.length === 1 && data[0].length === 1 ? data[0][0] : csv$1.stringify(data, this._settings.delimiter);
return value;
},
_clip_to_sel: function (text) {
if (!isUndefined(this._paste[this._settings.clipboard])) {
var data = csv$1.parse(text, this._settings.delimiter);
this._paste[this._settings.clipboard].call(this, data);
}
},
_paste: {
block: function (data) {
var leftTop = this.mapSelection(null);
if (!leftTop) return; // filling cells with data
this.mapCells(leftTop.row, leftTop.column, data.length, null, function (value, row, col, row_ind, col_ind) {
if (data[row_ind] && data[row_ind].length > col_ind) {
return data[row_ind][col_ind];
}
return value;
});
this.render();
},
selection: function (data) {
this.mapSelection(function (value, row, col, row_ind, col_ind) {
if (data[row_ind] && data[row_ind].length > col_ind) return data[row_ind][col_ind];
return value;
});
this.render();
},
repeat: function (data) {
this.mapSelection(function (value, row, col, row_ind, col_ind) {
row = data[row_ind % data.length];
value = row[col_ind % row.length];
return value;
});
this.render();
},
custom: function () {}
}
};
var TreeAPI = {
open: function (id, show) {
if (!id) return; //ignore open for leaf items
var item = this.getItem(id);
assert(item, "Incorrect ID to open: " + id);
if (!item.$count || item.open) return;
if (this.callEvent("onBeforeOpen", [id])) {
item.open = true;
this.data.callEvent("onStoreUpdated", [id, 0, "branch"]);
this.callEvent("onAfterOpen", [id]);
}
if (show && id != "0") this.open(this.getParentId(id), show);
},
close: function (id) {
if (!id) return;
var item = this.getItem(id);
if (!item.open) return;
if (this.callEvent("onBeforeClose", [id])) {
item.open = false;
this.data.callEvent("onStoreUpdated", [id, 0, "branch"]);
this.callEvent("onAfterClose", [id]);
}
},
openAll: function (id) {
this.data.eachSubItem(id || 0, function (obj, branch) {
if (branch) obj.open = true;
});
this.data.refresh();
},
closeAll: function (id) {
this.data.eachSubItem(id || 0, function (obj, branch) {
if (branch) obj.open = false;
});
this.data.refresh();
},
_tree_check_uncheck: function (id, mode, e) {
if (this._settings.threeState) return this._tree_check_uncheck_3(id, mode !== null ? mode : "");
var value,
item = this.getItem(id),
trg = e ? e.target : null; //read actual value from HTML tag when possible
//as it can be affected by dbl-clicks
if (trg && trg.type == "checkbox") value = trg.checked ? true : false;else value = mode !== null ? mode : !item.checked;
item.checked = value;
this.callEvent("onItemCheck", [id, item.checked, e]);
},
isBranchOpen: function (search_id) {
if (search_id == "0") return true;
var item = this.getItem(search_id);
if (item.open) return this.isBranchOpen(item.$parent);
return false;
},
getOpenItems: function () {
var open = [];
for (var id in this.data.branch) {
if (this.exists(id) && this.getItem(id).open) open.push(id);
}
return open;
},
getState: function () {
return {
open: this.getOpenItems(),
select: this.getSelectedId(true)
};
},
_repeat_set_state: function (tree, open) {
var event = this.data.attachEvent("onStoreLoad", function () {
tree.setState.call(tree, open);
tree.data.detachEvent(event);
tree = null;
});
},
setState: function (state) {
if (state.open) {
this.closeAll();
var open = state.open;
for (var i = 0; i < open.length; i++) {
var item = this.getItem(open[i]);
if (item && item.$count) {
item.open = true; //dynamic loading
if (item.$count == -1) {
//call the same method after data loading
this._repeat_set_state(this, state);
this.refresh();
return 0; //end processing
}
}
}
this.refresh();
}
if (state.select && this.select) {
var select = state.select;
this.unselect();
for (var _i = 0; _i < select.length; _i++) {
if (this.exists(select[_i])) this.select(select[_i], true);
}
}
return 1;
}
};
var TreeClick = {
webix_tree_open: function (e, id) {
this.close(id);
return false;
},
webix_tree_close: function (e, id) {
this.open(id);
return false;
},
webix_tree_checkbox: function (e, id) {
this._tree_check_uncheck(id, null, e);
return false;
}
};
var TreeDataLoader = {
$init: function () {
this.data.attachEvent("onStoreUpdated", bind(this._sync_hierarchy, this), null, true); //redefine methods
this._feed_common = this._feed_commonA;
},
_feed_commonA: function (from, count, callback, defer, details, clear) {
// branch loading
details = count === 0 ? {
parent: encodeURIComponent(from)
} : null;
return DataLoader.prototype._feed_common.call(this, from, count, callback, defer, details, clear);
},
//load next set of data rows
loadBranch: function (id, callback, url) {
id = id || 0;
this.data.url = url || this.data.url;
if (this.callEvent("onDataRequest", [id, callback, this.data.url]) && this.data.url) return this.data.feed.call(this, id, 0, callback);
return Deferred.reject();
},
_sync_hierarchy: function (id, data, mode) {
if (!mode || mode == "add" || mode == "delete" || mode == "branch") {
this.data._sync_to_order(this);
}
}
};
/*
Behavior:DataMove - allows to move and copy elements, heavily relays on DataStore.move
@export
copy
move
*/
var TreeDataMove = {
$init: function () {
assert(this.data, "DataMove :: Component doesn't have DataStore");
},
//creates a copy of the item
copy: function (sid, tindex, tobj, details) {
details = details || {};
details.copy = true;
return this.move(sid, tindex, tobj, details);
},
_next_move_index: function (nid, next, source) {
if (next && nid) {
var new_index = this.getBranchIndex(nid); // check parent only when moving locally (source == this)
return new_index + (source == this && this.getParentId(nid) == this.getParentId(next) && source.getBranchIndex(next) < new_index ? 0 : 1);
}
},
_check_branch_child: function (parent, child) {
var t = this.data.branch[parent];
if (t && t.length) {
for (var i = 0; i < t.length; i++) {
if (t[i] == child) return true;
if (this._check_branch_child(t[i], child)) return true;
}
}
return false;
},
_remove_childs: function (ids) {
for (var i = 0; i < ids.length; i++) {
var id = ids[i];
while (this.getParentId(id)) {
id = this.getParentId(id);
if (_power_array.find.call(ids, id) != -1) {
ids.splice(i, 1);
i--;
continue;
}
}
}
return ids;
},
//move item to the new position
move: function (sid, tindex, tobj, details) {
details = details || {};
tindex = tindex || 0;
var new_id = details.newId || sid;
var target_parent = details.parent || 0;
tobj = tobj || this;
assert(tobj.data, "moving attempt to component without datastore");
if (!tobj.data) return;
if (isArray(sid)) {
this._remove_childs(sid);
for (var i = 0; i < sid.length; i++) {
//increase index for each next item in the set, so order of insertion will be equal to order in the array
var nid = this.move(sid[i], tindex, tobj, details);
tindex = tobj._next_move_index(nid, sid[i + 1], this);
}
return;
}
if (this != tobj || details.copy) {
new_id = tobj.data.add(tobj._externalData(this.getItem(sid), new_id), tindex, target_parent || 0);
if (this.data.branch[sid] && tobj.getBranchIndex) {
var temp = this.data._scheme_serialize;
this.data._scheme_serialize = function (obj) {
var copy$$1 = copy(obj);
delete copy$$1.$parent;
delete copy$$1.$level;
delete copy$$1.$child;
if (tobj.data.pull[copy$$1.id]) copy$$1.id = uid();
return copy$$1;
};
var copy_data = {
data: this.serialize(sid, true),
parent: new_id
};
this.data._scheme_serialize = temp;
tobj.parse(copy_data);
}
if (!details.copy) this.data.remove(sid);
} else {
//move in self
if (sid == target_parent || this._check_branch_child(sid, target_parent)) return;
var source = this.getItem(sid);
var tbranch = this.data.branch[target_parent];
if (!tbranch) tbranch = this.data.branch[target_parent] = [];
var sbranch = this.data.branch[source.$parent];
var sindex = _power_array.find.call(sbranch, sid);
if (tindex < 0) tindex = tbranch.length; //in the same branch and same position
if (sbranch === tbranch && tindex === sindex) return new_id; //return ID
_power_array.removeAt.call(sbranch, sindex);
_power_array.insertAt.call(tbranch, sid, Math.min(tbranch.length, tindex));
if (!sbranch.length) delete this.data.branch[source.$parent];
if (source.$parent && source.$parent != "0") this.getItem(source.$parent).$count--;
if (target_parent && target_parent != "0") {
var target = tobj.getItem(target_parent);
target.$count++;
this._set_level_rec(source, target.$level + 1);
} else this._set_level_rec(source, 1);
source.$parent = target_parent;
tobj.data.callEvent("onDataMove", [sid, tindex, target_parent, tbranch[tindex + 1]]);
}
this.refresh();
return new_id; //return ID of item after moving
},
_set_level_rec: function (item, value) {
item.$level = value;
var branch = this.data.branch[item.id];
if (branch) for (var i = 0; i < branch.length; i++) {
this._set_level_rec(this.getItem(branch[i]), value + 1);
}
},
//reaction on pause during dnd
_drag_pause: function (id) {
if (id && !id.header && this.exists(id) && this._target_to_id(id) != DragControl._drag_context.start) //ignore drag other header
this.open(id);
},
$dropAllow: function (context) {
if (context.from != context.to) return true;
for (var i = 0; i < context.source.length; i++) {
if (this._check_branch_child(context.source, context.target)) return false;
}
return true;
},
/*
this is a stub for future functionality
currently it just makes a copy of data object, which is enough for current situation
*/
_externalData: function (data, id) {
var new_data = DataMove._externalData.call(this, data, id);
delete new_data.open;
return new_data;
}
};
var TreeRenderStack = {
$init: function () {
assert(this.render, "TreeRenderStack :: Object must use RenderStack first");
},
_toHTMLItem: function (obj) {
var mark = this.data._marks[obj.id];
this.callEvent("onItemRender", [obj]);
return this.type.templateStart(obj, this.type, mark) + (obj.$template ? this.type["template" + obj.$template](obj, this.type, mark) : this.type.template(obj, this.type, mark)) + this.type.templateEnd();
},
_toHTMLItemObject: function (obj) {
this._html.innerHTML = this._toHTMLItem(obj);
return this._html.firstChild;
},
//convert single item to HTML text (templating)
_toHTML: function (obj) {
//check if related template exist
assert(!obj.$template || this.type["template" + obj.$template], "RenderStack :: Unknown template: " + obj.$template);
var html = "<div role='presentation' class='webix_tree_branch_" + obj.$level + "'>" + this._toHTMLItem(obj);
if (obj.open) html += this._toHTMLLevel(obj.id);
html += "</div>";
return html;
},
_toHTMLLevel: function (id) {
var html = "";
var leaves = this.data.branch[id];
if (leaves) {
html += "<div role='presentation' class='webix_tree_leaves'>";
var last = leaves.length - 1;
for (var i = 0; i <= last; i++) {
var obj = this.getItem(leaves[i]);
var state = this.type._tree_branch_render_state;
if (state !== 0) state[obj.$level] = i == last;
html += this._toHTML(obj);
}
html += "</div>";
}
return html;
},
//return true when some actual rendering done
render: function (id, data, type) {
TreeRenderStack._obj = this; //can be used from complex render
if (!this.isVisible(this._settings.id) || this.$blockRender) return;
if (id) {
var cont, node;
var item = this.getItem(id);
if (type != "add") {
cont = this.getItemNode(id);
if (!cont) return;
}
switch (type) {
case "branch":
var branch = cont.parentNode;
node = this._toHTMLObject(item);
insertBefore(node, branch);
remove(branch);
this._htmlmap = null;
break;
case "paint":
case "update":
node = this._htmlmap[id] = this._toHTMLItemObject(item);
insertBefore(node, cont);
remove(cont);
break;
case "delete":
//deleting not item , but full branch
remove(cont.parentNode);
break;
case "add":
var parent; //we want process both empty value and 0 as string
//jshint -W041:true
if (item.$parent == 0) {
parent = this._dataobj.firstChild;
} else if (this.getItem(item.$parent).open) {
parent = this.getItemNode(item.$parent);
if (parent) {
//when item created by the script, it will miss the container for child notes
//create it on demand
if (!parent.nextSibling) {
var leafs = create("DIV", {
"class": "webix_tree_leaves"
}, "");
parent.parentNode.appendChild(leafs);
}
parent = parent.nextSibling;
}
}
if (parent) {
var next = this.data.getNextSiblingId(id);
next = this.getItemNode(next);
if (next) next = next.parentNode;
node = this._toHTMLObject(item);
this._htmlmap[id] = node.firstChild;
insertBefore(node, next, parent);
}
break;
default:
return false;
}
this.callEvent("onPartialRender", [id, data, type]);
} else {
//full reset
if (this.callEvent("onBeforeRender", [this.data])) {
//will be used for lines management
this.type._tree_branch_render_state = []; //getTopRange - returns all elements on top level
this._dataobj.innerHTML = this._toHTMLLevel(0);
this._htmlmap = null; //clear map, it will be filled at first getItemNode
this.callEvent("onAfterRender", []);
}
} //clear after usage
this.type._tree_branch_render_state = 0;
TreeRenderStack._obj = null;
return true;
},
getItemNode: function (search_id) {
if (this._htmlmap) return this._htmlmap[search_id]; //fill map if it doesn't created yet
this._htmlmap = {};
var t = this._dataobj.getElementsByTagName("DIV");
for (var i = 0; i < t.length; i++) {
var id = t[i].getAttribute(this._id); //get item's
if (id) this._htmlmap[id] = t[i];
} //call locator again, when map is filled
return this.getItemNode(search_id);
},
_branch_render_supported: 1
};
var TreeStateCheckbox = {
_init_render_tree_state: function () {
if (this._branch_render_supported) {
var old_render = this.render;
this.render = function (id, data) {
var updated = old_render.apply(this, arguments);
if (this._settings.threeState && updated && data != "checkbox") this._setThirdState.apply(this, arguments);
};
this._init_render_tree_state = function () {};
}
},
threeState_setter: function (value) {
if (value) this._init_render_tree_state();
return value;
},
_setThirdState: function (id) {
var i, leaves, parents, checkedParents, tree;
parents = [];
tree = this;
/*if item was removed*/
if (id && !tree.data.pull[id]) {
id = 0;
}
/*sets checkbox states*/
/*if branch or full reloading*/
if (!id || tree.data.pull[id].$count) {
leaves = this._getAllLeaves(id);
leaves.sort(function (a, b) {
return tree.data.pull[b].$level - tree.data.pull[a].$level;
});
for (i = 0; i < leaves.length; i++) {
if (!i || tree.data.pull[leaves[i]].$parent != tree.data.pull[leaves[i - 1]].$parent) parents = parents.concat(tree._setParentThirdState(leaves[i]));
}
} else {
/*an item is a leaf */
parents = parents.concat(tree._setParentThirdState(id));
}
checkedParents = {};
for (i = 0; i < parents.length; i++) {
if (!checkedParents[parents[i]]) {
checkedParents[parents[i]] = 1;
this._setCheckboxIndeterminate(parents[i]);
}
}
tree = null;
},
_setCheckboxIndeterminate: function (id) {
var chElem, elem;
elem = this.getItemNode(id);
if (elem) {
this.render(id, "checkbox", "update");
/*needed to get the new input obj and to set indeterminate state*/
if (this.getItem(id).indeterminate) {
elem = this.getItemNode(id);
chElem = elem.getElementsByTagName("input")[0];
if (chElem) chElem.indeterminate = this.getItem(id).indeterminate;
}
}
},
_setParentThirdState: function (itemId) {
//we need to use dynamic function creating
//jshint -W083:true
var checked, checkedCount, indeterminate, parentId, result, unsureCount, needrender;
parentId = this.getParentId(itemId);
result = [];
while (parentId && parentId != "0") {
unsureCount = 0;
checkedCount = 0;
this.data.eachChild(parentId, function (obj) {
if (obj.indeterminate) {
unsureCount++;
} else if (obj.checked) {
checkedCount++;
}
});
checked = indeterminate = needrender = false;
var item = this.getItem(parentId);
if (checkedCount == item.$count) {
checked = true;
} else if (checkedCount > 0 || unsureCount > 0) {
indeterminate = true;
} //we need to reset indeterminate in any case :(
if (indeterminate || indeterminate != item.indeterminate) needrender = true;
item.indeterminate = indeterminate;
if (checked || item.checked != checked) needrender = true;
item.checked = checked;
if (needrender) {
result.push(parentId);
parentId = this.getParentId(parentId);
} else parentId = 0;
}
return result;
},
/*get all checked items in tree*/
getChecked: function () {
var result = [];
var tree = this;
this.data.eachSubItem(0, function (obj) {
if (tree.isChecked(obj.id)) result.push(obj.id);
});
return result;
},
_tree_check_uncheck_3: function (id, mode) {
var item = this.getItem(id);
if (item) {
if (mode === "") mode = !item.checked;
if (item.checked != mode || item.indeterminate) {
item.checked = mode;
this._correctThreeState(id);
var parents = this._setParentThirdState(id);
if (this._branch_render_supported && parents.length < 5) {
for (var i = 0; i < parents.length; i++) {
this._setCheckboxIndeterminate(parents[i]);
}
} else this.refresh();
this.callEvent("onItemCheck", [id, mode]);
}
}
},
/*set checked state for item checkbox*/
checkItem: function (id) {
this._tree_check_uncheck(id, true);
this.updateItem(id);
},
/*uncheckes an item checkbox*/
uncheckItem: function (id) {
this._tree_check_uncheck(id, false);
this.updateItem(id);
},
_checkUncheckAll: function (id, mode, all) {
var method = mode ? "checkItem" : "uncheckItem";
if (!id) id = 0;else this[method](id);
if (this._settings.threeState) {
if (!id) this.data.eachChild(0, function (item) {
this[method](item.id);
}, this, all);
} else this.data.each(function (item) {
this[method](item.id);
}, this, all, id);
},
/*checkes checkboxes of all items in a branch/tree*/
checkAll: function (id, all) {
this._checkUncheckAll(id, true, all);
},
/*uncheckes checkboxes of all items in a branch/tree*/
uncheckAll: function (id, all) {
this._checkUncheckAll(id, false, all);
},
_correctThreeState: function (id) {
var state;
var item = this.getItem(id);
item.indeterminate = false;
state = item.checked;
this.data.eachSubItem(id, function (child) {
child.indeterminate = false;
child.checked = state;
});
if (this._branch_render_supported && this.isBranchOpen(item.$parent)) {
//for tree-render only
this.render(id, 0, "branch");
}
},
/*returns checked state of item checkbox*/
isChecked: function (id) {
return this.getItem(id).checked;
},
/*gets all leaves in a certain branch (in the whole tree if id is not set)*/
_getAllLeaves: function (parentId) {
var result = [];
this.data.eachSubItem(parentId, function (obj, branch) {
if (!branch) result.push(obj.id);
});
return result;
}
};
// #include core/bind.js
// #include core/treemove.js
var TreeStore = {
name: "TreeStore",
$init: function () {
this._filterMode = {
//level:1,
showSubItems: true
};
this.branch = {
0: []
};
this.attachEvent("onParse", function (driver) {
this._set_child_scheme(driver.child);
});
this.attachEvent("onClearAll", bind(function () {
this._filter_branch = null;
}, this));
},
filterMode_setter: function (mode) {
return exports.extend(this._filterMode, mode, true);
},
_filter_reset: function (preserve) {
//remove previous filtering , if any
if (this._filter_branch && !preserve) {
this.branch = this._filter_branch;
this.order = _to_array(copy(this.branch[0]));
for (var key in this.branch) {
if (key != "0") //exclude 0 - virtual root
this.getItem(key).$count = this.branch[key].length;
}
delete this._filter_branch;
}
},
_filter_core: function (filter, value, preserve, filterMode) {
//for tree we have few filtering options
//- filter leafs only
//- filter data on specific level
//- filter data on all levels
//- in all cases we can show or hide empty folder
//- in all cases we can show or hide childs for matched item
//set new order of items, store original
if (!preserve || !this._filter_branch) {
this._filter_branch = this.branch;
this.branch = clone(this.branch);
}
this.branch[0] = this._filter_branch_rec(filter, value, this.branch[0], 1, filterMode || {});
},
_filter_branch_rec: function (filter, value, branch, level, config) {
//jshint -W041
var neworder = [];
var allow = config.level && config.level != level;
for (var i = 0; i < branch.length; i++) {
var id = branch[i];
var item = this.getItem(id);
var child_run = false;
var sub = this.branch[id];
if (allow) {
child_run = true;
} else if (filter(this.getItem(id), value)) {
neworder.push(id); // open all parents of the found item
if (config.openParents !== false) {
var parentId = this.getParentId(id);
while (parentId && parentId != "0") {
this.getItem(parentId).open = 1;
parentId = this.getParentId(parentId);
}
} //in case of of fixed level filtering - do not change child-items
if (config.level || config.showSubItems) continue;
} else {
//filtering level, not match
child_run = true;
} //if "filter by all levels" - filter childs
if (allow || !config.level) {
if (sub) {
var newsub = this.branch[id] = this._filter_branch_rec(filter, value, sub, level + 1, config);
item.$count = newsub.length;
if (child_run && newsub.length) neworder.push(id);
}
}
}
return neworder;
},
count: function () {
if (this.order.length) return this.order.length; //we must return some non-zero value, or logic of selection will think that we have not data at all
var count = 0;
this.eachOpen(function () {
count++;
});
return count;
},
_change_branch_id: function (branches, parent, old, newid) {
if (branches[old]) {
var branch = branches[newid] = branches[old];
for (var i = 0; i < branch.length; i++) {
this.getItem(branch[i]).$parent = newid;
}
delete branches[old];
}
if (branches[parent]) {
var index = _power_array.find.call(branches[parent], old);
if (index >= 0) branches[parent][index] = newid;
}
},
changeId: function (old, newid) {
if (old == newid) return;
var parent = this.getItem(old).$parent;
this._change_branch_id(this.branch, parent, old, newid); //in case of filter applied, update id in filtered state as well
if (this._filter_branch) this._change_branch_id(this._filter_branch, parent, old, newid);
return DataStore.prototype.changeId.call(this, old, newid);
},
clearAll: function (soft) {
this.branch = {
0: []
};
DataStore.prototype.clearAll.call(this, soft);
},
getPrevSiblingId: function (id) {
var order = this.branch[this.getItem(id).$parent];
var pos = _power_array.find.call(order, id) - 1;
if (pos >= 0) return order[pos];
return null;
},
getNextSiblingId: function (id) {
var order = this.branch[this.getItem(id).$parent];
var pos = _power_array.find.call(order, id) + 1;
if (pos < order.length) return order[pos];
return null;
},
getParentId: function (id) {
return this.getItem(id).$parent;
},
getFirstChildId: function (id) {
var order = this.branch[id];
if (order && order.length) return order[0];
return null;
},
isBranch: function (parent) {
return !!this.branch[parent];
},
getBranchIndex: function (child) {
var t = this.branch[this.pull[child].$parent];
return _power_array.find.call(t, child);
},
_set_child_scheme: function (parse_name) {
if (typeof parse_name == "string") this._datadriver_child = function (obj) {
var t = obj[parse_name];
if (t) delete obj[parse_name];
return t;
};else this._datadriver_child = parse_name;
},
_inner_parse: function (info, recs) {
var parent = info.parent || 0;
for (var i = 0; i < recs.length; i++) {
//get hash of details for each record
var temp = this.driver.getDetails(recs[i]);
var id = this.id(temp); //generate ID for the record
var update = !!this.pull[id]; //update mode
if (update) {
temp = exports.extend(this.pull[id], temp, true);
if (this._scheme_update) this._scheme_update(temp);
} else {
if (this._scheme_init) this._scheme_init(temp);
this.pull[id] = temp;
}
this._extraParser(temp, parent, 0, update, info.from ? info.from * 1 + i : 0);
} //fix state of top item after data loading
var pItem = this.pull[parent] || {};
var pBranch = this.branch[parent] || [];
pItem.$count = pBranch.length;
delete pItem.webix_kids;
if (info.size && info.size != pBranch.length) pBranch[info.size - 1] = undefined;
},
_extraParser: function (obj, parent, level, update, from) {
//processing top item
obj.$count = 0; //using soft check, as parent can be a both 0 and "0" ( second one in case of loading from server side )
obj.$parent = parent != "0" ? parent : 0;
obj.$level = level || (parent != "0" ? this.pull[parent].$level + 1 : 1);
var parent_branch = this.branch[obj.$parent];
if (!parent_branch) parent_branch = this.branch[obj.$parent] = [];
if (this._filter_branch) this._filter_branch[obj.$parent] = parent_branch;
if (!update) {
var pos = from || parent_branch.length;
parent_branch[pos] = obj.id;
}
var child = this._datadriver_child(obj);
if (obj.webix_kids) {
return obj.$count = -1;
}
if (!child) //ignore childless
return obj.$count = 0; //when loading from xml we can have a single item instead of an array
if (!isArray(child)) child = [child];
for (var i = 0; i < child.length; i++) {
//extra processing to convert strings to objects
var item = DataDriver.json.getDetails(child[i]);
var itemid = this.id(item);
update = !!this.pull[itemid];
if (update) {
item = exports.extend(this.pull[itemid], item, true);
if (this._scheme_update) this._scheme_update(item);
} else {
if (this._scheme_init) this._scheme_init(item);
this.pull[itemid] = item;
}
this._extraParser(item, obj.id, obj.$level + 1, update);
} //processing childrens
var branch = this.branch[obj.id];
if (branch) obj.$count = branch.length;
},
_sync_to_order: function (master) {
this.order = _to_array(); // send current order to prevent simultaneous use in synс mode
this._sync_each_child(this.order, 0, master);
},
_sync_each_child: function (order, start, master) {
var branch = this.branch[start];
for (var i = 0; i < branch.length; i++) {
var id = branch[i];
order.push(id);
var item = this.pull[id];
if (item && item.open) {
if (item.$count == -1) master.loadBranch(id);else if (item.$count) this._sync_each_child(order, id, master);
}
}
},
provideApi: function (target, eventable) {
var list = ["getPrevSiblingId", "getNextSiblingId", "getParentId", "getFirstChildId", "isBranch", "getBranchIndex", "filterMode_setter"];
for (var i = 0; i < list.length; i++) {
target[list[i]] = this._methodPush(this, list[i]);
}
if (!target.getIndexById) DataStore.prototype.provideApi.call(this, target, eventable);
},
getTopRange: function () {
return _to_array([].concat(this.branch[0])).map(function (id) {
return this.getItem(id);
}, this);
},
eachChild: function (id, functor, master, all) {
var branch = this.branch;
if (all && this._filter_branch) branch = this._filter_branch;
var stack = branch[id];
if (stack) for (var i = 0; i < stack.length; i++) {
if (stack[i]) functor.call(master || this, this.getItem(stack[i]));
}
},
each: function (method, master, all, id) {
this.eachChild(id || 0, function (item) {
var branch = this.branch;
method.call(master || this, item);
if (all && this._filter_branch) branch = this._filter_branch;
if (item && branch[item.id]) this.each(method, master, all, item.id);
}, this, all);
},
eachOpen: function (method, master, id) {
this.eachChild(id || 0, function (item) {
method.call(master || this, item);
if (this.branch[item.id] && item.open) this.eachOpen(method, master, item.id);
});
},
eachSubItem: function (id, functor) {
var top = this.branch[id || 0];
if (top) for (var i = 0; i < top.length; i++) {
var key = top[i];
if (this.branch[key]) {
functor.call(this, this.getItem(key), true);
this.eachSubItem(key, functor);
} else functor.call(this, this.getItem(key), false);
}
},
eachLeaf: function (id, functor) {
var top = this.branch[id || 0];
if (top) for (var i = 0; i < top.length; i++) {
var key = top[i];
if (this.branch[key]) {
this.eachLeaf(key, functor);
} else functor.call(this, this.getItem(key), false);
}
},
_sort_core: function (sorter, order) {
for (var key in this.branch) {
var bset = this.branch[key];
var data = [];
for (var i = 0; i < bset.length; i++) {
data.push(this.pull[bset[i]]);
}
data.sort(sorter);
for (var _i = 0; _i < bset.length; _i++) {
data[_i] = data[_i].id;
}
this.branch[key] = data;
}
return order;
},
add: function (obj, index, pid) {
var refresh_parent = false;
var parent = this.getItem(pid || 0);
if (parent) {
//when adding items to leaf item - it need to be repainted
if (!this.branch[parent.id]) refresh_parent = true;
parent.$count++; //fix for the adding into dynamic loading branch
//dynamic branch has $count as -1
if (!parent.$count) parent.$count = 1;
}
this.branch[pid || 0] = this.order = _to_array(this.branch[pid || 0]);
obj.$count = obj.webix_kids ? -1 : 0;
obj.$level = parent ? parent.$level + 1 : 1;
obj.$parent = parent ? parent.id : 0;
if (this._filter_branch) {
//adding during filtering
var origin = this._filter_branch[pid || 0]; //newly created branch
if (!origin) origin = this._filter_branch[pid] = this.order; //branch can be shared bettwen collections, ignore such cases
if (this.order !== origin) {
//we can't know the location of new item in full dataset, making suggestion
//put at end by default
var original_index = origin.length; //put at start only if adding to the start and some data exists
if (!index && this.branch[pid || 0].length) original_index = 0;
origin = _to_array(origin);
obj.id = obj.id || uid();
origin.insertAt(obj.id, original_index);
}
} //call original adding logic
var result = DataStore.prototype.add.call(this, obj, index);
if (refresh_parent) this.refresh(pid);
return result;
},
_rec_remove: function (id) {
var obj = this.pull[id];
if (this.branch[obj.id] && this.branch[obj.id].length > 0) {
var branch = this.branch[id];
for (var i = 0; i < branch.length; i++) {
this._rec_remove(branch[i], true);
}
}
delete this.branch[id];
if (this._filter_branch) delete this._filter_branch[id];
delete this.pull[id];
if (this._marks[id]) delete this._marks[id];
},
_filter_removed: function (pull, parentId, id) {
var branch = pull[parentId];
if (branch.length == 1 && branch[0] == id && parentId) {
delete pull[parentId];
} else _to_array(branch).remove(id);
},
remove: function (id) {
//id can be an array of IDs - result of getSelect, for example
if (isArray(id)) {
for (var i = 0; i < id.length; i++) {
this.remove(id[i]);
}
return;
}
assert(this.exists(id), "Not existing ID in remove command" + id);
var obj = this.pull[id];
var parentId = obj.$parent || 0;
if (this.callEvent("onBeforeDelete", [id]) === false) return false;
this._rec_remove(id);
this.callEvent("onAfterDelete", [id]);
var parent = this.pull[parentId];
this._filter_removed(this.branch, parentId, id);
if (this._filter_branch) this._filter_removed(this._filter_branch, parentId, id);
var refresh_parent = 0;
if (parent) {
parent.$count--;
if (parent.$count <= 0) {
parent.$count = 0;
parent.open = 0;
refresh_parent = 1;
}
} //repaint signal
this.callEvent("onStoreUpdated", [id, obj, "delete"]);
if (refresh_parent) this.refresh(parent.id);
},
/*
serializes data to a json object
*/
getBranch: function (id) {
var out = [];
var items = (this._filter_branch || this.branch)[id];
if (items) for (var i = 0; i < items.length; i++) {
out[i] = this.pull[items[i]];
}
return out;
},
serialize: function (id, all) {
var coll = this.branch; //use original collection of branches
if (all && this._filter_branch) coll = this._filter_branch;
var ids = coll[id || 0];
var result = [];
for (var i = 0; i < ids.length; i++) {
var obj = this.pull[ids[i]];
var rel;
if (this._scheme_serialize) {
rel = this._scheme_serialize(obj);
if (rel === false) continue;
} else rel = copy(obj);
if (coll[obj.id]) rel.data = this.serialize(obj.id, all);
result.push(rel);
}
return result;
}
};
var TreeTablePaste = {
insert: function (data) {
var parent = this.getSelectedId(true, true);
for (var i = 0; i < data.length; i++) {
var item = {};
for (var j = 0; j < this._settings.columns.length; j++) {
item[this._settings.columns[j].id] = data[i][j] || "";
}
if (!isUndefined(item.id) && this.exists(item.id)) item.id = uid();
this.add(item, null, parent[0]);
}
}
};
var TreeType = {
space: function (obj) {
var html = "";
for (var i = 1; i < obj.$level; i++) {
html += "<div class='webix_tree_none'></div>";
}
return html;
},
icon: function (obj) {
if (obj.$count) {
if (obj.open) return "<div class='webix_tree_open'></div>";else return "<div class='webix_tree_close'></div>";
} else return "<div class='webix_tree_none'></div>";
},
checkbox: function (obj) {
if (obj.nocheckbox) return "";
return "<input type='checkbox' class='webix_tree_checkbox' " + (obj.checked ? "checked" : "") + (obj.disabled ? " disabled" : "") + ">";
},
folder: function (obj) {
if (obj.icon) return "<div class='webix_tree_file webix_tree_" + obj.icon + "'></div>";
if (obj.$count) {
if (obj.open) return "<div class='webix_tree_folder_open'></div>";else return "<div class='webix_tree_folder'></div>";
}
return "<div class='webix_tree_file'></div>";
}
};
var UploadDriver = {
$render: function () {
if (this._upload_area) {
//firstChild is webix_el_box container, which have relative position
//as result, file control is placed under the button and not in the top corner
this._contentobj.firstChild.appendChild(this._upload_area);
return;
}
this.files.attachEvent("onBeforeDelete", this._stop_file);
var input_config = {
"type": "file",
"class": "webix_hidden_upload",
tabindex: -1
};
if (this._settings.accept) input_config.accept = this._settings.accept;
if (this._settings.multiple) input_config.multiple = "true";
if (this._settings.directory) {
input_config.webkitdirectory = "true";
input_config.mozdirectory = "true";
input_config.directory = "true";
}
var f = create("input", input_config);
this._upload_area = this._contentobj.firstChild.appendChild(f);
_event(this._viewobj, "drop", bind(function (e) {
this.$drop(e);
preventEvent(e);
}, this));
_event(f, "change", bind(function () {
this._add_files(f.files);
if (env.isIE) {
var t = document.createElement("form");
t.appendChild(this._upload_area);
t.reset();
this._contentobj.firstChild.appendChild(f);
} else f.value = "";
}, this));
_event(this._viewobj, "click", bind(function () {
var now_date = new Date();
if (now_date - (this._upload_timer_click || 0) > 250) {
this.fileDialog();
}
}, this));
_event(this._viewobj, "dragenter", preventEvent);
_event(this._viewobj, "dragexit", preventEvent);
_event(this._viewobj, "dragover", preventEvent);
},
_directoryEntry: function (value) {
return value.isDirectory;
},
_directoryDrop: function (item, state, path) {
if (item.isFile) {
item.file(function (file) {
state.addFile(file, null, null, {
name: path + "/" + file.name
});
});
} else if (item.isDirectory) {
// Get folder contents
var dirReader = item.createReader();
dirReader.readEntries(function (entries) {
for (var i = 0; i < entries.length; i++) {
state._directoryDrop(entries[i], state, (path ? path + "/" : "") + item.name);
}
});
}
},
// adding files by drag-n-drop
$drop: function (e) {
var files = e.dataTransfer.files;
var items = e.dataTransfer.items; // non-file drop
if (!files.length) return;
if (this.callEvent("onBeforeFileDrop", [files, e])) {
items = items || files; //IE10+
for (var i = 0; i < items.length; i++) {
//https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/webkitGetAsEntry
var item = items[i];
if (item.webkitGetAsEntry) {
item = item.webkitGetAsEntry();
if (item.isDirectory) {
this._directoryDrop(item, this, "");
continue;
}
}
this.addFile(files[i]);
}
}
this.callEvent("onAfterFileDrop", [files, e]);
},
fileDialog: function (context) {
this._upload_timer_click = new Date();
this._last_file_context = context;
var inputs = this._viewobj.getElementsByTagName("INPUT");
inputs[inputs.length - 1].click();
},
send: function (id) {
//alternative syntx send(callback)
if (typeof id == "function") {
this._last_assigned_upload_callback = id;
id = 0;
}
if (!id) {
var order = this.files.data.order;
var complete = true;
if (order.length) for (var i = 0; i < order.length; i++) {
complete = !this.send(order[i]) && complete;
}
if (complete) this._upload_complete();
return;
}
var item = this.files.getItem(id);
if (item.status !== "client") return false;
assert(this._settings.upload, "You need to define upload url for uploader component");
item.status = "transfer";
var formData = new FormData();
formData.append(this.config.inputName, item.file, item.name);
formData.append(this.config.inputName + "_fullpath", item.name);
var headers = {};
var globalData = this._settings.formData || {};
if (typeof globalData === "function") globalData = globalData.call(this);
var details = exports.extend(item.formData || {}, globalData);
var xhr = new XMLHttpRequest();
var url = this._get_active_url(item);
if (callEvent("onBeforeAjax", ["POST", url, details, xhr, headers, formData])) {
for (var key in details) {
formData.append(key, details[key]);
}
item.xhr = xhr;
xhr.upload.addEventListener("progress", bind(function (e) {
this.$updateProgress(id, e.loaded / e.total * 100);
}, this), false);
xhr.onload = bind(function () {
if (!xhr.aborted) this._file_complete(id);
}, this);
xhr.open("POST", url, true);
for (var _key in headers) {
xhr.setRequestHeader(_key, headers[_key]);
}
xhr.send(formData);
}
this.$updateProgress(id, 0);
return true;
},
_file_complete: function (id) {
var item = this.files.getItem(id);
if (item) {
var response = null;
if (item.xhr.status < 400) {
var driver = DataDriver[this._settings.datatype || "json"];
response = driver.toObject(item.xhr.responseText);
if (response) response = driver.getDetails(response);
}
if (!response || response.status == "error") {
// file upload error
item.status = "error";
delete item.percent;
this.files.updateItem(id);
this.callEvent("onFileUploadError", [item, response]);
} else {
// file upload complete
assert(!response.status || response.status == "server", "Not supported status value, use 'error' or 'server'");
this._complete(id, response);
}
delete item.xhr;
}
},
stopUpload: function (id) {
bind(this._stop_file, this.files)(id);
},
_stop_file: function (id) {
var item = this.getItem(id);
if (typeof item.xhr !== "undefined") {
item.xhr.aborted = true;
item.xhr.abort();
delete item.xhr;
item.status = "client";
}
}
};
var ValidateCollection = {
_validate_init_once: function () {
this.data.attachEvent("onStoreUpdated", bind(function (id, data, mode) {
if (id && (mode == "add" || mode == "update" || mode == "save")) this.validate(id);
}, this));
this.data.attachEvent("onClearAll", bind(this.clearValidation, this));
this._validate_init_once = function () {};
},
rules_setter: function (value) {
if (value) {
this._validate_init_once();
}
return value;
},
clearValidation: function () {
this.data.clearMark("webix_invalid", true);
},
validate: function (id) {
var result = true;
if (!id) for (var key in this.data.pull) {
result = this.validate(key) && result;
} else {
this._validate_details = {};
var obj = this.getItem(id);
result = ValidateData.validate.call(this, null, obj);
if (result) {
if (this.callEvent("onValidationSuccess", [id, obj])) this._clear_invalid(id);
} else {
if (this.callEvent("onValidationError", [id, obj, this._validate_details])) this._mark_invalid(id, this._validate_details);
}
}
return result;
},
_validate: function (rule, data, obj, key) {
if (typeof rule == "string") rule = rules[rule];
var res = rule.call(this, data, obj, key);
if (!res) {
this._validate_details[key] = true;
}
return res;
},
_clear_invalid: function (id) {
this.data.removeMark(id, "webix_invalid", true);
},
_mark_invalid: function (id) {
this.data.addMark(id, "webix_invalid", true);
}
};
var Values = {
$init: function () {
this.elements = {};
},
focus: function (name) {
if (name) {
assert(this.elements[name], "unknown input name: " + name);
this._focus(this.elements[name]);
} else {
for (var n in this.elements) {
if (this._focus(this.elements[n]) !== false) return true;
}
}
return false;
},
_focus: function (target) {
if (target && target.focus) {
return target.focus();
}
return false;
},
setValues: function (data, update, config) {
var _this = this;
if (this._settings.complexData) data = CodeParser.collapseNames(data, "", {}, function (v) {
return !_this.elements[v];
});
this._inner_setValues(data, update, config);
},
_inner_setValues: function (data, update, config) {
this._is_form_dirty = update; //prevent onChange calls from separate controls
this.blockEvent();
if (!update || !this._values) this._values = {};
for (var name in data) {
if (!this.elements[name]) this._values[name] = data[name];
}
for (var _name in this.elements) {
var input = this.elements[_name];
if (input) {
if (!isUndefined(data[_name])) input.setValue(data[_name], config);else if (!update && input.$allowsClear) input.setValue("", config);
this._values[_name] = input.getValue();
}
}
this.unblockEvent();
this.callEvent("onValues", []);
},
isDirty: function () {
return !!this._is_form_dirty || this.getDirtyValues(true) === true;
},
setDirty: function (flag) {
this._is_form_dirty = flag;
if (!flag) this._values = this._inner_getValues();
},
getDirtyValues: function () {
var result = {};
if (this._values) {
for (var name in this.elements) {
var view = this.elements[name];
var value = view.getValue();
var defaultValue = this._values[name];
var isDirty = view.$compareValue ? !view.$compareValue(defaultValue, value) : defaultValue != value;
if (isDirty) {
result[name] = value;
if (arguments[0]) return true;
}
}
}
return result;
},
getCleanValues: function () {
return this._values;
},
getValues: function (filter) {
var data = this._inner_getValues(filter);
if (this._settings.complexData) data = CodeParser.expandNames(data);
return data;
},
_inner_getValues: function (filter) {
//get original data
var success,
elem = null,
data = this._values ? copy(this._values) : {}; //update properties from linked controls
for (var name in this.elements) {
elem = this.elements[name];
success = true;
if (filter) {
if (_typeof(filter) == "object") {
if (filter.hidden === false) success = elem.isVisible();
if (success && filter.disabled === false) success = elem.isEnabled();
} else success = filter.call(this, elem);
}
if (success) data[name] = elem.getValue();else delete data[name]; //in case of this._values[name]
}
return data;
},
clear: function (config) {
this._is_form_dirty = false;
var data = {};
for (var name in this.elements) {
if (this.elements[name].$allowsClear) data[name] = "";
}
this._inner_setValues(data, false, config);
},
markInvalid: function (name, state) {
// remove 'invalid' mark
if (state === false) {
this._clear_invalid(name);
} // add 'invalid' mark
else {
// set invalidMessage
if (typeof state == "string") {
var input = this.elements[name];
if (input) input._settings.invalidMessage = state;
} //add mark to current validation process
if (this._validate_details) this._validate_details[name] = true;
this._mark_invalid(name);
}
},
_mark_invalid: function (id) {
var input = this.elements[id];
if (id && input) {
this._clear_invalid(id, true);
addCss(input._viewobj, "webix_invalid");
input._settings.invalid = true;
var message = input._settings.invalidMessage;
if (typeof message === "string" && input.setBottomText) input.setBottomText();
}
},
_clear_invalid: function (id, silent) {
var input = this.elements[id];
if (id && input && input.$view && input._settings.invalid) {
removeCss(input._viewobj, "webix_invalid");
input._settings.invalid = false;
var message = input._settings.invalidMessage;
if (typeof message === "string" && !silent && input.setBottomText) input.setBottomText();
}
}
};
/*
Renders collection of items
Always shows y-scroll
Can be used with huge datasets
@export
show
render
*/
var VirtualRenderStack = {
$init: function () {
assert(this.render, "VirtualRenderStack :: Object must use RenderStack first");
this._htmlmap = {}; //init map of rendered elements
//we need to repaint area each time when view resized or scrolling state is changed
_event(this._viewobj, "scroll", bind(this._render_visible_rows, this)); //here we store IDs of elemenst which doesn't loadede yet, but need to be rendered
this._unrendered_area = [];
},
//return html object by item's ID. Can return null for not-rendering element
getItemNode: function (search_id) {
//collection was filled in _render_visible_rows
return this._htmlmap[search_id];
},
//adjust scrolls to make item visible
showItem: function (id) {
var range = this._getVisibleRange();
var ind = this.data.getIndexById(id); //we can't use DOM method for not-rendered-yet items, so fallback to pure math
var dy = Math.floor(ind / range._dx) * range._y;
var state = this.getScrollState();
if (dy < state.y || dy + this._settings.height >= state.y + this._content_height) this.scrollTo(0, dy);
},
//repain self after changes in DOM
//for add, delete, move operations - render is delayed, to minify performance impact
render: function (id, data, type) {
if (!this.isVisible(this._settings.id) || this.$blockRender) return;
if (id) {
var cont = this.getItemNode(id); //old html element
switch (type) {
case "update":
if (!cont) return; //replace old with new
var t = this._htmlmap[id] = this._toHTMLObject(data);
insertBefore(t, cont);
remove(cont);
break;
default:
// "move", "add", "delete"
/*
for all above operations, full repainting is necessary
but from practical point of view, we need only one repainting per thread
code below initiates double-thread-rendering trick
*/
this._render_delayed();
break;
}
} else {
//full repainting
if (this.callEvent("onBeforeRender", [this.data])) {
this._htmlmap = {}; //nulify links to already rendered elements
this._render_visible_rows(null, true); // clear delayed-rendering, because we already have repaint view
this._wait_for_render = false;
this.callEvent("onAfterRender", []);
}
}
},
//implement double-thread-rendering pattern
_render_delayed: function () {
//this flag can be reset from outside, to prevent actual rendering
if (this._wait_for_render) return;
this._wait_for_render = true;
window.setTimeout(bind(function () {
this.render();
}, this), 1);
},
//create empty placeholders, which will take space before rendering
_create_placeholder: function (height) {
if (env.maxHTMLElementSize) height = Math.min(env.maxHTMLElementSize, height);
var node = document.createElement("DIV");
node.style.cssText = "height:" + height + "px; width:100%; overflow:hidden;";
return node;
},
/*
Methods get coordinatest of visible area and checks that all related items are rendered
If, during rendering, some not-loaded items was detected - extra data loading is initiated.
reset - flag, which forces clearing of previously rendered elements
*/
_render_visible_rows: function (e, reset) {
this._unrendered_area = []; //clear results of previous calls
var viewport = this._getVisibleRange(); //details of visible view
if (!this._dataobj.firstChild || reset) {
//create initial placeholder - for all view space
this._dataobj.innerHTML = "";
this._dataobj.appendChild(this._create_placeholder(viewport._max)); //register placeholder in collection
this._htmlrows = [this._dataobj.firstChild];
}
/*
virtual rendering breaks all view on rows, because we know widht of item
we can calculate how much items can be placed on single row, and knowledge
of that, allows to calculate count of such rows
each time after scrolling, code iterate through visible rows and render items
in them, if they are not rendered yet
both rendered rows and placeholders are registered in _htmlrows collection
*/
//position of first visible row
var t = viewport._from;
while (t <= viewport._height) {
//loop for all visible rows
//skip already rendered rows
while (this._htmlrows[t] && this._htmlrows[t]._filled && t <= viewport._height) {
t++;
} //go out if all is rendered
if (t > viewport._height) break; //locate nearest placeholder
var holder = t;
while (!this._htmlrows[holder]) {
holder--;
}
var holder_row = this._htmlrows[holder]; //render elements in the row
var base = t * viewport._dx + (this.data.$min || 0); //index of rendered item
if (base > (this.data.$max || Infinity)) break; //check that row is in virtual bounds, defined by paging
var nextpoint = Math.min(base + viewport._dx - 1, this.data.$max ? this.data.$max - 1 : Infinity);
var node = this._create_placeholder(viewport._y); //all items in rendered row
var range = this.data.getIndexRange(base, nextpoint);
if (!range.length) break;
var loading = {
$template: "Loading"
};
for (var i = 0; i < range.length; i++) {
if (!range[i]) this._unrendered_area.push(base + i);
range[i] = this._toHTML(range[i] || loading);
}
node.innerHTML = range.join(""); //actual rendering
for (var _i = 0; _i < range.length; _i++) {
//register all new elements for later usage in getItemNode
this._htmlmap[this.data.getIdByIndex(base + _i)] = node.childNodes[_i];
} //correct placeholders
var h = parseFloat(holder_row.style.height, 10);
var delta = (t - holder) * viewport._y;
var delta2 = h - delta - viewport._y; //add new row to the DOOM
insertBefore(node, delta ? holder_row.nextSibling : holder_row, this._dataobj);
this._htmlrows[t] = node;
node._filled = true;
/*
if new row is at start of placeholder - decrease placeholder's height
else if new row takes whole placeholder - remove placeholder from DOM
else
we are inserting row in the middle of existing placeholder
decrease height of existing one, and add one more,
before the newly added row
*/
if (delta <= 0 && delta2 > 0) {
holder_row.style.height = delta2 + "px";
this._htmlrows[t + 1] = holder_row;
} else {
if (delta < 0) remove(holder_row);else holder_row.style.height = delta + "px";
if (delta2 > 0) {
var new_space = this._htmlrows[t + 1] = this._create_placeholder(delta2);
insertBefore(new_space, node.nextSibling, this._dataobj);
}
}
t++;
} //when all done, check for non-loaded items
if (this._unrendered_area.length) {
//we have some data to load
//detect borders
var from = this._unrendered_area[0];
var to = this._unrendered_area.pop() + 1;
if (to > from) {
//initiate data loading
var count = to - from;
if (this._maybe_loading_already(count, from)) return;
count = Math.max(count, this._settings.datafetch || this._settings.loadahead || 0);
this.loadNext(count, from);
}
}
},
//calculates visible view
_getVisibleRange: function () {
var state = this.getScrollState();
var top = Math.max(0, state.y);
var tpadding = this._tilesPadding || 0;
var width = this._content_width - tpadding;
var height = this._content_height - tpadding / 2; //size of single item
var t = this.type;
var dx = Math.floor(width / t.width) || 1; //at least single item per row
var min = Math.floor(top / t.height); //index of first visible row
var dy = Math.ceil((height + top) / t.height) - 1; //index of last visible row
//total count of items, paging can affect this math
var count = this.data.$max ? this.data.$max - this.data.$min : this.data.count();
var max = Math.ceil(count / dx) * t.height; //size of view in rows
return {
_from: min,
_height: dy,
_top: top,
_max: max,
_y: t.height,
_dx: dx
};
},
_cellPosition: function (id) {
var html = this.getItemNode(id);
if (!html) {
this.showItem(id);
this._render_visible_rows();
html = this.getItemNode(id);
}
return {
left: html.offsetLeft,
top: html.offsetTop,
height: html.offsetHeight,
width: html.offsetWidth,
parent: this._contentobj
};
}
};
/*
Renders collection of items on demand
*/
var VRenderStack = {
$init: function () {
this._htmlmap = {};
_event(this._viewobj, "scroll", bind(function () {
this.render(null, null, "paint");
}, this));
},
_sync_scroll: function (x, y, t) {
if (this._settings.footer) Touch._set_matrix(this._footer.childNodes[1].firstChild, x, 0, t);
this.callEvent("onSyncScroll", [x, y, t]);
},
//return html container by its ID
//can return undefined if container doesn't exists
getItemNode: function (search_id) {
return this._htmlmap && this._htmlmap[search_id];
},
/*change scrolling state of top level container, so related item will be in visible part*/
showItem: function (id) {
var index$$1 = this.data.getIndexById(id);
if (index$$1 > -1) {
var top = index$$1 * this.type.height;
var bottom = top + this.type.height;
var scroll = this.getScrollState();
var box = offset(this.$view);
if (top < scroll.y) this.scrollTo(0, top);else if (bottom > scroll.y + box.height) this.scrollTo(0, bottom - box.height);
}
},
//update view after data update
//when called without parameters - all view refreshed
render: function (id, data, type) {
if (!this.isVisible(this._settings.id) || this.$blockRender) return;
var parent = this._renderobj || this._dataobj;
if (id) {
if (type == "paint" || type == "update") {
var cont = this.getItemNode(id); //get html element of updated item
if (cont) {
var t = this._htmlmap[id] = this._toHTMLObject(data);
t.style.top = cont.style.top;
t.style.position = "absolute";
t.style.left = 0;
t.style.width = "100%";
insertBefore(t, cont);
remove(cont);
return;
} //updating not rendered yet item
return;
}
}
var isDrag,
source,
marked = this._marked_item_id;
if (DragControl.active && type != "drag-end") {
var context = DragControl.getContext();
isDrag = this._init_drop_area && context.from === this; //move and order modes
source = isDrag && _to_array(copy(context.source || []));
}
if (type != "paint" || isDrag) {
//repaint all
this._htmlmap = {};
parent.innerHTML = "";
} //full reset
if (this.callEvent("onBeforeRender", [this.data])) {
var count = this.data.count();
var scroll = this.getScrollState();
var box = offset(this._viewobj);
var top = Math.floor(scroll.y / this.type.height) - 2;
var bottom = Math.ceil((scroll.y + box.height) / this.type.height) + 2;
top = Math.max(0, top);
bottom = Math.min(count - 1, bottom + (isDrag ? source.length - 1 : 0));
var html = [];
for (var i = top; i <= bottom; i++) {
var sid = this.data.order[i];
if (isDrag && source.find(sid) !== -1) {
if (sid == marked) marked = this.data.order[i + 1];
continue;
} else if (!this._htmlmap[sid]) {
var item = this.data.getItem(sid);
if (!item) {
this._run_load_next({
count: bottom - i + (this._settings.loadahead || 0),
start: i
});
break;
}
html.push(this._toHTML(item));
} else {
html.push("<div webix_skip=\"true\" ".concat(this._id, "=\"").concat(sid, "\"></div>"));
}
}
this._html.innerHTML = html.join("");
if (this._init_drop_area && type == "drag-in") {
// can be external
var node = this._html.querySelector("[".concat(this._id, "=\"").concat(marked, "\"]"));
if (node) {
this._html.insertBefore(DragControl._dropHTML[0], node);
} else this._html.appendChild(DragControl._dropHTML[0]);
}
parent.style.position = "relative";
parent.style.height = count * this.type.height + "px";
var kids = this._html.childNodes;
for (var _i = kids.length - 1; _i >= 0; _i--) {
var child = kids[_i];
if (child.getAttribute("webix_skip")) continue;
var cid = child.getAttribute(this._id);
if (cid) {
child.style.position = "absolute";
child.style.top = (top + _i) * this.type.height + "px";
child.style.left = 0;
child.style.width = "100%";
parent.appendChild(child);
this._htmlmap[cid] = child;
}
}
this.callEvent("onAfterRender", []);
}
},
$setSize: function () {
if (base$1.api.$setSize.apply(this, arguments)) {
this.render(null, null, "paint");
}
},
_run_load_next: function (conf) {
var count = Math.max(conf.count, this._settings.datafetch || this._settings.loadahead || 0);
if (this._maybe_loading_already(conf.count, conf.start)) return;
this.loadNext(count, conf.start);
},
_set_drop_area: function () {
this.render(null, null, "drag-in");
},
_remove_drop_area: function () {
remove(DragControl._dropHTML);
this.render(null, null, "drag-out");
},
$dragDestroy: function () {
if (this._init_drop_area) {
var context = DragControl._drag_context;
if (isArray(context.source)) this._remove_css(context.source, "webix_invisible");
this.render(null, null, "drag-end");
}
remove(DragControl._html);
}
};
var version$1 = "9.0.0";
var name$1 = "core";
var errorMessage = "non-existing view for export";
function getDataHelper(key, column, raw) {
if (!raw && column.format) return function (obj) {
return column.format(obj[key]);
};
return function (obj) {
return obj[key];
};
}
function getHeaderText(view, header) {
var text = header.text;
if (header.contentId) {
var content = view.getHeaderContent(header.contentId);
if (content && !content.type.$icon) text = content.getValue(true);
}
return (text || "").toString().replace(/<[^>]*>/gi, "");
}
function getStyles(r, c, styles) {
//row index, column index, styles array
if (styles[r] && styles[r][c]) return styles[r][c];
return {};
}
function getExportScheme(view, options) {
var scheme = [];
var h_count = 0,
f_count = 0;
var isTable = view.getColumnConfig;
var columns = options.columns;
var raw = !!options.rawValues;
var isTree = view.data.name == "TreeStore";
var treeLines = options.treeLines;
if (treeLines === true || isUndefined(treeLines)) treeLines = "value";
scheme.heights = {};
if (options.hidden || options.hide) {
scheme.hiddenCols = {};
scheme.hiddenRows = {};
}
if (!columns) {
columns = [];
if (isTable) {
var order = view._hidden_column_order;
if (options.hidden && order.length) {
for (var i = 0; i < order.length; i++) {
var col = view.getColumnConfig(order[i]);
if (!view.isColumnVisible(col.id)) scheme.hiddenCols[col.id] = 1;
columns.push(col);
}
} else columns = columns.concat(view._columns);
} else {
var obj = view.data.pull[view.data.order[0]];
for (var key in obj) {
if (key !== "id" && key[0] != "$") columns.push({
id: key,
isTree: isTree && key === treeLines
});
}
}
} else if (!columns.length) {
//export options are set as - columns:{ rank:true, title:{ header:"custom"}}
var arr = [];
for (var _key in columns) {
arr.push(exports.extend({
id: _key
}, exports.extend({}, columns[_key])));
}
columns = arr;
}
if (options.ignore) for (var _i = columns.length - 1; _i >= 0; _i--) {
if (options.ignore[columns[_i].id]) columns.splice(_i, 1);
}
if (options.id) scheme.push({
id: "id",
width: 50,
header: " ",
template: function (obj) {
return obj.id;
}
});
if (options.flatTree) {
(function () {
var flatKey = options.flatTree.id;
var copy$$1 = [].concat(options.flatTree.columns);
var fill = [];
var fillMode = !!options.flatTree.fill;
for (var _i2 = 1; _i2 <= copy$$1.length; _i2++) {
copy$$1[_i2 - 1].template = function (i) {
return function (obj) {
return obj.$level == i ? fill[i] = obj[flatKey] : fillMode && i < obj.$level ? fill[i] : "";
};
}(_i2);
}
var index = 0;
for (var _i3 = columns.length - 1; _i3 >= 0; _i3--) {
if (columns[_i3].id === flatKey) index = _i3;
}
columns = [].concat(columns.slice(0, index)).concat(copy$$1).concat(columns.slice(index + 1));
})();
}
var treeColumn;
for (var j = 0; j < columns.length; j++) {
var column = columns[j];
var _key2 = column.id;
if (column.noExport) continue; // raw mode has sense only for datatable
// in other cases we don't have built-in data templates
var rawColumn = raw && isTable;
if (isTable) {
var sourceColumn = view.getColumnConfig(_key2); // when these's no column to take raw data from, or custom template defined - ignore raw mode
if (column.template && (!sourceColumn || sourceColumn.template != column.template)) rawColumn = false;
if (sourceColumn) column = exports.extend(exports.extend({}, column), sourceColumn);
}
var record = {
id: column.id,
template: rawColumn || !column.template ? getDataHelper(_key2, column, raw) : column.template,
width: (column.width || 200) * (options.export_mode === "excel" ? 8.43 / 70 : 1),
header: column.header !== false ? column.header || _key2 : ""
};
if (isTree && _key2 === treeLines) record.isTree = treeColumn = true;
if (options.export_mode === "excel") {
exports.extend(record, {
type: column.exportType || "",
format: column.exportFormat || ""
});
if (column.hidden) {
if (!scheme.hiddenCols) scheme.hiddenCols = {};
scheme.hiddenCols[column.id] = 1;
}
}
if (typeof record.header === "string") record.header = [{
text: record.header
}];else record.header = [].concat(record.header);
for (var _i4 = 0; _i4 < record.header.length; _i4++) {
record.header[_i4] = record.header[_i4] ? getHeaderText(view, record.header[_i4]) : "";
}
h_count = Math.max(h_count, record.header.length);
if (view.config.footer) {
var footer = column.footer || "";
if (typeof footer == "string") footer = [{
text: footer
}];else footer = [].concat(footer);
for (var _i5 = 0; _i5 < footer.length; _i5++) {
footer[_i5] = footer[_i5] ? getHeaderText(view, footer[_i5]) : "";
}
record.footer = footer;
f_count = Math.max(f_count, record.footer.length);
}
scheme.push(record);
}
if (!treeColumn && isTree && options.treeLines != treeLines && scheme[0]) scheme[0].isTree = true;
for (var _i6 = 0; _i6 < scheme.length; _i6++) {
var diff = h_count - scheme[_i6].header.length;
for (var d = 0; d < diff; d++) {
scheme[_i6].header.push("");
}
if (view.config.footer) {
diff = f_count - scheme[_i6].footer.length;
for (var _d = 0; _d < diff; _d++) {
scheme[_i6].footer.push("");
}
}
}
return scheme;
}
function getFileName(name, extension) {
if (name) name = name.replace(/[/?\\<>:*|"]/g, "").substring(0, 150);
return "".concat(name || "Data", ".").concat(extension);
}
function getExportData(view, options, scheme) {
var filterHTML = !!options.filterHTML;
var htmlFilter = /<[^>]*>/gi;
var data = [];
var header, headers;
var mode = options.export_mode;
if ((mode === "excel" || mode == "csv") && options.docHeader) {
data = [[(options.docHeader.text || options.docHeader).toString()], [""]];
if (mode === "excel" && options.docHeader.height) scheme.heights[0] = options.docHeader.height;
}
if (options.header !== false && scheme.length) {
for (var h = 0; h < scheme[0].header.length; h++) {
headers = [];
for (var i = 0; i < scheme.length; i++) {
header = "";
if (scheme[i].header[h]) {
header = scheme[i].header[h];
if (filterHTML) header = scheme[i].header[h] = header.replace(htmlFilter, "");
}
headers.push(header);
}
if (mode == "excel" && view._columns && options.heights !== false && (view._headers[h] !== $active.barHeight || options.heights == "all")) scheme.heights[data.length] = view._headers[h];
if (mode !== "pdf") data[data.length] = headers;
}
}
options.yCorrection = (options.yCorrection || 0) - data.length;
var treeline = options.flatTree || options.plainOutput ? "" : "-";
view.data.each(function (item, index) {
if (!options.filter || options.filter(item)) {
var reallyHidden = options.hidden && view.data._filter_order && view.getIndexById(item.id) == -1;
if (options.hide && options.hide(item) || reallyHidden) {
var _header = (options.docHeader ? 2 : 0) + (options.header === false ? 0 : scheme[0].header.length);
scheme.hiddenRows[_header + index] = 1;
}
if (this.data._scheme_export) {
item = view.data._scheme_export(item);
}
var line = [];
for (var _i7 = 0; _i7 < scheme.length; _i7++) {
var column = scheme[_i7],
cell = null; //spreadsheet use muon to store data, get value via $getExportValue
if (view.$getExportValue) cell = view.$getExportValue(item.id, column.id, options); //datatable math
else if (options.math && item["$" + column.id] && item["$" + column.id].charAt(0) == "=") cell = item["$" + column.id];
if (this._spans_pull) {
var span = this.getSpan(item.id, column.id);
if (span && span[4] && span[0] == item.id && span[1] == column.id) {
cell = span[4];
if (filterHTML && typeof cell === "string") cell = cell.replace(htmlFilter, "");
}
}
if (!cell) {
cell = column.template(item, view.type, item[column.id], column, _i7);
if (!cell && cell !== 0) cell = "";
if (column.isTree && treeline) cell = " " + Array(item.$level).join(treeline) + " " + cell;
if (filterHTML && typeof cell === "string") {
cell = cell.replace(htmlFilter, "");
} //remove end/start spaces(ex.hierarchy data)
if (typeof cell === "string" && mode === "csv") cell = cell.trim(); //for multiline data
if (typeof cell === "string" && (mode === "excel" || mode === "csv")) {
cell = cell.replace(/<br\s*\/?>/mg, "\n");
}
}
line.push(cell);
}
if (mode == "excel" && view._columns && options.heights !== false && (item.$height && item.$height !== $active.rowHeight || options.heights == "all")) scheme.heights[data.length] = item.$height || this.config.rowHeight;
data.push(line);
}
}, view, options.hidden);
if (options.footer !== false) {
var f_count = scheme[0].footer ? scheme[0].footer.length : 0;
for (var f = 0; f < f_count; f++) {
var footers = [];
for (var _i8 = 0; _i8 < scheme.length; _i8++) {
var footer = scheme[_i8].footer[f];
if (filterHTML) footer = scheme[_i8].footer[f] = footer.toString().replace(htmlFilter, "");
footers.push(footer);
}
if (mode == "excel" && view._columns && options.heights !== false && (view._footers[f] !== $active.barHeight || options.heights == "all")) scheme.heights[data.length] = view._footers[f];
if (mode !== "pdf") data.push(footers);
}
}
if (mode === "excel" && options.docFooter) {
data = data.concat([[], [(options.docFooter.text || options.docFooter).toString()]]);
if (options.docFooter.height) scheme.heights[data.length - 1] = options.docFooter.height;
}
return data;
}
var toPNG = function (id, options) {
var defer = Deferred.defer();
return require(env.cdn + "/extras/html2canvas-1.0.min.js").then(function () {
//backward compatibility
if (typeof options === "string") options = {
filename: options
};
options = options || {};
options.export_mode = "png";
var view = $$(id);
if (view && view.$exportView) view = view.$exportView(options);
assert(view, errorMessage);
if (!view) return defer.reject(errorMessage);
var node = view ? view.$view : toNode(id);
var filename = getFileName(options.filename, "png");
window.html2canvas(node, {
background: "#fff",
logging: false,
useCORS: true
}).then(function (canvas) {
var callback = function (data) {
if (options.download !== false) download(data, filename);
defer.resolve(data);
};
if (canvas.msToBlob) callback(canvas.msToBlob());else canvas.toBlob(callback, "image/png");
});
return defer;
});
};
var toCSV = function (id, options) {
options = options || {};
var view = $$(id);
if (view && view.$exportView) view = view.$exportView(options);
assert(view, errorMessage);
if (!view) return Deferred.reject(errorMessage);
options.export_mode = "csv";
options.filterHTML = true;
var scheme = getExportScheme(view, options);
var result = getExportData(view, options, scheme);
var data = getCsvData(result, scheme);
var filename = getFileName(options.filename, "csv");
var blob = new Blob(["\uFEFF" + data], {
type: "text/csv"
});
if (options.download !== false) download(blob, filename);
return Deferred.resolve(blob);
};
function getCsvData(data) {
return csv$1.stringify(data);
}
var font = {};
var toPDF = function (id, options) {
options = options || {};
options.export_mode = "pdf";
options.fontName = options.fontName || "pt-sans.regular";
options.boldFontName = options.boldFontName || "pt-sans.bold";
id = isArray(id) ? id : [id];
var views = [];
for (var i = 0; i < id.length; i++) {
if (!id[i].id) id[i] = {
id: id[i]
};
var view = $$(id[i].id);
if (view) {
var viewOptions = exports.extend(id[i].options || {}, options);
var display = viewOptions.display || "table";
if (viewOptions.display == "image") delete viewOptions.styles;
if (view.$exportView) view = view.$exportView(viewOptions); //$exportView returns array
if (isArray(view)) {
views = views.concat(view);
if (options.autowidth) getAutowidth(viewOptions, options);
} else {
//display table should be first (in case of styles:true $exportView adds styles to the first view)
if (display == "table" || display == "all") {
if (view.data && view.data.pull) {
var scheme = getExportScheme(view, viewOptions);
views.push({
scheme: scheme,
exportData: getExportData(view, viewOptions, scheme),
viewOptions: viewOptions
});
if (options.autowidth) getAutowidth(view, options, scheme);
}
}
if (display == "image" || display == "all") {
var node = viewOptions._hidden ? cloneNodeWithStyles(view.$view) : view.$view;
views.push({
node: node,
viewOptions: viewOptions
});
if (options.autowidth) getAutowidth(view, options);
}
}
}
assert(view, errorMessage);
}
if (options.dataOnly) return views;
return require([env.cdn + "/extras/pdfjs.js", env.cdn + "/extras/html2canvas-1.0.min.js"]).then(function () {
if (views.length == 0) return Deferred.reject(errorMessage);
if (font[options.fontName] && font[options.boldFontName]) {
options._export_font = font[options.fontName];
options._export_font_bold = font[options.boldFontName];
return getPdfData(views, options).then(function (pdf) {
return getBlob(pdf, options);
});
} else {
var defer = Deferred.defer();
/* global pdfjs */
pdfjs.load(options.fontURL || env.cdn + "/extras/" + options.fontName + ".ttf", function (err, regular) {
if (err) return defer.reject(err);
pdfjs.load(options.boldFontURL || env.cdn + "/extras/" + options.boldFontName + ".ttf", function (err, bold) {
options._export_font = font[options.fontName] = new pdfjs.TTFFont(regular);
options._export_font_bold = font[options.boldFontName] = err ? null : new pdfjs.TTFFont(bold);
defer.resolve(getPdfData(views, options).then(function (pdf) {
return getBlob(pdf, options);
}));
});
});
return defer;
}
});
};
function getBlob(pdf, options) {
var filename = getFileName(options.filename, "pdf");
var blob = new Blob([pdf.toString()], {
type: "application/pdf"
});
if (options.download !== false) download(blob, filename);
return blob;
}
function getPdfData(views, options) {
var doc = addPDFDoc(options);
var promises = [];
for (var i = 0; i < views.length; i++) {
if (views[i].node) promises.push(getPDFImage(views[i].node));else promises.push(Deferred.resolve());
}
return Deferred.all(promises).then(function (images) {
for (var _i = 0; _i < promises.length; _i++) {
var viewOptions = views[_i].viewOptions;
if (viewOptions.textBefore) addText(doc, "before", viewOptions.textBefore);
if (images[_i]) doc.image(images[_i], {
align: "center"
});else {
viewOptions._export_font_bold = options._export_font_bold;
addPDFTable(views[_i], doc);
}
if (viewOptions.textAfter) addText(doc, "after", viewOptions.textAfter);
if (_i != views.length - 1) doc.pageBreak();
}
return addPDFHeader(doc, options);
});
}
function addText(doc, type, text) {
if (type == "after") doc.text().br();
if (typeof text == "string") text = {
text: text
};
doc.text(text.text, text.options || {});
if (type == "before") doc.text().br();
}
function getPDFImage(node) {
var hidden = !document.body.contains(node);
if (hidden) {
//node is a cloneNode of the real view, so it shouldn't be visible
document.body.appendChild(node);
node.style.position = "absolute";
node.style.left = "-9999px";
}
return window.html2canvas(node, {
background: "#fff",
logging: false,
useCORS: true
}).then(function (canvas) {
var image = canvas.toDataURL("image/jpeg");
var binary_string = window.atob(image.split("base64,")[1]);
var length = binary_string.length;
var bytes = new Uint8Array(length);
for (var i = 0; i < length; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return new pdfjs.Image(bytes.buffer);
}).finally(function () {
if (hidden) document.body.removeChild(node);
});
}
function getAutowidth(view, options, scheme) {
var prop = options.orientation && options.orientation == "landscape" ? "height" : "width";
var width;
if (scheme) {
width = 80; //paddings
for (var i = 0; i < scheme.length; i++) {
width += scheme[i].width;
}
} else if (view.$width) width = view.$width;else //'view' can be local settings and we need to compare them with common ones
width = view[prop];
options[prop] = Math.max(options[prop] || 0, width || 0);
}
function addPDFDoc(options) {
var width = options.width || 595.296,
height = options.height || 841.896; // default A4 size
if (options.orientation && options.orientation === "landscape") height = [width, width = height][0];
return new pdfjs.Document({
padding: 40,
font: options._export_font,
threshold: 256,
width: width,
height: height
});
}
function addPDFTable(view, doc) {
var scheme = view.scheme;
var data = view.exportData;
var options = view.viewOptions;
var styles = view.styles;
options.header = isUndefined(options.header) || options.header === true ? {} : options.header;
options.footer = isUndefined(options.footer) || options.footer === true ? {} : options.footer;
options.table = options.table || {}; //render table
var h_count = options.header === false ? 0 : scheme[0].header.length;
var f_count = options.footer === false || !scheme[0].footer ? 0 : scheme[0].footer.length;
var colWidths = [];
for (var i = 0; i < scheme.length; i++) {
colWidths[i] = scheme[i].width;
}
var tableOps = exports.extend(options.table, {
borderWidth: 1,
height: 20,
lineHeight: 1.1,
borderColor: 0xEEEEEE,
backgroundColor: 0xFFFFFF,
color: 0x666666,
textAlign: "left",
paddingRight: 10,
paddingLeft: 10,
headerRows: h_count,
widths: colWidths.length ? colWidths : ["100%"]
});
var table = doc.table(tableOps);
var boldFont = options._export_font_bold; //render table header
if (h_count) {
var headerOps = exports.extend(options.header, {
borderRightColor: 0xB0CEE3,
borderBottomColor: 0xB0CEE3,
color: 0x4A4A4A,
backgroundColor: 0xD2E3EF,
height: 27,
lineHeight: 1.2
});
for (var _i2 = 0; _i2 < h_count; _i2++) {
var header = table.tr(headerOps);
for (var s = 0; s < scheme.length; s++) {
var cellStyle = styles ? getStyles(_i2, s, styles) : {};
if (boldFont && cellStyle.bold) cellStyle.font = boldFont;
header.td(scheme[s].header[_i2].toString(), cellStyle);
}
}
} //render table data
for (var r = 0; r < data.length; r++) {
var row = table.tr({});
for (var c = 0; c < data[r].length; c++) {
var _cellStyle = styles ? getStyles(r + h_count, c, styles) : {};
if (boldFont && _cellStyle.bold) _cellStyle.font = boldFont;
row.td(data[r][c], _cellStyle);
}
} //render table footer
if (f_count) {
var footerOps = exports.extend(options.footer, {
borderRightColor: 0xEEEEEE,
borderBottomColor: 0xEEEEEE,
backgroundColor: 0xFAFAFA,
color: 0x666666,
height: 27,
lineHeight: 1.2
});
for (var _i3 = 0; _i3 < f_count; _i3++) {
var beforeCount = h_count + data.length;
var footer = table.tr(footerOps);
for (var _s = 0; _s < scheme.length; _s++) {
var _cellStyle2 = styles ? getStyles(_i3 + beforeCount, _s, styles) : {};
if (boldFont && _cellStyle2.bold) _cellStyle2.font = boldFont;
footer.td(scheme[_s].footer[_i3].toString(), _cellStyle2);
}
}
}
}
function addPDFHeader(doc, options) {
//doc footer
if (options.docFooter !== false) {
var ft = doc.footer();
ft.text({
color: 0x666666,
textAlign: "center"
}).append(i18n.dataExport.page || "Page").pageNumber().append(" " + (i18n.dataExport.of || "of") + " ").pageCount();
}
var horder = {
text: 0,
image: 1
}; //doc header, configurable
if (options.docHeader) {
if (typeof options.docHeader == "string") options.docHeader = {
text: options.docHeader
};
exports.extend(options.docHeader, {
color: 0x666666,
textAlign: "right",
order: 0
});
horder.text = options.docHeader.order;
}
if (options.docHeaderImage) {
if (typeof options.docHeaderImage == "string") options.docHeaderImage = {
url: options.docHeaderImage
};
exports.extend(options.docHeaderImage, {
align: "right",
order: 1
});
horder.image = options.docHeaderImage.order;
}
if (options.docHeader && horder.image > horder.text) doc.header({
paddingBottom: 10
}).text(options.docHeader.text, options.docHeader);
if (options.docHeaderImage) {
var defer = Deferred.defer();
pdfjs.load(options.docHeaderImage.url, function (err, buffer) {
if (!err) {
var img = new pdfjs.Image(buffer);
doc.header({
paddingBottom: 10
}).image(img, options.docHeaderImage);
if (options.docHeader && horder.image < horder.text) doc.header({
paddingBottom: 10
}).text(options.docHeader.text, options.docHeader);
} //render pdf and show in browser
defer.resolve(doc.render());
});
return defer;
} else return Deferred.resolve(doc.render());
}
function cloneNodeWithStyles(node) {
var clone$$1 = node.cloneNode(false);
if (node.tagName) {
var styles = window.getComputedStyle(node);
clone$$1.style.cssText = styles.cssText;
}
for (var i = 0; i < node.childNodes.length; i++) {
clone$$1.appendChild(cloneNodeWithStyles(node.childNodes[i]));
}
return clone$$1;
}
var toExcel = function (id, options) {
options = options || {};
options.export_mode = "excel";
id = isArray(id) ? id : [id];
var views = [];
for (var i = 0; i < id.length; i++) {
if (!id[i].id) id[i] = {
id: id[i]
};
var view = $$(id[i].id);
var viewOptions = exports.extend(id[i].options || {}, options);
if (view && view.$exportView) view = view.$exportView(viewOptions);
assert(view, errorMessage); //$exportView returns array
if (isArray(view)) views = views.concat(view);else if (view.data && view.data.pull) {
//spreadsheet and excelviewer require plain data output first
var scheme = getExportScheme(view, viewOptions);
views.push({
scheme: scheme,
exportData: getExportData(view, viewOptions, scheme),
spans: viewOptions.spans ? getSpans(view, viewOptions) : [],
viewOptions: viewOptions
});
}
}
if (options.dataOnly) return views;
var defer = Deferred.defer();
return require(env.cdn + "/extras/xlsx.core.styles.min.js").then(function () {
if (!views.length) return defer.reject(errorMessage);
var wb = {
SheetNames: [],
Sheets: {},
Workbook: {
WBProps: {},
Names: []
}
};
for (var _i = 0; _i < views.length; _i++) {
var _viewOptions = views[_i].viewOptions;
var _scheme = views[_i].scheme;
var result = views[_i].exportData;
var spans = views[_i].spans;
var ranges = views[_i].ranges || [];
var styles = views[_i].styles || [];
var data = getExcelData(result, _scheme, spans, styles, _viewOptions);
var sname = (_viewOptions.name || "Data" + (_i + 1)).replace(/[*?:[\]\\/]/g, "").replace(/&/g, "&").substring(0, 31); //avoid name duplication
var k = _i;
while (wb.SheetNames.indexOf(sname) != -1) {
sname = "Data" + ++k;
}
wb.SheetNames.push(sname);
wb.Sheets[sname] = data;
wb.Workbook.Names = wb.Workbook.Names.concat(ranges);
}
/* global XLSX */
var xls = XLSX.write(wb, {
bookType: "xlsx",
bookSST: false,
type: "binary"
});
var filename = getFileName(options.filename, "xlsx");
var blob = new Blob([str2array(xls)], {
type: "application/xlsx"
});
if (options.download !== false) download(blob, filename);
defer.resolve(blob);
return defer;
});
};
function str2array(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i != s.length; ++i) {
view[i] = s.charCodeAt(i) & 0xFF;
}
return buf;
}
var types = {
number: "n",
date: "n",
string: "s",
boolean: "b"
};
var table = "_table";
function getExcelData(data, scheme, spans, styles, options) {
var ws = {};
var range = {
s: {
c: 10000000,
r: 10000000
},
e: {
c: 0,
r: 0
}
};
for (var R = 0; R != data.length; ++R) {
for (var C = 0; C != data[R].length; ++C) {
if (range.s.r > R) range.s.r = R;
if (range.s.c > C) range.s.c = C;
if (range.e.r < R) range.e.r = R;
if (range.e.c < C) range.e.c = C;
var cell = {
v: data[R][C]
};
if (cell.v === null) continue;
var cell_ref = XLSX.utils.encode_cell({
c: C,
r: R
});
var stringValue = cell.v.toString();
var isFormula = stringValue.charAt(0) === "=";
if (styles) {
var cellStyle = getStyles(R, C, styles);
if (cellStyle.format) {
cell.z = cellStyle.format;
delete cellStyle.format;
}
if (cellStyle.type) {
cell.t = types[cellStyle.type];
delete cellStyle.type;
}
cell.s = cellStyle;
} // set type based on column's config
// skip headers and formula based cells
var header = (options.docHeader ? 2 : 0) + scheme[0].header.length;
if (R >= header && !isFormula) {
var column = scheme[C];
if (column.type && !cell.t) cell.t = types[column.type] || "";
if (column.format && !cell.z) cell.z = column.format;
} // set type based on cell's value
if (options.stubCells && !stringValue) cell.t = "z";else if (cell.v instanceof Date) {
cell.t = cell.t || "n";
cell.z = cell.z || XLSX.SSF[table][14];
cell.v = excelDate(cell.v);
} else if (isFormula) {
cell.t = cell.t || "n";
cell.f = cell.v.substring(1);
delete cell.v;
} else if (!cell.t) {
if (typeof cell.v === "boolean") cell.t = "b";else if (typeof cell.v === "number" || parseFloat(cell.v) == cell.v) {
cell.v = cell.v * 1;
cell.t = "n";
} else {
// convert any other object to a string
cell.v = stringValue;
cell.t = "s";
}
}
ws[cell_ref] = cell;
}
}
if (range.s.c < 10000000) ws["!ref"] = XLSX.utils.encode_range(range);
ws["!rows"] = getRowHeights(scheme);
ws["!cols"] = getColumnsWidths(scheme);
if (spans.length) ws["!merges"] = spans;
return ws;
}
function getRowHeights(scheme) {
var heights = scheme.heights;
for (var i in heights) {
heights[i] = {
hpx: heights[i],
hpt: heights[i] * 0.75
};
}
var hidden = scheme.hiddenRows;
if (hidden) for (var _i2 in hidden) {
if (!heights[_i2]) heights[_i2] = {};
heights[_i2].hidden = 1;
}
return heights;
}
function getSpans(view, options) {
var isTable = view.getColumnConfig;
var pull = view._spans_pull;
var spans = [];
if (isTable) {
if (options.header !== false) spans = getHeaderSpans(view, options, "header", spans);
if (pull) {
var xc = options.xCorrection || 0;
var yc = options.yCorrection || 0;
for (var row in pull) {
//{ s:{c:1, r:0}, e:{c:3, r:0} }
var cols = pull[row];
for (var col in cols) {
var colIndex = view.getColumnIndex(col);
var rowId = view.getItem(row).id;
var rowIndex = view.getIndexById(rowId);
if (options.hidden) {
var hiddenColsOrder = view._hidden_column_order;
if (hiddenColsOrder.length) {
var colId = view.getColumnConfig(col).id;
colIndex = hiddenColsOrder.indexOf(colId);
}
var hiddenRowsOrder = view.data._filter_order;
if (hiddenRowsOrder && hiddenRowsOrder.length) rowIndex = hiddenRowsOrder.indexOf(rowId);
}
var sc = colIndex - xc;
var sr = rowIndex - yc;
if (sc < 0 || sr < 0) //hidden cols/rows
continue;
var ec = sc + cols[col][0] - 1;
var er = sr + (cols[col][1] - 1);
spans.push({
s: {
c: sc,
r: sr
},
e: {
c: ec,
r: er
}
});
}
}
}
if (options.footer !== false) spans = getHeaderSpans(view, options, "footer", spans);
}
return spans;
}
function getHeaderSpans(view, options, group, spans) {
var columns = view.config.columns;
var delta = (options.docHeader ? 2 : 0) + (group == "header" ? 0 : (options.header !== false ? view._headers.length : 0) + view.count());
for (var i = 0; i < columns.length; i++) {
var header = columns[i][group];
for (var h = 0; h < header.length; h++) {
if (header[h] && (header[h].colspan || header[h].rowspan)) {
spans.push({
s: {
c: i,
r: h + delta
},
e: {
c: i + (header[h].colspan || 1) - 1,
r: h + (header[h].rowspan || 1) - 1 + delta
}
});
}
}
}
return spans;
}
function excelDate(date) {
var returnDateTime = 25569 + (date.getTime() - date.getTimezoneOffset() * 60 * 1000) / (1000 * 60 * 60 * 24);
return returnDateTime.toString().substr(0, 20);
}
function getColumnsWidths(scheme) {
var wscols = [];
for (var i = 0; i < scheme.length; i++) {
var col = scheme[i];
wscols.push({
wch: col.width,
hidden: scheme.hiddenCols ? scheme.hiddenCols[col.id] : 0
});
}
return wscols;
}
function editStop() {
callEvent("onEditEnd", []);
}
if (env.isIE8) {
// Not really a polyfill, silence the esModule flag
Object.defineProperty = function (obj, key, data) {
obj[key] = data.value;
};
}
var en = {
groupDelimiter: ",",
groupSize: 3,
decimalDelimiter: ".",
decimalSize: 2,
dateFormat: "%m/%d/%Y",
timeFormat: "%h:%i %A",
longDateFormat: "%d %F %Y",
fullDateFormat: "%m/%d/%Y %h:%i %A",
am: ["am", "AM"],
pm: ["pm", "PM"],
price: "${obj}",
priceSettings: {
groupDelimiter: ",",
groupSize: 3,
decimalDelimiter: ".",
decimalSize: 2
},
fileSize: ["b", "Kb", "Mb", "Gb", "Tb", "Pb", "Eb"],
calendar: {
monthFull: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
monthShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
dayFull: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
dayShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
hours: "Hours",
minutes: "Minutes",
done: "Done",
clear: "Clear",
today: "Today"
},
dataExport: {
page: "Page",
of: "of"
},
PDFviewer: {
of: "of",
automaticZoom: "Automatic Zoom",
actualSize: "Actual Size",
pageFit: "Page Fit",
pageWidth: "Page Width",
pageHeight: "Page Height",
enterPassword: "Enter password",
passwordError: "Wrong password"
},
aria: {
calendar: "Calendar",
increaseValue: "Increase value",
decreaseValue: "Decrease value",
navMonth: ["Previous month", "Next month"],
navYear: ["Previous year", "Next year"],
navDecade: ["Previous decade", "Next decade"],
dateFormat: "%d %F %Y",
monthFormat: "%F %Y",
yearFormat: "%Y",
hourFormat: "Hours: %h %A",
minuteFormat: "Minutes: %i",
removeItem: "Remove item",
pages: ["First page", "Previous page", "Next page", "Last page"],
page: "Page",
headermenu: "Header menu",
openGroup: "Open column group",
closeGroup: "Close column group",
closeTab: "Close tab",
showTabs: "Show more tabs",
resetTreeMap: "Reset tree map",
navTreeMap: "Level up",
nextTab: "Next tab",
prevTab: "Previous tab",
multitextSection: "Add section",
multitextextraSection: "Remove section",
showChart: "Show chart",
hideChart: "Hide chart",
resizeChart: "Resize chart"
},
richtext: {
underline: "Underline",
bold: "Bold",
italic: "Italic"
},
combo: {
select: "Select",
selectAll: "Select all",
unselectAll: "Unselect all"
},
message: {
ok: "OK",
cancel: "Cancel"
},
comments: {
send: "Send",
confirmMessage: "The comment will be removed. Are you sure?",
edit: "Edit",
remove: "Remove",
placeholder: "Type here..",
moreComments: "More comments"
},
filter: {
less: "less",
lessOrEqual: "less or equal",
greater: "greater",
greaterOrEqual: "greater or equal",
contains: "contains",
notContains: "not contains",
equal: "equal",
notEqual: "not equal",
beginsWith: "begins with",
notBeginsWith: "not begins with",
endsWith: "ends with",
notEndsWith: "not ends with",
between: "between",
notBetween: "not between"
},
timeboard: {
seconds: "Seconds"
}
};
var wDate = {
startOnMonday: false,
toFixed: function (num, ms) {
if (num < 10) num = "0" + num;
if (ms && num < 100) num = "0" + num;
return num;
},
weekStart: function (date) {
date = this.copy(date);
var shift = date.getDay();
if (this.startOnMonday) {
if (shift === 0) shift = 6;else shift--;
}
return this.datePart(this.add(date, -1 * shift, "day"));
},
monthStart: function (date) {
date = this.copy(date);
date.setDate(1);
return this.datePart(date);
},
yearStart: function (date) {
date = this.copy(date);
date.setMonth(0);
return this.monthStart(date);
},
dayStart: function (date) {
return this.datePart(date, true);
},
dateToStr: function (format, utc) {
if (typeof format == "function") return format;
if (env.strict) {
return function (date) {
if (!date) return "";
if (!date.getMonth) date = i18n.parseFormatDate(date);
var str = "";
var lastPos = 0;
format.replace(/%[a-zA-Z]/g, function (s, pos) {
str += format.slice(lastPos, pos);
var fn = function (date) {
if (s == "%d") return wDate.toFixed(date.getDate());
if (s == "%m") return wDate.toFixed(date.getMonth() + 1);
if (s == "%j") return date.getDate();
if (s == "%n") return date.getMonth() + 1;
if (s == "%y") return wDate.toFixed(date.getFullYear() % 100);
if (s == "%Y") return date.getFullYear();
if (s == "%D") return i18n.calendar.dayShort[date.getDay()];
if (s == "%l") return i18n.calendar.dayFull[date.getDay()];
if (s == "%M") return i18n.calendar.monthShort[date.getMonth()];
if (s == "%F") return i18n.calendar.monthFull[date.getMonth()];
if (s == "%h") return wDate.toFixed((date.getHours() + 11) % 12 + 1);
if (s == "%g") return (date.getHours() + 11) % 12 + 1;
if (s == "%G") return date.getHours();
if (s == "%H") return wDate.toFixed(date.getHours());
if (s == "%i") return wDate.toFixed(date.getMinutes());
if (s == "%a") return date.getHours() > 11 ? i18n.pm[0] : i18n.am[0];
if (s == "%A") return date.getHours() > 11 ? i18n.pm[1] : i18n.am[1];
if (s == "%s") return wDate.toFixed(date.getSeconds());
if (s == "%S") return wDate.toFixed(date.getMilliseconds(), true);
if (s == "%W") return wDate.toFixed(Date.getISOWeek(date));
if (s == "%c") {
var str = date.getFullYear();
str += "-" + wDate.toFixed(date.getMonth() + 1);
str += "-" + wDate.toFixed(date.getDate());
str += "T";
str += wDate.toFixed(date.getHours());
str += ":" + wDate.toFixed(date.getMinutes());
str += ":" + wDate.toFixed(date.getSeconds());
return str;
}
return s;
};
str += fn(date);
lastPos = pos + 2;
});
str += format.slice(lastPos, format.length);
return str;
};
}
format = format.replace(/%[a-zA-Z]/g, function (a) {
switch (a) {
case "%d":
return "\"+wDate.toFixed(date.getDate())+\"";
case "%m":
return "\"+wDate.toFixed((date.getMonth()+1))+\"";
case "%j":
return "\"+date.getDate()+\"";
case "%n":
return "\"+(date.getMonth()+1)+\"";
case "%y":
return "\"+wDate.toFixed(date.getFullYear()%100)+\"";
case "%Y":
return "\"+date.getFullYear()+\"";
case "%D":
return "\"+i18n.calendar.dayShort[date.getDay()]+\"";
case "%l":
return "\"+i18n.calendar.dayFull[date.getDay()]+\"";
case "%M":
return "\"+i18n.calendar.monthShort[date.getMonth()]+\"";
case "%F":
return "\"+i18n.calendar.monthFull[date.getMonth()]+\"";
case "%h":
return "\"+wDate.toFixed((date.getHours()+11)%12+1)+\"";
case "%g":
return "\"+((date.getHours()+11)%12+1)+\"";
case "%G":
return "\"+date.getHours()+\"";
case "%H":
return "\"+wDate.toFixed(date.getHours())+\"";
case "%i":
return "\"+wDate.toFixed(date.getMinutes())+\"";
case "%a":
return "\"+(date.getHours()>11?i18n.pm[0]:i18n.am[0])+\"";
case "%A":
return "\"+(date.getHours()>11?i18n.pm[1]:i18n.am[1])+\"";
case "%s":
return "\"+wDate.toFixed(date.getSeconds())+\"";
case "%S":
return "\"+wDate.toFixed(date.getMilliseconds(), true)+\"";
case "%W":
return "\"+wDate.toFixed(wDate.getISOWeek(date))+\"";
case "%c":
var str = "\"+date.getFullYear()+\"";
str += "-\"+wDate.toFixed((date.getMonth()+1))+\"";
str += "-\"+wDate.toFixed(date.getDate())+\"";
str += "T";
str += "\"+wDate.toFixed(date.getHours())+\"";
str += ":\"+wDate.toFixed(date.getMinutes())+\"";
str += ":\"+wDate.toFixed(date.getSeconds())+\"";
if (utc === true) str += "Z";
return str;
default:
return a;
}
});
if (utc === true) format = format.replace(/date\.get/g, "date.getUTC");
var temp = new Function("date", "i18n", "wDate", "if (!date) return ''; if (!date.getMonth) date=i18n.parseFormatDate(date); return \"" + format + "\";");
return function (v) {
return temp(v, i18n, wDate);
};
},
strToDate: function (format, utc) {
if (typeof format == "function") return format;
var mask = format.match(/%[a-zA-Z]/g);
var splt = "var temp=date.split(/[\\s\\./\\-\\:\\,]+/g); if(!temp.join('')){return ''}";
var i, t, s;
if (!i18n.calendar.monthShort_hash) {
s = i18n.calendar.monthShort;
t = i18n.calendar.monthShort_hash = {};
for (i = 0; i < s.length; i++) {
t[s[i]] = i;
}
s = i18n.calendar.monthFull;
t = i18n.calendar.monthFull_hash = {};
for (i = 0; i < s.length; i++) {
t[s[i]] = i;
}
}
if (env.strict) {
return function (date) {
if (!date) return "";
if (_typeof(date) == "object") return date;
var temp = date.split(/[\s./\-:,]+/g);
if (!temp.join("")) return "";
var set = [0, 0, 1, 0, 0, 0, 0];
for (i = 0; i < mask.length; i++) {
var a = mask[i];
if (a == "%y") set[0] = temp[i] * 1 + (temp[i] > 30 ? 1900 : 2000);else if (a == "%Y") {
set[0] = (temp[i] || 0) * 1;
if (set[0] < 30) set[0] += 2000;
} else if (a == "%n" || a == "%m") set[1] = (temp[i] || 1) - 1;else if (a == "%M") set[1] = i18n.calendar.monthShort_hash[temp[i]] || 0;else if (a == "%F") set[1] = i18n.calendar.monthFull_hash[temp[i]] || 0;else if (a == "%j" || a == "%d") set[2] = temp[i] || 1;else if (a == "%g" || a == "%G" || a == "%h" || a == "%H") set[3] = temp[i] || 0;else if (a == "%a") set[3] = set[3] % 12 + ((temp[i] || "") == i18n.am[0] ? 0 : 12);else if (a == "%A") set[3] = set[3] % 12 + ((temp[i] || "") == i18n.am[1] ? 0 : 12);else if (a == "%i") set[4] = temp[i] || 0;else if (a == "%s") set[5] = temp[i] || 0;else if (a == "%S") set[6] = temp[i] || 0;else if (a == "%c") {
var reg = /(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(\+.*|)/g;
var res = reg.exec(date);
set[0] = (res[1] || 0) * 1;
if (set[0] < 30) set[0] += 2000;
set[1] = (res[2] || 1) - 1;
set[2] = res[3] || 1;
set[3] = res[4] || 0;
set[4] = res[5] || 0;
set[5] = res[6] || 0;
}
}
if (utc) return new Date(Date.UTC(set[0], set[1], set[2], set[3], set[4], set[5], set[6]));
return new Date(set[0], set[1], set[2], set[3], set[4], set[5], set[6]);
};
}
for (i = 0; i < mask.length; i++) {
switch (mask[i]) {
case "%j":
case "%d":
splt += "set[2]=temp[" + i + "]||1;";
break;
case "%n":
case "%m":
splt += "set[1]=(temp[" + i + "]||1)-1;";
break;
case "%y":
splt += "set[0]=temp[" + i + "]*1+(temp[" + i + "]>30?1900:2000);";
break;
case "%g":
case "%G":
case "%h":
case "%H":
splt += "set[3]=temp[" + i + "]||0;";
break;
case "%i":
splt += "set[4]=temp[" + i + "]||0;";
break;
case "%Y":
splt += "set[0]=(temp[" + i + "]||0)*1; if (set[0]<30) set[0]+=2000;";
break;
case "%a":
splt += "set[3]=set[3]%12+(temp[" + i + "]==i18n.am[0]?0:12);";
break;
case "%A":
splt += "set[3]=set[3]%12+(temp[" + i + "]==i18n.am[1]?0:12);";
break;
case "%s":
splt += "set[5]=temp[" + i + "]||0;";
break;
case "%S":
splt += "set[6]=temp[" + i + "]||0;";
break;
case "%M":
splt += "set[1]=i18n.calendar.monthShort_hash[temp[" + i + "]]||0;";
break;
case "%F":
splt += "set[1]=i18n.calendar.monthFull_hash[temp[" + i + "]]||0;";
break;
case "%c":
splt += "var res = date.split('T');";
splt += "if(res[0]){ var d = res[0].split('-');";
splt += "set[0]= (d[0]||0)*1; if (set[0]<30) set[0]+=2000;";
splt += "set[1]= (d[1]||1)-1;";
splt += "set[2]= d[2]||1;}";
splt += "if(res[1]){ var t = res[1].split(':');";
splt += "set[3]= t[0]||0;";
splt += "set[4]= t[1]||0;";
splt += "set[5]= parseInt(t[2])||0;}";
break;
default:
break;
}
}
var code = "set[0],set[1],set[2],set[3],set[4],set[5],set[6]";
if (utc) code = " Date.UTC(" + code + ")";
var temp = new Function("date", "i18n", "if (!date) return ''; if (typeof date == 'object') return date; var set=[0,0,1,0,0,0,0]; " + splt + " return new Date(" + code + ");");
return function (v) {
return temp(v, i18n);
};
},
getISOWeek: function (ndate) {
if (!ndate) return false;
var nday = ndate.getDay();
if (nday === 0) {
nday = 7;
}
var first_thursday = new Date(ndate.valueOf());
first_thursday.setDate(ndate.getDate() + (4 - nday));
var year_number = first_thursday.getFullYear(); // year of the first Thursday
var ordinal_date = Math.floor((first_thursday.getTime() - new Date(year_number, 0, 1).getTime()) / 86400000); //ordinal date of the first Thursday - 1 (so not really ordinal date)
var weekNumber = 1 + Math.floor(ordinal_date / 7);
return weekNumber;
},
getUTCISOWeek: function (ndate) {
return this.getISOWeek(ndate);
},
_correctDate: function (d, d0, inc, checkFunc) {
if (!inc) return;
var incorrect = checkFunc(d, d0);
if (incorrect) {
var i = inc > 0 ? 1 : -1;
while (incorrect) {
d.setHours(d.getHours() + i);
incorrect = checkFunc(d, d0);
i += inc > 0 ? 1 : -1;
}
}
},
add: function (date, inc, mode, copy) {
if (copy) date = this.copy(date);
var d = wDate.copy(date);
switch (mode) {
case "day":
date.setDate(date.getDate() + inc);
this._correctDate(date, d, inc, function (d, d0) {
return wDate.datePart(d0, true).valueOf() == wDate.datePart(d, true).valueOf();
});
break;
case "week":
date.setDate(date.getDate() + 7 * inc);
this._correctDate(date, d, 7 * inc, function (d, d0) {
return wDate.datePart(d0, true).valueOf() == wDate.datePart(d, true).valueOf();
});
break;
case "month":
date.setMonth(date.getMonth() + inc);
this._correctDate(date, d, inc, function (d, d0) {
return d0.getMonth() == d.getMonth() && d0.getYear() == d.getYear();
});
break;
case "quarter":
date.setMonth(date.getMonth() + inc * 3);
this._correctDate(date, d, inc, function (d, d0) {
return d0.getMonth() == d.getMonth() && d0.getYear() == d.getYear();
});
break;
case "year":
date.setYear(date.getFullYear() + inc);
this._correctDate(date, d, inc, function (d, d0) {
return d0.getFullYear() == d.getFullYear();
});
break;
case "hour":
date.setHours(date.getHours() + inc);
this._correctDate(date, d, inc, function (d, d0) {
return d0.getHours() == d.getHours() && Date.datePart(d0, true) == Date.datePart(d, true);
});
break;
case "minute":
date.setMinutes(date.getMinutes() + inc);
break;
default:
wDate.add[mode](date, inc, mode);
break;
}
return date;
},
datePart: function (date, copy) {
if (copy) date = this.copy(date); // workaround for non-existent hours
var d = this.copy(date);
d.setHours(0);
if (d.getDate() != date.getDate()) {
date.setHours(1);
} else {
date.setHours(0);
}
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
return date;
},
timePart: function (date, copy) {
if (copy) date = this.copy(date);
return (date.valueOf() / 1000 - date.getTimezoneOffset() * 60) % 86400;
},
copy: function (date) {
return new Date(date.valueOf());
},
equal: function (a, b) {
if (!a || !b) return false;
return a.valueOf() === b.valueOf();
},
isHoliday: function (day) {
day = day.getDay();
if (day === 0 || day == 6) return "webix_cal_event";
}
};
var Number$1 = {
getConfig: function (value) {
var config = {
decimalSize: 0,
groupSize: 999,
prefix: "",
sufix: ""
};
var parts = value.split(/[0-9].*[0-9]/g);
if (parts[0].length) config.prefix = parts[0];
if (parts[1].length) config.sufix = parts[1];
if (config.prefix || config.sufix) {
value = value.substr(config.prefix.length, value.length - config.prefix.length - config.sufix.length);
}
var num = value.indexOf("1");
if (num > 0) {
config.prefix = value.substr(0, num);
value = value.substr(num);
}
var dot = value.indexOf("0");
if (dot > 0) {
config.decimalSize = value.length - dot;
config.decimalDelimiter = value[dot - 1];
value = value.substr(0, dot - 1);
}
var sep = value.match(/[^0-9]/);
if (sep) {
config.groupSize = value.length - sep.index - 1;
config.groupDelimiter = value[sep.index];
}
return config;
},
parse: function (value, config) {
if (!value || typeof value !== "string") return value;
if (config.prefix) value = value.toLowerCase().replace(config.prefix.toLowerCase() || "", "");
if (config.sufix) value = value.toLowerCase().replace(config.sufix.toLowerCase() || "", "");
var decimal = "";
if (config.decimalDelimiter) {
var ind = value.indexOf(config.decimalDelimiter);
if (ind > -1) {
decimal = value.substr(ind + 1).replace(/[^0-9]/g, "");
decimal = decimal.substr(0, Math.min(decimal.length, config.decimalSize));
value = value.substr(0, ind);
}
}
var sign = value[0] === "-" ? -1 : 1;
value = value.replace(/[^0-9]/g, "");
if (!value) value = "0";
if (decimal) value += "." + decimal;
return parseFloat(value) * sign;
},
format: function (value, config) {
if (value === "" || typeof value === "undefined") return value;
config = config || i18n;
value = parseFloat(value);
var sign = value < 0 ? "-" : "";
value = Math.abs(value);
if (!config.decimalOptional) value = value.toFixed(config.decimalSize);
var str = value.toString();
str = str.split(".");
var int_value = "";
if (config.groupSize) {
var step = config.groupSize;
var i = str[0].length;
do {
i -= step;
var chunk = i > 0 ? str[0].substr(i, step) : str[0].substr(0, step + i);
int_value = chunk + (int_value ? config.groupDelimiter + int_value : "");
} while (i > 0);
} else int_value = str[0];
if (config.decimalSize) str = sign + int_value + (str[1] ? config.decimalDelimiter + str[1] : "");else str = sign + int_value;
if (config.prefix || config.sufix) {
return config.prefix + str + config.sufix;
} else return str;
},
numToStr: function (config) {
return function (value) {
return Number$1.format(value, config);
};
}
};
function extend(base, source) {
for (var method in source) {
if (_typeof(source[method]) == "object" && !isArray(source[method])) {
if (!base[method]) {
base[method] = {};
}
extend(base[method], source[method]);
} else base[method] = source[method];
}
}
var helpers = ["fullDateFormat", "timeFormat", "dateFormat", "longDateFormat", "parseFormat", "parseTimeFormat"];
i18n.setLocale = function (locale) {
if (typeof locale == "string") locale = i18n.locales[locale];
if (locale) {
locale.priceSettings = copy(locale.priceSettings || locale);
extend(i18n, locale);
delete i18n.calendar.monthShort_hash;
delete i18n.calendar.monthFull_hash;
}
for (var i = 0; i < helpers.length; i++) {
var key = helpers[i];
var utc = i18n[key + "UTC"];
i18n[key + "Str"] = wDate.dateToStr(i18n[key], utc);
i18n[key + "Date"] = wDate.strToDate(i18n[key], utc);
}
var _price_format = template(i18n.price);
var _price_settings = i18n.priceSettings || i18n;
i18n.intFormat = Number$1.numToStr({
groupSize: i18n.groupSize,
groupDelimiter: i18n.groupDelimiter,
decimalSize: 0
});
i18n.priceFormat = function (value) {
return _price_format(Number$1.format(value, _price_settings));
};
i18n.numberFormat = Number$1.format;
};
i18n.locales = {
"en-US": en
};
i18n.setLocale("en-US");
var storage = {};
storage.prefix = function (scope, storage) {
scope = scope + ".";
return {
put: function (name, data) {
return storage.put(scope + name, data);
},
get: function (name) {
return storage.get(scope + name);
},
remove: function (name) {
return storage.remove(scope + name);
}
};
};
storage.local = {
put: function (name, data) {
if (name && window.JSON && window.localStorage) {
window.localStorage.setItem(name, stringify(data));
}
},
get: function (name) {
if (name && window.JSON && window.localStorage) {
var json = window.localStorage.getItem(name);
if (!json) return null;
return DataDriver.json.toObject(json);
} else return null;
},
remove: function (name) {
if (name && window.JSON && window.localStorage) {
window.localStorage.removeItem(name);
}
},
clear: function () {
window.localStorage.clear();
}
};
storage.session = {
put: function (name, data) {
if (name && window.JSON && window.sessionStorage) {
window.sessionStorage.setItem(name, stringify(data));
}
},
get: function (name) {
if (name && window.JSON && window.sessionStorage) {
var json = window.sessionStorage.getItem(name);
if (!json) return null;
return DataDriver.json.toObject(json);
} else return null;
},
remove: function (name) {
if (name && window.JSON && window.sessionStorage) {
window.sessionStorage.removeItem(name);
}
},
clear: function () {
window.sessionStorage.clear();
}
};
storage.cookie = {
put: function (name, data, domain, expires) {
if (name && window.JSON) {
document.cookie = name + "=" + escape(stringify(data)) + (expires && expires instanceof Date ? ";expires=" + expires.toUTCString() : "") + (domain ? ";domain=" + domain : "") + (env.https ? ";secure" : "");
}
},
getRaw: function (check_name) {
// first we'll split this cookie up into name/value pairs
// note: document.cookie only returns name=value, not the other components
var a_all_cookies = document.cookie.split(";");
var a_temp_cookie = "";
var cookie_name = "";
var cookie_value = "";
var b_cookie_found = false; // set boolean t/f default f
for (var i = 0; i < a_all_cookies.length; i++) {
// now we'll split apart each name=value pair
a_temp_cookie = a_all_cookies[i].split("="); // and trim left/right whitespace while we're at it
cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, ""); // if the extracted name matches passed check_name
if (cookie_name == check_name) {
b_cookie_found = true; // we need to handle case where cookie has no value but exists (no = sign, that is):
if (a_temp_cookie.length > 1) {
cookie_value = unescape(a_temp_cookie[1].replace(/^\s+|\s+$/g, ""));
} // note that in cases where cookie is initialized but no value, null is returned
return cookie_value;
}
a_temp_cookie = null;
cookie_name = "";
}
if (!b_cookie_found) {
return null;
}
return null;
},
get: function (name) {
if (name && window.JSON) {
var json = this.getRaw(name);
if (!json) return null;
return DataDriver.json.toObject(unescape(json));
} else return null;
},
remove: function (name, domain) {
if (name && this.getRaw(name)) document.cookie = name + "=" + (domain ? ";domain=" + domain : "") + ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
},
clear: function (domain) {
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
document.cookie = /^[^=]+/.exec(cookies[i])[0] + "=" + (domain ? ";domain=" + domain : "") + ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
}
}
};
env.printPPI = 96;
env.printMargin = 0.75 * env.printPPI;
var papers = {
"a4": "A4",
"a3": "A3",
"letter": "letter"
};
var fits = {
page: true,
data: true
};
var modes = {
portrait: true,
landscape: true
};
var sizes = {
//inches, real size is value*ppi
"A3": {
width: 11.7,
height: 16.5
},
"A4": {
width: 8.27,
height: 11.7
},
"letter": {
width: 8.5,
height: 11
}
};
var print = function (id, options) {
var view = $$(id);
if (view && view.$printView) view = view.$printView();
assert(view, "non-existing view for printing");
if (!view) return;
if (view.callEvent) view.callEvent("onBeforePrint", [options]);
options = _checkOptions(options);
_beforePrint(options); //try widget's custom logic first, sometimes it may deny
if (!view.$customPrint || view.$customPrint(options) === true) _print(view, options);
_afterPrint(options);
};
/*processing print options*/
function _checkOptions(options) {
options = options || {};
options.paper = papers[(options.paper || "").toLowerCase()] || "A4";
options.mode = modes[options.mode] ? options.mode : "portrait";
options.fit = fits[options.fit] ? options.fit : "page";
options.scroll = options.scroll || false;
options.size = sizes[options.paper];
options.margin = options.margin || options.margin === 0 ? options.margin : {};
var margin = isNaN(options.margin * 1) ? env.printMargin : options.margin;
options.margin = {
top: options.margin.top || options.margin.top === 0 ? options.margin.top : margin,
bottom: options.margin.bottom || options.margin.bottom === 0 ? options.margin.bottom : margin,
right: options.margin.right || options.margin.right === 0 ? options.margin.right : margin,
left: options.margin.left || options.margin.left === 0 ? options.margin.left : margin
};
return options;
}
/*preparing printing environment*/
function _beforePrint(options) {
addCss(document.body, "webix_print");
if (options.docHeader) _getHeaderFooter("Header", options);
if (options.docFooter) _getHeaderFooter("Footer", options);
/* static print styles are located at 'css/print.less'*/
var cssString = "@media print { " + "@page{ size:" + options.paper + " " + options.mode + ";" + "margin-top:" + options.margin.top + "px;margin-bottom:" + options.margin.bottom + "px;margin-right:" + options.margin.right + "px;margin-left:" + options.margin.left + "px;}" + "}";
addStyle(cssString, "print");
}
/*cleaning environment*/
function _afterPrint(options) {
removeCss(document.body, "webix_print");
removeStyle("print");
if (options.docHeader) remove(options.docHeader);
if (options.docFooter) remove(options.docFooter);
}
/*common print actions */
function _print(view, options) {
var doc = view.$view.cloneNode(true); //copy data from all canvases
var canvases = view.$view.getElementsByTagName("canvas");
if (canvases.length) for (var i = canvases.length - 1; i >= 0; i--) {
var destCtx = doc.getElementsByTagName("canvas")[i].getContext("2d");
destCtx.drawImage(canvases[i], 0, 0);
}
insertBefore(doc, options.docFooter, document.body);
addCss(doc, "webix_ui_print");
if (!options.scroll && (view._dataobj && view.data && view.data.pull || view.getBody)) addCss(doc, "webix_print_noscroll");
window.print();
remove(doc);
}
/*custom header nad footer*/
function _getHeaderFooter(group, options) {
var header = create("div", {
"class": "webix_view webix_print_" + group.toLowerCase(),
"style": "height:0px;visibility:hidden;"
}, options["doc" + group]);
if (group === "Header") insertBefore(header, document.body.firstChild);else document.body.appendChild(header);
options["doc" + group] = header;
}
var filters = {
number: {
greater: function (a, b) {
return a > b;
},
less: function (a, b) {
return a < b;
},
greaterOrEqual: function (a, b) {
return a >= b;
},
lessOrEqual: function (a, b) {
return a <= b;
},
equal: function (a, b) {
return a == b;
},
notEqual: function (a, b) {
return a != b;
},
contains: function (a, b) {
return a.toString().toLowerCase().indexOf(b.toString().toLowerCase()) !== -1;
},
notContains: function (a, b) {
return a.toString().toLowerCase().indexOf(b.toString().toLowerCase()) === -1;
}
},
text: {
equal: function (a, b) {
return a.toLowerCase() === b.toLowerCase();
},
notEqual: function (a, b) {
return a.toLowerCase() !== b.toLowerCase();
},
contains: function (a, b) {
return a.toLowerCase().indexOf(b.toLowerCase()) !== -1;
},
notContains: function (a, b) {
return a.toLowerCase().indexOf(b.toLowerCase()) === -1;
},
beginsWith: function (a, b) {
return a.toLowerCase().lastIndexOf(b.toLowerCase(), 0) === 0;
},
notBeginsWith: function (a, b) {
return a.toLowerCase().lastIndexOf(b.toLowerCase(), 0) !== 0;
},
endsWith: function (a, b) {
return a.toLowerCase().indexOf(b.toLowerCase(), a.length - b.length) !== -1;
},
notEndsWith: function (a, b) {
return a.toLowerCase().indexOf(b.toLowerCase(), a.length - b.length) === -1;
}
},
date: {
greater: function (a, b) {
return a > b;
},
less: function (a, b) {
return a < b;
},
greaterOrEqual: function (a, b) {
return a >= b;
},
lessOrEqual: function (a, b) {
return a <= b;
},
equal: function (a, b) {
if (!a || !b) return false;
return a.valueOf() === b.valueOf();
},
notEqual: function (a, b) {
if (!a || !b) return true;
return a.valueOf() !== b.valueOf();
},
between: function (a, b) {
return (!b.start || a > b.start) && (!b.end || a < b.end);
},
notBetween: function (a, b) {
return !b.start || a <= b.start || !b.end || a >= b.end;
}
}
};
var patterns = {
phone: {
mask: "+# (###) ###-####",
allow: /[0-9]/g
},
card: {
mask: "#### #### #### ####",
allow: /[0-9]/g
},
date: {
mask: "####-##-## ##:##",
allow: /[0-9]/g
}
};
/*
Common helpers
*/
var html$1 = {
denySelect: denySelect,
allowSelect: allowSelect,
index: index,
createCss: createCss,
addStyle: addStyle,
removeStyle: removeStyle,
create: create,
getValue: getValue,
remove: remove,
insertBefore: insertBefore,
locate: locate,
offset: offset,
posRelative: posRelative,
pos: pos,
preventEvent: preventEvent,
stopEvent: stopEvent,
triggerEvent: triggerEvent,
addCss: addCss,
removeCss: removeCss,
getTextSize: getTextSize,
download: download,
_getClassName: _getClassName,
setSelectionRange: setSelectionRange,
getSelectionRange: getSelectionRange,
addMeta: addMeta
};
var error_key = "__webix_remote_error";
function RemoteContext(url, config) {
this._proxy = {};
this._queue = [];
this._url = url;
this._key = "";
if (config) this._process(config);else this._ready = ajax(url).then(function (data) {
return data.text();
}).then(bind(function (text) {
text = text.split("/*api*/")[1];
this._process(JSON.parse(text));
return this._proxy;
}, this));
}
RemoteContext.prototype = {
_process: function (config) {
if (config.$key) this._key = config.$key;
if (config.$vars) for (var key in config.$vars) {
this._proxy[key] = config.$vars[key];
}
this._parse(config, this._proxy, "");
},
_parse: function (api, obj, prefix) {
for (var key in api) {
if (key === "$key" || key === "$vars") continue;
var val = api[key];
if (_typeof(val) == "object") {
var sub = obj[key] = {};
this._parse(val, sub, prefix + key + ".");
} else obj[key] = this._proxy_call(this, prefix + key);
}
},
_call: function (name, args) {
var def = this._deffer(this, name, args);
this._queue.push(def);
this._start_queue();
return def;
},
_start_queue: function () {
if (!this._timer) this._timer = setTimeout(bind(this._run_queue, this), 1);
},
_run_queue: function () {
var data = [],
defs = this._queue;
for (var i = 0; i < this._queue.length; i++) {
var def = this._queue[i];
if (def.$sync) {
defs.splice(i, 1);
i--;
} else data.push({
name: def.$name,
args: def.$args
});
}
if (defs.length) {
var request = ajax();
var pack = this._pack(data);
callEvent("onBeforeRemoteCall", [request, pack, {}]);
var promise = request.post(this._url, pack).then(function (response) {
var data = response.json();
var results = data.data;
for (var i = 0; i < results.length; i++) {
var res = results[i];
var error = results[i] && results[i][error_key];
if (error) {
callEvent("onRemoteError", [error]);
defs[i].reject(error);
} else {
defs[i].resolve(res);
}
}
}, function (res) {
for (var i = 0; i < defs.length; i++) {
defs[i].reject(res);
}
throw res;
});
callEvent("onAfterRemoteCall", [promise]);
}
this._queue = [];
this._timer = null;
},
_sync: function () {
var value = null;
this.$sync = true;
var data = [{
name: this.$name,
args: this.$args
}];
try {
var request = ajax();
var pack = this.$context._pack(data);
callEvent("onBeforeRemoteCall", [request, pack, {
sync: true
}]);
var xhr = request.sync().post(this.$context._url, pack);
callEvent("onAfterRemoteCall", [null]);
value = JSON.parse(xhr.responseText).data[0];
if (value[error_key]) value = null;
} catch (e) {} //eslint-disable-line
return value;
},
_deffer: function (master, name, args) {
var pr = Deferred.defer();
pr.sync = master._sync;
pr.$name = name;
pr.$args = args;
pr.$context = this;
return pr;
},
_proxy_call: function (master, name) {
return function () {
return master._call(name, [].slice.call(arguments));
};
},
_getProxy: function () {
return this._ready || this._proxy;
},
_pack: function (obj) {
return {
key: this._key,
payload: obj
};
}
};
function getApi(url, config) {
var ctx = new RemoteContext(url, config);
var proxy = ctx._getProxy();
for (var key in proxy) {
remote[key] = proxy[key];
}
return proxy;
}
var remote = function (url, config) {
if (_typeof(url) === "object") {
var scripts = document.getElementsByTagName("script");
config = url;
url = scripts[scripts.length - 1].src;
return getApi(url, config);
} else return getApi(url, config);
};
/*submits values*/
function send(url, values, method, target) {
var form = create("FORM", {
"target": target || "_self",
"action": url,
"method": method || "POST"
}, "");
for (var k in values) {
var field = create("INPUT", {
"type": "hidden",
"name": k,
"value": values[k]
}, "");
form.appendChild(field);
}
form.style.display = "none";
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}
function animate$1(obj, parent, config) {
var pobj = $$(parent);
if (pobj) {
var aniset = config || {
type: "slide",
direction: "left"
};
var d = pobj._viewobj.cloneNode(true);
var view = ui(obj, parent);
view._viewobj.parentNode.appendChild(d);
var line = animate.formLine(view._viewobj, d, aniset);
aniset.callback = function () {
animate.breakLine(line);
};
animate(line, aniset);
return view;
}
}
function animateView(view, stateHandler, config) {
view = $$(view);
if (view) {
config = config || {
type: "slide",
direction: "left"
};
var getHTML = function (view) {
var el = view._viewobj;
var css = el.className;
var content = el.innerHTML;
return "<div class='" + css + "' style='width:" + el.offsetWidth + "px;height:" + el.offsetHeight + "px;'>" + content + "</div>";
}; // get 'display' state of child nodes
var display = [];
for (var i = 0; i < view._viewobj.childNodes.length; i++) {
var node = view._viewobj.childNodes[i];
var value = node.currentStyle ? node.currentStyle.display : getComputedStyle(node, null).display;
display.push(value || "");
} // get current html content
var currentState = getHTML(view); // apply new state
if (typeof stateHandler == "function") {
stateHandler.call(this);
} // get new html content
var newState = getHTML(view); // insert elements into the view
var tempParent = view._viewobj.insertBefore(create("DIV", {
"class": "webix_view_animate",
"style": "width:" + view._viewobj.offsetWidth + "px;height:" + view._viewobj.offsetHeight + "px;"
}, newState + currentState), view._viewobj.firstChild); // hide child nodes
for (var _i = 1; _i < view._viewobj.childNodes.length; _i++) {
view._viewobj.childNodes[_i].style.display = "none";
} // animate inserted elements
var line = animate.formLine(tempParent.childNodes[0], tempParent.childNodes[1], config);
config.callback = function () {
if (tempParent) {
view._viewobj.removeChild(tempParent);
tempParent = null; // restore 'display' state of child nodes
for (var i = 0; i < view._viewobj.childNodes.length; i++) {
view._viewobj.childNodes[i].style.display = display[i];
}
}
};
animate(line, config);
return view;
}
}
function orientation() {
var new_orientation = !!(window.orientation % 180);
if (state.orientation === new_orientation) return;
state.orientation = new_orientation;
callEvent("onRotate", [new_orientation]);
}
if (env.touch) {
state.orientation = !!((isUndefined(window.orientation) ? 90 : window.orientation) % 180);
event$1(window, "onorientationchange" in window ? "orientationchange" : "resize", orientation);
}
function fullScreen() {
if (!env.touch) return;
addMeta("apple-mobile-web-app-capable", "yes");
addMeta("viewport", "initial-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no");
if (!env.isMac) addStyle("body.webix_full_screen{ overflow-y: auto; }");
var fix = function () {
var x = window.innerWidth;
var y = window.innerHeight;
if (y) {
document.body.style.height = y + "px";
document.body.style.width = x + "px";
}
state._freeze_resize = false;
resize();
};
var onrotate = function () {
state._freeze_resize = true;
delay(fix, null, [], 500);
};
attachEvent("onRotate", onrotate);
orientation();
delay(onrotate);
}
var datafilter = {
textWaitDelay: 500,
"summColumn": {
getValue: function (node) {
return node.innerText;
},
setValue: function () {},
refresh: function (master, node, value) {
var result = 0;
master.mapCells(null, value.columnId, null, 1, function (value) {
value = value * 1;
if (!isNaN(value)) result += value;
}, true);
if (value.format) result = value.format(result);
if (value.template) result = value.template({
value: result
});
node.innerHTML = result;
},
trackCells: true,
render: function (master, config) {
if (config.template) config.template = template(config.template);
return "";
}
},
"masterCheckbox": {
getValue: function () {},
setValue: function () {},
getHelper: function (node, config) {
return {
check: function () {
config.checked = false;
node.onclick();
},
uncheck: function () {
config.checked = true;
node.onclick();
},
isChecked: function () {
return config.checked;
}
};
},
refresh: function (master, node, config) {
node.onclick = function () {
this.getElementsByTagName("input")[0].checked = config.checked = !config.checked;
var column = master.getColumnConfig(config.columnId);
var checked = config.checked ? column.checkValue : column.uncheckValue;
master.data.each(function (obj) {
obj[config.columnId] = checked;
master.callEvent("onCheck", [obj.id, config.columnId, checked]);
this.callEvent("onStoreUpdated", [obj.id, obj, "save"]);
});
master.refresh();
};
},
render: function (master, config) {
return "<input type='checkbox' " + (config.checked ? "checked='1'" : "") + ">";
}
},
"textFilter": {
getInputNode: function (node) {
return node.querySelector("input") || {
value: null
};
},
getValue: function (node) {
return this.getInputNode(node).value;
},
setValue: function (node, value) {
this.getInputNode(node).value = value;
},
refresh: function (master, node, value) {
node.component = master._settings.id;
master.registerFilter(node, value, this);
node._comp_id = master._settings.id;
if (value.value && this.getValue(node) != value.value) this.setValue(node, value.value);
node.onclick = preventEvent;
_event(node, "keydown", this._on_key_down);
},
render: function (master, config) {
if (this.init) this.init(config);
config.css = (config.css || "") + " webix_ss_filter";
return "<input " + (config.placeholder ? "placeholder=\"" + config.placeholder + "\" " : "") + "type='text'>";
},
_on_key_down: function (e) {
var id = this._comp_id; //tabbing through filters must not trigger filtering
//we can improve this functionality by preserving initial filter value
//and comparing new one with it
if ((e.which || e.keyCode) == 9) return;
if (this._filter_timer) window.clearTimeout(this._filter_timer);
this._filter_timer = window.setTimeout(function () {
var ui$$1 = $$(id); //ensure that ui is not destroyed yet
if (ui$$1) ui$$1.filterByAll();
}, datafilter.textWaitDelay);
}
},
"selectFilter": {
getInputNode: function (node) {
return node.querySelector("select") || {
value: null
};
},
getValue: function (node) {
return this.getInputNode(node).value;
},
setValue: function (node, value) {
this.getInputNode(node).value = value;
},
refresh: function (master, node, value) {
//value - config from header { contet: }
value.compare = value.compare || function (a, b) {
return a == b;
};
node.component = master._settings.id;
master.registerFilter(node, value, this);
var data = datafilter._get_data(master, value);
if (value.emptyOption !== false) data.unshift({
id: "",
value: value.emptyOption || ""
}); //slow in IE
//http://jsperf.com/select-options-vs-innerhtml
var select = document.createElement("select");
for (var i = 0; i < data.length; i++) {
var option = document.createElement("option");
option.value = data[i].id;
option.text = data[i].value;
select.add(option);
}
node.innerHTML = "";
node.appendChild(select);
if (value.value) this.setValue(node, value.value);
node.onclick = preventEvent;
select._comp_id = master._settings.id;
_event(select, "change", this._on_change);
},
render: function (master, config) {
if (this.init) this.init(config);
config.css = (config.css || "") + " webix_ss_filter";
return "";
},
_on_change: function () {
$$(this._comp_id).filterByAll();
}
},
_get_data: function (master, value) {
var data;
var options = value.options;
if (options) {
data = master._collectValues.call(options, "id", "value");
} else data = master.collectValues(value.columnId, value.collect);
return data;
}
};
datafilter.serverFilter = exports.extend({
$server: true,
_on_key_down: function (e) {
var id = this._comp_id,
code = e.which || e.keyCode; //ignore tab and navigation keys
if (code == 9 || code >= 33 && code <= 40) return;
if (this._filter_timer) window.clearTimeout(this._filter_timer);
this._filter_timer = window.setTimeout(function () {
$$(id).filterByAll();
}, datafilter.textWaitDelay);
}
}, datafilter.textFilter);
datafilter.serverSelectFilter = exports.extend({
$server: true,
_on_change: function () {
var id = this._comp_id;
$$(id).filterByAll();
}
}, datafilter.selectFilter);
datafilter.numberFilter = exports.extend({
init: function (config) {
config.prepare = function (value) {
var _this = this;
var equality = value.indexOf("=") != -1;
var intvalue = this.format(value);
if (intvalue === "") return "";
var compare;
if (value.indexOf(">") != -1) {
compare = this._greater;
} else if (value.indexOf("<") != -1) {
compare = this._lesser;
}
if (compare && equality) {
config.compare = function (a, b) {
return _this._equal(a, b) || compare(a, b);
};
} else {
config.compare = compare || this._equal;
}
return intvalue;
};
},
format: function (value) {
return value.replace(/[^\-.0-9]/g, "");
},
_greater: function (a, b) {
return a * 1 > b;
},
_lesser: function (a, b) {
return a !== "" && a * 1 < b;
},
_equal: function (a, b) {
return a !== "" && a * 1 == b;
}
}, datafilter.textFilter);
datafilter.dateFilter = exports.extend({
format: function (value) {
if (value === "") return "";
var date = new Date();
if (value.indexOf("today") != -1) {
date = wDate.dayStart(date);
} else if (value.indexOf("now") == -1) {
var parts = value.match(/[0-9]+/g);
if (!parts || !parts.length) return "";
if (parts.length < 3) {
parts.reverse();
date = new Date(parts[0], (parts[1] || 1) - 1, 1);
} else date = i18n.dateFormatDate(value.replace(/^[>< =]+/, ""));
}
return date.valueOf();
}
}, datafilter.numberFilter);
env.scrollSize = env.touch || env.$customScroll ? 0 : 17;
ready(function () {
var size = _detectScrollSize();
env.scrollSize = env.touch ? 0 : size;
});
function _detectScrollSize() {
var div = create("div");
div.className = "webix_skin_mark";
div.style.cssText = "position:absolute;left:-1000px;width:100px;padding:0px;margin:0px;min-height:100px;overflow-y:scroll;";
document.body.appendChild(div);
var width = div.offsetWidth - div.clientWidth;
var name = {
200: "flat",
210: "compact",
230: "contrast",
240: "material",
250: "mini"
}[Math.floor(div.offsetHeight / 10) * 10];
document.body.removeChild(div);
if (name) set$1(name);
if (env.$customScroll) return 0;
return width;
}
var fixed = false;
function _fixHeight() {
if (fixed) return;
addStyle("html, body{ height:100%; }");
document.body.className += " webix_full_screen";
Touch.limit(false);
fixed = true;
}
define("_fixHeight", _fixHeight);
ui.animate = animate$1;
ui.animateView = animateView;
ui.freeze = freeze;
ui.resize = resize;
ui.zIndex = zIndex;
ui.datafilter = datafilter;
ui.fullScreen = fullScreen;
/*German (Germany) locale*/
var de = {
groupDelimiter: ".",
groupSize: 3,
decimalDelimiter: ",",
decimalSize: 2,
dateFormat: "%d.%n.%Y",
timeFormat: "%H:%i",
longDateFormat: "%j. %F %Y",
fullDateFormat: "%j. %F %Y %H:%i",
am: null,
pm: null,
price: "{obj} €",
priceSettings: {
groupDelimiter: ".",
groupSize: 3,
decimalDelimiter: ",",
decimalSize: 2
},
calendar: {
monthFull: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
monthShort: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"],
dayFull: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
dayShort: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
hours: "Stunden",
minutes: "Minuten",
done: "Fertig",
clear: "Entfernen",
today: "Heute"
},
dataExport: {
page: "Seite",
of: "von"
},
PDFviewer: {
of: "von",
automaticZoom: "Automatisch Zoom",
actualSize: "Aktuelles Ausmaß",
pageFit: "Seite Ausmaß",
pageWidth: "Seite Breite",
pageHeight: "Seite Höhe",
enterPassword: "Passwort eingeben",
passwordError: "Falsches passwort"
},
aria: {
calendar: "Kalender",
increaseValue: "Wert erhöhen",
decreaseValue: "Wert verringern",
navMonth: ["Vorheriger Monat", "Nächsten Monat"],
navYear: ["Vorheriges Jahr", "Nächstes Jahr"],
navDecade: ["Zurück Jahrzehnt", "Als nächstes Jahrzehnt"],
dateFormat: "%j. %F %Y",
monthFormat: "%F %Y",
yearFormat: "%Y",
hourFormat: "Stunden: %H",
minuteFormat: "Minuten: %i",
removeItem: "Element entfernen",
pages: ["Erste Seite", "Vorherige Seite", "Folgeseite", "Letzte Seite"],
page: "Seite",
headermenu: "Titelmenü",
openGroup: "Öffnen Spaltengruppe ",
closeGroup: "Schließen Spaltengruppe ",
closeTab: "Tab schließen",
showTabs: "Weitere Tabs",
resetTreeMap: "Zurück zur ursprünglichen Ansicht",
navTreeMap: "Aufleveln",
nextTab: "Weiter tab",
prevTab: "Zurück tab",
multitextSection: "Element hinzufügen",
multitextextraSection: "Element entfernen",
showChart: "Chart anzeigen",
hideChart: "Chart verstecken",
resizeChart: "Chart Größe ändern"
},
richtext: {
underline: "Unterstreichen",
bold: "Fettgedruckt",
italic: "Kursiv"
},
combo: {
select: "Auswählen",
selectAll: "Alles auswählen",
unselectAll: "Alles widerrufen"
},
message: {
ok: "OK",
cancel: "Abbrechen"
},
comments: {
send: "Absenden",
confirmMessage: "Der Kommentar wird entfernt. Sind Sie sicher?",
edit: "Redigieren",
remove: "Löschen",
placeholder: "Geben Sie hier ein..",
moreComments: "Mehr Kommentare"
},
filter: {
less: "weniger",
lessOrEqual: "weniger oder gleich",
greater: "mehr",
greaterOrEqual: "größer oder gleich",
contains: "enthält",
notContains: "nicht enthält",
equal: "gleich",
notEqual: "ungleich",
beginsWith: "beginnt mit",
notBeginsWith: "nicht beginnt mit",
endsWith: "endet mit",
notEndsWith: "nicht endet mit",
between: "zwischen",
notBetween: "nicht zwischen"
},
timeboard: {
seconds: "Sekunden"
}
};
/*Spanish (Spain, International Sort) locale*/
var es = {
groupDelimiter: ".",
groupSize: 3,
decimalDelimiter: ",",
decimalSize: 2,
dateFormat: "%d/%n/%Y",
timeFormat: "%G:%i",
longDateFormat: "%d %F %Y",
fullDateFormat: "%d %F %Y %G:%i",
am: null,
pm: null,
price: "{obj} €",
priceSettings: {
groupDelimiter: ".",
groupSize: 3,
decimalDelimiter: ",",
decimalSize: 2
},
calendar: {
monthFull: ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
monthShort: ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"],
dayFull: ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"],
dayShort: ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"],
hours: "Horas",
minutes: "Minutos",
done: "Listo",
clear: "Reinicio",
today: "Hoy"
},
dataExport: {
page: "Página",
of: "de"
},
PDFviewer: {
of: "de",
automaticZoom: "Zoom automático",
actualSize: "Tamaño real",
pageFit: "Tamaño de página",
pageWidth: "Ancho de página",
pageHeight: "Altura de la página",
enterPassword: "Introduzca la contraseña",
passwordError: "Contraseña incorrecta"
},
aria: {
calendar: "Сalendario",
increaseValue: "Aumentar el valor",
decreaseValue: "Disminuye el valor",
navMonth: ["Mes anterior", "Próximo mes"],
navYear: ["Año anterior", "Próximo año"],
navDecade: ["Década anterior", "Próxima década"],
dateFormat: "%d %F %Y",
monthFormat: "%F %Y",
yearFormat: "%Y",
hourFormat: "Horas: %G",
minuteFormat: "Minutos: %i",
removeItem: "Retire el elemento",
pages: ["Primera página", "Pagina anterior", "Siguiente página", "Última página"],
page: "Página",
headermenu: "Menú de títulos",
openGroup: "Grupo de columnas abiertas",
closeGroup: "Primer grupo de columnas",
closeTab: "Cerrar tab",
showTabs: "Mostrar más tabs",
resetTreeMap: "Volver a la vista original",
navTreeMap: "Elevar a mismo nivel",
nextTab: "Siguiente tab",
prevTab: "Tab anterior",
multitextSection: "Añadir elemento",
multitextextraSection: "Retire el elemento",
showChart: "Espectáculo chart",
hideChart: "Esconder chart",
resizeChart: "Cambiar el tamaño el chart"
},
richtext: {
underline: "Subrayar",
bold: "Negrita",
italic: "Itálico"
},
combo: {
select: "Seleccionar",
selectAll: "Seleccionar todo",
unselectAll: "Deselecciona todo"
},
message: {
ok: "OK",
cancel: "Cancelar"
},
comments: {
send: "Enviar",
confirmMessage: "El comentario será eliminado. Estás seguro?",
edit: "Corregir",
remove: "Suprimir",
placeholder: "Escriba aquí..",
moreComments: "Más comentarios"
},
filter: {
less: "menos",
lessOrEqual: "menor o igual",
greater: "mayor",
greaterOrEqual: "mayor o igual",
contains: "contiene",
notContains: "not contiene",
equal: "igual",
notEqual: "no es igual",
beginsWith: "comienza con",
notBeginsWith: "no comienza con",
endsWith: "termina con",
notEndsWith: "no termina con",
between: "entre",
notBetween: "no entre"
},
timeboard: {
seconds: "segundos"
}
};
var fr = {
groupDelimiter: " ",
groupSize: 3,
decimalDelimiter: ",",
decimalSize: 2,
dateFormat: "%d/%m/%Y",
timeFormat: "%H:%i",
longDateFormat: "%d %F %Y",
fullDateFormat: "%d.%m.%Y %H:%i",
price: "{obj} €",
priceSettings: null,
//use number defaults
calendar: {
monthFull: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"],
monthShort: ["Jan", "Fév", "Mar", "Avr", "Mai", "Juin", "Juil", "Aôu", "Sep", "Oct", "Nov", "Déc"],
dayFull: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"],
dayShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"],
hours: "Heures",
minutes: "Minutes",
done: "Fini",
clear: "Effacer",
today: "Aujourd'hui"
},
dataExport: {
page: "Page",
of: "sur"
},
PDFviewer: {
of: "sur",
automaticZoom: "Zoom automatique",
actualSize: "Taille actuelle",
pageFit: "Taille de la page",
pageWidth: "Largeur de la page",
pageHeight: "Hauteur de page",
enterPassword: "Entrez le mot de passe",
passwordError: "Mauvais mot de passe"
},
aria: {
calendar: "Сalendrier",
increaseValue: "Augmenter la valeur",
decreaseValue: "Diminution de la valeur",
navMonth: ["Le mois précédent", "Le mois prochain"],
navYear: ["Année précédente", "L'année prochaine"],
navDecade: ["Décennie précédente", "Suivant décennie"],
dateFormat: "%d %F %Y",
monthFormat: "%F %Y",
yearFormat: "%Y",
hourFormat: "Heures: %H",
minuteFormat: "Minutes: %i",
removeItem: "Retirer l'élément",
pages: ["Première page", "Page précédente", "Page suivante", "Dernière page"],
page: "Page",
headermenu: "Menu de titre",
openGroup: "Ouvrir groupe de colonnes ",
closeGroup: "Fermer groupe de colonnes",
closeTab: "Fermer tab",
showTabs: "Montrer plus tabs",
resetTreeMap: "Revenir à la vue originale",
navTreeMap: "Niveau supérieur",
nextTab: "Prochain tab",
prevTab: "Précédent tab",
multitextSection: "Ajouter l'élément",
multitextextraSection: "Retirer l'élément",
showChart: "Montrer chart",
hideChart: "Cacher chart",
resizeChart: "Redimensionner chart"
},
richtext: {
underline: "Souligner",
bold: "Gras",
italic: "Italique"
},
combo: {
select: "Sélectionner",
selectAll: "Tout sélectionner",
unselectAll: "Tout déselectionner"
},
message: {
ok: "OK",
cancel: "Annuler"
},
comments: {
send: "Envoyer",
confirmMessage: "Le commentaire sera supprimé. Êtes-vous sûr?",
edit: "Modifier",
remove: "Effacer",
placeholder: "Écrivez ici..",
moreComments: "Plus de commentaires"
},
filter: {
less: "moins",
lessOrEqual: "inférieur ou égal",
greater: "plus grand",
greaterOrEqual: "supérieur ou égal",
contains: "contient",
notContains: "ne contient",
equal: "égal",
notEqual: "pas égal",
beginsWith: "commence par",
notBeginsWith: "ne commence par",
endsWith: "se termine par",
notEndsWith: "pas se termine par",
between: "entre",
notBetween: "pas entre"
},
timeboard: {
seconds: "secondes"
}
};
/*Italian (Italy) locale*/
var it = {
groupDelimiter: ".",
groupSize: 3,
decimalDelimiter: ",",
decimalSize: 2,
dateFormat: "%d/%m/%Y",
timeFormat: "%H:%i",
longDateFormat: "%j %F %Y",
fullDateFormat: "%j %F %Y %H:%i",
am: null,
pm: null,
price: "€ {obj}",
priceSettings: {
groupDelimiter: ".",
groupSize: 3,
decimalDelimiter: ",",
decimalSize: 2
},
calendar: {
monthFull: ["gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"],
monthShort: ["gen", "feb", "mar", "apr", "mag", "giu", "lug", "ago", "set", "ott", "nov", "dic"],
dayFull: ["domenica", "lunedì", "martedì", "mercoledì", "giovedì", "venerdì", "sabato"],
dayShort: ["dom", "lun", "mar", "mer", "gio", "ven", "sab"],
hours: "Orario",
minutes: "Minuti",
done: "Pronto",
clear: "Pulisci",
today: "Oggi"
},
dataExport: {
page: "Pagina",
of: "di"
},
PDFviewer: {
of: "di",
automaticZoom: "Zoom automatico",
actualSize: "Dimensione reale",
pageFit: "Dimensioni della pagina",
pageWidth: "Larghezza della pagina",
pageHeight: "Altezza della pagina",
enterPassword: "Inserisci la password",
passwordError: "Password errata"
},
aria: {
calendar: "Calendario",
increaseValue: "Aumenta il valore",
decreaseValue: "Riduci il valore",
navMonth: ["Il mese scorso", "Il prossimo mese"],
navYear: ["L'anno scorso", "L'anno prossimo"],
navDecade: ["Decennio precedente", "Prossimo decennio"],
dateFormat: "%j %F %Y",
monthFormat: "%F %Y",
yearFormat: "%Y",
hourFormat: "Orario: %H",
minuteFormat: "Minuti: %i",
removeItem: "Rimuovere l'elemento",
pages: ["Prima pagina", "Pagina precedente", "Pagina successiva", "Ultima pagina"],
page: "Pagina",
headermenu: "Menu del titolo",
openGroup: "Aperto gruppo di colonne",
closeGroup: "Chiudi gruppo di colonne",
closeTab: "Chiudi tab",
showTabs: "Mostra più tabs",
resetTreeMap: "Tornare alla vista originale",
navTreeMap: "Livello superiore",
nextTab: "Tab successivo",
prevTab: "Tab precedente",
multitextSection: "Aggiungi elemento",
multitextextraSection: "Rimuovere l'elemento",
showChart: "Mostrare grafico",
hideChart: "Nascondere grafico",
resizeChart: "Ridimensionare grafico"
},
richtext: {
underline: "Sottolineare",
bold: "Grassetto",
italic: "Corsivo"
},
combo: {
select: "Selezionare",
selectAll: "Seleziona tutto",
unselectAll: "Deseleziona tutto"
},
message: {
ok: "OK",
cancel: "Annullare"
},
comments: {
send: "Inviare",
confirmMessage: "Il commento verrà rimosso. Sei sicuro?",
edit: "Correggere",
remove: "Elimina",
placeholder: "Digitare qui..",
moreComments: "Altri commenti"
},
filter: {
less: "meno",
lessOrEqual: "minore o uguale",
greater: "maggiore",
greaterOrEqual: "maggiore o uguale",
contains: "contiene",
notContains: "non contiene",
equal: "uguale",
notEqual: "non uguale",
beginsWith: "inizia con",
notBeginsWith: "non inizia con",
endsWith: "finisce con",
notEndsWith: "non termina con",
between: "tra",
notBetween: "non tra"
},
timeboard: {
seconds: "secondi"
}
};
var ja = {
groupDelimiter: ",",
groupSize: 3,
decimalDelimiter: ".",
decimalSize: 2,
dateFormat: "%Y.%m.%d",
timeFormat: "%H:%i",
longDateFormat: "%Y年%m月%d日",
fullDateFormat: "%Y.%m.%d %H:%i",
price: "¥{obj}",
priceSettings: {
groupSize: 3,
groupDelimiter: ",",
decimalDelimiter: "",
decimalSize: 0
},
calendar: {
monthFull: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
monthShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
dayFull: ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"],
dayShort: ["日", "月", "火", "水", "木", "金", "土"],
hours: "営業時間",
minutes: "分",
done: "レディー",
clear: "削除する",
today: "今日"
},
dataExport: {
page: "ページ",
of: "から"
},
PDFviewer: {
of: "から",
automaticZoom: "自動ズーム",
actualSize: "実サイズ",
pageFit: "ページサイズ",
pageWidth: "ページ幅",
pageHeight: "ページの高さ",
enterPassword: "パスワードを入力する",
passwordError: "間違ったパスワード"
},
aria: {
calendar: "カレンダー",
increaseValue: "増加値",
decreaseValue: "数字を小さく",
navMonth: ["前の月", "来月"],
navYear: ["前年", "来年"],
navDecade: ["前の十年", "次の10年"],
dateFormat: "%Y年%m月%d日",
monthFormat: "%Y年%m月",
yearFormat: "%Y年",
hourFormat: "営業時間: %H",
minuteFormat: "分: %i",
removeItem: "要素を削除します",
pages: ["一ページ目", "前のページ", "次のページ", "最後のページ"],
page: "ページ",
headermenu: "ヘッダメニュー",
openGroup: "オープン列グループ",
closeGroup: "閉じる列グループ",
closeTab: "タブを閉じます",
showTabs: "複数のタブを表示します",
resetTreeMap: "元の表示に戻ります",
navTreeMap: "レベルパック",
nextTab: "次のタブ",
prevTab: "前のタブ",
multitextSection: "要素を追加します。",
multitextextraSection: "要素を削除します",
showChart: "靴チャート",
hideChart: "隠すチャート",
resizeChart: "グラフのサイズを変更"
},
richtext: {
underline: "アンダーライン",
bold: "大胆な",
italic: "イタリック"
},
combo: {
select: "選択する",
selectAll: "すべて選択",
unselectAll: "すべての選択を解除する"
},
message: {
ok: "OK",
cancel: "取り消す"
},
comments: {
send: "送信",
confirmMessage: "コメントは削除されます. 本気ですか?",
edit: "編集",
remove: "削除",
placeholder: "ここに入力..",
moreComments: "その他のコメント"
},
filter: {
less: "レス",
lessOrEqual: "以下",
greater: "大きいです",
greaterOrEqual: "以上",
contains: "含まれています",
notContains: "含まれていません",
equal: "等しいです",
notEqual: "等しくありません",
beginsWith: "で始まります",
notBeginsWith: "ないで始まります",
endsWith: "で終わります",
notEndsWith: "で終わりではありません",
between: "間に",
notBetween: "いない間"
},
timeboard: {
seconds: "秒"
}
};
var pt = {
groupDelimiter: ".",
groupSize: 3,
decimalDelimiter: ",",
decimalSize: 2,
dateFormat: "%d/%m/%Y",
timeFormat: "%G:%i",
longDateFormat: "%d de %F de %Y",
fullDateFormat: "%d de %F de %Y %G:%i",
am: null,
pm: null,
price: "R$ {obj}",
priceSettings: {
groupDelimiter: ".",
groupSize: 3,
decimalDelimiter: ",",
decimalSize: 2
},
fileSize: ["b", "Kb", "Mb", "Gb", "Tb", "Pb", "Eb"],
calendar: {
monthFull: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
monthShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
dayFull: ["Domingo", "Segunda-Feira", "Terça-Feira", "Quarta-Feira", "Quinta-Feira", "Sexta-Feira", "Sábado"],
dayShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
hours: "Horas",
minutes: "Minutos",
done: "Feito",
clear: "Limpar",
today: "Hoje"
},
dataExport: {
page: "Página",
of: "de"
},
PDFviewer: {
of: "de",
automaticZoom: "Zoom automático",
actualSize: "Tamanho atual",
pageFit: "Tamanho da página",
pageWidth: "Largura da página",
pageHeight: "Altura da página",
enterPassword: "Digite a senha",
passwordError: "Senha incorreta"
},
aria: {
calendar: "Calendário",
increaseValue: "Aumentar o valor",
decreaseValue: "Diminuir o valor",
navMonth: ["Mês anterior", "Próximo mês"],
navYear: ["Ano anterior", "Próximo ano"],
navDecade: ["Década anterior", "Próxima década"],
dateFormat: "%d de %F de %Y",
monthFormat: "%F de %Y",
yearFormat: "%Y",
hourFormat: "Horas: %G",
minuteFormat: "Minutos: %i",
removeItem: "Remover elemento",
pages: ["Primeira página", "Página anterior", "Próxima página", "Última página"],
page: "Página",
headermenu: "Menu de títulos",
openGroup: "Grupo coluna aberta",
closeGroup: "Fechar grupo de colunas",
closeTab: "Fechar tab",
showTabs: "Mostre mais tabs",
resetTreeMap: "Мoltar à vista original",
navTreeMap: "Upar",
nextTab: "Próximo tab",
prevTab: "Anterior tab",
multitextSection: "Adicionar elemento",
multitextextraSection: "Remover elemento",
showChart: "Exposição chart",
hideChart: "Esconder chart",
resizeChart: "Redimensionar chart"
},
richtext: {
underline: "Sublinhado",
bold: "Negrito",
italic: "itálico"
},
combo: {
select: "Selecionar",
selectAll: "Selecionar tudo",
unselectAll: "Desmarque todos"
},
message: {
ok: "OK",
cancel: "Cancelar"
},
comments: {
send: "Enviar",
confirmMessage: "Comentário será removido. Você tem certeza?",
edit: "Editar",
remove: "Excluir",
placeholder: "Digite aqui..",
moreComments: "Mais comentários"
},
filter: {
less: "menos",
lessOrEqual: "menor ou igual",
greater: "maior",
greaterOrEqual: "maior ou igual",
contains: "contém",
notContains: "não contém",
equal: "igual",
notEqual: "não é igual",
beginsWith: "começa com",
notBeginsWith: "não começa com",
endsWith: "termina com",
notEndsWith: "não termina com",
between: "entre",
notBetween: "não entre"
},
timeboard: {
seconds: "segundos"
}
};
/*Chinese (Simplified, PRC) locale*/
var zh = {
groupDelimiter: ",",
groupSize: 3,
decimalDelimiter: ".",
decimalSize: 2,
dateFormat: "%Y/%m/%j",
timeFormat: "%G:%i",
longDateFormat: "%Y'年'%m'月'%j'日'",
fullDateFormat: "%Y'年'%m'月'%j'日' %G:%i",
am: ["上午", "上午"],
pm: ["下午", "下午"],
price: "¥{obj}",
priceSettings: {
groupDelimiter: ",",
groupSize: 3,
decimalDelimiter: ".",
decimalSize: 2
},
calendar: {
monthFull: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
monthShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
dayFull: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
dayShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
hours: "小时",
minutes: "分钟",
done: "完成",
clear: "清除",
today: "今天"
},
dataExport: {
page: "页",
of: "从"
},
PDFviewer: {
of: "从",
automaticZoom: "自动设置页面大小",
actualSize: "实际尺寸",
pageFit: "页面大小",
pageWidth: "页面宽度",
pageHeight: "页面高度",
enterPassword: "输入密码",
passwordError: "密码错误"
},
aria: {
calendar: "日历",
increaseValue: "增加值",
decreaseValue: "减少值",
navMonth: ["上个月", "下个月"],
navYear: ["去年", "明年"],
navDecade: ["过去十年", "下个十年"],
dateFormat: "%Y'年'%m'月'%j'日'",
monthFormat: "%Y'年'%m'月",
yearFormat: "%Y'年",
hourFormat: "小时: %G",
minuteFormat: "分钟: %i",
removeItem: "删除项",
pages: ["第一页", "上一页", "下一页", "最后一页"],
page: "页",
headermenu: "标题菜单",
openGroup: "打开列分组",
closeGroup: "关闭列分组",
closeTab: "关闭标签",
showTabs: "更多标签",
resetTreeMap: "重置视图",
navTreeMap: "上一级",
nextTab: "下一个标签",
prevTab: "前一个标签",
multitextSection: "添加项",
multitextextraSection: "删除项",
showChart: "显示图表",
hideChart: "隐藏图表",
resizeChart: "调整图表大小"
},
richtext: {
underline: "下划线",
bold: "粗体",
italic: "斜体"
},
combo: {
select: "选择",
selectAll: "全选",
unselectAll: "取消全选"
},
message: {
ok: "确定",
cancel: "取消"
},
comments: {
send: "发送",
confirmMessage: "你确定要删除评论吗?",
edit: "编辑",
remove: "删除",
placeholder: "在此输入..",
moreComments: "更多评论"
},
filter: {
less: "小于",
lessOrEqual: "少于等于",
greater: "大于",
greaterOrEqual: "大于等于",
contains: "包含",
notContains: "不包含",
equal: "等于",
notEqual: "不等于",
beginsWith: "开始于",
notBeginsWith: "不以开始",
endsWith: "结束",
notEndsWith: "不以结束",
between: "之间",
notBetween: "不介于"
},
timeboard: {
seconds: "秒"
}
};
var ru = {
groupDelimiter: " ",
groupSize: 3,
decimalDelimiter: ",",
decimalSize: 2,
dateFormat: "%d.%m.%Y",
timeFormat: "%H:%i",
longDateFormat: "%d %F %Y",
fullDateFormat: "%d.%m.%Y %H:%i",
price: "{obj} руб.",
priceSettings: null,
//use number defaults
calendar: {
monthFull: ["Январь", "Февраль", "Март", "Апрель", "Maй", "Июнь", "Июль", "Август", "Сентябрь", "Oктябрь", "Ноябрь", "Декабрь"],
monthShort: ["Янв", "Фев", "Maр", "Aпр", "Maй", "Июн", "Июл", "Aвг", "Сен", "Окт", "Ноя", "Дек"],
dayFull: ["Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"],
dayShort: ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"],
hours: "Часы",
minutes: "Минуты",
done: "Гoтовo",
clear: "Очистить",
today: "Сегодня"
},
dataExport: {
page: "Страница",
of: "из"
},
PDFviewer: {
of: "из",
automaticZoom: "Автоматический зум",
actualSize: "Настоящий размер",
pageFit: "Размер страницы",
pageWidth: "Ширина страницы",
pageHeight: "Высота страницы",
enterPassword: "Введите пароль",
passwordError: "Неверный пароль"
},
aria: {
calendar: "Календарь",
increaseValue: "Увеличить значение",
decreaseValue: "Уменьшить значение",
navMonth: ["Предыдущий месяц", "Следующий месяц"],
navYear: ["Предыдущий год", "Следующий год"],
navDecade: ["Предыдущие десять лет", "Следующие десять лет"],
dateFormat: "%d %F %Y",
monthFormat: "%F %Y",
yearFormat: "%Y",
hourFormat: "Часы: %H",
minuteFormat: "Минуты: %i",
removeItem: "Удалить элемент",
pages: ["Первая страница", "Предыдущая страница", "Следующая страница", "Последняя страница"],
page: "Страница",
headermenu: "Меню шапки таблицы",
openGroup: "Развернуть группу столбцов",
closeGroup: "Свернуть группу столбцов",
closeTab: "Закрыть вкладку",
showTabs: "Показать больше вкладок",
resetTreeMap: "Вернуться к первоначальному представлению",
navTreeMap: "Перейти на уровень выше",
nextTab: "Следующая вкладка",
prevTab: "Предыдущая вкладка",
multitextSection: "Добавить элемент",
multitextextraSection: "Удалить элемент",
showChart: "Показать чарт",
hideChart: "Спрятать чарт",
resizeChart: "Изменить размер чарта"
},
richtext: {
underline: "Подчеркивание",
bold: "Жирный",
italic: "Курсив"
},
combo: {
select: "Выбрать",
selectAll: "Выбрать все",
unselectAll: "Сброс выбора"
},
message: {
ok: "OK",
cancel: "Отмена"
},
comments: {
send: "Отправить",
confirmMessage: "Комментарий будет удален. Вы уверены?",
edit: "Редактировать",
remove: "Удалить",
placeholder: "Введите текст..",
moreComments: "Больше комментариев"
},
filter: {
less: "меньше",
lessOrEqual: "меньше или равно",
greater: "больше",
greaterOrEqual: "больше или равно",
contains: "содержит",
notContains: "не содержит",
equal: "равно",
notEqual: "не равно",
beginsWith: "начинается с",
notBeginsWith: "не начинается с",
endsWith: "заканчиватся",
notEndsWith: "не заканчиватся",
between: "между",
notBetween: "не между"
},
timeboard: {
seconds: "Секунды"
}
};
var be = {
groupDelimiter: " ",
groupSize: 3,
decimalDelimiter: ",",
decimalSize: 2,
dateFormat: "%d.%m.%Y",
timeFormat: "%H:%i",
longDateFormat: "%d %F %Y",
fullDateFormat: "%d.%m.%Y %H:%i",
price: "{obj} руб.",
priceSettings: {
groupSize: 3,
groupDelimiter: " ",
decimalDelimiter: "",
decimalSize: 0
},
calendar: {
monthFull: ["Студзень", "Люты", "Сакавік", "Красавік", "Травень", "Чэрвень", "Ліпень", "Жнівень", "Верасень", "Кастрычнік", "Лістапад", "Снежань"],
monthShort: ["Студз", "Лют", "Сак", "Крас", "Трав", "Чэр", "Ліп", "Жнів", "Вер", "Каст", "Ліст", "Снеж"],
dayFull: ["Нядзеля", "Панядзелак", "Аўторак", "Серада", "Чацвер", "Пятніца", "Субота"],
dayShort: ["Нд", "Пн", "Аўт", "Ср", "Чцв", "Пт", "Сб"],
hours: "Гадзіны",
minutes: "Хвіліны",
done: "Гатова",
today: "Cёння",
clear: "Ачысціць"
},
dataExport: {
page: "Старонка",
of: "з"
},
PDFviewer: {
of: "з",
automaticZoom: "Аўтаматычны зум",
actualSize: "Сапраўдны памер",
pageFit: "Памер старонкі",
pageWidth: "Шырыня старонкі",
pageHeight: "Вышыня старонкі",
enterPassword: "Увядзіце пароль",
passwordError: "Няправільны пароль"
},
aria: {
calendar: "Каляндар",
increaseValue: "Павялічыць значэнне",
decreaseValue: "Паменшыць значэнне",
navMonth: ["Папярэдні месяц", "Наступны месяц"],
navYear: ["Папярэдні год", "Наступны год"],
navDecade: ["Папярэднія дзесяць год", "Наступныя дзесяць год"],
dateFormat: "%d %F %Y",
monthFormat: "%F %Y",
yearFormat: "%Y",
hourFormat: "Hours: %h",
minuteFormat: "Гадзіны: %i",
removeItem: "Прыбраць элемент",
pages: ["Першая старонка", "Папярэдняя старонка", "Наступная старонка", "Апошняя старонка"],
page: "Старонка",
headermenu: "Меню загалоўка",
openGroup: "Адкрыць групу слупкоў",
closeGroup: "Закрыць групу слупкоў",
closeTab: "Закрыць укладку",
showTabs: "Паказаць больш укладак",
resetTreeMap: "Вярнуцца да першапачатковага выгляду",
navTreeMap: "Падняцца на ўзровень вышэй",
nextTab: "Наступная ўкладка",
prevTab: "Папярэдняя ўкладка",
multitextSection: "Дадаць элемент",
multitextextraSection: "Прыбраць элемент",
showChart: "Паказаць графік",
hideChart: "Схаваць графік",
resizeChart: "Змяніць памер графіка"
},
richtext: {
underline: "Падкрэсліванне",
bold: "Паўтлусты",
italic: "Курсіў"
},
combo: {
select: "Абраць",
selectAll: "Абраць усё",
unselectAll: "Ачысціць ўсе"
},
message: {
ok: "ОК",
cancel: "Адмена"
},
comments: {
send: "Даслаць",
confirmMessage: "Каментарый будзе выдалены. Вы ўпэўнены?",
edit: "Рэдагаваць",
remove: "Выдаліць",
placeholder: "Пішыце тут..",
moreComments: "Больш каментарыяў"
},
filter: {
less: "менш",
lessOrEqual: "менш або роўна",
greater: "больш",
greaterOrEqual: "больш або роўна",
contains: "змяшчае",
notContains: "не змяшчае",
equal: "роўныя",
notEqual: "не роўныя",
beginsWith: "пачынаецца з",
notBeginsWith: "не пачынаецца з",
endsWith: "заканчваецца",
notEndsWith: "не сканчаецца",
between: "паміж",
notBetween: "не паміж"
},
timeboard: {
seconds: "Секунды"
}
};
// en-EN locale is bundled by default
i18n.locales["de-DE"] = de; // spain
i18n.locales["es-ES"] = es; // france
i18n.locales["fr-FR"] = fr; // italy
i18n.locales["it-IT"] = it; // japan
i18n.locales["ja-JP"] = ja; // portuguese
i18n.locales["pt-BR"] = pt; // chinese
i18n.locales["zh-CN"] = zh; // russian
i18n.locales["ru-RU"] = ru; // belarus
i18n.locales["be-BY"] = be;
var api$4 = {
name: "baselayout",
restore: function (state$$1, factory, configOnly) {
var out = this._restore(copy(state$$1), factory);
if (configOnly) return out;else ui(out.cols || out.rows, this);
},
_restore: function (state$$1, factory) {
if (state$$1.$layout) {
var sub = state$$1.cols || state$$1.rows;
for (var i = 0; i < sub.length; i++) {
sub[i] = this._restore(sub[i], factory);
}
} else {
return factory.call(this, state$$1);
}
return state$$1;
},
serialize: function (serializer) {
var out = [];
var childs = this.getChildViews();
for (var i = 0; i < childs.length; i++) {
var sub = childs[i];
if (sub.movePortlet) {
var child = sub.getChildViews();
out.push(serializer.call(this, child[child.length - 1]));
} else if (sub.serialize) {
// some kind of layout
out.push(sub.serialize(serializer, true));
} else {
// leaf view
out.push(serializer.call(this, sub));
}
}
var obj = {
$layout: true,
type: this.config.type
};
if (this.config.rows) obj.rows = out;else obj.cols = out;
return obj;
},
$init: function (config) {
this.$ready.push(this._parse_cells);
this._dataobj = this._contentobj;
this._layout_sizes = [];
this._responsive = [];
this._padding = {
top: 0,
left: 0,
right: 0,
bottom: 0
};
if (config.$topView) {
config.borderless = true;
config._inner = {
top: true,
left: true,
bottom: true,
right: true
};
}
if (config.isolate) exports.extend(this, IdSpace);
},
rows_setter: function (value) {
this._vertical_orientation = 1;
this._collection = value;
return true;
},
cols_setter: function (value) {
this._vertical_orientation = 0;
this.$view.style.whiteSpace = "nowrap";
this._collection = value;
return true;
},
_remove: function (view) {
var index$$1 = _power_array.find.call(this._cells, view);
if (this._beforeRemoveView) this._beforeRemoveView(index$$1);
_power_array.removeAt.call(this._cells, index$$1);
this._fix_hidden_cells(true);
},
_fix_hidden_cells: function (resize$$1) {
this._hiddencells = 0;
for (var i = 0; i < this._cells.length; i++) {
var cell = this._cells[i];
if (cell._settings.hidden || cell.$nospace) this._hiddencells++;
}
if (resize$$1) this.resizeChildren(true);
},
_replace: function (new_view, target_id) {
if (isUndefined(target_id)) {
for (var i = 0; i < this._cells.length; i++) {
this._cells[i].destructor();
}
this._collection = new_view;
this._parse_cells();
} else {
var source;
if (typeof target_id == "number") {
if (target_id < 0 || target_id > this._cells.length) target_id = this._cells.length;
_power_array.insertAt.call(this._cells, new_view, target_id);
if (!new_view._settings.hidden) this._insertBeforeView(new_view, this._cells[target_id]);
} else {
source = $$(target_id);
target_id = _power_array.find.call(this._cells, source);
assert(target_id != -1, "Attempt to replace the non-existing view");
if (!new_view._settings.hidden) this._insertBeforeView(new_view, source);
source.destructor();
this._cells[target_id] = new_view;
}
if (!this._vertical_orientation) this._fix_vertical_layout(new_view);
}
this._fix_hidden_cells(true);
var form = this.elements ? this : this.getFormView();
if (form && !this._fill_data) form._recollect_elements();
callEvent("onReconstruct", [this]);
},
_fix_vertical_layout: function (cell) {
cell._viewobj.style.display = "inline-block";
cell._viewobj.style.verticalAlign = "top";
},
addView: function (view, index$$1) {
if (isUndefined(index$$1)) index$$1 = this._cells.length;
var top = this.$$ ? this : this.getTopParentView();
state._parent_cell = this;
var newui = top && top.ui ? top.ui(view, this, index$$1) : ui(view, this, index$$1);
state._parent_cell = null;
return newui._settings.id;
},
removeView: function (id) {
var view;
if (_typeof(id) != "object") view = $$(id) || (this.$$ ? this.$$(id) : null);else view = id;
var target = _power_array.find.call(this._cells, view);
if (target >= 0) {
if (this._beforeRemoveView) this._beforeRemoveView(target, view);
var form = this.elements ? this : this.getFormView();
this._cells.splice(target, 1);
if (form) _each(view, function (sub) {
if (sub.name) delete form.getCleanValues()[sub.config.name];
}, form, true);
view.destructor();
this._fix_hidden_cells(true);
if (form) form._recollect_elements();
} else assert(false, "Attemp to remove not existing view: " + id);
callEvent("onReconstruct", [this]);
},
reconstruct: function () {
this._hiddencells = 0;
this._replace(this._collection);
},
_hide: function (obj, settings, silent) {
if (obj._settings.hidden) return;
obj._settings.hidden = true;
remove(obj._viewobj);
this._hiddencells++;
if (!silent && !state._ui_creation) this.resizeChildren(true);
},
_signal_hidden_cells: function (view) {
if (view.callEvent) view.callEvent("onViewShow", []);
},
resizeChildren: function () {
if (state._freeze_resize) return;
if (this._layout_sizes) {
var parent = this.getParentView();
if (parent) {
if (parent.resizeChildren) return parent.resizeChildren();else return parent.resize();
}
var sizes = this.$getSize(0, 0);
var x, y, nx, ny;
nx = x = this._layout_sizes[0] || 0;
ny = y = this._layout_sizes[1] || 0; //for auto-fill content, use adjust strategy
if ((sizes[1] >= 100000 || sizes[3] >= 100000) && this._viewobj.parentNode) {
//in hidden container adjust doesn't work, so fallback to last known size
//also, ensure that min-size is not violated
nx = x = Math.max(sizes[0], this._settings.width || this._viewobj.parentNode.offsetWidth || x || 0);
ny = y = Math.max(sizes[2], this._settings.height || this._viewobj.parentNode.offsetHeight || y || 0);
}
if (!parent) {
//minWidth
if (sizes[0] > x) nx = sizes[0]; //minHeight
if (sizes[2] > y) ny = sizes[2];
var fullscreen = this._viewobj.parentNode == document.body && !this.setPosition; //maxWidth rule
if (!fullscreen && x > sizes[1]) nx = sizes[1]; //maxHeight rule
if (!fullscreen && y > sizes[3]) ny = sizes[3];
this.$setSize(nx, ny);
} else this._set_child_size(x, y);
if (state._responsive_exception) {
state._responsive_exception = false;
this.resizeChildren();
}
callEvent("onResize", []);
}
},
getChildViews: function () {
return this._cells;
},
index: function (obj) {
if (obj._settings) obj = obj._settings.id;
for (var i = 0; i < this._cells.length; i++) {
if (this._cells[i]._settings.id == obj) return i;
}
return -1;
},
_insertBeforeView: function (view, before) {
if (before) {
if (before._settings.hidden || view === before) {
//index of sibling cell, next to which new item will appear
var index$$1 = this.index(before) + 1; //locate nearest visible cell
while (this._cells[index$$1] && this._cells[index$$1]._settings.hidden) {
index$$1++;
}
before = this._cells[index$$1] ? this._cells[index$$1]._viewobj : null;
} else {
before = before._viewobj;
}
}
insertBefore(view._viewobj, before, this._dataobj || this._viewobj);
},
_show: function (obj, settings, silent) {
if (!obj._settings.hidden) return;
this._insertBeforeView(obj, obj);
obj._settings.hidden = false;
this._hiddencells--;
if (!silent) {
this.resizeChildren(true);
if (obj.refresh) obj.refresh();
}
if (obj.callEvent) {
obj.callEvent("onViewShow", []);
_each(obj, this._signal_hidden_cells);
}
},
showBatch: function (name, mode) {
var preserve = typeof mode != "undefined";
mode = mode !== false;
if (!preserve) {
if (this._settings.visibleBatch == name) return;
this._settings.visibleBatch = name;
} else this._settings.visibleBatch = "";
var show = [];
for (var i = 0; i < this._cells.length; i++) {
if (!this._cells[i]._settings.batch && !this._cells[i]._settings.hidden) show.push(this._cells[i]);else if (this._cells[i]._settings.batch == name) {
if (mode) show.push(this._cells[i]);else this._hide(this._cells[i], null, true);
} else if (!preserve) this._hide(this._cells[i], null, true);
}
for (var _i = 0; _i < show.length; _i++) {
this._show(show[_i], null, true);
show[_i]._render_hidden_views();
}
this.resizeChildren(true);
},
_parse_cells: function (collection) {
this._cells = [];
assert(collection, this.name + " was incorrectly defined. <br><br> You have missed rows|cols|cells|elements collection");
for (var i = 0; i < collection.length; i++) {
state._parent_cell = this;
if (!collection[i]._inner) collection[i].borderless = true;
this._cells[i] = ui._view(collection[i], this);
if (!this._vertical_orientation) this._fix_vertical_layout(this._cells[i]);
if (this._settings.visibleBatch && this._settings.visibleBatch != this._cells[i]._settings.batch && this._cells[i]._settings.batch) {
this._cells[i]._settings.hidden = true;
}
if (!this._cells[i]._settings.hidden) {
(this._dataobj || this._contentobj).appendChild(this._cells[i]._viewobj);
}
}
this._fix_hidden_cells();
if (this._parse_cells_ext_end) this._parse_cells_ext_end(collection);
},
_fix_container_borders: function (style, inner) {
if (inner.top) style.borderTopWidth = "0px";
if (inner.left) style.borderLeftWidth = "0px";
if (inner.right) style.borderRightWidth = "0px";
if (inner.bottom) style.borderBottomWidth = "0px";
},
_bubble_size: function (prop, size, vertical) {
if (this._vertical_orientation != vertical) for (var i = 0; i < this._cells.length; i++) {
this._cells[i]._settings[prop] = size;
if (this._cells[i]._bubble_size) this._cells[i]._bubble_size(prop, size, vertical);
}
},
$getSize: function (dx, dy) {
debug_size_box_start(this, true);
var minWidth = 0;
var maxWidth = 100000;
var maxHeight = 100000;
var minHeight = 0;
if (this._vertical_orientation) maxHeight = 0;else maxWidth = 0;
var fixed = 0;
var fixed_count = 0;
var gravity = 0;
this._sizes = [];
for (var i = 0; i < this._cells.length; i++) {
//ignore hidden cells
if (this._cells[i]._settings.hidden) continue;
var sizes = this._sizes[i] = this._cells[i].$getSize(0, 0);
if (this._cells[i].$nospace) {
fixed_count++;
continue;
}
if (this._vertical_orientation) {
//take max minSize value
if (sizes[0] > minWidth) minWidth = sizes[0]; //take min maxSize value
if (sizes[1] < maxWidth) maxWidth = sizes[1];
minHeight += sizes[2];
maxHeight += sizes[3];
if (sizes[2] == sizes[3] && sizes[2] != -1) {
fixed += sizes[2];
fixed_count++;
} else gravity += sizes[4];
} else {
//take max minSize value
if (sizes[2] > minHeight) minHeight = sizes[2]; //take min maxSize value
if (sizes[3] < maxHeight) maxHeight = sizes[3];
minWidth += sizes[0];
maxWidth += sizes[1];
if (sizes[0] == sizes[1] && sizes[0] != -1) {
fixed += sizes[0];
fixed_count++;
} else gravity += sizes[4];
}
}
if (minHeight > maxHeight) maxHeight = minHeight;
if (minWidth > maxWidth) maxWidth = minWidth;
this._master_size = [fixed, this._cells.length - fixed_count, gravity];
this._desired_size = [minWidth + dx, minHeight + dy]; //get layout sizes
var self_size = base.api.$getSize.call(this, 0, 0); //use child settings if layout's one was not defined
if (self_size[1] >= 100000) self_size[1] = 0;
if (self_size[3] >= 100000) self_size[3] = 0;
self_size[0] = (self_size[0] || minWidth) + dx;
self_size[1] = Math.max(self_size[0], (self_size[1] || maxWidth) + dx);
self_size[2] = (self_size[2] || minHeight) + dy;
self_size[3] = Math.max(self_size[2], (self_size[3] || maxHeight) + dy);
debug_size_box_end(this, self_size);
if (!this._vertical_orientation && this._settings.responsive) self_size[0] = 0;
return self_size;
},
$setSize: function (x, y) {
this._layout_sizes = [x, y];
debug_size_box_start(this);
base.api.$setSize.call(this, x, y);
this._set_child_size(x, y);
debug_size_box_end(this, [x, y]);
},
_set_child_size_a: function (sizes, min, max) {
min = sizes[min];
max = sizes[max];
var height = min;
if (min != max) {
var ps = this._set_size_delta * sizes[4] / this._set_size_gravity;
if (ps < min) {
height = min;
this._set_size_gravity -= sizes[4];
this._set_size_delta -= height;
} else if (ps > max) {
height = max;
this._set_size_gravity -= sizes[4];
this._set_size_delta -= height;
} else {
return -1;
}
}
return height;
},
_responsive_hide: function (cell, mode) {
var target = $$(mode);
if (target === "hide" || !target) {
cell.hide();
cell._responsive_marker = "hide";
} else {
//for SideBar in Webix 1.9
if (!target) target = ui({
view: "popup",
body: [{}]
});
cell._responsive_width = cell._settings.width;
cell._responsive_height = cell._settings.height;
cell._responsive_marker = target._settings.id;
cell._settings.width = 0;
if (!cell._settings.height) cell._settings.autoheight = true;
ui(cell, target, this._responsive.length);
}
this._responsive.push(cell);
},
_responsive_show: function (cell) {
var target = cell._responsive_marker;
cell._responsive_marker = 0;
if (target === "hide" || !target) {
cell.show();
} else {
cell._settings.width = cell._responsive_width;
cell._settings.height = cell._responsive_height;
delete cell._settings.autoheight;
var index$$1 = 0;
while (this._cells[index$$1] && this._cells[index$$1]._settings.responsiveCell === false) {
index$$1++;
}
ui(cell, this, index$$1);
}
this._responsive.pop();
},
_responsive_cells: function (x) {
state._responsive_tinkery = true;
if (x + this._padding.left + this._padding.right + this._margin * (this._cells.length - 1) < this._desired_size[0]) {
var max = this._cells.length - 1;
for (var i = 0; i < max; i++) {
var cell = this._cells[i];
if (!cell._responsive_marker) {
if (cell._settings.responsiveCell !== false) {
this._responsive_hide(cell, this._settings.responsive);
callEvent("onResponsiveHide", [cell._settings.id]);
state._responsive_exception = true;
break;
} else {
max = this._cells.length;
}
}
}
} else if (this._responsive.length) {
var _cell = this._responsive[this._responsive.length - 1];
var dx = _cell._responsive_marker == "hide" ? 0 : _cell._responsive_width;
var px = _cell.$getSize(dx, 0);
if (px[0] + this._desired_size[0] + this._margin + 20 <= x) {
this._responsive_show(_cell);
callEvent("onResponsiveShow", [_cell._settings.id]);
state._responsive_exception = true;
}
}
state._responsive_tinkery = false;
},
_set_child_size: function (x, y) {
state._child_sizing_active = (state._child_sizing_active || 0) + 1;
if (!this._vertical_orientation && this._settings.responsive) this._responsive_cells(x, y);
this._set_size_delta = (this._vertical_orientation ? y : x) - this._master_size[0];
this._set_size_gravity = this._master_size[2];
var width = x;
var height = y;
var auto = [];
for (var i = 0; i < this._cells.length; i++) {
//ignore hidden cells
if (this._cells[i]._settings.hidden || !this._sizes[i]) continue;
var sizes = this._sizes[i];
if (this._vertical_orientation) {
height = this._set_child_size_a(sizes, 2, 3);
if (height < 0) {
auto.push({
oldIndex: i,
view: this._cells[i]
});
continue;
}
} else {
width = this._set_child_size_a(sizes, 0, 1);
if (width < 0) {
auto.push({
oldIndex: i,
view: this._cells[i]
});
continue;
}
}
this._cells[i].$setSize(width, height);
}
for (var _i2 = 0; _i2 < auto.length; _i2++) {
var index$$1 = auto[_i2].oldIndex;
var _sizes = this._sizes[index$$1];
var dx = Math.round(this._set_size_delta * _sizes[4] / this._set_size_gravity);
this._set_size_delta -= dx;
this._set_size_gravity -= _sizes[4];
if (this._vertical_orientation) height = dx;else {
width = dx;
}
auto[_i2].view.$setSize(width, height);
}
state._child_sizing_active -= 1;
},
_next: function (obj, mode) {
var index$$1 = this.index(obj);
if (index$$1 == -1) return null;
return this._cells[index$$1 + mode];
},
_first: function () {
return this._cells[0];
}
};
var view$4 = exports.protoUI(api$4, EventSystem, base.view);
var baselayout = {
api: api$4,
view: view$4
};
var api$5 = {
name: "spacer",
defaults: {
borderless: true
},
$init: function () {
this._viewobj.className += " webix_spacer";
}
};
var view$5 = exports.protoUI(api$5, base$1.view);
var api$6 = {
name: "template",
$init: function (config) {
var subtype = this._template_types[config.type];
if (subtype) {
if (subtype.css && config.css) this._viewobj.className += " " + subtype.css;
exports.extend(config, subtype); //will reset borders for "section"
if (config.borderless) {
delete config._inner;
this._set_inner(config);
}
}
if (this._dataobj == this._viewobj) {
this._dataobj = create("DIV");
this._dataobj.className = " webix_template";
this._viewobj.appendChild(this._dataobj);
} else this._dataobj.className += " webix_template";
this.attachEvent("onAfterRender", this._correct_height);
},
setValues: function (obj, update) {
this.data = update ? exports.extend(this.data, obj, true) : obj;
this.render();
},
getValues: function () {
return this.data;
},
$skin: function () {
this._template_types.header.height = $active.barHeight - $active.borderWidth * 2;
this._template_types.section.height = $active.barHeight;
},
_template_types: {
"header": {
css: "webix_header"
},
"section": {
css: "webix_section",
borderless: true
},
"clean": {
css: "webix_clean",
borderless: true
}
},
onClick_setter: function (value) {
this.on_click = exports.extend(this.on_click || {}, value, true);
if (!this._onClick) exports.extend(this, MouseEvents);
return value;
},
defaults: {
template: template.empty
},
_render_me: function () {
this._not_render_me = false;
this._probably_render_me();
this.resize();
},
_probably_render_me: function () {
if (!this._not_render_me) {
this._not_render_me = true;
this.render();
}
},
src_setter: function (value) {
this._not_render_me = true;
if (!this.callEvent("onBeforeLoad", [])) return "";
ajax(value, bind(function (text) {
this._settings.template = template(text);
this._render_me();
this.callEvent("onAfterLoad", []);
}, this));
return value;
},
content_setter: function (config) {
if (config) {
this._not_render_me = true;
this.render = function () {};
this._dataobj.appendChild(toNode(config));
this._correct_height();
}
},
refresh: function () {
this.render();
},
setHTML: function (html) {
this._settings.template = function () {
return html;
};
this.refresh();
},
setContent: function (content) {
this._dataobj.innerHTML = "";
this.content_setter(content);
},
$setSize: function (x, y) {
if (base$1.api.$setSize.call(this, x, y)) {
this._probably_render_me();
if (this._settings.autoheight) {
var top = this.getTopParentView();
clearTimeout(top._template_resize_timer);
top._template_resize_timer = delay(this.resize, this);
}
return true;
}
},
$getSize: function (x, y) {
if (this._settings.autoheight && (!this._settings.type || this._settings.type == "clean")) this._settings.height = this._get_auto_height();
return base$1.api.$getSize.call(this, x, y);
},
_correct_height: function () {
//we need to force auto height calculation after content change
//dropping the last_size flag will ensure that inner logic of $setSize will be processed
if (this._settings.autoheight) {
this._last_size = null;
this.resize();
}
},
_get_auto_height: function () {
var size;
var padding = $active.layoutPadding.space;
this._probably_render_me();
if (!this.isVisible()) {
//try getting height of a hidden template
size = getTextSize(this._toHTML(this.data) || this._dataobj.innerHTML, //check for config.content
"webix_template", (this.$width || (this.getParentView() ? this.getParentView().$width : 0)) - padding).height;
} else {
this._dataobj.style.height = "auto";
size = this._dataobj.scrollHeight;
this._dataobj.style.height = "";
}
return size;
},
_one_time_scroll: true //scroll will appear only if set directly in config
};
var view$6 = exports.protoUI(api$6, Scrollable, AutoTooltip, AtomDataLoader, AtomRender, EventSystem, base$1.view);
var template$1 = {
api: api$6,
view: view$6
};
/*scrollable view with another view insize*/
var api$7 = {
name: "scrollview",
defaults: {
scroll: "y",
scrollSpeed: "300ms"
},
$init: function () {
this._viewobj.className += " webix_scrollview";
},
body_setter: function (config) {
config.borderless = true;
state._parent_cell = this;
this._body_cell = ui._view(config);
this._dataobj.appendChild(this._body_cell._viewobj);
},
getChildViews: function () {
return [this._body_cell];
},
getBody: function () {
return this._body_cell;
},
resizeChildren: function () {
if (!this._body_cell) return;
this._desired_size = this._body_cell.$getSize(0, 0);
this._resizeChildren();
callEvent("onResize", []);
},
_resizeChildren: function () {
var cx = Math.max(this._content_width, this._desired_size[0]);
var cy = Math.max(this._content_height, this._desired_size[2]);
this._body_cell.$setSize(cx, cy);
if (env.touch) {
var scroll = this.getScrollState();
var top = this._body_cell._content_height - this._content_height;
if (top < scroll.y) this.scrollTo(null, top);
}
if (state._responsive_exception) {
state._responsive_exception = false;
this._desired_size = this._body_cell.$getSize(0, 0);
this._resizeChildren();
}
},
$getSize: function (dx, dy) {
var desired_size = this._desired_size = this._body_cell.$getSize(0, 0);
var self_sizes = base$1.api.$getSize.call(this, dx, dy);
var scroll_size = this._native_scroll || env.scrollSize;
if (this._settings.scroll == "x") {
self_sizes[2] = Math.max(self_sizes[2], desired_size[2]) + scroll_size;
self_sizes[3] = Math.min(self_sizes[3], desired_size[3]) + scroll_size;
} else if (this._settings.scroll == "y") {
self_sizes[0] = Math.max(self_sizes[0], desired_size[0]) + scroll_size;
self_sizes[1] = Math.min(self_sizes[1], desired_size[1]) + scroll_size;
}
return self_sizes;
},
$setSize: function (x, y) {
var temp = env.scrollSize;
env.scrollSize = this._native_scroll || temp;
if (base$1.api.$setSize.call(this, x, y) || state._force_resize) this._resizeChildren();
env.scrollSize = temp;
},
scroll_setter: function (value) {
var custom = env.$customScroll;
if (typeof value == "string" && value.indexOf("native-") === 0) {
this._native_scroll = 17;
value = value.replace("native-", "");
env.$customScroll = false;
}
value = Scrollable.scroll_setter.call(this, value);
env.$customScroll = custom;
return value;
},
_replace: function (new_view) {
this._body_cell.destructor();
this._body_cell = new_view;
this._dataobj.appendChild(this._body_cell._viewobj);
this.resizeChildren();
},
showView: function (id) {
var topPos = $$(id).$view.offsetTop - $$(id).$view.parentNode.offsetTop;
this.scrollTo(0, topPos);
}
};
var view$7 = exports.protoUI(api$7, Scrollable, EventSystem, base$1.view);
var api$8 = {
name: "iframe",
$init: function () {
this._dataobj = this._contentobj;
this._contentobj.innerHTML = "<iframe style='width:100%; height:100%' frameborder='0' onload='var t = $$(this.parentNode.getAttribute(\"view_id\")); if (t) t.callEvent(\"onAfterLoad\",[]);' src='about:blank'></iframe>";
},
load: function (value) {
this.src_setter(value);
},
src_setter: function (value) {
if (!this.callEvent("onBeforeLoad", [])) return "";
this.getIframe().src = value;
return value;
},
getIframe: function () {
return this._contentobj.getElementsByTagName("iframe")[0];
},
getWindow: function () {
return this.getIframe().contentWindow;
}
};
var view$8 = exports.protoUI(api$8, base$1.view, EventSystem);
var api$9 = {
name: "layout",
$init: function () {
this._hiddencells = 0;
},
defaults: {
type: "line"
},
_parse_cells: function () {
if (this._parse_cells_ext) collection = this._parse_cells_ext(collection);
if (!this._parse_once) {
this._viewobj.className += " webix_layout_" + (this._settings.type || "");
this._parse_once = 1;
}
if (this._settings.margin !== undefined) this._margin = this._settings.margin;
if (this._settings.padding !== undefined && _typeof(this._settings.padding) !== "object") this._padding.left = this._padding.right = this._padding.top = this._padding.bottom = this._settings.padding;
if (this._settings.paddingX !== undefined) this._padding.left = this._padding.right = this._settings.paddingX;
if (this._settings.paddingY !== undefined) this._padding.top = this._padding.bottom = this._settings.paddingY;
if (_typeof(this._settings.padding) === "object") exports.extend(this._padding, this._settings.padding, true);
if (this._padding.left || this._padding.right || this._padding.top || this._padding.bottom) this._padding.defined = true; //if layout has paddings we need to set the visible border
if (this._hasBorders() && !this._settings.borderless) {
this._contentobj.style.borderWidth = "1px"; //if layout has border - normal bordering rules are applied
this._render_borders = true;
}
var collection = this._collection;
if (this._settings.borderless) this._settings._inner = {
top: true,
left: true,
right: true,
bottom: true
};
this._beforeResetBorders(collection);
baselayout.api._parse_cells.call(this, collection);
this._afterResetBorders(collection);
},
$getSize: function (dx, dy) {
dx = dx || 0;
dy = dy || 0;
var correction = this._margin * (this._cells.length - this._hiddencells - 1);
if (this._render_borders || this._hasBorders()) {
var _borders = this._settings._inner;
if (_borders) {
dx += (_borders.left ? 0 : 1) + (_borders.right ? 0 : 1);
dy += (_borders.top ? 0 : 1) + (_borders.bottom ? 0 : 1);
}
}
if (!this._settings.height) dy += this._padding.top + this._padding.bottom + (this._vertical_orientation ? correction : 0);
if (!this._settings.width) dx += this._padding.left + this._padding.right + (this._vertical_orientation ? 0 : correction);
return baselayout.api.$getSize.call(this, dx, dy);
},
$setSize: function (x, y) {
this._layout_sizes = [x, y];
debug_size_box_start(this);
if (this._hasBorders() || this._render_borders) base$1.api.$setSize.call(this, x, y);else base.api.$setSize.call(this, x, y); //form with scroll
y = this._content_height;
x = this._content_width;
var config = this._settings;
if (config.scroll) {
y = Math.max(y, this._desired_size[1]);
x = Math.max(x, this._desired_size[0]);
}
this._set_child_size(x, y);
debug_size_box_end(this, [x, y]);
},
_set_child_size: function (x, y) {
var correction = this._margin * (this._cells.length - this._hiddencells - 1);
y -= this._padding.top + this._padding.bottom;
x -= this._padding.left + this._padding.right;
if (this._vertical_orientation) y -= correction;else x -= correction;
return baselayout.api._set_child_size.call(this, x, y);
},
resizeChildren: function (structure_changed) {
if (structure_changed) {
this._last_size = null; //forces children resize
var config = [];
for (var i = 0; i < this._cells.length; i++) {
var cell = this._cells[i];
config[i] = cell._settings;
var n = cell._layout_sizes && !cell._render_borders || cell._settings.borderless ? "0px" : "1px";
cell._viewobj.style.borderTopWidth = cell._viewobj.style.borderBottomWidth = cell._viewobj.style.borderLeftWidth = cell._viewobj.style.borderRightWidth = n;
}
this._beforeResetBorders(config);
for (var _i = 0; _i < config.length; _i++) {
if (config[_i].borderless && this._cells[_i]._set_inner) this._cells[_i]._set_inner(config[_i]);
}
this._afterResetBorders(this._cells);
}
if (state._responsive_tinkery) return;
baselayout.api.resizeChildren.call(this);
},
_hasBorders: function () {
return this._padding.defined && this._margin > 0 && !this._cleanlayout;
},
_beforeResetBorders: function (collection) {
if (this._hasBorders() && (!this._settings.borderless || this._settings.type == "space")) {
for (var i = 0; i < collection.length; i++) {
if (!collection[i]._inner || !collection[i].borderless) collection[i]._inner = {
top: false,
left: false,
right: false,
bottom: false
};
}
} else {
for (var _i2 = 0; _i2 < collection.length; _i2++) {
collection[_i2]._inner = clone(this._settings._inner);
}
var mode = false;
if (this._cleanlayout) mode = true;
var maxlength = collection.length;
if (this._vertical_orientation) {
for (var _i3 = 1; _i3 < maxlength - 1; _i3++) {
collection[_i3]._inner.top = collection[_i3]._inner.bottom = mode;
}
if (maxlength > 1) {
if (this._settings.type != "head") collection[0]._inner.bottom = mode;
while (collection[maxlength - 1].hidden && maxlength > 1) {
maxlength--;
}
if (maxlength > 0) collection[maxlength - 1]._inner.top = mode;
}
} else {
for (var _i4 = 1; _i4 < maxlength - 1; _i4++) {
collection[_i4]._inner.left = collection[_i4]._inner.right = mode;
}
if (maxlength > 1) {
if (this._settings.type != "head") collection[0]._inner.right = mode;
collection[maxlength - 1]._inner.left = mode;
while (maxlength > 1 && collection[maxlength - 1].hidden) {
maxlength--;
}
if (maxlength > 0) collection[maxlength - 1]._inner.left = mode;
}
}
}
},
_afterResetBorders: function (collection) {
var start = 0;
for (var i = 0; i < collection.length; i++) {
var cell = this._cells[i];
var s_inner = cell._settings._inner;
if (cell._settings.hidden && this._cells[i + 1]) {
var s_next = this._cells[i + 1]._settings._inner;
if (!s_inner.top) s_next.top = false;
if (!s_inner.left) s_next.left = false;
if (i == start) start++;
}
this._fix_container_borders(cell._viewobj.style, cell._settings._inner);
}
var style = this._vertical_orientation ? "marginLeft" : "marginTop";
var contrstyle = this._vertical_orientation ? "marginTop" : "marginLeft";
var padding = this._vertical_orientation ? this._padding.left : this._padding.top;
var contrpadding = this._vertical_orientation ? this._padding.top : this._padding.left; //add top offset to all
for (var _i5 = 0; _i5 < collection.length; _i5++) {
this._cells[_i5]._viewobj.style[style] = padding + "px";
} //add left offset to first cell
if (this._cells.length) this._cells[start]._viewobj.style[contrstyle] = contrpadding + "px"; //add offset between cells
for (var index = start + 1; index < collection.length; index++) {
this._cells[index]._viewobj.style[contrstyle] = this._margin + "px";
}
},
type_setter: function (value) {
this._margin = typeof this._margin_set[value] !== "undefined" ? this._margin_set[value] : this._margin_set["line"];
this._padding.left = this._padding.right = this._padding.top = this._padding.bottom = typeof this._margin_set[value] !== "undefined" ? this._padding_set[value] : this._padding_set["line"];
this._cleanlayout = value == "material" || value == "clean";
if (value == "material") this._settings.borderless = true;
return value;
},
$skin: function () {
this._margin_set = $active.layoutMargin;
this._padding_set = $active.layoutPadding;
}
};
var view$9 = exports.protoUI(api$9, baselayout.view);
var layout = {
api: api$9,
view: view$9
}; //not necessary anymore
//preserving for backward compatibility
view$9.call(-1);
var api$a = {
name: "accordion",
defaults: {
panelClass: "accordionitem",
multi: false,
collapsed: false
},
$init: function () {
this._viewobj.setAttribute("role", "tablist");
this._viewobj.setAttribute("aria-multiselectable", "true");
},
_replace: function (newview) {
layout.api._replace.apply(this, arguments);
if (newview.collapsed_setter && newview.refresh) {
newview.refresh();
}
},
_parse_cells: function () {
var panel = this._settings.panelClass;
var cells = this._collection;
for (var i = 0; i < cells.length; i++) {
if ((cells[i].body || cells[i].header) && !cells[i].view && !cells[i].align) cells[i].view = panel;
if (isUndefined(cells[i].collapsed)) cells[i].collapsed = this._settings.collapsed;
}
this._skin_render_collapse = true;
layout.api._parse_cells.call(this);
this._skin_render_collapse = false;
for (var _i = 0; _i < this._cells.length; _i++) {
if (this._cells[_i].name == panel) this._cells[_i].refresh();
this._cells[_i]._accLastChild = false;
}
var found = false;
for (var _i2 = this._cells.length - 1; _i2 >= 0 && !found; _i2--) {
if (!this._cells[_i2]._settings.hidden) {
this._cells[_i2]._accLastChild = true;
found = true;
}
}
},
_afterOpen: function (view) {
if (this._settings.multi === false && this._skin_render_collapse !== true) {
for (var i = 0; i < this._cells.length; i++) {
if (view != this._cells[i] && !this._cells[i]._settings.collapsed && this._cells[i].collapse) this._cells[i].collapse();
}
}
if (view.callEvent) {
view.callEvent("onViewShow", []);
_each(view, this._signal_hidden_cells);
}
},
_canCollapse: function (view) {
if (this._settings.multi === true || this._skin_render_collapse) return true; //can collapse only if you have other item to open
for (var i = 0; i < this._cells.length; i++) {
if (view != this._cells[i] && !this._cells[i]._settings.collapsed && this._cells[i].isVisible() && !this._cells[i].$nospace) return true;
}
return false;
},
$skin: function () {
layout.api.$skin.call(this);
if ($active.accordionType) this.defaults.type = $active.accordionType;
}
};
var view$a = exports.protoUI(api$a, layout.view);
var base$2 = {
api: api$a,
view: view$a
};
var api$b = {
name: "headerlayout",
defaults: {
type: "accordion",
multi: "mixed",
collapsed: false
}
};
var view$b = exports.protoUI(api$b, base$2.view);
var api$c = {
name: "accordionitem",
$init: function (config) {
this._viewobj.innerHTML = "<div tabindex='0' " +
/*@attr*/
"webix_ai_id" + "='" + config.id + "' class='webix_accordionitem_header'><div class='webix_accordionitem_button' ></div><div class='webix_accordionitem_label' ></div></div><div class='webix_accordionitem_body'></div>";
this._contentobj = this._viewobj;
this._headobj = this._contentobj.childNodes[0];
if (!config.header) this._headobj.style.display = "none";
this._headlabel = this._contentobj.childNodes[0].childNodes[1];
this._headbutton = this._contentobj.childNodes[0].childNodes[0];
this._bodyobj = this._contentobj.childNodes[1];
this._viewobj.className += " webix_accordionitem";
this._head_cell = this._body_cell = null;
this._cells = true;
this._bodyobj.setAttribute("role", "tabpanel");
this._headobj.setAttribute("role", "tab");
this.attachEvent("onKeyPress", this._onKeyPress);
},
_remove: function () {
this.body_setter();
},
_replace: function (new_view) {
this._body_cell.destructor();
this._body_cell = new_view;
this._bodyobj.appendChild(this._body_cell._viewobj);
this.resize();
},
_id:
/*@attr*/
"webix_ai_id",
getChildViews: function () {
return [this._body_cell];
},
body_setter: function (value) {
if (_typeof(value) != "object") value = {
template: value
};
value._inner = {
top: true,
left: true,
right: true,
bottom: true
};
state._parent_cell = this;
this._body_cell = ui._view(value);
this._bodyobj.appendChild(this._body_cell._viewobj);
return value;
},
header_setter: function (value) {
if (value) value = template(value);
return value;
},
headerAlt_setter: function (value) {
if (value) value = template(value);
return value;
},
$getSize: function (dx, dy) {
var size = this._body_cell.$getSize(0, 0); //apply external border to inner content sizes
var _borders = this._settings._inner;
if (_borders) {
dx += (_borders.left ? 0 : 1) + (_borders.right ? 0 : 1);
dy += (_borders.top ? 0 : 1) + (_borders.bottom ? 0 : 1);
}
var header = 0;
var self_size = base.api.$getSize.call(this, 0, 0); //use child settings if layout's one was not defined
self_size[0] = (self_size[0] || size[0]) + dx;
if (self_size[1] >= 100000) self_size[1] = size[1];
self_size[1] += dx;
self_size[2] = (self_size[2] || size[2]) + dy;
var fixedHeight = self_size[3] < 100000;
if (!fixedHeight) self_size[3] = size[3];
self_size[3] += dy;
if (this.getParentView()._vertical_orientation) {
if (this._settings.collapsed) {
self_size[2] = self_size[3] = this._getHeaderSize() + dy;
} else if (this._settings.header) header = this._settings.headerHeight;
} else {
if (this._settings.collapsed) self_size[0] = self_size[1] = this._getHeaderSize() + dx;
if (this._settings.header) header = this._settings.headerHeight;
} //include header in total height calculation
if (!fixedHeight) {
self_size[2] += header;
self_size[3] += header;
}
debug_size_box(this, self_size, true);
return self_size;
},
on_click: {
webix_accordionitem_header: function (e) {
this._toggle(e);
return false;
},
webix_accordionitem_header_v: function (e) {
this._toggle(e);
return false;
}
},
_toggle: function () {
this.define("collapsed", !this._settings.collapsed);
},
collapsed_setter: function (value) {
if (this._settings.header === false) return; //use last layout element if parent is not known yet
var parent = this.getParentView();
if (parent) {
if (!value) this._expand();else {
if (parent._canCollapse(this)) this._collapse();else {
var success = 0;
if (parent._cells.length > 1) for (var i = 0; i < parent._cells.length; i++) {
var sibl = parent._cells[i];
if (this != sibl && sibl.isVisible() && sibl.expand) {
sibl.expand();
this._collapse();
success = 1;
break;
}
}
if (!success) return;
}
}
this._settings.collapsed = value;
if (!value) parent._afterOpen(this);
this.refresh();
if (!state._ui_creation) this.resize();
parent.callEvent("onAfter" + (value ? "Collapse" : "Expand"), [this._settings.id]);
this._settings.$noresize = value;
}
return value;
},
collapse: function () {
this.define("collapsed", true);
UIManager._moveChildFocus(this);
},
expand: function () {
this.define("collapsed", false);
},
_show: function () {
this.show();
},
_hide: function () {
this.hide();
},
_expand: function () {
this._bodyobj.style.display = "";
removeCss(this.$view, "collapsed");
removeCss(this._headobj, "collapsed");
this._headobj.setAttribute("aria-expanded", "true");
},
_collapse: function () {
if (this._settings.headerAlt) this._headlabel.innerHTML = this._settings.headerAlt();
this._bodyobj.style.display = "none";
addCss(this.$view, "collapsed");
addCss(this._headobj, "collapsed");
this._headobj.setAttribute("aria-expanded", "false");
},
refresh: function () {
var template$$1 = this._settings[this._settings.collapsed ? "headerAlt" : "header"] || this._settings.header;
if (template$$1) {
this._headlabel.innerHTML = template$$1();
this._headbutton.setAttribute("aria-label", template$$1());
}
var css = this.getParentView()._vertical_orientation ? "vertical" : "horizontal";
if (this._viewobj.className.indexOf(" " + css) < 0) {
addCss(this._viewobj, css);
} //fix collapsed columns in IE8
if (!env.transform) {
addCss(this._viewobj, "webix_ie", true);
}
},
_getHeaderSize: function () {
return this._settings.collapsed ? this._settings.headerAltHeight : this._settings.headerHeight;
},
$setSize: function (x, y) {
if (base$1.api.$setSize.call(this, x, y) || this._getHeaderSize() != this._last_set_header_size) {
x = this._content_width;
y = this._content_height;
var headerSize = this._last_set_header_size = this._getHeaderSize(); //-(this._settings._inner.top?0:1);
if (this._settings.header) {
this._headobj.style.height = headerSize + "px";
this._headobj.style.width = "auto";
this._headobj.style[env.transform] = "";
this._headobj.style.borderBottomWidth = (this._settings.collapsed ? 0 : 1) + "px";
if (this.getParentView()._vertical_orientation || !this._settings.collapsed) {
y -= this._getHeaderSize();
} else if (this._settings.collapsed) {
//-2 - borders
if (animate.isSupported()) {
this._headobj.style.width = y + "px";
this._headobj.style.height = x + 3 + "px";
var d = Math.floor(y / 2 - x / 2) + (x - this._settings.headerAltHeight) / 2;
this._headobj.style[env.transform] = "rotate(90deg) translate(" + d + "px, " + (d + 1) + "px)";
} else {
//IE8 fix
this._headobj.style.width = x + "px";
this._headobj.style.height = y + 3 + "px";
}
}
}
if (!this._settings.collapsed) {
this._body_cell.$setSize(x, y);
this._last_size_y = y;
}
} else if (!this._settings.collapsed) {
var body = this._body_cell;
if (this._last_size_y) body.$setSize(this._content_width, this._last_size_y);
}
},
$skin: function () {
this.defaults.headerAltHeight = this.defaults.headerHeight = $active.barHeight - $active.borderWidth * 2;
},
defaults: {
header: false,
headerAlt: false,
body: ""
}
};
var view$c = exports.protoUI(api$c, MouseEvents, EventSystem, base$1.view);
var api$d = {
name: "resizearea",
defaults: {
dir: "x"
},
$init: function (config) {
var dir = config.dir || "x";
var node = toNode(config.container);
var size = dir == "x" ? "width" : "height";
var margin = config.margin ? config.margin + "px" : 0;
this._key_property = dir == "x" ? "left" : "top";
this._viewobj = create("DIV", {
"class": "webix_resize_area webix_dir_" + dir
}); //[[COMPAT]] FF12 can produce 2 move events
_event(this._viewobj, env.mouse.down, stopEvent);
if (margin) {
if (dir == "x") margin = margin + " 0 " + margin;else margin = "0 " + margin + " 0 " + margin;
}
this._dragobj = create("DIV", {
"class": "webix_resize_handle_" + dir,
"style": margin ? "padding:" + margin : ""
}, "<div class='webix_handle_content'></div>");
this._originobj = create("DIV", {
"class": "webix_resize_origin_" + dir
});
if (config[size]) {
this._originobj.style[size] = config[size] + (config.border ? 1 : 0) + "px";
this._dragobj.style[size] = config[size] + "px";
}
if (config.cursor) this._dragobj.style.cursor = this._originobj.style.cursor = this._viewobj.style.cursor = config.cursor;
this._moveev = event$1(node, env.mouse.move, this._onmove, {
bind: this
});
this._upev = event$1(document.body, env.mouse.up, this._onup, {
bind: this
});
this._dragobj.style[this._key_property] = this._originobj.style[this._key_property] = config.start + "px";
node.appendChild(this._viewobj);
node.appendChild(this._dragobj);
node.appendChild(this._originobj);
},
_onup: function () {
this.callEvent("onResizeEnd", [this._last_result]);
eventRemove(this._moveev);
eventRemove(this._upev);
remove(this._viewobj);
remove(this._dragobj);
remove(this._originobj);
this._viewobj = this._dragobj = this._originobj = null;
},
_onmove: function (e) {
var eventPos = pos(e);
this._last_result = (this._settings.dir == "x" ? eventPos.x : eventPos.y) + this._settings.start - this._settings.eventPos;
this._dragobj.style[this._key_property] = this._last_result + "px";
this.callEvent("onResize", [this._last_result]);
}
};
var view$d = exports.protoUI(api$d, EventSystem, Settings);
var api$e = {
name: "resizer",
defaults: {
width: 7,
height: 7
},
$init: function (config) {
assert(this.getParentView(), "Resizer can't be initialized outside a layout");
this._viewobj.className += " webix_resizer";
var space = this.getParentView()._margin;
_event(this._viewobj, env.mouse.down, this._rsDown, {
bind: this
});
var dir = this._getResizeDir();
this._rs_started = false;
this._resizer_dir = dir;
this._resizer_dim = dir == "x" ? "width" : "height";
if (dir == "x") config.height = 0;else config.width = 0;
if (space > 0) {
this._viewobj.className += " webix_resizer_v" + dir;
this._viewobj.style.marginRight = "-" + space + "px";
if (dir == "x") config.width = space;else config.height = space;
this.$nospace = true;
} else this._viewobj.className += " webix_resizer_" + dir;
this._viewobj.innerHTML = "<div class='webix_resizer_content'></div>";
if (dir == "y" && space > 0) this._viewobj.style.marginBottom = "-" + (config.height || this.defaults.height) + "px";
this._viewobj.setAttribute(
/*@attr*/
"webix_disable_drag", "true");
this._viewobj.setAttribute("tabindex", "-1");
this._viewobj.setAttribute("aria-grabbed", "false");
},
_rsDown: function (e) {
var _this = this;
var cells = this._getResizerCells(); //some sibling can block resize
if (cells && !this._settings.disabled) {
e = e || window.event;
this._rs_started = true;
this._rs_process = pos(e);
this._rsLimit = [];
this._viewobj.setAttribute("aria-grabbed", "true");
for (var i = 0; i < 2; i++) {
cells[i].$view.setAttribute("aria-dropeffect", "move");
}
this._viewobj.setAttribute("aria-dropeffect", "move");
this._rsStart(e, cells[0]);
var handler = event$1(document.body, env.mouse.up, function (e) {
eventRemove(handler);
return _this._rsUp(e);
});
}
},
_rsUp: function () {
this._rs_started = false;
this._rs_process = false;
},
_rsStart: function (e, cell) {
var dir, cellOffset, pos$$1, posParent, start;
e = e || window.event;
dir = this._resizer_dir;
/*layout position:relative to place absolutely positioned elements in it*/
this.getParentView()._viewobj.style.position = "relative";
pos$$1 = offset(this._viewobj);
posParent = offset(this.getParentView()._viewobj);
start = pos$$1[dir] - posParent[dir];
cellOffset = offset(cell.$view)[dir] - offset(this.getParentView().$view)[dir];
this._rs_progress = [dir, cell, start, cellOffset];
/*resizer stick (resizerea ext)*/
this._resizeStick = new ui.resizearea({
container: this.getParentView()._viewobj,
dir: dir,
eventPos: this._rs_process[dir],
start: start - 1,
height: this.$height,
width: this.$width,
border: 1,
margin: this.getParentView()._padding[dir === "x" ? "left" : "top"]
});
/*stops resizing on stick mouseup*/
this._resizeStick.attachEvent("onResizeEnd", bind(this._rsEnd, this));
/*needed to stop stick moving when the limit for dimension is reached*/
this._resizeStick.attachEvent("onResize", bind(this._rsResizeHandler, this));
addCss(document.body, "webix_noselect", 1);
},
_getResizeDir: function () {
return this.getParentView()._vertical_orientation ? "y" : "x";
},
_rsResizeHandler: function () {
var cells, cDiff, diff, dir, i, limits, limitSizes, sizes, totalSize;
if (this._rs_progress) {
cells = this._getResizerCells();
dir = this._rs_progress[0];
/*vector distance between resizer and stick*/
diff = this._resizeStick._last_result - this._rs_progress[2];
/*new sizes for the resized cells, taking into account the stick position*/
sizes = this._rsGetDiffCellSizes(cells, dir, diff);
/*sum of cells dimensions*/
totalSize = cells[0]["$" + this._resizer_dim] + cells[1]["$" + this._resizer_dim];
for (i = 0; i < 2; i++) {
cDiff = i ? -diff : diff;
/*if cDiff is positive, the size of i cell is increased*/
/*max and min limits*/
limits = cells[i].$getSize(0, 0);
/*if size is bigger than max limit or size is smaller than min limit*/
var min = dir == "y" ? limits[2] : limits[0];
var max = dir == "y" ? limits[3] : limits[1]; //if size is fixed, treat it as responsive (default behavior)
if (min === max) {
min = cells[i]._settings[dir == "y" ? "minHeight" : "minWidth"] || 3;
max = cells[i]._settings[dir == "y" ? "maxHeight" : "maxWidth"] || 100000;
}
if (cDiff > 0 && max && max <= sizes[i] || cDiff < 0 && min && min >= sizes[i]) {
this._rsLimit[i] = cDiff > 0 ? max : min;
/*new sizes, taking into account max and min limits*/
limitSizes = this._rsGetLimitCellSizes(cells, dir);
/*stick position*/
this._resizeStick._dragobj.style[dir == "y" ? "top" : "left"] = this._rs_progress[3] + limitSizes[0] + "px";
return;
} else if (sizes[i] < 3) {
/*cells size can not be less than 1*/
this._resizeStick._dragobj.style[dir == "y" ? "top" : "left"] = this._rs_progress[3] + i * totalSize + 1 + "px";
} else {
this._rsLimit[i] = null;
}
}
}
},
_getResizerCells: function () {
var cells, i, res;
cells = this.getParentView()._cells;
for (i = 0; i < cells.length; i++) {
if (cells[i] == this) {
res = [this._getRsCell(cells, i, 1, -1), this._getRsCell(cells, i, 1, 1)];
if (!res[0] || !res[1]) res = null;
return res;
}
}
},
_getRsCell: function (cells, i, step, dir) {
var cell = cells[i + dir * step];
if (cell && cell._settings.hidden) return this._getRsCell(cells, i, step + 1, dir);else if (cell && cell._settings.$noresize) return null;else return cell;
},
_rsEnd: function (result) {
if (typeof result == "undefined") return;
var cells, dir, diff, size;
var vertical = this.getParentView()._vertical_orientation;
this._resizerStick = null;
if (this._rs_progress) {
dir = this._rs_progress[0];
diff = result - this._rs_progress[2];
cells = this._getResizerCells();
if (cells[0] && cells[1]) {
/*new cell sizes*/
size = this._rsGetCellSizes(cells, dir, diff);
for (var i = 0; i < 2; i++) {
//cell has not fixed size, of fully fixed layout
var cell_size = cells[i].$getSize(0, 0);
if (vertical ? cell_size[2] == cell_size[3] : Math.abs(cell_size[1] - cell_size[0]) < 3) {
/*set fixed sizes for both cells*/
cells[i]._settings[this._resizer_dim] = size[i];
if (cells[i]._bubble_size) cells[i]._bubble_size(this._resizer_dim, size[i], vertical);
} else {
var actualSize = cells[i].$view[vertical ? "offsetHeight" : "offsetWidth"]; //cells[i]["$"+this._resizer_dim];
cells[i]._settings.gravity = size[i] / actualSize * cells[i]._settings.gravity;
}
}
cells[0].resize();
for (var _i = 0; _i < 2; _i++) {
if (cells[_i].callEvent) cells[_i].callEvent("onViewResize", []);
cells[_i].$view.removeAttribute("aria-dropeffect");
}
callEvent("onLayoutResize", [cells]);
}
this._rs_progress = false;
}
this._rs_progress = false;
this._rs_started = false;
this._rsLimit = null;
removeCss(document.body, "webix_noselect");
this._viewobj.setAttribute("aria-grabbed", "false");
this._viewobj.removeAttribute("aria-dropeffect");
},
_rsGetLimitCellSizes: function (cells) {
var size1, size2, totalSize;
totalSize = cells[0]["$" + this._resizer_dim] + cells[1]["$" + this._resizer_dim];
if (this._rsLimit[0]) {
size1 = this._rsLimit[0];
size2 = totalSize - size1;
} else if (this._rsLimit[1]) {
size2 = this._rsLimit[1];
size1 = totalSize - size2;
}
return [size1, size2];
},
_rsGetDiffCellSizes: function (cells, dir, diff) {
var sizes = [];
var styleDim = this._resizer_dim == "height" ? "offsetHeight" : "offsetWidth";
for (var i = 0; i < 2; i++) {
sizes[i] = cells[i].$view[styleDim] + (i ? -1 : 1) * diff;
}
return sizes;
},
_rsGetCellSizes: function (cells, dir, diff) {
var i, sizes, totalSize;
/*if max or min dimentsions are set*/
if (this._rsLimit[0] || this._rsLimit[1]) {
sizes = this._rsGetLimitCellSizes(cells, dir);
} else {
sizes = this._rsGetDiffCellSizes(cells, dir, diff);
for (i = 0; i < 2; i++) {
/*if stick moving is stopped outsize cells borders*/
if (sizes[i] < 0) {
totalSize = sizes[0] + sizes[1];
sizes[i] = 1;
sizes[1 - i] = totalSize - 1;
}
}
}
return sizes;
}
};
var view$e = exports.protoUI(api$e, MouseEvents, Destruction, base$1.view);
var api$f = {
name: "align",
defaults: {
borderless: true,
left: 0,
top: 0,
right: 0,
bottom: 0
},
$init: function () {
this._viewobj.className += " webix_view_align";
},
_remove: function () {
this.body_setter({});
},
_replace: function (new_view) {
this._body_cell.destructor();
this._body_cell = new_view;
this._viewobj.appendChild(this._body_cell._viewobj);
this.resize();
},
getChildViews: function () {
return [this._body_cell];
},
body_setter: function (value) {
value._inner = {
top: false,
left: false,
right: false,
bottom: false
};
state._parent_cell = this;
this._body_cell = ui._view(value);
this._viewobj.appendChild(this._body_cell._viewobj);
return value;
},
align_setter: function (value) {
if (typeof value === "string") value = value.split(",");
this._x_align = this._y_align = this._p_align = "";
for (var i = 0; i < value.length; i++) {
var c = value[i];
if (c === "center" || c === "left" || c === "right") this._x_align = c;
if (c === "top" || c === "bottom" || c === "middle") this._y_align = c;
if (c === "absolute") this._x_align = this._y_align = this._p_align = "precise";
}
return value;
},
getBody: function () {
return this._body_cell;
},
$setSize: function (x, y) {
base$1.api.$setSize.call(this, x, y);
var dx, dy;
if (this._p_align) {
dx = x - this._settings.left - this._settings.right;
dy = y - this._settings.top - this._settings.bottom;
} else {
dx = this._desired_size[0] || x;
dy = this._desired_size[2] || y;
}
this._body_cell.$setSize(dx, dy);
var box = this._body_cell._viewobj;
if (this._x_align == "center") box.style.marginLeft = Math.ceil((x - dx) / 2) + "px";else if (this._x_align == "right") box.style.marginLeft = x - dx + "px";else box.style.marginLeft = (this._p_align ? this._settings.left : 0) + "px";
if (this._y_align == "middle") box.style.marginTop = Math.ceil((y - dy) / 2) + "px";else if (this._y_align == "bottom") box.style.marginTop = y - dy + "px";else box.style.marginTop = (this._p_align ? this._settings.top : 0) + "px";
},
$getSize: function (dx, dy) {
var size = this._desired_size = this._body_cell.$getSize(0, 0);
var self_size = base.api.$getSize.call(this, 0, 0);
if (this._p_align) {
dx += this._settings.left + this._settings.right;
dy += this._settings.top + this._settings.bottom;
}
if (!this._x_align || this._p_align) {
self_size[0] = size[0] + dx;
self_size[1] = size[1] + dx;
} else {
self_size[0] = (self_size[0] || size[0]) + dy;
self_size[1] += dx;
}
if (!this._y_align || this._p_align) {
self_size[2] = size[2] + dy;
self_size[3] = size[3] + dy;
} else {
self_size[2] = (self_size[2] || size[2]) + dy;
self_size[3] += dy;
}
return self_size;
}
};
var view$f = exports.protoUI(api$f, base$1.view);
var api$g = {
name: "multiview",
defaults: {
animate: {}
},
setValue: function (val) {
$$(val).show();
},
getValue: function () {
return this.getActiveId();
},
$init: function () {
this._active_cell = 0;
this._vertical_orientation = 1;
this._viewobj.style.position = "relative";
this._viewobj.className += " webix_multiview";
this._back_queue = [];
},
_ask_render: function (cell_id, view_id) {
var cell = $$(cell_id);
if (!cell._render_hash) {
cell._render_queue = [];
cell._render_hash = {};
}
if (!cell._render_hash[view_id]) {
cell._render_hash[view_id] = true;
cell._render_queue.push(view_id);
}
},
_render_activation: function (cell_id) {
var cell = $$(cell_id);
if (this._settings.keepViews) cell._viewobj.style.display = "";
/*back array*/
if (this._back_queue[this._back_queue.length - 2] != cell_id) {
if (this._back_queue.length == 10) this._back_queue.splice(0, 1);
this._back_queue.push(cell_id);
} else this._back_queue.splice(this._back_queue.length - 1, 1);
if (cell._render_hash) {
for (var i = 0; i < cell._render_queue.length; i++) {
var subcell = $$(cell._render_queue[i]); //cell can be already destroyed
if (subcell) subcell.render();
}
cell._render_queue = [];
cell._render_hash = {};
}
},
addView: function (view, index$$1) {
var inc = !isUndefined(index$$1) && index$$1 <= this._active_cell ? 1 : 0;
var id = baselayout.api.addView.apply(this, arguments);
if (this._cells.length > 1) {
if (this._settings.keepViews) $$(id)._viewobj.style.display = "none";else remove($$(id)._viewobj);
this._active_cell += inc;
}
return id;
},
_replace: function (view) {
if (!view._settings.borderless) {
var settings = clone(this._settings._inner);
view._settings._inner = settings;
var style = view._viewobj.style;
style.borderTopWidth = style.borderBottomWidth = style.borderLeftWidth = style.borderRightWidth = "1px";
this._fix_container_borders(style, settings);
}
baselayout.api._replace.apply(this, arguments);
},
_beforeRemoveView: function (index$$1) {
//removing current view
if (index$$1 == this._active_cell) {
var next = index$$1 ? index$$1 - 1 : 1;
if (this._cells[next]) {
this._animation_promise = null;
this._show(this._cells[next], false);
}
}
if (index$$1 < this._active_cell) this._active_cell--;
},
//necessary, as we want to ignore hide calls for elements in multiview
_hide: function () {},
_parse_cells: function (collection) {
collection = collection || this._collection;
for (var i = 0; i < collection.length; i++) {
collection[i]._inner = this._settings.borderless ? {
top: 1,
left: 1,
right: 1,
bottom: 1
} : this._settings._inner || {};
}
baselayout.api._parse_cells.call(this, collection);
for (var _i = 1; _i < this._cells.length; _i++) {
if (this._settings.keepViews) this._cells[_i]._viewobj.style.display = "none";else remove(this._cells[_i]._viewobj);
}
for (var _i2 = 0; _i2 < collection.length; _i2++) {
var cell = this._cells[_i2];
if (cell._cells && !cell._render_borders) continue;
this._fix_container_borders(cell._viewobj.style, cell._settings._inner);
cell._viewobj.setAttribute("role", "tabpanel");
}
this._render_activation(this.getActiveId());
},
cells_setter: function (value) {
assert(value && value.length, "Multiview must have at least one view in 'cells'");
this._collection = value;
},
_getDirection: function (next, active) {
var dir = (this._settings.animate || {}).direction;
var vx = dir == "top" || dir == "bottom";
return next < active ? vx ? "bottom" : "right" : vx ? "top" : "left";
},
_show: function (obj, animation_options) {
var _this = this,
_arguments = arguments;
var parent = this.getParentView();
if (parent && parent.getTabbar) {
var tabBar = parent.getTabbar();
tabBar.blockEvent();
tabBar.setValue(obj._settings.$id || obj._settings.id);
tabBar.unblockEvent();
}
if (this._animation_promise) return this._animation_promise.then(function () {
return _this._show.apply(_this, _arguments);
});
var _next_cell = -1;
for (var i = 0; i < this._cells.length; i++) {
if (this._cells[i] == obj) {
_next_cell = i;
break;
}
}
if (_next_cell < 0 || _next_cell == this._active_cell) return;
var prev = this._cells[this._active_cell];
var next = this._cells[_next_cell];
prev.$getSize(0, 0); //need to be moved in animate
if ((animation_options || typeof animation_options == "undefined") && animate.isSupported() && this._settings.animate) {
var aniset = exports.extend({}, this._settings.animate);
if (this._settings.keepViews) aniset.keepViews = true;
aniset.direction = this._getDirection(_next_cell, this._active_cell);
aniset = Settings._mergeSettings(animation_options || {}, aniset);
var line = animate.formLine(next._viewobj, prev._viewobj, aniset);
next.$getSize(0, 0);
next.$setSize(this._content_width, this._content_height);
var callback_original = aniset.callback;
aniset.callback = function () {
animate.breakLine(line, this._settings.keepViews);
this._animation_promise = null;
aniset.wait_animation.resolve();
if (callback_original) callback_original.call(this);
callback_original = aniset.master = aniset.callback = null;
this.resize();
};
aniset.master = this;
this._active_cell = _next_cell;
this._render_activation(this.getActiveId());
animate(line, aniset);
this._animation_promise = aniset.wait_animation = Deferred.defer();
} else {
// browsers which don't support transform and transition, or animate:false in config
if (this._settings.keepViews) {
prev._viewobj.style.display = "none";
} else {
remove(prev._viewobj);
this._viewobj.appendChild(this._cells[i]._viewobj);
}
this._active_cell = _next_cell;
this.resizeChildren();
this._render_activation(this.getActiveId());
}
if (next.callEvent) {
next.callEvent("onViewShow", []);
_each(next, this._signal_hidden_cells);
}
this.callEvent("onViewChange", [prev._settings.id, next._settings.id]);
},
$getSize: function (dx, dy) {
if (!this._cells.length) return base.api.$getSize.call(this, 0, 0);
debug_size_box_start(this, true);
var size = this._cells[this._active_cell].$getSize(0, 0);
if (this._settings.fitBiggest) {
for (var i = 0; i < this._cells.length; i++) {
if (i != this._active_cell) {
var other = this._cells[i].$getSize(0, 0);
for (var j = 0; j < 4; j++) {
size[j] = Math.max(size[j], other[j]);
}
}
}
} //get layout sizes
var self_size = base.api.$getSize.call(this, 0, 0); //use child settings if layout's one was not defined
if (self_size[1] >= 100000) self_size[1] = 0;
if (self_size[3] >= 100000) self_size[3] = 0;
self_size[0] = (self_size[0] || size[0]) + dx;
self_size[1] = (self_size[1] || size[1]) + dx;
self_size[2] = (self_size[2] || size[2]) + dy;
self_size[3] = (self_size[3] || size[3]) + dy;
debug_size_box_end(this, self_size);
return self_size;
},
$setSize: function (x, y) {
if (!this._cells.length) return;
this._layout_sizes = [x, y];
base.api.$setSize.call(this, x, y);
this._cells[this._active_cell].$setSize(x, y);
},
isVisible: function (base_id, cell_id) {
if (cell_id && cell_id != this.getActiveId()) {
if (base_id) this._ask_render(cell_id, base_id);
return false;
}
return base$1.api.isVisible.call(this, base_id, this._settings.id);
},
getActiveId: function () {
return this._cells.length ? this._cells[this._active_cell]._settings.id : null;
},
back: function (step) {
step = step || 1;
if (this.callEvent("onBeforeBack", [this.getActiveId(), step])) {
if (this._back_queue.length > step) {
var viewId = this._back_queue[this._back_queue.length - step - 1];
$$(viewId).show();
return viewId;
}
return null;
}
return null;
},
_insertBeforeView: function (view, before) {
if (this._settings.keepViews || !before || before == this._cells[this._active_cell]) baselayout.api._insertBeforeView.call(this, view, before);
}
};
var view$g = exports.protoUI(api$g, baselayout.view);
var api$h = {
name: "tabview",
setValue: function (val, config) {
this._cells[0].setValue(val, config);
},
getValue: function () {
return this._cells[0].getValue();
},
getTabbar: function () {
return this._cells[0];
},
getMultiview: function () {
return this._cells[1];
},
addView: function (obj) {
var nid = this.getMultiview().addView(obj.body);
obj.id = nid;
obj.value = obj.header;
delete obj.body;
delete obj.header;
var t = this.getTabbar();
t.addOption(obj);
return nid;
},
removeView: function (id) {
var t = this.getTabbar();
t.removeOption(id);
t.refresh();
},
$init: function (config) {
this.$ready.push(this._init_tabview_handlers);
var cells = config.cells;
var tabs = [];
assert(cells && cells.length, "tabview must have cells collection");
for (var i = cells.length - 1; i >= 0; i--) {
var view = cells[i].body || cells[i];
if (!view.id) view.id = "view" + uid();
tabs[i] = {
value: cells[i].header,
id: view.id,
close: cells[i].close,
width: cells[i].width,
hidden: !!cells[i].hidden
};
cells[i] = view;
}
var tabbar = {
view: "tabbar",
multiview: true
};
var mview = {
view: "multiview",
cells: cells,
animate: !!config.animate
};
if (config.value) tabbar.value = config.value;
if (config.tabbar) exports.extend(tabbar, config.tabbar, true);
if (config.multiview) exports.extend(mview, config.multiview, true);
tabbar.options = tabbar.options || tabs;
config.rows = [tabbar, mview];
delete config.cells;
delete config.tabs;
},
_init_tabview_handlers: function () {
this.getTabbar().attachEvent("onOptionRemove", function (id) {
var view = $$(id);
if (view) {
var parent = view.getParentView();
if (parent) parent.removeView(view);
}
});
}
};
var view$h = exports.protoUI(api$h, layout.view);
var api$i = {
name: "carousel",
defaults: {
scrollSpeed: "300ms",
type: "clean",
navigation: {},
animate: true
},
$init: function () {
this._viewobj.className += " webix_carousel";
this._layout = null;
this._dataobj = null;
this._active_cell = 0;
this.$ready.unshift(this._initLayout);
this.$ready.push(this._after_init_call);
},
addView: function (view, index) {
var t = this._layout.addView(view, index);
this._fix_after_view_add();
return t;
},
removeView: function (id) {
this._layout.removeView(id);
this._fix_after_view_add();
},
_replace: function (new_view, target_id) {
this._layout._replace(new_view, target_id);
this._fix_after_view_add();
},
_fix_after_view_add: function () {
this._cells = this._layout._cells;
this._renderPanel();
this.setActiveIndex(Math.min(this._active_cell, this._cells.length - 1));
},
_initLayout: function () {
var _this = this;
if (this._layout && this._layout.destructor) this._layout.destructor();
var layout = "";
if (this.config.cols) {
layout = "cols";
this._vertical_orientation = 0;
} else {
layout = "rows";
this._vertical_orientation = 1;
}
var config = {
borderless: true,
type: "clean"
};
config[layout] = copy(this._settings[layout]);
var layoutProp = ["type", "margin", "marginX", "marginY", "padding", "paddingX", "paddingY"];
var layoutConfig = {};
for (var i = 0; i < layoutProp.length; i++) {
if (this._settings[layoutProp[i]]) {
layoutConfig[layoutProp[i]] = this._settings[layoutProp[i]];
}
}
exports.extend(config, layoutConfig, true);
state._parent_cell = this;
this._layout = ui._view(config);
this._viewobj.appendChild(this._layout._viewobj);
this._cells = this._layout._cells;
this._layout._show = bind(api$i._show, this);
this._layout.adjustScroll = bind(api$i.adjustScroll, this);
var e1 = attachEvent("onReconstruct", function (view) {
if (view == _this._layout) _this._setScroll();
});
this.attachEvent("onDestruct", function () {
detachEvent(e1);
});
this._contentobj = this._viewobj.firstChild;
},
_onKeyPress: function (code, e) {
if (this._settings.navigation.items && e.target.getAttribute("role") === "tab") this._moveActive(code, e);
base.api._onKeyPress.call(this, code, e);
},
getChildViews: function () {
return [this._layout];
},
getLayout: function () {
return this._layout;
},
_after_init_call: function () {
this._contentobj.setAttribute("touch_scroll", this._vertical_orientation ? "y" : "x");
this._layout.attachEvent("onAfterScroll", bind(function () {
this.callEvent("onShow", [this.getActiveId()]);
}, this));
_each(this._layout, function (view) {
view._viewobj.setAttribute("role", "tabpanel");
});
},
adjustScroll: function (matrix) {
var size = this._vertical_orientation ? this._content_height : this._content_width;
var correction;
if (this._vertical_orientation) {
correction = Math.round(matrix.f / size);
matrix.f = correction * size;
} else {
correction = Math.round(matrix.e / size);
matrix.e = correction * size;
}
this._active_cell = -correction;
if (this._settings.navigation) this._renderNavItems();
return true;
},
_show: function (obj) {
var i, layout, _nextCell, _size, x, y;
_nextCell = -1;
layout = this._layout;
for (i = 0; i < layout._cells.length; i++) {
if (layout._cells[i] == obj) {
_nextCell = i;
break;
}
}
if (_nextCell < 0 || _nextCell == this._active_cell) return;
this._active_cell = _nextCell;
_size = layout._vertical_orientation ? this._content_height : this._content_width;
x = -(layout._vertical_orientation ? 0 : _nextCell * _size);
y = -(layout._vertical_orientation ? _nextCell * _size : 0);
this.scrollTo(x, y);
this.callEvent("onShow", [layout._cells[this._active_cell]._settings.id]);
if (this._settings.navigation) this._renderPanel();
},
scrollTo: function (x, y) {
if (Touch && animate.isSupported() && this._settings.animate) Touch._set_matrix(this._contentobj, x, y, this._settings.scrollSpeed || "100ms");else {
this._contentobj.style.marginLeft = x + "px";
this._contentobj.style.marginTop = y + "px";
}
},
navigation_setter: function (config) {
this._mergeSettings(config, {
type: "corner",
buttons: true,
items: true
});
return config;
},
showNext: function () {
if (this._active_cell < this._layout._cells.length - 1) this.setActiveIndex(this._active_cell + 1);
},
showPrev: function () {
if (this._active_cell > 0) this.setActiveIndex(this._active_cell - 1);
},
setActiveIndex: function (value) {
assert(value < this._layout._cells.length, "Not existing index in collection");
var id = this._layout._cells[value]._settings.id;
$$(id).show();
},
getActiveIndex: function () {
return this._active_cell;
},
$getSize: function (dx, dy) {
var layoutSizes = this._layout.$getSize(0, 0);
var selfSizes = base$1.api.$getSize.call(this, dx, dy);
if (this._layout._vertical_orientation) {
selfSizes[0] = Math.max(selfSizes[0], layoutSizes[0]);
selfSizes[1] = Math.min(selfSizes[1], layoutSizes[1]);
} else {
selfSizes[2] = Math.max(selfSizes[2], layoutSizes[2]);
selfSizes[3] = Math.min(selfSizes[3], layoutSizes[3]);
}
return selfSizes;
},
$setSize: function (x, y) {
var layout = this._layout;
var c = layout._cells.length;
var changed = base$1.api.$setSize.call(this, x, y);
var yc = this._content_height * (layout._vertical_orientation ? c : 1);
var xc = this._content_width * (layout._vertical_orientation ? 1 : c);
if (changed) {
this._contentobj.style.height = yc + "px";
this._contentobj.style.width = xc + "px";
layout.$setSize(xc, yc);
this._setScroll();
} else layout.$setSize(xc, yc);
},
_setScroll: function () {
var layout = this._layout;
var activeCell = this._active_cell || 0;
var size = layout._vertical_orientation ? this._content_height : this._content_width;
var x = -(layout._vertical_orientation ? 0 : activeCell * size);
var y = -(layout._vertical_orientation ? activeCell * size : 0);
this.scrollTo(x, y);
if (this._settings.navigation) this._renderPanel();
},
getActiveId: function () {
var cell = this._layout._cells[this._active_cell];
return cell ? cell._settings.id : null;
},
setActive: function (value) {
$$(value).show();
}
};
var view$i = exports.protoUI(api$i, EventSystem, NavigationButtons, base$1.view);
var api$j = {
name: "proxy",
body_setter: function (value) {
state._parent_cell = this;
this._body_cell = ui._view(value);
this._viewobj.appendChild(this._body_cell._viewobj);
return value;
},
getChildViews: function () {
return [this._body_cell];
},
$setSize: function (x, y) {
base$1.api.$setSize.call(this, x, y);
this._body_cell.$setSize(this.$width, this.$height);
},
$getSize: function (dx, dy) {
var selfSize = base$1.api.$getSize.call(this, dx, dy);
var size = this._body_cell.$getSize(dx, dy);
size[0] = Math.max(selfSize[0], size[0]);
size[1] = Math.min(selfSize[1], size[1]);
size[2] = Math.max(selfSize[2], size[2]);
size[3] = Math.min(selfSize[3], size[3]);
size[4] = Math.max(selfSize[4], size[4]);
return size;
},
_replace: function (n) {
this._body_cell.destructor();
this._body_cell = n;
this._viewobj.appendChild(n._viewobj);
this.resize();
}
};
var view$j = exports.protoUI(api$j, base$1.view);
exports.protoUI({
name: "portlet",
defaults: {
template: "GPL version doesn't support portlet <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "dashboard",
defaults: {
template: "GPL version doesn't support dashboard <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "panel",
defaults: {
template: "GPL version doesn't support panel <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "abslayout",
defaults: {
template: "GPL version doesn't support abslayout <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "gridlayout",
defaults: {
template: "GPL version doesn't support gridlayout <br> You need Webix PRO"
}
}, template$1.view);
var api$k = {
$init: function () {
exports.extend(this, FlexLayout, true);
},
name: "flexlayout"
};
var view$k = exports.protoUI(api$k, layout.view);
exports.protoUI({
name: "flexdatalayout",
defaults: {
template: "GPL version doesn't support flexdatalayout <br> You need Webix PRO"
}
}, template$1.view);
var api$l = {
name: "popup",
$init: function () {
var _this = this;
this._settings.head = false;
this.$view.className += " webix_popup";
var clickHandler = attachEvent("onClick", function (e) {
return _this._hide(e);
});
this.attachEvent("onDestruct", function () {
detachEvent(clickHandler);
});
this.attachEvent("onHide", this._hide_point);
},
$skin: function () {
window$1.api.$skin.call(this);
this.defaults.padding = $active.popupPadding;
this.defaults.point = !$active.popupNoPoint;
this.defaults.borderless = $active.borderlessPopup;
},
close: function () {
remove(this._point_element);
window$1.api.close.call(this);
},
$getSize: function (x, y) {
return window$1.api.$getSize.call(this, x + this._settings.padding * 2, y + this._settings.padding * 2);
},
$setSize: function (x, y) {
base$1.api.$setSize.call(this, x, y);
x = this._content_width - this._settings.padding * 2;
y = this._content_height - this._settings.padding * 2;
this._contentobj.style.padding = this._settings.padding + "px";
this._headobj.style.display = "none";
this._body_cell.$setSize(x, y);
},
//redefine to preserve inner borders
//_inner_body_set:function(){}, //same as win?
_inner_body_set: function (value) {
if (typeof value.borderless == "undefined") value.borderless = false;
},
head_setter: function () {},
_set_point: function (mode, left, top, fixed) {
this._hide_point();
document.body.appendChild(this._point_element = create("DIV", {
"class": "webix_point_" + mode
}, ""));
this._point_element.style.zIndex = this._viewobj.style.zIndex;
this._point_element.style.position = fixed ? "fixed" : "absolute";
this._point_element.style.top = top + "px";
this._point_element.style.left = left + "px";
},
_hide_point: function () {
this._point_element = remove(this._point_element);
}
};
var view$l = exports.protoUI(api$l, window$1.view);
var popup = {
api: api$l,
view: view$l
};
var api$m = {
name: "toolbar",
defaults: {
type: "toolbar"
},
_render_borders: true,
_form_classname: "webix_toolbar",
_form_vertical: false,
$init: function (config) {
if (!config.borderless) {
this._contentobj.style.borderWidth = "1px";
this._settings._inner = {
top: false,
left: false,
right: false,
bottom: false
};
}
this._contentobj.className += " " + this._form_classname;
this._viewobj.setAttribute("role", "toolbar");
},
_recollect_elements: function () {
var form = this;
form.elements = {};
_each(this, function (view) {
if (view._settings.name && view.getValue && view.setValue) {
form.elements[view._settings.name] = view;
if (view.mapEvent) view.mapEvent({
onbeforetabclick: form,
onaftertabclick: form,
onitemclick: form,
onchange: form
});
}
if (view.setValues || view._fill_data) return false;
});
var old = this._values;
this.setDirty(false);
if (old) {
//restore dirty state after form reconstructing
var now = this._values;
for (var key in form.elements) {
if (old[key] && now[key] != old[key]) {
now[key] = old[key];
this.setDirty(true);
}
}
}
},
_parse_cells_ext_end: function () {
this._recollect_elements();
},
_parse_cells_ext: function (collection) {
var config = this._settings;
if (config.elements && !collection) {
this._collection = collection = config.elements;
this._vertical_orientation = this._form_vertical;
delete config.elements;
}
if (this._settings.elementsConfig) this._rec_apply_settings(this._collection, config.elementsConfig);
return collection;
},
_rec_apply_settings: function (col, settings) {
for (var i = 0; i < col.length; i++) {
var element = col[i];
exports.extend(element, settings);
var nextsettings = settings;
if (element.elementsConfig) nextsettings = exports.extend(exports.extend({}, element.elementsConfig), settings);
var sub;
if (element.body) sub = [element.body];else sub = element.rows || element.cols || element.cells || element.body;
if (sub) this._rec_apply_settings(sub, nextsettings);
}
},
$getSize: function (dx, dy) {
var sizes = layout.api.$getSize.call(this, dx, dy);
var parent = this.getParentView();
var index = this._vertical_orientation ? 3 : 1;
if (parent && this._vertical_orientation != parent._vertical_orientation) sizes[index] += 100000;
debug_size_box(this, sizes, true);
return sizes;
},
render: function () {},
refresh: function () {
this.render();
}
};
var view$m = exports.protoUI(api$m, Scrollable, AtomDataLoader, Values, layout.view, ValidateData);
var toolbar = {
api: api$m,
view: view$m
};
var api$n = {
name: "form",
defaults: {
type: "form",
autoheight: true
},
_default_height: -1,
_form_classname: "webix_form",
_form_vertical: true,
$init: function () {
this._viewobj.setAttribute("role", "form");
},
$getSize: function (dx, dy) {
if (this._scroll_y && !this._settings.width) dx += env.scrollSize;
var sizes = layout.api.$getSize.call(this, dx, dy);
if (this._settings.scroll || !this._settings.autoheight) {
sizes[2] = this._settings.height || this._settings.minHeight || 0;
sizes[3] = this._settings.height || 100000;
}
return sizes;
}
};
var view$n = exports.protoUI(api$n, toolbar.view);
var api$o = {
name: "fieldset",
defaults: {
borderless: true,
$cssName: "webix_fieldset",
paddingX: 18,
paddingY: 30
},
$init: function (obj) {
obj.body = obj.body || {};
var css = this.defaults.$cssName;
this._viewobj.className += " " + css;
this._viewobj.innerHTML = "<fieldset><legend class='" + css + "_label" + (obj.required ? " webix_required" : "") + "'></legend><div class='" + css + "_body'></div></fieldset>";
},
label_setter: function (value) {
this._viewobj.firstChild.childNodes[0].innerHTML = value;
return value;
},
getChildViews: function () {
return [this._body_view];
},
body_setter: function (config) {
state._parent_cell = this;
this._body_view = ui(config, this._viewobj.firstChild.childNodes[1]);
return config;
},
getBody: function () {
return this._body_view;
},
resizeChildren: function () {
if (!this._body_view) return;
var x = this.$width - this._settings.paddingX;
var y = this.$height - this._settings.paddingY;
var sizes = this._body_view.$getSize(0, 0); //minWidth
if (sizes[0] > x) x = sizes[0]; //minHeight
if (sizes[2] > y) y = sizes[2];
this._body_view.$setSize(x, y);
this.resize();
},
$getSize: function (x, y) {
debug_size_box_start(this, true);
x += this._settings.paddingX;
y += this._settings.paddingY;
var t = this._body_view.$getSize(x, y);
var s = this._last_body_size = base$1.api.$getSize.call(this, x, y); //inner content minWidth > outer
if (s[0] < t[0]) s[0] = t[0];
if (s[2] < t[2]) s[2] = t[2]; //inner content maxWidth < outer
if (s[1] > t[1]) s[1] = t[1];
if (s[3] > t[3]) s[3] = t[3]; //make max size not less than min size
if (s[1] < s[0]) s[1] = s[0];
if (s[3] < s[2]) s[3] = s[2];
debug_size_box_end(this, s);
return s;
},
$setSize: function (x, y) {
if (base$1.api.$setSize.call(this, x, y)) {
x = Math.min(this._last_body_size[1], x);
y = Math.min(this._last_body_size[3], y);
this._body_view.$setSize(x - this._settings.paddingX, y - this._settings.paddingY);
}
}
};
var view$o = exports.protoUI(api$o, base$1.view);
var fieldset = {
api: api$o,
view: view$o
};
var api$p = {
name: "forminput",
defaults: {
$cssName: "webix_forminput",
labelWidth: 80,
labelAlign: "left",
// remove fieldset sizing
paddingY: 0,
paddingX: 0
},
setValue: function (value, config) {
if (this._body_view.setValue) this._body_view.setValue(value, config);else if (this._body_view.setValues) this._body_view.setValues(value, false, config);
},
focus: function () {
if (this._body_view.focus) {
return this._body_view.focus();
}
return false;
},
getValue: function () {
if (this._body_view.getValue) return this._body_view.getValue();else if (this._body_view.getValues) return this._body_view.getValues();
},
getBody: function () {
return this._body_view;
},
$skin: function () {
this._inputPadding = $active.inputPadding;
this._inputSpacing = $active.inputSpacing;
this._labelTopHeight = $active.labelTopHeight;
},
$init: function () {
this.$ready.push(function () {
var label = this._viewobj.firstChild.childNodes[0];
var body = this._viewobj.firstChild.childNodes[1];
var config = this._settings;
if (config.labelPosition != "top") {
config.labelWidth = config.label ? this._getLabelWidth(config.labelWidth, config.label) : 0;
config.paddingX = config.labelWidth + this._inputSpacing;
} else {
config.paddingY = this._labelTopHeight;
config.paddingX = this._inputSpacing;
}
if (!config.label || !config.labelWidth && config.labelPosition != "top") {
label.style.display = "none";
body.style.padding = "0 " + this._inputSpacing / 2 + "px";
config.paddingX = this._inputSpacing;
config.paddingY = 0;
return;
}
if (config.labelPosition == "top") {
label.style.lineHeight = this._labelTopHeight - this._inputPadding + "px";
label.className += " " + this.defaults.$cssName + "_label_top";
body.style.padding = "0 " + this._inputSpacing / 2 + "px";
} else label.style.width = config.paddingX - this._inputSpacing / 2 + "px";
label.style.textAlign = config.labelAlign;
if (config.value) this.setValue(config.value, "auto");
});
},
_getLabelWidth: function (width, label) {
if (width == "auto") width = getTextSize(label, "webix_inp_label").width;
return width ? Math.max(width, $active.dataPadding) : 0;
},
setBottomText: function (text) {
var config = this._settings;
if (typeof text != "undefined") {
if (config.bottomLabel == text) return;
config.bottomLabel = text;
}
var message = (config.invalid ? config.invalidMessage : "") || config.bottomLabel;
if (this._invalidMessage) {
remove(this._invalidMessage);
}
if (message) {
this.$view.style.position = "relative";
this._invalidMessage = create("div", {
"class": "webix_inp_bottom_label",
role: config.invalid ? "alert" : "",
"aria-relevant": "all",
style: "position:absolute; bottom:0px; padding:2px 0; background: white; left:" + (this._inputSpacing / 2 + (config.label ? config.labelWidth : 0)) + "px; "
}, message);
this._viewobj.appendChild(this._invalidMessage);
}
}
};
var view$p = exports.protoUI(api$p, fieldset.view);
function _tagname(el) {
if (!el.tagName) return null;
return el.tagName.toLowerCase();
}
function _attribute(el, name) {
if (!el.getAttribute) return null;
var attr = el.getAttribute(name);
return attr ? attr.toLowerCase() : null;
}
function _get_html_value() {
var tagname = _tagname(this);
if (_get_value[tagname]) return _get_value[tagname](this);
return _get_value.other(this);
}
var _get_value = {
radio: function (el) {
for (var i = 0; i < el.length; i++) {
if (el[i].checked) return el[i].value;
}
return "";
},
input: function (el) {
var type = _attribute(el, "type");
if (type === "checkbox") return el.checked;
return el.value;
},
textarea: function (el) {
return el.value;
},
select: function (el) {
var index$$1 = el.selectedIndex;
return el.options[index$$1].value;
},
other: function (el) {
return el.innerHTML;
}
};
function _set_html_value(value) {
var tagname = _tagname(this);
if (_set_value[tagname]) return _set_value[tagname](this, value);
return _set_value.other(this, value);
}
var _set_value = {
radio: function (el, value) {
for (var i = 0; i < el.length; i++) {
el[i].checked = el[i].value == value;
}
},
input: function (el, value) {
var type = _attribute(el, "type");
if (type === "checkbox") el.checked = value ? true : false;else el.value = value;
},
textarea: function (el, value) {
el.value = value;
},
select: function (el, value) {
el.value = value; //incorrect option applied, select first option
if (el.selectedIndex === -1) el.value = el.firstElementChild.value;
},
other: function (el, value) {
el.innerHTML = value;
}
};
var api$q = {
name: "htmlform",
$init: function (config) {
this.elements = {};
this._default_values = false;
if (config.content && (config.container == config.content || !config.container && config.content == document.body)) this._copy_inner_content = true;
},
content_setter: function (content) {
content = toNode(content);
if (this._copy_inner_content) {
while (content.childNodes.length > 1) {
this._viewobj.childNodes[0].appendChild(content.childNodes[0]);
}
} else {
this._viewobj.childNodes[0].appendChild(content);
}
this._parse_inputs();
return true;
},
render: function () {
template$1.api.render.apply(this, arguments);
this._parse_inputs();
},
_parse_inputs: function () {
var inputs = this._viewobj.querySelectorAll("[name]");
this.elements = {};
for (var i = 0; i < inputs.length; i++) {
var el = inputs[i];
var name = _attribute(el, "name");
if (name) {
var tag = _tagname(el) === "button";
var type = _attribute(el, "type");
var cant_clear = tag || type === "button" || type === "submit";
if (type === "radio") {
var stack = this.elements[name] || [];
stack.tagName = "radio";
stack.push(el);
el = stack;
}
this.elements[name] = el;
el.getValue = _get_html_value;
el.setValue = _set_html_value;
el.$allowsClear = !cant_clear;
}
}
return this.elements;
},
_mark_invalid: function (id, obj) {
this._clear_invalid(id, obj);
var el = this._viewobj.querySelector("[name=\"" + id + "\"]");
if (el) addCss(el, "invalid");
},
_clear_invalid: function (id) {
var el = this._viewobj.querySelector("[name=\"" + id + "\"]");
if (el) removeCss(el, "invalid");
},
focus: function (name) {
if (!name && this.$view.contains(document.activeElement)) {
// focus already inside of form, leaving
return false;
}
Values.focus.apply(this, arguments);
}
};
var view$q = exports.protoUI(api$q, template$1.view, Values);
var api$r = {
name: "property",
$init: function () {
this._contentobj.className += " webix_property";
this._contentobj.setAttribute("role", "listbox");
this._destroy_with_me = [];
this.attachEvent("onAfterEditStart", function (id) {
var node = this.getItemNode(id);
addCss(node, "webix_focused");
});
this.attachEvent("onAfterEditStop", function (id, editor) {
var node = this.getItemNode(editor.config.id);
removeCss(node, "webix_focused");
});
},
defaults: {
nameWidth: 100,
editable: true
},
on_render: {
password: function (value) {
return !value && value !== 0 ? "" : "•".repeat(value.toString().length);
},
checkbox: function (value) {
return "<input type='checkbox' class='webix_property_check' " + (value ? "checked" : "") + ">";
},
color: function (value) {
return "<div class='webix_property_col_ind' style='background-color:" + (value || "#FFFFFF") + ";'></div>" + value;
}
},
on_edit: {
label: false
},
_id:
/*@attr*/
"webix_f_id",
on_click: {
webix_property_check: function (ev) {
var id = this.locate(ev);
var item = this.getItem(id);
this.callEvent("onCheck", [id, item.value = !item.value]);
return false;
}
},
on_dblclick: {},
registerType: function (name, data) {
if (!isUndefined(data.template)) this.on_render[name] = data.template;
if (!isUndefined(data.editor)) this.on_edit[name] = data.editor;
if (!isUndefined(data.click)) for (var key in data.click) {
this.on_click[key] = data.click[key];
}
},
elements_setter: function (data) {
this._idToLine = {};
for (var i = 0; i < data.length; i++) {
var line = data[i];
if (line.type == "multiselect") line.optionslist = true; //line.type = line.type||"label";
line.id = line.id || uid();
line.label = line.label || "";
line.value = line.value || "";
this._idToLine[line.id] = i;
this._map_options(data[i]);
}
return data;
},
showItem: function (id) {
RenderStack.showItem.call(this, id);
},
locate: function () {
return locate(arguments[0], this._id);
},
getItemNode: function (id) {
return this._dataobj.childNodes[this._idToLine[id]];
},
getItem: function (id) {
return this._settings.elements[this._idToLine[id]];
},
_get_editor_type: function (id) {
var type = this.getItem(id).type;
if (type == "checkbox") return "inline-checkbox";
var alter_type = this.on_edit[type];
return alter_type === false ? false : alter_type || type;
},
_get_edit_config: function (id) {
return this.getItem(id);
},
_find_cell_next: function (start, check, direction) {
var row = this._idToLine[start.id];
var order = this._settings.elements;
if (direction) {
for (var i = row + 1; i < order.length; i++) {
if (check.call(this, order[i].id)) return order[i].id;
}
} else {
for (var _i = row - 1; _i >= 0; _i--) {
if (check.call(this, order[_i].id)) return order[_i].id;
}
}
return null;
},
updateItem: function (key, data) {
var line = this.getItem(key);
if (line) exports.extend(line, data || {}, true);
this.refresh();
},
_cellPosition: function (id) {
var html = this.getItemNode(id);
return {
left: html.offsetLeft + this._settings.nameWidth,
top: html.offsetTop,
height: html.firstChild.offsetHeight,
width: this._data_width,
parent: this._contentobj
};
},
_clear: function () {
var lines = this._settings.elements;
for (var i = 0; i < lines.length; i++) {
lines[i].value = "";
}
},
clear: function () {
this._clear();
this._props_dataset = {};
this.refresh();
},
setValues: function (data, update) {
var _this = this;
if (this._settings.complexData) data = CodeParser.collapseNames(data, "", {}, function (v) {
return isUndefined(_this._idToLine[v]);
});
if (!update) this._clear();
for (var key in data) {
var line = this.getItem(key);
if (line) line.value = data[key];
}
this._props_dataset = data;
this.refresh();
},
getValues: function () {
var data = clone(this._props_dataset || {});
for (var i = 0; i < this._settings.elements.length; i++) {
var line = this._settings.elements[i];
if (line.type != "label") data[line.id] = line.value;
}
if (this._settings.complexData) data = CodeParser.expandNames(data);
return data;
},
refresh: function () {
this.render();
},
$setSize: function (x, y) {
if (base$1.api.$setSize.call(this, x, y)) {
this._data_width = this._content_width - this._settings.nameWidth;
this.render();
}
},
$getSize: function (dx, dy) {
if (this._settings.autoheight) {
var count = this._settings.elements.length;
this._settings.height = Math.max(this.type.height * count, this._settings.minHeight || 0);
}
return base$1.api.$getSize.call(this, dx, dy);
},
_toHTML: function () {
var html = [];
var els = this._settings.elements;
if (els) for (var i = 0; i < els.length; i++) {
var data = els[i];
if (data.css && _typeof(data.css) == "object") data.css = createCss(data.css);
var pre = "<div " +
/*@attr*/
"webix_f_id" + "=\"" + data.id + "\"" + (data.type !== "label" ? "role=\"option\" tabindex=\"0\"" : "") + " class=\"webix_property_line " + (data.css || "") + "\">";
if (data.type == "label") html[i] = pre + "<div class='webix_property_label_line'>" + data.label + "</div></div>";else {
var render = this.on_render[data.type],
content;
var post = "<div class='webix_property_label' style='width:" + this._settings.nameWidth + "px'>" + data.label + "</div><div class='webix_property_value' style='width:" + this._data_width + "px'>";
if (data.collection || data.options) {
content = data.template(data);
} else if (data.format) {
content = data.format(data.value);
} else content = data.value;
if (render) content = render.call(this, data.value, data);
html[i] = pre + post + content + "</div></div>";
}
}
return html.join("");
},
type: {
height: 24,
templateStart: template(""),
templateEnd: template("</div>")
},
$skin: function () {
this.type.height = $active.propertyItemHeight;
}
};
var view$r = exports.protoUI(api$r, AutoTooltip, EditAbility, MapCollection, MouseEvents, Scrollable, SingleRender, AtomDataLoader, EventSystem, base$1.view);
var api$s = {
name: "calendar",
defaults: {
date: new Date(),
//selected date, not selected by default
navigation: true,
monthSelect: true,
weekHeader: true,
monthHeader: true,
weekNumber: false,
skipEmptyWeeks: false,
calendarHeader: "%F %Y",
//calendarTime: "%H:%i",
events: wDate.isHoliday,
minuteStep: 5,
timeIcon: "wxi-clock",
icons: false,
timepickerHeight: 30,
headerHeight: 30,
dayTemplate: function (d) {
return d.getDate();
},
width: 260,
height: 250
},
dayTemplate_setter: template,
calendarHeader_setter: wDate.dateToStr,
calendarTime_setter: function (format) {
this._calendarTime = format;
return wDate.dateToStr(format);
},
date_setter: function (date) {
return this._string_to_date(date);
},
maxDate_setter: function (date) {
return this._string_to_date(date);
},
minDate_setter: function (date) {
return this._string_to_date(date);
},
minTime_setter: function (time) {
if (typeof time == "string") {
time = i18n.parseTimeFormatDate(time);
time = [time.getHours(), time.getMinutes()];
}
return time;
},
maxTime_setter: function (time) {
if (typeof time == "string") {
time = i18n.parseTimeFormatDate(time);
time = [time.getHours(), time.getMinutes()];
}
return time;
},
_ariaFocus: function () {
var ev = "focus" + (env.isIE ? "in" : "");
if (!env.touch) {
_event(this.$view, ev, bind(function (e) {
var t = e.target.className;
var css = t.indexOf("webix_cal_day") !== -1 ? "webix_cal_day" : t.indexOf("webix_cal_block") !== -1 ? "webix_cal_block" : "";
if (new Date() - UIManager._tab_time > 300 && new Date() - UIManager._mouse_time > 100 && css) {
var prev = e.relatedTarget;
if (prev && !isUndefined(prev.className)) {
var date = css == "webix_cal_day" ? this._locate_day(e.target) : this._locate_date(e.target);
this._moveSelection(date);
}
}
}, this), {
capture: !env.isIE
});
}
},
$init: function () {
this._viewobj.className += " webix_calendar";
this._viewobj.setAttribute("role", "region");
this._viewobj.setAttribute("aria-label", i18n.aria.calendar); //special dates
this._special_dates = {};
this._selected_days = {};
this._zoom_level = 0; //navigation and aria
this._ariaFocus();
this.attachEvent("onKeyPress", this._onKeyPress);
},
minuteStep_setter: function (value) {
return Math.max(Math.min(value, 60), this.defaults.minuteStep);
},
type_setter: function (value) {
if (value == "time") {
this._zoom_in = true;
this._zoom_level = -1;
} else if (value == "year") {
this._fixed = true;
}
return value;
},
$setSize: function (x, y) {
if (base$1.api.$setSize.call(this, x, y)) {
//repaint calendar when size changed
this.render();
}
},
$getSize: function (dx, dy) {
var s = this._settings;
if (s.cellHeight && !s.type) {
var state = this._getDateBoundaries(s.date);
s.height = s.cellHeight * state._rows + s.headerHeight + (s.weekHeader ? $active.calendarWeekHeaderHeight : 0) + (s.timepicker || this._icons ? s.timepickerHeight : 0) + (this._content_padding + $active.borderWidth) * 2;
}
return base$1.api.$getSize.call(this, dx, dy);
},
moveSelection: function (mode, details, focus) {
if (this.config.master) return; //in daterange
var start = this.getSelectedDate();
if (this.config.multiselect) start = start[0];
var date = wDate.copy(start || this.getVisibleDate());
this._moveSelection(date, mode, focus);
},
_moveSelection: function (date, mode, focus) {
var css = this._zoom_logic[this._zoom_level]._keyshift(date, mode, this);
if (focus !== false) {
var sel = this._viewobj.querySelector("." + css + "[tabindex='0']");
if (sel) sel.focus();
}
},
_getDateBoundaries: function (date, reset) {
// addition information about rendering event:
// how many days from the previous month,
// next,
// number of weeks to display and so on
if (!this._set_date_bounds || reset) {
var month = date.getMonth();
var year = date.getFullYear();
var next = new Date(year, month + 1, 1);
var start = wDate.weekStart(new Date(year, month, 1));
var days = Math.round((next.valueOf() - start.valueOf()) / (60 * 1000 * 60 * 24));
var rows = this._settings.skipEmptyWeeks ? Math.ceil(days / 7) : 6;
this._set_date_bounds = {
_month: month,
_start: start,
_next: next,
_rows: rows
};
}
return this._set_date_bounds;
},
$skin: function () {
if ($active.calendar) {
if ($active.calendar.width) this.defaults.width = $active.calendar.width;
if ($active.calendar.height) this.defaults.height = $active.calendar.height;
if ($active.calendar.headerHeight) this.defaults.headerHeight = $active.calendar.headerHeight;
if ($active.calendar.timepickerHeight) this.defaults.timepickerHeight = $active.calendar.timepickerHeight;
}
this._content_padding = $active.layoutPadding.form;
},
_getColumnConfigSizes: function (date) {
var bounds = this._getDateBoundaries(date);
var s = this._settings;
var _columnsHeight = [];
var _columnsWidth = [];
var min = Infinity;
var containerWidth = this._content_width - (this._content_padding + $active.borderWidth) * 2;
var containerHeight = this._content_height - (s.monthHeader ? s.headerHeight : 0) - (s.weekHeader ? $active.calendarWeekHeaderHeight : 0) - (s.timepicker || this._icons ? s.timepickerHeight : 0) - (this._content_padding + $active.borderWidth) * 2;
var columnsNumber = s.weekNumber ? 8 : 7;
for (var i = 0; i < columnsNumber; i++) {
_columnsWidth[i] = Math.ceil(containerWidth / (columnsNumber - i));
containerWidth -= _columnsWidth[i];
min = Math.min(min, _columnsWidth[i]);
}
var rowsNumber = bounds._rows;
for (var k = 0; k < rowsNumber; k++) {
_columnsHeight[k] = Math.ceil(containerHeight / (rowsNumber - k));
containerHeight -= _columnsHeight[k];
min = Math.min(min, _columnsHeight[k]);
}
return [_columnsWidth, _columnsHeight, min];
},
icons_setter: function (value) {
if (!value) this._icons = null;else if (_typeof(value) == "object") this._icons = value;else this._icons = this._icons2;
},
_icons: [],
_icons2: [{
template: function () {
return "<span role='button' tabindex='0' class='webix_cal_icon_today webix_cal_icon'>" + i18n.calendar.today + "</span>";
},
on_click: {
"webix_cal_icon_today": function () {
var date = new Date();
if (!this._settings.timepicker) date = wDate.datePart(date);
this.setValue(date, "user");
this.callEvent("onTodaySet", [this.getSelectedDate()]);
}
}
}, {
template: function () {
return "<span role='button' tabindex='0' class='webix_cal_icon_clear webix_cal_icon'>" + i18n.calendar.clear + "</span>";
},
on_click: {
"webix_cal_icon_clear": function () {
this.setValue("", "user");
this.callEvent("onDateClear", [this.getSelectedDate()]);
}
}
}],
refresh: function () {
this.render();
},
render: function () {
//reset zoom level
this._zoom_level = 0;
this._zoom_size = false;
var s = this._settings;
if (!this.isVisible(s.id)) return;
this._current_time = wDate.datePart(new Date());
this.callEvent("onBeforeRender", []);
var date = this._settings.date;
var bounds = this._getDateBoundaries(date, true);
var sizes = this._getColumnConfigSizes(date);
var cpad = this._content_padding + "px";
var width = sizes[0];
var height = sizes[1];
var html = "";
if (s.monthHeader) {
html += "<div class='webix_cal_month' style='margin:0 " + cpad + "'><span aria-live='assertive' aria-atomic='true' class='webix_cal_month_name" + (!s.monthSelect || !s.navigation ? " webix_readonly'" : "' role='button' tabindex='0'") + ">" + s.calendarHeader(date) + "</span>";
if (s.navigation) html += "<div role='button' tabindex='0' aria-label='" + i18n.aria.navMonth[0] + "' class='webix_cal_prev_button'></div><div role='button' tabindex='0' aria-label='" + i18n.aria.navMonth[1] + "' class='webix_cal_next_button'></div>";
html += "</div>";
}
if (s.weekHeader) html += "<div class='webix_cal_header' style='margin:0 " + cpad + "' aria-hidden='true'>" + this._week_template(width) + "</div>";
html += "<div class='webix_cal_body' style='margin:0 " + cpad + "'>" + this._body_template(width, height, bounds, sizes[2]) + "</div>";
if (this._settings.timepicker || this._icons) {
html += "<div class='webix_cal_footer' style='margin:0 " + cpad + "'>";
if (this._settings.timepicker) html += this._timepicker_template(date);
if (this._icons) html += this._icons_template();
html += "</div>";
}
this._contentobj.innerHTML = html;
this._contentobj.firstChild.style.marginTop = cpad;
if (this._settings.type == "time") {
var time = this._settings.date;
if (time) {
if (typeof time == "string") {
date = i18n.parseTimeFormatDate(time);
} else if (isArray(time)) {
date.setHours(time[0]);
date.setMinutes(time[1]);
}
}
this._changeZoomLevel(-1, date);
} else if (this._settings.type == "month") {
this._changeZoomLevel(1, date);
} else if (this._settings.type == "year") {
this._changeZoomLevel(2, date);
}
this._fix_cover();
this.callEvent("onAfterRender", []);
},
_icons_template: function (date) {
var html = "<div class='webix_cal_icons'>";
var icons = this._icons;
for (var i = 0; i < icons.length; i++) {
if (icons[i].template) {
var template$$1 = typeof icons[i].template == "function" ? icons[i].template : template$$1(icons[i].template);
html += template$$1.call(this, date);
}
if (icons[i].on_click) {
exports.extend(this.on_click, icons[i].on_click);
}
}
html += "</div>";
return html;
},
_timepicker_template: function (date) {
var timeFormat = this._settings.calendarTime || i18n.timeFormatStr;
var clock = this._settings.timeIcon;
var tpl = "";
if (!this._settings.master) tpl = "<div role='button' tabindex='0' class='webix_cal_time" + (this._icons ? " webix_cal_time_icons" : "") + "'><span class='webix_icon " + clock + "'></span> " + timeFormat(date) + "</div>";else {
//daterange needs two clocks
var range_date = copy($$(this._settings.master)._settings.value);
if (wDate.equal(range_date.end, date)) range_date.start = range_date.end;
for (var i in range_date) {
tpl += "<div role='button' tabindex='0' class='webix_range_time_" + i + " webix_cal_time'><span class='webix_icon " + clock + "'></span> " + timeFormat(range_date[i]) + "</div>";
}
}
return tpl;
},
_week_template: function (widths) {
var s = this._settings;
var week_template = "";
var correction = 0;
if (s.weekNumber) {
correction = 1;
week_template += "<div class='webix_cal_week_header' style='width: " + widths[0] + "px;' >" + (s.calendarWeekHeader || "") + "</div>";
}
var k = wDate.startOnMonday ? 1 : 0;
for (var i = 0; i < 7; i++) {
// 7 days total
var day_index = (k + i) % 7; // 0 - Sun, 6 - Sat as in Locale.date.day_short
var day = i18n.calendar.dayShort[day_index]; // 01, 02 .. 31
week_template += "<div day='" + day_index + "' style='width: " + widths[i + correction] + "px;' >" + day + "</div>";
}
return week_template;
},
blockDates_setter: function (value) {
return toFunctor(value, this.$scope);
},
_day_css: function (day, bounds) {
var css = "",
isOutside = false;
if (wDate.equal(day, this._current_time)) css += " webix_cal_today";
if (!this._checkDate(day)) css += " webix_cal_day_disabled";
if (day.getMonth() != bounds._month) {
isOutside = true;
css += " webix_cal_outside";
}
if (!isOutside && this._selectedDay(day)) css += " webix_cal_select";
if (this._settings.events) css += " " + (this._settings.events(day, isOutside) || "");
css += " webix_cal_day";
return css;
},
_body_template: function (widths, heights, bounds, sqSize) {
var s = this._settings;
var html = "";
var day = wDate.datePart(wDate.copy(bounds._start));
var start = s.weekNumber ? 1 : 0;
var weekNumber = wDate.getISOWeek(wDate.add(day, 2, "day", true));
for (var y = 0; y < heights.length; y++) {
html += "<div class='webix_cal_row' style='height:" + heights[y] + "px;line-height:" + heights[y] + "px'>";
if (start) {
// recalculate week number for the first week of a year
if (!day.getMonth() && day.getDate() < 7) weekNumber = wDate.getISOWeek(wDate.add(day, 2, "day", true));
html += "<div class='webix_cal_week_num' aria-hidden='true' style='width:" + widths[0] + "px'>" + weekNumber + "</div>";
}
for (var x = start; x < widths.length; x++) {
var css = this._day_css(day, bounds);
var d = this._settings.dayTemplate.call(this, day);
var sel = this._selectedDay(day);
var alabel = "";
var isOutside = day.getMonth() != bounds._month;
if (_typeof(d) == "object") {
alabel = d.aria || alabel;
d = d.text;
} else alabel = wDate.dateToStr(i18n.aria.dateFormat)(day);
html += "<div day='" + x + "' role='gridcell' " + (isOutside ? "aria-hidden='true'" : "") + " aria-label='" + alabel + "' tabindex='" + (sel && !isOutside ? "0" : "-1") + "' aria-selected='" + (sel && !isOutside ? "true" : "false") + "' class='" + css + "' style='text-align:center; width:" + widths[x] + "px'><span aria-hidden='true' class='webix_cal_day_inner' style='display:inline-block; " + this._getCalSizesString(sqSize, sqSize) + "'>" + d + "</span></div>";
day = wDate.add(day, 1, "day");
if (day.getHours()) {
day = wDate.datePart(day);
}
}
html += "</div>";
weekNumber++;
}
return html;
},
_changeDate: function (dir, step) {
var now = this._settings.date;
if (!step) {
step = this._zoom_logic[this._zoom_level]._changeStep;
}
if (!this._zoom_level) {
now = wDate.copy(now);
now.setDate(1);
}
var next = wDate.add(now, dir * step, "month", true);
this._changeDateInternal(now, next);
},
_changeDateInternal: function (now, next) {
if (this.callEvent("onBeforeMonthChange", [now, next])) {
if (this._zoom_level) {
this._update_zoom_level(next);
} else {
this.showCalendar(next);
}
this.callEvent("onAfterMonthChange", [next, now]);
}
},
_zoom_logic: {
"-2": {
_isBlocked: function (i) {
var config = this._settings,
date = config.date,
isBlocked = false;
var minHour = config.minTime ? config.minTime[0] : 0;
var maxHour = config.maxTime ? config.maxTime[0] + (config.maxTime[1] ? 1 : 0) : 24;
var minMinute = config.minTime && date.getHours() == minHour ? config.minTime[1] : 0;
var maxMinute = config.maxTime && config.maxTime[1] && date.getHours() == maxHour - 1 ? config.maxTime[1] : 60;
if (this._settings.blockTime) {
var d = wDate.copy(date);
d.setMinutes(i);
isBlocked = this._settings.blockTime(d);
}
return i < minMinute || i >= maxMinute || isBlocked;
},
_setContent: function (next, i) {
next.setMinutes(i);
},
_findActive: function (date, mode, calendar) {
if (!this._isBlocked.call(calendar, date.getMinutes())) return date;else {
var step = calendar._settings.minuteStep;
var newdate = wDate.add(date, mode == "right" ? step : -step, "minute", true);
if (date.getHours() === newdate.getHours()) return this._findActive(newdate, mode, calendar);
}
}
},
"-1": {
_isBlocked: function (i) {
var config = this._settings,
date = config.date;
var minHour = config.minTime ? config.minTime[0] : 0;
var maxHour = config.maxTime ? config.maxTime[0] + (config.maxTime[1] ? 1 : 0) : 24;
if (i < minHour || i >= maxHour) return true;
if (config.blockTime) {
var d = wDate.copy(date);
d.setHours(i);
var minMinute = config.minTime && i == minHour ? config.minTime[1] : 0;
var maxMinute = config.maxTime && config.maxTime[1] && i == maxHour - 1 ? config.maxTime[1] : 60;
for (var j = minMinute; j < maxMinute; j += config.minuteStep) {
d.setMinutes(j);
if (!config.blockTime(d)) return false;
}
return true;
}
},
_setContent: function (next, i) {
next.setHours(i);
},
_keyshift: function (date, mode, calendar) {
var newdate,
inc,
step = calendar._settings.minuteStep;
if (mode === "bottom" || mode === "top") {
date.setHours(mode === "bottom" ? 23 : 0);
date.setMinutes(mode === "bottom" ? 55 : 0);
date.setSeconds(0);
date.setMilliseconds(0);
newdate = date;
} else if (mode === "left" || mode === "right") {
//minutes
inc = mode === "right" ? step : -step;
if (mode === "left" && date.getMinutes() < step) inc = 60 - step;
if (mode === "right" && date.getMinutes() >= 60 - step) inc = step - 60;
inc -= date.getMinutes() % step;
newdate = calendar._zoom_logic["-2"]._findActive(wDate.add(date, inc, "minute"), mode, calendar);
} else if (mode === "up" || mode === "down") {
//hours
inc = mode === "down" ? 1 : -1;
if (mode === "down" && date.getHours() === 23) inc = -23;
if (mode === "up" && date.getHours() === 0) inc = 23;
newdate = this._findActive(wDate.add(date, inc, "hour"), mode, calendar);
} else if (mode === false) newdate = this._findActive(date, mode, calendar);
calendar.selectDate(newdate, false, false, "user");
if (newdate) {
calendar._update_zoom_level(newdate);
calendar.selectDate(newdate, false, false, "user");
}
return "webix_cal_block" + (mode === "left" || mode === "right" ? "_min" : "");
},
_findActive: function (date, mode, calendar) {
if (!this._isBlocked.call(calendar, date.getHours())) return date;else {
var newdate = wDate.add(date, mode == "down" ? 1 : -1, "hour", true);
if (date.getDate() === newdate.getDate()) return this._findActive(newdate, mode, calendar);
}
}
},
"0": {
//days
_changeStep: 1,
_keyshift: function (date, mode, calendar) {
var newdate = date;
if (mode === "pgup" || mode === "pgdown") newdate = wDate.add(date, mode === "pgdown" ? 1 : -1, "month");else if (mode === "bottom") newdate = new Date(date.getFullYear(), date.getMonth() + 1, 0);else if (mode === "top") newdate = new Date(date.setDate(1));else if (mode === "left" || mode === "right") newdate = wDate.add(date, mode === "right" ? 1 : -1, "day");else if (mode === "up" || mode === "down") newdate = wDate.add(date, mode === "down" ? 1 : -1, "week");
if (!calendar._checkDate(newdate)) newdate = calendar._findActive(date, mode);
if (newdate) calendar.selectDate(newdate, true, false, "user");
return "webix_cal_day";
}
},
"1": {
//months
_isBlocked: function (i, calendar) {
var blocked = false,
min = calendar._settings.minDate,
max = calendar._settings.maxDate,
year = calendar._settings.date.getFullYear();
if (min) {
var minYear = min.getFullYear();
blocked = year < minYear || year == minYear && min.getMonth() > i;
}
if (max && !blocked) {
var maxYear = max.getFullYear();
blocked = year > maxYear || year == maxYear && max.getMonth() < i;
}
return blocked;
},
_correctDate: function (date, calendar) {
date = wDate.monthStart(date);
if (date < calendar._settings.minDate) {
date = wDate.copy(calendar._settings.minDate);
} else if (date > calendar._settings.maxDate) {
date = wDate.copy(calendar._settings.maxDate);
}
return date;
},
_getTitle: function (date) {
return date.getFullYear();
},
_getContent: function (i) {
return i18n.calendar.monthShort[i];
},
_setContent: function (next, i) {
if (i != next.getMonth()) next.setDate(1);
next.setMonth(i);
},
_changeStep: 12,
_keyshift: function (date, mode, calendar) {
var newdate = date;
if (mode === "pgup" || mode === "pgdown") newdate = wDate.add(date, mode === "pgdown" ? 1 : -1, "year");else if (mode === "bottom") newdate = new Date(date.setMonth(11));else if (mode === "top") newdate = new Date(date.setMonth(0));else if (mode === "left" || mode === "right") newdate = wDate.add(date, mode === "right" ? 1 : -1, "month");else if (mode === "up" || mode === "down") newdate = wDate.add(date, mode === "down" ? 4 : -4, "month");
newdate = calendar._correctDate(newdate);
if (!calendar._checkDate(newdate)) {
newdate = calendar._findActive(date, mode);
}
if (newdate) {
calendar._update_zoom_level(newdate);
calendar.selectDate(newdate, false, false, "user");
}
return "webix_cal_block";
}
},
"2": {
//years
_isBlocked: function (i, calendar) {
i += calendar._zoom_start_date;
var min = calendar._settings.minDate;
var max = calendar._settings.maxDate;
if (min && min.getFullYear() > i || max && max.getFullYear() < i) return true;
return false;
},
_correctDate: function (date, calendar) {
date = wDate.yearStart(date);
if (date < calendar._settings.minDate) {
date = wDate.copy(calendar._settings.minDate);
} else if (date > calendar._settings.maxDate) {
date = wDate.copy(calendar._settings.maxDate);
}
return date;
},
_getTitle: function (date, calendar) {
var start = date.getFullYear();
calendar._zoom_start_date = start = start - start % 10 - 1;
return start + " - " + (start + 10 + 1);
},
_getContent: function (i, calendar) {
return calendar._zoom_start_date + i;
},
_setContent: function (next, i, calendar) {
next.setFullYear(calendar._zoom_start_date + i);
},
_changeStep: 12 * 10,
_keyshift: function (date, mode, calendar) {
var newdate = date;
if (mode === "pgup" || mode === "pgdown") newdate = wDate.add(date, mode === "pgdown" ? 10 : -10, "year");else if (mode === "bottom") newdate = new Date(date.setYear(calendar._zoom_start_date + 10));else if (mode === "top") newdate = new Date(date.setYear(calendar._zoom_start_date));else if (mode === "left" || mode === "right") newdate = wDate.add(date, mode === "right" ? 1 : -1, "year");else if (mode === "up" || mode === "down") newdate = wDate.add(date, mode === "down" ? 4 : -4, "year");
newdate = calendar._correctDate(newdate);
if (!calendar._checkDate(newdate)) newdate = calendar._findActive(date, mode);
if (newdate) {
calendar._update_zoom_level(newdate);
calendar.selectDate(newdate, false, false, "user");
}
return "webix_cal_block";
}
}
},
_correctBlockedTime: function () {
var i, isDisabledHour, isDisabledMinutes;
isDisabledHour = this._zoom_logic[-1]._isBlocked.call(this, this._settings.date.getHours());
if (isDisabledHour) {
for (i = 0; i < 24; i++) {
if (!this._zoom_logic[-1]._isBlocked.call(this, i)) {
this._settings.date.setHours(i);
break;
}
}
}
isDisabledMinutes = this._zoom_logic[-2]._isBlocked.call(this, this._settings.date.getMinutes());
if (isDisabledMinutes) {
for (i = 0; i < 60; i += this._settings.minuteStep) {
if (!this._zoom_logic[-2]._isBlocked.call(this, i)) {
this._settings.date.setMinutes(i);
break;
}
}
}
},
_update_zoom_level: function (date) {
var config, css, height, i, index$$1, sections, selected, type, width, zlogic, temp, sqSize;
var html = "";
var cpad = this._content_padding + "px";
config = this._settings;
index$$1 = 2 - (config.weekHeader ? 0 : 1) - (config.monthHeader ? 0 : 1);
zlogic = this._zoom_logic[this._zoom_level];
sections = this._contentobj.childNodes;
if (date) {
config.date = date;
}
type = config.type; //store width and height of draw area
if (!this._zoom_size) {
this._reserve_box_height = this._contentobj.offsetHeight - (config.monthHeader || this._zoom_in ? config.headerHeight : 0) - (this._content_padding + $active.borderWidth) * 2;
if (type != "year" && type != "month") this._reserve_box_height -= config.timepickerHeight;
this._reserve_box_width = sections[index$$1].offsetWidth;
this._zoom_size = 1;
} //main section
if (this._zoom_in) {
//hours and minutes
height = this._reserve_box_height / 6;
var timeColNum = 6;
var timeFormat = this._calendarTime || i18n.timeFormat;
var enLocale = timeFormat.match(/%([a,A])/);
if (enLocale) timeColNum++;
width = parseInt((this._reserve_box_width - 3) / timeColNum, 10);
sqSize = Math.min(width, height);
html += "<div class='webix_time_header' style='margin:0 " + cpad + "'>" + this._timeHeaderTemplate(width, enLocale) + "</div>";
html += "<div class='webix_cal_body' style='height:" + this._reserve_box_height + "px; margin:0 " + cpad + ";'>"; // check and change blocked selected time
this._correctBlockedTime();
html += "<div class='webix_hours'>";
selected = config.date.getHours();
temp = wDate.copy(config.date);
for (i = 0; i < 24; i++) {
css = "";
if (enLocale) {
if (i % 4 === 0) {
var label = !i ? i18n.am[0] : i == 12 ? i18n.pm[0] : "";
html += "<div class='webix_cal_block_empty" + css + "' style='" + this._getCalSizesString(width, height) + "clear:both;" + "'>" + label + "</div>";
}
}
if (this._zoom_logic[-1]._isBlocked.call(this, i)) {
css += " webix_cal_day_disabled";
} else if (selected == i) css += " webix_selected";
temp.setHours(i);
html += "<div aria-label='" + wDate.dateToStr(i18n.aria.hourFormat)(temp) + "' role='gridcell'" + " tabindex='" + (selected == i ? "0" : "-1") + "' aria-selected='" + (selected == i ? "true" : "false") + "' class='webix_cal_block" + css + "' data-value='" + i + "' style='" + this._getCalSizesString(width, height) + (i % 4 === 0 && !enLocale ? "clear:both;" : "") + "'><span style='display:inline-block; " + this._getCalSizesString(sqSize, sqSize) + "'>" + wDate.toFixed(enLocale ? !i || i == 12 ? 12 : i % 12 : i) + "</span></div>";
}
html += "</div>";
html += "<div class='webix_minutes'>";
selected = config.date.getMinutes();
temp = wDate.copy(config.date);
for (i = 0; i < 60; i += config.minuteStep) {
css = "";
if (this._zoom_logic[-2]._isBlocked.call(this, i)) {
css = " webix_cal_day_disabled";
} else if (selected == i) css = " webix_selected";
temp.setMinutes(i);
html += "<div aria-label='" + wDate.dateToStr(i18n.aria.minuteFormat)(temp) + "' role='gridcell' tabindex='" + (selected == i ? "0" : "-1") + "' aria-selected='" + (selected == i ? "true" : "false") + "' class='webix_cal_block webix_cal_block_min" + css + "' data-value='" + i + "' style='" + this._getCalSizesString(width, height) + (i / config.minuteStep % 2 === 0 ? "clear:both;" : "") + "'><span style='display:inline-block; " + this._getCalSizesString(sqSize, sqSize) + "'>" + wDate.toFixed(i) + "</span></div>";
}
html += "</div>";
html += "</div>";
html += "<div class='webix_time_footer' style='margin:0 " + cpad + "'>" + this._timeButtonsTemplate() + "</div>";
this._contentobj.innerHTML = html;
this._contentobj.firstChild.style.marginTop = cpad;
} else {
//years and months
//reset header
if (config.monthHeader) {
var header = sections[0].childNodes;
var labels = i18n.aria["nav" + (this._zoom_level == 1 ? "Year" : "Decade")];
header[0].innerHTML = zlogic._getTitle(config.date, this);
header[0].blur();
if (config.navigation) {
header[1].setAttribute("aria-label", labels[0]);
header[2].setAttribute("aria-label", labels[1]);
}
} else //needed for "year" to set start value
zlogic._getTitle(config.date, this);
height = Math.floor(this._reserve_box_height / 3);
width = Math.floor(this._reserve_box_width / 4);
sqSize = Math.min(height, width);
if (this._checkDate(config.date)) selected = this._zoom_level == 1 ? config.date.getMonth() : config.date.getFullYear();
for (i = 0; i < 12; i++) {
css = selected == (this._zoom_level == 1 ? i : zlogic._getContent(i, this)) ? " webix_selected" : "";
if (zlogic._isBlocked(i, this)) {
css += " webix_cal_day_disabled";
}
var format = i18n.aria[(this._zoom_level == 1 ? "month" : "year") + "Format"];
html += "<div role='gridcell' aria-label='" + wDate.dateToStr(format)(config.date) + "' tabindex='" + (css.indexOf("selected") !== -1 ? "0" : "-1") + "' aria-selected='" + (css.indexOf("selected") !== -1 ? "true" : "false") + "' class='webix_cal_block" + css + "' data-value='" + i + "' style='" + this._getCalSizesString(width, height) + "'><span style='display:inline-block; " + this._getCalSizesString(sqSize, sqSize) + "'>" + zlogic._getContent(i, this) + "</span></div>";
}
if (config.weekHeader) {
sections[index$$1 - 1].style.display = "none";
if (index$$1 === 1) sections[index$$1].style.marginTop = cpad;
}
sections[index$$1].innerHTML = html;
if (type != "year" && type != "month") {
if (!sections[index$$1 + 1]) this._contentobj.innerHTML += "<div class='webix_time_footer' style='margin:0 " + cpad + "'>" + this._timeButtonsTemplate() + "</div>";else sections[index$$1 + 1].innerHTML = this._timeButtonsTemplate();
} else if (sections[index$$1 + 1]) {
sections[index$$1 + 1].style.display = "none";
}
sections[index$$1].style.height = this._reserve_box_height + "px";
}
},
_getCalSizesString: function (width, height) {
return "width:" + width + "px; height:" + height + "px; line-height:" + height + "px;";
},
_timeButtonsTemplate: function () {
return "<input type='button' style='width:100%' class='webix_cal_done' value='" + i18n.calendar.done + "'>";
},
_timeHeaderTemplate: function (width, enLocale) {
var w1 = width * (enLocale ? 5 : 4);
var w2 = width * 2;
return "<div class='webix_cal_hours' style='width:" + w1 + "px'>" + i18n.calendar.hours + "</div><div class='webix_cal_minutes' style='width:" + w2 + "px'>" + i18n.calendar.minutes + "</div>";
},
_changeZoomLevel: function (zoom, date) {
var oldzoom = this._zoom_level;
if (this.callEvent("onBeforeZoom", [zoom, oldzoom])) {
this._zoom_level = zoom;
if (zoom) this._update_zoom_level(date);else this.showCalendar(date);
this.callEvent("onAfterZoom", [zoom, oldzoom]);
}
},
_correctDate: function (date) {
if (!this._checkDate(date) && this._zoom_logic[this._zoom_level]._correctDate) date = this._zoom_logic[this._zoom_level]._correctDate(date, this);
return date;
},
_mode_selected: function (target, config) {
var next = this._locate_date(target);
var zoom = this._zoom_level - (this._fixed ? 0 : 1);
next = this._correctDate(next);
if (this._checkDate(next)) {
this._changeZoomLevel(zoom, next);
var type = this._settings.type;
if (type == "month" || type == "year") this._selectDate(next, false, config);
}
},
// selects date and redraw calendar
_selectDate: function (date, add, config) {
if (this.callEvent("onBeforeDateSelect", [date])) {
this.selectDate(date, true, add, config);
this.callEvent("onAfterDateSelect", [date]);
}
},
_locate_day: function (target) {
var cind = index(target) - (this._settings.weekNumber ? 1 : 0);
var rind = index(target.parentNode);
var date = wDate.add(this._getDateBoundaries()._start, cind + rind * 7, "day", true);
if (this._settings.timepicker) {
date.setHours(this._settings.date.getHours());
date.setMinutes(this._settings.date.getMinutes());
}
return date;
},
_locate_date: function (target) {
var value = target.getAttribute("data-value") * 1;
var level = target.className.indexOf("webix_cal_block_min") != -1 ? this._zoom_level - 1 : this._zoom_level;
var now = this._settings.date;
var next = wDate.copy(now);
this._zoom_logic[level]._setContent(next, value, this);
return next;
},
on_click: {
webix_cal_prev_button: function () {
this._changeDate(-1);
},
webix_cal_next_button: function () {
this._changeDate(1);
},
webix_cal_day_disabled: function () {
return false;
},
webix_cal_outside: function () {
if (!this._settings.navigation) return false;
},
webix_cal_day: function (e, id, target) {
var date = this._locate_day(target);
var add = this._settings.multiselect === "touch" || e.ctrlKey || e.metaKey;
this._selectDate(date, add, "user");
},
webix_cal_time: function () {
if (this._zoom_logic[this._zoom_level - 1]) {
this._zoom_in = true;
var zoom = this._zoom_level - 1;
this._changeZoomLevel(zoom);
}
},
webix_range_time_start: function () {
$$(this._settings.master)._time_mode = "start";
},
webix_range_time_end: function () {
$$(this._settings.master)._time_mode = "end";
},
webix_cal_done: function () {
var date = wDate.copy(this._settings.date);
date = this._correctDate(date);
this._selectDate(date, false, "user");
},
webix_cal_month_name: function () {
if (!this._settings.navigation) return;
this._zoom_in = false; //maximum zoom reached
if (this._zoom_level == 2 || !this._settings.monthSelect) return;
var zoom = Math.max(this._zoom_level, 0) + 1;
this._changeZoomLevel(zoom);
},
webix_cal_block: function (e, id, trg) {
if (this._zoom_in) {
if (trg.className.indexOf("webix_cal_day_disabled") !== -1) return false;
var next = this._locate_date(trg);
this._update_zoom_level(next);
} else {
if (trg.className.indexOf("webix_cal_day_disabled") == -1) this._mode_selected(trg, "user");
}
}
},
_string_to_date: function (date, format) {
if (!date) {
return wDate.datePart(new Date());
}
if (typeof date == "string") {
if (format) date = wDate.strToDate(format)(date);else date = i18n.parseFormatDate(date);
}
return date;
},
_checkDate: function (date) {
var blockedDate = this._settings.blockDates && this._settings.blockDates.call(this, date);
var minDate = this._settings.minDate;
var maxDate = this._settings.maxDate;
var outOfRange = date < minDate || date > maxDate;
return !blockedDate && !outOfRange;
},
_findActive: function (date, mode) {
var dir = mode === "top" || mode === "left" || mode === "pgup" || mode === "up" ? -1 : 1;
var newdate = wDate.add(date, dir, "day", true);
if (this._checkDate(newdate)) return newdate;else {
var compare;
if (this._zoom_level === 0) compare = date.getMonth() === newdate.getMonth();else if (this._zoom_level === 1) compare = date.getFullYear() === newdate.getFullYear();else if (this._zoom_level === 2) compare = newdate.getFullYear() > this._zoom_start_date && newdate.getFullYear() < this._zoom_start_date + 10;
if (compare) return this._findActive(newdate, mode);
}
},
showCalendar: function (date) {
date = this._string_to_date(date);
this._settings.date = date;
this.render();
this.resize();
},
_selectedDay: function (day) {
return day && this._selected_days[day.valueOf()];
},
getSelectedDate: function () {
var result = [];
for (var key in this._selected_days) {
result.push(wDate.copy(this._selected_days[key]));
}
return this.config.multiselect ? result : result[0] || null;
},
getVisibleDate: function () {
return wDate.copy(this._settings.date);
},
setValue: function (date, config) {
this.selectDate(date, true, false, config);
},
getValue: function (format) {
var date = this.getSelectedDate();
if (format) date = wDate.dateToStr(format)(date);
return date;
},
selectDate: function (date, show, add, config) {
if (!date || !add || !this.config.multiselect) this._selected_days = {};
if (date) {
if (!isArray(date)) date = [date];
for (var i = 0; i < date.length; i++) {
var days = this._string_to_date(date[i]);
var key = wDate.datePart(wDate.copy(days)).valueOf();
if (this._selected_days[key] && add) delete this._selected_days[key];else this._selected_days[key] = days;
if (!this.config.multiselect) break;
}
if (date.length && show) this.showCalendar(date[0]);
}
if (show !== false) this.render();
this.callEvent("onChange", [date, config]);
},
locate: function () {
return null;
}
};
var view$s = exports.protoUI(api$s, KeysNavigation, MouseEvents, base$1.view, EventSystem);
var api$t = {
name: "colorboard",
defaults: {
template: function (obj) {
return "<div class=\"webix_color_item\" style=\"background-color:".concat(obj.val, ";\"></div>");
},
palette: null,
height: 250,
width: 260,
cols: 11,
rows: 10,
minLightness: 0.15,
maxLightness: 1,
navigation: true,
grayScale: true,
type: "material" // "classic"
},
$init: function () {
_event(this._viewobj, "click", bind(function (e) {
// prevent selection the main item container
var node = e.target.parentNode;
var value = locate(node,
/*@attr*/
"webix_val"); // locate can return null in case of drag
if (value) {
var oldvalue = this._settings.value;
value = this.setValue(value, "user");
this.callEvent("onItemClick", [value, e]);
if (value != oldvalue) this.callEvent("onSelect", [value]);
}
}, this));
this.$view.setAttribute("role", "grid");
this._viewobj.setAttribute("aria-readonly", "true");
},
_get_clear_palette: function () {
return ["#F34336", "#FF9700", "#FFEA3B", "#4CB050", "#009788", "#00BCD4", "#2196F3", "#3F51B5", "#673BB7", "#9C28B1", "#EA1E63"];
},
_set_item_focus: function () {
if (!this.getValue()) this.moveSelection("up");
},
_findIndex: function (value) {
var pal = this._settings.palette;
value = (value || "").toUpperCase();
for (var r = 0, rows = pal.length; r < rows; r++) {
for (var c = 0, cols = pal[r].length; c < cols; c++) {
if (pal[r][c].toUpperCase() == value) {
return {
row: r,
col: c
};
}
}
}
return null;
},
$setSize: function (x, y) {
if (base$1.api.$setSize.call(this, x, y)) {
this.render();
}
},
getValue: function () {
return this._settings.value;
},
_getBox: function () {
return this._viewobj.firstChild;
},
$prepareValue: function (value) {
value = value ? value.toString(16) : "";
if (value && value.charAt(0) != "#" && /^[0-9a-fA-F]+$/.test(value)) value = "#" + value;
return value;
},
value_setter: function (value) {
return this.$prepareValue(value);
},
setValue: function (value, config) {
value = this.$prepareValue(value);
var oldvalue = this._settings.value;
if (oldvalue != value) {
this._settings.value = value;
this.$setValue(value);
this.callEvent("onChange", [value, oldvalue, config]);
}
return value;
},
$setValue: function (value) {
if (this.isVisible(this._settings.id)) {
// clear previous
if (this._activeSelection) {
var oldCell = this._getCell(this._activeSelection);
this._setSelection(oldCell, false);
}
var ind = this._activeSelection = this._findIndex(value);
if (ind) {
var cell = this._getCell(ind);
this._setSelection(cell, true);
}
}
},
_getCell: function (ind) {
return this._viewobj.lastChild.childNodes[ind.row].childNodes[ind.col];
},
_setSelection: function (cell, state) {
if (state) {
cell.setAttribute("tabindex", "0");
cell.setAttribute("aria-selected", "true");
addCss(cell, "webix_color_selected");
} else {
cell.setAttribute("tabindex", "-1");
cell.removeAttribute("aria-selected");
removeCss(cell, "webix_color_selected");
}
},
/* handle colors */
_numToHex: function (n) {
return color.toHex(n, 2);
},
_rgbToHex: function (r, g, b) {
return "#" + this._numToHex(Math.floor(r)) + this._numToHex(Math.floor(g)) + this._numToHex(Math.floor(b));
},
_hslToRgb: function (h, s, l) {
var r, g, b;
if (!s) {
r = g = b = l; // achromatic
} else {
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = this._hue2rgb(p, q, h + 1 / 3);
g = this._hue2rgb(p, q, h);
b = this._hue2rgb(p, q, h - 1 / 3);
}
return {
r: r * 255,
g: g * 255,
b: b * 255
};
},
_hue2rgb: function (p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;else if (t <= 1 / 2) return q;else if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;else return p;
},
_lightenRgb: function (rgb, lt) {
/* color = color * alpha + background * (1 - alpha); */
var r = rgb[0] * lt + 255 * (1 - lt);
var g = rgb[1] * lt + 255 * (1 - lt);
var b = rgb[2] * lt + 255 * (1 - lt);
return {
r: r,
g: g,
b: b
};
},
_getGrayScale: function (colCount) {
var gray = [];
var val = 255,
step = val / colCount;
for (var i = 0; i < colCount; i++) {
val = Math.round(val > 0 ? val : 0);
gray.push(this._rgbToHex(val, val, val));
val -= step;
}
gray[gray.length - 1] = "#000000";
return gray;
},
_initPalette: function (config) {
/* default palette (material and custom) */
var clearColors = this._get_clear_palette();
config.cols = clearColors.length; // always use the same set
var colors = [];
var colorRows = config.rows - 1; // a row is reserved for clear colors
var lightStep = 1 / config.rows;
var colorRange = null;
if (this._settings.grayScale) {
var grayColors = this._getGrayScale(config.cols);
colors.push(grayColors.reverse()); // inverted order
lightStep = 1 / colorRows;
colorRows -= 1;
}
colors.push(clearColors);
for (var step = 0, lt = config.maxLightness; step < colorRows; step++) {
lt -= lightStep;
colorRange = [];
for (var col = 0; col < config.cols; col++) {
var clearRgb = color.toRgb(clearColors[col]);
var val = this._lightenRgb(clearRgb, lt);
colorRange.push(this._rgbToHex(val.r, val.g, val.b));
}
colors.push(colorRange);
}
this._settings.palette = colors;
},
_initOldPalette: function (config) {
/* old (classic) palette */
var colors = [];
var colorStep = 1 / config.cols;
var colorRows = config.rows;
var colorRange = null;
if (this._settings.grayScale) {
colors.push(this._getGrayScale(config.cols));
colorRows -= 1;
}
var lightStep = (config.maxLightness - config.minLightness) / colorRows;
for (var step = 0, lt = config.minLightness; step < colorRows; step++) {
colorRange = [];
for (var c = 0, col = 0; c < config.cols; c++) {
var val = this._hslToRgb(col, 1, lt);
colorRange.push(this._rgbToHex(val.r, val.g, val.b));
col += colorStep;
}
colors.push(colorRange);
lt += lightStep;
}
this._settings.palette = colors;
},
moveSelection: function (mode, details, focus) {
var value = this.getValue(),
ind,
cell;
if (value) ind = this._findIndex(value);
if (!ind) ind = {
row: 0,
col: 0
};
if (ind) {
if (mode == "up" || mode == "down") ind.row = ind.row + (mode == "up" ? -1 : 1);else if (mode == "right" || mode == "left") ind.col = ind.col + (mode == "right" ? 1 : -1);else if (mode == "top") ind.row = ind.col = 0;else if (mode == "bottom") {
ind.row = this._viewobj.lastChild.querySelectorAll(".webix_color_row").length - 1;
ind.col = this._viewobj.lastChild.childNodes[ind.row].childNodes.length - 1;
}
ind.row = Math.max(ind.row, 0);
if (ind.row >= 0) {
// check if this is a last row
var row = this._viewobj.lastChild.childNodes[ind.row];
if (row) cell = row.childNodes[ind.col];
}
if (cell) {
value = cell.getAttribute(
/*@attr*/
"webix_val");
var config = details && details.e instanceof KeyboardEvent ? "user" : "auto";
this.setValue(value, config);
this.callEvent("onSelect", [this._settings.value]);
if (focus !== false) {
var sel = this._viewobj.querySelector("div[tabindex='0']");
if (sel) sel.focus();
}
}
}
},
_renderRow: function (row, widths, height) {
var data = {
width: 0,
height: 0,
val: 0
};
var rowHtml = "<div class=\"webix_color_row\" role=\"row\">";
for (var cell = 0; cell < row.length; cell++) {
data.width = widths[cell];
data.height = height;
data.val = row[cell];
rowHtml += this._renderItem(data);
}
rowHtml += "</div>";
return rowHtml;
},
_renderItem: function (obj) {
var colorTemplate = template(this._settings.template || "");
return "<div role=\"gridcell\" tabindex=\"-1\" aria-label=\"".concat(obj.val, "\" style=\"width:").concat(obj.width, "px;height:").concat(obj.height, "px;\" ",
/*@attr*/
"webix_val", "=\"").concat(obj.val, "\">").concat(colorTemplate(obj), "</div>");
},
render: function () {
if (!this.isVisible(this._settings.id)) return;
var type = this._settings.type;
if (!this._settings.palette) {
if (type === "classic") this._initOldPalette(this._settings);else this._initPalette(this._settings);
}
var palette = this._settings.palette;
this.callEvent("onBeforeRender", []);
var padding = type === "classic" ? 0 : $active.colorPadding;
var single$$1 = _typeof(palette[0]) == "object";
var firstRow = single$$1 ? palette[0] : palette;
var deltaWidth = padding * 2 + padding * (firstRow.length - 1);
var deltaHeight = padding * 2 + padding * (single$$1 ? palette.length - 1 : 0);
var width = this.$width - deltaWidth,
height = this.$height - deltaHeight,
widths = [];
var html = "<div class=\"webix_color_palette ".concat("webix_palette_" + type, "\" role=\"rowgroup\">");
for (var i = 0; i < firstRow.length; i++) {
widths[i] = Math.floor(width / (firstRow.length - i));
width -= widths[i];
}
if (_typeof(palette[0]) == "object") {
for (var r = 0; r < palette.length; r++) {
var cellHeight = Math.floor(height / (palette.length - r));
height -= cellHeight;
var row = palette[r];
html += this._renderRow(row, widths, cellHeight);
}
} else html += this._renderRow(palette, widths, height);
html += "</div>";
this._viewobj.innerHTML = html;
if (this._settings.value) this.$setValue(this._settings.value);else this._viewobj.lastChild.childNodes[0].childNodes[0].setAttribute("tabindex", "0");
this._fix_cover();
this.callEvent("onAfterRender", []);
},
refresh: function () {
this.render();
}
};
var view$t = exports.protoUI(api$t, KeysNavigation, base$1.view, EventSystem);
var api$u = {
name: "colorselect",
defaults: {
width: 260,
height: 250,
value: "#751FE0"
},
$init: function () {
var _this = this;
this._hValue = this._sValue = this._vValue = 0;
if (env.touch) {
this.attachEvent("onTouchStart", function (e, ctx) {
var css = e.target.className;
var parent = e.target.parentNode.className;
if (css == "webix_color_block" || parent == "webix_color_block") _this._handle_dnd(ctx || e);else if (css.indexOf("webix_color_line") == 0) _this._handle_dnd(ctx || e, true);
});
}
_event(this.$view, "keydown", function (e) {
return _this._handle_move_keyboard(e);
});
this.attachEvent("onAfterRender", function () {
var _this2 = this;
if (!env.touch) {
_event(this._colorBlock, "mousedown", function (e) {
return _this2._handle_dnd(e);
});
_event(this._colorLine, "mousedown", function (e) {
return _this2._handle_dnd(e, true);
});
}
_event(this._colorOutText, "change", function () {
return _this2.setValue(_this2._colorOutText.value, "user");
});
if (this._settings.button) _event(this._viewobj.querySelector(".webix_button"), "click", function () {
_this2.callEvent("onColorSelect", [_this2.getValue()]);
});
});
this.attachEvent("onDestruct", function () {
this._colorCircle = this._colorLineCircle = this._colorBlock = null;
this._colorLine = this._colorOutText = this._colorOutBlock = this._offset = null;
if (this._handle_drag_events) this._detach_drag_events();
});
},
$skin: function () {
if ($name == "compact" || $name == "mini") this._inpHeight = 24;else this._inpHeight = 32;
},
$setSize: function (x, y) {
if (base$1.api.$setSize.call(this, x, y)) {
this.render();
}
},
getValue: function () {
return this._settings.value;
},
$prepareValue: function (value) {
value = value ? value.toString(16) : "";
if (value && value.charAt(0) != "#" && /^[0-9a-fA-F]+$/.test(value)) value = "#" + value;
return value;
},
value_setter: function (value) {
return this.$prepareValue(value);
},
setValue: function (value, config) {
value = this.$prepareValue(value);
var oldvalue = this._settings.value;
if (oldvalue != value) {
this._settings.value = value;
this.$setValue(value);
this.callEvent("onChange", [value, oldvalue, config]);
}
},
$setValue: function (value) {
if (this.isVisible(this._settings.id)) {
var rgb = color.toRgb(value);
if (value !== this._current_value) {
//set by API
var hsv = color.rgbToHsv.apply(color, _toConsumableArray(rgb));
this._hValue = hsv[0];
this._sValue = hsv[1];
this._vValue = hsv[2];
}
var left = this._hValue * this._offset.width / 359;
this._colorLineCircle.style.left = left + "px";
var x = this._sValue * this._offset.width;
var y = Math.abs(this._offset.height * (this._vValue - 1));
this._colorCircle.style.left = Math.max(Math.min(x, this._offset.width), 0) + "px";
this._colorCircle.style.top = Math.max(Math.min(y, this._offset.height), 0) + "px";
this._colorCircle.setAttribute("aria-valuetext", value);
this._colorLineCircle.setAttribute("aria-valuetext", value);
this._setOutColors(rgb, value);
this._setBlockColors();
}
},
_setOutColors: function (rgb, hex) {
if (!rgb) rgb = color.hsvToRgb(this._hValue, this._sValue, this._vValue);
if (!hex) hex = "#" + color.rgbToHex(rgb);
var bgColor = "rgb(".concat(rgb[0], ", ").concat(rgb[1], ", ").concat(rgb[2], ")");
this._colorCircle.style.backgroundColor = bgColor;
this._colorOutBlock.style.backgroundColor = bgColor;
this._colorOutText.value = hex.toUpperCase();
this._current_value = hex;
},
_setBlockColors: function () {
var rgb = color.hsvToRgb(this._hValue, 1, 1);
var rgbStr = "rgb(".concat(rgb[0], ", ").concat(rgb[1], ", ").concat(rgb[2], ")");
this._colorLineCircle.style.backgroundColor = rgbStr;
this._colorBlock.style.backgroundColor = rgbStr;
},
// dragging to set value
_move_block: function (e) {
var pos$$1 = env.touch ? {
x: e.x,
y: e.y
} : pos(e);
var x = pos$$1.x - this._offset.x;
var y = pos$$1.y - this._offset.y;
x = Math.max(Math.min(x, this._offset.width), 0);
y = Math.max(Math.min(y, this._offset.height), 0);
this._colorCircle.style.left = x + "px";
this._colorCircle.style.top = y + "px";
var pxX = this._offset.width / 100;
var pxY = this._offset.height / 100;
var s = Math.ceil(x / pxX) / 100;
var v = Math.ceil(Math.abs(y / pxY - 100)) / 100;
this._sValue = s;
this._vValue = v;
this._setOutColors();
},
_move_line: function (e) {
var pos$$1 = env.touch ? {
x: e.x,
y: e.y
} : pos(e);
var x = pos$$1.x - this._offset.x;
x = Math.max(Math.min(x, this._offset.width), 0);
this._colorLineCircle.style.left = x + "px";
var h = Math.round(x * 359 / this._offset.width);
this._hValue = Math.max(Math.min(h, 359), 0);
this._setOutColors();
this._setBlockColors();
},
_handle_dnd: function (e, line) {
var _this3 = this;
this._offset = offset(this._colorBlock);
if (line) {
addCss(this._colorLine, "webix_color_area_active");
this._move_line(e);
} else {
addCss(this._colorBlock, "webix_color_area_active");
this._move_block(e);
}
if (env.touch) {
this._handle_drag_events = [this.attachEvent("onTouchMove", function (e, ctx) {
return _this3._handle_move_process(ctx || e, line);
}), this.attachEvent("onTouchEnd", function () {
return _this3._handle_move_stop(line);
})];
} else {
this._handle_drag_events = [event$1(document.body, "mousemove", function (e) {
return _this3._handle_move_process(e, line);
}), event$1(window, "mouseup", function () {
return _this3._handle_move_stop(line);
})];
}
addCss(document.body, "webix_noselect");
},
_handle_move_process: function (e, line) {
if (line) this._move_line(e);else this._move_block(e);
},
_detach_drag_events: function () {
if (env.touch) {
this.detachEvent(this._handle_drag_events[0]);
this.detachEvent(this._handle_drag_events[1]);
} else {
eventRemove(this._handle_drag_events[0]);
eventRemove(this._handle_drag_events[1]);
}
this._handle_drag_events = null;
},
_handle_move_stop: function (line) {
this._detach_drag_events();
this.setValue(this._current_value, "user");
if (line) {
removeCss(this._colorLine, "webix_color_area_active");
this._colorLineCircle.focus();
} else {
removeCss(this._colorBlock, "webix_color_area_active");
this._colorCircle.focus();
}
removeCss(document.body, "webix_noselect");
},
_move_block_value: function (val, inc) {
return Math.min(Math.max(val + inc / 100, 0), 1);
},
_move_line_value: function (val, inc) {
return Math.min(Math.max(val + inc, 0), 359);
},
_handle_move_keyboard: function (e) {
var code = e.keyCode;
if (code > 32 && code < 41) {
var match = /webix_color_(\w*)circle/.exec(e.target.className);
if (!match) return;
preventEvent(e);
if (match[1].length) {
//line
if (code === 36) this._hValue = 0;else if (code === 35) this._hValue = 359;else {
var inc = code === 37 || code === 40 || code === 34 ? -1 : 1;
this._hValue = this._move_line_value(this._hValue, inc);
}
this._setBlockColors();
} else {
if (code === 36) {
this._sValue = 0;
this._vValue = 1;
} else if (code === 35) this._sValue = this._vValue = 1;else if (code === 39 || code === 37) {
var _inc = code === 39 ? 1 : -1;
this._sValue = this._move_block_value(this._sValue, _inc);
} else {
var _inc2 = code === 33 || code === 38 ? 1 : -1;
this._vValue = this._move_block_value(this._vValue, _inc2);
}
}
this._setOutColors(); //paint value, black colors may have a bigger step
if (this._settings.value == this._current_value) this.$setValue(this._current_value);else this.setValue(this._current_value, "user");
}
},
moveSelection: function (mode) {
if (mode == "pgup" || mode == "pgdown") {
//line
var inc = mode === "pgup" ? -1 : 1;
this._hValue = this._move_line_value(this._hValue, inc);
this._setBlockColors();
} else if (mode != "top" && mode !== "bottom") {
var _inc3 = mode == "up" || mode == "right" ? 1 : -1;
if (mode == "down" || mode == "up") this._vValue = this._move_block_value(this._vValue, _inc3);else this._sValue = this._move_block_value(this._sValue, _inc3);
}
this._setOutColors();
this.setValue(this._current_value, "auto");
},
render: function () {
if (!this.isVisible(this._settings.id)) return;
this.callEvent("onBeforeRender", []);
var inpWidth = (this.$width - $active.dataPadding * 3) / 2; //24 paddings, 32 color line, 12 padding
var bHeight = this.$height - 24 - 32 - this._inpHeight - (this._settings.button ? this._inpHeight + 12 : 0);
var html = "<div class=\"webix_color_area\">";
html += "\n\t\t\t<div ".concat(
/*@attr*/
"webix_disable_drag", "=\"true\" class=\"webix_color_block\" style=\"height:", bHeight, "px;\">\n\t\t\t\t<div class=\"webix_color_circle\" tabindex=\"0\" role=\"slider\"></div>\n\t\t\t</div>\n\t\t\t<div ",
/*@attr*/
"webix_disable_drag", "=\"true\" class=\"webix_color_line\">\n\t\t\t\t<div class=\"webix_color_line_circle\" tabindex=\"0\" role=\"slider\"></div>\n\t\t\t</div>\n\t\t\t<div class=\"webix_color_out\">\n\t\t\t\t<div style=\"width:").concat(inpWidth, "px\" class=\"webix_color_out_block\"></div>\n\t\t\t\t<input type=\"text\" style=\"width:").concat(inpWidth, "px\" class=\"webix_color_out_text\"></input>\n\t\t\t</div>\n\t\t");
if (this._settings.button) html += "<div class='webix_secondary'><button class=\"webix_button\">".concat(i18n.combo.select, "</button></div>");
html += "</div>";
this._viewobj.innerHTML = html;
this._collect_vars();
this.$setValue(this._settings.value);
this._fix_cover();
this.callEvent("onAfterRender", []);
},
_collect_vars: function () {
this._colorCircle = this._viewobj.querySelector(".webix_color_circle");
this._colorLineCircle = this._viewobj.querySelector(".webix_color_line_circle");
this._colorBlock = this._viewobj.querySelector(".webix_color_block");
this._colorLine = this._viewobj.querySelector(".webix_color_line");
this._colorOutText = this._viewobj.querySelector(".webix_color_out_text");
this._colorOutBlock = this._viewobj.querySelector(".webix_color_out_block");
this._offset = offset(this._colorBlock);
},
refresh: function () {
this.render();
}
};
var view$u = exports.protoUI(api$u, base$1.view, EventSystem);
var api$v = {
name: "button",
touchable: true,
$skin: function () {
this.defaults.height = $active.buttonHeight || $active.inputHeight;
},
defaults: {
template: function (obj, common) {
var text = common.$renderInput(obj, common);
if (obj.badge || obj.badge === 0) text = text.replace("</button>", "<span class='webix_badge'>" + obj.badge + "</span></button>");
return "<div class='webix_el_box' style='width:" + obj.awidth + "px; height:" + obj.aheight + "px'>" + text + "</div>";
},
label: "",
value: "",
borderless: true
},
$renderInput: function (obj) {
return "<button type='button' " + (obj.popup ? "aria-haspopup='true'" : "") + " class='webix_button'>" + (obj.label || obj.value) + "</button>";
},
$init: function (config) {
this._viewobj.className += " webix_control webix_el_" + (this.$cssName || this.name);
this._destroy_with_me = [];
this._set_default_css(config);
this.data = this._settings;
this._dataobj = this._viewobj;
this.$ready.push(function () {
this._calc_size(this.config);
});
},
hotkey_setter: function (key) {
var control = this;
this._addElementHotKey(key, function (view, ev) {
if (control.isVisible()) {
var elem = control.$view.firstChild;
triggerEvent(elem, "MouseEvents", "click");
preventEvent(ev);
}
});
},
_set_default_css: function (config) {
if (!config.css || !this._get_class(config.css) || this.defaults.css && !this._get_class(this.defaults.css)) {
this._viewobj.className += " webix_secondary";
}
},
_get_class: function (css) {
if (typeof css == "string") {
var classes = {
webix_danger: 1,
webix_transparent: 1,
webix_primary: 1
};
for (var i in classes) {
if (css.indexOf(i) !== -1) return true;
}
}
return false;
},
_addElementHotKey: function (key, func, view) {
var keyCode = UIManager.addHotKey(key, func, view);
this.attachEvent("onDestruct", function () {
UIManager.removeHotKey(keyCode, func, view);
});
},
type_setter: function (value) {
if (this._types[value]) this.$renderInput = template(this._types[value]);
return value;
},
_set_inner_size: false,
_types: {
image: "<button type='button' class='webix_button webix_img_btn' style='line-height:#cheight#px;'><img class='webix_image' style='max-width:#cheight#px; max-height:#cheight#px;' src = '#image#'>#label#</button>",
imageTop: "<button type='button' class='webix_button webix_img_btn_top'><img class='webix_image' style='max-width:#cheight#px; max-height:#cheight#px;' src = '#image#'><div class='webix_img_btn_text'>#label#</div></button>",
icon: "<button type='button' class='webix_button webix_img_btn' style='line-height:#cheight#px;'><span class='webix_icon_btn #icon#' style='max-width:#cheight#px;'></span>#label#</button>",
iconTop: "<button type='button' class='webix_button webix_img_btn_top' style='width:100%;text-align:center;'><span class='webix_icon #icon#'></span><div class='webix_img_btn_text'>#label#</div></button>"
},
_findAllInputs: function () {
var result = [];
var tagNames = ["input", "select", "textarea", "button"];
for (var i = 0; i < tagNames.length; i++) {
var inputs = this.$view.getElementsByTagName(tagNames[i]);
for (var j = 0; j < inputs.length; j++) {
result.push(inputs[j]);
}
}
return result;
},
disable: function () {
var i,
node,
elem = this._getBox();
base.api.disable.apply(this, arguments);
if (elem && elem.className.indexOf(" webix_disabled_box") == -1) {
elem.className += " webix_disabled_box";
var inputs = this._findAllInputs();
for (i = 0; i < inputs.length; i++) {
inputs[i].setAttribute("disabled", true);
} // richselect and based on it
node = this.getInputNode();
if (node && node.tagName.toLowerCase() == "div") {
this._disabledTabIndex = node.getAttribute("tabIndex");
node.removeAttribute("tabIndex");
}
if (this._settings.labelPosition == "top") {
var label = this._dataobj.firstChild;
if (label) label.className += " webix_disabled_top_label";
}
}
},
enable: function () {
base.api.enable.apply(this, arguments);
var node,
elem = this._getBox();
if (elem) {
elem.className = elem.className.replace(" webix_disabled_box", "");
var inputs = this._findAllInputs();
for (var i = 0; i < inputs.length; i++) {
inputs[i].removeAttribute("disabled");
}
node = this.getInputNode();
if (node && !isUndefined(this._disabledTabIndex)) node.setAttribute("tabIndex", this._disabledTabIndex);
if (this._settings.labelPosition == "top") {
var label = this._dataobj.firstChild;
if (label) label.className = label.className.replace(" webix_disabled_top_label", "");
}
}
},
$setSize: function (x, y) {
if (base$1.api.$setSize.call(this, x, y)) {
this.render();
}
},
setValue: function (value, config) {
value = this.$prepareValue(value);
var oldvalue = this._settings.value;
if (this.$compareValue(oldvalue, value)) {
if (this._rendered_input && value != this.$getValue()) this.$setValue(value);
return;
}
this._settings.value = value;
if (this._rendered_input) this.$setValue(value);
this.callEvent("onChange", [value, oldvalue, config]);
},
$compareValue: function (oldvalue, value) {
if (typeof value === "number") value = value.toString();
if (typeof oldvalue === "number") oldvalue = oldvalue.toString();
return oldvalue == value;
},
$prepareValue: function (value) {
return value === 0 ? "0" : (value || "").toString();
},
value_setter: function (value) {
return this.$prepareValue(value);
},
//visual part of setValue
$setValue: function (value) {
var node = this.getInputNode();
if (node && !this._types[this._settings.type]) {
value = this._settings.label || value;
if (node.tagName == "BUTTON") node.innerHTML = value;else node.value = value;
}
},
getValue: function () {
//if button was rendered - returning actual value
//otherwise - returning last set value
var value = this._rendered_input ? this.$getValue() : this._settings.value;
return typeof value == "undefined" ? "" : value;
},
$getValue: function () {
return this._settings.value || "";
},
focus: function () {
if (!UIManager.canFocus(this)) return false;
var input = this.getInputNode();
if (input && input.focus) input.focus();
},
blur: function () {
var input = this.getInputNode();
if (input && input.blur) input.blur();
},
//get input element
getInputNode: function () {
return this._dataobj.getElementsByTagName("input")[0] || this._dataobj.getElementsByTagName("button")[0];
},
//get top-level sub-container
_getBox: function () {
for (var i = 0; i < this._dataobj.childNodes.length; i++) {
if (this._dataobj.childNodes[i].className.indexOf("webix_el_box") >= 0) return this._dataobj.childNodes[i];
}
return null;
},
_get_tooltip_data: function (t, e) {
var node = e.target;
var box = this._getBox();
var isTopLabel = this._settings.labelPosition == "top" && this._dataobj.firstChild.contains(node);
if (isTopLabel || box && box.contains(node)) return this._settings;
return null;
},
_sqrt_2: Math.sqrt(2),
_calc_size: function (config) {
config = config || this._settings;
if (config.autowidth) {
var width = getTextSize(config.value || config.label || "", "webixbutton").width + (config.badge || config.badge === 0 ? getTextSize(config.badge, "webix_badge").width * 2 - 32 : 0) + (config.type === "icon" ? 24 : 0) + (config.type === "image" ? config.height - $active.inputPadding : 0);
width = Math.max(config.minWidth || 0, width);
config.width = Math.min(config.maxWidth || Infinity, width);
}
},
_calck_input_size: function () {
//use width for both width and inputWidth settings in clever way
//in form, we can define width for some element smaller than for siblings
//it will use inputWidth to render the desired view
this._input_width = this._settings.inputWidth || (this._content_width - this._settings.width > 2 ? this._settings.width : 0) || this._content_width;
this._input_height = this._settings.inputHeight || this._inputHeight || 0;
},
resize: function () {
this._calc_size();
return base$1.api.resize.apply(this, arguments);
},
render: function () {
this._calck_input_size();
this._settings.awidth = this._input_width || this._content_width;
this._settings.aheight = this._input_height || this._content_height; //image button - image width
this._settings.bheight = this._settings.aheight + 2;
this._settings.cheight = this._settings.aheight - 2 * $active.inputPadding;
this._settings.dheight = this._settings.cheight - 2; // - borders
if (AtomRender.render.call(this)) {
this._rendered_input = true;
if (this._set_inner_size) this._set_inner_size();
if (this._settings.align) {
var handle = this._dataobj.firstChild;
if (this._settings.labelPosition == "top" && handle.nextSibling) handle = handle.nextSibling;
switch (this._settings.align) {
case "right":
handle.style.cssFloat = "right";
break;
case "center":
handle.style.display = "inline-block";
handle.parentNode.style.textAlign = "center";
break;
case "middle":
handle.style.marginTop = Math.round((this._content_height - this._input_height) / 2) + "px";
break;
case "bottom":
handle.style.marginTop = this._content_height - this._input_height + "px";
break;
case "left":
handle.style.cssFloat = "left";
break;
default:
assert(false, "Unknown align mode: " + this._settings.align);
break;
}
}
if (this.$render) this.$render(this.data);
if (this._settings.disabled) this.disable();
if (this._init_once) {
this._init_once(this.data);
this._init_once = 0;
}
}
},
refresh: function () {
this.render();
},
on_click: {
_handle_tab_click: function (ev) {
var id = locate(ev,
/*@attr*/
"button_id");
var opt = this.getOption(id);
if (opt && !opt.disabled && this.callEvent("onBeforeTabClick", [id, ev])) {
this.setValue(id, "user");
this.focus();
this.callEvent("onAfterTabClick", [id, ev]);
}
},
webix_all_segments: function (ev, button) {
this.on_click._handle_tab_click.call(this, ev, button);
},
webix_all_tabs: function (ev, button) {
this.on_click._handle_tab_click.call(this, ev, button);
},
webix_inp_counter_next: function () {
if (!this._settings.readonly) this.next(this._settings.step, "user");
},
webix_inp_counter_prev: function () {
if (!this._settings.readonly) this.prev(this._settings.step, "user");
},
webix_input_icon: function () {
this.getInputNode().focus();
},
webix_clear_icon: function () {
if (this.$allowsClear) this.setValue("", "user");
return false;
},
webix_inp_checkbox_border: function (e) {
if (!this._settings.disabled && e.target.tagName != "DIV" && !this._settings.readonly) this.toggle("user");
},
webix_inp_checkbox_label: function () {
if (!this._settings.readonly) this.toggle("user");
},
webix_inp_radio_border: function (e) {
var id = locate(e,
/*@attr*/
"radio_id");
var opt = this.getOption(id);
if (opt && !opt.disabled) {
this.setValue(id, "user");
this.focus();
}
},
webix_tab_more_icon: function (ev, obj, node) {
var popup = this.getPopup();
if (!popup.isVisible()) {
popup.resize();
popup.show(node, null, true);
} else popup.hide();
},
webix_tab_close: function (e) {
var id = locate(e,
/*@attr*/
"button_id");
var opt = this.getOption(id);
if (opt && !opt.disabled && this.callEvent("onBeforeTabClose", [id, e])) this.removeOption(id);
return false;
}
},
//method do not used by button, but used by other child-views
_check_options: function (opts) {
assert(!!opts, this.name + ": options not defined");
assert(isArray(opts), this.name + ": options must be an array");
for (var i = 0; i < opts.length; i++) {
// asserts need to be removed in final version
assert(!opts[i].text, "Please replace .text with .value in control config");
assert(!opts[i].label, "Please replace .label with .value in control config");
if (typeof opts[i] == "string") {
opts[i] = {
id: opts[i],
value: opts[i]
};
} else {
if (isUndefined(opts[i].id)) opts[i].id = opts[i].value;
if (isUndefined(opts[i].value)) opts[i].value = opts[i].id;
}
}
return opts;
},
_get_div_placeholder: function (obj) {
var placeholder = obj ? obj.placeholder : this._settings.placeholder;
return placeholder ? "<span class='webix_placeholder'>" + placeholder + "</span>" : "";
}
};
var view$v = exports.protoUI(api$v, base$1.view, AutoTooltip, AtomRender, Settings, EventSystem);
var button$1 = {
api: api$v,
view: view$v
};
var api$w = {
name: "label",
defaults: {
template: "<div class='webix_el_box' style='width:#awidth#px;height:#aheight#px;line-height:#cheight#px'>#label#</div>"
},
$skin: function () {
button$1.api.$skin.call(this);
this.defaults.height = $active.inputHeight;
},
focus: function () {
return false;
},
_getBox: function () {
return this._dataobj.firstChild;
},
setHTML: function (html) {
this._settings.label = html;
this.refresh();
},
setValue: function (value) {
this._settings.label = value;
button$1.api.setValue.apply(this, arguments);
},
$setValue: function (value) {
this._dataobj.firstChild.innerHTML = value;
},
$render: function (config) {
if (config.align === "right") this._dataobj.firstChild.style.textAlign = "right";
},
_set_inner_size: false,
_set_default_css: function () {},
_calc_size: function (config) {
var css = "webix_el_box webixlabel" + (this.queryView("toolbar", "parent") ? " webixtoolbarlabel" : "");
config = config || this._settings;
if (config.autowidth) config.width = getTextSize(config.label, css).width;
}
};
var view$w = exports.protoUI(api$w, button$1.view);
var nav_controls = {
9: "tab",
38: "up",
40: "down",
37: "left",
39: "right"
};
var TextPattern = {
$init: function (config) {
var pattern = this.defaults.pattern || config.pattern;
var format = this.defaults.format || config.format;
config.value = isUndefined(config.value) ? "" : config.value;
if (pattern || format && !this.format_setter) {
this.attachEvent("onKeyPress", function (code, e) {
if (e.ctrlKey || e.altKey || this._settings.readonly || this._custom_format) return;
if (code > 105 && code < 112) //numpad operators
code -= 64;
if (nav_controls[code] && code !== 8 && code !== 46) {
//del && bsp
return;
}
preventEvent(e);
this._on_key_pressed(e, code);
});
this.attachEvent("onAfterRender", this._after_render);
this.getText = function () {
return this.getInputNode().value;
};
this.$prepareValue = function (value) {
return this._pattern(value, false);
};
this._pattern = function (value, mode) {
if (mode === false) return this._getRawValue(value);else return this._matchPattern(value);
};
if (format) {
if (_typeof(format) === "object") {
this._custom_format = format;
} else {
format = Number$1.getConfig(format);
this._custom_format = {
parse: function (value) {
return Number$1.parse(value, format);
},
edit: function (value) {
return Number$1.format(value, format);
}
};
}
}
} // initialize pattern before value_setter
if (pattern) {
this._settings.pattern = this.pattern_setter(pattern);
delete config.pattern;
}
},
pattern_setter: function (value) {
var pattern = patterns[value] || value;
if (typeof pattern == "string") pattern = {
mask: pattern
};
pattern.allow = pattern.allow || /[A-Za-z0-9]/g;
this._patternScheme(pattern);
return pattern;
},
_init_validation: function () {
this.config.validate = this.config.validate || bind(function () {
var value = this.getText();
var raw = value.replace(this._pattern_chars, "");
var matches = (value.toString().match(this._pattern_allows) || []).join("");
return matches.length == raw.length && value.length == this._settings.pattern.mask.length;
}, this);
},
_after_render: function () {
var ev = env.isIE8 ? "propertychange" : "input";
if (!this._custom_format) _event(this.getInputNode(), ev, function () {
var stamp = new Date().valueOf(); //dark ie8 magic
var width = this.$view.offsetWidth; //eslint-disable-line
if (!this._property_stamp || stamp - this._property_stamp > 100) {
this._property_stamp = stamp;
this.$setValue(this.getText());
}
}, {
bind: this
});
_event(this.getInputNode(), "blur", function () {
this._applyChanges();
}, {
bind: this
});
},
_patternScheme: function (pattern) {
var mask = pattern.mask,
scheme = {},
chars = "",
count = 0;
for (var i = 0; i < mask.length; i++) {
if (mask[i] === "#") {
scheme[i] = count;
count++;
} else {
scheme[i] = false;
if (chars.indexOf(mask[i]) === -1) chars += "\\" + mask[i];
}
}
this._pattern_allows = pattern.allow;
this._pattern_chars = new RegExp("[" + chars + "]", "g");
this._pattern_scheme = scheme;
this._init_validation();
},
_on_key_pressed: function (e, code) {
var node = this.getInputNode();
var value = node.value;
var pos$$1 = getSelectionRange(node);
var chr = "";
if (code == 8 || code == 46) {
if (pos$$1.start == pos$$1.end) {
if (code == 8) pos$$1.start--;else pos$$1.end++;
}
} else {
chr = String.fromCharCode(code);
var isCapsLock = e.getModifierState("CapsLock");
if (!e.shiftKey && !isCapsLock || e.shiftKey && isCapsLock) chr = chr.toLowerCase();
}
value = value.substr(0, pos$$1.start) + chr + value.substr(pos$$1.end);
pos$$1 = this._getCaretPos(chr, value.length, pos$$1.start, code);
this._input_code = code;
this.$setValue(value);
setSelectionRange(node, pos$$1);
},
_getCaretPos: function (chr, len, pos$$1, code) {
if (chr && chr.match(this._pattern_allows) || code == 8 || code == 46) {
pos$$1 = chr ? pos$$1 + 1 : pos$$1;
pos$$1 = this._fixCaretPos(pos$$1, code);
} else if (len - 1 == pos$$1 && code !== 8 && code !== 46) {
var rest = this._settings.pattern.mask.indexOf("#", pos$$1);
if (rest > 0) pos$$1 += rest;
}
return pos$$1;
},
_fixCaretPos: function (pos$$1, code) {
var prev = pos$$1 - (code !== 46) * 1;
if (this._pattern_scheme[prev] === false) {
pos$$1 = pos$$1 + (code == 8 ? -1 : 1);
return this._fixCaretPos(pos$$1, code);
}
if (this._pattern_scheme[pos$$1] === false && code !== 8) return this._fixCaretPos(pos$$1 + 1, code) - 1;
return pos$$1;
},
_getRawValue: function (value) {
if (this._custom_format) return this._custom_format.parse(value);
value = value || value === 0 ? value : "";
var matches = value.toString().match(this._pattern_allows) || [];
return matches.join("").replace(this._pattern_chars, "");
},
_matchPattern: function (value) {
if (this._custom_format) return this._custom_format.edit(this._custom_format.parse(value));
var raw = this._getRawValue(value),
pattern = this._settings.pattern.mask,
mask = this._settings.pattern.mask,
scheme = this._pattern_scheme,
end = false,
index$$1 = 0,
rawIndex = 0,
rawLength = 0;
for (var i in scheme) {
if (scheme[i] !== false) {
if (!end) {
index$$1 = i * 1;
rawIndex = scheme[i];
var rchar = raw[rawIndex] || "";
var next = raw[rawIndex + 1];
pattern = (rchar ? pattern.substr(0, index$$1) : "") + rchar + (rchar && next ? pattern.substr(index$$1 + 1) : "");
if (!next) end = true;
}
rawLength++;
}
} //finalize value with subsequent mask chars
var icode = this._input_code;
if (icode && icode !== 8 || !icode && rawLength - 1 === rawIndex && pattern.length < mask.length) {
if (raw) {
var nind = index$$1 + 1;
if (mask.charAt(nind) !== "#" && pattern.length < mask.length) {
var lind = mask.indexOf("#", nind);
if (lind < 0) lind = mask.length;
pattern += mask.substr(nind, lind - nind);
}
} else if (icode !== 46) {
pattern += mask.substr(0, mask.indexOf("#"));
}
}
this._input_code = null;
return pattern;
}
};
var api$x = {
name: "text",
$allowsClear: true,
_init_onchange: function () {
var _this = this;
if (this.$allowsClear) {
var c = this._settings;
var node = this.getInputNode(); //attach onChange handler only for controls which do not manage blur on their own
//for example - combo
if (!this._onBlur) _event(node, "change", this._applyChanges, {
bind: this
});
if (c.suggest) $$(c.suggest).linkInput(this);
if (c.clear && !this.addSection) {
this._clear_icon = this.$view.querySelector(".webix_input_icon:last-child");
if (node.tagName == "INPUT" || node.tagName == "SELECT") _event(node, "input", function (e) {
return _this._toggleClearIcon(e.target.value);
});
var text = this.getText ? this.getText() : c.text || c.value;
this._toggleClearIcon(text);
}
}
},
_applyChanges: function () {
var value = this.getValue();
var res = this.setValue(value, "user"); //controls with post formating, we need to repaint value
if (this._custom_format && res === false) this.$setValue(value);
},
_toggleClearIcon: function (value) {
var c = this._settings;
if (!c.clear || !this._clear_icon) return;
if (c.clear === "hover" || c.clear === "replace") {
var css = value ? "webix_clear_icon " + (c.clear === "hover" ? c.icon : "wxi-close") : c.icon;
this._clear_icon.className = "webix_input_icon " + css;
} else {
var state = value ? "" : "hidden";
if (this._clear_icon.style.visibility !== state) this._clear_icon.style.visibility = state;
}
},
$skin: function () {
button$1.api.$skin.call(this);
this.defaults.height = $active.inputHeight;
this.defaults.inputPadding = $active.inputPadding;
this._inputSpacing = $active.inputSpacing;
this._labelTopHeight = $active.labelTopHeight;
},
$init: function (config) {
if (config.labelPosition == "top" && isUndefined(config.height) && this.defaults.height) // textarea
config.height = this.defaults.height + (config.label ? this._labelTopHeight : 0); // used in clear_setter
if (!isUndefined(config.icon)) this._settings.icon = config.icon;
if (this._onBlur) this.attachEvent("onBlur", function () {
if (this._rendered_input) this._onBlur();
});
this.attachEvent("onAfterRender", this._init_onchange);
this.attachEvent("onDestruct", function () {
this._clear_icon = null;
});
},
clear_setter: function (value) {
if (value) {
if (!this._settings.icon) value = true;
if (value !== "hover" && value !== "replace") value = !!value;
}
return value;
},
$renderIcon: function (c) {
var height = c.aheight - 2 * c.inputPadding;
var padding = (height - 18) / 2 - 1;
var right = this._inputSpacing / 2 - 24;
var html = "";
if (c.icon) {
right += 24;
html += "<span style='right:" + right + "px;height:" + (height - padding) + "px;padding-top:" + padding + "px;' class='webix_input_icon " + c.icon + "'></span>";
}
if (c.clear === true) {
right += 24;
html += "<span style='right:" + right + "px;height:" + (height - padding) + "px;padding-top:" + padding + "px;' class='webix_input_icon webix_clear_icon webix_icon_transparent wxi-close'></span>";
}
return html;
},
relatedView_setter: function (value) {
this.attachEvent("onChange", function () {
var value = this.getValue();
var mode = this._settings.relatedAction;
var viewid = this._settings.relatedView;
var view = $$(viewid);
if (!view) {
var top = this.getTopParentView();
if (top && top.$$) view = top.$$(viewid);
}
assert(view, "Invalid relatedView: " + viewid);
if (mode == "enable") {
if (value) view.enable();else view.disable();
} else {
if (value) view.show();else view.hide();
}
});
return value;
},
validateEvent_setter: function (value) {
if (value == "blur") this.attachEvent("onBlur", this.validate);
if (value == "key") this.attachEvent("onTimedKeyPress", this.validate);
return value;
},
validate: function () {
var rule = this._settings.validate;
if (!rule && this._settings.required) rule = rules.isNotEmpty;
var form = this.getFormView();
var name = this._settings.name;
var value = this.getValue();
var data = {};
data[name] = value;
assert(form, "Validation works only for fields in the form");
assert(name, "Validation works only for fields with name");
if (rule && !form._validate(rule, value, data, name)) return false;
return true;
},
bottomLabel_setter: function (value) {
if (!this._settings.bottomPadding) this._settings.bottomPadding = 18;
return value;
},
_getInvalidText: function () {
var text = this._settings.invalidMessage;
if (typeof text == "function") {
text.call(this);
}
return text;
},
setBottomText: function (text, height) {
var config = this._settings;
if (typeof text != "undefined") {
if (config.bottomLabel == text) return;
config.bottomLabel = text;
}
var message = (config.invalid ? config.invalidMessage : "") || config.bottomLabel;
if (!message && !config.bottomPadding) config.inputHeight = 0;
if (message && !config.bottomPadding) {
this._restorePadding = 1;
config.bottomPadding = config.bottomPadding || height || 18;
this.render();
this.adjust();
this.resize();
} else if (!message && this._restorePadding) {
config.bottomPadding = this._restorePadding = 0; //textarea
if (!config.height) this.render();
this.adjust();
this.resize();
} else this.render();
},
$getSize: function () {
var sizes = base$1.api.$getSize.apply(this, arguments);
var heightInc = this.config.bottomPadding;
if (heightInc) {
sizes[2] += heightInc;
sizes[3] += heightInc;
}
return sizes;
},
$setSize: function (x, y) {
var config = this._settings;
if (base$1.api.$setSize.call(this, x, y)) {
if (!x || !y) return;
if (config.labelPosition == "top") {
config.labelWidth = 0; // textarea
if (!config.inputHeight) this._inputHeight = this._content_height - (config.label ? this._labelTopHeight : 0) - (this.config.bottomPadding || 0);
} else {
if (config.label) config.labelWidth = this._getLabelWidth(config.labelWidth, config.label);
if (config.bottomPadding) config.inputHeight = this._content_height - this.config.bottomPadding;
}
this.render();
}
},
_get_input_width: function (config) {
var width = (this._input_width || 0) - (config.label ? config.labelWidth : 0) - this._inputSpacing - (config.iconWidth || 0); //prevent js error in IE
return width < 0 ? 0 : width;
},
_render_div_block: function (obj, common) {
var id = "x" + uid();
var width = common._get_input_width(obj);
var inputAlign = obj.inputAlign || "left";
var height = obj.aheight - 2 * $active.inputPadding - 2 * $active.borderWidth;
var rightPadding = obj.clear === true ? "padding-right:51px;" : "";
var text = obj.text || obj.value || this._get_div_placeholder(obj);
var html = "<div class='webix_inp_static' role='combobox' aria-label='" + template.escape(obj.label) + "' tabindex='0'" + (obj.readonly ? " aria-readonly='true'" : "") + (obj.invalid ? "aria-invalid='true'" : "") + " onclick='' style='line-height:" + height + "px;width:" + width + "px;text-align:" + inputAlign + ";" + rightPadding + "'>" + text + "</div>";
return common.$renderInput(obj, html, id);
},
_baseInputHTML: function (tag) {
var html = "<" + tag + (this._settings.placeholder ? " placeholder='" + template.escape(this._settings.placeholder) + "' " : " ");
if (this._settings.readonly) html += "readonly='true' aria-readonly=''";
if (this._settings.required) html += "aria-required='true'";
if (this._settings.invalid) html += "aria-invalid='true'";
var attrs = this._settings.attributes;
if (attrs) for (var prop in attrs) {
html += prop + "='" + attrs[prop] + "' ";
}
return html;
},
$renderLabel: function (config, id) {
var label = "";
if (config.label) {
var top = this._settings.labelPosition == "top";
var style = "text-align:".concat(config.labelAlign || "left", "; line-height:").concat(this._getLabelHeight(top), "px; ");
if (top) style += "display:block;";else style += config.labelWidth ? "width:".concat(config.labelWidth, "px;") : "display:none;";
label = "<label style='" + style + "' onclick='' for='" + id + "' class='webix_inp_" + (top ? "top_" : "") + "label " + (config.required ? "webix_required" : "") + "'>" + (config.label || "") + "</label>";
}
return label;
},
_getLabelHeight: function (top) {
return top ? this._labelTopHeight - this._settings.inputPadding : this._settings.aheight - 2 * this._settings.inputPadding;
},
$renderInput: function (config, div_start, id) {
var inputAlign = config.inputAlign || "left";
var top = config.labelPosition == "top";
var inputWidth = this._get_input_width(config);
id = id || uid();
var label = this.$renderLabel(config, id);
var html = "";
if (div_start) {
html += div_start;
} else {
var value = template.escape(config.text || this._pattern(config.value));
var rightPadding = (config.icon || config.clear ? 27 : 0) + (config.icon && config.clear === true ? 24 : 0);
rightPadding = rightPadding && !this.addSection ? "padding-right:" + rightPadding + "px;" : "";
html += this._baseInputHTML("input") + "id='" + id + "' type='" + (config.type || this.name) + "'" + (config.editable ? " role='combobox'" : "") + " value='" + value + "' style='width:" + inputWidth + "px;text-align:" + inputAlign + ";" + rightPadding + "'";
var attrs = config.attributes;
if (attrs) for (var prop in attrs) {
html += " " + prop + "='" + attrs[prop] + "'";
}
html += " />";
}
html += this.$renderIcon ? this.$renderIcon(config) : "";
var result = ""; //label position, top or left
if (top) result = label + "<div class='webix_el_box' style='width:" + config.awidth + "px; height:" + config.aheight + "px'>" + html + "</div>";else result = "<div class='webix_el_box' style='width:" + config.awidth + "px; height:" + config.aheight + "px'>" + label + html + "</div>"; //bottom message width
var padding = config.awidth - inputWidth - $active.inputPadding * 2; //bottom message text
var message = (config.invalid ? config.invalidMessage : "") || config.bottomLabel;
if (message) result += "<div class='webix_inp_bottom_label'" + (config.invalid ? "role='alert' aria-relevant='all'" : "") + " style='width:" + (inputWidth || config.awidth) + "px;margin-left:" + Math.max(padding, $active.inputPadding) + "px;'>" + message + "</div>";
return result;
},
defaults: {
template: function (obj, common) {
return common.$renderInput(obj);
},
label: "",
labelWidth: 80
},
_getLabelWidth: function (width, label) {
if (width == "auto") width = getTextSize(label, "webix_inp_label").width;
return width ? Math.max(width, $active.dataPadding) : 0;
},
type_setter: function (value) {
return value;
},
_set_inner_size: false,
_set_default_css: function () {},
_pattern: function (value) {
return value;
},
$setValue: function (value) {
value = this._pattern(value);
this.getInputNode().value = value;
this._toggleClearIcon(value);
},
$getValue: function () {
return this._pattern(this.getInputNode().value, false);
},
setValueHere: function (v, data, details) {
if (details && details.symbol) {
var s = details.symbol;
var value = this.getValue();
var last = value.substring(details.pos);
value = value.substring(0, details.pos);
value = value.substring(0, value.lastIndexOf(s) + s.length) + v;
this.setValue(value + last, details.config);
setSelectionRange(this.getInputNode(), value.length);
} else this.setValue(v, details && details.config);
},
suggest_setter: function (value) {
if (value) {
assert(value !== true, "suggest options can't be set as true, data need to be provided instead");
if (typeof value == "string") {
var attempt = $$(value);
if (attempt) return $$(value)._settings.id;
value = {
body: {
url: value,
dataFeed: value
}
};
} else if (value.getItem) value = {
body: {
data: value
}
};else if (isArray(value)) value = {
body: {
data: this._check_options(value)
}
};else if (!value.body) value.body = {};
exports.extend(value, {
view: "suggest"
});
var _view = ui(value);
this._destroy_with_me.push(_view);
return _view._settings.id;
}
return false;
}
};
var view$x = exports.protoUI(api$x, TextPattern, button$1.view);
var text = {
api: api$x,
view: view$x
};
var DataCollection = exports.proto({
name: "DataCollection",
isVisible: function () {
if (!this.data.order.length && !this.data._filter_order && !this._settings.dataFeed) return false;
return true;
},
$init: function (config) {
this.data.provideApi(this, true);
var id = config && config.id ? config.id : uid();
this._settings.id = id;
ui.views[id] = this;
this.data.attachEvent("onStoreLoad", bind(function () {
this.callEvent("onBindRequest", []);
}, this));
},
refresh: function () {
this.callEvent("onBindRequest", []);
}
}, DataMove, CollectionBind, BindSource, ValidateCollection, DataLoader, MapCollection, EventSystem, BaseBind, Destruction, Settings);
define("DataCollection", DataCollection);
var api$y = {
name: "select",
defaults: {
template: function (obj, common) {
var id = "x" + uid();
var html = common._baseInputHTML("select") + "id='" + id + "' style='width:" + common._get_input_width(obj) + "px;'>";
var optview = $$(obj.options);
if (optview && optview.data && optview.data.each) {
optview.data.each(function (option) {
html += "<option" + (option.id == obj.value ? " selected='true'" : "") + " value='" + option.id + "'>" + option.value + "</option>";
});
} else {
var options = common._check_options(obj.options);
for (var i = 0; i < options.length; i++) {
html += "<option" + (options[i].id == obj.value ? " selected='true'" : "") + " value='" + options[i].id + "'>" + options[i].value + "</option>";
}
}
html += "</select>";
return common.$renderInput(obj, html, id);
}
},
options_setter: function (value) {
if (value) {
if (typeof value == "string") {
var collection = new DataCollection({
url: value
});
collection.data.attachEvent("onStoreLoad", bind(this.refresh, this));
return collection;
} else return value;
}
},
$renderIcon: function () {
return "";
},
//get input element
getInputNode: function () {
return this._dataobj.getElementsByTagName("select")[0];
}
};
var view$y = exports.protoUI(api$y, text.view);
var api$z = {
name: "checkbox",
defaults: {
checkValue: 1,
uncheckValue: 0,
template: function (config, common) {
var id = "x" + uid();
var rightlabel = "";
if (config.labelRight) {
rightlabel = "<label class='webix_label_right'>" + config.labelRight + "</label>"; //user clearly attempts to hide the label, help him
if (config.labelWidth) config.label = config.label || " ";
}
var checked = config.checkValue == config.value;
var margin = Math.floor((common._settings.aheight - 16) / 2);
var ch = common._baseInputHTML("input") + "style='margin-top:" + margin + "px;" + (config.customCheckbox ? "display:none" : "") + "' id='" + id + "' type='checkbox' " + (checked ? "checked='1'" : "") + (config.labelRight ? " aria-label='" + template.escape(config.labelRight) + "'" : "") + "/>";
var className = "webix_inp_checkbox_border webix_el_group webix_checkbox_" + (checked ? "1" : "0");
var customCheckbox = config.customCheckbox || "";
if (customCheckbox) {
customCheckbox = customCheckbox.replace(/(aria-checked=')\w*(?=')/, "$1" + (config.value == config.checkValue ? "true" : "false"));
customCheckbox = customCheckbox.replace(/(aria-label=')\w*(?=')/, "$1" + template.escape(config.labelRight || config.label));
customCheckbox = customCheckbox.replace(/(aria-invalid=')\w*(?=')/, "$1" + (config.invalid ? "true" : "false"));
}
var html = "<div style='line-height:" + common._settings.cheight + "px' class='" + className + "'>" + ch + customCheckbox + rightlabel + "</div>";
return common.$renderInput(config, html, id);
}
},
customCheckbox_setter: function (value) {
if (value === true && $active.customCheckbox) {
value = "<a role='presentation' onclick='javascript:void(0)'><button role='checkbox' aria-checked='false' aria-label='' type='button' aria-invalid='' class='webix_custom_checkbox'></button></a>";
}
return value;
},
blur: function () {
var input = this.getInputNode();
if (input) input.blur();
},
$prepareValue: function (value) {
return value;
},
_init_onchange: function () {},
$setValue: function (value) {
var isChecked = value == this._settings.checkValue;
var input = this.$view.getElementsByTagName("input")[0];
var parentNode = input ? input.parentNode : null;
if (parentNode && this._settings.customCheckbox) {
var button = parentNode.getElementsByTagName("BUTTON");
if (button[0]) button[0].setAttribute("aria-checked", isChecked ? "true" : "false");
}
if (parentNode) {
parentNode.className = parentNode.className.replace(/(webix_checkbox_)\d/, "$1" + (isChecked ? 1 : 0));
}
input.checked = isChecked;
},
toggle: function (config) {
var c = this._settings;
var value = this.getValue() != c.checkValue ? c.checkValue : c.uncheckValue;
this.setValue(value, config);
},
getValue: function () {
var c = this._settings;
return c.value == c.checkValue ? c.checkValue : c.uncheckValue;
},
getInputNode: function () {
return this.$view.getElementsByTagName(this._settings.customCheckbox ? "button" : "input")[0];
},
$skin: function () {
text.api.$skin.call(this);
this.defaults.customCheckbox = !!$active.customCheckbox;
}
};
var view$z = exports.protoUI(api$z, text.view);
var checkbox = {
api: api$z,
view: view$z
};
var api$A = {
name: "radio",
defaults: {
template: function (config, common) {
common._check_options(config.options);
var options = common._filterOptions(config.options);
var active = common._getFirstActive();
var id, eachid, isChecked, isDisabled, label, tooltip, customRadio, optlabel, rd, input, focusable;
var html = [];
for (var i = 0; i < options.length; i++) {
eachid = "x" + uid();
id = id || eachid;
if (i && (options[i].newline || config.vertical)) html.push("<div class='webix_line_break'></div>");
isChecked = options[i].id == config.value;
focusable = isChecked || !config.value && options[i].id === active;
isDisabled = !!options[i].disabled;
label = options[i].value || "";
tooltip = config.tooltip ? " webix_t_id='" + options[i].id + "'" : "";
customRadio = config.customRadio || "";
if (customRadio) {
optlabel = (i === 0 ? config.label + " " : "") + label;
customRadio = customRadio.replace(/(aria-label=')\w*(?=')/, "$1" + template.escape(optlabel));
customRadio = customRadio.replace(/(aria-checked=')\w*(?=')/, "$1" + (isChecked ? "true" : "false"));
customRadio = customRadio.replace(/(tabindex=')\w*(?=')/, "$1" + (!isDisabled && focusable ? "0" : "-1"));
customRadio = customRadio.replace(/(aria-invalid=')\w*(?=')/, "$1" + (config.invalid ? "true" : "false"));
customRadio = customRadio.replace(/(button_id=')\w*(?=')/, "$1" + options[i].id);
if (isDisabled) customRadio = customRadio.replace("role='radio'", "role='radio' webix_disabled='true'");
}
rd = common._baseInputHTML("input") + " name='" + (config.name || config.id) + "' type='radio' " + (isChecked ? "checked='1'" : "") + "tabindex=" + (!isDisabled && focusable ? "0" : "-1") + " value='" + options[i].id + "' id='" + eachid + "'" + (isDisabled ? " disabled='true'" : "") + " style='" + (customRadio ? "display:none" : "") + "' />";
input = "<div " +
/*@attr*/
"radio_id" + "='" + options[i].id + "' class='webix_inp_radio_border webix_radio_" + (isChecked ? "1" : "0") + "' role='presentation'>" + rd + customRadio + "</div>";
if (label) label = "<label for='" + eachid + "' class='webix_label_right'>" + label + "</label>";
html.push("<div class='webix_radio_option" + (isDisabled ? " webix_disabled" : "") + "' role='presentation'" + tooltip + ">" + input + label + "</div>");
}
html = "<div class='webix_el_group' role='radiogroup' style='margin-left:" + (config.label ? config.labelWidth : 0) + "px;'>" + html.join("") + "</div>";
return common.$renderInput(config, html, id);
}
},
refresh: function () {
this.render();
if (this._last_size && this.$getSize(0, 0)[2] != this._last_size[1]) this.resize();
},
$getSize: function (dx, dy) {
var size = button$1.api.$getSize.call(this, dx, dy);
var options = this._filterOptions(this._settings.options);
if (options) {
var count = this._settings.vertical ? 0 : 1;
for (var i = 0; i < options.length; i++) {
if (this._settings.vertical || options[i].newline) count++;
}
size[3] = size[2] = Math.max(size[2], (this._settings.optionHeight || 25) * count + this._settings.inputPadding * 2 + (this._settings.labelPosition == "top" ? this._labelTopHeight : 0));
}
var heightInc = this.config.bottomPadding;
if (heightInc) {
size[2] += heightInc;
size[3] += heightInc;
}
return size;
},
_getInputNode: function () {
return this._dataobj.getElementsByTagName(this._settings.customRadio ? "button" : "input");
},
$setValue: function (value) {
var inp = this._dataobj.getElementsByTagName("input");
var active = this._getFirstActive();
var id, option, focusable, parentNode, button;
for (var i = 0; i < inp.length; i++) {
id = inp[i].parentNode.getAttribute(
/*@attr*/
"radio_id");
option = this.getOption(id);
inp[i].checked = id == value;
focusable = option && !option.disabled && (inp[i].checked || !value && option.id == active);
inp[i].setAttribute("tabindex", focusable ? "0" : "-1");
parentNode = inp[i] ? inp[i].parentNode : null;
if (parentNode) {
parentNode.className = parentNode.className.replace(/(webix_radio_)\d/, "$1" + (inp[i].checked ? 1 : 0));
if (this._settings.customRadio) {
button = parentNode.getElementsByTagName("BUTTON");
if (button[0]) {
button[0].setAttribute("aria-checked", inp[i].checked ? "true" : "false");
button[0].setAttribute("tabindex", focusable ? "0" : "-1");
}
}
}
}
},
getValue: function () {
return this._settings.value;
},
focus: function () {
return this._focus();
},
blur: function () {
this._blur();
},
customRadio_setter: function (value) {
if (value === true && $active.customRadio) value = "<a role='presentation' onclick='javascript:void(0)'><button type='button' class='webix_custom_radio' " +
/*@attr*/
"button_id='' role='radio' aria-checked='false' aria-label='' aria-invalid='' tabindex=''></button></a>";
return value;
},
$skin: function () {
text.api.$skin.call(this);
this.defaults.customRadio = !!$active.customRadio;
if ($active.optionHeight) this.defaults.optionHeight = $active.optionHeight;
}
};
var view$A = exports.protoUI(api$A, text.view, HTMLOptions);
var api$B = {
name: "datepicker",
_editable: true,
$init: function (config) {
// value_setter handling
if (config.multiselect) {
this._settings.multiselect = config.multiselect;
}
if (config.type) {
this._settings.type = config.type;
}
this.$ready.push(this._init_popup);
},
defaults: {
template: function (obj, common) {
if (common._settings.type == "time") {
common._settings.icon = common._settings.timeIcon;
} //temporary remove obj.type [[DIRTY]]
var t = obj.type;
obj.type = "";
var res = obj.editable ? common.$renderInput(obj) : common._render_div_block(obj, common);
obj.type = t;
return res;
},
stringResult: false,
timepicker: false,
icon: "wxi-calendar",
icons: true,
timeIcon: "wxi-clock",
separator: ", "
},
_onBlur: function () {
var text$$1 = this.getText();
if (this._settings.text == text$$1) return;
var value = this._settings.editable ? this.getValue() : this.getPopup().getValue();
this.setValue(value || "", "user");
},
$skin: function () {
text.api.$skin.call(this);
this.defaults.inputPadding = $active.inputPadding;
this.defaults.point = !$active.popupNoPoint;
},
getPopup: function () {
return $$(this._settings.popup);
},
_init_popup: function () {
var obj = this._settings;
if (obj.suggest) obj.popup = obj.suggest;else if (!obj.popup) {
var timepicker = this._settings.timepicker;
obj.popup = obj.suggest = this.suggest_setter({
type: "calendar",
point: this._settings.point === false ? false : true,
padding: 0,
body: {
height: 240 + (timepicker || this._settings.icons ? 30 : 0),
width: 250,
multiselect: this._settings.multiselect,
timepicker: timepicker,
type: this._settings.type,
icons: this._settings.icons,
timeIcon: this._settings.timeIcon
}
});
}
this._init_once = function () {};
},
$render: function (obj) {
this.$setValue(obj.value);
},
$prepareValue: function (value) {
if (this._settings.multiselect) {
if (typeof value === "string") value = value.split(this._settings.separator);else if (value instanceof Date) value = [value];else if (!value) value = [];
for (var i = 0; i < value.length; i++) {
value[i] = this._prepareSingleValue(value[i]);
}
return value;
} else return this._prepareSingleValue(value);
},
_prepareSingleValue: function (value) {
var type = this._settings.type;
var timeMode = type == "time"; //setValue("1980-12-25")
if (!isNaN(parseFloat(value))) value = "" + value;
if (typeof value == "string" && value) {
var formatDate = null;
if ((type == "month" || type == "year") && this._formatDate) formatDate = this._formatDate;else formatDate = timeMode ? i18n.parseTimeFormatDate : i18n.parseFormatDate;
value = formatDate(value);
}
if (value) {
//time mode
if (timeMode) {
//setValue([16,24])
if (isArray(value)) {
var time = new Date();
time.setHours(value[0]);
time.setMinutes(value[1]);
value = time;
}
} //setValue(invalid date)
if (isNaN(value.getTime())) value = "";
}
return value;
},
_get_visible_text: function (value) {
var _this = this;
if (this._settings.multiselect) return [].concat(value).map(function (a) {
return _this._get_visible_text_single(a);
}).join(this.config.separator);else return this._get_visible_text_single(value);
},
_get_visible_text_single: function (value) {
var formatStr = this._formatStr;
if (!formatStr) {
if (this._settings.type == "time") formatStr = i18n.timeFormatStr;else if (this.config.timepicker) formatStr = i18n.fullDateFormatStr;else formatStr = i18n.dateFormatStr;
}
return formatStr(value);
},
_set_visible_text: function () {
var node = this.getInputNode();
if (isUndefined(node.value)) node.innerHTML = this._settings.text || this._get_div_placeholder();else node.value = this._settings.text || "";
},
$compareValue: function (oldvalue, value) {
if (!oldvalue && !value) return true;
return wDate.equal(oldvalue, value);
},
$setValue: function (value) {
this._settings.text = value ? this._get_visible_text(value) : "";
this._set_visible_text();
this._toggleClearIcon(this._settings.text);
},
format_setter: function (value) {
if (value) {
if (typeof value === "function") this._formatStr = value;else {
this._formatStr = wDate.dateToStr(value);
this._formatDate = wDate.strToDate(value);
}
} else this._formatStr = this._formatDate = null;
return value;
},
getInputNode: function () {
return this._settings.editable ? this._dataobj.getElementsByTagName("input")[0] : this._dataobj.getElementsByTagName("DIV")[1];
},
getValue: function () {
var _this2 = this;
if (this._settings.multiselect) {
var value = this._settings.value;
if (!value) return [];
var result = [].concat(value).map(function (a) {
return _this2._get_value_single(a);
});
if (this._settings.stringResult) return result.join(this._settings.separator);
return result;
}
return this._get_value_single(this._settings.value);
},
_get_value_single: function (value) {
var type = this._settings.type;
var timeMode = type == "time"; //input was not rendered, we need to parse value from setValue method
if (!this._rendered_input) value = this.$prepareValue(value) || null; //rendere and in edit mode
else if (this._settings.editable) {
var formatDate = this._formatDate;
if (!formatDate) {
if (timeMode) formatDate = i18n.timeFormatDate;else if (this.config.timepicker) formatDate = i18n.fullDateFormatDate;else formatDate = i18n.dateFormatDate;
}
var time = formatDate(this.getInputNode().value);
if (timeMode && value != "") {
value.setHours(time.getHours());
value.setMinutes(time.getMinutes());
} else value = time;
} //return string from getValue
if (this._settings.stringResult) {
var formatStr = i18n.parseFormatStr;
if (timeMode) formatStr = i18n.parseTimeFormatStr;
if (this._formatStr && (type == "month" || type == "year")) {
formatStr = this._formatStr;
}
if (this._settings.multiselect) return [].concat(value).map(function (a) {
return a ? formatStr(a) : "";
});
return value ? formatStr(value) : "";
}
return value || null;
},
getText: function () {
var node = this.getInputNode();
if (!node) return "";
if (isUndefined(node.value)) {
if (node.firstChild && node.firstChild.className === "webix_placeholder") return "";
return node.innerHTML;
}
return node.value;
}
};
var view$B = exports.protoUI(api$B, text.view);
var datepicker = {
api: api$B,
view: view$B
};
var api$C = {
name: "colorpicker",
$init: function () {
this.$ready.push(this._init_popup);
},
defaults: {
icon: true
},
_init_popup: function () {
var obj = this._settings;
if (obj.suggest) obj.popup = obj.suggest;else if (!obj.popup) obj.popup = obj.suggest = this.suggest_setter({
type: "colorboard"
});
this._init_once = function () {};
},
clear_setter: function (value) {
return !!value;
},
getValue: function () {
if (this._rendered_input && this._settings.editable) return this.getInputNode().value;else return this._settings.value;
},
$prepareValue: function (value) {
value = value ? value.toString(16) : "";
if (value && value.charAt(0) != "#" && /^[0-9a-fA-F]+$/.test(value)) value = "#" + value;
return value;
},
_getColorNode: function () {
return this.$view.getElementsByTagName("DIV")[this._settings.editable ? 1 : 2];
},
_get_visible_text: function (value) {
return value;
},
$compareValue: function (oldvalue, value) {
return oldvalue == value;
},
$setValue: function (value) {
this._getColorNode().style.backgroundColor = value;
this._settings.text = value;
this._toggleClearIcon(value);
var node = this.getInputNode();
if (isUndefined(node.value)) node.innerHTML = value;else node.value = value;
},
$renderIcon: function (c) {
var right = this._inputSpacing / 2 + 5;
var html = "<div class='webix_input_icon' style='top:" + (c.inputPadding + 4) + "px;right:" + right + "px;background-color:" + c.value + ";'></div>";
if (c.clear) {
var height = c.aheight - 2 * c.inputPadding;
var padding = (height - 18) / 2 - 1;
right += 24;
html += "<span style='right:" + right + "px;height:" + (height - padding) + "px;padding-top:" + padding + "px;' class='webix_input_icon webix_clear_icon wxi-close'></span>";
}
return html;
}
};
var view$C = exports.protoUI(api$C, datepicker.view);
var api$D = {
name: "richselect",
defaults: {
template: function (obj, common) {
return common._render_div_block(obj, common);
},
popupWidth: 200,
icon: "wxi-menu-down"
},
_onBlur: function () {
var text$$1 = this.getText();
if (this._settings.text == text$$1 || isUndefined(this._settings.text) && !text$$1) return;
var suggest = this.getPopup(); //handle clicks on suggest items
if (suggest.$view.contains(document.activeElement)) return;
var nodeValue = this.getInputNode().value;
var value = suggest.getSuggestion(nodeValue);
var oldvalue = this.getValue(); //non-empty value that differs from old value and matches filtering rule
if (value && value != oldvalue && !(nodeValue === "" && suggest.getItemText(value) !== "")) this.setValue(value, "user");else if (nodeValue === "") this.setValue("", "user");else if (this._revertValue) this._revertValue();
},
suggest_setter: function (value) {
return this.options_setter(value);
},
options_setter: function (value) {
value = this._suggest_config ? this._suggest_config(value) : value;
var suggest = this._settings.popup = this._settings.suggest = text.api.suggest_setter.call(this, value);
var list = $$(suggest).getList();
if (list) list.attachEvent("onAfterLoad", bind(this._reset_value, this));
return suggest;
},
getList: function () {
var suggest = $$(this._settings.suggest);
assert(suggest, "Input doesn't have a list");
return suggest.getList();
},
_reset_value: function () {
// multiselect requires value as an array
var value = this._settings.value || [];
if (value.length && !this.getPopup().isVisible() && this.getInputNode() && !(this._settings.text || this.getText())) this.$setValue(value);
},
$skin: function () {
text.api.$skin.call(this);
this.defaults.inputPadding = $active.inputPadding;
},
$render: function (obj) {
this.$setValue(obj.value);
},
getInputNode: function () {
return this._dataobj.getElementsByTagName("DIV")[1];
},
getPopup: function () {
return $$(this._settings.popup);
},
getText: function () {
var value = this._settings.value,
node = this.getInputNode();
if (!node) return value ? this.getPopup().getItemText(value) : "";
if (isUndefined(node.value)) {
if (node.firstChild && node.firstChild.className === "webix_placeholder") return "";
return node.innerHTML;
}
return node.value;
},
$prepareValue: function (value) {
if (value && value.id) return value; //don't convert new items
return text.api.$prepareValue.call(this, value);
},
$setValue: function (value) {
var text$$1 = value;
var popup = this.getPopup();
if (popup) text$$1 = popup.getItemText(value);
if (value && value.id) {
//add new value
var list = popup.getList();
var exists = list.exists(value.id); // add new item only when item with such id doesn't exists yet
if (!exists) list.add(value);
text$$1 = popup.getItemText(value.id); // in case of dynamic list, we can't add extra items
// to not interfere with dynamic loading
if (list._settings.dynamic && !exists) list.remove(value.id);
this._settings.value = this.$prepareValue(value.id);
}
var node = this.getInputNode();
if (isUndefined(node.value)) node.innerHTML = text$$1 || this._get_div_placeholder();else node.value = text$$1 = text$$1.replace(/<[^>]*>/g, "");
this._settings.text = text$$1;
this._toggleClearIcon(text$$1);
},
getValue: function () {
return this._settings.value || "";
},
_ignoreLabelClick: function (ev) {
this.focus();
preventEvent(ev);
}
};
var view$D = exports.protoUI(api$D, text.view);
var richselect = {
api: api$D,
view: view$D
};
var api$E = {
name: "combo",
getInputNode: function () {
return this._dataobj.getElementsByTagName("input")[0];
},
_revertValue: function () {
var value = this.getValue();
this.$setValue(isUndefined(value) ? "" : value);
},
_applyChanges: function () {
var input = this.getInputNode(),
value = "",
suggest = this.getPopup();
if (input.value) {
value = this._settings.value;
if (suggest.getItemText(value) != this.getText()) value = suggest.getSuggestion() || value;
}
if (value != this._settings.value) this.setValue(value, "user");else this.$setValue(value);
},
defaults: {
template: function (config, common) {
return common.$renderInput(config).replace(/(<input)\s*(?=\w)/, "$1" + " role='combobox'");
},
icon: "wxi-menu-down"
},
on_click: {
webix_clear_icon: function () {
if (this.$allowsClear) this.setValue("", "user");
return false;
},
"webix_inp_label": function (e) {
this._ignoreLabelClick(e);
},
"webix_inp_top_label": function (e) {
this._ignoreLabelClick(e);
}
}
};
var view$E = exports.protoUI(api$E, richselect.view);
var api$F = {
name: "counter",
defaults: {
template: function (config, common) {
var value = config.value;
var id = "x" + uid();
var html = "<div role='spinbutton' aria-label='" + template.escape(config.label) + "' aria-valuemin='" + config.min + "' aria-valuemax='" + config.max + "' aria-valuenow='" + config.value + "' class='webix_el_group' style='width:" + common._get_input_width(config) + "px'>";
html += "<button type='button' class='webix_inp_counter_prev' tabindex='-1' aria-label='" + i18n.aria.decreaseValue + "'>-</button>";
html += common._baseInputHTML("input") + " id='" + id + "' type='text' class='webix_inp_counter_value' aria-live='assertive'" + " value='" + value + "'></input>";
html += "<button type='button' class='webix_inp_counter_next' tabindex='-1' aria-label='" + i18n.aria.increaseValue + "'>+</button></div>";
return common.$renderInput(config, html, id);
},
min: 0,
max: Infinity,
value: 0,
step: 1
},
$init: function () {
_event(this.$view, "keydown", this._keyshift, {
bind: this
});
},
_keyshift: function (e) {
if (this._settings.readonly) return;
var code = e.which || e.keyCode,
c = this._settings;
var value = this.getValue();
if (code > 32 && code < 41) {
if (code === 36) value = c.min;else if (code === 35) value = c.max === Infinity ? 1000000 : c.max;else if (code === 33) this.next(c.step, "user");else if (code === 34) this.prev(c.step, "user");else value = value + (code === 37 || code === 40 ? -1 : 1);
if (code > 34 && value >= c.min && value <= c.max) this.setValue(value, "user");
}
},
$setValue: function (value) {
this.getInputNode().value = value;
},
$prepareValue: function (value) {
value = parseFloat(value);
var min = this._settings.min;
var max = this._settings.max;
if (isNaN(value)) value = isFinite(min) ? min : 0;
return Math.min(Math.max(value, min), max);
},
getInputNode: function () {
return this._dataobj.getElementsByTagName("input")[0];
},
getValue: function () {
return button$1.api.getValue.apply(this, arguments) * 1;
},
next: function (step, config) {
step = 1 * (step || this._settings.step);
this.shift(step, config);
},
prev: function (step, config) {
step = -1 * (step || this._settings.step);
this.shift(step, config);
},
shift: function (step, config) {
//round values to fix math precision issue in JS
var new_value = Math.round((this.getValue() + step) * 100000) / 100000;
this.setValue(new_value, config);
}
};
var view$F = exports.protoUI(api$F, text.view);
var api$G = {
name: "icon",
$skin: function () {
button$1.api.$skin.call(this);
this.defaults.height = $active.inputHeight;
this.defaults.width = $active.inputHeight;
},
defaults: {
template: function (obj, view) {
var min = Math.min(obj.awidth, obj.aheight);
var top = Math.round((view._content_height - obj.aheight) / 2);
var inner = "<button type='button' style='height:" + min + "px;width:" + min + "px;' class='webix_icon_button'>" + "<span class='webix_icon " + obj.icon + "'></span></button>";
var lineHeight = obj.aheight != min ? obj.aheight : 0;
return "<div class='webix_el_box' style='width:" + obj.awidth + "px;height:" + obj.aheight + "px;line-height:" + lineHeight + "px;margin-top:" + top + "px'>" + inner + (obj.badge || obj.badge === 0 ? "<span class='webix_badge'>" + obj.badge + "</span>" : "") + "</div>";
}
},
_set_inner_size: false,
_set_default_css: function () {},
$setValue: function () {}
};
var view$G = exports.protoUI(api$G, button$1.view);
var api$H = {
name: "search",
on_click: {
webix_clear_icon: function () {
if (this.$allowsClear) this.setValue("", "user");
return false;
},
"webix_input_icon": function (e) {
this.getInputNode().focus();
if (this.config.clear !== "hover" && e.target && e.target.className.indexOf(this.config.icon) !== -1) this.callEvent("onSearchIconClick", [e]);
}
},
defaults: {
type: "text",
icon: "wxi-search"
}
};
var view$H = exports.protoUI(api$H, text.view);
var api$I = {
name: "segmented",
$allowsClear: false,
$init: function () {
this.attachEvent("onChange", function (value) {
if (this._settings.multiview) this._show_view(value);
});
this.attachEvent("onAfterRender", once(function () {
if (this._settings.multiview && this._settings.value) this._show_view(this._settings.value);
}));
},
_show_view: function (value) {
var top = this.getTopParentView();
var view = null; //get from local isolate
if (top && top.$$) view = top.$$(value); //or check globally
if (!view) view = $$(value);
if (view && view.show) view.show();
},
defaults: {
template: function (obj, common) {
common._check_options(obj.options);
var options = common._filterOptions(obj.options);
var width = common._get_input_width(obj);
var borders = $name == "contrast" ? 0 : options.length - 1;
var optionWidth = obj.optionWidth || Math.floor((width - borders) / options.length);
var html = "<div style='width:" + width + "px' class='webix_all_segments' role='tablist' aria-label='" + template.escape(obj.label) + "'>";
var tooltip, isDisabled;
if (!obj.value) obj.value = common._getFirstActive(true);
for (var i = 0; i < options.length; i++) {
isDisabled = !!options[i].disabled;
tooltip = obj.tooltip ? " webix_t_id='" + options[i].id + "'" : "";
html += "<button type='button' style='width:" + (options[i].width || optionWidth) + "px' role='tab' aria-selected='" + (obj.value == options[i].id ? "true" : "false") + "' tabindex='" + (!isDisabled && obj.value == options[i].id ? "0" : "-1") + "' class='" + "webix_segment_" + (i == options.length - 1 ? "N" : i > 0 ? 1 : 0) + (obj.value == options[i].id ? " webix_selected" : "") + (isDisabled ? " webix_disabled" : "") + "' " + (isDisabled ? "webix_disabled='true' " : "") +
/*@attr*/
"button_id='" + options[i].id + "'" + tooltip + ">" + options[i].value + "</button>";
}
return common.$renderInput(obj, html + "</div>", uid());
}
},
_getInputNode: function () {
return this.$view.getElementsByTagName("BUTTON");
},
focus: function () {
return this._focus();
},
blur: function () {
this._blur();
},
$setValue: function (value) {
//refresh tabbar if the option is in the popup list
var popup = this.config.tabbarPopup;
if (popup && $$(popup) && $$(popup).getBody().exists(value)) return this.refresh();
var inputs = this._getInputNode();
var id, option;
for (var i = 0; i < inputs.length; i++) {
id = inputs[i].getAttribute(
/*@attr*/
"button_id");
option = this.getOption(id);
inputs[i].setAttribute("aria-selected", value == id ? "true" : "false");
inputs[i].setAttribute("tabindex", option && !option.disabled && value == id ? "0" : "-1");
if (value == id) addCss(inputs[i], "webix_selected");else removeCss(inputs[i], "webix_selected");
}
},
$getValue: function () {
return this._settings.value || "";
},
getValue: function () {
return this._settings.value;
},
getInputNode: function () {
return null;
},
_set_inner_size: false
};
var view$I = exports.protoUI(api$I, text.view, HTMLOptions);
var segmented = {
api: api$I,
view: view$I
};
var api$J = {
name: "textarea",
defaults: {
template: function (obj, common) {
var name = obj.name || obj.id;
var id = "x" + uid();
var html = common._baseInputHTML("textarea") + "style='width:" + common._get_input_width(obj) + "px;'";
html += " id='" + id + "' name='" + name + "' class='webix_inp_textarea'>" + common._pattern(obj.value) + "</textarea>";
return common.$renderInput(obj, html, id);
},
minHeight: 60
},
$skin: function () {
text.api.$skin.call(this);
this.defaults.height = 0;
},
_skipSubmit: true,
_getLabelHeight: function (top) {
return top ? this._labelTopHeight - this._settings.inputPadding : "";
},
$renderIcon: function () {
return "";
},
//get input element
getInputNode: function () {
return this._dataobj.getElementsByTagName("textarea")[0];
}
};
var view$J = exports.protoUI(api$J, text.view);
var api$K = {
name: "toggle",
$allowsClear: true,
$init: function () {
this.attachEvent("onItemClick", function () {
this.toggle("user");
});
},
$renderInput: function (obj) {
return "<button type='button' " + (obj.popup ? "aria-haspopup='true'" : "") + " class='webix_button'>" + obj.label + "</button>";
},
$setValue: function (value) {
var input = this.getInputNode();
var obj = this._settings;
var isPressed = value && value != "0";
var text = (isPressed ? obj.onLabel : obj.offLabel) || obj.label;
var children = input.children; //icon or image button
if (this._types[obj.type]) {
var icon = children[0];
if (icon.nodeName == "SPAN" && obj.onIcon && obj.offIcon && obj.onIcon != obj.offIcon) icon.className = icon.className.replace(isPressed ? obj.offIcon : obj.onIcon, isPressed ? obj.onIcon : obj.offIcon);
if (obj.type == "imageTop" || obj.type == "iconTop") children[1].innerHTML = text;else {
input.innerHTML = text;
input.insertBefore(icon, input.firstChild);
}
} else input.innerHTML = text;
input.setAttribute("aria-pressed", isPressed ? "true" : "false");
var changeCss = isPressed ? addCss : removeCss;
changeCss(input.parentNode, "webix_pressed");
},
toggle: function (config) {
this.setValue(!this.getValue(), config);
},
getValue: function () {
var value = this._settings.value;
return !value || value == "0" ? 0 : 1;
},
defaults: {
template: function (obj, common) {
var isPressed = obj.value && obj.value != "0";
var css = isPressed ? " webix_pressed" : "";
obj.label = (isPressed ? obj.onLabel : obj.offLabel) || obj.label;
obj.icon = (isPressed ? obj.onIcon : obj.offIcon) || obj.icon;
var html = "<div class='webix_el_box" + css + "' style='width:" + obj.awidth + "px; height:" + obj.aheight + "px'>" + common.$renderInput(obj, common) + "</div>";
html = html.replace(/(button)\s*(?=\w)/, "$1" + (" aria-pressed='" + (isPressed ? "true" : "false") + "' "));
if (obj.badge || obj.badge === 0) html = html.replace(/<\/div>$/, "<span class='webix_badge'>" + obj.badge + "</span></div>");
return html;
}
},
_set_inner_size: false
};
var view$K = exports.protoUI(api$K, button$1.view);
var api$L = {
name: "multitext",
$cssName: "text",
defaults: {
icon: "wxi-plus-circle",
iconWidth: 25,
separator: ", "
},
getValueHere: function () {
return text.api.getValue.call(this);
},
setValueHere: function (value) {
return text.api.$setValue.call(this, value);
},
getValue: function () {
if (this.config.mode == "extra") return this.getValueHere();
if (this._full_value) return this._full_value;
var values = [this.getValueHere(this)];
for (var i = 0; i < this._subs.length; i++) {
var seg = $$(this._subs[i]).getValueHere();
if (seg) values.push(seg);
}
return values.join(this.config.separator);
},
$setValue: function (value) {
value = value || "";
if (this.config.mode == "extra") return this.setValueHere(value);
this._full_value = value;
var parts = value.split(this.config.separator);
if (parts.length == this._subs.length + 1) {
this.setValueHere(parts[0]);
for (var i = 0; i < this._subs.length; i++) {
$$(this._subs[i]).setValueHere(parts[i + 1]);
}
this._full_value = "";
return;
}
this.removeSection();
this.setValueHere.call(this, parts[0]);
for (var _i = 1; _i < parts.length; _i++) {
this.addSection(parts[_i]);
}
this._full_value = "";
},
$renderIcon: function (c) {
if (c.icon) {
var height = c.aheight - 2 * c.inputPadding;
var padding = (height - 18) / 2 - 1;
var aria = "role='button' tabindex='0' aria-label='" + i18n.aria["multitext" + (c.mode || "") + "Section"] + "'";
return "<span style='right:0;height:" + (height - padding) + "px;padding-top:" + padding + "px;' class='webix_input_icon webix_multitext_icon " + c.icon + "' " + aria + "></span>";
}
return "";
},
_subOnChange: function (v, o, config) {
var parent = this.config.master ? $$(this.config.master) : this;
var value = parent.getValue();
var oldvalue = parent._settings.value;
if (value != oldvalue) {
parent._settings.value = value;
parent.callEvent("onChange", [value, oldvalue, config]);
}
},
addSection: function (text$$1) {
var config = this.config,
newConfig = {
labelWidth: config.labelWidth,
inputWidth: config.inputWidth,
width: config.width,
label: config.label ? " " : "",
view: this.name,
mode: "extra",
value: text$$1 || "",
icon: "wxi-minus-circle",
tooltip: config.tooltip,
suggest: config.suggest || null,
master: config.id
};
exports.extend(newConfig, config.subConfig || {}, true);
var newone = this.getParentView().addView(newConfig);
$$(newone).attachEvent("onChange", this._subOnChange);
this._subs.push(newone);
this.callEvent("onSectionAdd", [newone, this._subs.length]);
return newone;
},
removeSection: function (id) {
var parent = this.config.master ? $$(this.config.master) : this;
for (var i = parent._subs.length - 1; i >= 0; i--) {
var section = parent._subs[i];
if (!id || section == id) {
parent._subs.removeAt(i);
this.getParentView().removeView(section);
parent.callEvent("onSectionRemove", [section, i + 1]);
}
}
},
on_click: {
"webix_input_icon": function () {
if (this.config.mode == "extra") {
var parent = this.getParentView();
this.removeSection(this.config.id);
var childs = parent.getChildViews();
childs[childs.length - 1].focus();
this._subOnChange(null, null, "user");
} else $$(this.addSection()).focus();
return false;
}
},
$init: function () {
this._subs = _to_array([]);
this.attachEvent("onKeyPress", this._onKeyPress);
},
$render: function (obj) {
this.$setValue(obj.value);
}
};
var view$L = exports.protoUI(api$L, text.view);
exports.protoUI({
name: "multiselect",
defaults: {
template: "GPL version doesn't support multiselect <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "multicombo",
defaults: {
template: "GPL version doesn't support multicombo <br> You need Webix PRO"
}
}, template$1.view);
var api$M = {
name: "slider",
$touchCapture: true,
defaults: {
min: 0,
max: 100,
value: 50,
step: 1,
title: false,
moveTitle: true,
template: function (obj, common) {
var id = common._handle_id = "x" + uid();
var html = "";
var title = "<div class='webix_slider_title" + (obj.moveTitle ? " webix_slider_move" : "") + "'" + (!obj.moveTitle && obj.vertical ? " style='line-height:" + (obj.aheight - obj.inputPadding * 2) + "px;'" : "") + "> </div>";
var left = "<div class='webix_slider_left'> </div>";
var right = "<div class='webix_slider_right'></div>";
var handle = "<div class='webix_slider_handle' " +
/*@attr*/
"webix_disable_drag" + "='true' role='slider' aria-label='" + obj.label + (obj.title ? " " + obj.title(obj) : "") + "' aria-valuemax='" + obj.max + "' aria-valuemin='" + obj.min + "' aria-valuenow='" + obj.value + "' tabindex='0' id='" + id + "'> </div>";
if (obj.vertical) html = "<div class='webix_slider_box'>" + right + left + handle + "</div>" + title;else html = title + "<div class='webix_slider_box'>" + left + right + handle + "</div>";
return common.$renderInput(obj, html, id);
}
},
type_setter: function (type) {
this._viewobj.className += " webix_slider_" + type;
},
title_setter: function (value) {
if (typeof value == "string") return template(value);
return value;
},
_get_slider_handle: function () {
return this.$view.querySelector(".webix_slider_handle");
},
_set_inner_size: function () {
var handle = this._get_slider_handle();
var config = this._settings;
if (handle) {
//view is rendered for sure
var size = config.vertical ? this._content_height : this._get_input_width(config); //width or height
var value = config.value % config.step ? Math.round(config.value / config.step) * config.step : config.value;
var max = config.max - config.min;
value = this._safeValue(value);
value = config.vertical ? max - (value - config.min) : value - config.min; //top or left
var corner1 = Math.ceil((size - 2 * this._sliderPadding) * value / max); //bottom or right
var corner2 = size - 2 * this._sliderPadding - corner1;
var cornerStr = config.vertical ? "top" : "left";
var sizeStr = config.vertical ? "height" : "width";
handle.style[cornerStr] = this._sliderPadding + corner1 - this._sliderHandleWidth / 2 + "px";
handle.parentNode.style[sizeStr] = size + "px"; //1px border
corner2 = this._safeValue(corner2, 2 * this._sliderBorder, size - this._sliderPadding * 2 - 2 * this._sliderBorder);
corner1 = this._safeValue(corner1, 2 * this._sliderBorder, size - this._sliderPadding * 2 - 2 * this._sliderBorder); //width for left/top and right/bottom bars
var part = handle.previousSibling;
part.style[sizeStr] = corner2 + "px";
var last = part.previousSibling;
last.style[sizeStr] = corner1 + "px";
this._set_title(handle, corner1, corner2, cornerStr);
}
},
_set_title: function (handle, corner1, corner2, cornerStr) {
var config = this._settings;
if (this._settings.title) {
var title = handle.parentNode[config.vertical ? "nextSibling" : "previousSibling"];
title.innerHTML = this._settings.title(this._settings, this);
if (this._settings.moveTitle) {
var pos$$1 = 0;
if (config.vertical) pos$$1 = corner1 + 2 * this._sliderBorder - this._sliderHandleWidth / 2;else {
var half = title.clientWidth / 2;
var pos1 = half > corner1 ? half - corner1 - 2 * this._sliderBorder : 0; //left/top text is to large
var pos2 = half > corner2 ? half - corner2 - 2 * this._sliderBorder - this._sliderHandleWidth / 2 : 0; //right/bottom text is too large
pos$$1 = this._sliderPadding + corner1 - half + pos1 - pos2;
}
title.style[cornerStr] = pos$$1 + "px";
}
}
},
_set_value_now: function () {
this._get_slider_handle().setAttribute("aria-valuenow", this._settings.value);
},
_safeValue: function (value, min, max) {
min = min ? min : this._settings.min;
max = max ? max : this._settings.max;
return Math.min(Math.max(value, min), max);
},
refresh: function () {
var handle = this._get_slider_handle();
if (handle) {
this._set_value_now();
if (this._settings.title) handle.setAttribute("aria-label", this._settings.label + " " + this._settings.title(this._settings, this));
this._set_inner_size();
}
},
$setValue: function () {
this.refresh();
},
$getValue: function () {
return this._settings.value;
},
$prepareValue: function (value) {
value = parseFloat(value);
if (isNaN(value)) value = this._settings.min;
return this._safeValue(value);
},
$init: function (config) {
if (env.touch) this.attachEvent("onTouchStart", bind(this._on_mouse_down_start, this));else _event(this._viewobj, "mousedown", bind(this._on_mouse_down_start, this));
_event(this.$view, "keydown", bind(this._handle_move_keyboard, this));
if (config.vertical) {
config.height = config.height || $active.vSliderHeight;
this._viewobj.className += " webix_slider_vertical";
this._sliderPadding = $active.vSliderPadding;
}
},
$skin: function () {
text.api.$skin.call(this);
this._sliderHandleWidth = $active.sliderHandleWidth; //8 - width of handle / 2
this._sliderPadding = $active.sliderPadding; //10 - padding of webix_slider_box ( 20 = 10*2 )
this._sliderBorder = $active.sliderBorder; //1px border
},
_handle_move_keyboard: function (e) {
var code = e.keyCode,
c = this._settings,
value = c.value;
if (code > 32 && code < 41) {
preventEvent(e);
var trg = e.target;
var match = /webix_slider_handle_(\d)/.exec(trg.className);
this._activeIndex = match ? parseInt(match[1], 10) : -1;
if (match) value = c.value[this._activeIndex];
value = value < c.min ? c.min : value > c.max ? c.max : value;
if (code === 36) value = c.min;else if (code === 35) value = c.max;else {
var inc = code === 37 || code === 40 || code === 34 ? -1 : 1;
if (code === 33 || code === 34 || c.step > 1) inc = inc * c.step;
value = value * 1 + inc;
}
if (match) {
var other = c.value[this._activeIndex ? 0 : 1];
value = this._activeIndex && value <= other || !this._activeIndex && value >= other ? other : value;
}
if (value >= c.min && value <= c.max) {
if (match) {
var temp = [];
for (var i = 0; i < c.value.length; i++) {
temp[i] = i === this._activeIndex ? value : c.value[i];
}
value = temp;
}
this.setValue(value, "user");
this._activeIndex = -1;
}
}
},
_on_mouse_down_start: function (e) {
if (this._handle_drag_events) return;
var trg = e.target;
if (this._mouse_down_process) {
this._mouse_down_process(e);
}
var value = this._settings.value;
if (isArray(value)) value = copy(value);
if (trg.className.indexOf("webix_slider_handle") != -1) {
this._start_value = value;
return this._start_handle_dnd.apply(this, arguments);
} else if (trg.className.indexOf("webix_slider") != -1) {
this._start_value = value;
this._settings.value = this._get_value_from_event.apply(this, arguments);
this._start_handle_dnd(e);
}
},
_start_handle_dnd: function () {
if (env.touch) {
this._handle_drag_events = [this.attachEvent("onTouchMove", bind(this._handle_move_process, this)), this.attachEvent("onTouchEnd", bind(this._handle_move_stop, this))];
} else this._handle_drag_events = [event$1(document.body, "mousemove", bind(this._handle_move_process, this)), event$1(window, "mouseup", bind(this._handle_move_stop, this))];
addCss(document.body, "webix_noselect");
},
_handle_move_stop: function () {
//detach event handlers
if (this._handle_drag_events) {
if (env.touch) {
this.detachEvent(this._handle_drag_events[0]);
this.detachEvent(this._handle_drag_events[1]);
} else {
eventRemove(this._handle_drag_events[0]);
eventRemove(this._handle_drag_events[1]);
}
this._handle_drag_events = null;
}
removeCss(document.body, "webix_noselect");
var value = this._settings.value;
if (isArray(value)) value = copy(value);
this._settings.value = this._start_value;
this.setValue(value, "user");
this._get_slider_handle(this._activeIndex).focus();
this._activeIndex = -1;
},
_handle_move_process: function () {
this._settings.value = this._get_value_from_event.apply(this, arguments);
this.refresh();
this.callEvent("onSliderDrag", []);
},
_get_value_from_event: function (event, touchContext) {
// this method takes 2 arguments in case of touch env
var pos$$1 = 0;
var ax = this._settings.vertical ? "y" : "x";
if (env.touch) pos$$1 = touchContext ? touchContext[ax] : event[ax];else pos$$1 = pos(event)[ax];
return this._get_value_from_pos(pos$$1);
},
_get_value_from_pos: function (pos$$1) {
var config = this._settings;
var max = config.max - config.min;
var ax = config.vertical ? "y" : "x"; //top or left depending on slider type
var corner = offset(this._get_slider_handle().parentNode)[ax] + this._sliderPadding; //height or width depending on slider type
var size = (config.vertical ? this._content_height : this._get_input_width(config)) - 2 * this._sliderPadding;
var newvalue = size ? (pos$$1 - corner) * max / size : 0;
if (config.vertical) newvalue = max - newvalue;
newvalue = Math.round((newvalue + 1 * config.min) / config.step) * config.step;
return this._safeValue(newvalue);
},
_init_onchange: function () {} //need not ui.text logic
};
var view$M = exports.protoUI(api$M, text.view);
exports.protoUI({
name: "rangeslider",
defaults: {
template: "GPL version doesn't support rangeslider <br> You need Webix PRO"
}
}, template$1.view);
var api$N = {
name: "switch",
defaults: {
template: function (config, common) {
common._calck_switch_size();
var id = config.name || "x" + uid();
var rightlabel = "";
if (config.labelRight) {
rightlabel = "<label class='webix_label_right'>" + config.labelRight + "</label>";
if (config.labelWidth) config.label = config.label || " ";
}
var checked = config.checkValue == config.value;
var aria = "aria-label=\"" + (config.label || config.labelRight || "") + "\" role=\"checkbox\" tabindex=\"0\" aria-checked=\"" + (checked ? "true" : "false") + "\" " + (config.readonly ? "aria-readonly='true'" : "") + "\"";
var html = "<div class=\"webix_switch_box " + (checked ? " webix_switch_on" : "") + "\" style=\"width:" + common._switchWidth + "px\">" + "<span class=\"webix_switch_text\">" + ((checked ? config.onLabel : config.offLabel) || "") + "</span>" + "<button class=\"webix_switch_handle\" " + aria + " style=\"left:" + (checked ? common._switchWidth - common._switchHeight : 0) + "px;\">" + "<input id=\"" + id + "\" class=\"webix_switch_toggle\" type=\"checkbox\" " + (checked ? "checked" : "") + "></button>" + "</div>" + rightlabel;
return common.$renderInput(config, html, id);
}
},
$skin: function () {
checkbox.api.$skin.call(this);
this._switchHeight = $active.switchHeight;
this._switchWidth = $active.switchWidth;
},
$setValue: function (value) {
var config = this._settings;
var checked = value == config.checkValue;
var box = this.$view.querySelector(".webix_switch_box");
if (box) {
var handle = box.childNodes[1];
var text = (checked ? config.onLabel : config.offLabel) || "";
if (checked) addCss(box, "webix_switch_on");else removeCss(box, "webix_switch_on");
handle.style.left = (checked ? this._switchWidth - this._switchHeight : 0) + "px";
handle.firstChild.checked = checked;
handle.setAttribute("aria-checked", checked ? "true" : "false");
if (text) {
box.childNodes[0].innerHTML = text;
}
}
},
_calck_switch_size: function () {
var config = this._settings;
if (config.onLabel || config.offLabel) {
var onWidth = config.onLabel ? getTextSize(config.onLabel, "webix_switch_text").width : 0;
var offWidth = config.onLabel ? getTextSize(config.offLabel, "webix_switch_text").width : 0;
this._switchWidth = Math.max(onWidth, offWidth) + this._switchHeight;
}
},
on_click: {
"webix_switch_box": function () {
if (!this._settings.readonly) this.toggle("user");
},
"webix_label_right": function () {
if (!this._settings.readonly) this.toggle("user");
}
}
};
var view$N = exports.protoUI(api$N, checkbox.view);
var api$O = {
name: "tabbar",
$init: function () {
this.attachEvent("onKeyPress", this._onKeyPress);
},
$skin: function () {
var skin = $active;
var defaults = this.defaults;
defaults.topOffset = skin.tabTopOffset || 0;
defaults.tabOffset = typeof skin.tabOffset != "undefined" ? skin.tabOffset : 10;
defaults.bottomOffset = skin.tabBottomOffset || 0;
defaults.height = skin.tabbarHeight;
defaults.tabMargin = skin.tabMargin;
defaults.inputPadding = skin.inputPadding;
defaults.tabMinWidth = skin.tabMinWidth || 100;
defaults.tabMoreWidth = skin.tabMoreWidth || 40;
defaults.borderless = !skin.tabBorder;
},
_getTabbarSizes: function () {
var config = this._settings,
i,
len,
tabs = this._filterOptions(config.options),
totalWidth = this._input_width - config.tabOffset * 2,
limitWidth = config.optionWidth || config.tabMinWidth;
len = tabs.length;
if (config.tabMinWidth && totalWidth / len < limitWidth) {
return {
max: parseInt(totalWidth / limitWidth, 10) || 1
};
}
if (!config.optionWidth) {
for (i = 0; i < len; i++) {
if (tabs[i].width) {
totalWidth -= tabs[i].width + (!i && !config.type ? config.tabMargin : 0);
len--;
}
}
}
return {
width: len ? totalWidth / len : config.tabMinWidth
};
},
_init_popup: function () {
var _this = this;
var obj = this._settings; // if tabbar popup is set as plain object with config
if (!obj.tabbarPopup || !$$(obj.tabbarPopup)) {
var popupConfig = exports.extend({
view: "popup",
autofocus: false,
width: 200
}, obj.tabbarPopup || {});
var body = exports.extend({
view: "list",
borderless: true,
select: true,
autoheight: true,
yCount: 7,
template: template("#value#")
}, obj.tabbarPopup ? obj.tabbarPopup.body || {} : {}, true);
body.css = "webix_tab_list ".concat(body.css || "");
popupConfig.body = body;
var _view = ui(popupConfig);
var list = _view.getBody();
_view.attachEvent("onShow", function () {
list.unselect();
UIManager.setFocus(list);
var node = list.getItemNode(list.getFirstId());
if (node) node.focus();
});
list.attachEvent("onItemClick", function (id) {
return _this._popupInnerClick(id);
});
list.attachEvent("onEnter", function () {
return _this._popupInnerClick();
});
obj.tabbarPopup = _view._settings.id;
this._destroy_with_me.push(_view);
}
this._init_popup = function () {};
},
_popupInnerClick: function (id) {
var popup = $$(this._settings.tabbarPopup);
id = id || popup.getBody().getSelectedId();
if (id && this.callEvent("onBeforeTabClick", [id])) {
this.setValue(id, "user");
popup.hide();
this.callEvent("onAfterTabClick", [id]);
this.refresh();
this.focus();
}
return false;
},
getPopup: function () {
this._init_popup();
return $$(this._settings.tabbarPopup);
},
moreTemplate_setter: template,
defaults: {
moreTemplate: "<span class=\"webix_icon wxi-dots\"></span>",
template: function (obj, common) {
common._check_options(obj.options);
var tabs = common._filterOptions(obj.options);
var contentWidth, html, leafWidth, resultHTML, style, sum, verticalOffset, width;
if (!tabs.length) {
html = "<div class='webix_tab_filler' style='width:" + common._input_width + "px; border-right:0px;'></div>";
} else {
if (!obj.value) obj.value = common._getFirstActive(true);
html = "";
if (obj.tabOffset) html += "<div class='webix_tab_filler' style='width:" + obj.tabOffset + "px;'> </div>";
contentWidth = common._input_width - obj.tabOffset * 2 - (!obj.type ? obj.tabMargin * (tabs.length - 1) : 0);
verticalOffset = obj.topOffset + obj.bottomOffset;
var sizes = common._getTabbarSizes();
if (sizes.max && sizes.max < tabs.length) {
//we need popup
var popup = common.getPopup();
popup.hide();
var body = popup.getBody() || null;
if (body) {
if (sizes.max) {
for (var i = 0, found = false; i < tabs.length && !found; i++) {
if (tabs[i].id == obj.value) {
found = true;
if (i + 1 > sizes.max) {
var selectedTab = tabs.splice(i, 1);
var displayTabs = tabs.splice(0, sizes.max - 1).concat(selectedTab);
tabs = displayTabs.concat(tabs);
}
}
}
body.clearAll();
body.parse(tabs.slice(sizes.max));
} else {
body.clearAll();
}
}
} else if (common._settings.tabbarPopup) {
var _popup = $$(common._settings.tabbarPopup);
if (_popup) _popup.hide();
}
sum = obj.tabOffset;
for (var _i = 0, lastTab = false; _i < tabs.length && !lastTab; _i++) {
// tab width
if (sizes && sizes.max) {
if (sizes.max == _i + 1) {
lastTab = true;
}
contentWidth = common._input_width - obj.tabOffset * 2 - (!obj.type && sizes.max > 1 ? obj.tabMargin * (sizes.max - 1) : 0);
width = (contentWidth - obj.tabMoreWidth) / sizes.max;
} else width = sizes.width;
width = tabs[_i].width || obj.optionWidth || width;
sum += width + (_i && !obj.type ? obj.tabMargin : 0);
if (obj.tabMargin > 0 && _i && !obj.type) html += "<div class='webix_tab_filler' style='width:" + obj.tabMargin + "px;'></div>"; // tab innerHTML
html += common._getTabHTML(tabs[_i], width);
if (lastTab) {
html += "<div role=\"button\" tabindex=\"0\" aria-label=\"" + i18n.aria.showTabs + "\" class=\"webix_tab_more_icon\" style=\"width:" + obj.tabMoreWidth + "px;\">" + obj.moreTemplate(obj, common) + "</div>";
sum += obj.tabMoreWidth;
}
}
leafWidth = common._content_width - sum;
if (leafWidth > 0 && !obj.type) html += "<div class='webix_tab_filler' style='width:" + leafWidth + "px;'> </div>";
}
resultHTML = ""; // consider top and bottom offset in tabs height (top tabbar)
style = verticalOffset && !obj.type ? "height:" + (common._content_height - verticalOffset) + "px" : ""; //space above tabs (top tabbar)
if (obj.topOffset && !obj.type) resultHTML += "<div class='webix_before_all_tabs' style='width:100%;height:" + obj.topOffset + "px'></div>"; // tabs html
resultHTML += "<div style='" + style + "' role='tablist' class='webix_all_tabs " + (obj.type ? "webixtype_" + obj.type : "") + "'>" + html + "</div>"; //space below to tabs (top tabbar)
if (obj.bottomOffset && !obj.type) resultHTML += "<div class='webix_after_all_tabs' style='width:100%;height:" + obj.bottomOffset + "px'></div>";
return resultHTML;
}
},
_getInputNode: function () {
return this.$view.querySelectorAll(".webix_item_tab");
},
_getTabHTML: function (tab, width) {
var html,
className = "",
tooltip = "",
isDisabled = !!tab.disabled,
config = this.config;
if (tab.id == config.value) className += " webix_selected";
if (isDisabled) className += " webix_disabled";
if (tab.css) className += " " + tab.css;
if (config.tooltip) tooltip = " webix_t_id='" + tab.id + "'";
width = tab.width || width;
html = "<div class=\"webix_item_tab" + className + "\" " +
/*@attr*/
"button_id=\"" + tab.id + "\" role=\"tab\" " + "aria-selected=\"" + (tab.id == config.value ? "true" : "false") + "\" tabindex=\"" + (!isDisabled && tab.id == config.value ? "0" : "-1") + "\" style=\"width:" + width + "px;\"" + (isDisabled ? " webix_disabled=\"true\"" : "") + tooltip + ">"; // a tab title
if (this._tabTemplate) {
var calcHeight = this._content_height - config.inputPadding * 2 - 2;
var height = this._content_height - 2;
var temp = exports.extend({
cheight: calcHeight,
aheight: height
}, tab);
html += this._tabTemplate(temp);
} else {
var icon = tab.icon ? "<span class='webix_icon " + tab.icon + "'></span> " : "";
html += icon + tab.value;
}
if (!isDisabled && (tab.close || config.close)) html += "<span role='button' tabindex='0' aria-label='" + i18n.aria.closeTab + "' class='webix_tab_close webix_icon wxi-close'></span>";
html += "</div>";
return html;
},
_getBox: function () {
return this._dataobj.firstChild;
},
_types: {
image: "<div class='webix_img_btn_top' style='height:#cheight#px;background-image:url(#image#);'><div class='webix_img_btn_text'>#value#</div></div>",
icon: "<div class='webix_img_btn' style='line-height:#cheight#px;height:#cheight#px;'><span class='webix_icon_btn #icon#' style='max-width:#cheight#px;max-height:#cheight#px;'></span>#value#</div>",
iconTop: "<div class='webix_img_btn_top' style='height:#cheight#px;width:100%;top:0px;text-align:center;'><span class='webix_icon #icon#'></span><div class='webix_img_btn_text'>#value#</div></div>"
},
type_setter: function (value) {
this._settings.tabOffset = 0;
if (this._types[value]) this._tabTemplate = template(this._types[value]);
return value;
}
};
var view$O = exports.protoUI(api$O, segmented.view);
var api$P = {
name: "richtext",
defaults: {
label: "",
labelWidth: 80,
labelPosition: "left"
},
$init: function () {
this._viewobj.className += " webix_richtext";
this.$ready.unshift(this._setLayout);
},
$skin: function () {
layout.api.$skin.call(this);
this.defaults.paddingX = $active.inputSpacing / 2;
this.defaults.paddingY = $active.inputPadding;
},
getInputNode: function () {
return this.$view.querySelector(".webix_richtext_editor");
},
_button: function (name) {
return {
view: "toggle",
type: "icon",
icon: "wxi-" + name,
name: name,
id: name,
label: i18n.richtext[name],
autowidth: true,
action: name,
click: this._add_data
};
},
_setLayout: function () {
var top = this;
var editField = {
view: "template",
css: "webix_richtext_container",
borderless: true,
template: "<div class='webix_richtext_editor' contenteditable='true'>" + this.getValue() + "</div>",
on: {
onAfterRender: function () {
top._rendered_input = true;
top.refresh();
_event(top.getInputNode(), "blur", function () {
top._updateValue(this.innerHTML, "user");
});
_event(top.getInputNode(), "keyup", function () {
top._getselection("auto");
});
}
},
onClick: {
webix_richtext_editor: function () {
top._getselection("auto");
}
}
};
var controls = [this._button("underline"), this._button("bold"), this._button("italic"), {}];
var editorToolbar = {
view: "toolbar",
id: "toolbar",
elements: controls
};
var rows = [editorToolbar, editField];
var config = this.config;
if (config.labelPosition == "top") {
editorToolbar.elements = controls.concat([{
view: "label",
label: config.label,
align: "right"
}, {
width: 4
}]);
this.rows_setter(rows);
} else {
config.labelWidth = config.label ? this._getLabelWidth(config.labelWidth, config.label) : 0;
if (config.labelWidth) {
config.margin = 0;
this.cols_setter([{
template: config.label,
css: "webix_richtext_inp_label" + (config.required ? " webix_required" : ""),
borderless: true,
width: config.labelWidth
}, {
rows: rows
}]);
} else this.rows_setter(rows);
}
},
_getLabelWidth: function (width, label) {
if (width == "auto") width = getTextSize(label, "webix_inp_label").width;
return width ? Math.max(width, $active.dataPadding) : 0;
},
_getselection: function (config) {
var top = this;
var bar = top.$$("toolbar");
var sel;
bar.setValues({
italic: false,
underline: false,
bold: false
}, false, config);
if (window.getSelection) {
sel = window.getSelection();
} else {
sel = document.selection.createRange();
}
for (var i = 0; i < sel.rangeCount; ++i) {
if (top.$view.contains(this.getInputNode())) {
if (document.queryCommandState("bold")) {
top.$$("bold").setValue(true, config);
}
if (document.queryCommandState("underline")) {
top.$$("underline").setValue(true, config);
}
if (document.queryCommandState("italic")) {
top.$$("italic").setValue(true, config);
}
}
}
},
refresh: function () {
if (this._rendered_input) this.getInputNode().innerHTML = this._settings.value;
},
_execCommandOnElement: function (commandName) {
var sel, selText;
if (window.getSelection) {
sel = window.getSelection();
selText = sel.toString().length;
var input = this.getInputNode();
if (!input.contains(sel.anchorNode) || !input.contains(sel.focusNode)) return;
} else return; //ie8
if (selText > 0) {
for (var i = 0; i < sel.rangeCount; ++i) {
var range = sel.getRangeAt(i);
if (!sel.isCollapsed) {
document.execCommand(commandName, false, "");
} else {
var textValue = sel.focusNode.textContent;
var focusEl = sel.focusNode;
var focustext = sel.anchorOffset;
var wordBegining = textValue.substring(0, focustext).match(/[A-Za-z]*$/)[0];
var wordEnd = textValue.substring(focustext).match(/^[A-Za-z]*/)[0];
var startWord = focustext - wordBegining.length;
var endWord = focustext + wordEnd.length;
range.setStart(focusEl, startWord);
range.setEnd(focusEl, endWord);
sel.removeAllRanges();
sel.addRange(range);
document.execCommand(commandName, false, "");
}
}
}
},
_add_data: function () {
var top = this.getTopParentView();
top._execCommandOnElement(this.config.action);
},
focus: function () {
if (!UIManager.canFocus(this)) return false;
var editableElement = this.getInputNode();
editableElement.focus();
},
_updateValue: function (value, config) {
value = this.$prepareValue(value);
var oldvalue = this._settings.value;
if (oldvalue != value) {
this._settings.value = value;
this.callEvent("onChange", [value, oldvalue, config]);
}
},
setValue: function (value, config) {
this._updateValue(value, config);
this.refresh();
},
$prepareValue: function (value) {
return value === 0 ? "0" : (value || "").toString();
},
value_setter: function (value) {
return this.$prepareValue(value);
},
getValue: function () {
var input = this.getInputNode();
if (input) return input.innerHTML;
return this._settings.value;
}
};
var view$P = exports.protoUI(api$P, IdSpace, layout.view);
var api$Q = {
name: "proto",
$init: function () {
this.data.provideApi(this, true);
this._dataobj = this._dataobj || this._contentobj; //render self , each time when data is updated
this.data.attachEvent("onStoreUpdated", bind(function () {
this.render.apply(this, arguments);
}, this));
},
$setSize: function () {
if (base$1.api.$setSize.apply(this, arguments)) this.render();
},
_id:
/*@attr*/
"webix_item",
on_mouse_move: {},
type: {}
};
var view$Q = exports.protoUI(api$Q, PagingAbility, DataMarks, AutoTooltip, ValidateCollection, RenderStack, DataLoader, base$1.view, EventSystem, Settings);
var proto = {
api: api$Q,
view: view$Q
};
var api$R = {
name: "list",
_listClassName: "webix_list",
_itemClassName: "webix_list_item",
$init: function (config) {
addCss(this._viewobj, this._listClassName + ((config.layout || this.defaults.layout) == "x" ? "-x" : ""));
this.data.provideApi(this, true);
this._auto_resize = bind(this._auto_resize, this);
this.data.attachEvent("onStoreUpdated", this._auto_resize);
this.data.attachEvent("onSyncApply", this._auto_resize);
this._viewobj.setAttribute("role", "listbox");
},
dynamic_setter: function (value) {
if (value) exports.extend(this, VRenderStack, true);
return value;
},
$dragHTML: function (obj, e, context) {
var html;
if (this._settings.layout == "y" && this.type.width == "auto") {
this.type.width = this._content_width;
html = this._toHTML(obj);
this.type.width = "auto";
} else html = this._toHTML(obj);
if (isArray(context.source) && context.source.length > 1) html = this._toMultipleHTML(html, context.source.length);
return html;
},
defaults: {
select: false,
scroll: true,
layout: "y",
navigation: true,
datafetch: 50
},
_id:
/*@attr*/
"webix_l_id",
on_click: {
webix_list_item: function (e, id) {
if (this._settings.select) {
this._no_animation = true;
if (this._settings.select == "multiselect" || this._settings.multiselect) this.select(id, false, e.ctrlKey || e.metaKey || this._settings.multiselect == "touch", e.shiftKey); //multiselection
else this.select(id);
this._no_animation = false;
}
}
},
on_dblclick: {},
getVisibleCount: function () {
return Math.floor(this._content_height / this._one_height());
},
_auto_resize: function () {
var c = this._settings;
if (c.autoheight || c.autowidth) return this.resize();
if (c.layout == "y") {
if (c.yCount) this._auto_height_calc(c.yCount);
} else {
if (c.xCount) this._auto_width_calc(c.xCount);
}
},
_auto_height_calc: function (count) {
var value = this.data.$pagesize || this.count();
this._onoff_scroll(count && count < value, "y");
if (this._settings.autoheight && value < (count || Infinity)) count = value;
var height = this._one_height() * count + (this.type.margin || 0); //unitlist
if (this.getUnits) height += this.getUnits().length * this.type.headerHeight;
return Math.max(height, this._settings.minHeight || 0);
},
_one_height: function () {
return this.type.height + (this.type.margin || 0);
},
_auto_width_calc: function (count) {
var value = this.data.$pagesize || this.count();
this._onoff_scroll(count && count < value, "x");
if (this._settings.autowidth && value < (count || Infinity)) count = value;
return this.type.width * count;
},
$getSize: function (dx, dy) {
if (this._settings.layout == "y") {
if (this.type.width != "auto") this._settings.width = this.type.width + (this._scroll_y ? env.scrollSize : 0);
if (this._settings.yCount || this._settings.autoheight) this._settings.height = this._auto_height_calc(this._settings.yCount) || 1;
} else {
if (this.type.height != "auto") this._settings.height = this._one_height() + (this._scroll_x ? env.scrollSize : 0);
if (this._settings.xCount || this._settings.autowidth) this._settings.width = this._auto_width_calc(this._settings.xCount) || 1;
}
return base$1.api.$getSize.call(this, dx, dy);
},
$setSize: function () {
base$1.api.$setSize.apply(this, arguments);
},
type: {
css: "",
widthSize: function (obj, common) {
return common.width + (common.width > -1 ? "px" : "");
},
heightSize: function (obj, common) {
return common.height + (common.height > -1 ? "px" : "");
},
classname: function (obj, common, marks) {
var css = "webix_list_item";
if (common.css) css += " " + common.css;
if (obj.disabled) css += " webix_disabled";
if (obj.$css) {
if (_typeof(obj.$css) == "object") obj.$css = createCss(obj.$css);
css += " " + obj.$css;
}
if (marks && marks.$css) css += " " + marks.$css;
return css;
},
aria: function (obj, common, marks) {
return "role=\"option\"" + (marks && marks.webix_selected ? " aria-selected=\"true\" tabindex=\"0\"" : " tabindex=\"-1\"") + (obj.$count && obj.$template ? "aria-expanded=\"true\"" : "") + (obj.disabled ? " aria-disabled=\"true\" webix_disabled=\"true\"" : "");
},
template: function (obj) {
return (obj.icon ? "<span class='webix_list_icon webix_icon " + obj.icon + "'></span>" : "") + obj.value + (obj.badge || obj.badge === 0 ? "<div class='webix_badge'>" + obj.badge + "</div>" : "");
},
width: "auto",
templateStart: template("<div " +
/*@attr*/
"webix_l_id" + "=\"#id#\" class=\"{common.classname()}\" style=\"width:{common.widthSize()}; height:{common.heightSize()}; overflow:hidden;\" {common.aria()}>"),
templateEnd: template("</div>")
},
$skin: function () {
this.type.height = $active.listItemHeight;
},
disableItem: function (id) {
this._set_item_disabled(id, true);
},
enableItem: function (id) {
this._set_item_disabled(id, false);
},
_set_item_disabled: function (id, state) {
var item = this.getItem(id);
if (item) {
item.disabled = state;
this.refresh(id);
}
},
isItemEnabled: function (id) {
var item = this.getItem(id);
return item && !item.disabled;
},
_skip_item: function (id, prev, dir) {
if (!this.isItemEnabled(id)) {
id = this.getNextId(id, dir) || null;
return id && id != prev ? this._skip_item(id, prev, dir) : prev;
}
return id;
}
};
var view$R = exports.protoUI(api$R, CustomPrint, KeysNavigation, DataMove, DragItem, MouseEvents, SelectionModel, Scrollable, proto.view, CopyPaste);
var list = {
api: api$R,
view: view$R
};
/*
UI:Uploader
*/
// #include ui/view.js
// #include ui/list.js
type(list.view, {
name: "uploader",
template: "{common.removeIcon()}{common.percent()}<div style='float:right'>#sizetext#</div>{common.fileName()}",
percent: function (obj) {
if (obj.status == "transfer") return "<div style='width:60px; text-align:center; float:right'>" + obj.percent + "%</div>";
return "<div class='webix_upload_" + obj.status + "'><span class='" + (obj.status == "error" ? "error_icon" : "webix_icon wxi-check") + "'></span></div>";
},
removeIcon: function () {
return "<div class='webix_remove_upload'><span class='cancel_icon'></span></div>";
},
fileName: function (obj) {
return "<div style='text-overflow:ellipsis; white-space:nowrap; overflow:hidden; padding-right:8px;'>" + obj.name + "</div>";
},
on_click: {
"webix_remove_upload": function (ev, id) {
$$(this.config.uploader).files.remove(id);
}
}
});
var api$S = {
name: "uploader",
defaults: {
autosend: true,
multiple: true,
inputName: "upload"
},
$cssName: "button webix_uploader",
$allowsClear: true,
on_click: {
//don't fire extra onItemClick events, visible button will do it
"webix_hidden_upload": function () {
return false;
}
},
//will be redefined by upload driver
send: function () {},
fileDialog: function () {},
stopUpload: function () {},
$skin: function () {
button$1.api.$skin.call(this);
if ($name == "material" || $name == "mini") this.defaults.css = "webix_primary";
},
$init: function () {
this.files = new DataCollection();
this._destroy_with_me = [this.files];
exports.extend(this, UploadDriver, true);
},
$setSize: function (x, y) {
if (base$1.api.$setSize.call(this, x, y)) {
this.render();
}
},
apiOnly_setter: function (value) {
delay(this.render, this);
return this.$apiOnly = value;
},
_add_files: function (files) {
for (var i = 0; i < files.length; i++) {
this.addFile(files[i]);
}
},
link_setter: function (value) {
if (value) delay(function () {
var view = $$(this._settings.link);
if (!view) {
var top = this.getTopParentView();
if (top.$$) view = top.$$(this._settings.link);
}
if (view.sync && view.filter) view.sync(this.files);else if (view.setValues) this.files.data.attachEvent("onStoreUpdated", function () {
view.setValues(this, false, "auto");
});
view._settings.uploader = this._settings.id;
}, this);
return value;
},
addFile: function (name, size, type$$1, extra) {
var file = null;
if (_typeof(name) == "object") {
file = name;
name = file.name;
size = file.size;
}
var format = this._format_size(size);
type$$1 = type$$1 || name.split(".").pop();
var file_struct = {
file: file,
name: name,
id: uid(),
size: size,
sizetext: format,
type: type$$1,
context: this._last_file_context,
status: "client"
};
if (file && file.webkitRelativePath) file_struct.name = file.webkitRelativePath;
if (extra) exports.extend(file_struct, extra, true);
if (this.callEvent("onBeforeFileAdd", [file_struct])) {
if (!this._settings.multiple) this.files.clearAll();
var id = this.files.add(file_struct);
this.callEvent("onAfterFileAdd", [file_struct]);
if (id && this._settings.autosend) this.send(id);
}
return file_struct;
},
_get_active_url: function (item) {
var url = this._settings.upload;
var urldata = exports.extend(item.urlData || {}, this._settings.urlData || {});
if (url && urldata) {
var subline = [];
for (var key in urldata) {
subline.push(encodeURIComponent(key) + "=" + encodeURIComponent(urldata[key]));
}
if (subline.length) url += (url.indexOf("?") == -1 ? "?" : "&") + subline.join("&");
}
return url;
},
addDropZone: function (id, hover_text) {
var node = toNode(id);
var extra_css = "";
if (hover_text) extra_css = " " + createCss({
content: "\"" + hover_text + "\""
}, ":before");
var fullcss = "webix_drop_file" + extra_css;
var timer = null; //web
_event(node, "dragover", preventEvent);
_event(node, "dragover", function () {
addCss(node, fullcss, true);
if (timer) {
clearTimeout(timer);
timer = null;
}
});
_event(node, "dragleave", function () {
//when moving over html child elements
//browser will issue dragleave and dragover events
//ignore first one
timer = setTimeout(function () {
removeCss(node, fullcss);
}, 150);
});
_event(node, "drop", bind(function (e) {
removeCss(node, fullcss);
this.$drop(e);
return preventEvent(e);
}, this));
},
_format_size: function (size) {
var index$$1 = 0;
while (size > 1024) {
index$$1++;
size = size / 1024;
}
return Math.round(size * 100) / 100 + " " + i18n.fileSize[index$$1];
},
_complete: function (id, response) {
var item = this.files.getItem(id);
exports.extend(item, response, true);
item.status = "server";
item.progress = 100;
this.callEvent("onFileUpload", [item, response]);
this.callEvent("onChange", []);
this.files.updateItem(id);
if (this.isUploaded()) this._upload_complete(response);
},
_upload_complete: function (response) {
this.callEvent("onUploadComplete", [response]);
if (this._last_assigned_upload_callback) {
this._last_assigned_upload_callback.call(this, response);
this._last_assigned_upload_callback = 0;
}
},
isUploaded: function () {
var order = this.files.data.order;
for (var i = 0; i < order.length; i++) {
if (this.files.getItem(order[i]).status != "server") return false;
}
return true;
},
$onUploadComplete: function () {},
$updateProgress: function (id, percent) {
var item = this.files.getItem(id);
item.percent = Math.round(percent);
this.files.updateItem(id);
},
setValue: function (value) {
if (typeof value == "string" && value) value = {
value: value,
status: "server"
};
this.files.clearAll();
if (value) this.files.parse(value);
this.callEvent("onChange", []);
},
getValue: function () {
var data = [];
this.files.data.each(function (obj) {
if (obj.status == "server") data.push(obj.value || obj.name);
});
return data.join(",");
}
};
var view$S = exports.protoUI(api$S, button$1.view);
var api$T = {
name: "texthighlight",
defaults: {
template: function (obj, common) {
var name = obj.name || obj.id;
var id = "x" + uid();
var width = common._get_input_width(obj);
var html = "<div class=\"webix_text_highlight\" style=\"width:".concat(width, "px;\"><div class=\"webix_text_highlight_value\""); // iOS adds 3px of (unremovable) padding to the left and right of a textarea
if (obj.type == "textarea" && env.mobile && env.isSafari) html += " style=\"margin-left:".concat($active.dataPadding + 3, "px; margin-right:").concat($active.dataPadding + 3, "px;\"");
html += "></div></div>";
if (obj.type == "textarea") {
html += "".concat(common._baseInputHTML("textarea"), " style=\"width:").concat(width, "px;\" id=\"").concat(id, "\" name=\"").concat(name, "\" class=\"webix_inp_textarea\">").concat(common._pattern(obj.value), "</textarea>");
return common.$renderInput(obj, html, id);
} else return html + common.$renderInput(obj);
},
highlight: function (text$$1) {
return template.escape(text$$1);
},
type: "text"
},
$init: function (config) {
var _this = this;
var type = config.type || this.defaults.type;
this._viewobj.className += " webix_el_" + type;
if (type == "textarea") {
delete config.clear;
config.height = config.height || 0;
config.minHeight = config.minHeight || 60;
this._skipSubmit = true;
} else {
//input hasn't scroll event
this.scrollEv = event$1(document, "selectionchange", function () {
if (_this.$view.contains(document.getSelection().focusNode)) _this._syncText();
});
this.attachEvent("onDestruct", function () {
eventRemove(_this.scrollEv);
});
} //setValue
this.attachEvent("onChange", function () {
return _this._syncText();
});
this.attachEvent("onAfterRender", function () {
_this._updatePos();
var evs = ["scroll", "focus", "blur", "paste", "cut", "keyup", "input"];
evs.forEach(function (ev) {
return _event(_this.getInputNode(), ev, function () {
return _this._syncText();
});
});
_this._handleInput(true);
});
},
$setSize: function () {
text.api.$setSize.apply(this, arguments);
this._updatePos();
},
$renderIcon: function (c) {
if (c.type == "text") return text.api.$renderIcon.apply(this, arguments);
return "";
},
_getLabelHeight: function (top) {
if (this._settings.type == "textarea") return top ? this._labelTopHeight - this._settings.inputPadding : "";
return text.api._getLabelHeight.apply(this, arguments);
},
getInputNode: function () {
return this._dataobj.querySelector(this._settings.type == "text" ? "input" : "textarea");
},
_getHighlightNode: function () {
return this._dataobj.querySelector(".webix_text_highlight");
},
_handleInput: function (init) {
var highlight = this._getHighlightNode().firstElementChild;
var text$$1 = this.getValue();
if (init || text$$1 != (this._lastText || "")) {
this._lastText = text$$1; //add at the end because div ignores last empty line + it gives better positioning
highlight.innerHTML = this._settings.highlight.apply(this, [text$$1]) + " ";
}
},
_handleScroll: function () {
var highlight = this._getHighlightNode();
if (this._settings.type == "text") highlight = highlight.firstElementChild;
var text$$1 = this.getInputNode();
highlight.scrollTop = text$$1.scrollTop;
highlight.scrollLeft = text$$1.scrollLeft;
},
_updatePos: function () {
if (this._rendered_input && this.isVisible()) {
var input = this.getInputNode();
var highlightStyles = this._getHighlightNode().style;
highlightStyles.left = input.offsetLeft + "px";
highlightStyles.top = input.offsetTop + "px";
highlightStyles.height = input.getBoundingClientRect().height + "px";
}
},
_syncText: function () {
delay(function () {
if (this.$destructed) return;
this._handleInput();
this._handleScroll();
}, this);
}
};
var view$T = exports.protoUI(api$T, text.view);
var api$U = {
name: "timeboard",
defaults: {
width: 260,
hours: true,
seconds: false,
twelve: /%([a,A])/.test(i18n.timeFormat)
},
$skin: function () {
layout.api.$skin.call(this);
this.defaults.margin = $active.layoutMargin.form;
this.defaults.padding = $active.layoutPadding.space;
},
$init: function (config) {
var _this = this;
this.$view.className += " webix_timeboard";
var rows = [];
var twelve = !isUndefined(config.twelve) ? config.twelve : this.defaults.twelve;
var hours = !isUndefined(config.hours) ? config.hours : this.defaults.hours;
var seconds = config.seconds || this.defaults.seconds;
if (isUndefined(config.height)) {
var nrows = 1 + hours * 1 + 1 + seconds * 1 + !!config.button * 1;
config.height = $active.inputHeight * nrows + (config.margin || this.defaults.margin) * (nrows - 1) + (config.padding || this.defaults.padding) * 2;
}
rows.push(this._getClock(hours, seconds, twelve));
rows.push.apply(rows, _toConsumableArray(this._getSliders(hours, seconds, twelve)));
if (config.button) rows.push(this._getDoneButton());
config.rows = [{
view: "form",
elements: rows,
padding: 0,
borderless: true,
on: {
onChange: function (v, o, c) {
return _this._recollectValues(c);
}
}
}];
this.$ready.push(function () {
this._form = this.queryView("form");
var value = this._settings.value;
if (value) this.setValue(value, "auto");
});
},
// accepts strings and Dates
setValue: function (value, config) {
value = this.$prepareValue(value);
var oldvalue = this._settings.value;
if (!wDate.equal(value, oldvalue)) {
this._settings.value = value;
this.$setValue(value);
this.callEvent("onChange", [value, oldvalue, config]);
}
},
$prepareValue: function (value) {
if (typeof value === "string") value = i18n.parseTimeFormatDate(value);
return value || wDate.datePart(new Date());
},
$setValue: function (value) {
var obj = {};
obj.minutes = obj.sminutes = value.getMinutes();
if (this._settings.hours) obj.shours = obj.hours = value.getHours();
if (this._settings.seconds) obj.sseconds = obj.seconds = value.getSeconds();
if (this._settings.twelve) {
if (!isUndefined(obj.hours)) {
obj.day_part = obj.hours > 11 ? i18n.pm[1] : i18n.am[1];
obj.hours = !obj.hours || obj.hours == 12 ? 12 : obj.hours % 12;
obj.shours = obj.hours == 12 ? 0 : obj.hours;
}
}
this._form.setValues(obj, false, "auto");
},
_recollectValues: function (config) {
var values = this.$getValue();
var date = this._settings.value ? wDate.copy(this._settings.value) : new Date();
date.setHours(values.hours || 0);
date.setMinutes(values.minutes);
if (this._settings.seconds) date.setSeconds(values.seconds);
this.setValue(date, config);
},
$getValue: function () {
var values = this._form.getValues();
if (this._settings.twelve && this._settings.hours) {
if (values.day_part == i18n.pm[1] && values.hours < 12) values.hours = (values.hours * 1 + 12).toString();else if (values.day_part == i18n.am[1] && values.hours == 12) values.hours = 0;
}
return values;
},
getValue: function () {
if (this._settings.stringResult) {
var values = this.$getValue();
var res = [];
if (values.hours) res.push(values.hours);
if (values.minutes) res.push(values.minutes);
if (values.seconds) res.push(values.seconds);
return res.join(":");
} else return this._settings.value;
},
_getClock: function (hours, seconds, twelve) {
var inputs = [{}, this._getText("minutes"), {}];
var separator = {
css: "webix_colon_template",
template: ":",
borderless: true,
width: 16
};
if (hours) inputs.splice(1, 0, this._getText("hours", twelve), copy(separator));
if (seconds) inputs.splice(-1, 0, copy(separator), this._getText("seconds"));
if (twelve && hours) {
var am = i18n.am[1];
var pm = i18n.pm[1];
var control = {
view: "label",
name: "day_part",
css: "webix_day_part",
template: "<div tabindex='0' role='button' class='webix_el_box' style='width:#awidth#px;height:#aheight#px;line-height:#cheight#px'>#label#</div>",
inputWidth: 30,
on: {
onItemClick: function () {
this.setValue(this.getValue() == am ? pm : am, "user");
},
onKeyPress: function (code, e) {
this._onKeyPress(code, e);
}
}
};
inputs.splice(-1, 1, control);
}
return {
type: "clean",
cols: inputs
};
},
_getText: function (name, twelve) {
var _this2 = this;
var max = name === "hours" ? twelve ? 11 : 23 : 59;
return {
view: "text",
width: getTextSize("00").width + 2 * $active.dataPadding + 2 * $active.inputPadding,
name: name,
format: {
parse: function (a) {
if (a == 12 && name === "hours" && twelve) a = "00";
return a.length > 1 ? a.replace(/^0/, "") : a || 0;
},
edit: function (a) {
if (a <= 0 && name === "hours" && twelve) a = 12;else if (a < 0) a = 0;else if (a > max) a = max;
return (a + "").length === 1 ? "0" + a : a + "" || "00";
}
},
on: {
onChange: function (nv) {
var v = (twelve && name === "hours" && (!nv || nv == 12) ? 0 : nv) * 1;
_this2._form.elements["s" + name].setValue(v, "auto");
}
}
};
},
_getSliders: function (hours, seconds, twelve) {
var sliders = [this._getSlider("minutes", i18n.calendar.minutes, 59)];
if (hours) {
sliders.unshift(this._getSlider("hours", i18n.calendar.hours, twelve ? 11 : 23));
}
if (seconds) sliders.push(this._getSlider("seconds", i18n.timeboard.seconds, 59, twelve));
return sliders;
},
_getSlider: function (name, title, max, twelve) {
var _this3 = this;
var enLocale = name === "hours" && twelve;
var config = {
view: "slider",
name: "s" + name,
title: title,
moveTitle: false,
min: 0,
max: max,
on: {
onChange: function (nv) {
_this3._form.elements[name].setValue((enLocale ? !nv || nv == 12 ? 12 : nv % 12 : nv) + "", "auto");
},
onSliderDrag: function () {
var nv = this.getValue();
var form = this.getFormView();
form.blockEvent();
form.elements[name].setValue((enLocale ? !nv || nv == 12 ? 12 : nv % 12 : nv) + "", "auto");
form.unblockEvent();
}
}
};
return config;
},
_getDoneButton: function () {
var _this4 = this;
return {
view: "button",
value: i18n.calendar.done,
css: "webix_primary",
click: function () {
_this4.callEvent("onTimeSelect", [_this4._settings.value]);
}
};
}
};
var view$U = exports.protoUI(api$U, layout.view);
var api$V = {
name: "suggest",
defaults: {
autofocus: false,
type: "list",
keyPressTimeout: 1,
body: {
yCount: 10,
autoheight: true,
body: true,
select: true,
borderless: true,
navigation: true
},
filter: function (item, value) {
if (item.value.toString().toLowerCase().indexOf(value.toLowerCase()) === 0) return true;
return false;
}
},
template_setter: template,
filter_setter: function (value) {
return toFunctor(value, this.$scope);
},
_show_on_key_press: true,
$init: function (obj) {
var temp = {};
exports.extend(temp, copy(this.defaults.body));
temp.view = obj.type || this.defaults.type;
var etemp = this._get_extendable_cell(temp);
if (obj.body) exports.extend(etemp, obj.body, true);
if (obj.data) etemp.data = obj.data;
if (obj.url) etemp.url = obj.url;
if (obj.datatype) etemp.datatype = obj.datatype;
if (obj.id) temp.id = temp.id || obj.id + "_" + temp.view;
obj.body = temp;
this.$ready.push(this._set_on_popup_click);
this.attachEvent("onShow", function () {
if (this._settings.master) {
var master = $$(this._settings.master);
if (master) {
var node = master._getInputDiv ? master._getInputDiv() : master.getInputNode();
node.setAttribute("aria-expanded", "true");
} // execute only if there is a master view
this._show_selection();
}
});
this.attachEvent("onHide", function () {
if (this._settings.master) {
var master = $$(this._settings.master);
if (master) {
var node = master._getInputDiv ? master._getInputDiv() : master.getInputNode();
node.setAttribute("aria-expanded", "false");
}
}
});
this._old_text = {};
},
_get_extendable_cell: function (obj) {
return obj;
},
_get_details: function (config) {
return isUndefined(config) ? null : {
config: config
};
},
_set_input_value: function (text) {
this._last_input_target.value = text;
},
_preselectMasterOption: function (data) {
var text = data.id ? this.getItemText(data.id) : data.text || data.value;
var node;
if (this._settings.master) {
var master = $$(this._settings.master);
node = master.getInputNode();
if (node) {
// restore last text to allow 'master' view to save new value on blur
var prev_text = master._settings.text;
if (master.options_setter) master.$setValue(data.$empty ? "" : data.id);else if (master.$setValueHere) master.$setValueHere(text, data, this._get_details());else master.$setValue(text);
master._settings.text = prev_text;
}
} else if (this._last_input_target) this._set_input_value(text);
node = node || this._last_input_target;
if (node) node.focus();
},
setMasterValue: function (data, refresh, config) {
var text = data.id ? this.getItemText(data.id) : data.text || data.value;
if (this._settings.master) {
var master = $$(this._settings.master);
if (refresh && data.id) master.refresh();else if (master.options_setter) master.setValue(data.$empty ? "" : data.id, config);else if (master.setValueHere) master.setValueHere(text, data, this._get_details(config));else master.setValue(text, config);
} else if (this._last_input_target) this._set_input_value(text);
if (!refresh) {
this.hide();
if (this._last_input_target) this._last_input_target.focus();
}
this.callEvent("onValueSuggest", [data, text]);
},
getMasterValue: function () {
if (this._settings.master) return $$(this._settings.master).getValue();
return null;
},
getItemId: function (text) {
var list = this.getList();
for (var key in list.data.pull) {
var obj = list.getItem(key);
if (this._settings.filter.call(this, obj, text)) return obj.id;
}
},
getItemText: function (id) {
var item = this.getList().getItem(id);
if (!item) return this._old_text[id] || "";
if (this._settings.template) return this._settings.template.call(this, item, this.type);
if (this._settings.textValue) return "" + item[this._settings.textValue] + "";
var type = this.getList().type;
var text = type.template.call(type, item, type);
return this._old_text[id] = text;
},
getSuggestion: function (text) {
var id,
list = this.getList(),
order = list.data.order;
if (list.getSelectedId) id = list.getSelectedId();
if (text && order.length && (!id || order.find(id) < 0)) {
id = order[0]; //ensure that option really does match client-side filtering rules
if (!list.config.dataFeed && !this.config.filter.call(this, list.data.pull[id], text)) return null;
} //complex id in datatable
if (id) {
if (_typeof(id) == "object") id = id + "";
if (list.getItem(id).$empty) return null;
}
return id;
},
getList: function () {
return this._body_cell;
},
_set_on_popup_click: function () {
var list = this.getList();
var type = this._settings.type;
if (list.count) {
list.attachEvent("onItemClick", bind(function (item) {
this.setMasterValue(list.getItem(item), false, "user");
}, this));
list.data.attachEvent("onStoreUpdated", bind(function (id, obj, mode) {
if (mode == "delete" && id == this.getMasterValue()) this.setMasterValue({
id: "",
text: ""
}, true, "auto");else if (mode == "update" && id == this.getMasterValue()) {
this.setMasterValue(obj, true, "auto");
}
}, this));
list.data.attachEvent("onAfterFilter", bind(this._suggest_after_filter, this));
list.data.attachEvent("onStoreLoad", bind(this._suggest_after_filter, this));
if (isUndefined(this._settings.fitMaster)) this._settings.fitMaster = true;
} else if (type == "calendar") {
list.attachEvent("onAfterDateSelect", function () {
this.getParentView().setMasterValue({
value: list.getSelectedDate()
}, list.config.multiselect, "user");
});
list.attachEvent("onTodaySet", function (date) {
this.getParentView().setMasterValue({
value: date
}, false, "user");
});
list.attachEvent("onDateClear", function (date) {
this.getParentView().setMasterValue({
value: date
}, false, "user");
});
} else if (type == "colorboard") {
list.attachEvent("onItemClick", function (value) {
this.getParentView().setMasterValue({
value: value
}, false, "user");
});
} else if (type == "timeboard") {
list.attachEvent("onTimeSelect", function (value) {
this.getParentView().setMasterValue({
value: value
}, false, "user");
});
} else if (type == "colorselect") {
list.attachEvent("onColorSelect", function (value) {
this.getParentView().setMasterValue({
value: value
}, false, "user");
});
}
},
input_setter: function (value) {
this.linkInput(value);
return 0;
},
linkInput: function (input) {
var node;
if (input.getInputNode) {
node = input.getInputNode();
node.webix_master_id = input._settings.id;
} else node = toNode(input);
_event(node, "keydown", function (e) {
if ((node != document.body || this.isVisible()) && (input.config ? !input.config.readonly : !node.getAttribute("readonly"))) this._suggestions(e);
}, {
bind: this
});
if (input._getInputDiv) node = input._getInputDiv();
node.setAttribute("aria-autocomplete", "list");
node.setAttribute("aria-expanded", "false");
if (node.tagName === "DIV") {
node.setAttribute("aria-live", "assertive");
node.setAttribute("aria-atomic", "true");
}
this._non_ui_mode = true;
},
_suggestions: function (e) {
//should be before tab and arrows handlers: IME can call keydown twice
if (this._last_delay) this._last_delay = clearTimeout(this._last_delay);
e = e || event;
var list = this.getList();
var trg = e.target;
if (trg == document.body && !this.isVisible() || trg.className == "webix_clipbuffer") return;
this._last_input_target = trg;
this._settings.master = trg.webix_master_id;
var code = e.keyCode; //shift and ctrl
if (code == 16 || code == 17) return; // tab - hide popup and do nothing
if (code == 9) return this._tab_key(e, list); // escape - hide popup
if (code == 27) return this._escape_key(e, list); // enter
if (code == 13) return this.$enterKey(e, list); // up/down/right/left are used for navigation
if (this._navigate(e) && this.isVisible()) {
preventEvent(e);
return false;
}
var contentEditable = trg.getAttribute("contentEditable") == "true" || trg.getAttribute("contentEditable") == "";
if (isUndefined(trg.value) && !contentEditable) return;
this._last_delay = delay(function () {
//focus moved to the different control, suggest is not necessary
if (!this._non_ui_mode && UIManager.getFocus() != $$(this._settings.master)) return;
this._resolve_popup = true; //spreadsheet use contentEditable div for cell highlighting
var val = contentEditable ? trg.innerText : trg.value;
if (this._before_filtering) this._before_filtering(); // used to prevent showing popup when it was initialized
if (list.config.dataFeed) list.filter("value", val);else if (list.filter) {
list.filter(bind(function (item) {
return this._settings.filter.call(this, item, val);
}, this));
}
}, this, [], this._settings.keyPressTimeout);
},
_suggest_after_filter: function () {
if (!this._resolve_popup) return true;
this._resolve_popup = false;
var list = this.getList(); // filtering is complete
// if there are as min 1 variant it must be shown, hidden otherwise
if (list.count() > 0) {
this.adjust();
if (!this.isVisible()) this._dont_unfilter = true;
this.show(this._last_input_target, null, true);
this._dont_unfilter = false;
} else {
this.hide();
this._last_input_target = null;
}
},
show: function (node) {
var input = node && (node.tagName == "INPUT" || node.tagName == "TEXTAREA") ? node : null;
if (!this.isVisible() || input && input != this._last_input_target) {
var list = this.getList();
if (list.filter && !this._dont_unfilter) {
list.filter("");
}
if (this.$customWidth) {
this.$customWidth(node);
} else if (node && node.tagName && this._settings.fitMaster) {
this._settings.width = node.offsetWidth - 2; //2 - borders
}
if (list._zoom_level) list.render();
this.adjust(); // needed to return focus
if (input) this._last_input_target = input;
}
popup.api.show.apply(this, arguments);
},
_show_selection: function () {
var list = this.getList();
var value = this.getMasterValue();
if (list.select && list.showItem) {
if (value && list.exists && list.exists(value)) {
list.select(value);
list.showItem(value);
} else {
list.unselect();
list.showItem(list.getFirstId());
}
} else if (list.setValue) {
if (this._settings.master) value = $$(this._settings.master).$prepareValue(value);
list.setValue(value, "auto");
}
},
$enterKey: function (e, list) {
var visible = this.isVisible();
var value;
var master;
if (this._settings.master) master = $$(this._settings.master);
if (master && master._editable && master._settings.editable) master._applyChanges();else if (visible) {
if (list.count) {
value = list.getSelectedId(false, true);
if (list.count() == 1 && list.getFirstId() != value) value = list.getFirstId();
if (value) value = list.getItem(value);
} else {
if (list.getSelectedDate) value = list.getSelectedDate();else if (list.getValue) value = list.getValue();
if (value) value = {
value: value
};
}
if (value) this.setMasterValue(value, false, "user");
}
if (visible) this.hide();else if (this._show_on_key_press) this.show(this._last_input_target);
},
_escape_key: function () {
return this.hide();
},
_tab_key: function () {
return this.hide();
},
/*! suggestions navigation: up/down buttons move selection
* @param e
* event object
**/
_navigate: function (e) {
var list = this.getList();
var code = e.keyCode;
var data;
if (list.moveSelection && code < 41 && code > 32 && !e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey) {
// down and up arrows
if (code === 40 || code === 38) {
if (this._show_on_key_press && !this.isVisible()) this.show(this._last_input_target);
var dir = code === 38 ? "up" : "down";
list.moveSelection(dir, false, false);
} // other arrows
else {
if (list.count || !list.count && !list.isVisible()) return false;
var _dir;
if (code == 33) _dir = "pgup";
if (code == 34) _dir = "pgdown";
if (code == 35) _dir = "bottom";
if (code == 36) _dir = "top";
if (code == 37) _dir = "left";
if (code == 39) _dir = "right";
list.moveSelection(_dir, false, false);
}
if (list.count) data = list.getSelectedItem(false);else {
if (list.getSelectedDate) data = list.getSelectedDate();else if (list.getValue) data = list.getValue();
if (data) data = {
value: data
};
}
if (data && this.isVisible()) this._preselectMasterOption(data);
return true;
}
return false;
},
getValue: function () {
var list = this.getList();
var value = (list.getValue ? list.getValue() : list.getSelectedId()) || "";
value = value.id || value; // check empty
if (list.getItem) {
var item = list.getItem(value);
if (item && item.$empty) return "";
}
return value;
},
setValue: function (value) {
var list = this.getList();
if (value) {
if (list.exists(value)) {
list.select(value);
list.showItem(value);
}
} else {
list.unselect();
list.showItem(list.getFirstId());
}
}
};
var view$V = exports.protoUI(api$V, popup.view);
var suggest = {
api: api$V,
view: view$V
};
exports.protoUI({
name: "multisuggest",
defaults: {
template: "GPL version doesn't support multisuggest <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "checksuggest",
defaults: {
template: "GPL version doesn't support checksuggest <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "datasuggest",
defaults: {
template: "GPL version doesn't support datasuggest <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "gridsuggest",
defaults: {
template: "GPL version doesn't support gridsuggest <br> You need Webix PRO"
}
}, template$1.view);
var api$W = {
name: "mentionsuggest",
defaults: {
symbol: "@",
filter: function (data, value) {
var s = this._settings.symbol;
value = value.substring(0, this._last_cursor_pos);
if (value.indexOf(s) === -1) return false;else {
value = value.substring(value.lastIndexOf(s) + s.length);
if (value.length) {
var text = data.id ? this.getItemText(data.id) : data.text || data.value;
return text.toString().toLowerCase().indexOf(value.toLowerCase()) !== -1;
}
return false;
}
}
},
$init: function () {
this.attachEvent("onValueSuggest", this._before_filtering);
},
$enterKey: function (e) {
if (this.isVisible()) {
preventEvent(e);
var master;
if (this._settings.master) master = $$(this._settings.master);
if (master && master.callEvent) master.callEvent("onEnter");
}
return suggest.api.$enterKey.apply(this, arguments);
},
_before_filtering: function () {
if (this._last_input_target) this._last_cursor_pos = getSelectionRange(this._last_input_target).start;
},
_get_details: function (config) {
return {
pos: this._last_cursor_pos,
symbol: this._settings.symbol,
config: config
};
},
_preselectMasterOption: function () {},
_set_input_value: function (text) {
var s = this._settings.symbol;
var value = this._last_input_target.value;
var last = value.substring(this._last_cursor_pos);
value = value.substring(0, this._last_cursor_pos);
value = value.substring(0, value.lastIndexOf(s) + s.length) + text;
this._last_input_target.value = value + last;
setSelectionRange(this._last_input_target, value.length);
},
_show_on_key_press: false
};
var view$W = exports.protoUI(api$W, suggest.view);
exports.protoUI({
name: "daterange",
defaults: {
template: "GPL version doesn't support daterange <br> You need Webix PRO"
}
}, template$1.view);
var api$X = {
name: "daterangesuggest",
defaults: {
type: "daterange",
body: {
view: "daterange",
icons: true,
button: true,
borderless: true
}
},
getValue: function () {
return this.getRange().getValue();
},
setValue: function (value, config) {
this.getRange().setValue(copy(value), config);
},
getRange: function () {
return this.getBody();
},
getButton: function () {
return this.getBody().getChildViews()[1].getChildViews()[1];
},
_setValue: function (value) {
var master = $$(this._settings.master);
if (master) master.setValue(value, "user");
},
_set_on_popup_click: function () {
var range = this.getRange();
range.attachEvent("onAfterDateSelect", bind(function (value) {
this._setValue(value);
}, this));
range.attachEvent("onDateClear", bind(function (value) {
this._setValue(value);
}, this));
range.attachEvent("onTodaySet", bind(function (value) {
this._setValue(value);
}, this));
}
};
var view$X = exports.protoUI(api$X, suggest.view);
exports.protoUI({
name: "daterangepicker",
defaults: {
template: "GPL version doesn't support daterangepicker <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "excelbar",
defaults: {
template: "GPL version doesn't support excelbar <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "excelviewer",
defaults: {
template: "GPL version doesn't support excelviewer <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "pdfbar",
defaults: {
template: "GPL version doesn't support pdfbar <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "pdfviewer",
defaults: {
template: "GPL version doesn't support pdfviewer <br> You need Webix PRO"
}
}, template$1.view);
/*
UI:Video
*/
// #include ui/view.js
var api$Y = {
name: "video",
$init: function (config) {
if (!config.id) config.id = uid();
this.$ready.push(this._init_video);
},
_init_video: function () {
var c = this._settings;
this._contentobj = create("video", {
"class": "webix_view_video",
"style": "width:100%;height:100%;",
"autobuffer": "autobuffer"
}, "");
if (c.poster) this._contentobj.poster = c.poster;
if (c.src) {
if (_typeof(c.src) != "object") c.src = [c.src];
for (var i = 0; i < c.src.length; i++) {
this._contentobj.innerHTML += " <source src=\"" + c.src[i] + "\">";
}
}
if (c.controls) this._contentobj.controls = true;
if (c.autoplay) this._contentobj.autoplay = true;
this._viewobj.appendChild(this._contentobj);
},
getVideo: function () {
return this._contentobj;
},
defaults: {
src: "",
controls: true
}
};
var view$Y = exports.protoUI(api$Y, base$1.view);
exports.protoUI({
name: "gage",
defaults: {
template: "GPL version doesn't support gage <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "barcode",
defaults: {
template: "GPL version doesn't support barcode <br> You need Webix PRO"
}
}, template$1.view);
exports.protoUI({
name: "bulletgraph",
defaults: {
template: "GPL version doesn't support bulletgraph <br> You need Webix PRO"
}
}, template$1.view);
var google, script;
var api$Z = {
name: "geochart",
defaults: {
chart: {
displayMode: "auto",
region: "world",
resolution: "countries"
}
},
$init: function (config) {
this.$view.innerHTML = "<div class='webix_map_content' style='width:100%;height:100%'></div>";
this._contentobj = this.$view.firstChild;
this._waitMap = Deferred.defer();
config.chart = exports.extend(config.chart || {}, this.defaults.chart);
this.data.provideApi(this, true);
this.$ready.push(this.render);
this.data.attachEvent("onClearAll", bind(this._refreshColumns, this));
this.data.attachEvent("onStoreUpdated", bind(this._drawData, this));
},
getMap: function (waitMap) {
return waitMap ? this._waitMap : this._map;
},
_getCallBack: function (prev) {
return bind(function () {
if (typeof prev === "function") prev();
google = google || window.google;
this._initMap();
}, this);
},
render: function () {
if (typeof window.google == "undefined" || typeof window.google.charts == "undefined") {
if (!script) {
script = document.createElement("script");
script.type = "text/javascript";
script.src = "//www.gstatic.com/charts/loader.js";
document.getElementsByTagName("head")[0].appendChild(script);
}
script.onload = this._getCallBack(script.onload);
} else //there's a custom link to google api in document head
this._getCallBack()();
},
_initMap: function () {
if (!google.visualization || !google.visualization.GeoChart) {
google.charts.load("current", {
"packages": ["geochart"],
"mapsApiKey": this._settings.key
});
google.charts.setOnLoadCallback(bind(function () {
this._initMap();
}, this));
} else {
this._map = new google.visualization.GeoChart(this._contentobj);
this._mapEvents();
this._waitMap.resolve(this._map);
}
},
$onLoad: function (obj) {
if (!this._map) {
this._waitMap.then(bind(function () {
this.parse(obj, this._settings.datatype);
}, this));
return true;
}
return false;
},
_drawData: function () {
if (!this._map) {
if (!this._map) this._waitMap.then(bind(this._drawData, this));
return;
}
var columns = this._columns && this._columns.length ? this._columns : this._defineColumns();
var data = [];
this.data.each(function (obj) {
var line = [];
for (var c = 0; c < columns.length; c++) {
var value = obj[columns[c].label];
if (columns[c].type == "number") value = value * 1;else if (columns[c].role == "tooltip") value = this._settings.tooltip(obj);
line.push(value);
}
data.push(line);
}, this);
if (columns.length) {
var table = new google.visualization.DataTable();
for (var i = 0; i < columns.length; i++) {
table.addColumn(columns[i]);
}
table.addRows(data);
var view = new google.visualization.DataView(table);
this._map.draw(view, this._settings.chart);
} else //draw clean chart
this._map.draw(google.visualization.arrayToDataTable([["", ""]]), {});
},
setDisplayMode: function (value) {
this._settings.chart.displayMode = value;
this.refresh();
},
setRegion: function (value) {
this._settings.chart.region = value;
this.refresh();
},
refresh: function () {
this._map.clearChart();
this._drawData();
},
tooltip_setter: function (value) {
var tooltip = this._settings.chart.tooltip;
this._settings.chart.tooltip = exports.extend(tooltip || {}, {
isHtml: true
});
return template(value);
},
$setSize: function (w, h) {
if (base$1.api.$setSize.apply(this, arguments) && this._map) {
exports.extend(this._settings, {
width: w,
height: h
});
this.refresh();
}
},
_refreshColumns: function () {
this._columns = null;
this._drawData();
},
_getColumnType: function (item, key) {
if (!item || isUndefined(item[key])) return "string";
var type = _typeof(item[key]);
if (type == "string" && !isNaN(item[key] * 1)) type = "number";
return type;
},
_defineColumns: function () {
var columns = this._settings.columns || [];
var item = this.data.pull[this.data.order[0]]; //auto columns
if (!columns.length && item) {
for (var key in item) {
if (key !== "id") columns.push(key);
}
} //["title", "area"]
for (var i = 0; i < columns.length; i++) {
if (_typeof(columns[i]) !== "object") {
columns[i] = {
type: this._getColumnType(item, columns[i]),
label: columns[i]
};
}
}
if (this._settings.tooltip) columns.push({
type: "string",
role: "tooltip",
p: {
"html": true
}
});
this._columns = columns;
return columns;
},
_mapEvents: function () {
google.visualization.events.addListener(this._map, "error", bind(function () {
this.callEvent("onMapError", arguments);
}, this));
google.visualization.events.addListener(this._map, "ready", bind(function () {
this.callEvent("onMapReady", arguments);
}, this));
google.visualization.events.addListener(this._map, "regionClick", bind(function () {
this.callEvent("onRegionClick", arguments);
}, this));
google.visualization.events.addListener(this._map, "select", bind(function () {
var selnow = this._map.getSelection()[0];
var sel = selnow || this._selprev;
if (sel) {
var id = this.data.order[sel.row];
this._selprev = sel;
this.callEvent("onItemClick", [id, !!selnow]);
}
}, this));
}
};
var view$Z = exports.protoUI(api$Z, DataLoader, EventSystem, base$1.view);
var google$1, script$1;
var api$_ = {
name: "google-map",
$init: function () {
this.$view.innerHTML = "<div class='webix_map_content' style='width:100%;height:100%'></div>";
this._contentobj = this.$view.firstChild;
this._waitMap = Deferred.defer();
this.data.provideApi(this, true);
this.$ready.push(this.render);
},
getMap: function (waitMap) {
return waitMap ? this._waitMap : this._map;
},
_getCallBack: function (prev) {
return bind(function () {
if (typeof prev === "function") prev();
google$1 = google$1 || window.google;
this._initMap.call(this);
}, this);
},
render: function () {
if (typeof window.google == "undefined" || typeof window.google.maps == "undefined") {
if (!script$1) {
script$1 = document.createElement("script");
script$1.type = "text/javascript";
var config = this._settings;
var src = config.src || "//maps.google.com/maps/api/js";
src += src.indexOf("?") === -1 ? "?" : "&";
if (config.key) src += "&key=" + config.key;
if (config.libraries) src += "&libraries=" + config.libraries;
script$1.src = src;
document.getElementsByTagName("head")[0].appendChild(script$1);
}
script$1.onload = this._getCallBack(script$1.onload);
} else //there's a custom link to google api in document head
this._getCallBack()();
},
_initMap: function () {
var c = this.config;
if (this.isVisible(c.id)) {
this._map = new google$1.maps.Map(this._contentobj, {
zoom: c.zoom,
center: new google$1.maps.LatLng(c.center[0], c.center[1]),
mapTypeId: google$1.maps.MapTypeId[c.mapType]
});
this._waitMap.resolve(this._map);
this._contentobj.firstChild.setAttribute(
/*@attr*/
"webix_disable_drag", "true");
}
},
center_setter: function (config) {
if (this._map) this._map.setCenter(new google$1.maps.LatLng(config[0], config[1]));
return config;
},
mapType_setter: function (config) {
/*ROADMAP,SATELLITE,HYBRID,TERRAIN*/
if (this._map) this._map.setMapTypeId(google$1.maps.MapTypeId[config]);
return config;
},
zoom_setter: function (config) {
if (this._map) this._map.setZoom(config);
return config;
},
layerType_setter: function (config) {
if (config == "heatmap") this.config.libraries = "visualization";
if (this._layerApi[config]) {
exports.extend(this, this._layerApi[config], true);
this.data.attachEvent("onStoreUpdated", bind(function () {
this._waitMap.then(bind(function () {
this.drawData.call(this, arguments);
}, this));
}, this));
}
return config;
},
defaults: {
zoom: 5,
center: [39.5, -98.5],
mapType: "ROADMAP",
layerType: "marker"
},
$setSize: function () {
base$1.api.$setSize.apply(this, arguments);
if (this._map) google$1.maps.event.trigger(this._map, "resize");
},
$onLoad: function (data) {
if (!this._map) {
this._waitMap.then(bind(function () {
this.parse(data);
}, this));
return true;
}
return false;
},
_layerApi: {
marker: {
drawData: function (id, item, operation) {
switch (operation) {
case "add":
item.$marker = this._getItemConfig(item);
break;
case "update":
item.$marker = this._getItemConfig(item);
break;
case "delete":
item.$marker.setMap(null);
break;
default:
this.data.each(function (item) {
item.$marker = this._getItemConfig(item);
}, this);
break;
}
},
clearAll: function (soft) {
this.data.each(function (obj) {
obj.$marker.setMap(null);
});
this.data.clearAll(soft);
},
showItem: function (id) {
var item = this.getItem(id);
this._map.setCenter(new google$1.maps.LatLng(item.lat, item.lng));
},
_getItemConfig: function (item) {
var obj = {};
for (var i in item) {
obj[i] = item[i];
}
obj.position = new google$1.maps.LatLng(item.lat, item.lng);
obj.map = item.hidden ? null : this._map;
var marker = item.$marker;
if (!marker) {
marker = new google$1.maps.Marker(obj);
this._events(marker);
} else {
item.$marker.setMap(obj.map);
}
this.callEvent("onItemRender", [item]);
return marker;
},
_events: function (marker) {
var map = this;
marker.addListener("click", function () {
map.callEvent("onItemClick", [this.id, this]);
});
if (marker.getDraggable()) {
marker.addListener("dragend", function () {
map._onDrag(this, true);
});
marker.addListener("drag", function () {
map._onDrag(this);
});
}
},
_onDrag: function (marker, end) {
var item = this.getItem(marker.id);
var pos = marker.getPosition();
var ev = end ? "onAfterDrop" : "onDrag";
item.lat = pos.lat();
item.lng = pos.lng();
this.callEvent(ev, [item.id, item]);
}
},
heatmap: {
heatmapConfig_setter: function (value) {
value = value || {};
return value;
},
drawData: function () {
if (this._heatmap) {
this._heatmap.setMap(null);
this._heatmap = null;
}
var hdata = [];
this.data.each(function (item) {
hdata.push(this._getConfig(item));
}, this);
if (hdata.length) {
var data = exports.extend(this.config.heatmapConfig, {
data: hdata,
map: this._map
}, true);
this._heatmap = new google$1.maps.visualization.HeatmapLayer(data);
this.callEvent("onHeatMapRender", [this._heatmap]);
}
},
getHeatmap: function () {
return this._heatmap;
},
_getConfig: function (item) {
var obj = {};
for (var i in item) {
obj[i] = item[i];
}
obj.location = new google$1.maps.LatLng(item.lat, item.lng);
return obj;
}
}
}
};
var view$_ = exports.protoUI(api$_, DataLoader, EventSystem, base$1.view);
var Pie$1 = {
$render_pie: function (ctx, data, x, y, sIndex, map) {
this._renderPie(ctx, data, x, y, 1, map, sIndex);
},
/**
* renders a pie chart
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: x - the width of the container
* @param: y - the height of the container
* @param: ky - value from 0 to 1 that defines an angle of inclination (0<ky<1 - 3D chart)
*/
_renderPie: function (ctx, data, point0, point1, ky, map, sIndex) {
if (!data.length) return;
var coord = this._getPieParameters(point0, point1);
/*pie radius*/
var radius = this._settings.radius ? this._settings.radius : coord.radius;
if (radius < 0) return;
/*real values*/
var values = this._getValues(data);
var totalValue = this._getTotalValue(values);
/*weighed values (the ratio of object value to total value)*/
var ratios = this._getRatios(values, totalValue);
/*pie center*/
var x0 = this._settings.x ? this._settings.x : coord.x;
var y0 = this._settings.y ? this._settings.y : coord.y;
/*adds shadow to the 2D pie*/
if (ky == 1 && this._settings.shadow) this._addShadow(ctx, x0, y0, radius);
/*changes vertical position of the center according to 3Dpie cant*/
y0 = y0 / ky;
/*the angle defines the 1st edge of the sector*/
var alpha0 = -Math.PI / 2;
var angles = [];
/*changes Canvas vertical scale*/
ctx.scale(1, ky);
/*adds radial gradient to a pie*/
if (this._settings.gradient) {
var x1 = ky != 1 ? x0 + radius / 3 : x0;
var y1 = ky != 1 ? y0 + radius / 3 : y0;
this._showRadialGradient(ctx, x0, y0, radius, x1, y1);
}
for (var i = 0; i < data.length; i++) {
if (!values[i]) continue;
/*drawing sector*/
//ctx.lineWidth = 2;
ctx.strokeStyle = this._settings.lineColor.call(this, data[i]);
ctx.beginPath();
ctx.moveTo(x0, y0);
angles.push(alpha0);
/*the angle defines the 2nd edge of the sector*/
var alpha1 = -Math.PI / 2 + ratios[i] - 0.0001;
ctx.arc(x0, y0, radius, alpha0, alpha1, false);
ctx.lineTo(x0, y0);
var color = this._settings.color.call(this, data[i]);
ctx.fillStyle = color;
ctx.fill();
/*text that needs being displayed inside the sector*/
if (this._settings.pieInnerText) this._drawSectorLabel(x0, y0, 5 * radius / 6, alpha0, alpha1, ky, this._settings.pieInnerText(data[i], totalValue), true);
/*label outside the sector*/
if (this._settings.label) this._drawSectorLabel(x0, y0, radius + this._settings.labelOffset, alpha0, alpha1, ky, this._settings.label(data[i]));
/*drawing lower part for 3D pie*/
if (ky != 1) {
this._createLowerSector(ctx, x0, y0, alpha0, alpha1, radius, true);
ctx.fillStyle = "#000000";
ctx.globalAlpha = 0.2;
this._createLowerSector(ctx, x0, y0, alpha0, alpha1, radius, false);
ctx.globalAlpha = 1;
ctx.fillStyle = color;
}
/*creats map area (needed for events)*/
map.addSector(data[i].id, alpha0, alpha1, x0 - point0.x, y0 - point0.y / ky, radius, ky, sIndex);
alpha0 = alpha1;
}
/*renders radius lines and labels*/
ctx.globalAlpha = 0.8;
var p;
for (i = 0; i < angles.length; i++) {
p = this._getPositionByAngle(angles[i], x0, y0, radius);
this._drawLine(ctx, x0, y0, p.x, p.y, this._settings.lineColor.call(this, data[i]), 2);
}
ctx.globalAlpha = 1;
if (ky == 1 && this._settings.border) {
ctx.lineWidth = this._settings.borderWidth || 2;
ctx.strokeStyle = this._settings.borderColor ? this._settings.borderColor.call(this) : "#ffffff";
ctx.beginPath();
ctx.arc(x0, y0, radius + 1, 0, 2 * Math.PI, false);
ctx.stroke();
}
ctx.scale(1, 1 / ky);
},
/**
* returns list of values
* @param: data array
*/
_getValues: function (data) {
var v = [];
for (var i = 0; i < data.length; i++) {
v.push(Math.abs(parseFloat(this._settings.value(data[i])) || 0));
}
return v;
},
/**
* returns total value
* @param: the array of values
*/
_getTotalValue: function (values) {
var t = 0;
for (var i = 0; i < values.length; i++) {
t += values[i];
}
return t;
},
/**
* gets angles for all values
* @param: the array of values
* @param: total value (optional)
*/
_getRatios: function (values, totalValue) {
var value;
var ratios = [];
var prevSum = 0;
totalValue = totalValue || this._getTotalValue(values);
for (var i = 0; i < values.length; i++) {
value = values[i];
ratios[i] = Math.PI * 2 * (totalValue ? (value + prevSum) / totalValue : 1 / values.length);
prevSum += value;
}
return ratios;
},
/**
* returns calculated pie parameters: center position and radius
* @param: x - the width of a container
* @param: y - the height of a container
*/
_getPieParameters: function (point0, point1) {
/*var offsetX = 0;
var offsetY = 0;
if(this._settings.legend &&this._settings.legend.layout!="x")
offsetX = this._settings.legend.width*(this._settings.legend.align=="right"?-1:1);
var x0 = (x + offsetX)/2;
if(this._settings.legend &&this._settings.legend.layout=="x")
offsetY = this._settings.legend.height*(this._settings.legend.valign=="bottom"?-1:1);
var y0 = (y+offsetY)/2;*/
var width = point1.x - point0.x;
var height = point1.y - point0.y;
var x0 = point0.x + width / 2;
var y0 = point0.y + height / 2;
var radius = Math.min(width / 2, height / 2);
return {
"x": x0,
"y": y0,
"radius": radius
};
},
/**
* creates lower part of sector in 3Dpie
* @param: ctx - canvas object
* @param: x0 - the horizontal position of the pie center
* @param: y0 - the vertical position of the pie center
* @param: a0 - the angle that defines the first edge of a sector
* @param: a1 - the angle that defines the second edge of a sector
* @param: R - pie radius
* @param: line (boolean) - if the sector needs a border
*/
_createLowerSector: function (ctx, x0, y0, a1, a2, R, line) {
ctx.lineWidth = 1;
/*checks if the lower sector needs being displayed*/
if (!(a1 <= 0 && a2 >= 0 || a1 >= 0 && a2 <= Math.PI || Math.abs(a1 - Math.PI) > 0.003 && a1 <= Math.PI && a2 >= Math.PI)) return;
if (a1 <= 0 && a2 >= 0) {
a1 = 0;
line = false;
this._drawSectorLine(ctx, x0, y0, R, a1, a2);
}
if (a1 <= Math.PI && a2 >= Math.PI) {
a2 = Math.PI;
line = false;
this._drawSectorLine(ctx, x0, y0, R, a1, a2);
}
/*the height of 3D pie*/
var offset = (this._settings.pieHeight || Math.floor(R / 4)) / this._settings.cant;
ctx.beginPath();
ctx.arc(x0, y0, R, a1, a2, false);
ctx.lineTo(x0 + R * Math.cos(a2), y0 + R * Math.sin(a2) + offset);
ctx.arc(x0, y0 + offset, R, a2, a1, true);
ctx.lineTo(x0 + R * Math.cos(a1), y0 + R * Math.sin(a1));
ctx.fill();
if (line) ctx.stroke();
},
/**
* draws a serctor arc
*/
_drawSectorLine: function (ctx, x0, y0, R, a1, a2) {
ctx.beginPath();
ctx.arc(x0, y0, R, a1, a2, false);
ctx.stroke();
},
/**
* adds a shadow to pie
* @param: ctx - canvas object
* @param: x - the horizontal position of the pie center
* @param: y - the vertical position of the pie center
* @param: R - pie radius
*/
_addShadow: function (ctx, x, y, R) {
ctx.globalAlpha = 0.5;
var shadows = ["#c4c4c4", "#c6c6c6", "#cacaca", "#dcdcdc", "#dddddd", "#e0e0e0", "#eeeeee", "#f5f5f5", "#f8f8f8"];
for (var i = shadows.length - 1; i > -1; i--) {
ctx.beginPath();
ctx.fillStyle = shadows[i];
ctx.arc(x + 1, y + 1, R + i, 0, Math.PI * 2, true);
ctx.fill();
}
ctx.globalAlpha = 1;
},
/**
* returns a gray gradient
* @param: gradient - gradient object
*/
_getGrayGradient: function (gradient) {
gradient.addColorStop(0.0, "#ffffff");
gradient.addColorStop(0.7, "#7a7a7a");
gradient.addColorStop(1.0, "#000000");
return gradient;
},
/**
* adds gray radial gradient
* @param: ctx - canvas object
* @param: x - the horizontal position of the pie center
* @param: y - the vertical position of the pie center
* @param: radius - pie radius
* @param: x0 - the horizontal position of a gradient center
* @param: y0 - the vertical position of a gradient center
*/
_showRadialGradient: function (ctx, x, y, radius, x0, y0) {
//ctx.globalAlpha = 0.3;
ctx.beginPath();
var gradient;
if (typeof this._settings.gradient != "function") {
gradient = ctx.createRadialGradient(x0, y0, radius / 4, x, y, radius);
gradient = this._getGrayGradient(gradient);
} else gradient = this._settings.gradient(gradient);
ctx.fillStyle = gradient;
ctx.arc(x, y, radius, 0, Math.PI * 2, true);
ctx.fill(); //ctx.globalAlpha = 1;
ctx.globalAlpha = 0.7;
},
/**
* returns the calculates pie parameters: center position and radius
* @param: ctx - canvas object
* @param: x0 - the horizontal position of the pie center
* @param: y0 - the vertical position of the pie center
* @param: R - pie radius
* @param: alpha1 - the angle that defines the 1st edge of a sector
* @param: alpha2 - the angle that defines the 2nd edge of a sector
* @param: ky - the value that defines an angle of inclination
* @param: text - label text
* @param: in_width (boolean) - if label needs being displayed inside a pie
*/
_drawSectorLabel: function (x0, y0, R, alpha1, alpha2, ky, text, in_width) {
var t = this.canvases[0].renderText(0, 0, text, 0, 1);
if (!t) return; //get existing width of text
var labelWidth = t.scrollWidth;
t.style.width = labelWidth + "px"; //adjust text label to fit all text
if (labelWidth > x0) labelWidth = x0; //the text can't be greater than half of view
//calculate expected correction based on default font metrics
var width = alpha2 - alpha1 < 0.2 ? 4 : 8;
if (in_width) width = labelWidth / 1.8;
var alpha = alpha1 + (alpha2 - alpha1) / 2; //position and its correction
R = R - (width - 8) / 2;
var corr_x = -width;
var corr_y = -8;
var align = "right"; //for items in left upper and lower sector
if (alpha >= Math.PI / 2 && alpha < Math.PI || alpha <= 3 * Math.PI / 2 && alpha >= Math.PI) {
corr_x = -labelWidth - corr_x + 1;
/*correction for label width*/
align = "left";
}
/*
calculate position of text
basically get point at center of pie sector
*/
var offset = 0;
if (!in_width && ky < 1 && alpha > 0 && alpha < Math.PI) offset = (this._settings.height || Math.floor(R / 4)) / ky;
var y = (y0 + Math.floor((R + offset) * Math.sin(alpha))) * ky + corr_y;
var x = x0 + Math.floor((R + width / 2) * Math.cos(alpha)) + corr_x;
/*
if pie sector starts in left of right part pie,
related text must be placed to the left of to the right of pie as well
*/
var left_end = alpha2 < Math.PI / 2 + 0.01;
var left_start = alpha1 < Math.PI / 2;
if (left_start && left_end) {
x = Math.max(x, x0 + 3); //right part of pie
/*if(alpha2-alpha1<0.2)
x = x0;*/
} else if (!left_start && !left_end) x = Math.min(x, x0 - labelWidth); //left part of pie
else if (!in_width && (alpha >= Math.PI / 2 && alpha < Math.PI || alpha <= 3 * Math.PI / 2 && alpha >= Math.PI)) {
x += labelWidth / 3;
} //we need to set position of text manually, based on above calculations
t.style.top = y + "px";
t.style.left = x + "px";
t.style.width = labelWidth + "px";
t.style.textAlign = align;
t.style.whiteSpace = "nowrap";
},
$render_pie3D: function (ctx, data, x, y, sIndex, map) {
this._renderPie(ctx, data, x, y, this._settings.cant, map);
},
$render_donut: function (ctx, data, point0, point1, sIndex, map) {
if (!data.length) return;
this._renderPie(ctx, data, point0, point1, 1, map, sIndex);
var config = this._settings;
var coord = this._getPieParameters(point0, point1);
var pieRadius = config.radius ? config.radius : coord.radius;
if (pieRadius <= 0) return;
var innerRadius = config.innerRadius && config.innerRadius < pieRadius ? config.innerRadius : pieRadius / 3;
var x0 = config.x ? config.x : coord.x;
var y0 = config.y ? config.y : coord.y;
ctx.fillStyle = $active.backColor;
ctx.beginPath();
ctx.arc(x0, y0, innerRadius, 0, Math.PI * 2, true);
ctx.fill();
if (this._settings.donutInnerText) {
var values = this._getValues(data);
var totalValue = this._getTotalValue(values);
var padding = $active.dataPadding;
var width = innerRadius * 2 - padding * 2;
var centerText = this.canvases[0].renderText(x0 - innerRadius + padding, y0 - innerRadius + padding, "<div class=\"webix_donut_center_text\">".concat(this._settings.donutInnerText(data, totalValue), "</div>"), "webix_donut_center_text_box", width);
centerText.style.height = centerText.style.lineHeight = width + "px";
}
}
};
var BarChart = {
/**
* renders a bar chart
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: x - the width of the container
* @param: y - the height of the container
* @param: sIndex - index of drawing chart
*/
$render_bar: function (ctx, data, point0, point1, sIndex, map) {
var barWidth,
cellWidth,
i,
limits,
maxValue,
minValue,
relValue,
valueFactor,
relativeValues,
startValue,
unit,
xax,
yax,
totalHeight = point1.y - point0.y;
yax = !!this._settings.yAxis;
xax = !!this._settings.xAxis;
limits = this._getLimits();
maxValue = limits.max;
minValue = limits.min;
/*an available width for one bar*/
cellWidth = (point1.x - point0.x) / data.length;
/*draws x and y scales*/
if (!sIndex && !(this._settings.origin != "auto" && !yax)) {
this._drawScales(data, point0, point1, minValue, maxValue, cellWidth);
}
/*necessary for automatic scale*/
if (yax) {
maxValue = parseFloat(this._settings.yAxis.end);
minValue = parseFloat(this._settings.yAxis.start);
}
/*unit calculation (bar_height = value*unit)*/
relativeValues = this._getRelativeValue(minValue, maxValue);
relValue = relativeValues[0];
valueFactor = relativeValues[1];
unit = relValue ? totalHeight / relValue : relValue;
if (!yax && !(this._settings.origin != "auto" && xax)) {
/*defines start value for better representation of small values*/
startValue = 10;
unit = relValue ? (totalHeight - startValue) / relValue : startValue;
}
/*if yAxis isn't set, but with custom origin */
if (!sIndex && this._settings.origin != "auto" && !yax && this._settings.origin > minValue) {
this._drawXAxis(ctx, data, point0, point1, cellWidth, point1.y - unit * (this._settings.origin - minValue));
}
/*a real bar width */
barWidth = parseInt(this._settings.barWidth, 10);
var seriesNumber = 0;
var seriesIndex = 0;
for (i = 0; i < this._series.length; i++) {
if (i == sIndex) {
seriesIndex = seriesNumber;
}
if (this._series[i].type == "bar") seriesNumber++;
}
if (this._series && barWidth * seriesNumber + 4 > cellWidth) barWidth = parseInt(cellWidth / seriesNumber - 4, 10);
/*the half of distance between bars*/
var barOffset = (cellWidth - barWidth * seriesNumber) / 2;
/*the radius of rounding in the top part of each bar*/
var radius = typeof this._settings.radius != "undefined" ? parseInt(this._settings.radius, 10) : Math.round(barWidth / 5);
var inner_gradient = false;
var gradient = this._settings.gradient;
if (gradient && typeof gradient != "function") {
inner_gradient = gradient;
gradient = false;
} else if (gradient) {
gradient = ctx.createLinearGradient(0, point1.y, 0, point0.y);
this._settings.gradient(gradient);
}
/*draws a black line if the horizontal scale isn't defined*/
if (!xax) {
this._drawLine(ctx, point0.x, point1.y + 0.5, point1.x, point1.y + 0.5, "#edeff0", 1); //hardcoded color!
}
for (i = 0; i < data.length; i++) {
var value = parseFloat(this._settings.value(data[i]) || 0);
if (this._logScaleCalc) value = this._log10(value);
if (!value || isNaN(value)) continue;
if (value > maxValue) value = maxValue;
value -= minValue;
value *= valueFactor;
/*start point (bottom left)*/
var x0 = point0.x + barOffset + i * cellWidth + (barWidth + 1) * seriesIndex;
var y0 = point1.y;
var color$$1 = gradient || this._settings.color.call(this, data[i]);
var border = this._settings.border ? 1 : 0;
var label = this._settings.label(data[i]);
/*takes start value into consideration */
if (!yax && !(this._settings.origin != "auto" && xax)) value += startValue / unit;
/* don't draw borders and labels for not painted values (on y-Axis or lower) */
else if (value == this._settings.origin || this._settings.origin == "auto" && this._settings.value(data[i]) == minValue) {
border = 0;
label = "";
} else if (value < 0 || this._settings.yAxis && value === 0 && !(this._settings.origin != "auto" && this._settings.origin > minValue)) {
value = border = 0;
label = "";
}
/*drawing bar body*/
ctx.globalAlpha = this._settings.alpha.call(this, data[i]);
var points = this._drawBar(ctx, point0, x0, y0, barWidth, minValue, radius, unit, value, color$$1, gradient, inner_gradient, border);
if (inner_gradient) {
this._drawBarGradient(ctx, x0, y0, barWidth, minValue, radius, unit, value, color$$1, inner_gradient, border);
}
/*drawing the gradient border of a bar*/
if (border) this._drawBarBorder(ctx, x0, y0, barWidth, minValue, radius, unit, value, color$$1);
ctx.globalAlpha = 1;
/*sets a bar label*/
if (points[0] != x0) this.canvases[sIndex].renderTextAt(false, true, x0 + Math.floor(barWidth / 2), points[1], label);else this.canvases[sIndex].renderTextAt(true, true, x0 + Math.floor(barWidth / 2), points[3], label);
/*defines a map area for a bar*/
map.addRect(data[i].id, [x0 - point0.x, points[3] - point0.y, points[2] - point0.x, points[1] - point0.y], sIndex); //this._addMapRect(map,data[i].id,[{x:x0,y:points[3]},{x:points[2],y:points[1]}],point0,sIndex);
}
},
_correctBarParams: function (ctx, x, y, value, unit, barWidth, minValue) {
var axisStart = y;
if (this._settings.origin != "auto" && this._settings.origin > minValue) {
y -= (this._settings.origin - minValue) * unit;
axisStart = y;
value = value - (this._settings.origin - minValue);
if (value < 0) {
value *= -1;
ctx.translate(x + barWidth, y);
ctx.rotate(Math.PI);
x = 0;
y = 0;
}
y -= 0.5;
}
return {
value: value,
x0: x,
y0: y,
start: axisStart
};
},
_drawBar: function (ctx, point0, x0, y0, barWidth, minValue, radius, unit, value, color$$1, gradient, inner_gradient, border) {
ctx.save();
ctx.fillStyle = color$$1;
var p = this._correctBarParams(ctx, x0, y0, value, unit, barWidth, minValue);
var points = this._setBarPoints(ctx, p.x0, p.y0, barWidth, radius, unit, p.value, border);
if (gradient && !inner_gradient) ctx.lineTo(p.x0 + border, point0.y); //fix gradient sphreading
ctx.fill();
ctx.restore();
var x1 = p.x0;
var x2 = p.x0 != x0 ? x0 + points[0] : points[0];
var y1 = p.x0 != x0 ? p.start - points[1] - p.y0 : p.y0;
var y2 = p.x0 != x0 ? p.start - p.y0 : points[1];
return [x1, y1, x2, y2];
},
_setBorderStyles: function (ctx, rawColor) {
var hsv, rgb;
rgb = color.toRgb(rawColor);
hsv = color.rgbToHsv(rgb[0], rgb[1], rgb[2]);
hsv[2] /= 1.4;
var rgbColor = "rgb(" + color.hsvToRgb(hsv[0], hsv[1], hsv[2]) + ")";
ctx.strokeStyle = rgbColor;
if (ctx.globalAlpha == 1) ctx.globalAlpha = 0.9;
},
_drawBarBorder: function (ctx, x0, y0, barWidth, minValue, radius, unit, value, color$$1) {
var p;
ctx.save();
p = this._correctBarParams(ctx, x0, y0, value, unit, barWidth, minValue);
this._setBorderStyles(ctx, color$$1);
this._setBarPoints(ctx, p.x0, p.y0, barWidth, radius, unit, p.value, ctx.lineWidth / 2, 1);
ctx.stroke();
/*ctx.fillStyle = color;
this._setBarPoints(ctx,p.x0,p.y0,barWidth,radius,unit,p.value,0);
ctx.lineTo(p.x0,0);
ctx.fill()
ctx.fillStyle = "#000000";
ctx.globalAlpha = 0.37;
this._setBarPoints(ctx,p.x0,p.y0,barWidth,radius,unit,p.value,0);
ctx.fill()
*/
ctx.restore();
},
_drawBarGradient: function (ctx, x0, y0, barWidth, minValue, radius, unit, value, color$$1, inner_gradient, border) {
ctx.save();
var p = this._correctBarParams(ctx, x0, y0, value, unit, barWidth, minValue);
var gradParam = this._setBarGradient(ctx, p.x0, p.y0, p.x0 + barWidth, p.y0 - unit * p.value + 2, inner_gradient, color$$1, "y");
ctx.fillStyle = gradParam.gradient;
this._setBarPoints(ctx, p.x0 + gradParam.offset, p.y0, barWidth - gradParam.offset * 2, radius, unit, p.value, gradParam.offset + border);
ctx.fill();
ctx.restore();
},
/**
* sets points for bar and returns the position of the bottom right point
* @param: ctx - canvas object
* @param: x0 - the x position of start point
* @param: y0 - the y position of start point
* @param: barWidth - bar width
* @param: radius - the rounding radius of the top
* @param: unit - the value defines the correspondence between item value and bar height
* @param: value - item value
* @param: offset - the offset from expected bar edge (necessary for drawing border)
*/
_setBarPoints: function (ctx, x0, y0, barWidth, radius, unit, value, offset, skipBottom) {
/*correction for displaing small values (when rounding radius is bigger than bar height)*/
ctx.beginPath(); //y0 = 0.5;
var angle_corr = 0;
if (radius > unit * value) {
var cosA = (radius - unit * value) / radius;
if (cosA <= 1 && cosA >= -1) angle_corr = -Math.acos(cosA) + Math.PI / 2;
}
/*start*/
ctx.moveTo(x0 + offset, y0);
/*start of left rounding*/
var y1 = y0 - Math.floor(unit * value) + radius + (radius ? 0 : offset);
if (radius < unit * value) ctx.lineTo(x0 + offset, y1);
/*left rounding*/
var x2 = x0 + radius;
if (radius && radius > 0) ctx.arc(x2, y1, Math.max(radius - offset, 0), -Math.PI + angle_corr, -Math.PI / 2, false);
/*start of right rounding*/
var x3 = x0 + barWidth - radius - offset;
var y3 = y1 - radius + (radius ? offset : 0);
ctx.lineTo(x3, y3);
/*right rounding*/
if (radius && radius > 0) ctx.arc(x3 + offset, y1, Math.max(radius - offset, 0), -Math.PI / 2, 0 - angle_corr, false);
/*bottom right point*/
var x5 = x0 + barWidth - offset;
ctx.lineTo(x5, y0);
/*line to the start point*/
if (!skipBottom) {
ctx.lineTo(x0 + offset, y0);
} // ctx.lineTo(x0,0); //IE fix!
return [x5, y3];
}
};
var LineChart = {
/**
* renders a graphic
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: width - the width of the container
* @param: height - the height of the container
* @param: sIndex - index of drawing chart
*/
$render_line: function (ctx, data, point0, point1, sIndex, map) {
var config, i, items, params, x0, x1, x2, y1, y2, y0, res1, res2;
params = this._calculateLineParams(ctx, data, point0, point1, sIndex);
config = this._settings;
if (data.length) {
x0 = config.offset ? point0.x + params.cellWidth * 0.5 : point0.x; //finds items with data (excludes scale units)
items = [];
for (i = 0; i < data.length; i++) {
res2 = this._getPointY(data[i], point0, point1, params);
if (res2 || res2 == "0") {
x2 = !i ? x0 : params.cellWidth * i - 0.5 + x0;
y2 = _typeof(res2) == "object" ? res2.y0 : res2;
if (i && this._settings.fixOverflow) {
res1 = this._getPointY(data[i - 1], point0, point1, params);
if (res1.out && res1.out == res2.out) {
continue;
}
x1 = params.cellWidth * (i - 1) - 0.5 + x0;
y1 = _typeof(res1) == "object" ? res1.y0 : res1;
if (res1.out) {
y0 = res1.out == "min" ? point1.y : point0.y;
items.push({
x: this._calcOverflowX(x1, x2, y1, y2, y0),
y: y0
});
}
if (res2.out) {
y0 = res2.out == "min" ? point1.y : point0.y;
items.push({
x: this._calcOverflowX(x1, x2, y1, y2, y0),
y: y0
});
}
}
if (!res2.out) items.push({
x: x2,
y: res2,
index: i
});
}
}
this._mapStart = point0;
for (i = 1; i <= items.length; i++) {
//line start position
x1 = items[i - 1].x;
y1 = items[i - 1].y;
if (i < items.length) {
//line end position
x2 = items[i].x;
y2 = items[i].y; //line
this._drawLine(ctx, x1, y1, x2, y2, config.line.color.call(this, data[i - 1]), config.line.width); //line shadow
if (config.line && config.line.shadow) {
ctx.globalAlpha = 0.3;
this._drawLine(ctx, x1 + 2, y1 + config.line.width + 8, x2 + 2, y2 + config.line.width + 8, "#eeeeee", config.line.width + 3);
ctx.globalAlpha = 1;
}
} //item
if (typeof items[i - 1].index != "undefined") {
this._drawItem(ctx, x1, y1, data[items[i - 1].index], config.label(data[items[i - 1].index]), sIndex, map, point0);
}
}
}
},
_calcOverflowX: function (x1, x2, y1, y2, y) {
return x1 + (y - y1) * (x2 - x1) / (y2 - y1);
},
/**
* draws an item and its label
* @param: ctx - canvas object
* @param: x0 - the x position of a circle
* @param: y0 - the y position of a circle
* @param: obj - data object
* @param: label - (boolean) defines wherether label needs being drawn
*/
_drawItem: function (ctx, x0, y0, obj, label, sIndex, map) {
var config = this._settings.item;
var R = parseInt(config.radius.call(this, obj), 10) || 0;
var mapStart = this._mapStart;
var item = config.type.call(this, obj);
if (R) {
ctx.save();
if (config.shadow) {
ctx.lineWidth = 1;
ctx.strokeStyle = "#bdbdbd";
ctx.fillStyle = "#bdbdbd";
var alphas = [0.1, 0.2, 0.3];
for (var i = alphas.length - 1; i >= 0; i--) {
ctx.globalAlpha = alphas[i];
ctx.strokeStyle = "#d0d0d0";
ctx.beginPath();
this._strokeChartItem(ctx, x0, y0 + 2 * R / 3, R + i + 1, item);
ctx.stroke();
}
ctx.beginPath();
ctx.globalAlpha = 0.3;
ctx.fillStyle = "#bdbdbd";
this._strokeChartItem(ctx, x0, y0 + 2 * R / 3, R + 1, item);
ctx.fill();
}
ctx.restore();
ctx.lineWidth = config.borderWidth;
ctx.fillStyle = config.color.call(this, obj);
ctx.strokeStyle = config.borderColor.call(this, obj);
ctx.globalAlpha = config.alpha.call(this, obj);
ctx.beginPath();
this._strokeChartItem(ctx, x0, y0, R + 1, item);
ctx.fill();
ctx.stroke();
ctx.globalAlpha = 1;
}
/*item label*/
if (label) {
this.canvases[sIndex].renderTextAt(false, true, x0, y0 - R - this._settings.labelOffset, this._settings.label.call(this, obj));
}
if (map) {
var areaPos = this._settings.eventRadius || R + 1; //this._addMapRect(map,obj.id,[{x:x0-areaPos,y:y0-areaPos},{x0+areaPos,y:y0+areaPos}],point0,sIndex);
map.addRect(obj.id, [x0 - areaPos - mapStart.x, y0 - areaPos - mapStart.y, x0 + areaPos - mapStart.x, y0 + areaPos - mapStart.y], sIndex);
}
},
_strokeChartItem: function (ctx, x0, y0, R, type) {
var p = [];
if (type && (type == "square" || type == "s")) {
R *= Math.sqrt(2) / 2;
p = [[x0 - R - ctx.lineWidth / 2, y0 - R], [x0 + R, y0 - R], [x0 + R, y0 + R], [x0 - R, y0 + R], [x0 - R, y0 - R]];
} else if (type && (type == "diamond" || type == "d")) {
var corr = ctx.lineWidth > 1 ? ctx.lineWidth * Math.sqrt(2) / 4 : 0;
p = [[x0, y0 - R], [x0 + R, y0], [x0, y0 + R], [x0 - R, y0], [x0 + corr, y0 - R - corr]];
} else if (type && (type == "triangle" || type == "t")) {
p = [[x0, y0 - R], [x0 + Math.sqrt(3) * R / 2, y0 + R / 2], [x0 - Math.sqrt(3) * R / 2, y0 + R / 2], [x0, y0 - R]];
} else p = [[x0, y0, R, 0, Math.PI * 2, true]];
this._path(ctx, p);
},
/**
* gets the vertical position of the item
* @param: data - data object
* @param: y0 - the y position of chart start
* @param: y1 - the y position of chart end
* @param: params - the object with elements: minValue, maxValue, unit, valueFactor (the value multiple of 10)
*/
_getPointY: function (data, point0, point1, params) {
var minValue = params.minValue;
var maxValue = params.maxValue;
var unit = params.unit;
var valueFactor = params.valueFactor;
/*the real value of an object*/
var value = this._settings.value(data);
if (this._logScaleCalc) {
value = this._log10(value);
}
/*a relative value*/
var v = (parseFloat(value || 0) - minValue) * valueFactor;
if (!this._settings.yAxis) v += params.startValue / unit;
/*a vertical coordinate*/
var y = point1.y - unit * v;
/*the limit of the max and min values*/
if (this._settings.fixOverflow && (this._settings.type == "line" || this._settings.type == "area")) {
if (value > maxValue) y = {
y: point0.y,
y0: y,
out: "max"
};else if (v < 0 || value < minValue) y = {
y: point1.y,
y0: y,
out: "min"
};
} else {
if (value > maxValue) y = point0.y;
if (v < 0 || value < minValue) y = point1.y;
}
return y;
},
_calculateLineParams: function (ctx, data, point0, point1, sIndex) {
var params = {};
/*maxValue - minValue*/
var relValue;
/*available height*/
params.totalHeight = point1.y - point0.y;
/*a space available for a single item*/
//params.cellWidth = Math.round((point1.x-point0.x)/((!this._settings.offset&&this._settings.yAxis)?(data.length-1):data.length));
if (this._settings.cellWidth) params.cellWidth = Math.min(point1.x - point0.x, this._settings.cellWidth);else params.cellWidth = (point1.x - point0.x) / (!this._settings.offset ? data.length - 1 : data.length);
/*scales*/
var yax = !!this._settings.yAxis;
var limits = this._settings.type.indexOf("stacked") != -1 ? this._getStackedLimits(data) : this._getLimits();
params.maxValue = limits.max;
params.minValue = limits.min;
/*draws x and y scales*/
if (!sIndex) this._drawScales(data, point0, point1, params.minValue, params.maxValue, params.cellWidth);
/*necessary for automatic scale*/
if (yax) {
params.maxValue = parseFloat(this._settings.yAxis.end);
params.minValue = parseFloat(this._settings.yAxis.start);
}
/*unit calculation (y_position = value*unit)*/
var relativeValues = this._getRelativeValue(params.minValue, params.maxValue);
relValue = relativeValues[0];
params.valueFactor = relativeValues[1];
params.unit = relValue ? params.totalHeight / relValue : 10;
params.startValue = 0;
if (!yax) {
/*defines start value for better representation of small values*/
params.startValue = 10;
if (params.unit != params.totalHeight) params.unit = relValue ? (params.totalHeight - params.startValue) / relValue : 10;
}
return params;
}
};
var BarHChart = {
/**
* renders a bar chart
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: x - the width of the container
* @param: y - the height of the container
* @param: sIndex - index of drawing chart
*/
$render_barH: function (ctx, data, point0, point1, sIndex, map) {
var barOffset, barWidth, cellWidth, color, gradient, i, limits, maxValue, minValue, innerGradient, valueFactor, relValue, radius, relativeValues, startValue, totalWidth, value, unit, x0, y0, xax;
/*an available width for one bar*/
cellWidth = (point1.y - point0.y) / data.length;
limits = this._getLimits("h");
maxValue = limits.max;
minValue = limits.min;
totalWidth = point1.x - point0.x;
xax = !!this._settings.xAxis;
/*draws x and y scales*/
if (!sIndex) this._drawHScales(ctx, data, point0, point1, minValue, maxValue, cellWidth);
/*necessary for automatic scale*/
if (xax) {
maxValue = parseFloat(this._settings.xAxis.end);
minValue = parseFloat(this._settings.xAxis.start);
}
/*unit calculation (bar_height = value*unit)*/
relativeValues = this._getRelativeValue(minValue, maxValue);
relValue = relativeValues[0];
valueFactor = relativeValues[1];
unit = relValue ? totalWidth / relValue : 10;
if (!xax) {
/*defines start value for better representation of small values*/
startValue = 10;
unit = relValue ? (totalWidth - startValue) / relValue : 10;
}
/*a real bar width */
barWidth = parseInt(this._settings.barWidth, 10);
if (barWidth * this._series.length + 4 > cellWidth) barWidth = cellWidth / this._series.length - 4;
/*the half of distance between bars*/
barOffset = Math.floor((cellWidth - barWidth * this._series.length) / 2);
/*the radius of rounding in the top part of each bar*/
radius = typeof this._settings.radius != "undefined" ? parseInt(this._settings.radius, 10) : Math.round(barWidth / 5);
innerGradient = false;
gradient = this._settings.gradient;
if (gradient && typeof gradient != "function") {
innerGradient = gradient;
gradient = false;
} else if (gradient) {
gradient = ctx.createLinearGradient(point0.x, point0.y, point1.x, point0.y);
this._settings.gradient(gradient);
}
/*draws a black line if the horizontal scale isn't defined*/
if (!xax) {
this._drawLine(ctx, point0.x - 0.5, point0.y, point0.x - 0.5, point1.y, "#edeff0", 1); //hardcoded color!
}
for (i = 0; i < data.length; i++) {
value = parseFloat(this._settings.value(data[i] || 0));
if (this._logScaleCalc) value = this._log10(value);
if (!value || isNaN(value)) continue;
if (value > maxValue) value = maxValue;
value -= minValue;
value *= valueFactor;
/*start point (bottom left)*/
x0 = point0.x;
y0 = point0.y + barOffset + i * cellWidth + (barWidth + 1) * sIndex;
if (value < 0 && this._settings.origin == "auto" || this._settings.xAxis && value === 0 && !(this._settings.origin != "auto" && this._settings.origin > minValue)) {
this.canvases[sIndex].renderTextAt("middle", "right", x0 + 10, y0 + barWidth / 2 + barOffset, this._settings.label(data[i]));
continue;
}
if (value < 0 && this._settings.origin != "auto" && this._settings.origin > minValue) {
value = 0;
}
/*takes start value into consideration*/
if (!xax) value += startValue / unit;
color = gradient || this._settings.color.call(this, data[i]);
/*drawing the gradient border of a bar*/
if (this._settings.border) {
this._drawBarHBorder(ctx, x0, y0, barWidth, minValue, radius, unit, value, color);
}
/*drawing bar body*/
ctx.globalAlpha = this._settings.alpha.call(this, data[i]);
var points = this._drawBarH(ctx, point1, x0, y0, barWidth, minValue, radius, unit, value, color, gradient, innerGradient);
if (innerGradient) {
this._drawBarHGradient(ctx, x0, y0, barWidth, minValue, radius, unit, value, color, innerGradient);
}
ctx.globalAlpha = 1;
/*sets a bar label and map area*/
if (points[3] == y0) {
this.canvases[sIndex].renderTextAt("middle", "left", points[0] - 5, points[3] + Math.floor(barWidth / 2), this._settings.label(data[i]));
map.addRect(data[i].id, [points[0] - point0.x, points[3] - point0.y, points[2] - point0.x, points[3] + barWidth - point0.y], sIndex);
} else {
this.canvases[sIndex].renderTextAt("middle", false, points[2] + 5, points[1] + Math.floor(barWidth / 2), this._settings.label(data[i]));
map.addRect(data[i].id, [points[0] - point0.x, y0 - point0.y, points[2] - point0.x, points[3] - point0.y], sIndex);
}
}
},
/**
* sets points for bar and returns the position of the bottom right point
* @param: ctx - canvas object
* @param: x0 - the x position of start point
* @param: y0 - the y position of start point
* @param: barWidth - bar width
* @param: radius - the rounding radius of the top
* @param: unit - the value defines the correspondence between item value and bar height
* @param: value - item value
* @param: offset - the offset from expected bar edge (necessary for drawing border)
*/
_setBarHPoints: function (ctx, x0, y0, barWidth, radius, unit, value, offset, skipLeft) {
/*correction for displaing small values (when rounding radius is bigger than bar height)*/
var angle_corr = 0;
if (radius > unit * value) {
var sinA = (radius - unit * value) / radius;
angle_corr = -Math.asin(sinA) + Math.PI / 2;
}
/*start*/
ctx.moveTo(x0, y0 + offset);
/*start of left rounding*/
var x1 = x0 + unit * value - radius - (radius ? 0 : offset);
x1 = Math.max(x0, x1);
if (radius < unit * value) ctx.lineTo(x1, y0 + offset);
/*left rounding*/
var y2 = y0 + radius;
if (radius && radius > 0) ctx.arc(x1, y2, radius - offset, -Math.PI / 2 + angle_corr, 0, false);
/*start of right rounding*/
var y3 = y0 + barWidth - radius - (radius ? 0 : offset);
var x3 = x1 + radius - (radius ? offset : 0);
ctx.lineTo(x3, y3);
/*right rounding*/
if (radius && radius > 0) ctx.arc(x1, y3, radius - offset, 0, Math.PI / 2 - angle_corr, false);
/*bottom right point*/
var y5 = y0 + barWidth - offset;
ctx.lineTo(x0, y5);
/*line to the start point*/
if (!skipLeft) {
ctx.lineTo(x0, y0 + offset);
} // ctx.lineTo(x0,0); //IE fix!
return [x3, y5];
},
_drawHScales: function (ctx, data, point0, point1, start, end, cellWidth) {
var x = 0;
if (this._settings.xAxis) {
if (!this.canvases["x"]) this.canvases["x"] = this._createCanvas("axis_x");
x = this._drawHXAxis(this.canvases["x"].getCanvas(), data, point0, point1, start, end);
}
if (this._settings.yAxis) {
if (!this.canvases["y"]) this.canvases["y"] = this._createCanvas("axis_y");
this._drawHYAxis(this.canvases["y"].getCanvas(), data, point0, point1, cellWidth, x);
}
},
_drawHYAxis: function (ctx, data, point0, point1, cellWidth, yAxisX) {
if (!this._settings.yAxis) return;
var unitPos;
var x0 = parseInt(yAxisX ? yAxisX : point0.x, 10) - 0.5;
var y0 = point1.y + 0.5;
var y1 = point0.y;
this._drawLine(ctx, x0, y0, x0, y1, this._settings.yAxis.color, 1);
for (var i = 0; i < data.length; i++) {
/*scale labels*/
var right = this._settings.origin != "auto" && this._settings.type == "barH" && parseFloat(this._settings.value(data[i])) < this._settings.origin;
unitPos = y1 + cellWidth / 2 + i * cellWidth;
this.canvases["y"].renderTextAt("middle", right ? false : "left", right ? x0 + 5 : x0 - 5, unitPos, this._settings.yAxis.template(data[i]), "webix_axis_item_y", right ? 0 : x0 - 10);
if (this._settings.yAxis.lines.call(this, data[i])) this._drawLine(ctx, point0.x, unitPos, point1.x, unitPos, this._settings.yAxis.lineColor.call(this, data[i]), 1);
}
if (this._settings.yAxis.lines.call(this, {})) this._drawLine(ctx, point0.x + 0.5, y1 + 0.5, point1.x, y1 + 0.5, this._settings.yAxis.lineColor.call(this, {}), 1);
this._setYAxisTitle(point0, point1);
},
_drawHXAxis: function (ctx, data, point0, point1, start, end) {
var step;
var scaleParam = {};
var axis = this._settings.xAxis;
if (!axis) return;
var y0 = point1.y + 0.5;
var x0 = point0.x - 0.5;
var x1 = point1.x - 0.5;
var yAxisStart = point0.x;
this._drawLine(ctx, x0, y0, x1, y0, axis.color, 1);
if (axis.step) step = parseFloat(axis.step);
if (typeof this._configXAxis.step == "undefined" || typeof this._configXAxis.start == "undefined" || typeof this._configXAxis.end == "undefined") {
scaleParam = this._calculateScale(start, end);
start = scaleParam.start;
end = scaleParam.end;
step = scaleParam.step;
this._settings.xAxis.end = end;
this._settings.xAxis.start = start;
this._settings.xAxis.step = step;
}
if (step === 0) return;
var stepHeight = (x1 - x0) * step / (end - start);
var c = 0;
for (var i = start; i <= end; i += step) {
var value = this._logScaleCalc ? Math.pow(10, i) : i;
if (scaleParam.fixNum) value = parseFloat(value).toFixed(scaleParam.fixNum);
var xi = Math.floor(x0 + c * stepHeight) + 0.5;
/*canvas line fix*/
if (!(i == start && this._settings.origin == "auto") && axis.lines.call(this, i)) this._drawLine(ctx, xi, y0, xi, point0.y, this._settings.xAxis.lineColor.call(this, i), 1);
if (i == this._settings.origin) yAxisStart = xi + 1;
/*correction for JS float calculation*/
if (step < 1 && !this._logScaleCalc) {
var power = Math.min(Math.floor(this._log10(step)), start <= 0 ? 0 : Math.floor(this._log10(start)));
var corr = Math.pow(10, -power);
value = Math.round(value * corr) / corr;
i = value;
}
this.canvases["x"].renderTextAt(false, true, xi, y0 + 2, axis.template(value.toString()), "webix_axis_item_x");
c++;
}
this.canvases["x"].renderTextAt(true, false, x0, point1.y + this._settings.padding.bottom - 3, this._settings.xAxis.title, "webix_axis_title_x", point1.x - point0.x);
return yAxisStart;
},
_correctBarHParams: function (ctx, x, y, value, unit, barWidth, minValue) {
var yax = this._settings.yAxis;
var axisStart = x;
if (!!yax && this._settings.origin != "auto" && this._settings.origin > minValue) {
x += (this._settings.origin - minValue) * unit;
axisStart = x;
value = value - (this._settings.origin - minValue);
if (value < 0) {
value *= -1;
ctx.translate(x, y + barWidth);
ctx.rotate(Math.PI);
x = 0.5;
y = 0;
}
x += 0.5;
}
return {
value: value,
x0: x,
y0: y,
start: axisStart
};
},
_drawBarH: function (ctx, point1, x0, y0, barWidth, minValue, radius, unit, value, color, gradient, inner_gradient) {
ctx.save();
var p = this._correctBarHParams(ctx, x0, y0, value, unit, barWidth, minValue);
ctx.fillStyle = color;
ctx.beginPath();
var points = this._setBarHPoints(ctx, p.x0, p.y0, barWidth, radius, unit, p.value, this._settings.border ? 1 : 0);
if (gradient && !inner_gradient) ctx.lineTo(point1.x, p.y0 + (this._settings.border ? 1 : 0)); //fix gradient sphreading
ctx.fill();
ctx.restore();
var y1 = p.y0;
var y2 = p.y0 != y0 ? y0 : points[1];
var x1 = p.y0 != y0 ? p.start - points[0] : p.start;
var x2 = p.y0 != y0 ? p.start : points[0];
return [x1, y1, x2, y2];
},
_drawBarHBorder: function (ctx, x0, y0, barWidth, minValue, radius, unit, value, color) {
ctx.save();
var p = this._correctBarHParams(ctx, x0, y0, value, unit, barWidth, minValue);
ctx.beginPath();
this._setBorderStyles(ctx, color);
ctx.globalAlpha = 0.9;
this._setBarHPoints(ctx, p.x0, p.y0, barWidth, radius, unit, p.value, ctx.lineWidth / 2, 1);
ctx.stroke();
ctx.restore();
},
_drawBarHGradient: function (ctx, x0, y0, barWidth, minValue, radius, unit, value, color, inner_gradient) {
ctx.save();
var p = this._correctBarHParams(ctx, x0, y0, value, unit, barWidth, minValue);
var gradParam = this._setBarGradient(ctx, p.x0, p.y0 + barWidth, p.x0 + unit * p.value, p.y0, inner_gradient, color, "x");
ctx.fillStyle = gradParam.gradient;
ctx.beginPath();
this._setBarHPoints(ctx, p.x0, p.y0 + gradParam.offset, barWidth - gradParam.offset * 2, radius, unit, p.value, gradParam.offset);
ctx.fill();
ctx.globalAlpha = 1;
ctx.restore();
}
};
var StackedBarChart = {
/**
* renders a bar chart
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: x - the width of the container
* @param: y - the height of the container
* @param: sIndex - index of drawing chart
*/
$render_stackedBar: function (ctx, data, point0, point1, sIndex, map) {
var maxValue, minValue, xAxisY, x0, y0;
/*necessary if maxValue - minValue < 0*/
var valueFactor;
/*maxValue - minValue*/
var relValue;
var config = this._settings;
var total_height = point1.y - point0.y;
var yax = !!config.yAxis;
var xax = !!config.xAxis;
var limits = this._getStackedLimits(data);
var origin = config.origin === 0;
maxValue = limits.max;
minValue = limits.min;
/*an available width for one bar*/
var cellWidth = Math.floor((point1.x - point0.x) / data.length);
/*draws x and y scales*/
if (!sIndex) {
xAxisY = this._drawScales(data, point0, point1, minValue, maxValue, cellWidth);
}
/*necessary for automatic scale*/
if (yax) {
maxValue = parseFloat(config.yAxis.end);
minValue = parseFloat(config.yAxis.start);
}
/*unit calculation (bar_height = value*unit)*/
var relativeValues = this._getRelativeValue(minValue, maxValue);
relValue = relativeValues[0];
valueFactor = relativeValues[1];
var unit = relValue ? total_height / relValue : 10;
/*a real bar width */
var barWidth = parseInt(config.barWidth, 10);
if (barWidth + 4 > cellWidth) barWidth = cellWidth - 4;
/*the half of distance between bars*/
var barOffset = Math.floor((cellWidth - barWidth) / 2);
var inner_gradient = config.gradient ? config.gradient : false;
/*draws a black line if the horizontal scale isn't defined*/
if (!xax) {
//scaleY = y-bottomPadding;
this._drawLine(ctx, point0.x, point1.y + 0.5, point1.x, point1.y + 0.5, "#edeff0", 1); //hardcoded color!
}
for (var i = 0; i < data.length; i++) {
var value = parseFloat(config.value(data[i] || 0));
if (this._logScaleCalc) value = this._log10(value);
/*start point (bottom left)*/
x0 = point0.x + barOffset + i * cellWidth;
var negValue = origin && value < 0;
if (!sIndex) {
y0 = xAxisY - 1;
data[i].$startY = y0;
if (origin) {
if (negValue) y0 = xAxisY + 1;
data[i].$startYN = xAxisY + 1;
}
} else {
y0 = negValue ? data[i].$startYN : data[i].$startY;
}
if (!value || isNaN(value)) continue;
/*adjusts the first tab to the scale*/
if (!sIndex && !origin) value -= minValue;
value *= valueFactor;
var border = config.border;
var label = config.label(data[i]);
/*the max height limit*/
if (y0 < point0.y + 1) continue;
var color = this._settings.color.call(this, data[i]);
var firstSector = Math.abs(y0 - (origin ? point1.y + minValue * unit : point1.y)) < 3;
/*drawing bar body*/
ctx.globalAlpha = config.alpha.call(this, data[i]);
ctx.fillStyle = ctx.strokeStyle = config.color.call(this, data[i]);
ctx.beginPath();
var y1 = y0 - unit * value + (firstSector ? negValue ? -1 : 1 : 0);
if (Math.floor(y1) > point1.y) {
y1 = point1.y;
if (label != "" && y1 - y0 < getTextSize("<div class=\"webix_canvas_text\">".concat(label, "</div>"), this.$view.className).height) label = "";
}
var points = this._setStakedBarPoints(ctx, x0 - (border ? 0.5 : 0), y0, barWidth + (border ? 0.5 : 0), y1, 0, point0.y);
ctx.fill();
ctx.stroke();
/*gradient*/
if (inner_gradient) {
ctx.save();
var gradParam = this._setBarGradient(ctx, x0, y0, x0 + barWidth, points[1], inner_gradient, color, "y");
ctx.fillStyle = gradParam.gradient;
ctx.beginPath();
points = this._setStakedBarPoints(ctx, x0 + gradParam.offset, y0, barWidth - gradParam.offset * 2, y1, border ? 1 : 0, point0.y);
ctx.fill();
ctx.restore();
}
/*drawing the gradient border of a bar*/
if (border) {
ctx.save();
if (typeof border == "string") ctx.strokeStyle = border;else this._setBorderStyles(ctx, color);
ctx.beginPath();
this._setStakedBarPoints(ctx, x0 - 0.5, parseInt(y0, 10) + 0.5, barWidth + 1, parseInt(y1, 10) + 0.5, 0, point0.y, firstSector);
ctx.stroke();
ctx.restore();
}
ctx.globalAlpha = 1;
/*sets a bar label*/
this.canvases[sIndex].renderTextAt(false, true, x0 + Math.floor(barWidth / 2), points[1] + (y0 - points[1]) / 2 - 7, label);
/*defines a map area for a bar*/
map.addRect(data[i].id, [x0 - point0.x, points[1] - point0.y, points[0] - point0.x, data[i][negValue ? "$startYN" : "$startY"] - point0.y], sIndex);
/*the start position for the next series*/
data[i][negValue ? "$startYN" : "$startY"] = points[1];
}
},
/**
* sets points for bar and returns the position of the bottom right point
* @param: ctx - canvas object
* @param: x0 - the x position of start point
* @param: y0 - the y position of start point
* @param: barWidth - bar width
* @param: radius - the rounding radius of the top
* @param: unit - the value defines the correspondence between item value and bar height
* @param: value - item value
* @param: offset - the offset from expected bar edge (necessary for drawing border)
* @param: minY - the minimum y position for the bars ()
*/
_setStakedBarPoints: function (ctx, x0, y0, barWidth, y1, offset$$1, minY, skipBottom) {
/*start*/
ctx.moveTo(x0, y0);
/*maximum height limit*/
if (y1 < minY) y1 = minY;
ctx.lineTo(x0, y1);
var x3 = x0 + barWidth;
var y3 = y1;
ctx.lineTo(x3, y3);
/*right rounding*/
/*bottom right point*/
var x5 = x0 + barWidth;
ctx.lineTo(x5, y0);
/*line to the start point*/
if (!skipBottom) {
ctx.lineTo(x0, y0);
} // ctx.lineTo(x0,0); //IE fix!
return [x5, y3];
}
};
var StackedBarHChart = {
/**
* renders a bar chart
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: x - the width of the container
* @param: y - the height of the container
* @param: sIndex - index of drawing chart
* @param: map - map object
*/
$render_stackedBarH: function (ctx, data, point0, point1, sIndex, map) {
var maxValue, minValue;
/*necessary if maxValue - minValue < 0*/
var valueFactor;
/*maxValue - minValue*/
var relValue;
var total_width = point1.x - point0.x;
var yax = !!this._settings.yAxis;
var limits = this._getStackedLimits(data);
maxValue = limits.max;
minValue = limits.min;
/*an available width for one bar*/
var cellWidth = Math.floor((point1.y - point0.y) / data.length);
/*draws x and y scales*/
if (!sIndex) this._drawHScales(ctx, data, point0, point1, minValue, maxValue, cellWidth);
/*necessary for automatic scale*/
if (yax) {
maxValue = parseFloat(this._settings.xAxis.end);
minValue = parseFloat(this._settings.xAxis.start);
}
/*unit calculation (bar_height = value*unit)*/
var relativeValues = this._getRelativeValue(minValue, maxValue);
relValue = relativeValues[0];
valueFactor = relativeValues[1];
var unit = relValue ? total_width / relValue : 10;
var startValue = 0;
if (!yax) {
/*defines start value for better representation of small values*/
startValue = 10;
unit = relValue ? (total_width - startValue) / relValue : 10;
}
/*a real bar width */
var barWidth = parseInt(this._settings.barWidth, 10);
if (barWidth + 4 > cellWidth) barWidth = cellWidth - 4;
/*the half of distance between bars*/
var barOffset = (cellWidth - barWidth) / 2;
/*the radius of rounding in the top part of each bar*/
var radius = 0;
var inner_gradient = false;
var gradient = this._settings.gradient;
if (gradient) {
inner_gradient = true;
}
/*draws a black line if the horizontal scale isn't defined*/
if (!yax) {
this._drawLine(ctx, point0.x - 0.5, point0.y, point0.x - 0.5, point1.y, "#edeff0", 1); //hardcoded color!
}
var seriesNumber = 0;
var seriesIndex = 0;
for (i = 0; i < this._series.length; i++) {
if (i == sIndex) {
seriesIndex = seriesNumber;
}
if (this._series[i].type == "stackedBarH") seriesNumber++;
}
for (var i = 0; i < data.length; i++) {
if (!seriesIndex) data[i].$startX = point0.x;
var value = Math.abs(parseFloat(this._settings.value(data[i] || 0)));
if (value > maxValue) value = maxValue;
value -= minValue;
value *= valueFactor;
/*start point (bottom left)*/
var x0 = point0.x;
var y0 = point0.y + barOffset + i * cellWidth;
if (!seriesIndex) data[i].$startX = x0;else x0 = data[i].$startX;
if (!value || isNaN(value)) continue;
/*takes start value into consideration*/
if (!yax) value += startValue / unit;
var color = this._settings.color.call(this, data[i]);
/*drawing bar body*/
ctx.globalAlpha = this._settings.alpha.call(this, data[i]);
ctx.fillStyle = this._settings.color.call(this, data[i]);
ctx.beginPath();
var points = this._setBarHPoints(ctx, x0, y0, barWidth, radius, unit, value, 0);
if (gradient && !inner_gradient) ctx.lineTo(point0.x + total_width, y0 + (this._settings.border ? 1 : 0)); //fix gradient sphreading
ctx.fill();
if (inner_gradient) {
var gradParam = this._setBarGradient(ctx, x0, y0 + barWidth, x0, y0, inner_gradient, color, "x");
ctx.fillStyle = gradParam.gradient;
ctx.beginPath();
points = this._setBarHPoints(ctx, x0, y0, barWidth, radius, unit, value, 0);
ctx.fill();
}
/*drawing the gradient border of a bar*/
if (this._settings.border) {
this._drawBarHBorder(ctx, x0, y0, barWidth, minValue, radius, unit, value, color);
}
ctx.globalAlpha = 1;
/*sets a bar label*/
this.canvases[sIndex].renderTextAt("middle", true, data[i].$startX + (points[0] - data[i].$startX) / 2 - 1, y0 + (points[1] - y0) / 2, this._settings.label(data[i]));
/*defines a map area for a bar*/
map.addRect(data[i].id, [data[i].$startX - point0.x, y0 - point0.y, points[0] - point0.x, points[1] - point0.y], sIndex);
/*the start position for the next series*/
data[i].$startX = points[0];
}
}
};
var Spline$1 = {
/**
* renders a spline chart
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: width - the width of the container
* @param: height - the height of the container
* @param: sIndex - index of drawing chart
*/
$render_spline: function (ctx, data, point0, point1, sIndex, map) {
var config, i, items, j, params, sparam, x, x0, x1, x2, y, y1, y2;
params = this._calculateLineParams(ctx, data, point0, point1, sIndex);
config = this._settings;
this._mapStart = point0;
/*array of all points*/
items = [];
/*drawing all items*/
if (data.length) {
/*getting all points*/
x0 = config.offset ? point0.x + params.cellWidth * 0.5 : point0.x;
for (i = 0; i < data.length; i++) {
y = this._getPointY(data[i], point0, point1, params);
if (y || y == "0") {
x = !i ? x0 : params.cellWidth * i - 0.5 + x0;
items.push({
x: x,
y: y,
v: this._settings.value(data[i]),
index: i
});
}
}
sparam = this._getSplineParameters(items);
for (i = 0; i < items.length; i++) {
x1 = items[i].x;
y1 = items[i].y;
if (i < items.length - 1) {
x2 = items[i + 1].x;
y2 = items[i + 1].y;
for (j = x1; j < x2; j++) {
var sY1 = this._getSplineYPoint(j, x1, i, sparam.a, sparam.b, sparam.c, sparam.d);
if (sY1 < point0.y) sY1 = point0.y;
if (sY1 > point1.y) sY1 = point1.y;
var sY2 = this._getSplineYPoint(j + 1, x1, i, sparam.a, sparam.b, sparam.c, sparam.d);
if (sY2 < point0.y) sY2 = point0.y;
if (sY2 > point1.y) sY2 = point1.y;
this._drawLine(ctx, j, sY1, j + 1, sY2, config.line.color(data[i]), config.line.width);
}
this._drawLine(ctx, x2 - 1, this._getSplineYPoint(j, x1, i, sparam.a, sparam.b, sparam.c, sparam.d), x2, y2, config.line.color(data[i]), config.line.width);
}
this._drawItem(ctx, x1, y1, data[items[i].index], config.label(data[items[i].index]), sIndex, map);
}
}
},
/*gets spline parameter*/
_getSplineParameters: function (points) {
var a,
b,
c,
d,
i,
s,
u,
v,
h = [],
m = [],
n = points.length;
for (i = 0; i < n - 1; i++) {
h[i] = points[i + 1].x - points[i].x;
m[i] = (points[i + 1].y - points[i].y) / h[i];
}
u = [];
v = [];
u[0] = 0;
u[1] = 2 * (h[0] + h[1]);
v[0] = 0;
v[1] = 6 * (m[1] - m[0]);
for (i = 2; i < n - 1; i++) {
u[i] = 2 * (h[i - 1] + h[i]) - h[i - 1] * h[i - 1] / u[i - 1];
v[i] = 6 * (m[i] - m[i - 1]) - h[i - 1] * v[i - 1] / u[i - 1];
}
s = [];
s[n - 1] = s[0] = 0;
for (i = n - 2; i >= 1; i--) {
s[i] = (v[i] - h[i] * s[i + 1]) / u[i];
}
a = [];
b = [];
c = [];
d = [];
for (i = 0; i < n - 1; i++) {
a[i] = points[i].y;
b[i] = -h[i] * s[i + 1] / 6 - h[i] * s[i] / 3 + (points[i + 1].y - points[i].y) / h[i];
c[i] = s[i] / 2;
d[i] = (s[i + 1] - s[i]) / (6 * h[i]);
}
for (i = 0; i < points.length - 1; i++) {
if (points[i].v === 0 && points[i + 1].v === 0) {
a[i] = points[i].y;
d[i] = c[i] = b[i] = 0;
}
}
return {
a: a,
b: b,
c: c,
d: d
};
},
/*returns the y position of the spline point */
_getSplineYPoint: function (x, xi, i, a, b, c, d) {
return a[i] + (x - xi) * (b[i] + (x - xi) * (c[i] + (x - xi) * d[i]));
}
};
var AreaChart = {
/**
* renders an area chart
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: width - the width of the container
* @param: height - the height of the container
* @param: sIndex - index of drawing chart
*/
$render_area: function (ctx, data, point0, point1, sIndex, map) {
var align, config, i, mapRect, obj, params, path, res1, res2, x0, x1, y1, x2, y2, y0;
params = this._calculateLineParams(ctx, data, point0, point1, sIndex);
config = this._settings; //the size of map area
mapRect = config.eventRadius || Math.floor(params.cellWidth / 2);
if (data.length) {
// area points
path = []; //the x position of the first item
x0 = !config.offset ? point0.x : point0.x + params.cellWidth * 0.5;
/*
iterates over all data items:
calculates [x,y] for area path, adds rect to chart map and renders labels
*/
for (i = 0; i < data.length; i++) {
obj = data[i];
res2 = this._getPointY(obj, point0, point1, params);
x2 = x0 + params.cellWidth * i;
if (res2) {
y2 = _typeof(res2) == "object" ? res2.y0 : res2;
if (i && this._settings.fixOverflow) {
res1 = this._getPointY(data[i - 1], point0, point1, params);
if (res1.out && res1.out == res2.out) {
continue;
}
x1 = params.cellWidth * (i - 1) - 0.5 + x0;
y1 = _typeof(res1) == "object" ? res1.y0 : res1;
if (res1.out) {
y0 = res1.out == "min" ? point1.y : point0.y;
path.push([this._calcOverflowX(x1, x2, y1, y2, y0), y0]);
}
if (res2.out) {
y0 = res2.out == "min" ? point1.y : point0.y;
path.push([this._calcOverflowX(x1, x2, y1, y2, y0), y0]);
if (i == data.length - 1 && y0 == point0.y) path.push([x2, point0.y]);
}
}
if (!res2.out) {
path.push([x2, y2]); //map
map.addRect(obj.id, [x2 - mapRect - point0.x, y2 - mapRect - point0.y, x2 + mapRect - point0.x, y2 + mapRect - point0.y], sIndex);
} //labels
if (!config.yAxis) {
align = !config.offset && i == data.length - 1 ? "left" : "center";
this.canvases[sIndex].renderTextAt(false, align, x2, y2 - config.labelOffset, config.label(obj));
}
}
}
if (path.length) {
path.push([x2, point1.y]);
path.push([path[0][0], point1.y]);
} //filling area
ctx.globalAlpha = this._settings.alpha.call(this, data[0]);
ctx.fillStyle = this._settings.color.call(this, data[0]);
ctx.beginPath();
this._path(ctx, path);
ctx.fill();
ctx.lineWidth = 1;
ctx.globalAlpha = 1; //border
if (config.border) {
ctx.lineWidth = config.borderWidth || 1;
if (config.borderColor) ctx.strokeStyle = config.borderColor.call(this, data[0]);else this._setBorderStyles(ctx, ctx.fillStyle);
ctx.beginPath();
this._path(ctx, path);
ctx.stroke();
}
}
},
/**
* renders an area chart
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: width - the width of the container
* @param: height - the height of the container
* @param: sIndex - index of drawing chart
*/
$render_stackedArea: function (ctx, data, point0, point1, sIndex, map) {
var a0, a1, align, config, i, j, lastItem, mapRect, obj, params, path, x, y, yPos;
params = this._calculateLineParams(ctx, data, point0, point1, sIndex);
config = this._settings;
/*the value that defines the map area position*/
mapRect = config.eventRadius || Math.floor(params.cellWidth / 2);
/*drawing all items*/
if (data.length) {
// area points
path = []; // y item positions
yPos = []; //the x position of the first item
x = !config.offset ? point0.x : point0.x + params.cellWidth * 0.5;
var setOffset = function (i, y) {
return sIndex ? data[i].$startY ? y - point1.y + data[i].$startY : 0 : y;
};
var solveEquation = function (x, p0, p1) {
var k = (p1.y - p0.y) / (p1.x - p0.x);
return k * x + p0.y - k * p0.x;
};
/*
iterates over all data items:
calculates [x,y] for area path, adds rect to chart map and renders labels
*/
for (i = 0; i < data.length; i++) {
obj = data[i];
if (!i) {
y = setOffset(i, point1.y);
path.push([x, y]);
} else {
x += params.cellWidth;
}
y = setOffset(i, this._getPointY(obj, point0, point1, params));
yPos.push(isNaN(y) && !i ? data[i].$startY || point1.y : y);
if (y) {
path.push([x, y]); //map
map.addRect(obj.id, [x - mapRect - point0.x, y - mapRect - point0.y, x + mapRect - point0.x, y + mapRect - point0.y], sIndex); //labels
if (!config.yAxis) {
align = !config.offset && lastItem ? "left" : "center";
this.canvases[sIndex].renderTextAt(false, align, x, y - config.labelOffset, config.label(obj));
}
}
} // bottom right point
path.push([x, setOffset(i - 1, point1.y)]); // lower border from the end to start
if (sIndex) {
for (i = data.length - 2; i > 0; i--) {
x -= params.cellWidth;
y = data[i].$startY;
if (y) path.push([x, y]);
}
} // go to start point
path.push([path[0][0], path[0][1]]); // filling path
ctx.globalAlpha = this._settings.alpha.call(this, data[0]);
ctx.fillStyle = this._settings.color.call(this, data[0]);
ctx.beginPath();
this._path(ctx, path);
ctx.fill(); // set y positions of the next series
for (i = 0; i < data.length; i++) {
y = yPos[i];
if (!y) {
if (i == data.length - 1) {
y = data[i].$startY;
}
for (j = i + 1; j < data.length; j++) {
if (yPos[j]) {
a0 = {
x: point0.x,
y: yPos[0]
};
a1 = {
x: point0.x + params.cellWidth * j,
y: yPos[j]
};
y = solveEquation(point0.x + params.cellWidth * i, a0, a1);
break;
}
}
}
data[i].$startY = y;
}
}
}
};
var Radar = {
$render_radar: function (ctx, data, x, y, sIndex, map) {
this._renderRadarChart(ctx, data, x, y, sIndex, map);
},
/**
* renders a pie chart
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: x - the width of the container
* @param: y - the height of the container
* @param: ky - value from 0 to 1 that defines an angle of inclination (0<ky<1 - 3D chart)
*/
_renderRadarChart: function (ctx, data, point0, point1, sIndex, map) {
if (!data.length) return;
var coord = this._getPieParameters(point0, point1);
/*scale radius*/
var radius = this._settings.radius ? this._settings.radius : coord.radius;
/*scale center*/
var x0 = this._settings.x ? this._settings.x : coord.x;
var y0 = this._settings.y ? this._settings.y : coord.y;
/*angles for each unit*/
var ratioUnits = [];
for (var i = 0; i < data.length; i++) {
ratioUnits.push(1);
}
var ratios = this._getRatios(ratioUnits, data.length);
this._mapStart = point0;
if (!sIndex) this._drawRadarAxises(ratios, x0, y0, radius, data);
this._drawRadarData(ctx, ratios, x0, y0, radius, data, sIndex, map);
},
_drawRadarData: function (ctx, ratios, x, y, radius, data, sIndex, map) {
var alpha0, alpha1, config, i, min, max, pos0, pos1, posArr, r0, r1, relValue, startAlpha, value, value0, value1, valueFactor, unit, unitArr;
config = this._settings;
/*unit calculation (item_radius_pos = value*unit)*/
min = config.yAxis.start;
max = config.yAxis.end;
unitArr = this._getRelativeValue(min, max);
relValue = unitArr[0];
unit = relValue ? radius / relValue : radius / 2;
valueFactor = unitArr[1];
startAlpha = -Math.PI / 2;
alpha0 = alpha1 = startAlpha;
posArr = [];
pos1 = 0;
for (i = 0; i < data.length; i++) {
if (!value1) {
value = config.value(data[i]);
if (this._logScaleCalc) value = this._log10(value);
/*a relative value*/
value0 = (parseFloat(value || 0) - min) * valueFactor;
} else value0 = value1;
r0 = Math.floor(unit * value0);
value = config.value(i != data.length - 1 ? data[i + 1] : data[0]);
if (this._logScaleCalc) value = this._log10(value);
value1 = (parseFloat(value || 0) - min) * valueFactor;
r1 = Math.floor(unit * value1);
alpha0 = alpha1;
alpha1 = i != data.length - 1 ? startAlpha + ratios[i] - 0.0001 : startAlpha;
pos0 = pos1 || this._getPositionByAngle(alpha0, x, y, r0);
pos1 = this._getPositionByAngle(alpha1, x, y, r1);
/*creates map area*/
/*areaWidth = (config.eventRadius||(parseInt(config.item.radius.call(this,data[i]),10)+config.item.borderWidth));
map.addRect(data[i].id,[pos0.x-areaWidth,pos0.y-areaWidth,pos0.x+areaWidth,pos0.y+areaWidth],sIndex);*/
//this._drawLine(ctx,pos0.x,pos0.y,pos1.x,pos1.y,config.line.color.call(this,data[i]),config.line.width)
posArr.push(pos0);
}
if (config.fill) this._fillRadarChart(ctx, posArr, data);
if (!config.disableLines && data.length > 2) this._strokeRadarChart(ctx, posArr, data);
if (!config.disableItems || data.length < 3) this._drawRadarItemMarkers(ctx, posArr, data, sIndex, map);
posArr = null;
},
_drawRadarItemMarkers: function (ctx, points, data, sIndex, map) {
for (var i = 0; i < points.length; i++) {
this._drawItem(ctx, points[i].x, points[i].y, data[i], this._settings.label.call(this, data), sIndex, map);
}
},
_fillRadarChart: function (ctx, points, data) {
var pos0, pos1;
ctx.globalAlpha = this._settings.alpha.call(this, {});
ctx.beginPath();
for (var i = 0; i < points.length; i++) {
ctx.fillStyle = this._settings.fill.call(this, data[i]);
pos0 = points[i];
pos1 = points[i + 1] || points[0];
if (!i) {
ctx.moveTo(pos0.x, pos0.y);
}
ctx.lineTo(pos1.x, pos1.y);
}
ctx.fill();
ctx.globalAlpha = 1;
},
_strokeRadarChart: function (ctx, points, data) {
var pos0, pos1;
for (var i = 0; i < points.length; i++) {
pos0 = points[i];
pos1 = points[i + 1] || points[0];
this._drawLine(ctx, pos0.x, pos0.y, pos1.x, pos1.y, this._settings.line.color.call(this, data[i]), this._settings.line.width);
}
},
_drawRadarAxises: function (ratios, x, y, radius, data) {
var configY = this._settings.yAxis;
var configX = this._settings.xAxis;
var start = configY.start;
var end = configY.end;
var step = configY.step;
var scaleParam = {};
var config = this._configYAxis;
if (typeof config.step == "undefined" || typeof config.start == "undefined" || typeof config.end == "undefined") {
var limits = this._getLimits();
scaleParam = this._calculateScale(limits.min, limits.max);
start = scaleParam.start;
end = scaleParam.end;
step = scaleParam.step;
configY.end = end;
configY.start = start;
}
var units = [];
var i, j, p;
var c = 0;
var stepHeight = radius * step / (end - start);
/*correction for small step*/
var power, corr;
if (step < 1) {
power = Math.min(this._log10(step), start <= 0 ? 0 : this._log10(start));
corr = Math.pow(10, -power);
}
var angles = [];
if (!this.canvases["scale"]) this.canvases["scale"] = this._createCanvas("radar_scale");
var ctx = this.canvases["scale"].getCanvas();
for (i = end; i >= start; i -= step) {
var value = this._logScaleCalc ? Math.pow(10, i) : i;
if (scaleParam.fixNum) value = parseFloat(i).toFixed(scaleParam.fixNum);
units.push(Math.floor(c * stepHeight) + 0.5);
if (corr && !this._logScaleCalc) {
value = Math.round(value * corr) / corr;
i = value;
}
var unitY = y - radius + units[units.length - 1];
this.canvases["scale"].renderTextAt("middle", "left", x, unitY, configY.template(value.toString()), "webix_axis_item_y webix_radar");
var startAlpha = -Math.PI / 2;
/*possibly need to moved in config*/
var alpha0 = startAlpha;
var alpha1;
for (j = 0; j < ratios.length; j++) {
if (!c) angles.push(alpha0);
alpha1 = startAlpha + ratios[j] - 0.0001;
this._drawScaleSector(ctx, ratios.length > 2 ? config.lineShape || "line" : "arc", x, y, radius - units[units.length - 1], alpha0, alpha1, i, j, data[i]);
alpha0 = alpha1;
}
c++;
}
/*renders radius lines and labels*/
for (i = 0; i < angles.length; i++) {
p = this._getPositionByAngle(angles[i], x, y, radius);
if (configX) {
if (configX.lines.call(this, data[i], i)) this._drawLine(ctx, x, y, p.x, p.y, configX.lineColor.call(this, data[i]), 1);
this._drawRadarScaleLabel(ctx, x, y, radius, angles[i], configX.template.call(this, data[i]));
}
}
},
_drawScaleSector: function (ctx, shape, x, y, radius, a1, a2, i, j) {
var pos1, pos2;
if (radius < 0) return false;
pos1 = this._getPositionByAngle(a1, x, y, radius);
pos2 = this._getPositionByAngle(a2, x, y, radius);
var configY = this._settings.yAxis;
if (configY.bg) {
ctx.beginPath();
ctx.moveTo(x, y);
if (shape == "arc") ctx.arc(x, y, radius, a1, a2, false);else {
ctx.lineTo(pos1.x, pos1.y);
ctx.lineTo(pos2.x, pos2.y);
}
ctx.fillStyle = configY.bg(i, j);
ctx.moveTo(x, y);
ctx.fill();
ctx.closePath();
}
if (configY.lines.call(this, i)) {
ctx.lineWidth = 1;
ctx.beginPath();
if (shape == "arc") ctx.arc(x, y, radius, a1, a2, false);else {
ctx.moveTo(pos1.x, pos1.y);
ctx.lineTo(pos2.x, pos2.y);
}
ctx.strokeStyle = configY.lineColor.call(this, i);
ctx.stroke();
}
},
_drawRadarScaleLabel: function (ctx, x, y, r, a, text) {
if (!text) return false;
var t = this.canvases["scale"].renderText(0, 0, text, "webix_axis_radar_title", 1);
var width = t.scrollWidth;
var height = t.offsetHeight;
var delta = 0.001;
var pos = this._getPositionByAngle(a, x, y, r + 5);
var corr_x = 0,
corr_y = 0;
if (a < 0 || a > Math.PI) {
corr_y = -height;
}
if (a > Math.PI / 2) {
corr_x = -width;
}
if (Math.abs(a + Math.PI / 2) < delta || Math.abs(a - Math.PI / 2) < delta) {
corr_x = -width / 2;
} else if (Math.abs(a) < delta || Math.abs(a - Math.PI) < delta) {
corr_y = -height / 2;
}
t.style.top = pos.y + corr_y + "px";
t.style.left = pos.x + corr_x + "px";
t.style.width = width + "px";
t.style.whiteSpace = "nowrap";
}
};
var Scatter = {
/**
* renders a graphic
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: point0 - top left point of a chart
* @param: point1 - right bottom point of a chart
* @param: sIndex - index of drawing chart
* @param: map - map object
*/
$render_scatter: function (ctx, data, point0, point1, sIndex, map) {
if (!this._settings.xValue) return;
var config = this._settings;
var lines = !(config.disableLines || typeof config.disableLines == "undefined");
/*max in min values*/
var limitsY = this._getLimits();
var limitsX = this._getLimits("h", "xValue");
/*render scale*/
if (!sIndex) {
if (!this.canvases["x"]) this.canvases["x"] = this._createCanvas("axis_x");
if (!this.canvases["y"]) this.canvases["y"] = this._createCanvas("axis_y");
this._drawYAxis(this.canvases["y"].getCanvas(), data, point0, point1, limitsY.min, limitsY.max);
this._drawHXAxis(this.canvases["x"].getCanvas(), data, point0, point1, limitsX.min, limitsX.max);
}
limitsY = {
min: config.yAxis.start,
max: config.yAxis.end
};
limitsX = {
min: config.xAxis.start,
max: config.xAxis.end
};
var params = this._getScatterParams(ctx, data, point0, point1, limitsX, limitsY);
this._mapStart = point0;
var items = [];
for (var i = 0; i < data.length; i++) {
var x = this._calculateScatterItemPosition(params, point1, point0, limitsX, data[i], "X");
var y = this._calculateScatterItemPosition(params, point0, point1, limitsY, data[i], "Y");
if (isNaN(x) || isNaN(y)) continue;
items.push({
x: x,
y: y,
index: i
});
}
var x1, y1, x2, y2, di;
for (var _i = 0; _i < items.length; _i++) {
di = items[_i].index;
if (lines) {
var color = config.line.color.call(this, data[di]); //line start position
x1 = items[_i].x;
y1 = items[_i].y;
if (_i == items.length - 1) {
//connecting last and first items
if (config.shape && items.length > 2) {
this._drawLine(ctx, x2, y2, items[0].x, items[0].y, color, config.line.width); //render shape on top of the line
if (!config.disableItems) this._drawScatterItem(ctx, map, items[0], data[0], sIndex);
if (config.fill) this._fillScatterChart(ctx, items, data);
}
} else {
// line between two points
x2 = items[_i + 1].x;
y2 = items[_i + 1].y;
this._drawLine(ctx, x1, y1, x2, y2, color, config.line.width);
}
} //item
if (!config.disableItems && items[_i]) {
this._drawScatterItem(ctx, map, items[_i], data[di], sIndex);
}
}
},
_fillScatterChart: function (ctx, points, data) {
var pos0, pos1;
ctx.globalAlpha = this._settings.alpha.call(this, {});
ctx.beginPath();
for (var i = 0; i < points.length; i++) {
ctx.fillStyle = this._settings.fill.call(this, data[i]);
pos0 = points[i];
pos1 = points[i + 1] || points[0];
if (!i) {
ctx.moveTo(pos0.x, pos0.y);
}
ctx.lineTo(pos1.x, pos1.y);
}
ctx.fill();
ctx.globalAlpha = 1;
},
_getScatterParams: function (ctx, data, point0, point1, limitsX, limitsY) {
var params = {};
/*available space*/
params.totalHeight = point1.y - point0.y;
/*available width*/
params.totalWidth = point1.x - point0.x;
/*unit calculation (y_position = value*unit)*/
this._calcScatterUnit(params, limitsX.min, limitsX.max, params.totalWidth, "X");
this._calcScatterUnit(params, limitsY.min, limitsY.max, params.totalHeight, "Y");
return params;
},
_drawScatterItem: function (ctx, map, item, obj, sIndex) {
this._drawItem(ctx, item.x, item.y, obj, this._settings.label.call(this, obj), sIndex, map);
},
_calculateScatterItemPosition: function (params, point0, point1, limits, obj, axis) {
/*the real value of an object*/
var value = this._settings[axis == "X" ? "xValue" : "value"].call(this, obj);
/*a relative value*/
var valueFactor = params["valueFactor" + axis];
var v = (parseFloat(value || 0) - limits.min) * valueFactor;
/*a vertical coordinate*/
var unit = params["unit" + axis];
var pos = point1[axis.toLowerCase()] - (axis == "X" ? -1 : 1) * Math.floor(unit * v);
/*the limit of the minimum value is the minimum visible value*/
if (v < 0) pos = point1[axis.toLowerCase()];
/*the limit of the maximum value*/
if (value > limits.max) pos = point0[axis.toLowerCase()];
/*the limit of the minimum value*/
if (value < limits.min) pos = point1[axis.toLowerCase()];
return pos;
},
_calcScatterUnit: function (p, min, max, size, axis) {
var relativeValues = this._getRelativeValue(min, max);
axis = axis || "";
p["relValue" + axis] = relativeValues[0];
p["valueFactor" + axis] = relativeValues[1];
p["unit" + axis] = p["relValue" + axis] ? size / p["relValue" + axis] : 10;
}
};
var Presets = {
presets: {
"simple": {
item: {
borderColor: "#ffffff",
color: "#2b7100",
shadow: false,
borderWidth: 2
},
line: {
color: "#8ecf03",
width: 2
}
},
"plot": {
color: "#8664C6",
item: {
borderColor: "#8664C6",
borderWidth: 1,
color: "#ffffff",
type: "r",
shadow: false
},
line: {
color: "#8664C6",
width: 2
}
},
"diamond": {
color: "#FF5C4C",
item: {
borderColor: "#FF5C4C",
color: "#FF5C4C",
type: "d",
radius: 3,
shadow: true
},
line: {
color: "#FF5C4C",
width: 2
}
},
"point": {
color: "#1ca1c1",
disableLines: true,
fill: false,
disableItems: false,
item: {
color: "#1ca1c1",
borderColor: "#1ca1c1",
radius: 2,
borderWidth: 2,
type: "r"
},
alpha: 1
},
"line": {
line: {
color: "#1ca1c1",
width: 2
},
item: {
color: "#ffffff",
borderColor: "#1ca1c1",
radius: 2,
borderWidth: 2,
type: "d"
},
fill: false,
disableItems: false,
disableLines: false,
alpha: 1
},
"area": {
fill: "#1ca1c1",
line: {
color: "#1ca1c1",
width: 1
},
disableItems: true,
alpha: 0.2,
disableLines: false
},
"round": {
item: {
radius: 3,
borderColor: "#1ca1c1",
borderWidth: 1,
color: "#1ca1c1",
type: "r",
shadow: false,
alpha: 0.6
}
},
"square": {
item: {
radius: 3,
borderColor: "#00a497",
borderWidth: 2,
color: "#ffffff",
type: "s",
shadow: false,
alpha: 1
},
line: {
color: "#00a497"
}
},
/*bar*/
"column": {
color: "RAINBOW",
gradient: false,
barWidth: 45,
radius: 0,
alpha: 1,
border: true
},
"stick": {
barWidth: 5,
gradient: false,
color: "#1ca1c1",
radius: 2,
alpha: 1,
border: false
},
"alpha": {
color: "#b9a8f9",
barWidth: 70,
gradient: "falling",
radius: 0,
alpha: 0.5,
border: true
}
}
};
var SplineArea$1 = {
/**
* renders an splineArea chart
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: width - the width of the container
* @param: height - the height of the container
* @param: sIndex - index of drawing chart
*/
$render_splineArea: function (ctx, data, point0, point1, sIndex, map) {
var color,
i,
items,
j,
mapRect,
params,
sParams,
x,
x0,
x1,
x2,
y,
y2,
config = this._settings,
path = [];
params = this._calculateLineParams(ctx, data, point0, point1, sIndex);
mapRect = config.eventRadius || Math.floor(params.cellWidth / 2);
/*array of all points*/
items = [];
if (data.length) {
/*getting all points*/
x0 = point0.x;
for (i = 0; i < data.length; i++) {
y = this._getPointY(data[i], point0, point1, params);
if (y || y == "0") {
x = !i ? x0 : params.cellWidth * i - 0.5 + x0;
items.push({
x: x,
y: y,
index: i
});
map.addRect(data[i].id, [x - mapRect - point0.x, y - mapRect - point0.y, x + mapRect - point0.x, y + mapRect - point0.y], sIndex);
}
}
sParams = this._getSplineParameters(items);
for (i = 0; i < items.length; i++) {
x1 = items[i].x;
if (i < items.length - 1) {
x2 = items[i + 1].x;
y2 = items[i + 1].y;
for (j = x1; j < x2; j++) {
var sY1 = this._getSplineYPoint(j, x1, i, sParams.a, sParams.b, sParams.c, sParams.d);
if (sY1 < point0.y) sY1 = point0.y;
if (sY1 > point1.y) sY1 = point1.y;
var sY2 = this._getSplineYPoint(j + 1, x1, i, sParams.a, sParams.b, sParams.c, sParams.d);
if (sY2 < point0.y) sY2 = point0.y;
if (sY2 > point1.y) sY2 = point1.y;
path.push([j, sY1]);
path.push([j + 1, sY2]);
}
path.push([x2, y2]);
}
}
color = this._settings.color.call(this, data[0]);
if (path.length) {
path.push([x2, point1.y]);
path.push([path[0][0], point1.y]);
} //filling area
ctx.globalAlpha = this._settings.alpha.call(this, data[0]);
ctx.fillStyle = color;
ctx.beginPath();
this._path(ctx, path);
ctx.fill();
ctx.lineWidth = 1;
ctx.globalAlpha = 1; // draw line
if (config.border) {
ctx.lineWidth = config.borderWidth || 1;
if (config.borderColor) ctx.strokeStyle = config.borderColor.call(this, data[0]);else this._setBorderStyles(ctx, color);
ctx.beginPath();
path.splice(path.length - 3);
this._path(ctx, path);
ctx.stroke();
}
}
}
};
var animateDuration = 400,
cellWidth = 30;
var DynamicChart = {
dynamic_setter: function (value) {
if (value) init(this);
return value;
}
};
/**
* Sets event handlers and properties for a stock chart
* @param {object} chart - chart view
*/
function init(chart) {
if (chart._stockRenderHandler) return;
var config = chart._settings;
if (!config.cellWidth) config.cellWidth = cellWidth;
if (!config.animateDuration) config.animateDuration = animateDuration;
config.offset = false;
chart._stockRenderHandler = chart.attachEvent("onBeforeRender", function (data, type) {
var bounds = chart._getChartBounds(chart._content_width, chart._content_height);
resizeStockCanvases(chart);
filterStockData(data, bounds.start, bounds.end, config.cellWidth);
if (type == "add") startAnimation(chart);
});
chart._stockXAxisHandler = chart.attachEvent("onBeforeXAxis", function (ctx, data, point0, point1, cellWidth, y) {
drawXAxis(chart, ctx, data, point0, point1, cellWidth, y);
return false;
});
}
/**
* Starts stock animation
* @param {object} chart - chart view
*/
function startAnimation(chart) {
var cellWidth = chart._settings.cellWidth;
if (chart._stockAnimationOffset != cellWidth) {
chart._stockAnimationOffset = cellWidth;
chart.render();
}
chart._stockAnimationOffset = 0;
chart._stockAnimationStart = null;
if (window.requestAnimationFrame && !document.hidden) window.requestAnimationFrame(function (t) {
animate$2(chart, t);
});
if (!chart._stockAnimateHandler) chart._stockAnimateHandler = chart.attachEvent("onAfterRender", function (data) {
applyStockOffset(chart, data);
});
}
/**
* Animates a chart
* @param {object} chart - chart view
* @param {number} timestamp - timestamp
*/
function animate$2(chart, timestamp) {
var progress,
duration = chart._settings.animateDuration,
cellWidth = chart._settings.cellWidth;
if (cellWidth && chart.count() > 1) {
if (!chart._stockAnimationStart) chart._stockAnimationStart = timestamp;
progress = timestamp - chart._stockAnimationStart;
chart._stockAnimationOffset = Math.min(Math.max(progress / duration * cellWidth, 1), cellWidth);
chart.render();
if (progress < duration) window.requestAnimationFrame(function (t) {
animate$2(chart, t);
});
}
}
/**
* Applies animation offset to "series" and "x-axis" canvases
* @param {object} chart - chart view
* @param {object} data - data array
*/
function applyStockOffset(chart, data) {
var count = chart.count(),
bounds = chart._getChartBounds(chart._content_width, chart._content_height),
cellWidth = chart._settings.cellWidth,
offset$$1 = chart._stockAnimationOffset || 0,
isScroll = data.length < count || (data.length - 1) * cellWidth > bounds.end.x - bounds.start.x;
function setCanvasOffset(canvas, x0, x1, skipRight) {
var ctx = canvas.getCanvas(),
elem = canvas._canvas,
labels = canvas._canvas_labels,
series = canvas._canvas_series; // if we need to display less values than they are
if (offset$$1 && (data.length < count || (data.length - 1) * cellWidth > x1 - x0)) {
// move canvas to the left
elem.style.left = -offset$$1 + "px";
if (data.length > 1) {
setLabelsOffset(labels, offset$$1, series); // clear out of the scale parts
ctx.clearRect(0, 0, x0 + offset$$1, elem.offsetHeight);
ctx.clearRect(x1 + offset$$1, 0, elem.offsetWidth, elem.offsetHeight);
}
} // animation for the right part (added item)
else {
elem.style.left = "0px";
if (!skipRight && offset$$1 != cellWidth) ctx.clearRect(x0 + (data.length - 1) * cellWidth - cellWidth + offset$$1, 0, elem.offsetWidth, elem.offsetHeight);
} // show label for the last label after finishing animation
if (labels.length > 1 && offset$$1 && offset$$1 != cellWidth) {
var last = labels.length - 1;
if (isAxisTitle(series, labels[last])) last -= 1;
labels[last].style.display = "none";
}
}
eachStockCanvas(chart, function (name, canvas) {
setCanvasOffset(canvas, bounds.start.x, bounds.end.x, name == "x");
});
setHtmlMapSizes(chart, bounds, isScroll ? offset$$1 : 0);
}
function isAxisTitle(series, label) {
return series === "axis_x" && label.className.indexOf("webix_axis_title_x") !== -1;
}
function setLabelsOffset(labels, offset$$1, series) {
if (labels.length) {
remove(labels[0]);
for (var i = 1; i < labels.length; i++) {
//don't move axis title
if (isAxisTitle(series, labels[i])) continue;
labels[i].style.left = labels[i].offsetLeft - offset$$1 + "px";
}
}
}
/**
* Gets visible chart data
* @param {object} data - an array with all chart data
* @param {object} point0 - a top left point of a plot
* @param {object} point1 - a bottom right point of a plot
* @param {number} cellWidth - a unit width
*/
function filterStockData(data, point0, point1, cellWidth) {
if (cellWidth && data.length) {
var limit = Math.ceil((point1.x - point0.x) / cellWidth);
if (data.length > limit + 1) data.splice(0, data.length - limit - 1);
}
}
/**
* Calls a function for "series" and "x-axis" canvases
* @param {object} chart - chart view
* @param {function} func - function to call
*/
function eachStockCanvas(chart, func) {
if (chart.canvases) {
for (var i = 0; i < chart._series.length; i++) {
if (chart.canvases[i]) func(i, chart.canvases[i]);
}
if (chart.canvases["x"]) func("x", chart.canvases["x"]);
}
}
/**
* Set sizes for animated canvases
* @param {object} chart - chart view
*/
function resizeStockCanvases(chart) {
eachStockCanvas(chart, function (name, canvas) {
canvas._resizeCanvas(chart._content_width + 2 * chart._settings.cellWidth, chart._content_height);
});
}
/**
* Set sizes for an html map of a chart
* @param {object} chart - a chart view
* @param {object} bounds - start and end points of a plot
* @param {number} offset - an offset to apply
*/
function setHtmlMapSizes(chart, bounds, offset$$1) {
chart._contentobj._htmlmap.style.left = bounds.start.x - offset$$1 + "px";
chart._contentobj._htmlmap.style.width = bounds.end.x - bounds.start.x + offset$$1 + "px";
}
/**
* Renders lines and labels of an x-axis
* @param {object} chart - a chart view
* @param {object} ctx - a canvas Context
* @param {object} data - a data array
* @param {object} point0 - a top left point of a plot
* @param {object} point1 - a bottom right point of a plot
* @param {number} cellWidth - a width of a unit
* @param {number} y - the vertical position of an "x-axis" line
*/
function drawXAxis(chart, ctx, data, point0, point1, cellWidth, y) {
var center,
i,
isScroll,
unitPos,
config = chart._settings,
x0 = point0.x - 0.5,
y0 = parseInt(y ? y : point1.y, 10) + 0.5,
x1 = point1.x;
if (!config.dynamic) return false;
isScroll = (data.length - 1) * cellWidth > x1 - x0 || data.length < chart.count();
for (i = 0; i < data.length; i++) {
unitPos = x0 + i * cellWidth;
center = isScroll ? i > 1 : !!i;
unitPos = Math.ceil(unitPos) - 0.5; //scale labels
chart._drawXAxisLabel(unitPos, y0, data[i], center); //draws a vertical line for the horizontal scale
if (i && config.xAxis.lines.call(chart, data[i])) chart._drawXAxisLine(ctx, unitPos, point1.y, point0.y, data[i]);
}
chart.canvases["x"].renderTextAt(true, false, x0, point1.y + config.padding.bottom - 3, config.xAxis.title, "webix_axis_title_x", point1.x - point0.x);
chart._drawLine(ctx, x0, y0, x1 + (isScroll ? chart._stockAnimationOffset : 0), y0, config.xAxis.color, 1);
}
var api$10 = {
name: "chart",
$init: function (config) {
this._series = [this._settings];
this._legend_labels = [];
this._contentobj.className += " webix_chart";
this.$ready.push(this._after_init_call);
/*preset*/
if (config.preset) {
this._definePreset(config);
} // move series to end of configuration properties hash
// so it will be parsed after other settings
if (config.series) {
var series = config.series;
delete config.series;
config.series = series;
}
this.data.provideApi(this, true);
},
_after_init_call: function () {
this.data.attachEvent("onStoreUpdated", bind(function () {
this.render.apply(this, arguments);
}, this));
},
defaults: {
ariaLabel: "chart",
color: "default",
alpha: "1",
radius: 0,
label: false,
value: "{obj.value}",
padding: {},
type: "pie",
lineColor: "#ffffff",
cant: 0.5,
barWidth: 30,
line: {
width: 2,
color: "#1ca1c1"
},
item: {
radius: 3,
borderColor: "#1ca1c1",
borderWidth: 2,
color: "#ffffff",
alpha: 1,
type: "r",
shadow: false
},
shadow: false,
gradient: false,
border: false,
labelOffset: 20,
origin: "auto",
scale: "linear"
},
_id:
/*@attr*/
"webix_area_id",
on_click: {
webix_chart_legend_item: function (e, id, obj) {
var series = obj.getAttribute(
/*@attr*/
"series_id");
if (this.callEvent("onLegendClick", [e, series, obj])) {
if (typeof series != "undefined" && this._series.length > 1) {
var config = this._settings;
var values = config.legend.values;
var toggle = values && values[series].toggle || config.legend.toggle; // hide action
if (toggle) {
if (obj.className.indexOf("hidden") != -1) {
this.showSeries(series);
} else {
this.hideSeries(series);
}
}
}
}
}
},
on_dblclick: {},
on_mouse_move: {},
locate: function (e) {
return locate(e, this._id);
},
$setSize: function (x, y) {
var res = base$1.api.$setSize.call(this, x, y);
if (res) {
for (var c in this.canvases) {
this.canvases[c]._resizeCanvas(this._content_width, this._content_height);
}
this.render();
}
return res;
},
type_setter: function (val) {
assert(this["$render_" + val], "Chart type is not supported, or extension is not loaded: " + val);
if (typeof this._settings.offset == "undefined") {
this._settings.offset = !(val.toLowerCase().indexOf("area") != -1);
}
if (val == "radar" && !this._settings.yAxis) this.define("yAxis", {});
if (val == "scatter") {
if (!this._settings.yAxis) this.define("yAxis", {});
if (!this._settings.xAxis) this.define("xAxis", {});
}
return val;
},
destructor: function () {
this.removeAllSeries();
Destruction.destructor.apply(this, arguments);
},
removeAllSeries: function () {
this.clearCanvas();
if (this._legendObj) {
this._legendObj.innerHTML = "";
this._legendObj.parentNode.removeChild(this._legendObj);
this._legendObj = null;
}
if (this.canvases) {
this.canvases = {};
}
this._contentobj.innerHTML = "";
this._series = [];
},
clearCanvas: function () {
if (this.canvases && _typeof(this.canvases) == "object") for (var c in this.canvases) {
this.canvases[c].clearCanvas();
}
},
render: function (id, changes, type) {
var bounds, data, map, temp;
if (!this.isVisible(this._settings.id)) return;
data = this._getChartData();
if (!this.callEvent("onBeforeRender", [data, type])) return;
if (this.canvases && _typeof(this.canvases) == "object") {
for (var i in this.canvases) {
this.canvases[i].clearCanvas();
}
} else this.canvases = {};
if (this._settings.legend) {
if (!this.canvases["legend"]) this.canvases["legend"] = this._createCanvas("legend");
this._drawLegend(this.data.getRange(), this._content_width, this._content_height);
}
this._map = map = new HtmlMap(this._id);
temp = this._settings;
bounds = this._getChartBounds(this._content_width, this._content_height);
if (this._series) {
for (var _i = 0; _i < this._series.length; _i++) {
this._settings = this._series[_i];
if (!this.canvases[_i]) this.canvases[_i] = this._createCanvas(this.name + " " + _i, "z-index:" + (2 + _i), null, _i, this._settings.ariaLabel);
this["$render_" + this._settings.type](this.canvases[_i].getCanvas(), data, bounds.start, bounds.end, _i, map);
}
}
map.render(this._contentobj);
this._contentobj.lastChild.style.zIndex = 80;
this._applyBounds(this._contentobj.lastChild, bounds);
this.callEvent("onAfterRender", [data]);
this._settings = temp; // hide hidden series
if (this._settings.legend && this._settings.legend.values) {
var series = this._settings.legend.values;
for (var _i2 = 0; _i2 < series.length; _i2++) {
if (series[_i2].$hidden) this.hideSeries(_i2);
}
}
},
_applyBounds: function (elem, bounds) {
var style = {};
style.left = bounds.start.x;
style.top = bounds.start.y;
style.width = bounds.end.x - bounds.start.x;
style.height = bounds.end.y - bounds.start.y;
for (var prop in style) {
elem.style[prop] = style[prop] + "px";
}
},
_getChartData: function () {
var axis, axisConfig, config, data, i, newData, start, units, value, valuesHash;
data = this.data.getRange();
axis = this._settings.type.toLowerCase().indexOf("barh") != -1 ? "yAxis" : "xAxis";
axisConfig = this._settings[axis];
if (axisConfig && axisConfig.units && _typeof(axisConfig.units) == "object") {
config = axisConfig.units;
units = [];
if (typeof config.start != "undefined" && typeof config.end != "undefined" && typeof config.next != "undefined") {
start = config.start;
while (start <= config.end) {
units.push(start);
start = config.next.call(this, start);
}
} else if (Object.prototype.toString.call(config) === "[object Array]") {
units = config;
}
newData = [];
if (units.length) {
value = axisConfig.value;
valuesHash = {};
for (i = 0; i < data.length; i++) {
valuesHash[value(data[i])] = i;
}
for (i = 0; i < units.length; i++) {
if (typeof valuesHash[units[i]] != "undefined") {
data[valuesHash[units[i]]].$unit = units[i];
newData.push(data[valuesHash[units[i]]]);
} else {
newData.push({
$unit: units[i]
});
}
}
}
return newData;
}
return data;
},
series_setter: function (config) {
if (!config || _typeof(config) != "object") {
assert(config, "Chart :: Series must be an array or object");
} else {
this._parseSettings(!config.length ? config : config[0]);
this._series = [this._settings];
for (var i = 1; i < config.length; i++) {
this.addSeries(config[i]);
}
}
return config;
},
value_setter: template,
xValue_setter: template,
yValue_setter: function (config) {
this.define("value", config);
},
alpha_setter: template,
label_setter: template,
lineColor_setter: template,
borderColor_setter: template,
pieInnerText_setter: template,
donutInnerText_setter: template,
gradient_setter: function (config) {
if (typeof config != "function" && config && config === true) config = "light";
return config;
},
colormap: {
"RAINBOW": function (obj) {
var pos$$1 = Math.floor(this.getIndexById(obj.id) / this.count() * 1536);
if (pos$$1 == 1536) pos$$1 -= 1;
return this._rainbow[Math.floor(pos$$1 / 256)](pos$$1 % 256);
},
"default": function (obj) {
var count = this.count();
var colorsCount = this._defColors.length;
var i = this.getIndexById(obj.id);
if (colorsCount > count) {
if (i) {
if (i < colorsCount - count) i = this._defColorsCursor + 2;else i = this._defColorsCursor + 1;
}
this._defColorsCursor = i;
} else i = i % colorsCount;
return this._defColors[i];
}
},
color_setter: function (value) {
return this.colormap[value] || template(value);
},
fill_setter: function (value) {
return !value || value == "0" ? false : template(value);
},
_definePreset: function (obj) {
this.define("preset", obj.preset);
delete obj.preset;
},
preset_setter: function (value) {
var a, b, preset;
this.defaults = exports.extend({}, this.defaults);
preset = this.presets[value];
if (_typeof(preset) == "object") {
for (a in preset) {
if (_typeof(preset[a]) == "object") {
if (!this.defaults[a] || _typeof(this.defaults[a]) != "object") {
this.defaults[a] = exports.extend({}, preset[a]);
} else {
this.defaults[a] = exports.extend({}, this.defaults[a]);
for (b in preset[a]) {
this.defaults[a][b] = preset[a][b];
}
}
} else {
this.defaults[a] = preset[a];
}
}
return value;
}
return false;
},
legend_setter: function (config) {
if (!config) {
if (this._legendObj) {
this._legendObj.innerHTML = "";
this._legendObj = null;
}
return false;
}
if (_typeof(config) != "object") //allow to use template string instead of object
config = {
template: config
};
this._mergeSettings(config, {
width: 150,
height: 18,
layout: "y",
align: "left",
valign: "bottom",
template: "",
toggle: this._settings.type.toLowerCase().indexOf("stacked") != -1 ? "" : "hide",
marker: {
type: "square",
width: 15,
height: 15,
radius: 3
},
margin: 4,
padding: 3
});
config.template = template(config.template);
return config;
},
item_setter: function (config) {
if (_typeof(config) != "object") config = {
color: config,
borderColor: config
};
this._mergeSettings(config, exports.extend({}, this.defaults.item));
var settings = ["alpha", "borderColor", "color", "radius", "type"];
this._converToTemplate(settings, config);
return config;
},
line_setter: function (config) {
if (_typeof(config) != "object") config = {
color: config
};
config = exports.extend(config, this.defaults.line);
config.color = template(config.color);
return config;
},
padding_setter: function (config) {
if (_typeof(config) != "object") config = {
left: config,
right: config,
top: config,
bottom: config
};
this._mergeSettings(config, {
left: 50,
right: 20,
top: 35,
bottom: 40
});
return config;
},
xAxis_setter: function (config) {
if (!config) return false;
if (_typeof(config) != "object") config = {
template: config
};
this._mergeSettings(config, {
title: "",
color: "#edeff0",
lineColor: "#edeff0",
template: "{obj}",
lines: true
});
var templates = ["lineColor", "template", "lines"];
this._converToTemplate(templates, config);
this._configXAxis = exports.extend({}, config);
return config;
},
yAxis_setter: function (config) {
this._mergeSettings(config, {
title: "",
color: "#edeff0",
lineColor: "#edeff0",
template: "{obj}",
lines: true,
bg: $active.backColor
});
var templates = ["lineColor", "template", "lines", "bg"];
this._converToTemplate(templates, config);
this._configYAxis = exports.extend({}, config);
return config;
},
_converToTemplate: function (arr, config) {
for (var i = 0; i < arr.length; i++) {
config[arr[i]] = template(config[arr[i]]);
}
},
_createCanvas: function (name, style, container, index$$1, title) {
var params = {
container: container || this._contentobj,
name: name,
title: isUndefined(title) ? name : title || "",
series: index$$1,
style: style || "",
width: this._content_width,
height: this._content_height
};
return new Canvas(params);
},
_drawScales: function (data, point0, point1, start, end, cellWidth) {
var ctx,
y = 0;
if (this._settings.yAxis) {
if (!this.canvases["y"]) this.canvases["y"] = this._createCanvas("axis_y");
y = this._drawYAxis(this.canvases["y"].getCanvas(), data, point0, point1, start, end);
}
if (this._settings.xAxis) {
if (!this.canvases["x"]) this.canvases["x"] = this._createCanvas("axis_x");
ctx = this.canvases["x"].getCanvas();
if (this.callEvent("onBeforeXAxis", [ctx, data, point0, point1, cellWidth, y])) this._drawXAxis(ctx, data, point0, point1, cellWidth, y);
}
return y;
},
_drawXAxis: function (ctx, data, point0, point1, cellWidth, y) {
var i,
unitPos,
config = this._settings,
x0 = point0.x - 0.5,
y0 = parseInt(y ? y : point1.y, 10) + 0.5,
x1 = point1.x,
center = true,
labelY = config.type == "stackedBar" ? point1.y + 0.5 : y0;
for (i = 0; i < data.length; i++) {
if (config.offset === true) unitPos = x0 + cellWidth / 2 + i * cellWidth;else {
unitPos = i == data.length - 1 && !config.cellWidth ? point1.x : x0 + i * cellWidth;
center = !!i;
}
unitPos = Math.ceil(unitPos) - 0.5;
/*scale labels*/
var top = config.origin != "auto" && config.type == "bar" && parseFloat(config.value(data[i])) < config.origin;
this._drawXAxisLabel(unitPos, labelY, data[i], center, top);
/*draws a vertical line for the horizontal scale*/
if ((config.offset || i || config.cellWidth) && config.xAxis.lines.call(this, data[i])) this._drawXAxisLine(ctx, unitPos, point1.y, point0.y, data[i]);
}
this.canvases["x"].renderTextAt(true, false, x0, point1.y + config.padding.bottom - 3, config.xAxis.title, "webix_axis_title_x", point1.x - point0.x);
this._drawLine(ctx, x0, y0, x1, y0, config.xAxis.color, 1);
/*the right border in lines in scale are enabled*/
if (!config.xAxis.lines.call(this, {}) || !config.offset) return;
this._drawLine(ctx, x1 + 0.5, point1.y, x1 + 0.5, point0.y + 0.5, config.xAxis.lineColor.call(this, {}), 1);
},
_drawYAxis: function (ctx, data, point0, point1, start, end) {
var step;
var scaleParam = {};
if (!this._settings.yAxis) return;
var x0 = point0.x - 0.5;
var y0 = point1.y;
var y1 = point0.y;
var lineX = point1.y + 0.5; //this._drawLine(ctx,x0,y0,x0,y1,this._settings.yAxis.color,1);
if (this._settings.yAxis.step) step = parseFloat(this._settings.yAxis.step);
if (typeof this._configYAxis.step == "undefined" || typeof this._configYAxis.start == "undefined" || typeof this._configYAxis.end == "undefined") {
scaleParam = this._calculateScale(start, end);
start = scaleParam.start;
end = scaleParam.end;
step = scaleParam.step;
this._settings.yAxis.end = end;
this._settings.yAxis.start = start;
} else if (this.config.scale == "logarithmic") this._logScaleCalc = true;
this._setYAxisTitle(point0, point1);
if (step === 0) return;
if (end == start) {
return y0;
}
var stepHeight = (y0 - y1) * step / (end - start);
var c = 0;
var origin = this._settings.origin;
for (var i = start; i <= end; i += step) {
var value = this._logScaleCalc ? Math.pow(10, i) : i;
if (scaleParam.fixNum) value = parseFloat(value).toFixed(scaleParam.fixNum);
var yi = Math.floor(y0 - c * stepHeight) + 0.5;
/*canvas line fix*/
if (!(i == start && origin == "auto") && this._settings.yAxis.lines.call(this, i)) this._drawLine(ctx, x0, yi, point1.x, yi, this._settings.yAxis.lineColor.call(this, i), 1);
if (origin != "auto" && i <= origin && i + step > origin) lineX = yi - stepHeight * (origin - value) / step;
/*correction for JS float calculation*/
if (step < 1 && !this._logScaleCalc) {
var power = Math.min(Math.floor(this._log10(step)), start <= 0 ? 0 : Math.floor(this._log10(start)));
var corr = Math.pow(10, -power);
value = Math.round(value * corr) / corr;
i = value;
}
this.canvases["y"].renderText(0, yi - 5, this._settings.yAxis.template(value.toString()), "webix_axis_item_y", point0.x - 5);
c++;
}
this._drawLine(ctx, x0, y0 + 1, x0, y1, this._settings.yAxis.color, 1);
return lineX;
},
_setYAxisTitle: function (point0, point1) {
var className = "webix_axis_title_y";
var text = this.canvases["y"].renderTextAt("middle", false, 0, parseInt((point1.y - point0.y) / 2 + point0.y, 10), this._settings.yAxis.title, className);
if (text) text.style.left = (env.transform ? (text.offsetHeight - text.offsetWidth) / 2 : 0) + "px";
},
_calculateLogScale: function (nmin, nmax) {
var startPower = Math.floor(this._log10(nmin));
var endPower = Math.ceil(this._log10(nmax));
return {
start: startPower,
step: 1,
end: endPower
};
},
_normStep: function (step) {
var power = Math.floor(this._log10(step));
var calculStep = Math.pow(10, power);
var stepVal = step / calculStep;
stepVal = stepVal > 5 ? 10 : 5;
return parseInt(stepVal, 10) * calculStep;
},
_calculateScale: function (nmin, nmax) {
this._logScaleCalc = false;
if (this._settings.scale == "logarithmic") {
var logMin = Math.floor(this._log10(nmin));
var logMax = Math.ceil(this._log10(nmax));
if (nmin > 0 && nmax > 0 && logMax - logMin > 1) {
this._logScaleCalc = true;
return this._calculateLogScale(nmin, nmax);
}
}
if (this._settings.origin != "auto" && this._settings.origin < nmin) nmin = this._settings.origin;
var start, end;
var step = this._normStep((nmax - nmin) / 8 || 1);
var power = Math.floor(this._log10(step));
if (step > Math.abs(nmin)) start = nmin < 0 ? -step : 0;else {
var absNmin = Math.abs(nmin);
var powerStart = Math.floor(this._log10(absNmin));
var nminVal = absNmin / Math.pow(10, powerStart);
if (powerStart != 0 || step >= 0.1) start = Math.ceil(nminVal * 10) / 10 * Math.pow(10, powerStart) - step;else start = absNmin;
if (absNmin > 1 && step > 0.1) {
start = Math.ceil(start);
}
while (nmin < 0 ? start <= nmin : start >= nmin) {
start -= step;
}
if (nmin < 0) start = -start - 2 * step;
start = start - start % step;
start = parseFloat((start * 1.0).toFixed(Math.abs(power)));
}
if (nmax - start > 10) step = this._normStep((nmax - start) / 8 || 1);
end = start;
if (nmax == 0 && nmax == nmin) nmax = step;
while (end < nmax) {
end += step;
end = parseFloat((end * 1.0).toFixed(Math.abs(power)));
}
return {
start: start,
end: end,
step: step,
fixNum: power < 0 ? Math.abs(power) : 0
};
},
_getLimits: function (orientation, value) {
var data = this.data._obj_array();
var maxValue, minValue;
var axis = arguments.length && orientation == "h" ? this._configXAxis : this._configYAxis;
value = value || "value";
if (axis && typeof axis.end != "undefined" && typeof axis.start != "undefined" && axis.step) {
maxValue = parseFloat(axis.end);
minValue = parseFloat(axis.start);
} else {
maxValue = GroupMethods.max(this._series[0][value], data);
minValue = axis && typeof axis.start != "undefined" ? parseFloat(axis.start) : GroupMethods.min(this._series[0][value], data);
if (this._series.length > 1) for (var i = 1; i < this._series.length; i++) {
var maxI = GroupMethods.max(this._series[i][value], data);
var minI = GroupMethods.min(this._series[i][value], data);
if (maxI > maxValue) maxValue = maxI;
if (minI < minValue) minValue = minI;
}
}
return {
max: maxValue,
min: minValue
};
},
_log10: function (n) {
var method_name = "log";
return Math[method_name](n) / Math.LN10;
},
_drawXAxisLabel: function (x, y, obj, center, top) {
if (!this._settings.xAxis) return;
var elem = this.canvases["x"].renderTextAt(top, center, x, y - (top ? 2 : 0), this._settings.xAxis.template(obj));
if (elem) elem.className += " webix_axis_item_x";
},
_drawXAxisLine: function (ctx, x, y1, y2, obj) {
if (!this._settings.xAxis || !this._settings.xAxis.lines) return;
this._drawLine(ctx, x, y1, x, y2, this._settings.xAxis.lineColor.call(this, obj), 1);
},
_drawLine: function (ctx, x1, y1, x2, y2, color$$1, width) {
ctx.strokeStyle = color$$1;
ctx.lineWidth = width;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
ctx.lineWidth = 1;
},
_getRelativeValue: function (minValue, maxValue) {
var relValue;
var valueFactor = 1;
if (maxValue != minValue) {
relValue = maxValue - minValue;
} else relValue = minValue;
return [relValue, valueFactor];
},
_rainbow: [function (pos$$1) {
return "#FF" + color.toHex(pos$$1 / 2, 2) + "00";
}, function (pos$$1) {
return "#FF" + color.toHex(pos$$1 / 2 + 128, 2) + "00";
}, function (pos$$1) {
return "#" + color.toHex(255 - pos$$1, 2) + "FF00";
}, function (pos$$1) {
return "#00FF" + color.toHex(pos$$1, 2);
}, function (pos$$1) {
return "#00" + color.toHex(255 - pos$$1, 2) + "FF";
}, function (pos$$1) {
return "#" + color.toHex(pos$$1, 2) + "00FF";
}],
_defColors: ["#f55b50", "#ff6d3f", "#ffa521", "#ffc927", "#ffee54", "#d3e153", "#9acb61", "#63b967", "#21a497", "#21c5da", "#3ea4f5", "#5868bf", "#7b53c0", "#a943ba", "#ec3b77", "#9eb0b8"],
_defColorsCursor: 0,
/**
* adds series to the chart (value and color properties)
* @param: obj - obj with configuration properties
*/
addSeries: function (obj) {
var temp = this._settings;
this._settings = exports.extend({}, temp);
this._parseSettings(obj);
this._series.push(this._settings);
this._settings = temp;
},
$tooltipIn: function (t) {
return t;
},
_get_tooltip_data: function (t, e) {
var id = this.locate(e);
if (!id) return null;
var active = this._getActiveSeries(e);
var def = exports.extend({
dx: 20,
dy: 0,
template: "{obj.value}",
css: ""
}, this._series[active].tooltip || {
template: ""
}, true);
TooltipControl._tooltip.define(def);
return this.getItem(id);
},
_getActiveSeries: function (e) {
var a, areas, i, offset$$1, pos$$1, selection, x, y;
areas = this._map._areas;
offset$$1 = offset(this._contentobj._htmlmap);
pos$$1 = pos(e);
x = pos$$1.x - offset$$1.x;
y = pos$$1.y - offset$$1.y;
for (i = 0; i < areas.length; i++) {
a = areas[i].points;
if (x <= a[2] && x >= a[0] && y <= a[3] && y >= a[1]) {
if (selection) {
if (areas[i].index > selection.index) selection = areas[i];
} else selection = areas[i];
}
}
return selection ? selection.index : 0;
},
hideSeries: function (series) {
this.canvases[series].hideCanvas();
var legend = this._settings.legend;
if (legend && legend.values && legend.values[series]) {
legend.values[series].$hidden = true;
this._drawLegend();
}
this._map.hide(this._contentobj, series, true);
},
showSeries: function (series) {
this.canvases[series].showCanvas();
var legend = this._settings.legend;
if (legend && legend.values && legend.values[series]) {
delete legend.values[series].$hidden;
this._drawLegend();
}
this._map.hide(this._contentobj, series, false);
},
/**
* renders legend block
* @param: ctx - canvas object
* @param: data - object those need to be displayed
* @param: width - the width of the container
* @param: height - the height of the container
*/
_drawLegend: function (data, width) {
/*position of the legend block*/
var i,
legend,
legendContainer,
legendHeight,
legendItems,
legendWidth,
style,
x = 0,
y = 0,
ctx,
itemColor,
disabled,
item;
data = data || [];
width = width || this._content_width;
ctx = this.canvases["legend"].getCanvas();
/*legend config*/
legend = this._settings.legend;
/*the legend sizes*/
style = this._settings.legend.layout != "x" ? "width:" + legend.width + "px" : "";
/*creation of legend container*/
if (this._legendObj) {
this._legendObj.innerHTML = "";
this._legendObj.parentNode.removeChild(this._legendObj);
}
this.canvases["legend"].clearCanvas(true);
legendContainer = create("DIV", {
"class": "webix_chart_legend",
"style": "left:" + x + "px; top:" + y + "px;" + style
}, "");
if (legend.padding) {
legendContainer.style.padding = legend.padding + "px";
}
this._legendObj = legendContainer;
this._contentobj.appendChild(legendContainer);
/*rendering legend text items*/
legendItems = [];
if (!legend.values) for (i = 0; i < data.length; i++) {
legendItems.push(this._drawLegendText(legendContainer, legend.template(data[i]), data[i].id));
} else for (i = 0; i < legend.values.length; i++) {
legendItems.push(this._drawLegendText(legendContainer, legend.values[i].text, typeof legend.values[i].id != "undefined" ? _typeof(legend.values[i].id) : i, legend.values[i].$hidden));
}
var rendered = document.body.contains(this._contentobj);
var parentNode, d; // inside window
if (!rendered) {
d = create("DIV", {
"style": "visibility:hidden; position:absolute; top:0px; left:0px;"
}, "");
parentNode = this._contentobj.parentNode;
document.body.appendChild(d);
d.appendChild(this._contentobj);
}
legendWidth = legendContainer.offsetWidth;
legendHeight = legendContainer.offsetHeight;
/*this._settings.legend.width = legendWidth;
this._settings.legend.height = legendHeight;*/
/*setting legend position*/
if (legendWidth < width) {
if (legend.layout == "x" && legend.align == "center") {
x = (width - legendWidth) / 2;
}
if (legend.align == "right") {
x = width - legendWidth;
}
if (legend.margin && legend.align != "center") {
x += (legend.align == "left" ? 1 : -1) * legend.margin;
}
}
if (legendHeight < this._content_height) {
if (legend.valign == "middle" && legend.align != "center" && legend.layout != "x") y = (this._content_height - legendHeight) / 2;else if (legend.valign == "bottom") y = this._content_height - legendHeight;
if (legend.margin && legend.valign != "middle") {
y += (legend.valign == "top" ? 1 : -1) * legend.margin;
}
}
legendContainer.style.left = x + "px";
legendContainer.style.top = y + "px";
/*drawing colorful markers*/
ctx.save();
for (i = 0; i < legendItems.length; i++) {
item = legendItems[i];
if (legend.values && legend.values[i].$hidden) {
disabled = true;
itemColor = legend.values[i].disableColor ? legend.values[i].disableColor : "#edeff0";
} else {
disabled = false;
itemColor = legend.values ? legend.values[i].color : this._settings.color.call(this, data[i]);
}
this._drawLegendMarker(ctx, item.offsetLeft + x, item.offsetTop + y, itemColor, item.offsetHeight, disabled, i);
}
ctx.restore();
if (!rendered) {
parentNode.appendChild(this._contentobj);
remove(d);
}
legendItems = null;
},
/**
* appends legend item to legend block
* @param: ctx - canvas object
* @param: obj - data object that needs being represented
*/
_drawLegendText: function (cont, value, series, disabled) {
var style = "";
if (this._settings.legend.layout == "x") style = "float:left;";
/*the text of the legend item*/
var text = create("DIV", {
"style": style + "padding-left:" + (10 + this._settings.legend.marker.width) + "px",
"class": "webix_chart_legend_item" + (disabled ? " hidden" : ""),
"role": "button",
"tabindex": "0",
"aria-label": i18n.aria[(disabled ? "show" : "hide") + "Chart"] + " " + value
}, value);
if (arguments.length > 2) text.setAttribute(
/*@attr*/
"series_id", series);
cont.appendChild(text);
return text;
},
/**
* draw legend colorful marder
* @param: ctx - canvas object
* @param: x - the horizontal position of the marker
* @param: y - the vertical position of the marker
* @param: obj - data object which color needs being used
*/
_drawLegendMarker: function (ctx, x, y, color$$1, height, disabled, i) {
var p = [];
var marker = this._settings.legend.marker;
var values = this._settings.legend.values;
var type = values && values[i].markerType ? values[i].markerType : marker.type;
if (color$$1) {
ctx.strokeStyle = ctx.fillStyle = color$$1;
}
if (type == "round" || !marker.radius) {
ctx.beginPath();
var r = marker.height / 2;
ctx.arc(x + r + 5, y + height / 2, r, 0, 2 * Math.PI);
ctx.fill();
} else if (type == "item") {
/*copy of line*/
if (this._settings.line && this._settings.type != "scatter" && !this._settings.disableLines) {
ctx.beginPath();
ctx.lineWidth = this._series[i].line.width;
ctx.strokeStyle = disabled ? color$$1 : this._series[i].line.color.call(this, {});
var x0 = x + 5;
var y0 = y + height / 2;
ctx.moveTo(x0, y0);
var x1 = x0 + marker.width;
ctx.lineTo(x1, y0);
ctx.stroke();
}
/*item copy*/
var config = this._series[i].item;
var radius = parseInt(config.radius.call(this, {}), 10) || 0;
var markerType = config.type.call(this, {});
if (radius) {
ctx.beginPath();
if (disabled) {
ctx.lineWidth = config.borderWidth;
ctx.strokeStyle = color$$1;
ctx.fillStyle = color$$1;
} else {
ctx.lineWidth = config.borderWidth;
ctx.fillStyle = config.color.call(this, {});
ctx.strokeStyle = config.borderColor.call(this, {});
ctx.globalAlpha = config.alpha.call(this, {});
}
ctx.beginPath();
x += marker.width / 2 + 5;
y += height / 2;
this._strokeChartItem(ctx, x, y, radius + 1, markerType);
ctx.fill();
ctx.stroke();
}
ctx.globalAlpha = 1;
} else {
ctx.beginPath();
ctx.lineWidth = 1;
x += 5;
y += height / 2 - marker.height / 2;
p = [[x + marker.radius, y + marker.radius, marker.radius, Math.PI, 3 * Math.PI / 2, false], [x + marker.width - marker.radius, y], [x + marker.width - marker.radius, y + marker.radius, marker.radius, -Math.PI / 2, 0, false], [x + marker.width, y + marker.height - marker.radius], [x + marker.width - marker.radius, y + marker.height - marker.radius, marker.radius, 0, Math.PI / 2, false], [x + marker.radius, y + marker.height], [x + marker.radius, y + marker.height - marker.radius, marker.radius, Math.PI / 2, Math.PI, false], [x, y + marker.radius]];
this._path(ctx, p);
ctx.stroke();
ctx.fill();
}
},
/**
* gets the points those represent chart left top and right bottom bounds
* @param: width - the width of the chart container
* @param: height - the height of the chart container
*/
_getChartBounds: function (width, height) {
var chartX0, chartY0, chartX1, chartY1;
chartX0 = this._settings.padding.left;
chartY0 = this._settings.padding.top;
chartX1 = width - this._settings.padding.right;
chartY1 = height - this._settings.padding.bottom;
if (this._settings.legend) {
var legend = this._settings.legend;
/*legend size*/
var legendWidth = this._settings.legend.width;
var legendHeight = this._settings.legend.height;
/*if legend is horizontal*/
if (legend.layout == "x") {
if (legend.valign == "center") {
if (legend.align == "right") chartX1 -= legendWidth;else if (legend.align == "left") chartX0 += legendWidth;
} else if (legend.valign == "bottom") {
chartY1 -= legendHeight;
} else {
chartY0 += legendHeight;
}
}
/*vertical scale*/
else {
if (legend.align == "right") chartX1 -= legendWidth;else if (legend.align == "left") chartX0 += legendWidth;
}
}
return {
start: {
x: chartX0,
y: chartY0
},
end: {
x: chartX1,
y: chartY1
}
};
},
/**
* gets the maximum and minimum values for the stacked chart
* @param: data - data set
*/
_getStackedLimits: function (data) {
var i, j, maxValue, minValue, value;
if (this._settings.yAxis && typeof this._settings.yAxis.end != "undefined" && typeof this._settings.yAxis.start != "undefined" && this._settings.yAxis.step) {
maxValue = parseFloat(this._settings.yAxis.end);
minValue = parseFloat(this._settings.yAxis.start);
} else {
for (i = 0; i < data.length; i++) {
data[i].$sum = 0;
data[i].$min = Infinity;
for (j = 0; j < this._series.length; j++) {
value = Math.abs(parseFloat(this._series[j].value(data[i]) || 0));
if (isNaN(value)) continue;
if (this._series[j].type.toLowerCase().indexOf("stacked") != -1) data[i].$sum += value;
if (value < data[i].$min) data[i].$min = value;
}
}
maxValue = -Infinity;
minValue = Infinity;
for (i = 0; i < data.length; i++) {
if (data[i].$sum > maxValue) maxValue = data[i].$sum;
if (data[i].$min < minValue) minValue = data[i].$min;
}
if (minValue > 0) minValue = 0;
}
return {
max: maxValue,
min: minValue
};
},
/*adds colors to the gradient object*/
_setBarGradient: function (ctx, x1, y1, x2, y2, type, rawColor, axis) {
var gradient, offset$$1, rgb, hsv, rawColor0, stops;
if (type == "light") {
if (axis == "x") gradient = ctx.createLinearGradient(x1, y1, x2, y1);else gradient = ctx.createLinearGradient(x1, y1, x1, y2);
stops = [[0, "#FFFFFF"], [0.9, rawColor], [1, rawColor]];
offset$$1 = 2;
} else if (type == "falling" || type == "rising") {
if (axis == "x") gradient = ctx.createLinearGradient(x1, y1, x2, y1);else gradient = ctx.createLinearGradient(x1, y1, x1, y2);
rgb = color.toRgb(rawColor);
hsv = color.rgbToHsv(rgb[0], rgb[1], rgb[2]);
hsv[1] *= 1 / 2;
rawColor0 = "rgb(" + color.hsvToRgb(hsv[0], hsv[1], hsv[2]) + ")";
if (type == "falling") {
stops = [[0, rawColor0], [0.7, rawColor], [1, rawColor]];
} else if (type == "rising") {
stops = [[0, rawColor], [0.3, rawColor], [1, rawColor0]];
}
offset$$1 = 0;
} else {
ctx.globalAlpha = 0.37;
offset$$1 = 0;
if (axis == "x") gradient = ctx.createLinearGradient(x1, y2, x1, y1);else gradient = ctx.createLinearGradient(x1, y1, x2, y1);
stops = [[0, "#9d9d9d"], [0.3, "#e8e8e8"], [0.45, "#ffffff"], [0.55, "#ffffff"], [0.7, "#e8e8e8"], [1, "#9d9d9d"]];
}
this._gradient(gradient, stops);
return {
gradient: gradient,
offset: offset$$1
};
},
/**
* returns the x and y position
* @param: a - angle
* @param: x - start x position
* @param: y - start y position
* @param: r - destination to the point
*/
_getPositionByAngle: function (a, x, y, r) {
a *= -1;
x = x + Math.cos(a) * r;
y = y - Math.sin(a) * r;
return {
x: x,
y: y
};
},
_gradient: function (gradient, stops) {
for (var i = 0; i < stops.length; i++) {
gradient.addColorStop(stops[i][0], stops[i][1]);
}
},
_path: function (ctx, points) {
var i, method;
for (i = 0; i < points.length; i++) {
method = i ? "lineTo" : "moveTo";
if (points[i].length > 2) method = "arc";
ctx[method].apply(ctx, points[i]);
}
},
_addMapRect: function (map, id, points, bounds, sIndex) {
map.addRect(id, [points[0].x - bounds.x, points[0].y - bounds.y, points[1].x - bounds.x, points[1].y - bounds.y], sIndex);
}
};
var view$10 = exports.protoUI(api$10, Pie$1, BarChart, LineChart, BarHChart, StackedBarChart, StackedBarHChart, Spline$1, AreaChart, Radar, Scatter, Presets, SplineArea$1, DynamicChart, Group, AutoTooltip, DataLoader, MouseEvents, EventSystem, base$1.view);
exports.protoUI({
name: "rangechart",
defaults: {
template: "GPL version doesn't support rangechart <br> You need Webix PRO"
}
}, template$1.view);
var api$11 = {
name: "grouplist",
defaults: {
animate: {}
},
_listClassName: "webix_grouplist",
$init: function () {
exports.extend(this.data, TreeStore, true); //needed for getRange
this.data.count = function () {
return this.order.length;
};
this.data.provideApi(this, true);
this.data.attachEvent("onClearAll", bind(this._onClear, this));
this._onClear();
},
_onClear: function () {
this._nested_cursor = [];
this._nested_chain = [];
},
$setSize: function () {
if (base$1.api.$setSize.apply(this, arguments)) {
//critical for animations in group list
this._dataobj.style.width = this._content_width;
}
},
on_click: {
webix_list_item: function (e, id) {
if (this._animation_promise) {
return false;
}
for (var i = 0; i < this._nested_chain.length; i++) {
if (this._nested_chain[i] == id) {
//one level up
for (var j = i; j < this._nested_chain.length; j++) {
this.data.getItem(this._nested_chain[j]).$template = "";
}
if (!i) {
//top level
this._nested_cursor = this.data.branch[0];
this._nested_chain = [];
} else {
this._nested_cursor = this.data.branch[this._nested_chain[i - 1]];
this._nested_chain.splice(i);
}
this._is_level_down = false;
return this.render();
}
}
var obj = this.getItem(id);
if (obj.$count) {
//one level down
this._is_level_down = true;
this._nested_chain.push(id);
obj.$template = "Back";
this._nested_cursor = this.data.branch[obj.id];
return this.render();
} else {
if (this._settings.select) {
this._no_animation = true;
if (this._settings.select == "multiselect" || this._settings.multiselect) this.select(id, false, this._settings.multiselect == "touch" || e.ctrlKey || e.metaKey, e.shiftKey); //multiselection
else this.select(id);
this._no_animation = false;
}
}
}
},
getOpenState: function () {
return {
parents: this._nested_chain,
branch: this._nested_cursor
};
},
render: function (id, data, type$$1) {
var _this = this,
_arguments = arguments;
var i, lastChain; //start filtering processing=>
this._nested_chain = copy(this._nested_chain);
this._nested_cursor = copy(this._nested_cursor);
if (this._nested_chain.length) {
for (i = 0; i < this._nested_chain.length; i++) {
if (!this.data.branch[this._nested_chain[i]]) {
this._nested_chain.splice(i, 1);
i--;
}
}
}
lastChain = this._nested_chain.length ? this._nested_chain[this._nested_chain.length - 1] : 0;
this._nested_cursor = copy(this.data.branch[lastChain]);
if (!this._nested_cursor.length && this._nested_chain.length) {
this._nested_cursor = [lastChain];
this._nested_chain.pop();
} //<= end filtering processing
if (this._animation_promise) return this._animation_promise.then(function () {
return _this.render.apply(_this, _arguments);
});
for (i = 0; i < this._nested_cursor.length; i++) {
this.data.getItem(this._nested_cursor[i]).$template = "";
}
if (!this._nested_cursor.length) this._nested_cursor = this.data.branch[0];
this.data.order = _to_array([].concat(this._nested_chain).concat(this._nested_cursor));
if (this.callEvent("onBeforeRender", [this.data])) {
if (this._no_animation || !this._dataobj.innerHTML || !(animate.isSupported() && this._settings.animate) || this._prev_nested_chain_length == this._nested_chain.length) {
// if dataobj is empty or animation is not supported
// don't repaint invisible data
if (id && type$$1 !== "delete" && this.data.getIndexById(id) === -1) return;
RenderStack.render.apply(this, arguments);
} else {
//getRange - returns all elements
if (this.callEvent("onBeforeRender", [this.data])) {
if (!this._back_scroll_states) this._back_scroll_states = [];
var next_div = this._dataobj.cloneNode(false);
next_div.innerHTML = this.data.getRange().map(this._toHTML, this).join("");
var aniset = exports.extend({}, this._settings.animate);
aniset.direction = this._is_level_down ? "left" : "right";
/*scroll position restore*/
var animArr = [clone(aniset), clone(aniset)];
var getScrollState;
if (this._is_level_down) this._back_scroll_states.push(this.getScrollState());else getScrollState = this._back_scroll_states.pop();
var line = animate.formLine(next_div, this._dataobj, aniset);
aniset.master = this;
aniset.callback = function () {
this._dataobj = next_div;
/*scroll position restore*/
if (!this._is_level_down) {
if (getScrollState) this.scrollTo(0, getScrollState.y);
} else this.scrollTo(0, 0);
animate.breakLine(line);
aniset.master = aniset.callback = null;
this._htmlmap = this._animation_promise = null; //clear map, it will be filled at first getItemNode
aniset.wait_animation.resolve();
this.callEvent("onAfterRender", []);
};
animate(line, animArr);
this._animation_promise = aniset.wait_animation = Deferred.defer();
}
}
this._prev_nested_chain_length = this._nested_chain.length;
}
},
templateBack_setter: function (config) {
this.type.templateBack = template(config);
},
templateItem_setter: function (config) {
this.type.templateItem = template(config);
},
templateGroup_setter: function (config) {
this.type.templateGroup = template(config);
},
type: {
template: function (obj, common) {
if (obj.$count) return common.templateGroup(obj, common);
return common.templateItem(obj, common);
},
css: "group",
classname: function (obj, common, marks) {
return "webix_list_item" + " webix_" + (obj.$count ? "group" : "item") + (obj.$template ? "_back" : "") + (marks && marks.webix_selected ? " webix_selected" : "") + (common.css ? " " + common.css : "") + (obj.$css ? " " + obj.$css : "");
},
templateStart: template("<div " +
/*@attr*/
"webix_l_id" + "=\"#id#\" class=\"{common.classname()}\" style=\"width:{common.widthSize()}; height:{common.heightSize()}; overflow:hidden;\" {common.aria()}>"),
templateBack: template("#value#"),
templateItem: template("#value#"),
templateGroup: template("#value#"),
templateEnd: function (obj) {
var html = "";
if (obj.$count) html += "<div class='webix_arrow_icon'></div>";
html += "</div>";
return html;
}
},
showItem: function (id) {
var obj, parent;
if (id) {
obj = this.getItem(id);
parent = obj.$parent;
if (obj.$count) parent = obj.id;
}
this._nested_cursor = this.data.branch[parent || 0];
this._nested_chain = []; //build _nested_chain
while (parent) {
this.getItem(parent).$template = "Back";
this._nested_chain.unshift(parent);
parent = this.getItem(parent).$parent;
} //render
this._no_animation = true;
this.render();
this._no_animation = false; //scroll if necessary
RenderStack.showItem.call(this, id);
}
};
var view$11 = exports.protoUI(api$11, Group, list.view);
type(view$11, {});
var api$12 = {
name: "unitlist",
_id:
/*@attr*/
"webix_item_id",
uniteBy_setter: template,
render: function (id, data, type) {
var config = this._settings;
if (!this.isVisible(config.id)) return;
if (!config.uniteBy) return;
if (id) {
var cont = this.getItemNode(id); //get html element of updated item
if (cont && type == "update" && this._settings.uniteBy.call(this, data) == this.getItem(id).$unitValue) {
var t = this._htmlmap[id] = this._toHTMLObject(data);
insertBefore(t, cont);
remove(cont);
return;
}
} //full reset
if (this.callEvent("onBeforeRender", [this.data])) {
this.units = null;
this._setUnits();
if (this.units) {
this.callEvent("onUnits", []);
this._dataobj.innerHTML = this._getUnitRange().map(this._toHTML, this).join("");
this._htmlmap = null;
}
this.callEvent("onAfterRender", []);
}
},
getUnits: function () {
var result = [];
if (this.units) {
for (var b in this.units) {
result.push(b);
}
}
return result;
},
getUnitList: function (id) {
return this.units ? this.units[id] : null;
},
_toHTML: function (obj) {
//check if related template exist
var mark = this.data._marks[obj.id];
assert(!obj.$template || this.type["template" + obj.$template], "RenderStack :: Unknown template: " + obj.$template);
this.callEvent("onItemRender", [obj]);
if (obj.$unit) {
return this.type.templateStartHeader(obj, this.type) + this.type.templateHeader.call(this, obj.$unit) + this.type.templateEnd(obj, this.type);
}
return this.type.templateStart(obj, this.type, mark) + (obj.$template ? this.type["template" + obj.$template] : this.type.template)(obj, this.type) + this.type.templateEnd(obj, this.type);
},
_getUnitRange: function () {
var data = [];
var min = this.data.$min || 0;
var max = this.data.$max || Infinity;
var count = 0;
for (var u in this.units) {
data.push({
$unit: u
});
var unit = this.units[u];
for (var i = 0; i < unit.length; i++) {
if (count == min) data = [{
$unit: u
}];
data.push(this.getItem(unit[i]));
if (count == max) return _to_array(data);
count++;
}
}
return _to_array(data);
},
_setUnits: function () {
var list$$1 = this;
this.units = {};
this.data.each(function (obj) {
var result = list$$1._settings.uniteBy.call(this, obj);
obj.$unitValue = result;
if (!list$$1.units[result]) list$$1.units[result] = [];
list$$1.units[result].push(obj.id);
});
},
type: {
headerHeight: 20,
classname: function (obj, type, marks) {
var css = "webix_list_item";
if (type.css) css += " webix_list_" + type.css + "_item";
if (marks && marks.$css) css += " " + marks.$css;
if (obj.$css) {
if (_typeof(obj.$css) == "object") obj.$css = createCss(obj.$css);
css += " " + obj.$css;
}
return css;
},
templateHeader: function (value) {
return "<span class='webix_unit_header_inner'>" + value + "</span>";
},
templateStart: function (obj, type, marks) {
if (obj.$unit) return type.templateStartHeader.apply(this, arguments);
var style = "width:" + type.widthSize(obj, type, marks) + "; height:" + type.heightSize(obj, type, marks) + "; overflow:hidden;" + (type.layout && type.layout == "x" ? "float:left;" : "");
return "<div " +
/*@attr*/
"webix_item_id" + "=\"" + obj.id + "\" class=\"" + type.classname(obj, type, marks) + "\" style=\"" + style + "\" " + type.aria(obj, type, marks) + ">";
},
templateStartHeader: function (obj, type, marks) {
var className = "webix_unit_header" + (type.css ? " webix_unit_header_" + type.css + "_item" : "");
var style = "width:" + type.widthSize(obj, type, marks) + "; height:" + type.headerHeight + "px; overflow:hidden;";
return "<div " +
/*@attr*/
"webix_unit_id" + "=\"" + obj.$unit + "\" class=\"" + className + "\" style=\"" + style + "\">";
}
},
$skin: function () {
list.api.$skin.call(this);
this.type.headerHeight = $active.unitHeaderHeight;
}
};
var view$12 = exports.protoUI(api$12, list.view);
i18n.dbllist = {
selectAll: "<span class='webix_icon wxi-angle-double-right'></span>",
selectOne: "<span class='webix_icon wxi-angle-right'></span>",
deselectAll: "<span class='webix_icon wxi-angle-double-left'></span>",
deselectOne: "<span class='webix_icon wxi-angle-left'></span>"
};
var api$13 = {
name: "dbllist",
defaults: {
borderless: true
},
$init: function () {
this._moved = {};
this._inRight = bind(function (obj) {
return this._moved[obj.id];
}, this);
this._inLeft = bind(function (obj) {
return !this._moved[obj.id];
}, this);
this.$view.className += " webix_dbllist";
this.$ready.unshift(this._setLayout);
},
$onLoad: function (data, driver) {
var left = this.$$("left");
var right = this.$$("right");
this._updateAndResize(function () {
left.data.driver = driver;
left.parse(data);
right.data.driver = driver;
right.parse(data);
});
this._data_ready = true;
this._refresh();
return true;
},
_getButtons: function () {
if (this._settings.buttons === false) return {
width: 10
};
var locale = i18n.dbllist;
var buttons = [this._getButton("deselect_all", locale.deselectAll), this._getButton("select_all", locale.selectAll), this._getButton("deselect_one", locale.deselectOne), this._getButton("select_one", locale.selectOne)];
buttons = {
width: 120,
template: buttons.join(""),
onClick: {
dbllist_button: function (e, id, trg) {
this.getTopParentView()._update_list(trg.getAttribute("action"));
}
}
};
if (this._settings.buttons) buttons.template = this._settings.buttons;
return buttons;
},
_getButton: function (action, label) {
return "<button class='dbllist_button' action='" + action + "'>" + label + "</button>";
},
_getList: function (id, action, label, bottom) {
var list = {
view: "list",
select: "multiselect",
multiselect: "touch",
id: id,
action: action,
drag: true,
type: {
margin: 3,
id: id
},
on: {
onBeforeDrop: function (context) {
var source = context.from;
var target = context.to;
var top = source.getTopParentView();
if (top === this.getTopParentView()) {
var mode = target._settings.action != "select_one";
top.select(context.source, mode);
}
return false;
},
onItemDblClick: function () {
return this.getTopParentView()._update_list(this.config.action);
}
}
};
if (this._settings.list) exports.extend(list, this._settings.list, true);
if (label) list = {
rows: [{
view: "label",
label: label,
css: "webix_inp_top_label"
}, list]
};
if (bottom) return {
rows: [list, {
view: "label",
height: 20,
label: bottom,
css: "bottom_label"
}]
};
return list;
},
_setLayout: function () {
var cols = [{
margin: 10,
type: "clean",
cols: [this._getList("left", "select_one", this._settings.labelLeft, this._settings.labelBottomLeft), this._getButtons(), this._getList("right", "deselect_one", this._settings.labelRight, this._settings.labelBottomRight)]
}];
this.cols_setter(cols);
},
_update_list: function (action) {
var top = this;
var id = null;
var mode = false;
if (action === "select_all") {
id = top.$$("left").data.order;
mode = true;
} else if (action === "select_one") {
id = top.$$("left").getSelectedId(true);
mode = true;
} else if (action === "deselect_all") {
id = top.$$("right").data.order;
mode = false;
} else if (action === "deselect_one") {
id = top.$$("right").getSelectedId(true);
mode = false;
}
top.select(id, mode);
},
select: function (id, mode) {
var i;
if (_typeof(id) !== "object") id = [id];
if (mode) {
for (i = 0; i < id.length; i++) {
this._moved[id[i]] = true;
}
} else {
for (i = 0; i < id.length; i++) {
delete this._moved[id[i]];
}
}
this._refresh();
this.callEvent("onChange", []);
},
_updateAndResize: function (handler, size) {
freeze(bind(handler, this), false);
if (size && (this.$$("left")._settings.autoheight || this.$$("right")._settings.autoheight)) this.resize();
},
_refresh: function () {
var left = this.$$("left");
var right = this.$$("right");
if (left) this._updateAndResize(function () {
left.filter(this._inLeft);
right.filter(this._inRight);
}, true);
},
focus: function () {
if (!UIManager.canFocus(this)) return false;
UIManager.setFocus(this);
},
value_setter: function (val) {
this.setValue(val);
},
setValue: function (value) {
this._moved = {};
if (value) {
if (_typeof(value) !== "object") value = value.toString().split(",");
for (var i = 0; i < value.length; i++) {
this._moved[value[i]] = true;
}
}
this._refresh();
},
getValue: function () {
var value = [];
var list = this.$$("left");
for (var key in this._moved) {
if (!this._data_ready || list.data.pull[key]) value.push(key);
}
return value.join(",");
}
};
var view$13 = exports.protoUI(api$13, AtomDataLoader, IdSpace, layout.view);
var api$14 = {
name: "tree",
defaults: {
scroll: "auto",
navigation: true
},
$init: function () {
this._viewobj.className += " webix_tree"; //map API of DataStore on self
exports.extend(this.data, TreeStore, true);
exports.extend(this.on_click, TreeClick);
this.data.provideApi(this, true);
this._viewobj.setAttribute("role", "tree");
},
//attribute , which will be used for ID storing
_id:
/*@attr*/
"webix_tm_id",
//supports custom context menu
on_context: {},
on_dblclick: {
webix_tree_checkbox: function () {
if (this.on_click.webix_tree_checkbox) return this.on_click.webix_tree_checkbox.apply(this, arguments);
}
},
$fixEditor: function (editor) {
var item = this.getItemNode(editor.id).querySelector("span");
if (item) {
if (item.innerHTML === "") item.innerHTML = " ";
var padding = 10;
var pos$$1 = item.offsetLeft;
editor.node.style.width = this.$view.scrollWidth - pos$$1 - padding + "px";
editor.node.style.marginLeft = pos$$1 + "px";
editor.node.style.left = "0px";
}
},
//css class to action map, for onclick event
on_click: {
webix_tree_item: function (e, id) {
if (this._settings.activeTitle) {
var item = this.getItem(id);
if (item.open) this.close(id);else this.open(id);
}
if (this._settings.select) {
if (this._settings.select == "multiselect" || this._settings.multiselect) {
var multimode = e.ctrlKey || e.metaKey || this._settings.multiselect == "touch";
if (this._settings.multiselect == "level" && (multimode || e.shiftKey)) {
//allow only selection on the same level
var select = this.getSelectedId(true)[0];
if (select && this.getParentId(id) != this.getParentId(select)) return;
}
this.select(id, false, multimode, e.shiftKey); //multiselection
} else this.select(id);
}
}
},
_paste: {
// insert new item with pasted value
insert: function (text) {
var parent = this.getSelectedId() || "0";
this.add({
value: text
}, null, parent);
},
// change value of each selected item
modify: function (text) {
var sel = this.getSelectedId(true);
for (var i = 0; i < sel.length; i++) {
this.getItem(sel[i]).value = text;
this.refresh(sel[i]);
}
},
// do nothing
custom: function () {}
},
_drag_order_complex: true,
$dragHTML: function (obj, e, context) {
var html = "<div class='webix_tree_item'>" + this.type.template(obj, this.type) + "</div>";
if (isArray(context.source) && context.source.length > 1) html = this._toMultipleHTML(html, context.source.length);
return html;
},
_close_branches: function (context) {
var source = context.source;
for (var i = 0; i < source.length; i++) {
this.close(source[i]);
}
},
_set_drop_area: function (target, t) {
var node = this.getItemNode(target);
if (node) {
node.parentNode.insertBefore(DragControl._dropHTML[0], node);
} else t.children[0].children[0].appendChild(DragControl._dropHTML[0]);
},
//css class to action map, for dblclick event
type: exports.extend({
//normal state of item
template: function (obj, common) {
var template$$1 = common["template" + obj.level] || common.templateCommon;
return template$$1.apply(this, arguments);
},
classname: function (obj, common, marks) {
var css = "webix_tree_item";
if (obj.$css) {
if (_typeof(obj.$css) == "object") obj.$css = createCss(obj.$css);
css += " " + obj.$css;
}
if (marks && marks.$css) css += " " + marks.$css;
if (common.css) css += " " + common.css;
return css;
},
aria: function (obj, common, marks) {
return "role=\"treeitem\"" + (marks && marks.webix_selected ? " aria-selected=\"true\" tabindex=\"0\"" : " tabindex=\"-1\"") + (obj.$count ? "aria-expanded=\"" + (obj.open ? "true" : "false") + "\"" : "") + "aria-level=\"" + obj.$level + "\"";
},
templateCommon: template("{common.icon()} {common.folder()} <span>#value#</span>"),
templateStart: template("<div " +
/*@attr*/
"webix_tm_id" + "=\"#id#\" class=\"{common.classname()}\" {common.aria()}>"),
templateEnd: template("</div>"),
templateCopy: template("#value#")
}, TreeType)
};
var view$14 = exports.protoUI(api$14, TreeStateCheckbox, Group, TreeAPI, DragItem, TreeDataMove, SelectionModel, KeysNavigation, MouseEvents, Scrollable, TreeDataLoader, proto.view, TreeRenderStack, CopyPaste, EventSystem);
var tree = {
api: api$14,
view: view$14
};
type(view$14, {
name: "lineTree",
css: "webixLineTree",
icon: function (obj, common) {
var html = "";
var open = "";
for (var i = 1; i <= obj.$level; i++) {
if (i == obj.$level) open = obj.$count ? obj.open ? "webix_tree_open " : "webix_tree_close " : "webix_tree_none ";
var icon = common._icon_src(obj, common, i);
if (icon) html += "<div class='" + open + "webix_tree_img webix_tree_" + icon + "'></div>";
}
return html;
},
_icon_src: function (obj, common, level) {
var lines = common._tree_branch_render_state;
var tree = TreeRenderStack._obj;
if (lines === 0 && tree) {
//we are in standalone rendering
//need to reconstruct rendering state
var lines_level = obj.$level;
var branch_id = obj.id;
lines = [];
while (lines_level) {
var parent_id = tree.getParentId(branch_id);
var pbranch = tree.data.branch[parent_id];
if (pbranch[pbranch.length - 1] == branch_id) lines[lines_level] = true;
branch_id = parent_id;
lines_level--;
} //store for next round
common._tree_branch_render_state = lines;
}
if (!lines) return 0; //need to be replaced with image urls
if (level == obj.$level) {
var mode = 3; //3-way line
if (!obj.$parent) {
//top level
if (obj.$index === 0) mode = 4; //firts top item
}
if (lines[obj.$level]) mode = 2;
if (obj.$count) {
if (obj.open) return "minus" + mode;else return "plus" + mode;
} else return "line" + mode;
} else {
if (!lines[level]) return "line1";
return "blank";
}
}
});
var api$15 = {
name: "treemap",
defaults: {
activeItem: false,
subRender: true,
header: true,
headerHeight: 35,
value: template("#value#"),
headerTemplate: "",
navigation: true
},
value_setter: template,
headerTemplate_setter: template,
header_setter: function (value) {
if (value && value !== true) {
this.type.header = value;
}
return value;
},
$init: function () {
this.$view.className += " webix_treemap";
this._viewobj.setAttribute("role", "tree");
this._htmlElement = document.createElement("DIV");
exports.extend(this.data, TreeStore, true);
this.data.provideApi(this, true);
this.data.attachEvent("onClearAll", bind(function () {
this._html = "";
this.$values = {};
this.$xy = {};
}, this));
this.attachEvent("onKeyPress", this._onKeyPress);
},
_toHTMLItem: function (obj) {
var mark = this.data._marks[obj.id];
this.callEvent("onItemRender", [obj]);
var template$$1 = obj.$template ? this.type["template" + obj.$template].call(this, obj, this.type, mark) : this.type.template.call(this, obj, this.type, mark);
return this.type.templateStart.call(this, obj, this.type, mark) + template$$1 + this.type.templateEnd.call(this);
},
_renderHeader: function (id) {
var item = this.getItem(id);
var height = this._settings.headerHeight;
var html = "<div class='webix_treemap_header' style='height:" + height + "px;line-height:" + height + "px;'>";
html += this.type.header.call(this, item, this.type);
html += "</div>";
return html;
},
_renderBranch: function (pId) {
var sizes,
row,
value,
sum,
leaves = [];
if (!this.$width || !this.count()) {
this._html = "";
return false;
}
if (!pId) {
pId = this.config.branch || 0;
this._html = "";
this.$values = {};
this.$xy = {};
this.$xy[pId] = {
width: this.$width,
height: this.$height,
top: 0,
left: 0
}; // header
if (pId && this._settings.header) {
this.$xy[pId].height -= this._settings.headerHeight;
this.$xy[pId].top = this._settings.headerHeight;
this._html += this._renderHeader(pId);
} // values calculation
sum = 0;
this.data.each(function (item) {
var parentId = this.getParentId(item.id);
if (!this.data.branch[item.id]) {
value = this.config.value.call(this, item) * 1;
if (!isNaN(value) && value) {
this.$values[item.id] = value;
sum += value;
while (parentId) {
if (!this.$values[parentId]) this.$values[parentId] = 0;
this.$values[parentId] += value;
parentId = this.getParentId(parentId);
}
}
}
}, this, false, pId);
}
this.data.eachChild(pId, function (item) {
if (this.$values[item.id]) leaves.push(copy(item));
}, this);
sum = sum || this.$values[pId];
if (leaves.length && sum) {
sizes = this.$xy[pId];
row = {
top: sizes.top,
left: sizes.left,
dx: sizes.width,
dy: sizes.height,
set: [],
sum: 0
};
row.dim = Math.min(row.dx, row.dy);
var delta = row.dx * row.dy / sum; //total area
for (var _i = 0; _i < leaves.length; _i++) {
leaves[_i].$value = this.$values[leaves[_i].id] * delta;
} //normalized value
leaves.sort(function (a, b) {
return a.$value > b.$value ? -1 : 1;
});
var bad = Infinity;
var i = 0;
while (leaves[i]) {
var check = this._worst(row, leaves[i]);
if (check < bad) {
row.sum += leaves[i].$value;
row.set.push(leaves[i]);
bad = check;
i++;
} else {
this._renderRow(row);
var r = {
top: row.top,
left: row.left,
dx: row.dx,
dy: row.dy,
set: [],
sum: 0
};
var _delta = row.sum / row.dim;
if (row.dx > row.dy) {
r.left += _delta;
r.dx -= _delta;
} else {
r.top += _delta;
r.dy -= _delta;
}
row = r;
row.dim = Math.min(row.dx, row.dy);
bad = Infinity;
}
}
}
if (row) this._renderRow(row);
},
_renderRow: function (row) {
var i,
id,
x,
y,
top = row.top,
left = row.left;
row.mode = row.dy < row.dx;
row.contra = row.sum / row.dim;
for (i = 0; i < row.set.length; i++) {
id = row.set[i].id;
if (row.mode) {
x = row.contra;
y = row.set[i].$value / row.contra;
} else {
x = row.set[i].$value / row.contra;
y = row.contra;
}
this.$xy[id] = {};
this.$xy[id].top = top;
this.$xy[id].left = left;
if (row.mode) top += y;else left += x;
this.$xy[id].width = x;
this.$xy[id].height = y;
this._html += this._toHTMLItem(this.getItem(id));
if (this._settings.subRender && this.data.branch[id]) this._renderBranch(id);
}
},
_worst: function (row, add) {
var s = row.sum + add.$value;
var a = s * s / (row.dim * row.dim * add.$value);
if (row.set.length) {
a = Math.max(row.dim * row.dim * row.set[0].$value / (s * s), a);
}
return a > 1 ? a : 1 / a;
},
_toHTMLObject: function (obj) {
this._htmlElement.innerHTML = this._toHTMLItem(obj);
return this._htmlElement.firstChild;
},
showBranch: function (id) {
this._settings.branch = id;
this.refresh();
},
render: function (id, data, type) {
if (!this.isVisible(this._settings.id) || this.$blockRender) return;
if (type == "update") {
var cont = this.getItemNode(id); //get html element of updated item
if (cont) {
var t = this._htmlmap[id] = this._toHTMLObject(data);
insertBefore(t, cont);
remove(cont);
}
} else if (this.data.branch && (!this._settings.branch || this.data.branch[this._settings.branch])) {
this._htmlmap = null;
this.callEvent("onBeforeRender", []);
this._renderBranch();
this._dataobj.innerHTML = this._html;
this.callEvent("onAfterRender", []);
}
return true;
},
_id:
/*@attr*/
"webix_dm_id",
on_click: {
webix_treemap_item: function (e, id) {
if (this._settings.select) {
if (this._settings.select == "multiselect" || this._settings.multiselect) this.select(id, false, e.ctrlKey || e.metaKey || this._settings.multiselect == "touch", e.shiftKey);else this.select(id);
}
if (this._settings.activeItem && this.isBranch(id)) {
this.showBranch(id);
}
},
webix_treemap_header_item: function (e) {
var id = locate(e,
/*@attr*/
"webix_dm_header_id");
this.define("branch", id);
this.refresh();
},
webix_treemap_reset: function () {
this.define("branch", 0);
this.refresh();
}
},
on_dblclick: {},
on_mouse_move: {},
_getCssText: function (style) {
var css = "";
for (var property in style) {
css += property + ":" + style[property] + ";";
}
return css;
},
type: {
//normal state of item
template: template("#value#"),
header: function (obj, common) {
var id = obj.id;
var resetIcon = "<div role='button' tabindex='0' aria-label='" + i18n.aria.resetTreeMap + "' class='webix_treemap_reset'></div>";
var arr = [];
while (id) {
obj = this.getItem(id);
arr.push(common.headerItem.call(this, obj, common));
id = this.getParentId(id);
}
arr.reverse();
return resetIcon + arr.join("<span class='webix_icon wxi-angle-right webix_treemap_path_icon'></span>");
},
headerItem: function (obj) {
var template$$1 = this.config.headerTemplate(obj);
var html = "<a role=\"button\" tabindex=\"0\" aria-label=\"" + template$$1 + "\" " +
/*@attr*/
"webix_dm_header_id" + "=\"" + obj.id + "\" class=\"webix_treemap_header_item\">";
html += template$$1;
html += "</a>";
return html;
},
classname: function (obj, common, marks) {
var css = "webix_treemap_item";
if (common.css) css += " " + common.css;
if (obj.$css) {
if (_typeof(obj.$css) == "object") obj.$css = createCss(obj.$css);
css += " " + obj.$css;
}
var xy = this.$xy[obj.id];
if (marks && marks.$css) css += " " + marks.$css;
css += " webix_treemap_level_" + this.getItem(obj.id).$level;
var parentId = this.getParentId(obj.id);
if (!parentId || parentId == this._settings.branch) css += " webix_treemap_level_top";
if (this.$height - xy.top - xy.height < 1) css += " webix_treemap_item_bottom";
if (this.$width - xy.left - xy.width < 1) css += " webix_treemap_item_right";
if (common.cssClass) {
var cssClass = common.cssClass.call(this, obj, common, marks);
if (cssClass) {
if (_typeof(cssClass) == "object") {
css += " " + createCss(cssClass);
} else css += " " + cssClass;
}
}
return css;
},
templateStart: function (obj, type, marks) {
var style = "";
if (this.$xy) {
var xy = this.$xy[obj.id];
style += "width: " + xy.width + "px; height: " + xy.height + "px;";
style += "top: " + xy.top + "px; left: " + xy.left + "px;";
}
return "<div role=\"treeitem\" aria-level=\"" + obj.$level + "\" " + (marks && marks.webix_selected ? "aria-selected=\"true\" tabindex=\"0\"" : "") + " " +
/*@attr*/
"webix_dm_id" + "=\"" + obj.id + "\" class=\"" + type.classname.call(this, obj, type, marks) + "\" style=\"" + style + "\">";
},
templateEnd: template("</div>")
}
};
var view$15 = exports.protoUI(api$15, Group, TreeAPI, SelectionModel, KeysNavigation, MouseEvents, Scrollable, TreeDataLoader, proto.view, TreeRenderStack, CopyPaste, EventSystem);
/*
UI:DataView
*/
// #include ui/component.js
// #include core/mouse.js
// #include core/edit.js
// #include core/selection.js
// #include core/drag.js
// #include core/move.js
// #include core/virtual_render.js
// #include core/keynav.js
// #include core/print.js
var api$16 = {
name: "dataview",
$init: function (config) {
if (config.sizeToContent) //method need to be called before data-loaders
//so we are using unshift to place it at start
this.$ready.unshift(this._after_init_call);
var type = config.type || config.item;
var prerender = config.prerender || this.defaults.prerender || type && type.width == "auto" || config.drag == "move" || config.drag == "order";
if (!prerender && !config.autoheight) exports.extend(this, VirtualRenderStack, true);
if (config.autoheight) config.scroll = false;
if (type && type.type == "tiles") {
this._tilesPadding = type.padding || this.type.padding;
this._viewobj.firstChild.style.float = "left";
this._viewobj.firstChild.style.padding = this._tilesPadding / 2 + "px";
}
this._contentobj.className += " webix_dataview";
this._viewobj.setAttribute("role", "listbox");
},
_after_init_call: function () {
var test = create("DIV", 0, this.type.template({}));
test.className = "webix_dataview_item";
test.style.position = "absolute";
document.body.appendChild(test);
this.type.width = test.offsetWidth + this._tilesPadding;
this.type.height = test.offsetHeight + this._tilesPadding;
remove(test);
},
defaults: {
scroll: true,
datafetch: 50,
navigation: true
},
_id:
/*@attr*/
"webix_l_id",
_itemClassName: "webix_dataview_item",
_tilesPadding: 0,
_drag_direction: "x",
on_click: {
webix_dataview_item: function (e, id) {
if (this._settings.select) {
if (this._settings.select == "multiselect" || this._settings.multiselect) this.select(id, false, this._settings.multiselect == "touch" || e.ctrlKey || e.metaKey, e.shiftKey); //multiselection
else this.select(id);
}
}
},
on_dblclick: {},
on_mouse_move: {},
type: {
//normal state of item
template: template("#value#"),
//in case of dyn. loading - temporary spacer
templateLoading: template("Loading..."),
width: 160,
height: 50,
padding: 8,
classname: function (obj, common, marks) {
var css = "webix_dataview_item";
if (common.css) css += " " + common.css;
if (common.type) css += " " + common.type;
if (obj.$css) {
if (_typeof(obj.$css) == "object") obj.$css = createCss(obj.$css);
css += " " + obj.$css;
}
if (marks && marks.$css) css += " " + marks.$css;
return css;
},
aria: function (obj, common, marks) {
return "role=\"option\"" + (marks && marks.webix_selected ? " aria-selected=\"true\" tabindex=\"0\"" : " tabindex=\"-1\"");
},
templateStart: function (obj, common, marks) {
var width = common.width,
height = common.height;
var padding = 0;
if (common.type == "tiles") {
width -= common.padding;
height -= common.padding;
padding = common.padding / 2;
}
return "<div " +
/*@attr*/
"webix_l_id=\"" + obj.id + "\" class=\"" + common.classname(obj, common, marks) + "\" " + common.aria(obj, common, marks) + " style=\"margin:" + padding + "px; width:" + width + "px; height:" + height + "px; float:left; overflow:hidden;\">";
},
templateEnd: template("</div>")
},
$dropHTML: function () {
var p = this._tilesPadding;
return "<div class=\"webix_drop_area_inner\" style=\"width:".concat(this.type.width - p, "px; height:").concat(this.type.height - p, "px; margin:").concat(p / 2, "px\"></div>");
},
_calck_autoheight: function (width) {
return this._settings.height = this.type.height * Math.ceil(this.data.count() / Math.floor(width / this.type.width));
},
autoheight_setter: function (mode) {
if (mode) {
this.data.attachEvent("onStoreLoad", bind(this.resize, this));
this._contentobj.style.overflowY = "hidden";
}
return mode;
},
$getSize: function (dx, dy) {
if (this._settings.xCount && this.type.width != "auto" && !this._autowidth) this._settings.width = this.type.width * this._settings.xCount + this._tilesPadding + (this._scroll_y ? env.scrollSize : 0);
if (this._settings.yCount && this.type.height != "auto" && !this._autoheight) this._settings.height = this.type.height * this._settings.yCount + this._tilesPadding;
var width = this._settings.width || this._content_width;
if (this._settings.autoheight && width) {
this._recalk_counts();
this._calck_autoheight(width);
this.scroll_setter(false);
}
return base$1.api.$getSize.call(this, dx, dy);
},
_recalk_counts: function () {
if (this._settings.yCount && (this._autoheight || this.type.height == "auto")) {
this.type.height = Math.floor((this._content_height - this._tilesPadding) / this._settings.yCount);
this._autoheight = this._settings.yCount;
}
if (this._settings.xCount && (this._autowidth || this.type.width == "auto")) {
this.type.width = Math.floor((this._content_width - this._tilesPadding) / this._settings.xCount);
this._autowidth = this._settings.xCount;
}
return this._autoheight || this._autowidth;
},
$setSize: function (x, y) {
var c = this._settings;
if (base$1.api.$setSize.call(this, x, y)) {
if (c.autoheight && this._calck_autoheight() != this._content_height) return delay(this.resize, this);
if (this._recalk_counts() || this._render_visible_rows) this.render();
} else if (c.yCount && c.yCount != this._autoheight || c.xCount && c.xCount != this._autowidth) {
if (this._recalk_counts()) this.render();
}
}
};
var view$16 = exports.protoUI(api$16, DataMove, DragItem, MouseEvents, KeysNavigation, SelectionModel, Scrollable, CustomPrint, proto.view);
i18n.pager = {
first: "<span class='webix_icon wxi-angle-double-left'></span>",
last: "<span class='webix_icon wxi-angle-double-right'></span>",
next: "<span class='webix_icon wxi-angle-right'></span>",
prev: "<span class='webix_icon wxi-angle-left'></span>"
};
var api$17 = {
defaults: {
size: 10,
//items on page
page: 0,
//current page
group: 5,
template: "{common.pages()}",
maxWidth: 100000,
height: 30,
borderless: true
},
name: "pager",
on_click: {
//on paging button click
"webix_pager_item": function (e, id) {
this.select(id);
}
},
$init: function (config) {
this.data = this._settings;
this._dataobj = this._viewobj;
this._viewobj.className += " webix_pager" + (config.autowidth ? " webix_pager_auto" : "");
if (config.master === false || config.master === 0) this.$ready.push(this._remove_master);
},
_remove_master: function () {
this.refresh();
this.$master = {
refresh: function () {},
select: function () {}
};
},
select: function (id) {
if (this.$master && this.$master.name == "pager") return this.$master.select(id); //id - id of button, number for page buttons
switch (id) {
case "next":
id = this._settings.page + 1;
break;
case "prev":
id = this._settings.page - 1;
break;
case "first":
id = 0;
break;
case "last":
id = this._settings.limit - 1;
break;
default:
//use incoming id
break;
}
if (id < 0) id = 0;
if (id >= this.data.limit) id = this.data.limit - 1;
var old = this.data.page;
if (this.callEvent("onBeforePageChange", [id, old])) {
this.data.page = id * 1; //must be int
if (this.refresh()) {
if (!this._settings.animate || !this._animate(old, id * 1, this._settings.animate)) this.$master.refresh();
}
this.callEvent("onAfterPageChange", [id]);
}
},
_id:
/*@attr*/
"webix_p_id",
template_setter: template,
type: {
template: function (a, b) {
return a.template.call(this, a, b);
},
//list of page numbers
pages: function (obj) {
var html = ""; //skip rendering if paging is not fully initialized
if (obj.page == -1) return ""; //current page taken as center of view, calculate bounds of group
obj.$min = obj.page - Math.round((obj.group - 1) / 2);
obj.$max = obj.$min + obj.group * 1 - 1;
if (obj.$min < 0) {
obj.$max += obj.$min * -1;
obj.$min = 0;
}
if (obj.$max >= obj.limit) {
obj.$min -= Math.min(obj.$min, obj.$max - obj.limit + 1);
obj.$max = obj.limit - 1;
} //generate HTML code of buttons
for (var i = obj.$min || 0; i <= obj.$max; i++) {
html += this.button({
id: i,
index: i + 1,
selected: i == obj.page ? "_selected" : "",
label: i18n.aria.page + " " + (i + 1)
});
}
return html;
},
page: function (obj) {
return obj.page + 1;
},
//go-to-first page button
first: function () {
return this.button({
id: "first",
index: i18n.pager.first,
selected: "",
label: i18n.aria.pages[0]
});
},
//go-to-last page button
last: function () {
return this.button({
id: "last",
index: i18n.pager.last,
selected: "",
label: i18n.aria.pages[3]
});
},
//go-to-prev page button
prev: function () {
return this.button({
id: "prev",
index: i18n.pager.prev,
selected: "",
label: i18n.aria.pages[1]
});
},
//go-to-next page button
next: function () {
return this.button({
id: "next",
index: i18n.pager.next,
selected: "",
label: i18n.aria.pages[2]
});
},
button: template("<button type='button' " +
/*@attr*/
"webix_p_id" + "='{obj.id}' class='webix_pager_item{obj.selected}' aria-label='{obj.label}'>{obj.index}</button>")
},
clone: function (pager) {
if (!pager.$view) {
pager.view = "pager";
pager = ui(pager);
}
this._clone = pager;
pager.$master = this;
this._refresh_clone();
},
refresh: function () {
var s = this._settings; //max page number
s.limit = Math.ceil(s.count / s.size) || 1;
var newPage = Math.min(s.limit - 1, s.page);
if (newPage != s.page) return this.$master.setPage(newPage);
s.page = newPage;
if (newPage >= 0 && newPage != s.old_page || s.limit != s.old_limit || s.old_count != s.count) {
//refresh self only if current page or total limit was changed
this.render();
this._refresh_clone();
s.old_limit = s.limit; //save for onchange check in next iteration
s.old_page = s.page;
s.old_count = s.count;
return true;
}
},
apiOnly_setter: function (value) {
return this.$apiOnly = value;
},
_refresh_clone: function () {
if (this._clone) {
this._clone._settings.count = this._settings.count;
this._clone._settings.page = this._settings.page;
this._clone.refresh();
}
},
_animate: function (old, id, config) {
if (old == id) return false;
if (this._pgInAnimation) {
if (this._pgAnimateTimeout) {
window.clearTimeout(this._pgAnimateTimeout);
}
return this._pgAnimateTimeout = delay(this._animate, this, [old, id, config], 100);
}
var direction = id > old ? "left" : "right";
if (config.direction == "top" || config.direction == "bottom") direction = id > old ? "top" : "bottom";
if (config.flip) direction = ""; //make copy of existing view
var top = 0;
var snode = this.$master._dataobj;
var isDataTable = !!this.$master._body;
if (isDataTable) {
snode = this.$master._body;
top = snode.offsetTop;
addCss(this.$master.$view, "webix_animation");
}
var onode = snode.cloneNode(true);
onode.style.width = snode.style.width = "100%"; //redraw page
this.$master.refresh(); //append copy next to original
insertBefore(onode, snode.nextSibling, snode.parentNode);
if (isDataTable) onode.childNodes[1].scrollLeft = snode.childNodes[1].scrollLeft; //animation config
var line;
var base = config !== true ? config : {};
var aniset = exports.extend({
direction: direction,
callback: bind(function () {
aniset.callback = null;
animate.breakLine(line);
this._pgInAnimation = false;
if (this.$master._body) removeCss(this.$master.$view, "webix_animation");
}, this),
top: top,
keepViews: isDataTable
}, base); //run animation
line = animate.formLine(snode, onode, aniset);
animate([snode, onode], aniset);
this._pgInAnimation = true;
}
};
var view$17 = exports.protoUI(api$17, MouseEvents, SingleRender, base$1.view, EventSystem);
var api$18 = {
name: "comments",
defaults: {
sendAction: "click",
mode: "comments",
highlight: true
},
$init: function (config) {
this.$view.className += " webix_comments";
this._destroy_with_me = [];
config.rows = [this._configList(config)];
if (!config.moreButton) config.moreButton = template(i18n.comments.moreComments);
if (!config.readonly) {
config.rows.push(this._configForm(config));
this._initMenu();
}
this._initUsers(config.users);
this.$ready.push(this._afterInit);
},
$exportView: function () {
return this._list;
},
_afterInit: function () {
var _this = this;
// store UI blocks
this._list = this.queryView("list");
this._form = this.queryView("form");
this._sendButton = this.queryView("button");
this._input = this.queryView({
localId: "textarea"
});
if (this.config.mentions) this._initMentions(this.config.mentions); //provide data-like API
this._list.data.provideApi(this, true);
this.serialize = function () {
var data = _this._list.serialize();
var index$$1 = _this.getIndexById("$more");
if (index$$1 >= 0) data.splice(index$$1, 1);
return data;
}; //tune input zone
if (!this._settings.readonly) {
this._clickHandler = attachEvent("onClick", function (e) {
var view = $$(e);
if (view == _this._input) {
_this.focus();
} else if (view !== _this._sendButton && view !== _this._listMenu && (!_this._userList || view !== _this._userList.getList()) && (!e || (e.target.className || "").toString().indexOf("webix_comments_menu") === -1)) {
_this._changeTextarea();
}
});
this.attachEvent("onDestruct", function () {
detachEvent(this._clickHandler);
});
this._list.attachEvent("onAfterScroll", function () {
_this._listMenu.hide();
});
}
},
$onLoad: function (data, driver) {
return this._fillList(data, driver);
},
_fillList: function (data, driver) {
var _this2 = this;
var list$$1 = this._list || this.queryView({
view: "list"
});
list$$1.data.driver = driver;
var more = false; //check if datastore
if (typeof data.serialize == "function") data = data.serialize();else {
more = data.more;
data = driver.getRecords(data);
} //parse more comments
if (this._moreCall) {
this._moreCall = false;
if (data.length) {
//add spaces after 'more' button to accommodate new data
var order = list$$1.data.order,
pos$$1 = 1;
if (this._settings.mode == "chat") list$$1.data.order = _to_array([order[0]].concat(new Array(data.length), order.slice(1)));else {
var start = list$$1.getIndexById("$more");
list$$1.data.order = _to_array(order.slice(0, start).concat(new Array(data.length), order.slice(start)));
pos$$1 = start;
} //parse into defined position
list$$1.parse({
data: data,
pos: pos$$1
});
if (more) dp(this._list).ignore(function () {
_this2._list.updateItem("$more", {
value: more
});
});
if (this._settings.mode == "chat") list$$1.showItem(list$$1.getIdByIndex(data.length));
}
if (!data.length || !more) dp(this._list).ignore(function () {
_this2._list.remove("$more");
});
} //normal parse
else {
if (more && !list$$1.exists("$more")) {
more = {
id: "$more",
value: more,
$css: "webix_comments_more_item"
};
if (this._settings.mode == "chat") data.unshift(more);else data.push(more);
}
list$$1.parse(data);
if (this._settings.mode == "chat") {
//wait until rendered
list$$1.waitData.then(function () {
return list$$1.showItem(list$$1.getLastId());
});
}
}
return true;
},
$skin: function () {
layout.api.$skin.call(this);
this._inputHeight = $active.inputHeight + 6;
},
getUsers: function () {
return this._users;
},
getMenu: function () {
return this._listMenu;
},
setCurrentUser: function (id, config) {
this.config.currentUser = id;
this._form.clear(config);
this._list.refresh();
},
edit: function (id, config) {
if (!this.config.readonly && this.callEvent("onBeforeEditStart", [id])) {
this._changeTextarea(true);
var values = this._list.getItem(id);
this._form.setValues(values, false, config);
this._form.focus(); //set cursor to the last character and scroll to bottom
var node = this._form.elements.text.getInputNode();
node.scrollTop = node.scrollHeight;
setSelectionRange(node, values.text.length);
this.callEvent("onAfterEditStart", [id]);
}
},
_saveComment: function (clear) {
var values = this._form.getValues();
if (values.text) {
if (values.id) this.updateItem(values.id, values);else {
if (this.config.currentUser) values.user_id = this.config.currentUser;
values.date = new Date();
this.add(values);
this._list.showItem(values.id);
}
this._form.clear("user");
if (clear) this._input.getInputNode().value = "";
}
},
_removeComment: function (id) {
if (this._form.getValues().id == id) {
this._form.clear("user");
}
this.remove(id);
},
_changeTextarea: function (increase) {
// this behaviour is only for desktop, otherwise we will never see the button on mobile
// prevent unnecessary operations
if (env.touch || !increase == !this._text_expanded) return;
var text$$1 = this._input;
if (increase) {
this._sendButton.getParentView().show();
text$$1.define({
height: 84
});
this._text_expanded = true;
} else {
if (UIManager.hasFocus(this._sendButton)) {
UIManager.setFocus(this._list);
}
this._sendButton.getParentView().hide();
text$$1.define({
height: this._inputHeight
});
this._text_expanded = false;
}
text$$1.resize();
},
focus: function () {
var _this3 = this;
this._changeTextarea(true);
delay(function () {
_this3._input.focus();
});
},
_toggleButton: function (value) {
if (!value) value = this._input.getValue();
if (value && !this._sendButton.isEnabled()) this._sendButton.enable();else if (!value && this._sendButton.isEnabled()) this._sendButton.disable();
},
_initMenu: function () {
var _this4 = this;
this._listMenu = ui({
view: "contextmenu",
autowidth: true,
point: false,
data: [{
id: "edit",
icon: "wxi-pencil",
value: i18n.comments["edit"]
}, {
id: "remove",
icon: "wxi-trash",
value: i18n.comments["remove"]
}],
on: {
onShow: function () {
var ctx = _this4._listMenu.getContext();
_this4._list.addCss(ctx.id, "active_menu");
},
onHide: function () {
var ctx = _this4._listMenu.getContext();
_this4._list.removeCss(ctx.id, "active_menu");
},
onItemClick: function (id) {
var ctx = _this4._listMenu.getContext();
if (_this4.callEvent("onBeforeMenuAction", [id, ctx.id])) {
if (id == "edit") _this4.edit(ctx.id, "user");else if (id == "remove") {
if (i18n.comments.confirmMessage) confirm({
text: i18n.comments.confirmMessage,
callback: function (res) {
if (res) _this4._removeComment(ctx.id);
}
});else _this4._removeComment(ctx.id);
}
}
}
}
});
this._destroy_with_me.push(this._listMenu);
},
_configForm: function (config) {
var _this5 = this;
var locale = i18n.comments;
var textarea = {
view: "textarea",
localId: "textarea",
css: "webix_comments_textarea",
height: this._inputHeight,
name: "text",
placeholder: locale["placeholder"],
keyPressTimeout: 100,
on: {
onTimedKeyPress: function () {
_this5._toggleButton();
},
onChange: function (newv) {
_this5._toggleButton(newv);
},
onKeyPress: function (code, ev) {
if (code == 13) {
var action = _this5._settings.sendAction,
shift = ev.shiftKey;
if (action == "enter" && !shift || action !== "enter" && shift) {
preventEvent(ev);
_this5._saveComment(true);
}
}
}
}
};
if (config.highlight !== false) {
exports.extend(textarea, {
view: "texthighlight",
type: "textarea",
highlight: function (text$$1) {
return _this5._highlightMention(template.escape(text$$1), true);
}
}, true);
}
return {
view: "form",
minHeight: 50,
paddingX: 10,
elements: [textarea, {
hidden: !env.touch,
cols: [{}, {
view: "button",
disabled: true,
css: "webix_comments_send webix_primary",
value: locale["send"],
autowidth: true,
click: function () {
_this5._saveComment();
}
}]
}]
};
},
_highlightMention: function (text$$1, textarea) {
var _this6 = this;
if (text$$1.indexOf("@") === -1) return text$$1;
var field;
if (this._settings.highlight === "users") field = this._userList ? this._userList._settings.textValue || "value" : "value";
var getMention = textarea ? this._markedText : this._markedHTML;
return text$$1.replace(getMention, function (text$$1, name1, _c, name2) {
return _this6._wrapName(text$$1, name2 || name1, field, textarea);
});
},
_wrapName: function (text$$1, name, field, textarea) {
if (field && !this._users.find(function (user) {
return user[field] == name;
}, true)) return text$$1;
return "<span class=\"webix_comments_mention\">".concat(textarea ? text$$1 : "@" + name, "</span>");
},
_configList: function (config) {
var _this7 = this;
var css = "webix_comments_";
var type = {
height: "auto",
templateStatus: function (obj) {
return "<span class = '" + css + "status " + obj.status + "'></span>";
},
templateUser: function (obj) {
var users = _this7.getUsers();
var user = users && users.exists(obj.user_id) ? users.getItem(obj.user_id) : {};
var name = "<span class = '" + css + "name'>" + (user.value || "") + "</span>";
return name;
},
templateMenu: function () {
return _this7.config.readonly ? "" : "<span class='webix_icon wxi-dots " + css + "menu'></span>";
},
templateDate: function (obj) {
var format = wDate.dateToStr("%d %M, %H:%i");
return obj.date ? "<span class='" + css + "date'>" + format(obj.date) + "</span>" : "";
},
templateLinks: function (obj) {
var text$$1 = obj.text.replace(/(https?:\/\/[^\s]+)/g, function (match) {
match = template.escape(match);
var html = "<a target='_blank' href='" + match + "'>";
if (match.match(/.(jpg|jpeg|png|gif)$/)) html += "<img class='webix_comments_image' src='" + match + "'/>";else html += match;
return html + "</a>";
});
return text$$1;
},
templateMentioned: function (obj) {
var text$$1 = obj.text;
if (_this7._settings.mentions && _this7._settings.highlight) text$$1 = _this7._highlightMention(obj.text);
return text$$1;
},
templateText: function (obj) {
return "<div class = '" + css + "message'>" + obj.text + "</div>";
},
templateAvatar: function (obj, common) {
var avatar = "<div class='" + css + "avatar'>";
var users = _this7.getUsers();
var user = users && users.exists(obj.user_id) ? users.getItem(obj.user_id) : {};
if (user.status) avatar += common.templateStatus(user);
avatar += "<div class='" + css + "avatar_image ";
if (user.image) avatar += "'><img src = '" + user.image + "' class='" + css + "photo'>";else {
var icon = user.value ? user.value[0].toUpperCase() : "<span class='webix_icon wxi-user'></span>";
avatar += css + "avatar_text'>" + icon;
}
avatar += "</div></div>";
return avatar;
},
template: function (obj, common) {
var message$$1;
if (obj.id == "$more") {
message$$1 = "<div class='webix_comments_more'>" + _this7._settings.moreButton(obj) + "</div>";
} else {
obj = copy(obj);
var avatar = common.templateAvatar(obj, common);
var user = common.templateUser(obj, common);
var date = common.templateDate(obj, common);
var menu = common.templateMenu(obj, common);
obj.text = common.templateMentioned(obj);
obj.text = common.templateLinks(obj);
var _text = common.templateText(obj, common);
message$$1 = avatar + user + menu + date + _text;
}
return message$$1;
},
classname: function (obj, common, marks) {
var css = list.api.type.classname(obj, common, marks);
if (obj.user_id && obj.user_id == _this7._settings.currentUser || !_this7._users.count()) css += " webix_comments_current";
return css;
}
};
type = exports.extend(type, config.listItem || {}, true);
var scheme = {
$init: function (obj) {
if (obj.date) obj.date = i18n.parseFormatDate(obj.date);
}
}; // using webix.extend() for extending schemes results in wrong calls of $init()
if (config.scheme) Object.keys(config.scheme).forEach(function (k) {
scheme[k] = config.scheme[k];
});
var listConfig = {
view: "list",
navigation: false,
type: type,
scheme: scheme,
onClick: {
"webix_comments_menu": function (ev, id) {
if (_this7._listMenu.isVisible()) _this7._listMenu.hide();else {
_this7._listMenu.setContext({
obj: _this7,
id: id
});
_this7._listMenu.show(ev.target, type.menuPosition || {
pos: "left",
y: 30,
x: 10
});
}
},
"webix_comments_more": function () {
if (_this7.config.url && _this7.callEvent("onDataRequest", [])) {
_this7._moreCall = true;
var more = _this7._list.getItem("$more").value;
var pos$$1 = _this7._settings.mode == "chat" ? more : _this7._list.getIndexById("$more");
var url = proxy$5.$parse(_this7.config.url);
var callback = {
error: function () {
_this7._moreCall = false;
}
};
if (typeof url == "string") url = url + (url.indexOf("?") < 0 ? "?" : "&") + "pos=" + pos$$1 + "&more=" + more;
_this7.load(url, callback, {
pos: pos$$1,
more: more
});
}
}
}
};
if (config.save) listConfig.save = config.save;
return listConfig;
},
_initUsers: function (value) {
var _this8 = this;
if (value && value.getItem) {
this._users = value;
} else {
this._users = new DataCollection();
this._destroy_with_me.push(this._users);
if (value && typeof value === "string") this._users.load(value);else this._users.parse(value || []);
}
this._users.data.attachEvent("onStoreUpdated", function () {
return _this8._list.refresh();
});
},
_initMentions: function (value) {
var _this9 = this;
var readonly = this.config.readonly;
if (!readonly) this._initUserList(value);
if (this.config.highlight) {
if (!readonly) this._markedText = new RegExp("@(("(.*?)")|([^\\s]{1,}))", "g");
this._markedHTML = new RegExp("@((\"(.*?)\")|([^\\s]{1,}))", "g");
}
Deferred.all([this._list.waitData, this._users.waitData]).then(function () {
_this9._list.refresh();
});
this._list.data.attachEvent("onStoreUpdated", function (id, obj, mode) {
if (id && (mode === "add" || mode === "update")) {
_this9._findMentioned(obj);
}
});
},
_initUserList: function (value) {
var config = _typeof(value) != "object" ? {} : value;
if (_typeof(config.body) !== "object") config.body = {
data: this._users
};else config.body.data = this._users;
exports.extend(config, {
view: "mentionsuggest"
}, true);
var suggest = this._input.define("suggest", config);
this._input.setValueHere = function (value, data, details) {
if (value.indexOf(" ") != -1) value = "\"".concat(value, "\"");
return text.api.setValueHere.apply(this, [value, data, details]);
};
this._userList = $$(suggest);
},
_findMentioned: function (obj) {
var _this10 = this;
if (obj.text.indexOf("@") != -1) {
var field = this._userList ? this._userList._settings.textValue || "value" : "value";
var mentioned = {}; // text.replace used instead of matchAll, which not supported by older browsers
obj.text.replace(this._markedHTML, function (text$$1, name1, _b, name2) {
var name = name2 || name1;
var user = _this10._users.find(function (user) {
return user[field] == name;
}, true);
if (user && !mentioned[name]) {
_this10.callEvent("onUserMentioned", [user.id, obj.id]);
mentioned[name] = true;
} // return original text to minimize extra work
return text$$1;
});
}
}
};
var view$18 = exports.protoUI(api$18, AtomDataLoader, layout.view);
var api$19 = {
name: "timeline",
defaults: {
scroll: "auto"
},
$init: function (config) {
var _this = this;
var isHorizontal = config.layout === "x";
if (isHorizontal) {
var common = config.type;
this.type.type = common && common.type || "top";
if (isUndefined(config.scroll)) config.scroll = "x";
}
this._viewobj.className += isHorizontal ? " webix_timeline_horizontal" : " webix_timeline";
this.$blockRender = true;
this.data.provideApi(this, true);
this.data.attachEvent("onStoreUpdated", function (id, data, type) {
return _this.render(id, data, type);
});
},
_id:
/*@attr*/
"webix_tl_id",
on_click: {},
$setSize: function (x, y) {
this.$blockRender = false;
if (base.api.$setSize.call(this, x, y)) {
this.refresh();
}
},
render: function (id, data, type) {
if (!this.isVisible(this._settings.id) || this.$blockRender) return;
if (type == "update") {
var node = this.getItemNode(id); //get html element of updated item
var t = this._htmlmap[id] = this._toHTMLObject(data);
insertBefore(t, node);
remove(node);
return true;
} else {
//full reset
if (this.callEvent("onBeforeRender", [this.data])) {
this._htmlmap = null;
this._dataobj.innerHTML = this.data.getRange().map(this._toHTML, this).join("");
this.callEvent("onAfterRender", []);
}
}
return true;
},
_toHTML: function (obj) {
this.callEvent("onItemRender", [obj]);
var index$$1 = this.getIndexById(obj.id);
return this.type.templateStart.call(this, obj, this.type, index$$1) + this.type.template.call(this, obj, this.type, index$$1) + this.type.templateEnd.call(this);
},
type: {
type: "left",
classname: function (obj, common, index$$1) {
var css = "webix_timeline_item";
if (common.type !== "alternate") css += " webix_timeline_" + common.type;else {
if (this._settings.layout == "x") css += " webix_timeline_" + (index$$1 % 2 ? "bottom" : "top");else css += " webix_timeline_" + (index$$1 % 2 ? "right" : "left");
}
if (common.css) css += " " + common.css;
if (obj.$css) {
if (_typeof(obj.$css) == "object") obj.$css = createCss(obj.$css);
css += " " + obj.$css;
}
return css;
},
lineColor: function (obj) {
return obj.color;
},
templateValue: template("#value#"),
templateDetails: function (obj) {
return obj.details || "";
},
templateDate: function (obj) {
var format = wDate.dateToStr("%d %M, %Y");
return format(obj.date);
},
template: function (obj, common, index$$1) {
var padding = $active.dataPadding;
var radius = 6,
stroke = 2;
var lineColor = typeof common.lineColor == "string" ? common.lineColor : common.lineColor(obj, common);
var commonStyle = "stroke-width:".concat(stroke, "px; stroke:").concat(lineColor || $active.timelineColor, ";");
var type = common.type;
var last = index$$1 + 1 == this.count();
var circleCenter = radius + stroke / 2;
var circleSize = radius * 2 + stroke;
var innerPadding = circleSize / 2 + 7; // common properties for HTML markup, values are different for layouts
var svgStyle = "position:relative;",
dateStyle = "",
eventStyle = "",
svgWidth,
svgHeight,
x1,
y1,
x2,
y2,
cx,
cy;
var date = common.templateDate(obj, common);
var details = common.templateDetails(obj, common);
var eventText = "<div class=\"webix_timeline_value\">".concat(common.templateValue(obj, common), "</div>\n\t\t\t\t").concat(details ? "<div class=\"webix_timeline_details\">".concat(details, "</div>") : "");
if (this._settings.layout == "x") {
var height = this.$height - padding * 2;
var center = $active.listItemHeight;
var top = padding,
theight = height - center - innerPadding,
eventOffset = center + innerPadding + padding,
eventPos = "top";
if (type == "bottom") {
center = height - center;
top = center + innerPadding + padding;
eventOffset = height - center + padding + innerPadding;
eventPos = "bottom";
} else if (type == "alternate") {
center = Math.round(height * 0.5);
theight = center - innerPadding;
top = center - innerPadding + padding - 20, eventOffset = center + innerPadding + padding;
if (index$$1 % 2) {
top = eventOffset;
eventPos = "bottom";
}
}
var itemWidth = obj.$width || common.width;
if (itemWidth == "auto") itemWidth = this._getTextSize([{
text: eventText,
css: "webix_timeline_event",
height: theight
}, {
text: date,
css: "webix_timeline_date"
}]).width + padding;
dateStyle = "top:".concat(top, "px;");
eventStyle = "".concat(eventPos, ":").concat(eventOffset, "px; height:auto; max-height:").concat(theight, "px; width:inherit;");
svgWidth = itemWidth;
svgHeight = center + circleSize;
svgStyle += "left:1px;";
y1 = center;
x1 = circleCenter + radius;
y2 = center;
x2 = "100%";
cy = center;
cx = circleCenter;
} else {
var scrollSize = this._settings.scroll ? env.scrollSize : 0;
var width = this.$width - padding * 2 - scrollSize;
var _center = Math.floor(width * 0.35);
var left = padding,
rwidth = Math.floor(width * 0.65) - innerPadding;
var right = _center + innerPadding + padding,
lwidth = _center - innerPadding;
if (type == "right") {
_center = width - right + innerPadding + padding;
left = _center + innerPadding + padding;
right = padding;
} else if (type == "alternate") {
_center = Math.floor(width * 0.5);
right = _center + innerPadding + padding;
lwidth = rwidth = _center - innerPadding;
if (index$$1 % 2) {
left = right;
right = padding;
}
}
var itemHeight = obj.$height || common.height;
if (itemHeight == "auto") itemHeight = this._getTextSize([{
text: eventText,
css: "webix_timeline_event",
width: rwidth
}, {
text: date,
css: "webix_timeline_date",
width: lwidth
}]).height + padding;
dateStyle = "left:".concat(left, "px; width:").concat(lwidth, "px;");
eventStyle = "left:".concat(right, "px; width:").concat(rwidth, "px; height:").concat(itemHeight - padding, "px;");
svgWidth = _center + circleSize;
svgHeight = itemHeight;
svgStyle += "top:3px;";
x1 = _center;
y1 = circleCenter + radius;
x2 = _center;
y2 = "100%";
cx = _center;
cy = circleCenter;
}
return "<div style=\"".concat(dateStyle, "\" class=\"webix_timeline_date\">").concat(date, "</div>\n\t\t\t\t\t<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"").concat(svgWidth, "px\" height=\"").concat(svgHeight, "px\" style=\"").concat(svgStyle, "\">\n\t\t\t\t\t\t").concat(!last ? "<line x1=\"".concat(x1, "\" y1=\"").concat(y1, "\" x2=\"").concat(x2, "\" y2=\"").concat(y2, "\" class=\"webix_timeline_node\" style=\"").concat(commonStyle, "\"/>") : "", "\n\t\t\t\t\t\t<circle cx=\"").concat(cx, "\" cy=\"").concat(cy, "\" r=\"").concat(radius, "\" class=\"webix_timeline_node webix_timeline_point\" style=\"").concat(commonStyle, " fill:transparent;\" />\n\t\t\t\t\t</svg>\n\t\t\t\t\t<div class=\"webix_timeline_event\" style=\"").concat(eventStyle, "\">\n\t\t\t\t\t\t").concat(eventText, "\n\t\t\t\t\t</div>");
},
widthSize: function (obj, common) {
var width = obj.$width || common.width;
return width + (width > -1 ? "px" : "");
},
heightSize: function (obj, common) {
var height = obj.$height || common.height;
return height + (height > -1 ? "px" : "");
},
templateStart: function (obj, common, index$$1) {
// horizontal layout
if (this._settings.layout == "x") {
return "<div ".concat(
/*@attr*/
"webix_tl_id", "=\"", obj.id, "\" class=\"").concat(common.classname.call(this, obj, common, index$$1), "\" style=\"width:").concat(common.widthSize(obj, common), ";\">");
}
return "<div ".concat(
/*@attr*/
"webix_tl_id", "=\"", obj.id, "\" class=\"").concat(common.classname.call(this, obj, common, index$$1), "\" style=\"height:").concat(common.heightSize(obj, common), ";\">");
},
templateEnd: template("</div>")
},
_getTextSize: function (c) {
var d = create("DIV");
d.style.cssText = "visibility:hidden;position:absolute;top:0px;left:0px;overflow:hidden;";
document.body.appendChild(d);
var width = 0;
var height = 0;
for (var i = 0; i < c.length; i++) {
d.className = "webix_measure_size " + c[i].css;
d.style.width = c[i].width ? c[i].width + "px" : "auto";
d.style.height = c[i].height ? c[i].height + "px" : "auto";
d.innerHTML = c[i].text;
width = Math.max(width, d.offsetWidth + 1);
height = Math.max(height, d.offsetHeight + 1);
}
remove(d);
return {
width: width,
height: height
};
},
templateValue_setter: function (config) {
this.type.templateValue = template(config);
},
templateDetails_setter: function (config) {
this.type.templateDetails = template(config);
},
templateDate_setter: function (config) {
this.type.templateDate = template(config);
},
$skin: function () {
this.type.height = $active.timelineItemHeight;
this.type.width = $active.timelineItemHeight * 3;
}
};
var view$19 = exports.protoUI(api$19, Scrollable, RenderStack, DataLoader, MouseEvents, EventSystem, AutoTooltip, base.view);
// #include ui/list.js
var api$1a = {
name: "menu",
_listClassName: "webix_menu",
$init: function (config) {
if (config.autowidth) {
this._autowidth_submenu = true;
delete config.autowidth;
}
this._init_mouse_events();
this.data.attachEvent("onStoreUpdated", bind(function () {
this._hide_sub_menu();
}, this));
this.attachEvent("onItemClick", function (id, e, trg) {
var item = this.getItem(id);
if (item) {
if (item.$template) return;
var parent = this.getTopMenu();
if (!parent.callEvent("onMenuItemClick", [id, e, trg])) {
e.showpopup = parent._settings.id;
return;
}
if (this != parent) parent._call_onclick(id, e, trg); //click on group - do not close submenus
if (!this.type._submenu(item) && !parent._show_child_on_click) {
parent._hide_sub_menu(true);
if (parent._hide_on_item_click) parent.hide();
} else {
if (env.touch || this === parent && parent._settings.openAction == "click") {
this._mouse_move_activation(id, trg);
} //do not close popups when clicking on menu folder
e.showpopup = parent._settings.id;
}
}
});
this.attachEvent("onKeyPress", function (code) {
if (code === 9) this.getTopMenu()._hide_sub_menu();else if (code === 13 || code === 32) {
var sel = this.getSelectedId(),
node;
if (sel) node = this.getItemNode(sel);
if (node) triggerEvent(node, "MouseEvents", "click");
}
});
this.data.attachEvent("onClearAll", function () {
this._hidden_items = [];
});
this.data._hidden_items = [];
this._viewobj.setAttribute("role", "menubar"); //component can create new view
this._destroy_with_me = [];
},
_init_mouse_events: function () {
this.attachEvent("onMouseMove", function (id, e, target) {
if (!this._menu_was_activated()) return;
this._mouse_move_activation(id, target);
});
this.attachEvent("onMouseOut", function (e) {
if (this._menu_was_activated() && this._settings.openAction == "click") return;
if (!this._child_menu_active && (!e.relatedTarget || !this.$view.contains(e.relatedTarget))) this._hide_sub_menu();
});
},
sizeToContent: function () {
if (this._settings.layout == "y") {
var texts = [];
var isSubmenu = false;
this.data.each(function (obj) {
texts.push(this._toHTML(obj));
if (obj.submenu) isSubmenu = true;
}, this); // text width + padding + borders+ arrow
this.config.width = getTextSize(texts, this.$view.className).width + 8 * 2 + 2 + (isSubmenu ? 15 : 0);
this.resize();
} else assert(false, "sizeToContent will work for vertical menu only");
},
getTopMenu: function () {
var parent = this;
while (parent._parent_menu) {
parent = $$(parent._parent_menu);
}
return parent;
},
_auto_height_calc: function (count) {
if (this._settings.autoheight) count = this.count();
var value = this.count(),
height = 0;
for (var i = 0; i < count; i++) {
var item = this.data.pull[this.data.order[i]];
if (item && item.$template == "Separator") {
height += 4;
if (!this._settings.autoheight) count++;
} else height += this.type.height;
}
this._onoff_scroll(count && count < value, "y");
return height;
},
on_mouse_move: {},
type: {
_submenu: function (obj) {
return obj.submenu || obj.data || obj.item;
},
css: "menu",
width: "auto",
aria: function (obj, common, marks) {
return "role=\"menuitem\"" + (marks && marks.webix_selected ? " aria-selected=\"true\" tabindex=\"0\"" : "tabindex=\"-1\"") + (common._submenu(obj) ? "aria-haspopup=\"true\"" : "") + (obj.disabled ? " aria-disabled=\"true\" webix_disabled=\"true\"" : "");
},
templateStart: function (obj, common, mark) {
if (obj.$template === "Separator" || obj.$template === "Spacer") {
return "<div " +
/*@attr*/
"webix_l_id" + "=\"#id#\" role=\"separator\" tabindex=\"-1\" class=\"webix_context_" + obj.$template.toLowerCase() + "\">";
}
var link = (obj.href ? " href='" + obj.href + "' " : "") + (obj.target ? " target='" + obj.target + "' " : "");
return list.api.type.templateStart(obj, common, mark).replace(/^<div/, "<a " + link) + (common._submenu(obj) && common.subsign ? "<div class='webix_submenu_icon'></div>" : "");
},
templateEnd: function (obj) {
return obj.$template === "Separator" || obj.$template === "Spacer" ? "</div>" : "</a>";
},
templateSeparator: template("<div class='sep_line'></div>"),
templateSpacer: template("<div></div>")
},
getMenu: function (id) {
if (!this.data.pull[id]) {
for (var subid in this.data.pull) {
var obj = this.getItem(subid);
if (obj.submenu) {
var search = this._get_submenu(obj).getMenu(id);
if (search) return search;
}
}
} else return this;
},
getSubMenu: function (id) {
var menu = this.getMenu(id);
var obj = menu.getItem(id);
return obj.submenu ? menu._get_submenu(obj) : null;
},
getMenuItem: function (id) {
return this.getMenu(id).getItem(id);
},
_get_submenu: function (data) {
var sub = $$(data.submenu);
if (!sub) {
data.submenu = this._create_sub_menu(data);
sub = $$(data.submenu);
}
return sub;
},
_menu_was_activated: function () {
if (env.touch) return false;
var top = this.getTopMenu();
if (top._settings.openAction == "click") {
var sub = top._open_sub_menu;
if (sub && $$(sub).isVisible()) return true;
return false;
}
return true;
},
_mouse_move_activation: function (id, target) {
var data = this.getItem(id);
if (!data) return; //clear flag of submenu usage
this._child_menu_active = null; //hide previously opened sub-menu
if (this._open_sub_menu && data.submenu != this._open_sub_menu) this._hide_sub_menu(true); //show submenu
if (this.type._submenu(data) && !this.config.hidden) {
var sub = this._get_submenu(data);
if (!this.isItemEnabled(id)) return;
sub.show(target, {
pos: this._settings.subMenuPos
});
sub._parent_menu = this._settings.id;
this._open_sub_menu = data.submenu;
}
},
disableItem: function (id) {
var menu = this.getMenu(id);
if (menu) menu._set_item_disabled(id, true);
},
enableItem: function (id) {
var menu = this.getMenu(id);
if (menu) menu._set_item_disabled(id, false);
},
isItemEnabled: function (id) {
var menu = this.getMenu(id);
if (menu) return list.api.isItemEnabled.apply(menu, arguments);
},
_set_item_hidden: function (id, state) {
var menu = this.data;
if (menu._hidden_items[id] != state) {
menu._hidden_items[id] = state;
menu.filter(function (obj) {
return !menu._hidden_items[obj.id];
});
this.resize();
}
},
hideItem: function (id) {
var menu = this.getMenu(id);
if (menu) menu._set_item_hidden(id, true);
},
showItem: function (id) {
var menu = this.getMenu(id);
if (menu) {
menu._set_item_hidden(id, false);
return list.api.showItem.call(menu, id);
}
},
_hide_sub_menu: function (mode) {
if (this._open_sub_menu) {
//recursive sub-closing
var sub = $$(this._open_sub_menu);
if (sub._hide_sub_menu) //custom context may not have submenu
sub._hide_sub_menu(mode);
if (mode || !sub._show_on_mouse_out) {
sub.hide();
this._open_sub_menu = null;
}
}
},
_create_sub_menu: function (data) {
var listConfig = {
view: "submenu",
data: this.type._submenu(data)
};
var settings = this.getTopMenu()._settings.submenuConfig;
if (settings) exports.extend(listConfig, settings, true);
var parentData = this.getMenuItem(data.id);
if (parentData && parentData.config) exports.extend(listConfig, parentData.config, true);
var menu = ui(listConfig);
this._destroy_with_me.push(menu);
menu._parent_menu = this;
return menu._settings.id;
},
_skip_item: function (id, prev, dir) {
var item = this.getItem(id);
if (item.$template == "Separator" || item.$template == "Spacer" || !this.isItemEnabled(id)) {
id = this.getNextId(id, dir) || null;
return id && id != prev ? this._skip_item(id, prev, dir) : prev;
}
return id;
},
$skin: function () {
list.api.$skin.call(this);
this.type.height = $active.menuHeight;
},
defaults: {
scroll: "",
layout: "x",
mouseEventDelay: 100,
subMenuPos: "bottom"
}
};
var view$1a = exports.protoUI(api$1a, list.view);
var menu = {
api: api$1a,
view: view$1a
};
var api$1b = {
name: "submenu",
$init: function () {
this._body_cell = clone(this._dummy_cell_interface);
this._body_cell._view = this;
this.attachEvent("onBeforeShow", function () {
if (this.getTopMenu()._autowidth_submenu && this.sizeToContent && !this.isVisible()) this.sizeToContent();
});
this._dataobj.setAttribute("role", "menu");
},
$skin: function () {
menu.api.$skin.call(this);
popup.api.$skin.call(this);
this.type.height = $active.menuHeight;
},
_init_mouse_events: function () {
this.attachEvent("onMouseMove", function (id, e, target) {
if (!this._menu_was_activated()) return;
this._mouse_move_activation(id, target);
});
this.attachEvent("onMouseOut", function (e) {
if (this.getTopMenu()._settings.openAction == "click") return;
if (!this._child_menu_active && !this._show_on_mouse_out && e.relatedTarget && !this.$view.contains(e.relatedTarget)) this.hide();
}); //inform parent that focus is still in menu
this.attachEvent("onMouseMoving", function () {
if (this._parent_menu) $$(this._parent_menu)._child_menu_active = true;
});
},
_dummy_cell_interface: {
$getSize: function (dx, dy) {
//we saving height and width, as list can hardcode new values
var h = this._view._settings.height * 1;
var w = this._view._settings.width * 1;
var size = menu.api.$getSize.call(this._view, dx, dy); //restoring
this._view._settings.height = h;
this._view._settings.width = w;
return size;
},
$setSize: function (x, y) {
if (this._view._settings.scroll) this._view._bodyobj.style.height = y + "px";
},
destructor: function () {
this._view = null;
}
},
//ignore body element
body_setter: function () {},
getChildViews: function () {
return [];
},
defaults: {
width: 150,
subMenuPos: "right",
layout: "y",
autoheight: true
},
type: {
height: $active.menuHeight,
subsign: true
}
};
var view$1b = exports.protoUI(api$1b, menu.view, popup.view);
var submenu = {
api: api$1b,
view: view$1b
};
var api$1c = {
name: "sidemenu",
defaults: {
animate: true,
position: "left",
width: 200,
borderless: true
},
$init: function () {
this.$view.className += " webix_sidemenu";
},
$skin: function () {
popup.api.$skin.call(this);
this.defaults.padding = 0;
},
position_setter: function (value) {
var prevPosition = this._settings.position;
if (prevPosition) removeCss(this.$view, " webix_sidemenu_" + prevPosition);
addCss(this.$view, " webix_sidemenu_" + value);
return value;
},
$getSize: function () {
var sizes = window$1.api.$getSize.apply(this, arguments);
this._desired_sizes = sizes;
return sizes;
},
$setSize: function (x, y) {
base$1.api.$setSize.call(this, x, y);
x = this._content_width - this._settings.padding * 2;
y = this._content_height - this._settings.padding * 2;
this._contentobj.style.padding = this._settings.padding + "px";
this._headobj.style.display = "none";
this._bodyobj.style.height = y + "px";
this._body_cell.$setSize(x, y);
},
show: function () {
if (!this.callEvent("onBeforeShow", arguments)) return false;
this._settings.hidden = false;
this._viewobj.style.zIndex = zIndex(this._settings.zIndex);
if (this._settings.modal || this._modal) {
this._modal_set(true);
this._modal = null; // hidden_setter handling
}
this._viewobj.style.display = "block";
this._render_hidden_views();
if (this._settings.position) this._setPosition();
this._hide_timer = 1;
delay(function () {
this._hide_timer = 0;
}, this, [], env.touch ? 400 : 100);
if (this.config.autofocus) {
this._prev_focus = UIManager.getFocus();
UIManager.setFocus(this);
}
if (-1 == state._popups.find(this)) state._popups.push(this);
this.callEvent("onShow", []);
},
_setPosition: function (x) {
var width,
height,
maxWidth,
maxHeight,
position,
left = 0,
top = 0,
state$$1 = {};
this.$view.style.position = "fixed";
maxWidth = document.documentElement.offsetWidth;
maxHeight = document.documentElement.offsetHeight;
width = this._desired_sizes[0] || maxWidth;
height = this._desired_sizes[2] || maxHeight;
assert(width && height, "Attempt to show not rendered window");
position = this._settings.position;
if (position == "top") {
width = maxWidth;
} else if (position == "right") {
height = maxHeight;
left = maxWidth - width;
} else if (position == "bottom") {
width = maxWidth;
top = maxHeight - height;
} else {
height = maxHeight;
}
state$$1 = {
left: left,
top: top,
width: width,
height: height,
maxWidth: maxWidth,
maxHeight: maxHeight
};
if (typeof this._settings.state == "function") this._settings.state.call(this, state$$1);
this._state = state$$1;
this.$setSize(state$$1.width, state$$1.height);
if (typeof x == "undefined" && this._isAnimationSupported()) {
removeCss(this.$view, "webix_animate", true); // set initial state
this._animate[this._settings.position].beforeShow.call(this, state$$1); // set apply animation css
delay(function () {
addCss(this.$view, "webix_animate", true);
}, this, null, 1); // animate popup
delay(function () {
this._animate[this._settings.position].show.call(this, state$$1);
}, this, null, 10);
} else {
if (this._settings.position === "right") state$$1.left = state$$1.right ? maxWidth - state$$1.width - state$$1.right : maxWidth - state$$1.width;
this.setPosition(state$$1.left, state$$1.top);
}
},
_state: {},
_isAnimationSupported: function () {
return animate.isSupported() && this._settings.animate && !(env.isIE && navigator.appVersion.indexOf("MSIE 9") != -1);
},
hidden_setter: function (value) {
if (value) this.hide();else this.show();
return !!value;
},
_animate: {
left: {
beforeShow: function (state$$1) {
this.$view.style.left = -state$$1.width + "px";
this.$view.style.top = state$$1.top + "px";
},
show: function (state$$1) {
this.$view.style.left = state$$1.left ? state$$1.left + "px" : "0px";
},
hide: function (state$$1) {
this.$view.style.left = -state$$1.width + "px";
}
},
right: {
beforeShow: function (state$$1) {
this.$view.style.left = "auto";
this.$view.style.right = -state$$1.width + "px";
this.$view.style.top = state$$1.top + "px";
},
show: function (state$$1) {
this.$view.style.right = state$$1.right ? state$$1.right + "px" : "0px";
},
hide: function (state$$1) {
this.$view.style.right = -state$$1.width + "px";
}
},
top: {
beforeShow: function (state$$1) {
this.setPosition(state$$1.left, state$$1.top);
this.$view.style.height = "0px";
this._bodyobj.style.height = "0px";
},
show: function (state$$1) {
this.$view.style.height = state$$1.height + "px";
this._bodyobj.style.height = state$$1.height + "px";
},
hide: function () {
this.$view.style.height = "0px";
this._bodyobj.style.height = "0px";
}
},
bottom: {
beforeShow: function (state$$1) {
this.$view.style.left = state$$1.left + "px";
this.$view.style.top = "auto";
var bottom = state$$1.bottom != undefined ? state$$1.bottom : state$$1.maxHeight - state$$1.top - state$$1.height;
this.$view.style.bottom = bottom + "px";
this.$view.style.height = "0px";
},
show: function (state$$1) {
this.$view.style.height = state$$1.height + "px";
},
hide: function () {
this.$view.style.height = "0px";
}
}
},
_hiding_process: function () {
var maxWidth = document.documentElement.offsetWidth;
var maxHeight = document.documentElement.offsetHeight;
if (this._isAnimationSupported() && maxWidth == this._state.maxWidth && maxHeight == this._state.maxHeight) {
// call 'hide' animation handler
this._animate[this._settings.position].hide.call(this, this._state); // hide popup
var tid = event$1(this.$view, env.transitionEnd, bind(function () {
this._hide_callback();
eventRemove(tid);
}, this));
} else this._hide_callback();
}
};
var view$1c = exports.protoUI(api$1c, popup.view);
var api$1d = {
name: "sidebar",
defaults: {
type: "sideBar",
activeTitle: true,
select: true,
scroll: false,
collapsed: false,
collapsedWidth: 44,
position: "left",
width: 250,
mouseEventDelay: 10
},
$skin: function () {
this.defaults.titleHeight = $active.sidebarTitleHeight;
},
$init: function (config) {
this._fullWidth = isUndefined(config.width) ? this.defaults.width : config.width;
this._settings.width = config.width = config.collapsed ? config.collapsedWidth || this.defaults.collapsedWidth : this._fullWidth;
this.$view.className += " webix_sidebar";
this.$ready.push(this._initSidebar);
this.$ready.push(this._initContextMenu);
this.data._scheme_init = function (obj) {
if (obj.data) obj.menu = copy(obj.data);else if (obj.item) //xml child records, can be {} or []
obj.menu = copy(obj.item.length ? obj.item : [obj.item]);
};
config.multiselect = false;
},
on_context: {},
on_mouse_move: {},
_initSidebar: function () {
this.attachEvent("onBeforeOpen", function (id) {
if (!this.config.multipleOpen) {
var open = this.getOpenItems();
for (var i = 0; i < open.length; i++) {
if (this.getParentId(id) == this.getParentId(open[i])) this.close(open[i]);
}
}
return !this.config.collapsed;
});
this.attachEvent("onItemClick", function (id, ev, node) {
var popup = this.getPopup();
if (popup && !popup.config.hidden) ev.showpopup = popup.config.id;
if (env.touch) this._showPopup(id, node);
});
this.attachEvent("onBeforeSelect", function (id) {
if (!this.getItem(id).$count) {
this.clearCss("webix_sidebar_selected");
return true;
}
return false;
});
this.attachEvent("onAfterSelect", function (id) {
this._markMenu(this, id, !$active.sidebarMarkAll);
this.getPopup()._onMasterSelect(id);
});
this.attachEvent("onAfterUnSelect", function () {
this.clearCss("webix_sidebar_selected");
});
this.attachEvent("onMouseMove", function (id, ev, node) {
this._showPopup(id, node);
});
this.attachEvent("onMouseOut", function () {
if (this.config.collapsed) this.getPopup().masterId = null;
});
},
_showPopup: function (id, node) {
if (this.config.collapsed) {
var popup = this.getPopup();
if (popup) {
this._updateTitle(id, popup);
this._updateList(id, popup);
popup.masterId = id;
popup.show(node, {
x: this.config.position == "left" ? this.config.collapsedWidth : -popup.config.width,
y: -1
});
}
}
},
_updateTitle: function (id, popup) {
var title = popup.getBody().getChildViews()[0];
if (!title || popup.masterId == id) return;
title.parse(this.getItem(id));
var selectedId = this.getSelectedId();
if (selectedId == id) {
addCss(title.$view, "webix_selected", true);
} else {
removeCss(title.$view, "webix_selected");
}
},
_updateList: function (id, popup) {
var list = popup.getBody().getChildViews()[1];
if (!list || popup.masterId == id) return;
if (this.exists(popup.masterId) && this.getItem(popup.masterId).menu) this.updateItem(popup.masterId, {
menu: list.data.serialize()
});
list.clearCss("webix_sidebar_selected");
list.unselectAll();
var data = copy(this.getItem(id).menu || []);
if (data.length) {
list.show();
list.data.importData(data);
var selectedId = this.getSelectedId();
if (list.exists(selectedId)) list.select(selectedId);else if (selectedId) this._markMenu(list, selectedId);
} else {
list.hide();
list.data.clearAll();
}
},
_initContextMenu: function () {
var master = this,
config = master.config,
popup;
if (config.popup) {
popup = $$(config.popup);
}
if (!popup) {
var dirClassName = config.position == "left" ? "webix_sidebar_popup_left" : "webix_sidebar_popup_right";
var subMenuPos = config.position == "left" ? "right" : "left";
var menuTemplate = function (obj) {
var icon = "wxi-angle-" + (config.position == "left" ? "right" : "left");
var arrow = obj.submenu || obj.data || obj.item ? "<div class=\"webix_icon " + icon + "\"></div>" : "";
return arrow + obj.value;
};
var css = config.css ? " " + config.css : "";
var popupConfig = {
view: "popup",
css: "webix_sidebar_popup " + dirClassName + css,
autofit: false,
width: this._fullWidth - this.config.collapsedWidth,
borderless: true,
padding: 0,
body: {
rows: [{
view: "template",
borderless: true,
css: "webix_sidebar_popup_title",
template: "#value#",
height: this.config.titleHeight + 2,
onClick: {
webix_template: function () {
var id = this.getValues().id;
if (!master.getItem(id).$count) master.select(id);
}
}
}, {
view: "menu",
submenu: "data",
layout: "y",
subMenuPos: subMenuPos,
select: true,
borderless: true,
autoheight: true,
css: "webix_sidebar_popup_list " + dirClassName + css,
template: menuTemplate,
type: {
subsign: false
},
submenuConfig: {
padding: 0,
subMenuPos: subMenuPos,
template: menuTemplate,
select: true,
type: {
subsign: false
},
css: "webix_sidebar_popup_list " + dirClassName + css,
on: {
onShow: function () {
this.clearCss("webix_sidebar_selected");
this.unselectAll();
var sel = master.getSelectedId();
if (sel && this.exists(sel)) this.select(sel);else if (sel) master._markMenu(this, sel);
},
onBeforeSelect: function (id) {
if (this.getSubMenu(id)) return false;
},
onAfterSelect: function (id) {
var menu = master.getPopup().queryView({
view: "menu"
});
var parent = master.getParentId(id);
while (parent) {
var sub = menu.getMenu(parent);
if (sub) {
sub.unselectAll();
master._markMenu(sub, id);
}
parent = master.getParentId(parent);
}
master._markMenu(this, id);
}
}
},
on: {
onBeforeSelect: function (id) {
if (this.getSubMenu(id)) return false;
},
onMenuItemClick: function (id) {
if (!this.getSubMenu(id)) master.select(id);
}
}
}]
}
};
exports.extend(popupConfig, config.popup || {}, true);
popup = ui(popupConfig);
popup._onMasterSelect = function (id) {
if (master.config.collapsed && master.getItem(id).$level == 1) {
var title = popup.getBody().getChildViews()[0];
if (title) addCss(title.$view, "webix_selected", true);
}
};
popup.queryView({
view: "menu"
})._show_child_on_click = true;
}
popup.attachEvent("onBeforeShow", function () {
return config.collapsed;
});
this._destroy_with_me = [popup];
config.popupId = popup.config.id;
_event(document.body, "mousemove", function (e) {
var trg = e.target;
if (!popup.config.hidden && !popup.$view.contains(trg) && !this.$view.firstChild.contains(trg) && !popup.queryView({
view: "menu"
})._open_sub_menu) {
popup.hide();
}
}, {
bind: this
});
},
_markMenu: function (view, sel, topOnly) {
var css = "webix_sidebar_selected";
view.data.each(function (obj) {
if (this._isChild(sel, obj.id) && (!topOnly || this.getParentId(obj.id) == "0")) view.addCss(obj.id, css);else if (view.hasCss(obj.id, css)) view.removeCss(obj.id, css);
}, this);
},
_isChild: function (cid, pid) {
var parent = this.getParentId(cid);
if (pid == parent) return true;
if (parent) return this._isChild(parent, pid);
return false;
},
getPopup: function () {
return $$(this.config.popupId);
},
position_setter: function (value) {
var newPos = value;
var oldPos = value == "left" ? "right" : "left";
removeCss(this.$view, "webix_sidebar_" + oldPos);
addCss(this.$view, "webix_sidebar_" + newPos, true);
var popup = this.getPopup();
if (popup) {
var popupEl = popup.$view;
removeCss(popupEl, "webix_sidebar_popup_" + oldPos);
addCss(popupEl, "webix_sidebar_popup_" + newPos, true);
}
return value;
},
select: function (id) {
//ignore multiple selection
if (id) {
if (isArray(id)) id = id.pop();
tree.api.select.call(this, id);
}
},
selectAll: function () {},
collapse: function () {
this.define("collapsed", true);
},
expand: function () {
this.define("collapsed", false);
},
toggle: function () {
var collapsed = !this.config.collapsed;
this.define("collapsed", collapsed);
},
collapsed_setter: function (value) {
var width;
if (!value) {
width = this._fullWidth;
this.type.collapsed = false;
addCss(this.$view, "webix_sidebar_expanded", true);
} else {
width = this.config.collapsedWidth;
this.closeAll();
this.type.collapsed = true;
removeCss(this.$view, "webix_sidebar_expanded");
}
if (!isUndefined(width) && width !== this.config.width) {
//skip first rendering
this.define("width", width);
this.resize();
}
return value;
},
getState: function () {
var state = {
collapsed: this.config.collapsed
};
exports.extend(state, TreeAPI.getState.call(this));
return state;
},
setState: function (state) {
TreeAPI.setState.call(this, state);
this.define("collapsed", state.collapsed);
}
};
type(tree.view, {
name: "sideBar",
height: "auto",
template: function (obj, common) {
if (common.collapsed) return common.icon(obj, common);
return common.arrow(obj, common) + common.icon(obj, common) + "<span>" + obj.value + "</span>";
},
arrow: function (obj) {
var html = "";
for (var i = 1; i <= obj.$level; i++) {
if (i == obj.$level && obj.$count) {
var icon = "wxi-angle-" + (obj.open ? "down" : "left");
var className = "webix_sidebar_dir_icon webix_icon " + icon;
html += "<span class='" + className + "'></span>";
}
}
return html;
},
icon: function (obj) {
var style = "";
if (obj.$level > 2) {
style = "style=\"padding-left:" + 40 * (obj.$level - 2) + "px\"";
}
if (obj.icon) return "<span class='webix_icon webix_sidebar_icon " + obj.icon + "' " + style + "></span>";
return "<span " + style + "></span>";
}
});
var view$1d = exports.protoUI(api$1d, tree.view);
var api$1e = {
name: "context"
};
var view$1e = exports.protoUI(api$1e, ContextHelper, popup.view);
var api$1f = {
name: "contextmenu",
_hide_on_item_click: true,
$init: function (config) {
if (config.submenuConfig) exports.extend(config, config.submenuConfig);
}
};
var view$1f = exports.protoUI(api$1f, ContextHelper, submenu.view);
var api$1g = {
name: "vscroll",
$apiOnly: true,
defaults: {
scroll: "x",
scrollPos: 0,
scrollSize: 18,
scrollVisible: 1,
zoom: 1
},
$init: function (config) {
var dir = config.scroll || "x";
var node = this._viewobj = toNode(config.container);
node.className += " webix_vscroll_" + dir;
node.innerHTML = "<div class='webix_vscroll_body'></div>";
_event(node, "scroll", this._onscroll, {
bind: this
});
this._last_set_size = 0;
},
$skin: function () {
this.defaults.scrollStep = $active.rowHeight;
},
reset: function () {
this.config.scrollPos = 0;
this._viewobj[this.config.scroll == "x" ? "scrollLeft" : "scrollTop"] = 0;
},
_check_quantum: function (value) {
if (value > 1500000) {
this._settings.zoom = value / 1000000;
value = 1000000;
} else {
this._settings.zoom = 1;
}
return value;
},
scrollWidth_setter: function (value) {
value = this._check_quantum(value);
this._viewobj.firstChild.style.width = value + "px";
return value;
},
scrollHeight_setter: function (value) {
value = this._check_quantum(value);
this._viewobj.firstChild.style.height = value + "px";
return value;
},
sizeTo: function (value, top, bottom) {
value = value - (top || 0) - (bottom || 0);
var width = this._settings.scrollSize; //IEFix
//IE doesn't react on scroll-click if it has not at least 1 px of visible content
if (env.isIE && width) width += 1;
if (!width && this._settings.scrollVisible && !env.$customScroll) {
this._viewobj.style.pointerEvents = "none";
width = 14;
}
if (!width) {
this._viewobj.style.display = "none";
} else {
this._viewobj.style.display = "block";
if (top) this._viewobj.style.marginTop = top + "px";
this._viewobj.style[this._settings.scroll == "x" ? "width" : "height"] = Math.max(0, value) + "px";
this._viewobj.style[this._settings.scroll == "x" ? "height" : "width"] = width + "px";
}
this._last_set_size = value;
},
getScroll: function () {
return Math.round(this._settings.scrollPos * this._settings.zoom);
},
getSize: function () {
return Math.round((this._settings.scrollWidth || this._settings.scrollHeight) * this._settings.zoom);
},
_fixSize: function () {
var pos$$1 = this.getScroll();
var max = Math.max(this.getSize() - this._last_set_size, 0);
if (pos$$1 > max) this.scrollTo(max);
},
scrollTo: function (value) {
if (value < 0) value = 0;
var config = this._settings;
value = value / config.zoom; //safety check for negative values
if (value < 0) value = 0; //apply new position
if (value != this._settings.scrollPos) {
this._viewobj[config.scroll == "x" ? "scrollLeft" : "scrollTop"] = value;
this._onscroll_inner(value, true);
return true;
}
},
_onscroll: function () {
var x = this._viewobj[this._settings.scroll == "x" ? "scrollLeft" : "scrollTop"];
if (Math.floor(x) != Math.floor(this._settings.scrollPos)) this._onscroll_inner(x, false);
},
_onscroll_inner: function (value, api) {
//size of scroll area
var height = this._settings.scrollWidth || this._settings.scrollHeight; //if we scrolled to the end of the area
if (value >= height - this._last_set_size / (api ? this._settings.zoom : 1)) {
//set value so the last row is visible
value = Math.max(0, height - this._last_set_size / this._settings.zoom);
}
this._settings.scrollPos = value || 0;
this.callEvent("onScroll", [this.getScroll()]);
},
activeArea: function (area, x_mode) {
this._x_scroll_mode = x_mode;
_event(area, "wheel", this._on_wheel, {
bind: this,
passive: false
});
this._add_touch_events(area);
},
_add_touch_events: function (area) {
if (!env.touch && window.navigator.pointerEnabled) {
addCss(area, "webix_scroll_touch_ie", true);
_event(area, "pointerdown", function (e) {
if (e.pointerType == "touch" || e.pointerType == "pen") {
this._start_context = Touch._get_context_m(e);
this._start_scroll_pos = this.getScroll();
}
}, {
bind: this
});
event$1(document.body, "pointermove", function (e) {
var scroll;
if (this._start_context) {
this._current_context = Touch._get_context_m(e);
if (this._settings.scroll == "x") {
scroll = this._current_context.x - this._start_context.x;
} else if (this._settings.scroll == "y") {
scroll = this._current_context.y - this._start_context.y;
}
if (scroll && Math.abs(scroll) > 5) {
this.scrollTo(this._start_scroll_pos - scroll);
}
}
}, {
bind: this
});
event$1(window, "pointerup", function () {
if (this._start_context) {
this._start_context = this._current_context = null;
}
}, {
bind: this
});
}
},
_on_wheel: function (e) {
var dir = 0;
var step = e.deltaMode === 0 ? 30 : 1;
if (e.ctrlKey) return false;
if (e.deltaX && Math.abs(e.deltaX) > Math.abs(e.deltaY)) {
//x-scroll
if (this._x_scroll_mode && this._settings.scrollVisible) dir = e.deltaX / step;
} else {
//y-scroll
if (!this._x_scroll_mode && this._settings.scrollVisible) {
if (isUndefined(e.deltaY)) dir = e.detail;else dir = e.deltaY / step;
}
} // Safari requires target preserving
// (used in _check_rendered_cols of DataTable)
if (env.isSafari) this._scroll_trg = e.target;
if (dir) if (this.scrollTo(this.getScroll() + dir * this._settings.scrollStep)) return preventEvent(e);
}
};
var view$1g = exports.protoUI(api$1g, EventSystem, Settings);
var temp$3 = {};
var Mixin = {
filterByAll: function () {
var _this2 = this;
//we need to use dynamic function creating
var server = false;
this.data.silent(function () {
var _this = this;
this.filter();
var first = false;
var _loop = function (key) {
assert(key, "empty column id for column with filtering");
if (!_this.isColumnVisible(key)) return "continue";
var record = _this._filter_elements[key];
var originvalue = record[2].getValue(record[0]); //saving last filter value, for usage in getState
var inputvalue = originvalue;
if (record[1].prepare) inputvalue = record[1].prepare.call(record[2], inputvalue, record[1], _this); //preserve original value
record[1].value = originvalue;
var compare = record[1].compare;
if (!_this.callEvent("onBeforeFilter", [key, inputvalue, record[1]])) return "continue";
if (record[2].$server || server) {
//if one of filters is server side, do not run any client side filters
server = true;
} else {
if (inputvalue === "") return "continue";
if (compare) {
compare = _this._multi_compare(key, compare);
_this.filter(bind(function (obj, value) {
if (!obj) return false;
return compare(obj[key], value, obj);
}, _this), inputvalue, first);
} else _this.filter(key, inputvalue, first);
first = true;
}
};
for (var key in this._filter_elements) {
var _ret = _loop(key);
if (_ret === "continue") continue;
}
}, this);
if (server) {
if (!this._skip_server_op) this.loadNext(0, 0, 0, 0, true, true).then(function () {
return _this2._on_after_filter();
});else this._skip_server_op.filter = true;
} else {
this.refresh();
this.callEvent("onAfterFilter", []);
}
},
_multi_compare: function (key, compare) {
var column = this.getColumnConfig(key);
var separator = column ? column.optionslist : null; //default mode
if (!separator) return compare;
if (typeof separator != "string") separator = ",";
return function (itemValue, inputValue, obj) {
if (!itemValue) return false;
var ids = itemValue.toString().split(separator);
for (var i = 0; i < ids.length; i++) {
if (compare(ids[i], inputValue, obj)) return true;
}
};
},
filterMode_setter: function (mode) {
return exports.extend(this.data._filterMode, mode, true);
},
getFilter: function (columnId) {
var filter = this._filter_elements[columnId];
if (filter && filter[2]._get_filter) return filter[2]._get_filter(filter[0]);
if (filter && filter[2].getInputNode) return filter[2].getInputNode(filter[0]);
return null;
},
registerFilter: function (node, config, obj) {
this._filter_elements[config.columnId] = [node, config, obj];
},
collectValues: function (id, mode) {
var values;
var obj = this.getColumnConfig(id);
var options = mode && mode.visible ? null : obj.collection;
if (options) values = this._collectValues.call(options, "id", "value");else values = this._collectValues(obj.id, obj.id);
var result = {
values: values
};
this.callEvent("onCollectValues", [id, result]);
return result.values;
},
_collectValues: function (id, value) {
var checks = {
"": true
};
var values = [];
this.data.each(function (obj) {
var lineId = obj ? obj[id] : ""; //special handling for 0 values
if (lineId === 0) lineId = "0"; //convert to string to create a valid ID
if (_typeof(lineId) == "object") lineId = String(lineId);
if (lineId !== undefined && !checks[lineId]) {
checks[lineId] = true;
values.push({
id: lineId,
value: obj[value]
});
}
}, this, true);
if (values.length) {
var type = typeof values[0].value === "string" ? "string" : "raw";
values.sort(this.data.sorting.create({
as: type,
by: "value",
dir: "asc"
}));
}
return values;
},
_on_after_filter: function () {
if (this.editStop) this.editStop();
this.callEvent("onAfterFilter", []);
}
};
var Mixin$1 = {
hover_setter: function (value) {
var _this = this;
if (value && !this._hover_initialized) {
this._enable_mouse_move();
this.config.experimental = true;
this.attachEvent("onMouseMoving", function (e) {
// do not show hover while dragging
if (DragControl.active) {
if (_this._last_hover) _this._last_hover = _this.removeRowCss(_this._last_hover, _this._settings.hover);
return;
}
var pos = _this.locate(e); // when we click inner html element, edge calls mousemove with incorrect e.target
if (!pos && env.isEdge && e.relatedTarget) pos = _this.locate(e.relatedTarget);
var row = pos ? pos.row : null;
if (_this._last_hover != row) {
if (_this._last_hover) _this.removeRowCss(_this._last_hover, _this._settings.hover);
_this._last_hover = row;
if (_this._last_hover) _this.addRowCss(_this._last_hover, _this._settings.hover);
}
});
_event(this.$view, "mouseout", function (e) {
var trg = e.target; // inner html elements blinking in case of hover:true
// ie and edge call mouseout when clicking inner html element
if (_this._last_hover && document.body.contains(trg)) {
var pos = e.relatedTarget ? _this.locate(e.relatedTarget) : null;
if (!pos) {
_this.removeRowCss(_this._last_hover, _this._settings.hover);
_this._last_hover = null;
}
}
});
this._hover_initialized = 1;
}
return value;
},
select_setter: function (value) {
if (!this.select && value) {
exports.extend(this, this._selections._commonselect, true);
if (value === true) value = "row";else if (value == "multiselect") {
value = "row";
this._settings.multiselect = true;
}
assert(this._selections[value], "Unknown selection mode: " + value);
exports.extend(this, this._selections[value], true);
}
return value;
},
getSelectedId: function (mode) {
return mode ? [] : ""; //dummy placeholder
},
getSelectedItem: function (mode) {
return SelectionModel.getSelectedItem.call(this, mode);
},
_selections: {
//shared methods for all selection models
_commonselect: {
_select_css: " webix_cell_select",
$init: function () {
this._reinit_selection();
this.on_click.webix_cell = bind(this._click_before_select, this); //temporary stab, actual handlers need to be created
this._data_cleared = this._data_filtered = function () {
this.unselect();
};
this.data.attachEvent("onStoreUpdated", bind(this._data_updated, this));
this.data.attachEvent("onSyncApply", bind(this._data_synced, this));
this.data.attachEvent("onClearAll", bind(this._data_cleared, this));
this.data.attachEvent("onAfterFilter", bind(this._data_filtered, this));
this.data.attachEvent("onIdChange", bind(this._id_changed, this));
this.$ready.push(SelectionModel._set_noselect);
},
_id_changed: function (oldid, newid) {
for (var i = 0; i < this._selected_rows.length; i++) {
if (this._selected_rows[i] == oldid) this._selected_rows[i] = newid;
}
for (var _i = 0; _i < this._selected_areas.length; _i++) {
var item = this._selected_areas[_i];
if (item.row == oldid) {
oldid = this._select_key(item);
item.row = newid;
newid = this._select_key(item);
item.id = newid;
delete this._selected_pull[oldid];
this._selected_pull[newid] = true;
}
}
},
_data_updated: function (id, obj, type) {
if (type == "delete") this.unselect(id);
},
_data_synced: function () {
for (var i = this._selected_areas.length - 1; i >= 0; i--) {
var row = this._selected_areas[i].row;
if (!this.exists(row)) {
this._selected_areas.splice(i, 1);
delete this._selected_pull[row];
}
}
},
_reinit_selection: function () {
//list of selected areas
this._selected_areas = []; //key-value hash of selected areas, for fast search
this._selected_pull = {}; //used to track selected cell objects
this._selected_rows = [];
},
isSelected: function (id, column) {
var key;
if (!isUndefined(column)) key = this._select_key({
row: id,
column: column
});else key = _typeof(id) === "object" ? this._select_key(id) : id;
return this._selected_pull[key];
},
getSelectedId: function (asArray, plain) {
var result; //if multiple selections was created - return array
//in case of single selection, return value or array, when asArray parameter provided
if (this._selected_areas.length > 1 || asArray) {
result = [].concat(this._selected_areas);
if (plain) for (var i = 0; i < result.length; i++) {
result[i] = result[i].id;
}
} else {
result = this._selected_areas[0];
if (plain && result) return result.id;
}
return result;
},
_id_to_string: function () {
return this.row;
},
_select: function (data, preserve) {
var key = this._select_key(data); //don't allow selection on unnamed columns
if (key === null) return;
if (preserve === -1) return this._unselect(data);
data.id = key;
data.toString = this._id_to_string;
if (!this.callEvent("onBeforeSelect", [data, preserve])) return false; //ignore area, if it was already selected and
// - we are preserving existing selection
// - this is the only selected area
// otherwise we need to clear other selected areas
if (this._selected_pull[key] && (preserve || this._selected_areas.length == 1)) return;
if (!preserve) this._clear_selection();
this._selected_areas.push(data);
this._selected_pull[key] = true;
this.callEvent("onAfterSelect", [data, preserve]);
this._finalize_select(this._post_select(data));
return true;
},
_clear_selection: function () {
if (!this._selected_areas.length) return false;
for (var i = 0; i < this._selected_areas.length; i++) {
if (!this.callEvent("onBeforeUnSelect", [this._selected_areas[i]])) return false;
}
for (var _i2 = 0; _i2 < this._selected_rows.length; _i2++) {
this.data.removeMark(this._selected_rows[_i2], "webix_selected", 0, true);
}
var cols = this._settings.columns;
if (cols) for (var _i3 = 0; _i3 < cols.length; _i3++) {
cols[_i3].$selected = null;
}
var data = this._selected_areas;
this._reinit_selection();
for (var _i4 = 0; _i4 < data.length; _i4++) {
this.callEvent("onAfterUnSelect", [data[_i4]]);
}
return true;
},
unselectAll: function () {
this.clearSelection();
},
selectAll: function () {
this.selectRange();
},
clearSelection: function () {
if (this._clear_selection()) {
this.callEvent("onSelectChange", []);
this.render();
}
},
_unselect: function (data) {
var key = this._select_key(data);
if (!key && this._selected_areas.length) {
this.clearSelection();
this.callEvent("onSelectChange", []);
} //ignore area, if it was already selected
if (!this._selected_pull[key]) return;
if (!this.callEvent("onBeforeUnSelect", [data])) return false;
for (var i = 0; i < this._selected_areas.length; i++) {
if (this._selected_areas[i].id == key) {
this._selected_areas.splice(i, 1);
break;
}
}
delete this._selected_pull[key];
this.callEvent("onAfterUnSelect", [data]);
this._finalize_select(0, this._post_unselect(data));
},
_add_item_select: function (id) {
var item = this.getItem(id);
return this.data.addMark(item.id, "webix_selected", 0, {
$count: 0
}, true);
},
_finalize_select: function (id) {
if (id) this._selected_rows.push(id);
if (!this._silent_selection) {
this.render();
this.callEvent("onSelectChange", []);
}
},
_click_before_select: function (e, id) {
var preserve = e.ctrlKey || e.metaKey || this._settings.multiselect == "touch";
var range = e.shiftKey;
if (!this._settings.multiselect && this._settings.select != "multiselect" && this._settings.select != "area") preserve = range = false;
if (range && this._selected_areas.length) {
var last = this._selected_areas[this._selected_areas.length - 1];
this._selectRange(id, last);
} else {
if (preserve && this._selected_pull[this._select_key(id)]) this._unselect(id);else this._select({
row: id.row,
column: id.column
}, preserve);
}
},
_mapSelection: function (callback, column, row) {
var cols = this._settings.columns; //selected columns only
if (column) {
var temp = [];
for (var i = 0; i < cols.length; i++) {
if (cols[i].$selected) temp.push(cols[i]);
}
cols = temp;
}
var rows = this.data.order;
var row_ind = 0;
for (var _i5 = 0; _i5 < rows.length; _i5++) {
var item = this.getItem(rows[_i5]);
if (!item) continue; //dyn loading, row is not available
var selection = this.data.getMark(item.id, "webix_selected");
if (selection || column) {
var col_ind = 0;
for (var j = 0; j < cols.length; j++) {
var id = cols[j].id;
if (row || column || selection[id]) {
if (callback) item[id] = callback(item[id], rows[_i5], id, row_ind, col_ind);else return {
row: rows[_i5],
column: id
};
col_ind++;
}
} //use separate row counter, to count only selected rows
row_ind++;
}
}
}
},
row: {
_select_css: " webix_row_select",
_select_key: function (data) {
return data.row;
},
select: function (row_id, preserve) {
//when we are using id from mouse events
if (row_id) row_id = row_id.toString();
assert(this.data.exists(row_id), "Incorrect id in select command: " + row_id);
this._select({
row: row_id
}, preserve);
},
_post_select: function (data) {
this._add_item_select(data.row).$row = true;
return data.row;
},
unselect: function (row_id) {
this._unselect({
row: row_id
});
},
_post_unselect: function (data) {
this.data.removeMark(data.row, "webix_selected", 0, true);
return data.row;
},
mapSelection: function (callback) {
return this._mapSelection(callback, false, true);
},
_selectRange: function (a, b) {
return this.selectRange(a.row, b.row);
},
selectRange: function (row_id, end_row_id, preserve) {
if (isUndefined(preserve)) preserve = true;
var row_start_ind = row_id ? this.getIndexById(row_id) : 0;
var row_end_ind = end_row_id ? this.getIndexById(end_row_id) : this.data.order.length - 1;
if (row_start_ind > row_end_ind) {
var temp = row_start_ind;
row_start_ind = row_end_ind;
row_end_ind = temp;
}
this._silent_selection = true;
for (var i = row_start_ind; i <= row_end_ind; i++) {
var id = this.getIdByIndex(i);
if (!id) {
if (row_id) this.select(row_id);
break;
}
this.select(id, preserve);
}
this._silent_selection = false;
this._finalize_select();
}
},
cell: {
_select_key: function (data) {
if (!data.column) return null;
return data.row + "_" + data.column;
},
select: function (row_id, column_id, preserve) {
assert(this.data.exists(row_id), "Incorrect id in select command: " + row_id);
this._select({
row: row_id,
column: column_id
}, preserve);
},
_post_select: function (data) {
var sel = this._add_item_select(data.row);
sel.$count++;
sel[data.column] = true;
return data.row;
},
unselect: function (row_id, column_id) {
this._unselect({
row: row_id,
column: column_id
});
},
_post_unselect: function (data) {
var sel = this._add_item_select(data.row);
sel.$count--;
sel[data.column] = false;
if (sel.$count <= 0) this.data.removeMark(data.row, "webix_selected", 0, true);
return data.row;
},
mapSelection: function (callback) {
return this._mapSelection(callback, false, false);
},
_selectRange: function (a, b) {
return this.selectRange(a.row, a.column, b.row, b.column);
},
selectRange: function (row_id, column_id, end_row_id, end_column_id, preserve) {
if (isUndefined(preserve)) preserve = true;
var row_start_ind = row_id ? this.getIndexById(row_id) : 0;
var row_end_ind = end_row_id ? this.getIndexById(end_row_id) : this.data.order.length - 1;
var col_start_ind = column_id ? this.getColumnIndex(column_id) : 0;
var col_end_ind = end_column_id ? this.getColumnIndex(end_column_id) : this._columns.length - 1;
if (row_start_ind > row_end_ind) {
var temp = row_start_ind;
row_start_ind = row_end_ind;
row_end_ind = temp;
}
if (col_start_ind > col_end_ind) {
var _temp = col_start_ind;
col_start_ind = col_end_ind;
col_end_ind = _temp;
}
this._silent_selection = true;
for (var i = row_start_ind; i <= row_end_ind; i++) {
for (var j = col_start_ind; j <= col_end_ind; j++) {
this.select(this.getIdByIndex(i), this.columnId(j), preserve);
}
}
this._silent_selection = false;
this._finalize_select();
}
},
column: {
_select_css: " webix_column_select",
_select_key: function (data) {
return data.column;
},
_id_to_string: function () {
return this.column;
},
//returns box-like area, with ordered selection cells
select: function (column_id, preserve) {
this._select({
column: column_id
}, preserve);
},
_post_select: function (data) {
this._settings.columns[this.getColumnIndex(data.column)].$selected = true;
if (!this._silent_selection) this._render_header_and_footer();
},
unselect: function (column_id) {
this._unselect({
column: column_id
});
},
_post_unselect: function (data) {
this._settings.columns[this.getColumnIndex(data.column)].$selected = null;
this._render_header_and_footer();
},
mapSelection: function (callback) {
return this._mapSelection(callback, true, false);
},
_selectRange: function (a, b) {
return this.selectRange(a.column, b.column);
},
selectRange: function (column_id, end_column_id, preserve) {
if (isUndefined(preserve)) preserve = true;
var column_start_ind = column_id ? this.getColumnIndex(column_id) : 0;
var column_end_ind = end_column_id ? this.getColumnIndex(end_column_id) : this._columns.length - 1;
if (column_start_ind > column_end_ind) {
var temp = column_start_ind;
column_start_ind = column_end_ind;
column_end_ind = temp;
}
this._silent_selection = true;
for (var i = column_start_ind; i <= column_end_ind; i++) {
this.select(this.columnId(i), preserve);
}
this._silent_selection = false;
this._render_header_and_footer();
this._finalize_select();
},
_data_synced: function () {//do nothing, as columns are not changed
}
},
area: {
_select_key: function (data) {
return data.row + "_" + data.column;
},
getSelectedId: function (asArray) {
var area = this.getSelectArea();
var result = [];
if (area) {
if (asArray && (area.start.row != area.end.row || area.start.column != area.end.column)) {
var row_start_ind = this.getIndexById(area.start.row);
var row_end_ind = this.getIndexById(area.end.row); //filtering in process
if (row_start_ind == -1 || row_end_ind == -1) return result;
var col_start_ind = this.getColumnIndex(area.start.column);
var col_end_ind = this.getColumnIndex(area.end.column);
for (var i = row_start_ind; i <= row_end_ind; i++) {
for (var j = col_start_ind; j <= col_end_ind; j++) {
result.push({
row: this.getIdByIndex(i),
column: this.columnId(j)
});
}
}
} else {
result.push(area.end);
}
}
return asArray ? result : result[0];
},
unselect: function () {
this._unselect();
},
_unselect: function () {
this.removeSelectArea();
this.callEvent("onSelectChange", []);
},
mapSelection: function (callback) {
var select = this.getSelectArea();
if (select) {
var sind = this.getColumnIndex(select.start.column);
var eind = this.getColumnIndex(select.end.column);
var srow = this.getIndexById(select.start.row);
var erow = this.getIndexById(select.end.row);
for (var i = srow; i <= erow; i++) {
var rid = this.data.order[i];
var item = this.getItem(rid);
for (var j = sind; j <= eind; j++) {
var cid = this._columns[j].id;
if (callback) item[cid] = callback(item[cid], rid, cid, i - srow, j - sind);else return {
row: rid,
column: cid
};
}
}
}
},
select: function (row_id, column_id, preserve) {
assert(this.data.exists(row_id), "Incorrect id in select command: " + row_id);
this._select({
row: row_id,
column: column_id
}, preserve);
},
_selectRange: function (id, last) {
this._extendAreaRange(id, last);
},
_select: function (cell) {
//ctrl-selection is not supported yet, so ignoring the preserve flag
this.addSelectArea(cell, cell, false);
return true;
},
_data_synced: function () {
if (this._selected_areas.length) this.refreshSelectArea();
}
}
}
};
var Mixin$2 = {
blockselect_setter: function (value) {
if (value && this._block_sel_flag) {
if (env.touch) this.attachEvent("onLongTouch", this._bs_down);else _event(this._viewobj, env.mouse.down, this._bs_down, {
bind: this
});
_event(this._viewobj, env.mouse.move, this._bs_move, {
bind: this
});
this._block_sel_flag = this._bs_ready = this._bs_progress = false;
this.attachEvent("onAfterScroll", this._update_block_selection); // auto scroll
exports.extend(this, AutoScroll, true);
this.attachEvent("onBeforeAutoScroll", function () {
return this._bs_progress;
});
}
return value;
},
_block_sel_flag: true,
_childOf: function (e, tag) {
var src = e.target;
while (src) {
if (src.getAttribute && src.getAttribute(
/*@attr*/
"webixignore")) return false;
if (src == tag) return true;
src = src.parentNode;
}
return false;
},
_bs_down: function (e) {
// do not listen to mousedown of subview on master
if (this._settings.subview && this != $$(e.target)) return;
if (this._childOf(e, this._body)) {
//disable block selection when we have an active editor
if (e.target && e.target.tagName == "INPUT" || this._rs_process) return;
this._bs_position = offset(this._body);
var pos$$1 = env.touch ? e : pos(e);
this._bs_ready = [pos$$1.x - this._bs_position.x, pos$$1.y - this._bs_position.y];
preventEvent(e);
this._bs_up_init();
}
},
_bs_up_init: function () {
var _this = this;
var handler = event$1(document.body, env.mouse.up, function (e) {
eventRemove(handler);
return _this._bs_up(e);
});
},
_bs_up: function (e) {
if (this._block_panel) {
this._bs_select("select", true, e);
this._block_panel = remove(this._block_panel);
}
removeCss(document.body, "webix_noselect");
this._bs_ready = this._bs_progress = false;
if (this._auto_scroll_delay) this._auto_scroll_delay = window.clearTimeout(this._auto_scroll_delay);
},
_update_block_selection: function () {
if (this._bs_progress) delay(this._bs_select, this, [false, false]);
},
_bs_select: function (mode, theend, e) {
var start = null;
if (!this._bs_ready[2]) this._bs_ready[2] = this._locate_cell_xy.apply(this, this._bs_ready);
start = this._bs_ready[2];
var end = this._locate_cell_xy.apply(this, this._bs_progress);
if (!this.callEvent("onBeforeBlockSelect", [start, end, theend, e])) return;
if ((!this._bs_do_select || this._bs_do_select(start, end, theend, e) !== false) && start.row && end.row) {
if (mode === "select") {
this._clear_selection();
this._selectRange(start, end);
} else {
var startx, starty, endx, endy;
if (mode === "box") {
startx = Math.min(this._bs_ready[0], this._bs_progress[0]);
endx = Math.max(this._bs_ready[0], this._bs_progress[0]);
starty = Math.min(this._bs_ready[1], this._bs_progress[1]);
endy = Math.max(this._bs_ready[1], this._bs_progress[1]);
} else {
var startn = this._cellPosition(start.row, start.column);
var endn = this._cellPosition(end.row, end.column);
var scroll = this.getScrollState();
var startWidth = startn.width;
var endWidth = endn.width;
if (this._right_width && this._bs_ready[0] > this._left_width + this._center_width) {
startn.left += this._left_width + this._center_width;
} else if (this._left_width) {
if (this._bs_ready[0] > this._left_width) {
if (startn.left < scroll.x) {
startWidth -= scroll.x - startn.left;
startn.left = this._left_width;
} else startn.left += this._left_width - scroll.x;
}
} else startn.left -= scroll.x;
if (this._right_width && this._bs_progress[0] > this._left_width + this._center_width) {
endn.left += this._left_width + this._center_width;
} else if (this._left_width) {
if (this._bs_progress[0] > this._left_width) {
if (endn.left < scroll.x) {
endWidth -= scroll.x - endn.left;
endn.left = this._left_width;
} else endn.left += this._left_width - scroll.x;
}
} else endn.left -= scroll.x;
if (this._settings.prerender) {
startn.top -= this._scrollTop;
endn.top -= this._scrollTop;
}
startx = Math.min(startn.left, endn.left);
endx = Math.max(startn.left + startWidth, endn.left + endWidth);
starty = Math.min(startn.top, endn.top);
endy = Math.max(startn.top + startn.height, endn.top + endn.height);
if (this._settings.topSplit) starty += this._getTopSplitOffset(start);
if (this._auto_scroll_delay) this._auto_scroll_delay = window.clearTimeout(this._auto_scroll_delay);
if (e && (!env.touch || this._settings.prerender)) this._auto_scroll_delay = delay(this._auto_scroll, this, [pos(e)], 250);
}
var style = this._block_panel.style;
style.left = startx + "px";
style.top = starty + "px";
style.width = endx - startx + "px";
style.height = endy - starty + "px";
}
}
if (theend) this.callEvent("onAfterBlockSelect", [start, end]);
},
_bs_start: function () {
this._block_panel = create("div", {
"class": "webix_block_selection"
}, "");
this._body.appendChild(this._block_panel);
},
_bs_move: function (e) {
if (this._rs_progress) return;
if (this._bs_ready !== false) {
if (!this._bs_progress) addCss(document.body, "webix_noselect");
var pos$$1 = env.touch ? env.mouse.context(e) : pos(e);
var progress = [pos$$1.x - this._bs_position.x, pos$$1.y - this._bs_position.y]; //prevent unnecessary block selection while dbl-clicking
if (Math.abs(this._bs_ready[0] - progress[0]) < 5 && Math.abs(this._bs_ready[1] - progress[1]) < 5) return;
if (this._bs_progress === false) this._bs_start(e);
this._bs_progress = progress;
this._bs_select(this.config.blockselect, false, e);
if (env.touch) preventEvent(e);
}
},
_locate_cell_xy: function (x, y) {
var inTopSplit = false,
row = null,
column = null;
if (this._right_width && x > this._left_width + this._center_width) x += this._x_scroll.getSize() - this._center_width - this._left_width - this._right_width;else if (!this._left_width || x > this._left_width) x += this._x_scroll.getScroll();
if (this._settings.topSplit && this._render_scroll_top > this._settings.topSplit) {
var splitPos = this._cellPosition(this.getIdByIndex(this._settings.topSplit - 1), this.columnId(0));
if (splitPos.top + splitPos.height > y) {
inTopSplit = true;
}
}
if (!inTopSplit) y += this.getScrollState().y;
if (x < 0) x = 0;
if (y < 0) y = 0;
var cols = this._settings.columns;
var rows = this.data.order;
var summ = 0;
for (var i = 0; i < cols.length; i++) {
summ += cols[i].width;
if (summ >= x) {
column = cols[i].id;
break;
}
}
if (!column) column = cols[cols.length - 1].id;
summ = 0;
var start = this.data.$min || 0;
if (this._settings.fixedRowHeight) {
row = rows[start + Math.floor(y / this._settings.rowHeight)];
} else for (var _i = start; _i < rows.length; _i++) {
summ += this._getHeightByIndex(_i);
if (summ >= y) {
row = rows[_i];
break;
}
}
if (!row) row = rows[rows.length - 1];
return {
row: row,
column: column
};
},
_getTopSplitOffset: function (cell, area) {
var y = 0,
startIndex = this.getIndexById(cell.row);
if (startIndex >= this._settings.topSplit) {
var startPos = this._cellPosition(this.getIdByIndex(startIndex), cell.column);
var splitPos = this._cellPosition(this.getIdByIndex(this._settings.topSplit - 1), cell.column);
if (splitPos.top + splitPos.height > startPos.top) y = splitPos.top + splitPos.height - (startPos.top > 0 || !area ? startPos.top : 0);
}
return y;
}
};
var Mixin$3 = {
resizeRow_setter: function (value) {
this._settings.scrollAlignY = false;
this._settings.fixedRowHeight = false;
return this.resizeColumn_setter(value);
},
resizeColumn_setter: function (value) {
var _this = this;
if (value && this._rs_init_flag) {
_event(this._viewobj, "mousemove", function (e) {
return _this._rs_move(e);
});
_event(this._viewobj, "mousedown", function (e) {
return _this._rs_down(e);
});
_event(this._viewobj, "mouseup", function () {
return _this._rs_up();
});
this._rs_init_flag = false;
}
return value;
},
_rs_init_flag: true,
_rs_down: function (e) {
// do not listen to mousedown of subview on master
if (!this._rs_ready || this._settings.subview && this != $$(e.target)) return;
this._rs_process = [pos(e), this._rs_ready];
addCss(document.body, "webix_noselect");
denySelect();
},
_rs_up: function () {
this._rs_process = false;
removeCss(document.body, "webix_noselect");
allowSelect();
},
_rs_start: function () {
var _this2 = this;
if (this._rs_progress) return;
var _this$_rs_process$ = _slicedToArray(this._rs_process[1], 4),
dir = _this$_rs_process$[0],
size = _this$_rs_process$[1],
node = _this$_rs_process$[2],
cell = _this$_rs_process$[3];
var eventPos = this._rs_process[0];
var start;
if (dir == "x") {
start = offset(node).x + size - offset(this._body).x;
eventPos = eventPos.x;
} else {
start = offset(node).y + size - offset(this._body).y + this._header_height;
eventPos = eventPos.y;
}
this._rs_progress = [dir, cell, start];
var resize = new ui.resizearea({
container: this._viewobj,
eventPos: eventPos,
start: start,
dir: dir,
cursor: (dir == "x" ? "col" : "row") + "-resize"
});
resize.attachEvent("onResizeEnd", function (pos$$1) {
return _this2._rs_end(pos$$1);
});
this._rs_ready = false;
},
_rs_end: function (result) {
if (this._rs_progress) {
var cell = this._rs_progress[1];
var newsize = result - this._rs_progress[2];
if (this._rs_progress[0] == "x") {
//in case of right split - different sizing logic applied
if (this._settings.rightSplit && cell.cind >= this._rightSplit) {
newsize *= -1;
}
var col = this._columns[cell.cind];
var oldwidth = col.width;
delete col.fillspace;
delete col.adjust;
this._setColumnWidth(cell.cind, oldwidth + newsize, true, true);
this._updateColsSizeSettings();
} else {
var id = this.getIdByIndex(cell.rind);
var oldheight = this._getRowHeight(this.getItem(id));
this.setRowHeight(id, oldheight + newsize);
}
this._rs_up();
}
this._rs_progress = null;
},
_rs_move: function (e) {
if (this._rs_ready && this._rs_process) return this._rs_start();
this._rs_ready = false;
var mode = false;
var node = e.target;
var config = this._settings; //we can't use node.className because there can be SVG (in SVG it is an SVGAnimatedString object)
var element_class = node.getAttribute("class") || ""; //ignore resize in case of drag-n-drop enabled
var in_body = element_class.indexOf("webix_cell") != -1;
if (in_body && config.drag) return this._mark_resize(mode);
var in_header = element_class.indexOf("webix_hcell") != -1;
if (in_body || in_header) {
var _pos = posRelative(e);
var cell = this._locate(node);
mode = this._is_column_rs(cell, _pos, node, config.resizeColumn, in_body) || in_body && this._is_row_rs(cell, _pos, node, config.resizeRow);
} //mark or unmark resizing ready state
this._mark_resize(mode);
},
_is_column_rs: function (cell, pos$$1, node, rColumn, in_body) {
// if resize is only within the header
if (!rColumn || in_body && rColumn.headerOnly) return false;
var dx = node.offsetWidth;
rColumn = rColumn.size ? rColumn.size : 3;
var col, config;
if (pos$$1.x < rColumn) {
if (cell.cind < this._rightSplit) cell.cind -= cell.span || 1;
col = this._columns[cell.cind];
config = ["x", 0, node, cell];
} else if (dx - pos$$1.x < rColumn + 1) {
if (this._settings.rightSplit && cell.cind + 1 >= this._rightSplit) cell.cind++;
if (!this._settings.rightSplit || cell.cind < this._columns.length) {
col = this._columns[cell.cind];
config = ["x", dx, node, cell];
}
}
if (col && col.resize !== false) {
this._rs_ready = config;
return "col-resize";
}
return false;
},
_is_row_rs: function (cell, pos$$1, node, rRow) {
// if resize is only within the first column
if (!rRow || rRow.headerOnly && cell.cind > 0) return false; // block selection in progress
if (this._bs_progress) return false;
var dy = node.offsetHeight;
rRow = rRow.size ? rRow.size : 3;
if (pos$$1.y < rRow) {
if (cell.rind > 0) {
// avoid resize header border
cell.rind--;
this._rs_ready = ["y", 0, node, cell];
}
} else if (dy - pos$$1.y < rRow + 1) this._rs_ready = ["y", dy, node, cell];
return this._rs_ready ? "row-resize" : false;
},
_mark_resize: function (mode) {
if (this._cursor_timer) window.clearTimeout(this._cursor_timer);
this._cursor_timer = delay(this._mark_resize_ready, this, [mode], mode ? 100 : 0);
},
_mark_resize_ready: function (mode) {
if (this._last_cursor_mode != mode) {
this._last_cursor_mode = mode;
this._viewobj.style.cursor = mode || "";
}
}
};
attachEvent("onDataTable", function (table, config) {
if (env.touch) {
Touch.$init();
config.scrollSize = 0; // needed to show datatable scroll
if (Touch._disabled) Touch.limit();
table.$ready.push(table.$touch);
}
});
var Mixin$4 = {
$touch: function () {
var config = this._settings;
config.scrollAlignY = false;
exports.extend(this, config.prerender === true ? this._touchNative : this._touch);
var scrollMode = "";
if (!config.autowidth && config.scrollX !== false) scrollMode += "x";
if (!config.autoheight && config.scrollY !== false) scrollMode += "y";
this._body.setAttribute("touch_scroll", scrollMode);
Touch._init_scroll_node(this._body.childNodes[1].firstChild);
Touch._set_matrix(this._body.childNodes[1].firstChild, 0, 0, "0ms");
this._sync_scroll(0, 0, "0ms");
},
$hasYScroll: function () {
return this._dtable_height - this._dtable_offset_height > 2;
},
_touchNative: {
_scrollTo_touch: function (x, y) {
Touch._set_matrix(this._body.childNodes[1].firstChild, -x, -y, "0ms");
this._sync_scroll(-x, -y, "0ms");
this.callEvent("onAfterScroll", [{
e: -x,
f: -y
}]);
},
_getScrollState_touch: function () {
var temp = Touch._get_matrix(this._body.childNodes[1].firstChild);
return {
x: -temp.e,
y: -temp.f
};
},
$init: function () {
this.attachEvent("onBeforeScroll", function () {
Touch._scroll_node = this._body.childNodes[1].firstChild;
Touch._get_sizes(Touch._scroll_node);
Touch._scroll_master = this;
});
this.attachEvent("onTouchEnd", function () {
Touch._scroll_master = null;
});
this.attachEvent("onAfterScroll", function (result) {
//onAfterScroll may be triggered by some non-touch related logic
if (!result) return;
this._scrollLeft = -result.e;
this._scrollTop = -result.f;
if (this._x_scroll) this._x_scroll._settings.scrollPos = this._scrollLeft;
if (this._y_scroll) this._y_scroll._settings.scrollPos = this._scrollTop;
});
},
_sync_scroll: function (x, y, t) {
Touch._set_matrix(this._body.childNodes[1].firstChild, x, y, t);
if (this._settings.leftSplit) Touch._set_matrix(this._body.childNodes[0].firstChild, 0, y, t);
if (this._settings.rightSplit) Touch._set_matrix(this._body.childNodes[2].firstChild, 0, y, t);
if (this._settings.header) Touch._set_matrix(this._header.childNodes[1].firstChild, x, 0, t);
if (this._settings.footer) Touch._set_matrix(this._footer.childNodes[1].firstChild, x, 0, t);
this.callEvent("onSyncScroll", [x, y, t]);
},
_sync_pos: function () {}
},
_touch: {
_scrollTo_touch: function (x, y) {
delay(function () {
this.callEvent("onAfterScroll", [{
e: -x,
f: -y
}]);
}, this);
},
$scroll: {
gravity: 0,
elastic: false
},
$init: function () {
//if the result column's width < container's width,
this.attachEvent("onAfterColumnHide", function () {
this._scrollTo_touch(0, 0);
});
this.attachEvent("onBeforeScroll", function () {
var t = Touch;
t._scroll_node = this._body.childNodes[1].firstChild;
t._get_sizes(t._scroll_node);
t._scroll_stat.left = this._scrollLeft;
t._scroll_stat.hidden = this._x_scroll._settings.scrollVisible || this._y_scroll._settings.scrollVisible;
t._scroll_stat.dy = this._dtable_height;
t._scroll_master = this;
});
this.attachEvent("onAfterRender", function () {
if (this._x_scroll && this._settings.scrollX) this._x_scroll._fixSize();
if (this._y_scroll && this._settings.scrollY) this._y_scroll._fixSize();
});
this.attachEvent("onAfterScroll", function (result) {
//onAfterScroll may be triggered by some non-touch related logic
if (!result) return;
var isScrollX = this._scrollLeft != -result.e;
var isScrollY = this._scrollTop != -result.f;
Touch._scroll_master = null;
Touch._fix_f = null;
this._scrollTop = 0;
this._scrollLeft = 0; //ipad can delay content rendering if 3d transformation applied
//switch back to 2d
var temp = Touch.config.translate;
Touch.config.translate = "translate";
this._sync_scroll(this._x_scroll ? 0 : result.e, 0, 0);
Touch.config.translate = temp;
this._scrollLeft = -result.e;
this._scrollTop = -result.f;
this._correctScrollSize();
this.render();
if (isScrollX) {
if (this._x_scroll) this._x_scroll.scrollTo(this._scrollLeft);
this.callEvent("onScrollX", []);
}
if (isScrollY) {
if (this._y_scroll) this._y_scroll.scrollTo(this._scrollTop);
this.callEvent("onScrollY", []);
}
return false;
});
},
_sync_scroll: function (x, y, t) {
y += this._scrollTop;
x += this._scrollLeft;
Touch._set_matrix(this._body.childNodes[1].firstChild, x, y, t);
if (this._settings.leftSplit) Touch._set_matrix(this._body.childNodes[0].firstChild, 0, y, t);
if (this._settings.rightSplit) Touch._set_matrix(this._body.childNodes[2].firstChild, 0, y, t);
if (this._settings.header) Touch._set_matrix(this._header.childNodes[1].firstChild, x, 0, t);
if (this._settings.footer) Touch._set_matrix(this._footer.childNodes[1].firstChild, x, 0, t);
this.callEvent("onSyncScroll", [x, y, t]);
},
_sync_pos: function (matrix) {
matrix.f -= this._scrollTop;
matrix.e -= this._scrollLeft;
}
}
};
var Mixin$5 = {
$init: function () {
this.data.attachEvent("onStoreUpdated", bind(function (id) {
if (!id) this._adjustColumns();
}, this));
this.attachEvent("onStructureLoad", this._adjustColumns);
this.attachEvent("onStructureUpdate", this._resizeColumns);
this.attachEvent("onColumnResize", function (a, b, c, user) {
if (user) this._resizeColumns();
});
this.attachEvent("onResize", this._resizeColumns);
},
_adjustColumns: function () {
var resize = false;
var cols = this._columns;
for (var i = 0; i < cols.length; i++) {
if (cols[i].adjust && (cols[i].adjust == "header" || this.count())) resize = this._adjustColumn(i, cols[i].adjust, true) || resize;
}
if (resize) {
this._updateColsSizeSettings(true);
this._resizeColumns();
}
},
_resizeColumns: function () {
var cols = this._settings.columns;
var fill = [];
var summ = 0;
if (cols && !this._settings.autowidth) for (var i = 0; i < cols.length; i++) {
var colfil = cols[i].fillspace;
if (colfil) {
fill[i] = colfil;
summ += colfil * 1 || 1;
}
}
if (summ) this._fillColumnSize(fill, summ);
},
_fillColumnSize: function (fill, summ) {
var cols = this._settings.columns;
if (!cols) return;
var width = this._content_width - this._scrollSizeY;
var resize = false;
if (width > 0) {
for (var i = 0; i < cols.length; i++) {
if (!fill[i]) width -= cols[i].width || this._settings.columnWidth;
}
for (var _i = 0; _i < fill.length; _i++) {
if (fill[_i]) {
var request = Math.min(width, Math.round(width * fill[_i] / summ));
resize = this._setColumnWidth(_i, request, true) || resize;
width = width - cols[_i].width;
summ = summ - fill[_i];
}
}
if (resize) this._updateColsSizeSettings(true);
}
},
_getColumnConfigSize: function (ind, headers) {
var config = this._settings.columns[ind];
var max = config.minWidth || this._settings.minColumnWidth; //get max data width
if (headers != "header") {
var count = this.data.order.length;
if (config.adjustBatch && config.adjustBatch < count) count = config.adjustBatch;
var order = this.data.order.slice(0, count);
for (var i = 0; i < count; i++) {
order[i] = order[i] ? this._getValue(this.getItem(order[i]), config, 0) : "";
}
max = Math.max(max, getTextSize(order, "webix_table_cell webix_cell").width);
} //get max header width
if (headers != "data") {
for (var _i2 = 0; _i2 < config.header.length; _i2++) {
var header = config.header[_i2];
if (header) {
var width = 0;
if (header.rotate) for (var h = 0; h < (header.rowspan || 1); h++) {
width += this._headers[h];
}
var css = "webix_table_cell webix_cell " + (header.css || "") + (header.rotate ? "webix_measure_rotate" : "");
var size = getTextSize([header.text], css, width);
max = Math.max(max, header.rotate ? size.height : size.width);
}
}
if (config.sort) max += 10; // add 10px for sort marker
}
max = max + (env.isIE ? $active.layoutPadding.space : 0);
return Math.min(max, config.maxWidth || this._settings.maxColumnWidth || 100000);
},
_adjustColumn: function (ind, headers, ignore) {
if (ind >= 0) {
var width = this._getColumnConfigSize(ind, headers);
return this._setColumnWidth(ind, width, ignore);
}
},
adjustColumn: function (id, headers) {
this._adjustColumn(this.getColumnIndex(id), headers);
},
adjustRowHeight: function (id, silent) {
if (id) this._adjustRowHeight(id);else {
var heights = {};
var cols = this._settings.columns;
for (var i = 0; i < cols.length; i++) {
this._adjustRowHeight(cols[i].id, heights);
} //adjust size for single columns
this.data.each(function (obj) {
obj.$height = heights[obj.id];
});
}
if (!silent) this.refresh();
},
_adjustRowHeight: function (id, size) {
var config = this.getColumnConfig(id);
var container;
var d = create("DIV", {
"class": "webix_table_cell webix_measure_size webix_cell"
}, "");
d.style.cssText = "width:" + config.width + "px; height:1px; visibility:hidden; position:absolute; top:0px; left:0px; overflow:hidden;";
this.$view.appendChild(d);
if (d.offsetHeight < 1) {
//hidden container, height detection is broken
//reattach to the body
container = this.$view.cloneNode(true);
document.body.appendChild(container);
container.appendChild(d);
}
this.data.each(function (obj) {
var height;
d.innerHTML = this._getValue(obj, config, 0);
height = Math.max(d.scrollHeight, this._settings.rowHeight, this._settings.minRowHeight || 0);
height = Math.min(height, this._settings.maxRowHeight || 100000);
if (size) size[obj.id] = Math.max(height, size[obj.id] || 0);else obj.$height = height;
}, this);
d = remove(d);
if (container) remove(container);
}
};
var Mixin$6 = {
math_setter: function (value) {
if (value) this._math_init();
return value;
},
_math_pref: "$",
_math_init: function () {
if (env.strict) return;
this.data.attachEvent("onStoreUpdated", bind(this._parse_row_math, this));
this.data.attachEvent("onStoreLoad", bind(this._parse_math, this));
this.attachEvent("onStructureLoad", this._parse_math);
},
_parse_row_math: function (id, obj, action) {
if (!id || action == "paint") return;
if (action == "delete") {
for (var i = 0; i < this._columns.length; i++) {
this._remove_old_triggers(obj, this._columns[i].id);
}
} else {
if (action == "add") this._exprs_by_columns(obj);
for (var _i = 0; _i < this._columns.length; _i++) {
this._math_recalc = {};
this._parse_cell_math(id, this._columns[_i].id);
}
this._math_recalc = {};
}
},
_parse_cell_math: function (row, col) {
var item = this.getItem(row);
var value; // use previosly saved formula if available
value = item[this._math_pref + col] || item[col];
if (value && value.length > 0 && value.toString().substr(0, 1) === "=") {
// calculate math value
item[this._math_pref + col] = value;
item[col] = this._calculate(value, row, col); //this.updateItem(item);
} else {
// just a string
if (typeof item[this._math_pref + col] !== "undefined") delete item[this._math_pref + col]; // remove triggers if they were setted earlier
this._remove_old_triggers(item, col);
} // recalculate depending cells
if (typeof item.depends !== "undefined" && typeof item.depends[col] !== "undefined") {
for (var i in item.depends[col]) {
var name = item.depends[col][i][0] + "__" + item.depends[col][i][1];
if (typeof this._math_recalc[name] === "undefined") {
this._math_recalc[name] = true;
this._parse_cell_math(item.depends[col][i][0], item.depends[col][i][1]);
}
}
}
},
_set_original_value: function (row, col) {
var item = this.getItem(row);
if (typeof item[this._math_pref + col] !== "undefined") item[col] = item[this._math_pref + col];
},
_parse_math: function () {
if (!this._columns || !this.count()) return;
this._exprs_by_columns();
for (var j = 0; j < this._columns.length; j++) {
var col = this.columnId(j);
this.data.each(function (obj) {
this._math_recalc = {};
this._parse_cell_math(obj.id, col);
}, this);
}
this._math_recalc = {};
},
_exprs_by_columns: function (row) {
for (var i = 0; i < this._columns.length; i++) {
if (this._columns[i].math) {
var col = this.columnId(i);
var math = "=" + this._columns[i].math;
math = math.replace(/\$c/g, "#$c#");
if (row) {
row[col] = this._parse_relative_expr(math, row.id, col);
delete row[this._math_pref + col];
this._remove_old_triggers(row, col);
} else this.data.each(function (obj) {
obj[col] = this._parse_relative_expr(math, obj.id, col);
delete obj[this._math_pref + col];
this._remove_old_triggers(obj, col);
}, this);
}
}
},
_parse_relative_expr: function (expr, row, col) {
return template(expr)({
"$r": row,
"$c": col
});
},
_get_calc_value: function (row, col) {
var item;
if (this.exists(row)) item = this.getItem(row);else return "#out_of_range";
var value = item[this._math_pref + col] || item[col] || 0;
value = value.toString();
if (value.substring(0, 1) !== "=") // it's a string
return value;else {
// TODO: check if value shouldn't be recalculated
// and return value calculated earlier
// calculate math expr value right now
if (typeof item[this._math_pref + col] === "undefined") item[this._math_pref + col] = item[col];
item[col] = this._calculate(value, row, col, true);
return item[col];
}
},
_calculate: function (value, row, col, _inner_call) {
// add coord in math trace to detect self-references
if (_inner_call === true) {
if (this._in_math_trace(row, col)) return "#selfreference";
} else this._start_math_trace();
this._to_math_trace(row, col);
var item = this.getItem(row);
value = value.substring(1); // get operations list
var operations = this._get_operations(value);
var triggers = this._get_refs(value, row);
if (operations) {
value = this._replace_refs(value, triggers);
value = this._parse_args(value, operations);
} else {
value = this._replace_refs(value, triggers, true);
}
var exc = this._math_exception(value);
if (exc !== false) return exc; // remove from coord from trace when calculations were finished - it's important!
this._from_math_trace(row, col); // process triggers to know which cells should be recalculated when one was changed
this._remove_old_triggers(item, col);
for (var i = 0; i < triggers.length; i++) {
this._add_trigger([row, col], triggers[i]);
}
exc = this._math_exception(value);
if (exc !== false) return exc; // there aren't any operations here. returns number or value of another cell
if (!value) return value; // process mathematical expression and getting final result
value = this._compute(value.replace(/\$r/g, item.id));
exc = this._math_exception(value);
if (exc !== false) return exc;
return value;
},
_get_operations: function (value) {
// gettings operations list (+-*/)
var splitter = /(\+|-|\*|\/)/g;
var operations = value.replace(/\[[^)]*?\]/g, "").match(splitter);
return operations;
},
/*! gets list of referencies in formula
**/
_get_refs: function (value, id) {
var reg = /\[([^\]]+),([^\]]+)\]/g;
var cells = value.match(reg);
if (cells === null) cells = [];
for (var i = 0; i < cells.length; i++) {
var cell = cells[i];
var tmp = cell;
cell = cell.substr(1, cell.length - 2);
cell = cell.split(",");
cell[0] = this._trim(cell[0]);
cell[1] = this._trim(cell[1]);
if (cell[0].substr(0, 1) === ":") cell[0] = this.getIdByIndex(cell[0].substr(1));
if (cell[0] === "$r") cell[0] = id;
if (cell[1].substr(0, 1) === ":") cell[1] = this.columnId(cell[1].substr(1));
cell[2] = tmp;
cells[i] = cell;
}
return cells;
},
// replace given list of references by their values
_replace_refs: function (value, cells, clean) {
var dell = "(",
delr = ")";
if (clean) dell = delr = "";
for (var i = 0; i < cells.length; i++) {
var cell = cells[i];
var cell_value = this._get_calc_value(cell[0], cell[1]);
if (isNaN(cell_value)) cell_value = "\"" + cell_value + "\"";
value = value.replace(cell[2], dell + cell_value + delr);
}
return value;
},
_parse_args: function (value, operations) {
var args = [];
for (var i = 0; i < operations.length; i++) {
var op = operations[i];
var temp = this._split_by(value, op);
args.push(temp[0]);
value = temp[1];
}
args.push(value); //var reg = /^(-?\d|\.|\(|\))+$/;
for (var _i2 = 0; _i2 < args.length; _i2++) {
var arg = this._trim(args[_i2]); // if (reg.test(arg) === false)
// return ''; //error
args[_i2] = arg;
}
var expr = "";
for (var _i3 = 0; _i3 < args.length - 1; _i3++) {
expr += args[_i3] + operations[_i3];
}
expr += args[args.length - 1];
return expr;
},
_compute: function (expr) {
var result;
try {
result = window.eval(expr);
} catch (ex) {
assert(false, "Math error in datatable<br>" + expr);
result = "";
}
return result.toString();
},
_split_by: function (value, splitter) {
var pos = value.indexOf(splitter);
var before = value.substr(0, pos);
var after = value.substr(pos + 1);
return [before, after];
},
_trim: function (value) {
value = value.replace(/^ */g, "");
value = value.replace(/ *$/g, "");
return value;
},
_start_math_trace: function () {
this._math_trace = [];
},
_to_math_trace: function (row, col) {
this._math_trace[row + "__" + col] = true;
},
_from_math_trace: function (row, col) {
if (typeof this._math_trace[row + "__" + col] !== "undefined") delete this._math_trace[row + "__" + col];
},
_in_math_trace: function (row, col) {
if (typeof this._math_trace[row + "__" + col] !== "undefined") return true;else return false;
},
_add_trigger: function (depends, from) {
var item = this.getItem(from[0]);
if (typeof item.depends === "undefined") item.depends = {};
if (typeof item.depends[from[1]] === "undefined") item.depends[from[1]] = {};
item.depends[from[1]][depends[0] + "__" + depends[1]] = depends;
item = this.getItem(depends[0]);
if (typeof item.triggers === "undefined") item.triggers = {};
if (typeof item.triggers[depends[1]] === "undefined") item.triggers[depends[1]] = {};
item.triggers[depends[1]][from[0] + "__" + from[1]] = from;
},
_remove_old_triggers: function (item, col) {
if (!item) return;
if (typeof item.triggers === "undefined") return;
for (var i in item.triggers[col]) {
var depend = item.triggers[col][i];
var row = this.getItem(depend[0]);
if (row) delete row.depends[depend[1]][item.id + "__" + col];
}
},
// check if exception syntax exists and returns exception text or false
_math_exception: function (value) {
var reg = /#\w+/;
var match = value.match(reg);
if (match !== null && match.length > 0) return match[0];
return false;
}
};
var temp$4 = {};
// #include core/edit.js
// #include ui/inputs.js
var Mixin$7 = {
/////////////////////////
// edit start //
/////////////////////////
_get_editor_type: function (id) {
return this.getColumnConfig(id.column).editor;
},
getEditor: function (row, column) {
if (!row) return this._last_editor;
if (arguments.length == 1) {
column = row.column;
row = row.row;
}
return (this._editors[row] || {})[column];
},
_for_each_editor: function (handler) {
for (var row in this._editors) {
var row_editors = this._editors[row];
for (var column in row_editors) {
if (column != "$count") handler.call(this, row_editors[column]);
}
}
},
_init_editor: function (id, type, show) {
var row = id.row;
var column = id.column;
var col_settings = type.config = this.getColumnConfig(column); //show it over cell
if (show !== false) this.showCell(row, column);
var node = type.render();
if (type.$inline) node = this._locateInput(id);
type.node = node;
var item = this.getItem(row);
var format = col_settings.editFormat;
var value;
if (this._settings.editMath) value = item["$" + column];
value = value || item[column];
if (isUndefined(value)) value = "";
type.setValue(format ? format(value) : value, item);
type.value = item[column];
this._addEditor(id, type);
if (!type.$inline) type._editor_pos = this._sizeToCell(id, node, true);
if (type.afterRender) type.afterRender();
if (this._settings.liveValidation) {
_event(type.node, "keyup", this._bind_live_validation(id, this));
this.validateEditor(id);
}
return node;
},
_bind_live_validation: function (id, that) {
return function () {
that.validateEditor(id);
};
},
_get_new_value: function (editor) {
var parser = this.getColumnConfig(editor.column).editParse;
var new_value = editor.getValue();
return parser ? parser(new_value) : new_value;
},
_set_new_value: function (editor, new_value, copy$$1) {
var item = copy$$1 ? {} : this.getItem(editor.row);
item[editor.column] = new_value;
if (this._settings.editMath) item["$" + editor.column] = null;
return item;
},
//register editor in collection
_addEditor: function (id, type) {
var row_editors = this._editors[id.row] = this._editors[id.row] || {};
row_editors.$count = (row_editors.$count || 0) + 1;
type.row = id.row;
type.column = id.column;
this._last_editor = row_editors[id.column] = type;
this._in_edit_mode++;
this._last_editor_scroll = this.getScrollState();
},
_removeEditor: function (editor) {
if (this._last_editor == editor) this._last_editor = 0;
if (editor.destroy) editor.destroy();
var row = this._editors[editor.row];
delete row[editor.column];
row.$count--;
if (!row.$count) delete this._editors[editor.row];
this._in_edit_mode--;
},
_changeEditorId: function (oldid, newid) {
var editor = this._editors[oldid];
if (editor) {
this._editors[newid] = editor;
delete this._editors[oldid];
for (var key in editor) {
if (key != "$count") editor[key].row = newid;
}
}
},
//get html cell by combined id
_locate_cell: function (id) {
var area,
i,
index,
j,
node,
span,
config = this.getColumnConfig(id.column),
cell = 0;
if (config && config.node && config.attached) {
index = this.getIndexById(id.row);
if (this._spans_pull) {
span = this.getSpan(id.row, id.column);
if (span) {
for (i = 0; i < 3; i++) {
area = this._spans_areas[i];
for (j = 0; !cell && j < area.childNodes.length; j++) {
node = area.childNodes[j];
if (node.getAttribute(
/*@attr*/
"row") == index && node.getAttribute(
/*@attr*/
"column") == this.getColumnIndex(id.column)) cell = node;
}
}
}
}
if (!cell && index >= config._yr0 - this._settings.topSplit && index < config._yr1) cell = config.node.childNodes[index - config._yr0 + this._settings.topSplit];
}
return cell;
},
/////////////////////////
// public methods //
/////////////////////////
editCell: function (row, column, preserve, show) {
column = column || this._settings.columns[0].id;
return EditAbility.edit.call(this, {
row: row,
column: column
}, preserve, show);
},
editRow: function (id) {
if (id && id.row) id = id.row;
var next = false;
this.eachColumn(function (column) {
this.edit({
row: id,
column: column
}, next, !next);
next = true;
});
},
editColumn: function (id) {
if (id && id.column) id = id.column;
var next = false;
this.eachRow(function (row) {
this.edit({
row: row,
column: id
}, next, !next);
next = true;
});
},
eachRow: function (handler, all) {
var order = this.data.order;
if (all) order = this.data._filter_order || order;
for (var i = 0; i < order.length; i++) {
handler.call(this, order[i]);
}
},
eachColumn: function (handler, all) {
var hidden = this._hidden_column_order;
if (all && hidden.length) {
for (var i = 0; i < hidden.length; i++) {
var column = this.getColumnConfig(hidden[i]);
handler.call(this, column.id, column);
}
} else {
var columns = [].concat(this._columns);
for (var _i = 0; _i < columns.length; _i++) {
var _column = columns[_i];
handler.call(this, _column.id, _column);
}
}
},
////////////////////
// edit next //
////////////////////
_after_edit_next: function (editor_next) {
if (this.getSelectedId) {
//select related cell when possible
var sel = this.getSelectedId(true);
if (sel.length == 1) {
this._select(editor_next);
return false;
}
}
},
_custom_tab_handler: function (tab, e) {
if (this._settings.editable && !this._in_edit_mode) {
//if we have focus in some custom input inside of datatable
if (e.target && e.target.tagName == "INPUT") return true; //init editor related to a single selected row/column/cell
var selection = this.getSelectedId(true);
if (selection.length == 1) {
var sel = selection[0];
if (this._settings.select == "row") sel.column = this._settings.columns[e.shiftKey ? 0 : this._settings.columns.length - 1].id;
this.editNext(tab, sel);
return false;
}
}
return true;
},
_find_cell_next: function (start, check, direction) {
var row = this.getIndexById(start.row);
var column = this.getColumnIndex(start.column);
var order = this.data.order;
var cols = this._columns;
if (direction) {
for (var i = row; i < order.length; i++) {
for (var j = column + 1; j < cols.length; j++) {
var id = {
row: order[i],
column: cols[j].id
};
if (check.call(this, id) && (!this._checkCellMerge || !this._checkCellMerge(start, id))) {
return id;
}
}
column = -1;
}
} else {
for (var _i2 = row; _i2 >= 0; _i2--) {
for (var _j = column - 1; _j >= 0; _j--) {
var _id = {
row: order[_i2],
column: cols[_j].id
};
if (check.call(this, _id)) return _id;
}
column = cols.length;
}
}
return null;
},
/////////////////////////////
// scroll correction //
/////////////////////////////
_correct_after_focus_y: function () {
if (this._in_edit_mode) {
if (this._ignore_after_focus_scroll) this._ignore_after_focus_scroll = false;else {
this._y_scroll.scrollTo(this.getScrollState().y + this._body.childNodes[1].firstChild.scrollTop);
this._body.childNodes[1].firstChild.scrollTop = 0;
this._ignore_after_focus_scroll = true;
}
}
},
_correct_after_focus_x: function () {
if (this._in_edit_mode) {
this._x_scroll.scrollTo(this._body.childNodes[1].scrollLeft);
}
},
_component_specific_edit_init: function () {
this.attachEvent("onScrollY", this._update_editor_y_pos);
this.attachEvent("onScrollX", this._update_editor_y_pos);
this.attachEvent("onScrollY", this._refocus_inline_editor);
this.attachEvent("onColumnResize", function () {
this.editStop();
});
this.attachEvent("onAfterFilter", function () {
this.editStop();
});
this.attachEvent("onRowResize", function () {
this.editStop();
});
this.attachEvent("onAfterScroll", function () {
if (this._settings.topSplit) this.editStop();
});
this._body.childNodes[1].firstChild.onscroll = bind(this._correct_after_focus_y, this);
this._body.childNodes[1].onscroll = bind(this._correct_after_focus_x, this);
},
_update_editor_y_pos: function () {
if (this._in_edit_mode) {
var old = this._last_editor_scroll;
this._last_editor_scroll = this.getScrollState();
var diff = this._last_editor_scroll.y - old.y;
this._for_each_editor(function (editor) {
if (editor.getPopup) {
var node = this.getItemNode(editor);
var isHidden = false;
if (this._settings.prerender) {
var pos = editor._editor_pos;
var ydiff = pos.top - this._scrollTop;
var xdiff = pos.left - this._scrollLeft;
isHidden = ydiff < 0 || ydiff + pos.height > this._dtable_offset_height || xdiff < 0 || xdiff + pos.width > this.$width - this._scrollSizeX;
}
if (!node || isHidden) editor.getPopup().show({
x: -10000,
y: -10000
});else editor.getPopup().show(node);
}
if (!this._settings.prerender && !editor.linkInput && !editor.$inline) {
editor.node.top -= diff;
editor.node.style.top = editor.node.top + "px";
}
});
}
}
};
var Mixin$8 = {
$init: function () {
this._clear_hidden_state();
this.attachEvent("onStructureLoad", this._hideInitialColumns);
},
_clear_hidden_state: function () {
this._hidden_column_hash = {};
this._hidden_column_order = _to_array();
this._hidden_split = [0, 0, 0];
},
_hideInitialColumns: function () {
var cols = this._columns;
for (var i = 0; i < cols.length; i++) {
if (cols[i].header) this._getInitialSpans(cols, cols[i].header);
if (cols[i].footer) this._getInitialSpans(cols, cols[i].footer);
}
for (var _i = cols.length - 1; _i >= 0; _i--) {
if (cols[_i].hidden) this.hideColumn(cols[_i].id, {}, true, true);else if (cols[_i].batch && this.config.visibleBatch && cols[_i].batch != this.config.visibleBatch) {
this.hideColumn(cols[_i].id, {}, true, true);
}
}
},
_getInitialSpans: function (cols, elements) {
for (var i = 0; i < elements.length; i++) {
var line = elements[i];
if (line && line.colspan && !line.$colspan) line.$colspan = line.colspan;
}
},
moveColumn: function (id, index) {
var cindex = this.getColumnIndex(id);
if (cindex == index || cindex == -1) return false; //already in place
var horder = this._hidden_column_order;
var columns = this._settings.columns; // remove from the previous place
var hindex;
var col = columns.splice(cindex, 1)[0];
if (horder.length) {
hindex = horder.find(id);
horder.removeAt(hindex);
}
this._updateSplit(cindex, hindex, -1); // paste into new
var nindex = index - (index > cindex ? 1 : 0);
_power_array.insertAt.call(columns, col, nindex);
var pos;
if (horder.length) {
var prev = columns[nindex - 1];
pos = prev && prev.id ? horder.find(prev.id) + 1 : 0;
horder.insertAt(col.id, pos);
}
this._updateSplit(nindex, pos, 1);
this._refresh_columns();
},
_init_horder: function (horder, cols) {
if (!horder.length) {
for (var i = 0; i < cols.length; i++) {
horder[i] = cols[i].id;
}
this._hidden_split = [this._settings.leftSplit, this._rightSplit, this._settings.rightSplit];
}
},
isColumnVisible: function (id) {
return !this._hidden_column_hash[id];
},
hideColumn: function (id, opts, silent, mode) {
var cols = this._settings.columns;
var horder = this._hidden_column_order;
var hhash = this._hidden_column_hash;
var column,
span = 1;
opts = opts || {};
if (mode !== false) {
var index = this.getColumnIndex(id);
assert(index != -1, "hideColumn: invalid ID or already hidden"); //in case of second call to hide the same column, command will be ignored
if (index == -1 || !this.callEvent("onBeforeColumnHide", [id])) return;
this._init_horder(horder, cols);
if (opts.spans) {
var header = cols[index].header;
for (var i = 0; i < header.length; i++) {
if (header[i]) span = Math.max(span, header[i].colspan || 1);
}
}
this._fixSplit(index, span, -1);
for (var _i2 = index + span - 1; _i2 >= index; _i2--) {
this._hideColumn(index);
column = cols.splice(index, 1)[0];
hhash[column.id] = column;
column._yr0 = -1;
column.hidden = true;
delete this._columns_pull[column.id];
}
this.callEvent("onAfterColumnHide", [id]);
} else {
column = hhash[id];
assert(column, "showColumn: invalid ID or already visible"); //in case of second show command for already visible column - ignoring
if (!column || !this.callEvent("onBeforeColumnShow", [id])) return;
var prev = null;
var hindex = 0;
for (var _i3 = 0; _i3 < horder.length; _i3++) {
if (horder[_i3] == id) {
hindex = _i3;
break;
}
if (!hhash[horder[_i3]]) prev = horder[_i3];
}
if (opts.spans) {
var _header = column.header;
for (var _i4 = 0; _i4 < _header.length; _i4++) {
if (_header[_i4]) {
_header[_i4].colspan = _header[_i4].$colspan || _header[_i4].colspan;
span = Math.max(span, _header[_i4].colspan || 1);
}
}
}
var _index = prev ? this.getColumnIndex(prev) + 1 : 0;
for (var _i5 = hindex + span - 1; _i5 >= hindex; _i5--) {
var col = hhash[horder[_i5]];
if (col) {
//can be already shown by another action
_power_array.insertAt.call(cols, col, _index);
delete col.hidden;
delete hhash[col.id];
this._columns_pull[col.id] = col;
} else span--;
}
this._fixSplit(hindex, span, 1, true);
this.callEvent("onAfterColumnShow", [id]);
}
if (column.header) this._fixColspansHidden(column, mode !== false ? 0 : 1, "header");
if (column.footer) this._fixColspansHidden(column, mode !== false ? 0 : 1, "footer");
if (horder.length === cols.length) this._clear_hidden_state();
if (!silent) this._refresh_columns();
},
showColumn: function (id, opts, silent) {
return this.hideColumn(id, opts, silent, false);
},
_fixSplit: function (index, span, op, hidden) {
var _ref = hidden ? this._hidden_split : [this._settings.leftSplit, this._rightSplit],
_ref2 = _slicedToArray(_ref, 2),
lSplit = _ref2[0],
rSplit = _ref2[1];
if (index < lSplit) this._settings.leftSplit += op * span;
if (index >= rSplit) this._settings.rightSplit += op * span;else this._rightSplit += op * span;
},
_updateSplit: function (index, hindex, op) {
if (index >= 0) {
if (index < this._settings.leftSplit) this._settings.leftSplit += op;
if (this._settings.rightSplit && index >= this._rightSplit) this._settings.rightSplit += op;else this._rightSplit += op;
}
var horder = this._hidden_column_order;
if (horder.length && hindex >= 0) {
if (hindex < this._hidden_split[0]) this._hidden_split[0] += op;
if (this._hidden_split[2] && hindex >= this._hidden_split[1]) this._hidden_split[2] += op;else this._hidden_split[1] += op;
}
},
_fixColspansHidden: function (config, mod, elName) {
for (var i = config[elName].length - 1; i >= 0; i--) {
var ind = this._hidden_column_order;
var spanSource,
isHidden = false,
spanSize = 0;
for (var j = 0; j < ind.length; j++) {
var colConfig = this.getColumnConfig(ind[j]);
var el = colConfig[elName][i];
if (!this.isColumnVisible(ind[j])) {
//hidden column
if (el && el.$colspan && spanSize <= 0) {
//start of colspan in hidden
spanSize = el.colspan = el.$colspan;
isHidden = spanSource = el;
}
if (spanSource && spanSize > 0) {
//hidden column in colspan, decrease colspan size
spanSource.colspan--;
}
} else {
//visible column
if (isHidden && spanSize > 0 && spanSource && spanSource.colspan > 0) {
//bit start of colspan is hidden
el = colConfig[elName][i] = spanSource;
spanSource = el;
} else if (el && el.$colspan && spanSize <= 0) {
//visible start of colspan
spanSize = el.colspan = el.$colspan;
spanSource = el;
}
isHidden = null;
}
spanSize--;
}
}
},
refreshColumns: function (columns) {
this._dtable_column_refresh = true;
if (columns) {
this._clear_hidden_state();
this._filter_elements = {};
}
this._columns_pull = {}; //clear rendered data
for (var i = 0; i < this._columns.length; i++) {
var col = this._columns[i];
this._columns_pull[col.id] = col;
col.attached = col.node = null;
}
for (var _i6 = 0; _i6 < 3; _i6++) {
this._header.childNodes[_i6].innerHTML = "";
this._body.childNodes[_i6].firstChild.innerHTML = "";
} //render new structure
this._columns = this.config.columns = columns || this.config.columns;
this._rightSplit = this._columns.length - (this.config.rightSplit || 0);
this._dtable_fully_ready = 0;
this._define_structure();
this._update_scroll();
this.callEvent("onStructureUpdate");
this.render();
this._dtable_column_refresh = false;
},
_refresh_columns: function () {
this._dtable_fully_ready = 0;
this.callEvent("onStructureUpdate");
this._apply_headers();
this.render();
},
showColumnBatch: function (batch, mode, silent) {
var preserve = typeof mode != "undefined";
mode = mode !== false;
var sub = [];
this.eachColumn(function (id, col) {
if (col.batch) {
var hidden = this._hidden_column_hash[col.id];
if (!mode) hidden = !hidden;
if (col.batch == batch && hidden) this.hideColumn(col.id, {
spans: true
}, true, !mode);else if (!preserve && col.batch != batch && !hidden) this.hideColumn(col.id, {
spans: true
}, true, mode);
}
if (preserve && mode) {
var header = col.header;
for (var i = 0; i < header.length; i++) {
if (header[i] && header[i].batch && header[i].closed) sub.push(header[i].batch);
}
}
}, true); // hide closed batches
for (var i = 0; i < sub.length; i++) {
if (sub[i] != batch) this.showColumnBatch(sub[i], false, true);
}
if (!silent) this._refresh_columns();
}
};
var Mixin$9 = {
$init: function (config) {
this.attachEvent("onAfterScroll", this._set_focusable_item);
this.attachEvent("onFocus", function () {
addCss(this.$view, "webix_dtable_focused");
});
this.attachEvent("onBlur", function () {
removeCss(this.$view, "webix_dtable_focused");
}); //open selected node in tree-like tables
if (config.select != "column" && (this.open || this._subViewStorage)) this.attachEvent("onEnter", function () {
var sel = this.getSelectedId(true);
if (sel.length == 1 && !(this.getEditor && this.getEditor())) {
var node = this.getItemNode(sel[0]);
sel = sel[0].row;
if (this.config.select == "row" || node.querySelector(".webix_tree_open") || node.querySelector(".webix_tree_close")) {
if (this.isBranchOpen(sel)) this.close(sel);else this.open(sel);
}
}
});
},
_set_focusable_item: function () {
var sel = this._getVisibleSelection();
if (!sel) {
var node = this._dataobj.querySelector(".webix_cell");
if (node) node.setAttribute("tabindex", "0");
}
},
_getVisibleSelection: function () {
var sel = this.getSelectedId(true);
for (var i = 0; i < sel.length; i++) {
if (sel[i].column && this.isColumnVisible(sel[i].column)) return this.getItemNode(sel[i]);
}
return null;
},
moveSelection: function (mode, details, focus) {
this._delayRender();
if (this._settings.disabled) return;
details = details || {}; //get existing selection as array
var t = this.getSelectedId(true);
var index$$1 = t.length - 1;
var preserve = this._settings.multiselect || this._settings.areaselect ? details.shift : false; //change defaults in case of multiselection
if (t.length > 1 && this._settings.select !== "cell") {
t = t.sort(bind(function (a, b) {
if (this.getIndexById(a.row) > this.getIndexById(b.row) || this.getColumnIndex(a.column) > this.getColumnIndex(b.column)) return 1;else return -1;
}, this));
if (mode == "up" || mode == "left" || mode == "top" || mode == "pgup") index$$1 = 0;
}
if (index$$1 < 0 && this.count()) {
//no selection
if (mode == "down" || mode == "right") mode = "top";else if (mode == "up" || mode == "left") mode = "bottom";else return;
index$$1 = 0;
t = [{
row: 1,
column: 1
}];
}
if (index$$1 >= 0) {
var row = t[index$$1].row;
var column = t[index$$1].column;
if (mode == "top" || mode == "bottom") {
if (row) {
// first/last row setting
if (mode == "top") row = this.data.getFirstId();else if (mode == "bottom") row = this.data.getLastId();
}
if (column) {
// first/last column setting
index$$1 = 0;
if (mode == "bottom") index$$1 = this.config.columns.length - 1;
column = this.columnId(index$$1);
}
} else if (mode == "up" || mode == "down" || mode == "pgup" || mode == "pgdown") {
if (row) {
//it seems row's can be seleted
var _index = this.getIndexById(row);
var step = 1;
if (mode == "pgup" || mode == "pgdown") step = this._pager ? this._pager.config.size : Math.round(this._dtable_offset_height / this._settings.rowHeight); //get new selection row
if (mode == "up" || mode == "pgup") _index -= step;else if (mode == "down" || mode == "pgdown") _index += step; //check that we in valid row range
if (_index < 0) _index = 0;
if (_index >= this.data.order.length) _index = this.data.order.length - 1;
row = this.getIdByIndex(_index);
if (!row && this._settings.pager) this.showItemByIndex(_index);
}
} else if (mode == "right" || mode == "left") {
if (column && this.config.select != "row") {
//it seems column's can be selected
var _index2 = this.getColumnIndex(column); //get new selected column
if (mode == "right") _index2++;else if (mode == "left") _index2--; //check that result column index is in valid range
if (_index2 < 0) _index2 = 0;
if (_index2 >= this.config.columns.length) _index2 = this.config.columns.length - 1;
column = this.columnId(_index2);
} else if ((this.open || this._subViewStorage) && mode == "right") {
return this.open ? this.open(row) : this.openSub(row);
} else if ((this.close || this._subViewStorage) && mode == "left") {
return this.close ? this.close(row) : this.closeSub(row);
}
} else {
assert(false, "Not supported selection moving mode");
return;
}
if (row) {
this.showCell(row, column);
if (!this.select) {
//switch on cell or row selection by default
exports.extend(this, this._selections._commonselect, true);
this._settings.select = this.open || this._subViewStorage ? "row" : "cell";
exports.extend(this, this._selections[this._settings.select], true);
}
var cell = {
row: row,
column: column
};
if (preserve && this._settings.select == "area") {
var last = this._selected_areas[this._selected_areas.length - 1];
this._extendAreaRange(cell, last, mode, details);
} else this._select(cell, preserve);
if (!this._settings.clipboard && focus !== false) {
var node = this.getItemNode(cell);
if (node) node.focus();
}
}
}
return false;
}
};
var DragOrder$1 = {
_set_drop_area: function (target) {
for (var i = 0; i < this._columns.length; i++) {
var column = this._columns[i];
var node = this.getItemNode({
row: target,
cind: i
});
if (node) {
node.parentNode.insertBefore(DragControl._dropHTML[i], node);
} else column.node.appendChild(DragControl._dropHTML[i]);
}
},
_init_drop_area: function () {
var dropArea = [];
var count = this._columns.length;
var node = document.createElement("div");
node.className = "webix_drop_area";
node.style.height = this._settings.rowHeight + "px";
node.innerHTML = this.$dropHTML();
for (var i = 0; i < count; i++) {
dropArea.push(node.cloneNode(true));
}
return dropArea;
}
};
var Mixin$a = {
drag_setter: function (value) {
// disable drag-n-drop for frozen rows
this.attachEvent("onBeforeDrag", function (context) {
return this._checkDragTopSplit(context.source);
});
this.attachEvent("onBeforeDragIn", function (context) {
var result = this._checkDragTopSplit(context.target);
if (!result && DragControl._dropHTML) {
remove(DragControl._dropHTML);
this._marked_item_id = DragControl._dropHTML = null;
}
return result;
});
DragItem.drag_setter.call(this, value);
if (value == "order" || value == "move") exports.extend(this, DragOrder$1, true);
return value;
},
_add_css: function (source, css, mark) {
var context = DragControl._drag_context;
if (!this._settings.prerender && !mark) source = [context.start];
for (var i = 0; i < source.length; i++) {
for (var j = 0; j < this._columns.length; j++) {
var node = this.getItemNode({
row: source[i],
cind: j
});
if (node) addCss(node, css);
}
this.data.addMark(source[i], css, 1, 1, true);
}
},
_remove_css: function (source, css, mark) {
var context = DragControl._drag_context;
if (!this._settings.prerender && !mark) source = [context.start];
for (var i = 0; i < source.length; i++) {
for (var j = 0; j < this._columns.length; j++) {
var node = this.getItemNode({
row: source[i],
cind: j
});
if (node) removeCss(node, css);
}
this.data.removeMark(source[i], css, 1, true);
}
},
_checkDragTopSplit: function (ids) {
var i,
index$$1,
frozen = false;
if (this._settings.topSplit && ids) {
if (!isArray(ids)) ids = [ids];
for (i = 0; !frozen && i < ids.length; i++) {
index$$1 = this.getIndexById(ids[i]);
frozen = index$$1 >= 0 && index$$1 < this._settings.topSplit;
}
}
return !frozen;
},
_toHTML: function (obj) {
var width = this._content_width - this._scrollSizeY;
var html = "<div class='webix_dd_drag' style='width:" + width + "px;'>";
var cols = this._settings.columns;
for (var i = 0; i < cols.length; i++) {
var value = this._getValue(obj, cols[i]);
html += "<div style='width:" + cols[i].width + "px;'>" + value + "</div>";
}
return html + "</div>";
},
getHeaderNode: function (column_id, row_index) {
return this._getHeaderNode(column_id, row_index, this._header);
},
getFooterNode: function (column_id, row_index) {
return this._getHeaderNode(column_id, row_index, this._footer);
},
_getHeaderNode: function (column_id, row_index, group) {
if (this.isColumnVisible(column_id)) {
var ind = this.getColumnIndex(column_id);
var hind = this._settings.leftSplit > ind ? 0 : this._rightSplit <= ind ? 2 : 1;
row_index = row_index || 0;
var groupNode = group.childNodes[hind];
var row =
/*@attr*/
"column";
var column =
/*@attr*/
"row";
return groupNode.querySelector("div[".concat(row, "=\"").concat(ind, "\"][").concat(column, "=\"").concat(row_index, "\"]"));
}
return null;
},
getItemNode: function (id) {
if (id && !id.header) {
var row = id.row || id;
var rowindex = typeof id.rind === "number" ? id.rind : this.getIndexById(row);
var state = this._get_y_range();
var minRow = state[0] - this._settings.topSplit; //row not visible
if (rowindex < minRow && rowindex > state[1]) return; //get visible column
var x_range = this._get_x_range();
var colindex = this._settings.leftSplit ? 0 : x_range[0];
var specific = typeof id.cind === "number";
if (id.column || specific) {
colindex = specific ? id.cind : this.getColumnIndex(id.column); //column not visible
if (colindex < this._rightSplit && colindex >= this._settings.leftSplit && (colindex < x_range[0] || colindex > x_range[1])) return;
}
var column = this._settings.columns[colindex];
if (column && column.attached && column.node) {
if (row === "$webix-drop") return DragControl._dropHTML[colindex];
var nodeIndex = rowindex < this._settings.topSplit || this._settings.prerender ? rowindex : rowindex - minRow;
var nodes = column.node.childNodes;
var length = Math.min(nodes.length, nodeIndex + 1);
for (var i = 0; i < length; i++) {
if (nodes[i].className === "webix_drop_area") nodeIndex++;
}
return nodes[nodeIndex];
}
}
},
_isDraggable: function (e) {
var nodeName = e.target.nodeName;
return nodeName != "INPUT" && nodeName != "TEXTAREA";
},
dragColumn_setter: function (value) {
var control; //will be defined below
if (value == "order") {
control = {
$drag: bind(function (s, e) {
if (!this._isDraggable(e) || this._rs_process) return false;
var id = this.locate(e);
if (!id || !this.callEvent("onBeforeColumnDrag", [id.column, e])) return false;
DragControl._drag_context = {
from: control,
start: id,
custom: "column_dnd"
};
var column = this.getColumnConfig(id.column);
this._relative_column_drag = posRelative(e);
this._limit_column_drag = column.width;
this._auto_scroll_force = true;
return "<div class='webix_dd_drag_column' style='width:" + column.width + "px'>" + (column.header[0].text || " ") + "</div>";
}, this),
$dragPos: bind(function (pos$$1, e, node) {
var _this = this;
var context = DragControl.getContext();
var box = offset(this.$view);
node.style.display = "none";
var html = document.elementFromPoint(pos$$1.x, box.y + this._settings.headerRowHeight / 2);
var id = html ? this.locate(html) : null;
var start = DragControl.getContext().start.column;
if (id && id.column != start && (!this._column_dnd_temp_block || id.column != this._last_sort_dnd_node)) {
//ignore normal dnd , and dnd from other components
if (context.custom == "column_dnd" && $$(html) == this) {
if (!this.callEvent("onBeforeColumnDropOrder", [start, id.column, e])) return;
var start_index = this.getColumnIndex(start);
var end_index = this.getColumnIndex(id.column); //on touch devices we need to preserve drag-start element till the end of dnd
if (e.touches) {
this._dragTarget = e.target;
this._dragTarget.style.display = "none";
this.$view.parentNode.appendChild(this._dragTarget);
}
this.moveColumn(start, end_index + (start_index < end_index ? 1 : 0));
this._last_sort_dnd_node = id.column;
this._column_dnd_temp_block = true;
}
}
if (id && id.column == start) {
//flag prevent flickering just after column move
this._column_dnd_temp_block = false;
}
node.style.display = "block";
pos$$1.x = pos$$1.x - this._relative_column_drag.x;
pos$$1.y = box.y;
if (pos$$1.x < box.x) pos$$1.x = box.x;else {
var max = box.x + this.$view.offsetWidth - this._scrollSizeY - this._limit_column_drag;
if (pos$$1.x > max) pos$$1.x = max;
}
DragControl._skip = true;
if (this._auto_scroll_delay) this._auto_scroll_delay = window.clearTimeout(this._auto_scroll_delay);
if (this._settings.dragscroll !== false) this._auto_scroll_delay = delay(function (pos$$1) {
return _this._auto_scroll_column(pos$$1);
}, this, [pos(e)], 250);
}, this),
$dragDestroy: bind(function (a, node) {
this._auto_scroll_force = null;
if (this._auto_scroll_delay) this._auto_scroll_delay = window.clearTimeout(this._auto_scroll_delay);
remove(node); //clean dnd source element
if (this._dragTarget) remove(this._dragTarget);
var id = DragControl.getContext().start;
this.callEvent("onAfterColumnDropOrder", [id.column, this._last_sort_dnd_node, a]);
}, this),
$drop: function () {}
};
} else if (value) {
control = {
_inner_drag_only: true,
$drag: bind(function (s, e) {
if (!this._isDraggable(e) || this._rs_process) return false;
var id = this.locate(e);
if (!id || !this.callEvent("onBeforeColumnDrag", [id.column, e])) return false;
DragControl._drag_context = {
from: control,
start: id,
custom: "column_dnd"
};
var header = this.getColumnConfig(id.column).header;
var text = " ";
for (var i = 0; i < header.length; i++) {
if (header[i]) {
text = header[i].text;
break;
}
}
this._auto_scroll_force = true;
return "<div class='webix_dd_drag_column'>" + text + "</div>";
}, this),
$drop: bind(function (s, t, e) {
var target = e; //on touch devices event doesn't point to the actual drop target
if (e.touches && this._drag_column_last) target = this._drag_column_last;
var id = this.locate(target);
if (!id) return false;
var start = DragControl.getContext().start.column;
if (start != id.column) {
if (!this.callEvent("onBeforeColumnDrop", [start, id.column, e])) return;
var start_index = this.getColumnIndex(start);
var end_index = this.getColumnIndex(id.column);
this.moveColumn(start, end_index + (start_index < end_index ? 1 : 0));
this.callEvent("onAfterColumnDrop", [start, id.column, e]);
}
}, this),
$dragIn: bind(function (s, t, e) {
var _this2 = this;
var context = DragControl.getContext(); //ignore normal dnd , and dnd from other components
if (context.custom != "column_dnd" || context.from != control) return false;
var target = e.target;
while ((target.className || "").indexOf("webix_hcell") == -1) {
target = target.parentNode;
if (!target) return;
}
if (this._auto_scroll_delay) this._auto_scroll_delay = window.clearTimeout(this._auto_scroll_delay);
if (this._settings.dragscroll !== false) this._auto_scroll_delay = delay(function (pos$$1) {
return _this2._auto_scroll_column(pos$$1);
}, this, [pos(e)], 250);
if (target != this._drag_column_last) {
//new target
if (this._drag_column_last) removeCss(this._drag_column_last, "webix_dd_over_column");
addCss(target, "webix_dd_over_column");
}
return this._drag_column_last = target;
}, this),
$dragDestroy: bind(function (a, h) {
this._auto_scroll_force = null;
if (this._auto_scroll_delay) this._auto_scroll_delay = window.clearTimeout(this._auto_scroll_delay);
if (this._drag_column_last) removeCss(this._drag_column_last, "webix_dd_over_column");
remove(h);
}, this)
};
}
if (value) {
DragControl.addDrag(this._header, control);
DragControl.addDrop(this._header, control, true);
this.attachEvent("onDestruct", function () {
return DragControl.unlink(control);
});
if (!this._auto_scroll) exports.extend(this, AutoScroll, true);
}
return value;
}
};
var Mixin$b = {
clearValidation: function () {
for (var i in this.data._marks) {
this._clear_invalid_css(i);
}
this.data.clearMark("webix_invalid", true);
},
_mark_invalid: function (id, details) {
this._clear_invalid_css(id);
for (var key in details) {
this.addCellCss(id, key, "webix_invalid_cell");
}
this.addCss(id, "webix_invalid");
},
_clear_invalid: function (id) {
this._clear_invalid_css(id);
this.removeCss(id, "webix_invalid");
},
_clear_invalid_css: function (id) {
var mark = this.data.getMark(id, "$cellCss");
if (mark) {
for (var key in mark) {
mark[key] = mark[key].replace("webix_invalid_cell", "").replace(" ", " ");
}
}
},
addRowCss: function (id, css, silent) {
this.addCss(id, css, silent);
},
removeRowCss: function (id, css, silent) {
this.removeCss(id, css, silent);
},
addCellCss: function (id, name, css, silent) {
var mark = this.data.getMark(id, "$cellCss");
var newmark = mark || {};
var style = newmark[name] || "";
newmark[name] = style.replace(css, "").replace(" ", " ") + " " + css;
if (!mark) this.data.addMark(id, "$cellCss", false, newmark, true);
if (!silent) this.refresh(id);
},
removeCellCss: function (id, name, css, silent) {
var mark = this.data.getMark(id, "$cellCss");
if (mark) {
var style = mark[name] || "";
if (style) mark[name] = style.replace(css, "").replace(" ", " ");
if (!silent) this.refresh(id);
}
}
};
var Mixin$c = {
_prePrint: function (options, htmlOnly) {
if (options.scroll && !htmlOnly) return true;
options.header = isUndefined(options.header) ? this.config.header ? true : false : options.header;
options.footer = isUndefined(options.footer) ? this.config.footer ? true : false : options.footer;
options.xCorrection = options.xCorrection || 0; //spreadsheet
},
_findIndex: function (arr, func) {
var result = -1;
for (var i = 0; result < 0 && i < arr.length; i++) {
if (func(arr[i])) result = i;
}
return result;
},
_getTableHeader: function (base, columns, group) {
var spans = {},
start = 0;
base.forEach(bind(function (tableArray, tid) {
var row = tableArray[0],
headerArray = [],
length = row.length;
row.forEach(bind(function (cell, cid) {
var column = columns[cid + start];
for (var h = 0; h < column[group].length; h++) {
var header = column[group][h];
if (!header && !(spans[tid] && spans[tid][h])) continue;
header = copy(header || {
text: ""
});
if (spans[tid] && spans[tid][h] && cid === 0) {
header.colspan = spans[tid][h];
spans[tid][h] = 0;
}
if (header.colspan) {
var colspan = Math.min(header.colspan, length - cid);
spans[tid + 1] = spans[tid + 1] || {};
spans[tid + 1][h] = header.colspan - colspan;
header.colspan = colspan;
}
if (header.rowspan && length === 1) {
header.height = (header.height || this.config.headerRowHeight) * header.rowspan;
header.rowspan = null;
}
var hcell = {
txt: header.rotate ? this.getHeaderNode(column.id, h).innerHTML : header.text || (header.contentId ? this.getHeaderContent(header.contentId).getValue() : ""),
className: "webix_hcell " + "webix_" + group + "_cell " + (header.css || ""),
style: {
height: (header.height || this.config.headerRowHeight) + "px",
width: header.colspan ? "auto" : column.width + "px"
},
span: header.colspan || header.rowspan ? {
colspan: header.colspan || 1,
rowspan: header.rowspan || 1
} : null
};
headerArray[h] = headerArray[h] || [];
headerArray[h][cid] = hcell;
}
}, this));
if (group == "header") base[tid] = headerArray.concat(tableArray);else base[tid] = tableArray.concat(headerArray);
start += length;
}, this));
return base;
},
_getTableArray: function (options, base, start) {
var columns = this.config.columns;
var sel = this.getSelectedId(true);
var maxWidth = options.fit == "page" ? Infinity : this._getPageWidth(options);
var rightRestriction = 0;
var bottomRestriction = 0;
var tableArray = [];
var newTableStart = 0;
var widths = [];
start = start || 0 + options.xCorrection;
base = base || [];
this.eachRow(bind(function (row) {
var width = 0;
var rowItem = this.getItem(row);
var rowIndex = this.getIndexById(row);
var colrow = [];
var datarow = false;
for (var c = start; c < columns.length; c++) {
var column = columns[c].id;
var colIndex = this.getColumnIndex(column) - start;
if (columns[c]) {
width += columns[c].width;
if (rowIndex === 0) widths.push(columns[c].width);
if (width > maxWidth && c > start) {
// 'c>start' ensures that a single long column will have to fit the page
newTableStart = c;
break;
}
if (options.data !== "selection" || options.data == "selection" && this._findIndex(sel, function (obj) {
return obj.column == column && obj.row == row;
}) !== -1) {
var span;
if (this.getSpan) span = this.getSpan(row, column); //check span from previous table
if (span && this.getColumnIndex(column) === start) {
var spanStart = this.getColumnIndex(span[1]);
if (spanStart < start) {
span[2] = span[2] - (start - spanStart);
span[4] = span[4] ? span[4] : rowItem[span[1]] ? this.getText(row, span[1]) : null;
span[1] = column;
}
}
if (!span || span && span[0] == row && span[1] == column) {
var cellValue = span && span[4] ? span[4] : this._columns_pull[column] ? this.getText(row, column) : "";
var className = this.getCss(row, column) + " " + (columns[c].css || "") + (span ? " webix_dtable_span " + (span[5] || "") : "");
var style = {
height: span && span[3] > 1 ? "auto" : (rowItem.$height || this.config.rowHeight) + "px",
width: span && span[2] > 1 ? "auto" : columns[c].width + "px"
};
colrow.push({
txt: cellValue,
className: className,
style: style,
span: span ? {
colspan: span[2],
spanStart: this.getColumnIndex(span[1]),
rowspan: span[3]
} : null
});
if (cellValue || cellValue === 0) {
rightRestriction = Math.max(colIndex + 1, rightRestriction);
bottomRestriction = Math.max(rowIndex + 1, bottomRestriction);
}
datarow = datarow || !!cellValue;
} else if (span) {
colrow.push({
$inspan: true
});
rightRestriction = Math.max(colIndex + 1, rightRestriction);
bottomRestriction = Math.max(rowIndex + 1, bottomRestriction);
}
}
}
}
if (!options.skiprows || datarow) tableArray.push(colrow);
}, this));
if (bottomRestriction && rightRestriction) {
if (options.trim) {
tableArray.length = bottomRestriction;
tableArray = tableArray.map(function (item) {
for (var i = item.length - 1; i >= 0; i--) {
if (item[i].span && item[i].span.colspan) {
item[i].span.colspan = Math.min(item[i].span.colspan, item.length - i);
break;
}
}
item.length = rightRestriction;
return item;
});
}
base.push(tableArray);
}
if (newTableStart) this._getTableArray(options, base, newTableStart);else {
//keep this order as logic relies on the first data row
if (options.footer) base = this._getTableHeader(base, columns, "footer");
if (options.header) base = this._getTableHeader(base, columns, "header");
if (options.fit == "page") this._correctWidth(base, widths, rightRestriction, options);
}
return base;
},
//a single grid tries to fit to page size - set column width to auto
_correctWidth: function (base, widths, rightRestriction, options) {
if (rightRestriction && options.trim) widths.length = rightRestriction;
var rwidth = 0;
for (var i = 0; i < widths.length; i++) {
rwidth += widths[i];
}
if (rwidth > this._getPageWidth(options)) {
base[0].forEach(function (item) {
for (var _i = 0; _i < item.length; _i++) {
if (item[_i] && item[_i].style && item[_i].style.width) item[_i].style.width = "auto";
}
});
}
},
_getTableHTML: function (tableData, options) {
var container = create("div");
tableData.forEach(bind(function (table, i) {
var tableHTML = create("table", {
"class": "webix_table_print " + this.$view.className + (options.borderless ? " borderless" : ""),
"style": "border-collapse:collapse",
"id": this.$view.getAttribute("id")
});
table.forEach(function (row) {
var tr = create("tr");
row.forEach(function (cell) {
if (!cell.$inspan) {
var td = create("td");
td.innerHTML = cell.txt;
td.className = cell.className;
for (var key in cell.style) {
td.style[key] = cell.style[key];
}
if (cell.span) {
td.colSpan = cell.span.colspan;
td.rowSpan = cell.span.rowspan;
}
tr.appendChild(td);
}
});
tableHTML.appendChild(tr);
});
container.appendChild(tableHTML);
if (i + 1 < tableData.length) {
var br = create("DIV", {
"class": "webix_print_pagebreak"
});
container.appendChild(br);
}
}, this));
return container;
}
};
var Mixin$d = {
$exportView: function (options) {
if (this.isBranchOpen) //treetable
exports.extend(options, {
filterHTML: true
});
var mode = options.export_mode;
if (mode != "pdf" && mode != "excel" || options.dataOnly || !options.styles) return this;else {
//excel export with styles
options.dataOnly = true;
options.heights = isUndefined(options.heights) ? "all" : options.heights;
var data = mode == "pdf" ? toPDF(this, options) : toExcel(this, options);
data[0].styles = this._getExportStyles(options);
delete options.dataOnly;
return data;
}
},
_getExportStyles: function (options) {
var type = options.export_mode;
var columns = this.config.columns;
var styles = [];
if (!this._style_hash) this._style_hash = {};
if (!this._style_hash[type]) this._style_hash[type] = {};
if (options.docHeader && type == "excel") styles = [{
0: this._getExportDocStyle(options.docHeader.css)
}, {
0: {}
}];
if (options.header !== false) styles = this._getExportHStyles(options, "header", styles, type);
this.data.each(function (obj) {
var row = {};
for (var i = 0; i < columns.length; i++) {
var cellCss = this.getCss(obj.id, columns[i].id);
var columnCss = columns[i].node.className;
var spanCss = "";
var span = null;
var node = null;
if (this._spans_pull && (span = this.getSpan(obj.id, columns[i].id))) {
node = this.getSpanNode({
row: span[0],
column: span[1]
});
spanCss = "webix_dtable_span " + (span[5] || "");
} else node = this.getItemNode({
row: obj.id,
column: columns[i].id
});
if (!node) {
node = create("div", {
"class": cellCss,
style: "visibility:hidden"
});
var cnode = columns[i].node;
if (!columns[i].attached) {
cnode = create("div", {
"class": columnCss,
style: "visibility:hidden"
});
this._body.appendChild(cnode);
}
cnode.appendChild(node);
}
row[i] = this._getExportCellStyle(node, [cellCss, columnCss, spanCss].join(":"), type);
}
styles[styles.length] = row;
}, this);
if (options.footer !== false && this.config.footer) styles = this._getExportHStyles(options, "footer", styles, type);
if (options.docFooter && type == "excel") styles = styles.concat([{
0: {}
}, {
0: this._getExportDocStyle(options.docFooter.css)
}]);
return styles;
},
_getExportHStyles: function (options, group, styles, type) {
var columns = this.config.columns;
var hs = []; //spans
for (var h = 0; h < columns[0][group].length; h++) {
var hrow = {};
for (var i = 0; i < columns.length; i++) {
var header = columns[i][group][h]; //ToDo:make sure it is rendered and attached
if (header) {
//can be null
var cid = header.colspan ? columns[i + header.colspan - 1].id : columns[i].id;
var node = group == "header" ? this.getHeaderNode(cid, h) : this.getFooterNode(cid, h);
if (node) {
var name = [node.className, header.css || "", group];
hrow[i] = this._getExportCellStyle(node, name.join(":"), type);
if (header.colspan || header.rowspan) hs.push([h, i, {
colspan: header.colspan - 1 || 0,
rowspan: header.rowspan - 1 || 0
}, hrow[i]]);
}
} else {
for (var s = 0; s < hs.length; s++) {
var st = hs[s][2],
hsc = hs[s][1],
hsr = hs[s][0];
if (hsc + st.colspan >= i && hsr + st.rowspan >= h) hrow[i] = hs[s][3];
}
}
}
styles[styles.length] = hrow;
}
return styles;
},
_getBorderColor: function (styles, defaultColor, type) {
return styles["border-".concat(type, "-width")] == "0px" ? null : color.rgbToHex(styles["border-".concat(type, "-color")]) || defaultColor;
},
_getExportCellStyle: function (node, name, type) {
if (this._style_hash[type][name]) return this._style_hash[type][name];else {
var cellStyle = this._getRules(node);
var bg = color.rgbToHex(cellStyle["background-color"]) || "FFFFFF";
var common = {
backgroundColor: bg,
fontSize: cellStyle["font-size"].replace("px", "") * 0.75,
//px to pt conversion
color: color.rgbToHex(cellStyle["color"]),
textAlign: cellStyle["text-align"],
borderRightColor: this._getBorderColor(cellStyle, bg, "right"),
borderLeftColor: this._getBorderColor(cellStyle, bg, "left"),
borderBottomColor: this._getBorderColor(cellStyle, bg, "bottom"),
borderTopColor: this._getBorderColor(cellStyle, bg, "top")
};
var rules = type == "pdf" ? common : this._getExcelCellRules(cellStyle, node, common);
this._style_hash[type][name] = rules;
return rules;
}
},
_getExportDocStyle: function (css) {
css = exports.extend(css || {}, {
visibility: "hidden",
"white-space": "nowrap",
"text-align": "left"
});
var cssStr = "";
for (var i in css) {
cssStr += i + ":" + css[i] + ";";
}
var node = create("div", {
style: cssStr
});
this._body.appendChild(node);
var style = this._getExportCellStyle(node, cssStr);
remove(node);
return style;
},
_getExcelCellRules: function (cellStyle, node, common) {
var rules = {
font: {},
alignment: {},
border: {}
}; //font
rules.font.name = cellStyle["font-family"].replace(/,.*$/, ""); // cut off fallback font;
rules.font.sz = common.fontSize;
rules.font.color = {
rgb: common.color
};
if (cellStyle["font-weight"] !== "normal" && cellStyle["font-weight"] != 400) rules.font.bold = true;
if (cellStyle["text-decoration-line"] === "underline") rules.font.underline = true;
if (cellStyle["font-style"] === "italic") rules.font.italic = true;
if (cellStyle["text-decoration-line"] === "line-through") rules.font.strike = true; //alignment
rules.alignment.horizontal = common.textAlign;
rules.alignment.vertical = cellStyle["height"] == cellStyle["line-height"] ? "center" : "top";
if (cellStyle["white-space"] == "normal") rules.alignment.wrapText = true; //rotated header
if (node.firstChild && node.firstChild.className && node.firstChild.className.indexOf("webix_rotate") !== -1) rules.alignment.textRotation = 90; //background
rules.fill = {
fgColor: {
rgb: common.backgroundColor
}
}; //borders
if (common.borderRightColor) rules.border.right = {
style: "thin",
color: {
rgb: common.borderRightColor
}
};
if (common.borderBottomColor) rules.border.bottom = {
style: "thin",
color: {
rgb: common.borderBottomColor
}
};
if (common.borderLeftColor) rules.border.left = {
style: "thin",
color: {
rgb: common.borderLeftColor
}
};
if (common.borderTopColor) rules.border.top = {
style: "thin",
color: {
rgb: common.borderTopColor
}
};
return rules;
},
_getRules: function (node) {
var style = {};
if (window.getComputedStyle) style = window.getComputedStyle(node);else style = node.currentStyle;
return style;
}
};
var temp$5 = {};
var temp$6 = {};
var temp$7 = {};
var api$1h = {
name: "datatable",
defaults: {
leftSplit: 0,
rightSplit: 0,
topSplit: 0,
columnWidth: 100,
sort: true,
prerender: false,
autoheight: false,
autowidth: false,
header: true,
fixedRowHeight: true,
scrollAlignY: true,
scrollX: true,
scrollY: true,
datafetch: 50,
navigation: true
},
$skin: function () {
this.defaults.rowHeight = $active.rowHeight;
this.defaults.minRowHeight = $active.rowHeight - 6;
this.defaults.headerRowHeight = $active.barHeight - $active.borderWidth * 2;
this.defaults.minColumnWidth = $active.dataPadding * 2 + $active.borderWidth;
},
on_click: {
webix_excel_filter: function () {
return false;
},
webix_richfilter: function () {
return false;
},
webix_table_checkbox: function (e, id) {
id = this.locate(e);
var item = this.getItem(id.row);
var col = this.getColumnConfig(id.column);
var trg = e.target; //read actual value from HTML tag when possible
//as it can be affected by dbl-clicks
var check = trg.type == "checkbox" ? trg.checked : item[id.column] != col.checkValue;
var value = check ? col.checkValue : col.uncheckValue;
var update = {};
update[id.column] = value;
this.updateItem(id.row, update, this._settings.checkboxRefresh ? "update" : "save");
this.callEvent("onCheck", [id.row, id.column, value]);
return false;
},
webix_table_radio: function (e) {
var id = this.locate(e);
var item = this.getItem(id.row);
var col = this.getColumnConfig(id.column);
this.eachRow(function (rowid) {
var item = this.data.pull[rowid];
if (item && item[id.column] == col.checkValue) item[id.column] = col.uncheckValue;
});
item[id.column] = col.checkValue;
this.callEvent("onCheck", [id.row, id.column, true]);
this.refresh();
return false;
}
},
on_dblclick: {
webix_table_checkbox: function () {
return this.on_click.webix_table_checkbox.apply(this, arguments);
}
},
on_context: {},
$init: function (config) {
this.on_click = exports.extend({}, this.on_click);
var html = "<div class='webix_ss_header' section='header'><div class='webix_hs_left'></div><div class='webix_hs_center'></div><div class='webix_hs_right'></div></div><div class='webix_ss_body'><div class='webix_ss_left'><div class='webix_ss_center_scroll'></div></div>";
html += "<div class='webix_ss_center'><div class='webix_ss_center_scroll' role='rowgroup'></div></div>";
html += "<div class='webix_ss_right'><div class='webix_ss_center_scroll'></div></div></div>";
html += "<div class='webix_ss_hscroll' role='scrollbar' aria-orientation='horizontal'></div><div class='webix_ss_footer' section='footer'><div class='webix_hs_left'></div><div class='webix_hs_center'></div><div class='webix_hs_right'></div></div><div class='webix_ss_vscroll_header'></div><div class='webix_ss_vscroll' role='scrollbar' aria-orientation='vertical'></div><div class='webix_ss_vscroll_footer'></div>";
this._contentobj.innerHTML = html;
this._top_id = this._contentobj.id = this.name + uid();
this._contentobj.className += " webix_dtable";
this._dataobj = this._contentobj;
this._header = this._contentobj.firstChild;
this._body = this._header.nextSibling;
this._footer = this._body.nextSibling.nextSibling;
this._viewobj.setAttribute("role", "grid");
if (!config.editable) this._viewobj.setAttribute("aria-readonly", "true");
this.data.provideApi(this, true);
this.data.attachEvent("onParse", bind(this._call_onparse, this));
this.$ready.push(this._first_render);
this._columns = [];
this._headers = [];
this._footers = [];
this._rows_cache = [];
this._active_headers = {};
this._filter_elements = {};
this._sort_signs = {};
this._sort_signs_order = [];
this._header_height = this._footer_height = 0; //component can create new view
this._destroy_with_me = [];
this.data.attachEvent("onServerConfig", bind(this._config_table_from_file, this));
this.data.attachEvent("onServerOptions", bind(this._config_options_from_file, this));
this.attachEvent("onViewShow", function () {
this._restore_scroll_state();
this._refresh_any_header_content();
});
this.data.attachEvent("onClearAll", bind(function (soft) {
if (!soft) {
this._scrollLeft = this._scrollTop = 0;
if (this._x_scroll) this._x_scroll.reset();
if (this._y_scroll) this._y_scroll.reset();
this._setLeftScroll(0);
}
}, this));
this.attachEvent("onDestruct", this._clean_config_struct);
this.attachEvent("onKeyPress", this._onKeyPress);
this.attachEvent("onScrollY", this._adjust_rows);
callEvent("onDataTable", [this, config]);
},
_render_initial: function () {
this._scrollSizeX = this._scrollSizeY = env.scrollSize;
var hheight = this._settings.headerRowHeight + 1;
addStyle("#" + this._top_id + " .webix_cell { height:" + this._settings.rowHeight + "px; line-height:" + (this._settings.rowLineHeight || this._settings.rowHeight) + "px;" + (this._settings.fixedRowHeight ? "" : "white-space:normal;") + " }");
addStyle("#" + this._top_id + " .webix_hcell { height:" + hheight + "px; line-height:" + hheight + "px;}");
this._render_initial = function () {};
},
_first_render: function () {
this.data.attachEvent("onStoreLoad", bind(this._refresh_any_header_content, this));
this.data.attachEvent("onSyncApply", bind(this._refresh_any_header_content, this));
this.data.attachEvent("onStoreUpdated", bind(function () {
return this.render.apply(this, arguments);
}, this));
this.data.attachEvent("onStoreUpdated", bind(this._refresh_tracking_header_content, this));
this.render();
},
refresh: function () {
this.render();
},
_delayRender: function () {
var _this = this;
clearTimeout(this._renderDelay);
this._renderDelay = delay(function () {
_this._renderDelay = 0;
if (!isUndefined(_this._delayedLeftScroll)) {
_this._setLeftScroll(_this._delayedLeftScroll);
delete _this._delayedLeftScroll;
}
_this.render();
});
},
render: function (id, data, mode) {
//pure data saving call
if (mode == "save" || this._renderDelay) return;
if (!this._columns.length) {
var cols = this._settings.columns;
if (!cols || !cols.length) {
if (this._settings.autoConfig && this.data.order.length && !this._hidden_column_order.length) {
this._dtable_fully_ready = 0;
this._autoDetectConfig();
} else return;
}
this._define_structure();
}
if (!this.isVisible(this._settings.id) || this.$blockRender) return this._render_initial(); //Chrome 34, Custom Font loading bug
var fast_mode = this.config.experimental && !this._settings.subview; //replace multiple atomic updates by single big repaint
if (id && data != -1 && (mode == "paint" || mode == "update") && !fast_mode) {
if (this._render_timer) clearTimeout(this._render_timer);
if (!this._render_timer || this._render_timer_id == id) {
this._render_timer_id = id;
this._render_timer = delay(function () {
//if only one call - repaint single item
this.render(id, -1, mode);
}, this);
} else {
this._render_timer_id = null;
this._render_timer = delay(function () {
//if ther was a serie of calls - replace them with single full repaint
this.render();
}, this);
}
return;
} else if (this._render_timer) {
clearTimeout(this._render_timer);
this._render_timer = 0;
}
if (this.callEvent("onBeforeRender", [this.data])) {
this._render_initial();
if (!this._dtable_fully_ready) this._apply_headers();
if (this._content_width) {
if (fast_mode && (mode == "paint" || mode == "update") && id) this._repaint_single_row(id);else this._check_rendered_cols(true, true);
}
if (!id || mode != "update") {
this._dtable_height = this._get_total_height();
this._set_split_sizes_y();
} //don't depend on hidden rows/rolumns
this._viewobj.setAttribute("aria-colcount", Math.max(this._hidden_column_order.length, this._columns.length));
this._viewobj.setAttribute("aria-rowcount", this.data.count());
this.callEvent("onAfterRender", [this.data]);
return true;
}
},
getColumns: function (all) {
var horder = this._hidden_column_order;
if (all && horder.length) {
var columns = [];
for (var i = 0; i < horder.length; i++) {
columns.push(this.getColumnConfig(horder[i]));
}
return columns;
} else return _toConsumableArray(this._columns);
},
getColumnConfig: function (id) {
return this._columns_pull[id] || this._hidden_column_hash[id];
},
_config_options_from_file: function (colls) {
for (var key in colls) {
var column = this.getColumnConfig(key);
assert(column, "Orphan collection: " + key);
var temp = new DataCollection({
data: colls[key]
});
this._destroy_with_me.push(temp);
this._bind_collection(temp, column);
}
},
//xml has different configuration structure, fixing
_config_table_from_file: function (config) {
this._create_scheme_init();
if (config.columns && this._dtable_fully_ready) this.refreshColumns(config.columns);
},
_define_structure: function () {
if (this._settings.columns) {
this._columns_pull = {};
this._columns = this._settings.columns;
this._rightSplit = this._columns.length - (this.config.rightSplit || 0);
for (var i = 0; i < this._columns.length; i++) {
this._prepare_single_column(this._columns[i]);
}
this._normalize_headers("header", this._headers);
this._normalize_headers("footer", this._footers);
this.callEvent("onStructureLoad", []);
}
},
_prepare_single_column: function (col) {
this._columns_pull[col.id] = col;
if (isUndefined(col.header)) col.header = col.id;
var format = col.cssFormat;
if (format) col.cssFormat = toFunctor(format, this.$scope);
col.width = this._correctColumnWidth(col.width || this._settings.columnWidth, col);
if (typeof col.format == "string") col.format = i18n[col.format] || window[col.format];
if (col.numberFormat) {
var nformat = col.numberFormat;
if (typeof nformat === "string") col.numberFormat = nformat = Number$1.getConfig(nformat);
col.format = Number$1.numToStr(nformat);
col.editFormat = col.editFormat || function (val) {
return Number$1.format(val, nformat);
};
col.editParse = col.editParse || function (val) {
return Number$1.parse(val, nformat);
};
} //default settings for checkboxes and radios
if (isUndefined(col.checkValue)) col.checkValue = 1;
if (isUndefined(col.uncheckValue)) col.uncheckValue = 0;
if (col.css && _typeof(col.css) == "object") col.css = createCss(col.css);
var rawTemplate = col.template;
if (rawTemplate) {
if (typeof rawTemplate == "string") rawTemplate = rawTemplate.replace(/#\$value#/g, "#" + col.id + "#");
col.template = template(rawTemplate);
}
},
_define_structure_and_render: function () {
this._apply_headers();
},
_clean_config_struct: function () {
//remove column technical info from the column
//it allows to reuse the same config object for new grid
for (var i = 0; i < this._columns.length; i++) {
delete this._columns[i].attached;
delete this._columns[i].node;
}
},
_apply_headers: function () {
this._rightSplit = this._columns.length - (this.config.rightSplit || 0);
this._dtable_width = 0;
for (var i = 0; i < this._columns.length; i++) {
if (!this._columns[i].node) {
var temp = create("DIV");
temp.style.width = this._columns[i].width + "px";
this._columns[i].node = temp;
}
if (i >= this._settings.leftSplit && i < this._rightSplit) this._dtable_width += this._columns[i].width;
}
var marks = [];
if (this._settings.rightSplit) {
var nr = this._columns.length - this._settings.rightSplit;
marks[nr] = " webix_first";
marks[nr - 1] = " webix_last";
}
if (this._settings.leftSplit) {
var nl = this._settings.leftSplit;
marks[nl] = " webix_first";
marks[nl - 1] = " webix_last";
}
marks[0] = (marks[0] || "") + " webix_first webix_select_mark";
var last_index = this._columns.length - 1;
marks[last_index] = (marks[last_index] || "") + " webix_last";
for (var _i = 0; _i < this._columns.length; _i++) {
var node = this._columns[_i].node;
node.setAttribute(
/*@attr*/
"column", _i);
node.className = "webix_column " + (this._columns[_i].css || "") + (marks[_i] || "");
}
this._create_scrolls();
this._set_columns_positions();
this._set_split_sizes_x();
this._render_header_and_footer();
this._dtable_fully_ready = true;
},
_set_columns_positions: function () {
var left = 0;
for (var i = 0; i < this._columns.length; i++) {
var column = this._columns[i];
if (i == this._settings.leftSplit || i == this._rightSplit) left = 0;
if (column.node) {
column.node.style.left = left + "px";
if (this._settings.leftSplit || this._settings.rightSplit) {
remove(column.node);
column.attached = false;
}
}
left += column.width;
}
},
_render_header_and_footer: function () {
if (!this._header_fix_width) this._header_fix_width = 0;
this._header_height = this._footer_height = 0;
if (this._settings.header) {
this._refreshHeaderContent(this._header, 0, 1);
this._normalize_headers("header", this._headers);
this._header_height = this._headers._summ;
this._render_header_section(this._header, "header", this._headers);
}
if (this._settings.footer) {
this._refreshHeaderContent(this._footer, 0, 1);
this._normalize_headers("footer", this._footers);
this._footer_height = this._footers._summ;
this._render_header_section(this._footer, "footer", this._footers);
}
this.refreshHeaderContent(false, false);
this._size_header_footer_fix();
for (var i = 0; i < this._sort_signs_order.length; i++) {
var col_id = this._sort_signs_order[i];
this._render_single_mark(col_id, this._sort_signs[col_id]);
}
},
_getHeaderHeight: function (header, column, ind) {
var width = 0;
var colspan = header.colspan || 1;
var css = "webix_hcell " + (header.css || "");
if (header.rotate) css += " webix_measure_rotate";else for (var i = 0; i < colspan; i++) {
width += this._columns[ind + i] ? this._columns[ind + i].width : this.config.columnWidth;
}
var size = getTextSize([header.text], css, width); //+1 to compensate for scrollHeight rounding
return (header.rotate ? size.width : size.height) + 1;
},
_normalize_headers: function (collection, heights) {
var rows = 0; // clear array of previous values
heights.length = 0;
for (var i = 0; i < this._columns.length; i++) {
var data = this._columns[i][collection] || "";
if (!isArray(data)) data = [data];
for (var j = 0; j < data.length; j++) {
if (_typeof(data[j]) != "object") data[j] = {
text: data[j]
};
if (data[j] && data[j].height) heights[j] = Math.max(heights[j] || 0, data[j].height);
if (data[j] && data[j].autoheight) heights[j] = Math.max(heights[j] || 0, this._getHeaderHeight(data[j], this._columns[i], i));
if (data[j] && data[j].css && _typeof(data[j].css) === "object") data[j].css = createCss(data[j].css);
}
rows = Math.max(rows, data.length);
this._columns[i][collection] = data;
}
heights._summ = rows;
for (var _i2 = rows - 1; _i2 >= 0; _i2--) {
heights[_i2] = heights[_i2] || this._settings.headerRowHeight;
heights._summ += heights[_i2] * 1;
} //set null to cells included in col|row spans
for (var _i3 = 0; _i3 < this._columns.length; _i3++) {
var col = this._columns[_i3][collection];
for (var _j = 0; _j < col.length; _j++) {
if (col[_j] && col[_j].rowspan) for (var z = 1; z < col[_j].rowspan; z++) {
col[_j + z] = null;
}
if (col[_j] && col[_j].colspan) for (var _z = 1; _z < col[_j].colspan; _z++) {
this._columns[_i3 + _z][collection][_j] = null;
}
}
} //auto-rowspan cells, which has not enough header lines
for (var _i4 = 0; _i4 < this._columns.length; _i4++) {
var _data = this._columns[_i4][collection];
if (_data.length < rows) {
var end = _data.length - 1;
_data[end].rowspan = rows - _data.length + 1;
for (var _j2 = end + 1; _j2 < rows; _j2++) {
_data[_j2] = null;
}
}
}
return rows;
},
_find_header_content: function (sec, id) {
var attr =
/*@attr*/
"active_id";
return sec.querySelector("DIV[".concat(attr, "=\"").concat(id, "\"]"));
},
getHeaderContent: function (id) {
var obj = this._find_header_content(this._header, id);
if (!obj) obj = this._find_header_content(this._footer, id);
if (obj) {
var config = this._active_headers[id];
var type$$1 = datafilter[config.content];
var _base = {
type: type$$1,
getValue: function (text) {
return type$$1.getValue(obj, text);
},
setValue: function (value) {
return type$$1.setValue(obj, value);
}
};
if (type$$1.getHelper) exports.extend(_base, type$$1.getHelper(obj, config));
return _base;
}
},
_render_empty_hcell: function (height, css) {
return "<div class='".concat(css, "' style='height:").concat(height, "px;'></div>");
},
_render_subheader: function (start, end, width, name, heights) {
if (start == end) return "";
var spans = "";
var html = "<div style=\"background:inherit;width:".concat(width, "px;\">");
var count = this._columns[0][name].length;
var left = 0;
for (var i = start; i < end; i++) {
var top = 0;
var _width = this._columns[i].width;
var abs = i == start ? "position:static;" : "position:absolute;top:".concat(top, "px;left:").concat(left, "px;");
html += "<div class=\"webix_hcolumn\" style=\"".concat(abs, "width:").concat(_width, "px;overflow:hidden;\">");
for (var j = 0; j < count; j++) {
var header = this._columns[i][name][j];
var cell_height = heights[j];
var hcss = "webix_hcell";
if (this._columns[i].$selected) hcss += " webix_sel_hcell";
if (i == start) hcss += " webix_first";
if (i == end - 1) hcss += " webix_last";
if (j == count - 1) hcss += " webix_last_row";
if (!header) {
html += this._render_empty_hcell(cell_height + 1, hcss);
top += cell_height + 1;
continue;
}
if (header.content) {
header.contentId = header.contentId || uid();
header.columnId = this._columns[i].id;
header.format = this._columns[i].format;
assert(datafilter, "Filtering extension was not included");
assert(datafilter[header.content], "Unknown content type: " + header.content);
header.text = datafilter[header.content].render(this, header);
this._active_headers[header.contentId] = header;
this._has_active_headers = true;
}
if (header.css) // apply unique css after content initialization
hcss += " " + header.css;
var cell = "<div " +
/*@attr*/
"row" + "='" + j + "'" +
/*@attr*/
"column" + "='" + (header.colspan ? header.colspan - 1 + i : i) + "'";
var sheight = "";
if (header.contentId) cell += " " +
/*@attr*/
"active_id" + "='" + header.contentId + "'";
var isSpan = false;
var cheight = cell_height;
if (header.colspan && header.colspan > 1 || header.rowspan && header.rowspan > 1) {
var cwidth = this._summ_right(this._columns, i, header.colspan) || _width;
cheight = this._summ_next(heights, j, header.rowspan);
if (cheight <= 0) cheight = cell_height;
html += this._render_empty_hcell(cell_height + 1, hcss);
if (header.colspan && i + header.colspan >= end) hcss += " webix_last";
if (header.rowspan && j + header.rowspan >= count) hcss += " webix_last_row";
hcss += " webix_span";
isSpan = true;
sheight = " colspan='".concat(header.colspan || 1, "' rowspan='").concat(header.rowspan || 1, "' style='position:absolute;top:").concat(top, "px;left:").concat(left, "px;line-height:").concat(cheight + 1, "px;width:").concat(cwidth, "px;height:").concat(cheight + 1, "px;'");
} else if (cell_height != this._settings.headerRowHeight) sheight = " style='line-height:".concat(cell_height + 1, "px;height:").concat(cell_height + 1, "px;'");
cell += " class=\"" + hcss + "\"";
cell += " " + sheight + ">";
var text = header.text === "" ? " " : header.text;
if (header.rotate) text = "<div class='webix_rotate' style='width:" + (cheight - 10) + "px;transform-origin:center " + (cheight - 15) / 2 + "px;-webkit-transform-origin:center " + (cheight - 15) / 2 + "px;'>" + text + "</div>";
cell += text + "</div>";
if (isSpan) spans += cell;else html += cell;
top += cell_height + 1;
}
left += _width;
html += "</div>";
}
return html + spans + "</div>";
},
_summ_next: function (heights, start, i) {
var summ = -1;
i += start;
for (start; start < i; start++) {
summ += heights[start] + 1;
}
return summ;
},
_summ_right: function (columns, start, i) {
var summ = 0;
i += start;
for (start; start < i; start++) {
summ += columns[start].width;
}
return summ;
},
showItemByIndex: function (row_ind, column_ind) {
var pager = this._settings.pager;
if (pager && row_ind >= this._settings.topSplit) {
var target = Math.floor(row_ind / pager.size);
if (target != pager.page) $$(pager.id).select(target);
} //parameter will be set to -1, to mark that scroll need not to be adjusted
var scroll = this.getScrollState();
if (row_ind >= this._settings.topSplit || this._settings.prerender && row_ind != -1) {
var state = this._get_y_range();
if (row_ind < state[0] + 1 || row_ind >= state[1] - 1) {
//not visible currently
var summ = this._getHeightByIndexSumm(pager ? this.data.$min : 0, row_ind);
var dataHeight = this._dtable_offset_height + 1;
var itemHeight = this._getHeightByIndex(row_ind);
if (row_ind < state[0] + 1) {
//scroll top - show row at top of screen
summ = Math.max(0, summ) - this._get_top_split_height();
} else if (summ + itemHeight > dataHeight) {
//scroll bottom - show row at bottom of screen
summ += itemHeight - dataHeight; //because of row rounding we need to scroll some extra
for (var cur_ind = row_ind; cur_ind > 0 && dataHeight > 0; cur_ind--) {
dataHeight -= this._getHeightByIndex(cur_ind);
}
if (row_ind > 0 && dataHeight) summ += this._getHeightByIndex(row_ind + 1);
} else {
summ = scroll.y;
}
scroll.y = summ;
}
}
if (column_ind != -1) {
//ignore split columns - they are always visible
if (column_ind < this._settings.leftSplit || column_ind >= this._rightSplit) return this.scrollTo(scroll.x, scroll.y); //very similar to y-logic above
var _state = this._get_x_range();
if (column_ind < _state[0] + 1 || column_ind >= _state[1] - 1) {
//not visible currently
var _summ = 0;
for (var i = this._settings.leftSplit; i < column_ind; i++) {
_summ += this._columns[i].width;
}
var itemWidth = this._columns[column_ind].width;
/*jsl:ignore*/
if (column_ind < _state[0] + 1) ; else if (_summ + itemWidth > this._center_width) {
//scroll to right border
_summ += itemWidth - this._center_width;
} else {
_summ = scroll.x;
}
/*jsl:end*/
scroll.x = _summ;
}
}
this.scrollTo(scroll.x, scroll.y);
},
showCell: function (row, column) {
if (!column || !row) {
//if column or row not provided - take from current selection
var t = this.getSelectedId(true);
if (t.length == 1) {
column = column || t[0].column;
row = row || t[0].row;
}
} //convert id to index
column = column ? this.getColumnIndex(column) : -1;
row = row ? this.getIndexById(row) : -1;
this.showItemByIndex(row, column);
},
scrollTo: function (x, y) {
if (!this._x_scroll) return;
if (this._scrollTo_touch) return this._scrollTo_touch(x, y);
if (x !== null) this._x_scroll.scrollTo(x);
if (y !== null) this._y_scroll.scrollTo(y);
},
_touch_scroll: "touch",
getScrollState: function () {
if (this._getScrollState_touch) return this._getScrollState_touch();
var diff = this._render_scroll_shift ? 0 : this._render_scroll_diff || 0;
return {
x: this._scrollLeft || 0,
y: this._scrollTop + diff
};
},
showItem: function (id) {
this.showItemByIndex(this.getIndexById(id), -1);
},
_render_header_section: function (sec, name, heights) {
var header = sec.childNodes;
header[0].innerHTML = this._render_subheader(0, this._settings.leftSplit, this._left_width, name, heights);
header[1].innerHTML = this._render_subheader(this._settings.leftSplit, this._rightSplit, this._dtable_width, name, heights);
header[2].innerHTML = this._render_subheader(this._rightSplit, this._columns.length, this._right_width, name, heights);
if (this._dtable_column_refresh) header[1].scrollLeft = this.getScrollState().x;
header[1].onscroll = bind(this._scroll_with_header, this);
},
_scroll_with_header: function () {
var active = this.getScrollState().x;
var header = this._header.childNodes[1].scrollLeft; // on mobile devices scrollLeft can be a non-round value
if (Math.ceil(header) != Math.ceil(active)) this.scrollTo(header, null);
},
_refresh_tracking_header_content: function () {
this.refreshHeaderContent(true, true);
},
_refresh_any_header_content: function () {
this.refreshHeaderContent(false, true);
},
//[DEPRECATE] - v3.0, move to private
refreshHeaderContent: function (trackedOnly, preserve, id) {
if (this._settings.header) {
if (preserve) this._refreshHeaderContent(this._header, trackedOnly, 1, id);
this._refreshHeaderContent(this._header, trackedOnly, 0, id);
}
if (this._settings.footer) {
if (preserve) this._refreshHeaderContent(this._footer, trackedOnly, 1, id);
this._refreshHeaderContent(this._footer, trackedOnly, 0, id);
}
},
refreshFilter: function (id) {
this.refreshHeaderContent(false, true, id);
},
_refreshHeaderContent: function (sec, cellTrackOnly, getOnly, byId) {
if (this._has_active_headers && sec) {
var tag = "DIV";
var attr =
/*@attr*/
"active_id";
var cells = sec.querySelectorAll("".concat(tag, "[").concat(attr, "]"));
for (var i = 0; i < cells.length; i++) {
var activeId = cells[i].getAttribute(
/*@attr*/
"active_id");
if (activeId) {
var obj = this._active_headers[activeId];
if (byId && byId != obj.columnId) continue;
var content = datafilter[obj.content];
if (getOnly) {
if (content.getValue) {
obj.value = content.getValue(cells[i]);
}
} else if (!cellTrackOnly || content.trackCells) {
content.refresh(this, cells[i], obj);
}
}
}
}
},
headerContent: [],
_set_size_scroll_area: function (obj, height, hdx) {
if (this._scrollSizeY) {
obj.style.height = Math.max(height, 1) - 1 + "px";
obj.style.width = (this._rightSplit ? 0 : hdx) + this._scrollSizeY - 1 + "px"; // temp. fix: Chrome [DIRTY]
if (env.isWebKit) var w = obj.offsetWidth; //eslint-disable-line
} else obj.style.display = "none";
},
_size_header_footer_fix: function () {
if (this._settings.header) this._set_size_scroll_area(this._header_scroll, this._header_height, this._header_fix_width);
if (this._settings.footer) this._set_size_scroll_area(this._footer_scroll, this._footer_height, this._header_fix_width);
},
_update_scroll: function () {
var hasX = !(this._settings.autowidth || this._settings.scrollX === false);
this._scrollSizeX = hasX ? env.scrollSize : 0;
var hasY = !(this._settings.autoheight || this._settings.scrollY === false);
this._scrollSizeY = hasY ? env.scrollSize : 0;
if (env.touch) hasX = hasY = false;
if (this._x_scroll) {
this._x_scroll._settings.scrollSize = this._scrollSizeX;
this._x_scroll._settings.scrollVisible = hasX;
}
if (this._y_scroll) {
this._y_scroll._settings.scrollSize = this._scrollSizeY;
this._y_scroll._settings.scrollVisible = hasY;
}
},
_create_scrolls: function () {
this._scrollTop = 0;
this._scrollLeft = 0;
var scrx, scry;
scrx = scry = 1;
if (this._settings.autoheight || this._settings.scrollY === false) scry = this._scrollSizeY = 0;
if (this._settings.autowidth || this._settings.scrollX === false) scrx = this._scrollSizeX = 0;
if (env.touch) scrx = scry = 0;
if (!this._x_scroll) {
this._x_scroll = ui({
view: "vscroll",
container: this._footer.previousSibling,
scrollWidth: this._dtable_width,
scrollSize: this._scrollSizeX,
scrollVisible: scrx
}); //fix for scroll space on Mac
if (scrx && !this._scrollSizeX && !env.$customScroll) this._x_scroll._viewobj.style.position = "absolute";
this._x_scroll.attachEvent("onScroll", bind(this._onscroll_x, this));
}
if (!this._y_scroll) {
this._header_scroll = this._footer.nextSibling;
var vscroll_view = this._header_scroll.nextSibling;
this._footer_scroll = vscroll_view.nextSibling;
this._y_scroll = ui({
view: "vscroll",
container: vscroll_view,
scrollHeight: 100,
scroll: "y",
scrollSize: this._scrollSizeY,
scrollVisible: scry
});
this._y_scroll.activeArea(this._body);
this._x_scroll.activeArea(this._body, true);
this._y_scroll.attachEvent("onScroll", bind(this._onscroll_y, this));
}
if (this._content_width) this.callEvent("onResize", [this._content_width, this._content_height]);
if (env.$customScroll) temp$1.enable(this);
this._create_scrolls = function () {};
},
columnId: function (index$$1) {
return this._columns[index$$1] && this._columns[index$$1].id;
},
getColumnIndex: function (id) {
for (var i = 0; i < this._columns.length; i++) {
if (this._columns[i].id == id) return i;
}
return -1;
},
_getNodeBox: function (rid, cid) {
var xs = 0,
xe = 0,
ye = 0,
ys = 0;
var i;
var zone = 0;
for (i = 0; i < this._columns.length; i++) {
if (this._rightSplit == i || this._settings.leftSplit == i) {
xs = 0;
zone++;
}
if (this._columns[i].id == cid) break;
xs += this._columns[i].width;
}
xe += this._columns[i].width;
for (i = 0; i < this.data.order.length; i++) {
if (this.data.order[i] == rid) break;
ys += this._getHeightByIndex(i);
}
ye += this._getHeightByIndex(i);
return [xs, xe, ys - this._scrollTop, ye, this._body.childNodes[zone]];
},
_id_to_string: function () {
return this.row;
},
locate: function (node, idOnly) {
if (this != $$(node)) return null;
node = node.target || node;
while (node && node.getAttribute) {
if (node === this.$view) break;
var cs = _getClassName(node).toString();
var pos$$1 = null;
if (cs.indexOf("webix_cell") != -1) {
pos$$1 = this._locate(node);
if (pos$$1) pos$$1.row = this.data.order[pos$$1.rind];
}
if (cs.indexOf("webix_hcell") != -1) {
pos$$1 = this._locate(node);
if (pos$$1) pos$$1.header = true;
}
if (cs.indexOf("webix_drop_area") != -1) {
pos$$1 = this._locate(node);
if (pos$$1) pos$$1.row = pos$$1.rind = "$webix-drop";
}
if (pos$$1) {
if (idOnly) return pos$$1.header ? null : pos$$1.row;
pos$$1.column = this._columns[pos$$1.cind].id;
pos$$1.toString = this._id_to_string;
return pos$$1;
}
node = node.parentNode;
}
return null;
},
_locate: function (node) {
var cdiv = node.parentNode;
if (!cdiv) return null;
var column = (node.getAttribute(
/*@attr*/
"column") || cdiv.getAttribute(
/*@attr*/
"column")) * 1;
var rind = node.getAttribute("aria-rowindex");
var row = node.getAttribute(
/*@attr*/
"row") || (rind ? rind - 1 : 0);
var span = (node.getAttribute("colspan") || cdiv.getAttribute("colspan")) * 1;
return {
rind: row,
cind: column,
span: span
};
},
_correctScrollSize: function () {
var center = -this._center_width;
for (var i = 0; i < this._columns.length; i++) {
center += this._columns[i].width;
}
this._scrollLeft = Math.min(this._scrollLeft, Math.max(0, center));
},
_updateColsSizeSettings: function (silent) {
if (!this._dtable_fully_ready) return;
this._correctScrollSize();
this._set_columns_positions();
this._set_split_sizes_x();
this._render_header_and_footer();
this._set_split_sizes_y();
if (!silent) this._check_rendered_cols(false, false);
},
setColumnWidth: function (col, width, skip_update) {
return this._setColumnWidth(this.getColumnIndex(col), width, skip_update);
},
_setColumnWidth: function (col, width, skip_update, by_user) {
if (isNaN(width) || col < 0) return;
var column = this._columns[col];
width = this._correctColumnWidth(width, column);
var old = column.width;
if (old != width) {
if (col >= this._settings.leftSplit && col < this._rightSplit) this._dtable_width += width - old;
column.width = width;
if (column.node) //method can be called from onStructLoad
column.node.style.width = width + "px";else return false;
if (!skip_update) this._updateColsSizeSettings();
this.callEvent("onColumnResize", [column.id, width, old, !!by_user]);
return true;
}
return false;
},
_correctColumnWidth: function (width, config) {
width = Math.max(width, config.minWidth || this._settings.minColumnWidth || 0);
width = Math.min(width, config.maxWidth || this._settings.maxColumnWidth || 100000);
return width;
},
_getRowHeight: function (row) {
return (row.$height || this._settings.rowHeight) + (row.$subopen ? row.$subHeight : 0);
},
_getHeightByIndex: function (index$$1) {
var id = this.data.order[index$$1];
if (!id) return this._settings.rowHeight;
return this._getRowHeight(this.data.pull[id]);
},
_getHeightByIndexSumm: function (index1, index2) {
if (this._settings.fixedRowHeight) return Math.max(index2 - index1, 0) * this._settings.rowHeight;else {
var summ = 0;
for (; index1 < index2; index1++) {
summ += this._getHeightByIndex(index1);
}
return summ;
}
},
_cellPosition: function (row, column, edit) {
if (row.row) {
column = row.column;
row = row.row;
}
var width = this.getColumnConfig(column).width;
var height = this.getItem(row).$height || this._settings.rowHeight;
if (this.config.spans && edit) {
var span = this.getSpan(row, column);
if (span) {
var spanNode = this.getSpanNode({
row: span[0],
column: span[1]
});
width = spanNode.offsetWidth;
height = spanNode.offsetHeight;
}
}
var left = 0;
var parent = 0;
for (var _index = 0; _index < this._columns.length; _index++) {
if (_index == this._settings.leftSplit || _index == this._rightSplit) left = 0;
var leftcolumn = this._columns[_index];
if (leftcolumn.id == column) {
var split_column = _index < this._settings.leftSplit ? 0 : _index >= this._rightSplit ? 2 : 1;
parent = this._body.childNodes[split_column].firstChild;
break;
}
left += leftcolumn.width;
}
var index$$1 = this.getIndexById(row);
var top;
if (index$$1 < this._settings.topSplit) top = this._getHeightByIndexSumm(0, index$$1);else {
var first = this._render_scroll_top || 0;
top = this._getHeightByIndexSumm(first, index$$1) + (this._render_scroll_shift || 0) + (index$$1 >= first ? this._get_top_split_height() : 0);
}
return {
parent: parent,
top: top,
left: left,
width: width,
height: height
};
},
_get_top_split_height: function () {
return this._settings.topSplit ? this._getHeightByIndexSumm(0, this._settings.topSplit) : 0;
},
_get_total_height: function () {
var pager = this._settings.pager;
var start = 0;
var max = this.data.order.length;
if (pager) {
start = pager.size * pager.page;
max = Math.min(max, start + pager.size);
if (pager.level) {
start = this.data.$min;
max = this.data.$max;
}
}
return this._getHeightByIndexSumm(start, max);
},
setRowHeight: function (rowId, height) {
if (isNaN(height)) return;
height = Math.max(height, this._settings.minRowHeight || 0);
height = Math.min(height, this._settings.maxRowHeight || 100000);
var item = this.getItem(rowId);
var old_height = item.$height || this._settings.rowHeight;
if (old_height != height) {
item.$height = height;
this.config.fixedRowHeight = false;
this.render();
this.callEvent("onRowResize", [rowId, height, old_height]);
}
},
_onscroll_y: function (value) {
var scrollChange = this._scrollTop !== value;
this._scrollTop = value;
if (!this._settings.prerender) {
this._check_rendered_cols();
} else {
var conts = this._body.childNodes;
for (var i = 0; i < conts.length; i++) {
conts[i].scrollTop = value;
}
}
if (env.$customScroll) temp$1._update_scroll(this._body);
if (scrollChange) {
this.callEvent("onScrollY", []);
this.callEvent("onAfterScroll", []);
}
},
_setLeftScroll: function (value) {
this._body.childNodes[1].scrollLeft = this._scrollLeft = value;
if (this._settings.header) this._header.childNodes[1].scrollLeft = value;
if (this._settings.footer) this._footer.childNodes[1].scrollLeft = value;
},
_onscroll_x: function (value) {
var scrollChange = this._scrollLeft !== value;
if (this._renderDelay) this._delayedLeftScroll = value;else this._setLeftScroll(value);
if (this._settings.prerender === false) this._check_rendered_cols(this._minimize_dom_changes ? false : true);
if (env.$customScroll) temp$1._update_scroll(this._body);
if (scrollChange) {
this.callEvent("onScrollX", []);
this.callEvent("onAfterScroll", []);
}
},
_get_x_range: function (full) {
if (full) return [0, this._columns.length];
var t = this._scrollLeft;
var xind = this._settings.leftSplit;
while (t > 0 && this._columns.length - 1 > xind) {
t -= this._columns[xind].width;
xind++;
}
var xend = xind;
if (t && xind > 0) xind--;
t += this._center_width;
while (t > 0 && xend < this._rightSplit) {
t -= this._columns[xend].width;
xend++;
}
return [xind, xend];
},
getVisibleCount: function () {
return Math.floor(this._dtable_offset_height / this.config.rowHeight);
},
//returns info about y-scroll position
_get_y_range: function (full) {
var t = this._scrollTop;
var start = 0;
var end = this.count(); //apply pager, if defined
var pager = this._settings.pager;
if (pager) {
start = pager.page * pager.size;
end = Math.min(end, start + pager.size);
if (pager.level) {
start = this.data.$min;
end = this.data.$max;
}
}
var xind = start + this._settings.topSplit; //in case of autoheight - request full rendering
if (full || this._settings.autoheight) return [xind, end, 0];
var rowHeight = this._settings.fixedRowHeight ? this._settings.rowHeight : 0;
if (rowHeight) {
var dep = Math.ceil(t / rowHeight);
t -= dep * rowHeight;
xind += dep;
} else while (t > 0) {
t -= this._getHeightByIndex(xind);
xind++;
} //how much of the first cell is scrolled out
var xdef = xind > 0 && t ? -(this._getHeightByIndex(xind - 1) + t) : 0;
var xend = xind;
if (t) xind--;
t += (this._dtable_offset_height || this._content_height) - this._get_top_split_height();
if (rowHeight) {
var _dep = Math.ceil(t / rowHeight);
t -= _dep * rowHeight;
xend += _dep;
} else {
while (t > 0 && xend < end) {
t -= this._getHeightByIndex(xend);
xend++;
}
}
if (xend > end) xend = end;
return [xind, xend, xdef];
},
_repaint_single_row: function (id) {
var item = this.getItem(id);
var rowindex = this.getIndexById(id);
var state = this._get_y_range();
var freeze = this._settings.topSplit;
var freezeCss = "";
if (rowindex >= freeze) {
//row not visible
if (rowindex < state[0] || rowindex >= state[1]) return;
rowindex -= state[0] - freeze;
} else {
freezeCss = rowindex == freeze - 1 ? " webix_topcell webix_last_topcell" : " webix_topcell";
} //get visible column
var x_range = this._get_x_range();
for (var i = 0; i < this._columns.length; i++) {
var column = this._columns[i]; //column not visible
if (i < this._rightSplit && i >= this._settings.leftSplit && (i < x_range[0] || i > x_range[1])) column._yr0 = -999; //ensure that column will not be reused
if (column.attached && column.node) {
var node = column.node.childNodes[rowindex];
if (!node) continue;
var value = this._getValue(item, this._columns[i], 0);
node.innerHTML = value;
node.className = this._getCss(this._columns[i], value, item, id) + freezeCss;
}
}
},
_check_rendered_cols: function (x_scroll, force) {
if (!this._columns.length || this._renderDelay) return;
if (force) this._clearColumnCache();
var xr = this._get_x_range(this._settings.prerender);
var yr = this._get_y_range(this._settings.prerender === true);
if (x_scroll) {
for (var i = this._settings.leftSplit; i < xr[0]; i++) {
this._hideColumn(i, force);
}
for (var _i5 = xr[1]; _i5 < this._rightSplit; _i5++) {
this._hideColumn(_i5, force);
}
}
this._render_full_rows = [];
for (var _i6 = 0; _i6 < this._settings.leftSplit; _i6++) {
this._renderColumn(_i6, yr, force);
}
for (var _i7 = xr[0]; _i7 < xr[1]; _i7++) {
this._renderColumn(_i7, yr, force, _i7 == xr[0]);
}
for (var _i8 = this._rightSplit; _i8 < this._columns.length; _i8++) {
this._renderColumn(_i8, yr, force);
}
this._check_and_render_full_rows(yr[0], yr[1], force);
this._check_load_next(yr);
},
_delete_full_rows: function (start, end) {
this._rows_cache_start = start;
this._rows_cache_end = end;
remove(this._rows_cache);
this._rows_cache = [];
},
_adjust_rows: function () {
if (this._settings.prerender && this._rows_body) {
var state = this.getScrollState();
this._rows_body.style.top = "-" + (state.y || 0) + "px";
}
},
_check_and_render_full_rows: function (start, end, force) {
if (this._rows_body) this._rows_body.style.top = this._render_scroll_shift + "px";
if (!force && start == this._rows_cache_start && end == this._rows_cache_end) {
if (this.config.topSplit) {
//don't move split rows
for (var i = 0; i < this._render_full_rows.length; i++) {
var row = this._rows_cache[i];
if (this._render_full_rows[i].index < this.config.topSplit) {
row.style.top = this._render_full_rows[i].top - this._render_scroll_shift + "px";
}
}
}
return;
}
this._delete_full_rows(start, end);
if (this._render_full_row_some) this._render_full_row_some = false;else return;
for (var _i9 = 0; _i9 < this._render_full_rows.length; _i9++) {
var info = this._render_full_rows[_i9];
var item = this.getItem(info.id);
var value;
if (typeof item.$row == "function") {
value = item.$row.call(this, item, this.type);
} else {
value = this._getValue(item, this.getColumnConfig(item.$row), _i9);
}
var _row = this._rows_cache[_i9] = create("DIV", null, value);
_row.className = "webix_cell " + (item.$sub ? "webix_dtable_sub" + (this._settings.subview ? "view" : "row") : "webix_dtable_colrow" + (item.$row ? " webix_topcell" + (this.data.getMark(item.id, "webix_selected") ? " webix_selected" : "") : ""));
_row.setAttribute(
/*@attr*/
"column", 0);
_row.setAttribute(
/*@attr*/
"row", info.index);
var height = item.$height || this._settings.rowHeight;
if (item.$subopen) _row.style.height = item.$subHeight + "px";else _row.style.height = height + "px";
_row.style.paddingRight = env.scrollSize + "px";
var topDelta = this._render_full_rows[_i9].index < this.config.topSplit ? -this._render_scroll_shift : 0;
_row.style.top = topDelta + info.top + (item.$subopen ? height - 1 : 0) + "px";
if (!this._rows_body) {
this._rows_body = create("DIV");
this._rows_body.style.position = "relative";
this._rows_body.style.top = this._render_scroll_shift + "px";
this._body.appendChild(this._rows_body);
}
this._rows_body.appendChild(_row);
this.attachEvent("onSyncScroll", function (x, y, t) {
Touch._set_matrix(this._rows_body, 0, y, t);
});
if (this._settings.subview) this.callEvent("onSubViewRender", [item, _row]);
}
},
_check_load_next: function (yr) {
var paging = this._settings.pager;
var fetch = this._settings.datafetch;
var direction = !this._last_valid_render_pos || yr[0] >= this._last_valid_render_pos;
this._last_valid_render_pos = yr[0];
if (this._data_request_flag) {
if (paging && (!fetch || fetch >= paging.size)) if (this._check_rows([0, paging.size * paging.page], Math.max(fetch, paging.size), true)) return this._data_request_flag = null;
this._run_load_next(this._data_request_flag, direction);
this._data_request_flag = null;
} else {
if (this._settings.loadahead) this._check_rows(yr, this._settings.loadahead, direction);
}
},
_check_rows: function (view, count, dir) {
var start = view[1];
var end = start + count;
if (!dir) {
start = view[0] - count;
end = view[0];
}
if (start < 0) start = 0;
end = Math.min(end, this.data.order.length - 1);
var result = false;
for (var i = start; i < end; i++) {
if (!this.data.order[i]) {
if (!result) result = {
start: i,
count: end - start
};else {
result.last = i;
result.count = i - start;
}
}
}
if (result) {
this._run_load_next(result, dir);
return true;
}
},
_run_load_next: function (conf, direction) {
var count = Math.max(conf.count, this._settings.datafetch || this._settings.loadahead || 0);
var start = direction ? conf.start : conf.last - count + 1;
if (this._maybe_loading_already(conf.count, conf.start)) return;
this.loadNext(count, start);
},
// necessary for safari only
_preserveScrollTarget: function (columnNode) {
if (env.isSafari) {
var i,
node,
newNode,
scroll,
dir = [this._x_scroll, this._y_scroll];
for (i = 0; i < 2; i++) {
scroll = dir[i];
if (scroll && scroll._scroll_trg && scroll._scroll_trg.parentNode == columnNode) {
node = scroll._scroll_trg;
}
}
if (node) {
if (this._scrollWheelTrg) remove(this._scrollWheelTrg);
this._scrollWheelTrg = node;
newNode = node.cloneNode(true); // required for _hideColumn
node.parentNode.insertBefore(newNode, node);
this._scrollWheelTrg.style.display = "none";
this._body.appendChild(this._scrollWheelTrg);
}
}
},
_hideColumn: function (index$$1) {
var col = this._columns[index$$1]; // preserve target node for Safari wheel event
this._preserveScrollTarget(col.node);
remove(col.node);
col.attached = false;
},
_clearColumnCache: function () {
for (var i = 0; i < this._columns.length; i++) {
this._columns[i]._yr0 = -1;
}
if (this._rows_cache.length) {
remove(this._rows_cache);
this._rows_cache = [];
}
},
getText: function (row_id, column_id) {
return this._getValue(this.getItem(row_id), this.getColumnConfig(column_id), 0);
},
getCss: function (row_id, column_id) {
var item = this.getItem(row_id);
return this._getCss(this.getColumnConfig(column_id), item[column_id], item, row_id);
},
_getCss: function (config, value, item, id) {
var css = "webix_cell";
if (config.cssFormat) {
var per_css = config.cssFormat(value, item, id, config.id);
if (per_css) {
if (_typeof(per_css) == "object") css += " " + createCss(per_css);else css += " " + per_css;
}
}
var row_css = item.$css;
if (row_css) {
if (_typeof(row_css) == "object") item.$css = row_css = createCss(row_css);
css += " " + row_css;
}
var mark = this.data._marks[id];
if (mark) {
if (mark.$css) css += " " + mark.$css;
if (mark.$cellCss) {
var mark_marker = mark.$cellCss[config.id];
if (mark_marker) css += " " + mark_marker;
}
}
if (item.$cellCss) {
var css_marker = item.$cellCss[config.id];
if (css_marker) {
if (_typeof(css_marker) == "object") css_marker = createCss(css_marker);
css += " " + css_marker;
}
} //cell-selection
var selected = this.data.getMark(item.id, "webix_selected");
if (selected && (selected.$row || selected[config.id]) || config.$selected) css += this._select_css;
return css;
},
_getValue: function (item, config, i) {
if (!item) return "";
var value;
value = item[config.id];
if (value === undefined || value === null) value = "";
if (config.format) value = config.format(value);
if (config.template) value = config.template(item, this.type, value, config, i);
return value;
},
//we don't use render-stack, but still need a place for common helpers
//so creating a simple "type" holder
type: {
checkbox: function (obj, common, value, config) {
var checked = value == config.checkValue ? "checked=\"true\"" : "";
return "<input class='webix_table_checkbox' type='checkbox' " + checked + ">";
},
radio: function (obj, common, value, config) {
var checked = value == config.checkValue ? "checked=\"true\"" : "";
return "<input class='webix_table_radio' type='radio' " + checked + ">";
},
editIcon: function () {
return "<span class='webix_icon wxi-pencil'></span>";
},
trashIcon: function () {
return "<span class='webix_icon wxi-trash'></span>";
}
},
type_setter: function (value) {
if (!this.types || !this.types[value]) type(this, value);else {
this.type = clone(this.types[value]);
if (this.type.css) this._contentobj.className += " " + this.type.css;
}
if (this.type.on_click) exports.extend(this.on_click, this.type.on_click);
return value;
},
_renderColumn: function (index$$1, yr, force, single$$1) {
var col = this._columns[index$$1];
if (!col.attached) {
var split_column = index$$1 < this._settings.leftSplit ? 0 : index$$1 >= this._rightSplit ? 2 : 1;
this._body.childNodes[split_column].firstChild.appendChild(col.node);
col.attached = true;
col.split = split_column;
}
this._render_scroll_top = yr[0];
this._render_scroll_shift = 0;
this._render_scroll_diff = yr[2]; //if columns not aligned during scroll - set correct scroll top value for each column
if (this._settings.scrollAlignY) {
if (yr[1] == this.data.order.length || this.data.$pagesize && yr[1] % this.data.$pagesize === 0) {
col.node.style.top = (this._render_scroll_shift = yr[2]) + "px";
} else if (col._yr2) col.node.style.top = "0px";
} else {
this._render_scroll_shift = yr[2];
col.node.style.top = yr[2] + "px";
}
if (!force && col._yr0 == yr[0] && col._yr1 == yr[1] && (!this._settings.topSplit || col._render_scroll_shift == this._render_scroll_shift)) return 0;
var html = "";
var config = this._settings.columns[index$$1];
var state = {
row: this._settings.rowHeight,
total: 0,
single: single$$1
};
for (var i = 0; i < this._settings.topSplit; i++) {
html += this._render_single_cell(i, config, yr, state, -this._render_scroll_shift, index$$1);
} // ignore not available rows in top-split area
this._data_request_flag = null;
for (var _i10 = Math.max(yr[0], this._settings.topSplit); _i10 < yr[1]; _i10++) {
html += this._render_single_cell(_i10, config, yr, state, -1, index$$1);
} // preserve target node for Safari wheel event
this._preserveScrollTarget(col.node);
col.node.innerHTML = html;
col._yr0 = yr[0];
col._yr1 = yr[1];
col._yr2 = yr[2];
col._render_scroll_shift = this._render_scroll_shift;
return 1;
},
_render_single_cell: function (i, config, yr, state, top, index$$1) {
var id = this.data.order[i];
var item = this.data.getItem(id);
var html = "";
if (item) {
var aria = " role='gridcell' aria-rowindex='" + (i + 1) + "' aria-colindex='" + (this.getColumnIndex(config.id) + 1) + "'" + (item.$count || item.$sub ? " aria-expanded='" + (item.open || item.$subopen ? "true" : "false") + "'" : "") + (item.$level ? " aria-level='" + item.$level + "'" : "");
if (state.single && item.$row) {
this._render_full_row_some = true;
this._render_full_rows.push({
top: state.total,
id: item.id,
index: i
});
if (!item.$sub) {
var rowHeight = item.$height || state.row;
state.total += rowHeight;
return "<div" + aria + " class='webix_cell' style='height:" + rowHeight + "px;'></div>";
}
}
var value = this._getValue(item, config, i);
var css = this._getCss(config, value, item, id);
var ariaSelect = " aria-selected='true' tabindex='0'";
if (css.indexOf("select") !== -1) {
//in case of row/column selection - make only first cell focusable
if (css.indexOf("row") !== -1) {
var xr = this._get_x_range();
if (xr[0] === index$$1) aria += ariaSelect;
} else if (css.indexOf("col") !== -1) {
if (i === yr[0]) aria += ariaSelect;
} else aria += ariaSelect;
}
var isOpen = !!item.$subopen;
var margin = isOpen ? "margin-bottom:" + item.$subHeight + "px;" : "";
if (top >= 0) {
if (top > 0) margin += "top:" + top + "px;'";
css = "webix_topcell " + css;
if (i == this._settings.topSplit - 1) css = "webix_last_topcell " + css;
}
if (item.$height) {
html = "<div" + aria + " class='" + css + "' style='height:" + item.$height + "px;" + margin + "'>" + value + "</div>";
state.total += item.$height - state.row;
} else {
html = "<div" + aria + " class='" + css + "'" + (margin ? " style='" + margin + "'" : "") + ">" + value + "</div>";
}
if (isOpen) state.total += item.$subHeight;
} else {
html = "<div role='gridcell' class='webix_cell'></div>";
if (!this._data_request_flag) this._data_request_flag = {
start: i,
count: yr[1] - i
};else this._data_request_flag.last = i;
}
state.total += state.row;
return html;
},
_set_split_sizes_y: function () {
if (!this._columns.length || isNaN(this._content_height * 1)) return;
debug_size_box(this, ["y-sizing"], true);
var wanted_height = this._dtable_height + (this._scrollSizeX ? this._scrollSizeX : 0);
if ((this._settings.autoheight || this._settings.yCount) && this.resize()) return;
this._y_scroll.sizeTo(this._content_height, this._header_height, this._footer_height);
this._y_scroll.define("scrollHeight", wanted_height);
this._dtable_offset_height = Math.max(0, this._content_height - this._scrollSizeX - this._header_height - this._footer_height);
for (var i = 0; i < 3; i++) {
this._body.childNodes[i].style.height = this._dtable_offset_height + "px";
if (this._settings.prerender) this._body.childNodes[i].firstChild.style.height = this._dtable_height + "px";else this._body.childNodes[i].firstChild.style.height = this._dtable_offset_height + "px";
} //prevent float overflow, when we have split and very small
this._header.style.height = this._header_height + "px";
},
_set_split_sizes_x: function () {
if (!this._columns.length) return;
var index$$1 = 0;
this._left_width = 0;
this._right_width = 0;
this._center_width = 0;
while (index$$1 < this._settings.leftSplit) {
this._left_width += this._columns[index$$1].width;
index$$1++;
}
index$$1 = this._columns.length - 1;
while (index$$1 >= this._rightSplit) {
this._right_width += this._columns[index$$1].width;
index$$1--;
}
if (!this._content_width) return;
if (this._settings.autowidth && this.resize()) return;
this._center_width = this._content_width - this._right_width - this._left_width - this._scrollSizeY;
this._body.childNodes[1].firstChild.style.width = this._dtable_width + "px";
this._body.childNodes[0].style.width = this._left_width + "px";
this._body.childNodes[1].style.width = this._center_width + "px";
this._body.childNodes[2].style.width = this._right_width + "px";
this._header.childNodes[0].style.width = this._left_width + "px";
this._header.childNodes[1].style.width = this._center_width + "px";
this._header.childNodes[2].style.width = this._right_width + "px";
this._footer.childNodes[0].style.width = this._left_width + "px";
this._footer.childNodes[1].style.width = this._center_width + "px";
this._footer.childNodes[2].style.width = this._right_width + "px";
var delta = this._center_width - this._dtable_width;
if (delta < 0) delta = 0; //negative header space has not sense
if (delta != this._header_fix_width) {
this._header_fix_width = delta;
this._size_header_footer_fix();
} // temp. fix: Chrome [DIRTY]
if (env.isWebKit) {
var w = this._body.childNodes[0].offsetWidth; //eslint-disable-line
w = this._body.childNodes[1].offsetWidth;
w = this._body.childNodes[1].firstChild.offsetWidth;
w = this._body.childNodes[2].offsetWidth;
}
this._x_scroll.sizeTo(this._content_width - this._scrollSizeY);
this._x_scroll.define("scrollWidth", this._dtable_width + this._left_width + this._right_width);
},
$getSize: function (dx, dy) {
if ((this._settings.autoheight || this._settings.yCount) && this._settings.columns) {
//if limit set - use it
var desired = (this._settings.yCount || 0) * this._settings.rowHeight; //else try to use actual rendered size
//if component invisible - this is not valid, so fallback to all rows
if (!desired) desired = this.isVisible() ? this._dtable_height : this.count() * this._settings.rowHeight; //add scroll and check minHeight limit
this._settings.height = Math.max(desired + (this._scrollSizeX ? this._scrollSizeX : 0) - 1, this._settings.minHeight || 0) + this._header_height + this._footer_height;
}
if (this._settings.autowidth && this._settings.columns) this._settings.width = Math.max(this._dtable_width + this._left_width + this._right_width + this._scrollSizeY, this._settings.minWidth || 0);
var minwidth = this._left_width + this._right_width + this._scrollSizeY;
var sizes = base$1.api.$getSize.call(this, dx, dy);
sizes[0] = Math.max(sizes[0] || minwidth);
return sizes;
},
_restore_scroll_state: function () {
if (this._x_scroll && !env.touch) {
var state = this.getScrollState();
this._x_scroll.config.scrollPos = this._y_scroll.config.scrollPos = 0;
this.scrollTo(state.x, state.y);
}
},
$setSize: function () {
var oldw = this._content_width;
var oldh = this._content_height;
if (base$1.api.$setSize.apply(this, arguments)) {
if (this._dtable_fully_ready) {
this.callEvent("onResize", [this._content_width, this._content_height, oldw, oldh]);
this._set_split_sizes_x();
this._set_split_sizes_y();
}
this.render();
}
},
_on_header_click: function (column, e) {
var col = this.getColumnConfig(column);
if (!this._settings.sort || !col.sort) return;
var dir = "asc";
if (this._last_sorted[col.id]) {
dir = this._last_sorted[col.id].dir == "asc" ? "desc" : "asc";
} else if (this._sort_signs[col.id]) {
dir = this._sort_signs[col.id].getAttribute("webix_sort_dir") == "asc" ? "desc" : "asc";
}
this._sort(col.id, dir, col.sort, e.ctrlKey || e.metaKey);
},
markSorting: function (column, direction, preserve) {
direction = direction || "asc";
if (!preserve) {
this._sort_signs_order = [];
for (var i in this._sort_signs) {
if (i !== column) {
var parent = this._sort_signs[i].parentNode;
if (parent) {
parent.removeAttribute("aria-sort");
parent.removeAttribute("tabindex");
}
remove(this._sort_signs[i]);
delete this._sort_signs[i];
} else {
this._sort_signs_order.push(i);
this._sort_signs[i].firstChild.innerHTML = "1";
}
}
}
if (!column) return;
if (this._sort_signs[column]) {
this._sort_signs[column].className = "webix_ss_sort_".concat(direction);
} else {
var sign = create("div", {
webix_sort_dir: direction,
class: "webix_ss_sort_".concat(direction)
}, "<div class=\"webix_ss_sort_num\">".concat(this._sort_signs_order.length + 1, "</div>"));
this._render_single_mark(column, sign, direction);
this._sort_signs[column] = sign;
this._sort_signs_order.push(column);
}
var first = this._sort_signs[this._sort_signs_order[0]];
switch (this._sort_signs_order.length) {
case 1:
addCss(first, "webix_ss_sort_single");
break;
case 2:
removeCss(first, "webix_ss_sort_single");
}
},
_render_single_mark: function (column, sign, direction) {
direction = direction || sign.getAttribute("webix_sort_dir");
var cell = this._get_header_cell(this.getColumnIndex(column));
if (cell) {
if (cell.style.position != "absolute") cell.style.position = "relative";
cell.appendChild(sign);
cell.setAttribute("aria-sort", direction + "ending");
cell.setAttribute("tabindex", "0");
}
},
scroll_setter: function (mode) {
if (typeof mode == "string") {
this._settings.scrollX = mode.indexOf("x") != -1;
this._settings.scrollY = mode.indexOf("y") != -1;
return mode;
} else return this._settings.scrollX = this._settings.scrollY = mode;
},
_get_header_cell: function (column) {
var attr =
/*@attr*/
"column";
var cells = this._header.querySelectorAll("div[".concat(attr, "=\"").concat(column, "\"]"));
var maybe = null;
for (var i = 0; i < cells.length; i++) {
var activeId = cells[i].getAttribute(
/*@attr*/
"active_id");
if (activeId && !datafilter[this._active_headers[activeId].content].$icon) return null;
if (!cells[i].innerHTML) continue;
maybe = cells[i];
if ((cells[i].colSpan || 0) < 2) return maybe;
}
return maybe;
},
_last_order: [],
_last_sorted: {},
_sort: function (col_id, direction, type$$1, preserve) {
var _this2 = this;
preserve = this._settings.sort === "multi" && preserve;
direction = direction || "asc";
if (!preserve) {
this._last_order = [];
this._last_sorted = {};
}
var col = this.getColumnConfig(col_id);
var config = typeof col.sort == "function" ? {
as: col.sort,
dir: direction
} : {
by: col.id,
dir: direction,
as: col.sort
};
if (!this._last_sorted[col.id]) this._last_order.push(col.id);
this._last_sorted[col.id] = config;
if (type$$1 == "server") {
var params = [col.id, direction, type$$1];
if (this._last_order.length > 1) params = [this._last_order.map(function (id) {
return _this2._last_sorted[id];
})];
this.callEvent("onBeforeSort", params);
if (!this._skip_server_op) this.loadNext(0, 0, 0, 0, true, true).then(function () {
return _this2._on_after_sort(params);
});else this._skip_server_op.$params = params; // save last parameters
} else {
if (type$$1 == "text") {
var new_id = "$text_" + col.id;
this.data.each(function (obj) {
obj[new_id] = this.getText(obj.id, col.id);
}, this);
config.as = "string";
config.by = new_id;
}
if (this._last_order.length > 1) this.data.sort(this._last_order.map(function (id) {
return _this2._last_sorted[id];
}));else this.data.sort(config);
}
this.markSorting(col.id, config.dir, preserve);
},
_on_after_sort: function (params) {
this.callEvent("onAfterSort", params);
},
_mouseEventCall: function (css_call, e, id, trg) {
var functor, i, res;
if (css_call.length) {
for (i = 0; i < css_call.length; i++) {
functor = toFunctor(css_call[i], this.$scope);
res = functor.call(this, e, id, trg);
if (res === false) return false;
}
}
},
//because we using non-standard rendering model, custom logic for mouse detection need to be used
_mouseEvent: function (e, hash, name, pair) {
e = e || event;
var trg = e.target;
if (this._settings.subview && this != $$(trg)) return; //define some vars, which will be used below
var css = "",
css_call = [],
found = false,
id = null,
res; //loop through all parents
while (trg && trg.parentNode && trg != this._viewobj.parentNode) {
var trgCss = _getClassName(trg);
if (css = trgCss) {
css = css.toString().split(" ");
for (var i = css.length - 1; i >= 0; i--) {
if (hash[css[i]]) css_call.push(hash[css[i]]);
}
}
if (trg.parentNode.getAttribute && !id) {
var column = trg.parentNode.getAttribute(
/*@attr*/
"column") || trg.getAttribute(
/*@attr*/
"column");
if (column) {
//we need to ignore TD - which is header|footer
var isBody = this._body.contains(trg); //column already hidden or removed
if (!this._columns[column]) return;
found = true;
if (isBody) {
var index$$1 = trg.parentNode.getAttribute(
/*@attr*/
"row") || trg.getAttribute(
/*@attr*/
"row");
if (!index$$1) {
//click event occurs on column holder, we can't detect cell
if (trg.getAttribute(
/*@attr*/
"column")) return;
index$$1 = index(trg);
if (index$$1 >= this._settings.topSplit) {
var pager = this._settings.pager;
if (pager || !this._settings.prerender && !this._settings.autoheight) index$$1 += this._columns[column]._yr0 - this._settings.topSplit;
}
}
this._item_clicked = id = {
row: this.data.order[index$$1],
column: this._columns[column].id
};
id.toString = this._id_to_string;
} else this._item_clicked = id = {
column: this._columns[column].id
}; //some custom css handlers was found
res = this._mouseEventCall(css_call, e, id, trg);
if (res === false) return; //call inner handler
if (isBody) {
if (this.callEvent("on" + name, [id, e, trg]) && pair) {
this.callEvent("on" + pair, [id, e, trg]);
}
} else if (name == "ItemClick") {
var isHeader = this._header.contains(trg);
if (isHeader && this.callEvent("onHeaderClick", [id, e, trg])) this._on_header_click(id.column, e);
}
css_call = [];
}
}
trg = trg.parentNode;
}
this._mouseEventCall(css_call, e, id, this.$view);
return found; //returns true if item was located and event was triggered
},
_get_tooltip_data: function (t, e) {
var id = this.locate(e);
if (!id) return null;
var tooltip = TooltipControl._tooltip;
var data;
if (id.header) {
var node = e.target;
var section = node;
var pos$$1;
var cind = id.cind - (id.span ? id.span - 1 : 0);
var rind = -1;
while (section && !pos$$1) {
section = section.parentNode;
pos$$1 = section.getAttribute("section");
}
while (node && rind < 0) {
var row = node.getAttribute("row");
if (row) rind = row;
node = node.parentNode;
}
var config = this._columns[cind][pos$$1][rind];
if (config.tooltip) tooltip.type.template = template(config.tooltip === true ? "#text#" : config.tooltip);else return null;
data = config;
} else {
var _config = tooltip.type.column = this.getColumnConfig(id.column); //empty tooltip - ignoring
if (!_config.tooltip && _config.tooltip !== undefined) return null;
if (_config.tooltip === true || !_config.tooltip && isUndefined(this._settings.tooltip.template)) {
data = this.getText(id.row, id.column).toString();
} else if (_config.tooltip) {
var area = e.target.getAttribute("webix_area");
if (area) {
tooltip.type.template = function (obj, common) {
var values = obj[_config.id];
return template(_config.tooltip).call(this, obj, common, values[area], area);
};
} else tooltip.type.template = template(_config.tooltip);
} else tooltip.type.template = template(this._settings.tooltip.template);
}
return data !== undefined ? data : this.getItem(id.row);
},
$tooltipOut: function () {
TooltipControl._hide_tooltip();
delete TooltipControl._tooltip.type.column;
return null;
},
showOverlay: function (message) {
if (!this._datatable_overlay) {
var t = create("DIV", {
"class": "webix_overlay"
}, "");
this._body.appendChild(t);
this._datatable_overlay = t;
}
this._datatable_overlay.innerHTML = message;
},
hideOverlay: function () {
if (this._datatable_overlay) {
remove(this._datatable_overlay);
this._datatable_overlay = null;
}
},
mapCells: function (startrow, startcol, numrows, numcols, callback, getOnly) {
if (startrow === null && this.data.order.length > 0) startrow = this.data.order[0];
if (startcol === null) startcol = this.columnId(0);
if (numrows === null) numrows = this.data.order.length;
if (numcols === null) numcols = this._settings.columns.length;
if (!this.exists(startrow)) return;
startrow = this.getIndexById(startrow);
startcol = this.getColumnIndex(startcol);
if (startcol === null) return;
for (var i = 0; i < numrows && startrow + i < this.data.order.length; i++) {
var row_ind = startrow + i;
var row_id = this.data.order[row_ind];
if (row_id) {
//dyn loading
var item = this.getItem(row_id);
for (var j = 0; j < numcols && startcol + j < this._settings.columns.length; j++) {
var col_ind = startcol + j;
var col_id = this.columnId(col_ind);
var result = callback(item[col_id], row_id, col_id, i, j);
if (!getOnly) item[col_id] = result;
}
}
}
},
_call_onparse: function (driver, data) {
if (!this._settings.columns && driver.getConfig) this.define("columns", driver.getConfig(data));
},
_autoDetectConfig: function () {
var test = this.getItem(this.getFirstId());
var res = this._settings.columns = [];
for (var key in test) {
if (key != "id" && key[0] != "$") res.push({
id: key,
header: key[0].toUpperCase() + key.substr(1),
sort: "string",
editor: "text"
});
}
if (res.length) res[0].fillspace = true;
if (typeof this._settings.select == "undefined") this.define("select", "row");
}
}; // #include ui/datatable/datatable_filter.js
// #include ui/datatable/datatable_selection.js
// #include ui/datatable/datatable_blockselect.js
// #include ui/datatable/datatable_resize.js
// #include ui/datatable/datatable_paging.js
// #include ui/datatable/datatable_clipboard.js
// #include ui/datatable/datatable_state.js
// #include ui/datatable/datatable_touch.js
// #include ui/datatable/datatable_size.js
// #include ui/datatable/datatable_math.js
// #include ui/datatable/datatable_edit.js
// #include ui/datatable/datatable_columns.js
// #include ui/datatable/datatable_keynav.js
// #include ui/datatable/datatable_dnd.js
// #include ui/datatable/datatable_validation.js
// #include ui/datatable/datatable_sparklines.js
// #include ui/datatable/datatable_print.js
// #include ui/datatable/datatable_export.js
var view$1h = exports.protoUI(api$1h, temp$3, DataState, TablePaste, DataMove, EditAbility, KeysNavigation, PagingAbility, CustomPrint, Mixin$c, ValidateCollection, Mixin$b, Mixin$d, DragItem, Mixin$a, Mixin$9, Mixin$8, Mixin$7, Mixin$6, temp$4, Mixin$5, Mixin$4, Mixin$3, temp$5, Mixin$2, Mixin$1, Mixin, temp$6, temp$7, AutoTooltip, Group, DataMarks, DataLoader, MouseEvents, MapCollection, base$1.view, EventSystem, Settings);
var datatable = {
api: api$1h,
view: view$1h
};
var api$1i = {
name: "treetable",
$init: function () {
exports.extend(this.data, TreeStore, true);
exports.extend(this.type, TreeType);
exports.extend(this, TreeDataMove, true);
for (var key in TreeClick) {
if (!this.on_click[key]) this.on_click[key] = this._unwrap_id(TreeClick[key]);
}
this.type.treetable = template("{common.space()}{common.icon()} {common.folder()}");
this.type.treecheckbox = function (obj) {
if (obj.indeterminate && !obj.nocheckbox) return "<div class='webix_tree_checkbox webix_indeterminate'></div>";else return TreeType.checkbox.apply(this, arguments);
};
this.data.provideApi(this, true);
this._viewobj.setAttribute("role", "treegrid");
},
_drag_order_complex: false,
_unwrap_id: function (original) {
return function (e, id) {
id = id.row;
return original.call(this, e, id);
};
},
_close_branches: function (context) {
var source = !this._settings.prerender ? [context.start] : context.source;
for (var i = 0; i < source.length; i++) {
this.close(source[i]);
}
},
getState: function () {
var state = DataState.getState.call(this);
exports.extend(state, TreeAPI.getState.call(this));
return state;
},
setState: function (state) {
if (TreeAPI.setState.call(this, state)) {
//run grid-state only when tree component was fully loaded
DataState.setState.call(this, state);
}
},
clipboard_setter: function (value) {
exports.extend(this._paste, TreeTablePaste);
return TablePaste.clipboard_setter.call(this, value);
},
_run_load_next: function (conf, direction) {
for (var i = 0; i < conf.start; i++) {
var id = this.data.order[i];
if (id && this.getItem(id).$level != 1) conf.start--;
}
return datatable.api._run_load_next.call(this, conf, direction);
}
};
var view$1i = exports.protoUI(api$1i, TreeAPI, TreeStateCheckbox, TreeDataLoader, datatable.view);
exports.protoUI({
name: "filter",
defaults: {
template: "GPL version doesn't support filter <br> You need Webix PRO"
}
}, template$1.view);
/* eslint no-constant-condition: 0 */
/* eslint no-inner-declarations: 0 */
{
var get_inspector_config = function (view) {
var values = {};
var options = [];
view = $$(view);
for (var key in view.config) {
if (ignore[key]) continue;
if (_typeof(view.config[key]) == "object") continue;
if (typeof view.config[key] == "undefined") continue;
if (typeof view.config[key] == "function") continue;
if (key == "view" || key == "id") options.push({
label: key,
id: key
});else options.push({
label: key,
type: "text",
id: key
});
if (view.defaults[key] == view.config[key]) options[options.length - 1].css = {
"color": "#888"
};
values[key] = view.config[key];
}
options.sort(function (a, b) {
if (!a.css && b.css) return -1;
if (a.css && !b.css) return 1;
return a.id > b.id ? 1 : a.id == b.id ? 0 : -1;
});
return {
elements: options,
data: values,
head: " [" + view.name + "] <strong>" + view._settings.id + "</strong>"
};
};
var create_inspector = function () {
if (!$$("webix_debug_inspector_win")) ui({
id: "webix_debug_inspector_win",
view: "window",
top: 2,
left: 0,
width: 350,
height: 350,
head: false,
autofit: false,
body: {
cols: [{
width: 10
}, {
type: "clean",
rows: [{
view: "toolbar",
elements: [{
view: "label",
value: "",
id: "webix_debug_inspector_head"
}, {
view: "button",
width: 100,
value: "Hide",
type: "custom",
click: function () {
show_inspector();
}
}]
}, {
id: "webix_debug_inspector",
nameWidth: 150,
view: "property",
scroll: "y",
elements: [],
on: {
onaftereditstop: function (state, editor) {
if (state.old == state.value) return;
var value = state.value;
if (value === "true" || value === "false") {
value = value === "true";
} else {
var intvalue = parseInt(value, 10);
if (intvalue == value) value = intvalue;
}
var view = $$(this.config.view);
view.define(editor.id, value);
if (view.refreshColumns) view.refreshColumns();else if (view.refresh) view.refresh();
view.resize();
}
}
}]
}]
}
});
};
var show_inspector = function (view, ev) {
create_inspector();
var win = $$("webix_debug_inspector_win");
if (view) {
var config = get_inspector_config(view);
var winx = document.body.offsetWidth;
var winy = document.body.offsetHeight;
var pos$$1 = ev ? pos(ev) : {
x: 0,
y: 0
};
win.define("height", Math.max(350, winy - 4));
win.resize();
var props = $$("webix_debug_inspector");
props.define("elements", config.elements);
props.define("view", view);
win.show({
x: pos$$1.x > winx / 2 ? 0 : winx - 370,
y: 0
});
$$("webix_debug_inspector").setValues(config.data);
$$("webix_debug_inspector_head").setValue(config.head);
} else win.hide();
};
var infi = function (value) {
if (value >= 100000) return "Any";
return value;
};
var log_level = function (data, prefix, now) {
window.console.log((data == now ? ">>" : " ") + prefix + data.name + " / " + data.config.id);
prefix += " ";
if (data._cells) for (var i = 0; i < data._cells.length; i++) {
log_level(data._cells[i], prefix, now);
}
if (data._head_cell) log_level(data._head_cell, prefix, now);
if (data._body_cell) log_level(data._body_cell, prefix, now);
};
attachEvent("onLoadError", function (xhttp, owner) {
var text; //xhttp can be of blob or arraybuffer type, or just empty in case of no data
try {
text = xhttp.responseText;
} catch (e) {
text = "";
}
text = text || "[EMPTY DATA]";
var error_text = "Data loading error, check console for details";
if (text.indexOf("<?php") === 0) error_text = "PHP support missed";else if (text.indexOf("WEBIX_ERROR:") === 0) error_text = text.replace("WEBIX_ERROR:", "");
message({
type: "debug",
text: error_text,
expire: -1
});
if (window.console) {
var logger = window.console;
logger.log("Data loading error");
logger.log("Object:", owner);
logger.log("Response:", text);
if (xhttp) logger.log("XHTTP:", xhttp);
}
});
ready(function () {
var path = document.location.href;
if (path.indexOf("file:") === 0) {
message({
type: "error",
text: "Please open sample by http,<br>not as file://",
expire: -1
});
}
});
var ignore = {
"_inner": true,
"awidth": true,
"cheight": true,
"bheight": true,
"aheight": true
};
var uiConfig = {
view: "contextmenu",
id: "webix:debugmenu",
on: {
onBeforeShow: function (e) {
if (!e.ctrlKey) return false;
var view = locate(e,
/*@attr*/
"view_id");
if (!view) return false;
this.config.lastTarget = view;
blockEvent();
delay(function () {
unblockEvent();
});
},
onShow: function () {
var view = $$(this.config.lastTarget);
var info = "<span style='color:#888'>" + view._settings.id + "<sup style='float:right'>[" + view.name + "]</sup></span>";
document.getElementById("webix_debug_cmx").innerHTML = info;
}
},
data: ["<div id='webix_debug_cmx'></div>", {
id: "inspect",
value: "Inspect"
}, {
id: "docs",
value: "Documentation"
}, {
value: "Log to Console",
submenu: [{
id: "size",
value: "Sizes"
}, {
id: "tree",
value: "Tree"
}, {
id: "dump",
value: "Dump"
}]
}],
click: function (id, ev) {
//mixing two object result in confusion
var obj = $$(this.config.lastTarget);
if (id == "dump") {
window.console.info("\n" + obj.name + " / " + obj.config.id);
window.console.log("\nView: ", obj, ", Config: ", obj.config, ", Data: ", obj.data);
window.console.log(obj.$view);
}
if (id == "tree") {
var now = obj;
while (obj.getParentView()) {
obj = obj.getParentView();
}
window.console.log("");
log_level(obj, "", now);
}
if (id == "size") {
window.console.info("");
window.console.info("\n" + obj.name + " / " + obj.config.id);
window.console.info("\n[min] ", obj.config.width, " x ", obj.config.height);
var sizes = obj.$getSize(0, 0);
window.console.info("[max] ", infi(sizes[1]), " x ", infi(sizes[3]) + (obj.config.autoheight ? ", auto height" : ""));
window.console.info("[gravity] ", obj.config.gravity);
window.console.info("\n[content] ", obj._content_width, " x ", obj._content_height);
window.console.info("[last set] ", obj._last_size[0], " x ", obj._last_size[1]);
if (obj._settings._inner) window.console.info("\n[borders] ", "left:", !obj._settings._inner.left, "\ttop:", !obj._settings._inner.top, "\tright:", !obj._settings._inner.right, "\tbottom:", !obj._settings._inner.bottom);else window.console.info("\n[borders] none");
}
if (id == "docs") window.open("http://docs.webix.com/api__refs__ui." + obj.name + ".html", "__blank");
if (id == "inspect") {
show_inspector(this.config.lastTarget, ev);
}
}
};
ready(function () {
uiConfig.master = document.body;
ui(uiConfig);
});
}
var DataRecord = exports.proto({
name: "DataRecord",
isVisible: function () {
return true;
},
$init: function (config) {
this.data = config || {};
var id = config && config.id ? config.id : uid();
this._settings = {
id: id
};
ui.views[id] = this;
},
getValues: function () {
return this.data;
},
setValues: function (data, update, config) {
this.data = update ? exports.extend(this.data, data, true) : data;
this.callEvent("onChange", [data, config]);
},
refresh: function () {
this.callEvent("onBindRequest");
}
}, EventSystem, BaseBind, AtomDataLoader, Settings);
var DataValue = exports.proto({
name: "DataValue",
isVisible: function () {
return true;
},
$init: function (config) {
if (!config || isUndefined(config.value)) this.data = config || "";
var id = config && config.id ? config.id : uid();
this._settings = {
id: id
};
ui.views[id] = this;
},
setValue: function (value, config) {
this.data = value;
this.callEvent("onChange", [value, config]);
},
getValue: function () {
return this.data;
},
refresh: function () {
this.callEvent("onBindRequest");
}
}, EventSystem, BaseBind);
var TreeCollection = exports.proto({
name: "TreeCollection",
$init: function () {
exports.extend(this.data, TreeStore, true);
this.data.provideApi(this, true);
exports.extend(this, TreeDataMove, true);
}
}, TreeDataLoader, DataCollection);
//----------------
exports.Date = wDate;
exports.Number = Number$1;
exports.promise = Deferred;
exports.DataCollection = DataCollection;
exports.DataRecord = DataRecord;
exports.DataValue = DataValue;
exports.TreeCollection = TreeCollection;
exports.AtomDataLoader = AtomDataLoader;
exports.AtomRender = AtomRender;
exports.AutoScroll = AutoScroll;
exports.AutoTooltip = AutoTooltip;
exports.BaseBind = BaseBind;
exports.BindSource = BindSource;
exports.Canvas = Canvas;
exports.CodeParser = CodeParser;
exports.CollectionBind = CollectionBind;
exports.ContextHelper = ContextHelper;
exports.CopyPaste = CopyPaste;
exports.CustomPrint = CustomPrint;
exports.CustomScroll = temp$1;
exports.DataMarks = DataMarks;
exports.DataMove = DataMove;
exports.DataLoader = DataLoader;
exports.DataState = DataState;
exports.DataStore = DataStore;
exports.Destruction = Destruction;
exports.DragControl = DragControl;
exports.DragItem = DragItem;
exports.DragOrder = DragOrder;
exports.EditAbility = EditAbility;
exports.EventSystem = EventSystem;
exports.FlexLayout = FlexLayout;
exports.Group = Group;
exports.GroupMethods = GroupMethods;
exports.GroupStore = GroupStore;
exports.HTMLOptions = HTMLOptions;
exports.HtmlMap = HtmlMap;
exports.IdSpace = IdSpace;
exports.KeysNavigation = KeysNavigation;
exports.MapCollection = MapCollection;
exports.Modality = Modality;
exports.MouseEvents = MouseEvents;
exports.Movable = Movable;
exports.NavigationButtons = NavigationButtons;
exports.OverlayBox = OverlayBox;
exports.PagingAbility = PagingAbility;
exports.ProgressBar = ProgressBar;
exports.RecordBind = RecordBind;
exports.RenderStack = RenderStack;
exports.ResizeArea = ResizeArea;
exports.SingleRender = SingleRender;
exports.Scrollable = Scrollable;
exports.SelectionModel = SelectionModel;
exports.Settings = Settings;
exports.Sparklines = Sparklines;
exports.TablePaste = TablePaste;
exports.TooltipControl = TooltipControl;
exports.Touch = Touch;
exports.TreeAPI = TreeAPI;
exports.TreeClick = TreeClick;
exports.TreeDataLoader = TreeDataLoader;
exports.TreeDataMove = TreeDataMove;
exports.TreeRenderStack = TreeRenderStack;
exports.TreeStateCheckbox = TreeStateCheckbox;
exports.TreeStore = TreeStore;
exports.TreeTablePaste = TreeTablePaste;
exports.TreeType = TreeType;
exports.UIManager = UIManager;
exports.Undo = Undo;
exports.UploadDriver = UploadDriver;
exports.ValidateCollection = ValidateCollection;
exports.ValidateData = ValidateData;
exports.ValueBind = ValueBind;
exports.Values = Values;
exports.VirtualRenderStack = VirtualRenderStack;
exports.VRenderStack = VRenderStack;
exports.html = html$1;
exports.skin = skin$5;
exports.debug = debug;
exports.i18n = i18n;
exports.ready = ready;
exports.env = env;
exports.color = color;
exports.csv = csv$1;
exports.clipbuffer = clipbuffer;
exports.storage = storage;
exports.template = template;
exports.type = type;
exports.editors = editors;
exports.animate = animate;
exports.print = print;
exports.rules = rules;
exports.filters = filters;
exports.patterns = patterns;
exports.fullscreen = fullscreen;
exports.version = version$1;
exports.name = name$1;
exports.level_in = level_in;
exports.level_out = level_out;
exports.clone = clone;
exports.copy = copy;
exports.single = single;
exports.bind = bind;
exports.exec = exec;
exports.wrap = wrap;
exports.isUndefined = isUndefined;
exports.delay = delay;
exports.once = once;
exports.uid = uid;
exports.toNode = toNode;
exports.toFunctor = toFunctor;
exports.isArray = isArray;
exports.isDate = isDate;
exports._to_array = _to_array;
exports._power_array = _power_array;
exports._events_final_destructor = _events_final_destructor;
exports._event = _event;
exports.event = event$1;
exports.eventRemove = eventRemove;
exports.callEvent = callEvent;
exports.attachEvent = attachEvent;
exports.detachEvent = detachEvent;
exports.blockEvent = blockEvent;
exports.unblockEvent = unblockEvent;
exports.mapEvent = mapEvent;
exports.hasEvent = hasEvent;
exports.stringify = stringify;
exports.toPNG = toPNG;
exports.toCSV = toCSV;
exports.toPDF = toPDF;
exports.toExcel = toExcel;
exports.alert = alert;
exports.confirm = confirm;
exports.modalbox = modalbox;
exports.prompt = prompt;
exports.message = message;
exports.editStop = editStop;
exports.ajax = ajax;
exports.DataDriver = DataDriver;
exports.dp = dp;
exports.DataProcessor = DataProcessor;
exports.remote = remote;
exports.require = require;
exports.proxy = proxy$5;
exports.send = send;
exports.ui = ui;
exports.$$ = $$;
Object.defineProperty(exports, '__esModule', { value: true });
})));