webix
Version:
Webix UI
1,821 lines (1,569 loc) • 1.52 MB
JavaScript
/**
* @license
* webix UI v.11.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) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
}, _typeof(obj);
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArray(iter) {
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
}
function _iterableToArrayLimit(arr, i) {
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
if (_i == null) return;
var _arr = [];
var _n = true;
var _d = false;
var _s, _e;
try {
for (_i = _i.call(arr); !(_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 _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
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 {
if (typeof queue[e.data] === "function") 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, origin, allowViewRefs) {
assert(source, "Invalid mixing target");
level_in();
var esModern = !!window.Map && !!window.Set && !!window.WeakMap && !!window.WeakSet;
var target;
if (origin) {
target = source;
source = origin;
} else target = isArray(source) ? [] : {};
for (var method in source) {
var from = source[method];
if (from && _typeof(from) == "object" && !(from instanceof RegExp)) {
var viewInstance = !!from._settings && !!from.$init && !!from.define;
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) || allowViewRefs && viewInstance) {
target[method] = from;
}
/* jshint ignore:end */
else {
target[method] = isArray(from) ? [] : {};
copy(target[method], from, allowViewRefs);
}
} 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 scope
function exec(code) {
return 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] || exec(str);
}
return str;
}
/*checks where an object is instance of Array*/
function isArray(obj) {
return Array.isArray(obj);
}
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(encodeURIComponent(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,
ignoreErrors: true,
save: function (data) {
return this.load(data);
},
load: function (view) {
var params = {
query: this.source
};
var isView = arguments.length > 1;
var xhr;
if (!isView) params.variables = view;
return ajax().headers({
"Content-type": "application/json"
}).post(this.url, params, function () {
xhr = arguments.length <= 2 ? undefined : arguments[2];
}).then(function (data) {
var res = data.json();
var resData = res.data,
errors = res.errors;
if (errors && !GraphQL.ignoreErrors) {
if (isView) {
return Deferred.reject(xhr);
} else {
// promise rejection for external callers
// the error must be handled via fail/catch in such cases
return Deferred.reject({
xhr: xhr,
errors: errors
});
}
}
return unbox(resData);
});
}
};
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 _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;
}
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 {
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) {
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
};
} //returns relative position of event
function posRelative(ev) {
return {
x: ev.offsetX,
y: ev.offsetY
};
} //returns position of event
function pos(ev) {
if (!ev.type) // webix touch event
return {
x: ev.x,
y: ev.y
};
if (ev.touches && ev.touches[0]) ev = ev.touches[0];
return {
x: ev.pageX,
y: ev.pageY
};
} //prevent event action
function preventEvent(e) {
e.preventDefault();
return stopEvent(e);
} //stop event bubbling
function stopEvent(e) {
e.stopPropagation();
return false;
}
function triggerEvent(node, type, name, details) {
var event;
if (typeof window[type] === "function") {
details = exports.extend(details || {}, {
bubbles: true,
cancelable: true
});
event = new window[type](name, details);
} else {
//IE 11 support
event = document.createEvent(type);
event.initEvent(name, true, true);
}
node.dispatchEvent(event);
} //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,
height = 0;
for (var i = 0; i < all.length; i++) {
d.innerHTML = all[i];
var rect = d.getBoundingClientRect();
width = Math.max(width, Math.ceil(rect.width));
height = Math.max(height, Math.ceil(rect.height));
}
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) {
node.focus();
var types = ["password", "search", "tel", "text", "url"];
if (node.setSelectionRange && types.includes(node.type)) {
start = start || 0;
end = end || start;
node.setSelectionRange(start, end);
}
}
function getSelectionRange(node) {
return {
start: node.selectionStart || 0,
end: node.selectionEnd || 0
};
}
function addMeta(name, value) {
document.getElementsByTagName("head").item(0).appendChild(create("meta", {
name: name,
content: value
}));
}
var html$1 = /*#__PURE__*/Object.freeze({
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,
addC