{"version":3,"file":"webix.min.js","sources":["../sources/thirdparty/promiz.js","../sources/load/drivers/xml.js","../sources/load/ajax.js","../sources/webix/html.js","../sources/webix/env.js","../sources/load/drivers/excel.js","../sources/webix/template.js","../sources/webix/htmlevents.js","../sources/ui/core.js","../sources/webix/message.js","../sources/core/uimanager.js","../sources/core/collectionbind.js","../sources/views/baseview.js","../sources/views/view.js","../sources/core/canvas.js","../sources/css/skins/material/config.js","../sources/css/skins/willow/config.js","../sources/core/touch.js","../sources/core/dragcontrol.js","../sources/views/window.js","../sources/core/customprint.js","../sources/core/customscroll.js","../sources/core/datamove.js","../sources/load/dataprocessor.js","../sources/core/datastore.js","../sources/core/dataloader.js","../sources/core/dragitem.js","../sources/core/dragorder.js","../sources/core/editability.js","../sources/core/groupmethods.js","../sources/core/htmloptions.js","../sources/core/htmlmap.js","../sources/core/mapcollection.js","../sources/core/mouseevents.js","../sources/core/scrollable.js","../sources/core/sparklines/line.js","../sources/core/sparklines/radar.js","../sources/core/treeapi.js","../sources/core/treerenderstack.js","../sources/core/treestore.js","../sources/core/uploaddriver.js","../sources/core/values.js","../sources/webix/export/common.js","../sources/webix/export/topdf.js","../sources/webix/export/toexcel.js","../sources/i18n/en.js","../sources/core/date.js","../sources/webix/storage.js","../sources/load/remote.js","../sources/ui/datafilter.js","../sources/views/baselayout.js","../sources/views/layout.js","../sources/views/daterange.js","../sources/ui/datafilter_pro.js","../sources/ui/detect.js","../sources/i18n/de.js","../sources/i18n/fr.js","../sources/i18n/it.js","../sources/i18n/pt.js","../sources/i18n/ru.js","../sources/i18n/be.js","../sources/views/scrollview.js","../sources/views/accordionitem.js","../sources/views/resizer.js","../sources/views/align.js","../sources/views/multiview.js","../sources/views/carousel.js","../sources/views/abslayout.js","../sources/views/gridlayout.js","../sources/views/toolbar.js","../sources/views/htmlform.js","../sources/views/property.js","../sources/views/calendar.js","../sources/views/colorboard.js","../sources/views/colorselect.js","../sources/views/button.js","../sources/views/label.js","../sources/core/textpattern.js","../sources/views/checkbox.js","../sources/views/radio.js","../sources/views/datepicker.js","../sources/views/segmented.js","../sources/views/toggle.js","../sources/views/list.js","../sources/views/multiselect.js","../sources/views/multicombo.js","../sources/views/rangeslider.js","../sources/views/tabbar.js","../sources/views/richtext.js","../sources/webix/debug.js","../sources/webix/print.js","../sources/webix/consts.js","../sources/webix/helpers.js","../sources/webix/customevents.js","../sources/webix/export/topng.js","../sources/webix/export/tocsv.js","../sources/webix/api.js","../sources/load/send.js"],"sourcesContent":["var global = window;\n\nvar queueId = 1;\nvar queue = {};\nvar isRunningTask = false;\n\nif (!global.setImmediate && global.addEventListener)\n\tglobal.addEventListener(\"message\", function (e) {\n\t\tif (e.source == global){\n\t\t\tif (isRunningTask)\n\t\t\t\tnextTick(queue[e.data]);\n\t\t\telse {\n\t\t\t\tisRunningTask = true;\n\t\t\t\ttry {\n\t\t\t\t\tif (typeof queue[e.data] === \"function\")\n\t\t\t\t\t\tqueue[e.data]();\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// eslint-disable-line\n\t\t\t\t}\n\n\t\t\t\tdelete queue[e.data];\n\t\t\t\tisRunningTask = false;\n\t\t\t}\n\t\t}\n\t});\n\nfunction nextTick(fn) {\n\tif (global.setImmediate) global.setImmediate(fn);\n\t// if inside of web worker\n\telse if (global.importScripts || !global.addEventListener) setTimeout(fn);\n\telse {\n\t\tqueueId++;\n\t\tqueue[queueId] = fn;\n\t\tglobal.postMessage(queueId, \"*\");\n\t}\n}\n\nDeferred.resolve = function (value) {\n\tif (!(this._d == 1))\n\t\tthrow TypeError();\n\n\tif (value instanceof Deferred)\n\t\treturn value;\n\n\treturn new Deferred(function (resolve) {\n\t\tresolve(value);\n\t});\n};\n\nDeferred.reject = function (value) {\n\tif (!(this._d == 1))\n\t\tthrow TypeError();\n\n\treturn new Deferred(function (resolve, reject) {\n\t\treject(value);\n\t});\n};\n\nDeferred.all = function (arr) {\n\tif (!(this._d == 1))\n\t\tthrow TypeError();\n\n\tif (!(arr instanceof Array))\n\t\treturn Deferred.reject(TypeError());\n\n\tvar d = new Deferred();\n\n\tfunction done(e, v) {\n\t\tif (v)\n\t\t\treturn d.resolve(v);\n\n\t\tif (e)\n\t\t\treturn d.reject(e);\n\n\t\tvar unresolved = arr.reduce(function (cnt, v) {\n\t\t\tif (v && v.then)\n\t\t\t\treturn cnt + 1;\n\t\t\treturn cnt;\n\t\t}, 0);\n\n\t\tif(unresolved == 0)\n\t\t\td.resolve(arr);\n\n\n\t\tarr.map(function (v, i) {\n\t\t\tif (v && v.then)\n\t\t\t\tv.then(function (r) {\n\t\t\t\t\tarr[i] = r;\n\t\t\t\t\tdone();\n\t\t\t\t\treturn r;\n\t\t\t\t}, done);\n\t\t});\n\t}\n\n\tdone();\n\n\treturn d;\n};\n\nDeferred.race = function (arr) {\n\tif (!(this._d == 1))\n\t\tthrow TypeError();\n\n\tif (!(arr instanceof Array))\n\t\treturn Deferred.reject(TypeError());\n\n\tif (arr.length == 0)\n\t\treturn new Deferred();\n\n\tvar d = new Deferred();\n\n\tfunction done(e, v) {\n\t\tif (v)\n\t\t\treturn d.resolve(v);\n\n\t\tif (e)\n\t\t\treturn d.reject(e);\n\n\t\tvar unresolved = arr.reduce(function (cnt, v) {\n\t\t\tif (v && v.then)\n\t\t\t\treturn cnt + 1;\n\t\t\treturn cnt;\n\t\t}, 0);\n\n\t\tif(unresolved == 0)\n\t\t\td.resolve(arr);\n\n\t\tarr.map(function (v) {\n\t\t\tif (v && v.then)\n\t\t\t\tv.then(function (r) {\n\t\t\t\t\tdone(null, r);\n\t\t\t\t}, done);\n\t\t});\n\t}\n\n\tdone();\n\n\treturn d;\n};\n\nDeferred._d = 1;\n\n\n/**\n * @constructor\n */\nfunction Deferred(resolver) {\n\t\"use strict\";\n\tif (typeof resolver != \"function\" && resolver != undefined)\n\t\tthrow TypeError();\n\t\t\n\tif (typeof this != \"object\" || (this && this.then))\n\t\tthrow TypeError();\n\n\t// states\n\t// 0: pending\n\t// 1: resolving\n\t// 2: rejecting\n\t// 3: resolved\n\t// 4: rejected\n\tvar self = this,\n\t\tstate = 0,\n\t\tval = 0,\n\t\tnext = [],\n\t\tfn, er;\n\n\tself[\"promise\"] = self;\n\n\tself[\"resolve\"] = function (v) {\n\t\tfn = self.fn;\n\t\ter = self.er;\n\t\tif (!state) {\n\t\t\tval = v;\n\t\t\tstate = 1;\n\n\t\t\tnextTick(fire);\n\t\t}\n\t\treturn self;\n\t};\n\n\tself[\"reject\"] = function (v) {\n\t\tfn = self.fn;\n\t\ter = self.er;\n\t\tif (!state) {\n\t\t\tval = v;\n\t\t\tstate = 2;\n\n\t\t\tnextTick(fire);\n\n\t\t}\n\t\treturn self;\n\t};\n\n\tself[\"_d\"] = 1;\n\n\tself[\"then\"] = function (_fn, _er) {\n\t\tif (!(this._d == 1))\n\t\t\tthrow TypeError();\n\n\t\tvar d = new Deferred();\n\n\t\td.fn = _fn;\n\t\td.er = _er;\n\t\tif (state == 3) {\n\t\t\td.resolve(val);\n\t\t}\n\t\telse if (state == 4) {\n\t\t\td.reject(val);\n\t\t}\n\t\telse {\n\t\t\tnext.push(d);\n\t\t}\n\n\t\treturn d;\n\t};\n\n\tself[\"finally\"] = function(_handler){\n\t\tvar _value;\n\t\tconst handler = function(value){\n\t\t\t_value = value;\n\t\t\treturn _handler();\n\t\t};\n\t\t\n\t\tconst value = function(){\n\t\t\tconst d = new Deferred();\n\t\t\tif(state == 4)\n\t\t\t\treturn d.reject(_value);\n\t\t\telse\n\t\t\t\treturn d.resolve(_value);\n\t\t};\n\n\t\treturn self.then(handler, handler).then(value, value);\n\t};\n\n\tself[\"catch\"] = function (_er) {\n\t\treturn self[\"then\"](null, _er);\n\t};\n\n\t//compatibility with old version of promiz lib\n\tself[\"fail\"] = function (_er) {\n\t\treturn self[\"then\"](null, _er);\n\t};\n\n\tvar finish = function (type) {\n\t\tstate = type || 4;\n\t\tfor (var i=0; i= 400 || x.status === 0;\n\t\t\t\tvar text, data;\n\t\t\t\tif (x.responseType == \"blob\" || x.responseType == \"arraybuffer\"){\n\t\t\t\t\ttext = \"\";\n\t\t\t\t\tdata = x.response;\n\t\t\t\t} else {\n\t\t\t\t\ttext = x.responseText||\"\";\n\t\t\t\t\tdata = self._data(x);\n\t\t\t\t}\n\t\t\t\tif (is_error){\n\t\t\t\t\tcallEvent(\"onAjaxError\", [x]);\n\t\t\t\t\tdefer.reject(x);\n\t\t\t\t\tif(call)\n\t\t\t\t\t\tajax.$callback((self.master || window), call, text, data, x, is_error);\n\t\t\t\t} else {\n\t\t\t\t\tdefer.resolve(data);\n\t\t\t\t\tif(call)\n\t\t\t\t\t\tajax.$callback((self.master || window), call, text, data, x, is_error);\n\t\t\t\t}\t\n\t\t\t}\n\t\t};\n\n\t\tif (this._timeout)\n\t\t\tx.timeout = this._timeout;\n\n\t\t//IE can use sync mode sometimes, fix it\n\t\tif (!this._sync)\n\t\t\tsetTimeout(function(){\n\t\t\t\tx.send(params||null);\n\t\t\t}, 0);\n\t\telse\n\t\t\tx.send(params||null);\n\t\t\n\t\tif (this.master && !this._sync){\n\t\t\tdefer.then(function(data){\n\t\t\t\t//anti-leak\n\t\t\t\tself.master=null;\n\t\t\t\tcall=self=master=null;\t\n\t\t\t\treturn data;\n\t\t\t});\n\t\t}\n\n\t\treturn this._sync?x:defer; //return XHR, which can be used in case of sync. mode\n\t},\n\t_data:function(x){\n\t\treturn {\n\t\t\txml:function(){ \n\t\t\t\ttry{\n\t\t\t\t\treturn xml.tagToObject(xml.toObject(x.responseText, this));\n\t\t\t\t}\n\t\t\t\tcatch(e){\n\t\t\t\t\tlog(x.responseText);\n\t\t\t\t\tlog(e.toString()); assert(0, \"Invalid xml data for parsing\"); \n\t\t\t\t}\n\t\t\t},\n\t\t\trawxml:function(){ \n\t\t\t\tif (!window.XPathResult)\n\t\t\t\t\treturn xml.fromString(x.responseText);\n\t\t\t\treturn x.responseXML;\n\t\t\t},\n\t\t\ttext:function(){ return x.responseText; },\n\t\t\tjson:function(){\n\t\t\t\treturn json.toObject(x.responseText, false);\n\t\t\t}\n\t\t};\n\t},\n\t//GET request\n\tget:function(url,params,call){\n\t\treturn this._send(url,params,call,\"GET\");\n\t},\n\t//POST request\n\tpost:function(url,params,call){\n\t\treturn this._send(url,params,call,\"POST\");\n\t},\n\t//PUT request\n\tput:function(url,params,call){\n\t\treturn this._send(url,params,call,\"PUT\");\n\t},\n\t//DELETE request\n\tdel:function(url,params,call){\n\t\treturn this._send(url,params,call,\"DELETE\");\n\t},\n\t//PATCH request\n\tpatch:function(url,params,call){\n\t\treturn this._send(url,params,call,\"PATCH\");\n\t},\n\n\tsync:function(){\n\t\tthis._sync = true;\n\t\treturn this;\n\t},\n\ttimeout:function(num){\n\t\tthis._timeout = num;\n\t\treturn this;\n\t},\n\tresponse:function(value){\n\t\tthis._response = value;\n\t\treturn this;\n\t},\n\theaders:function(header){\n\t\tthis._header = extend(this._header||{},header);\n\t\treturn this;\n\t},\n\tbind:function(master){\n\t\tthis.master = master;\n\t\treturn this;\n\t}\n};\najax.$callback = function(owner, call, text, data, x, is_error){\n\tif (owner.$destructed) return;\n\n\tif (is_error)\n\t\tcallEvent(\"onAjaxError\", [x]);\n\t\n\tif (call){\n\t\tvar method = call.success || call;\n\t\tif (is_error)\n\t\t\tmethod = call.error;\n\t\tif (method && method.call)\n\t\t\tmethod.call(owner,text,data,x);\n\t}\n};","import {delay, uid, toNode, extend, isUndefined} from \"./helpers.js\";\n\nlet _native_on_selectstart = 0;\nconst _style_element = {};\nconst _style_cache = {};\n\nexport function denySelect(){\n\tif (!_native_on_selectstart)\n\t\t_native_on_selectstart = document.onselectstart;\n\tdocument.onselectstart = stopEvent;\n}\n\nexport function allowSelect(){\n\tif (_native_on_selectstart !== 0){\n\t\tdocument.onselectstart = _native_on_selectstart||null;\n\t}\n\t_native_on_selectstart = 0;\n\n}\n\nexport function index(node){\n\tvar k=0;\n\t//must be =, it is not a comparation!\n\twhile ((node = node.previousSibling)) k++;\n\treturn k;\n}\n\nexport function createCss(rule, sufix){\n\tvar text = \"\";\n\tsufix = sufix || \"\";\n\n\tfor (var key in rule)\n\t\ttext+= key+\":\"+rule[key]+\";\";\n\n\tvar name = _style_cache[text+sufix];\n\tif (!name){\n\t\tname = \"s\"+uid();\n\t\taddStyle(\".\"+name+(sufix||\"\")+\"{\"+text+\"}\");\n\t\t_style_cache[text+sufix] = name;\n\t}\n\treturn name;\n}\n\nexport function addStyle(rule, group){\n\tvar style = group ? _style_element[group] :_style_element[\"default\"];\n\tif(!style){\n\t\tstyle = document.createElement(\"style\");\n\t\tstyle.setAttribute(\"type\", \"text/css\");\n\t\tstyle.setAttribute(\"media\", \"screen,print\");\n\t\tdocument.getElementsByTagName(\"head\")[0].appendChild(style);\n\n\t\tif (group)\n\t\t\t_style_element[group] = style;\n\t\telse\n\t\t\t_style_element[\"default\"] = style;\n\t}\n\n\tstyle.appendChild(document.createTextNode(rule));\n}\n\nexport function removeStyle(group){\n\tvar box = _style_element[group||\"default\"];\n\tif (box)\n\t\tbox.innerHTML = \"\";\n}\n\nexport function create(name,attrs,html){\n\tattrs = attrs || {};\n\tvar node = document.createElement(name);\n\tfor (var attr_name in attrs)\n\t\tnode.setAttribute(attr_name, attrs[attr_name]);\n\tif (attrs.style)\n\t\tnode.style.cssText = attrs.style;\n\tif (attrs[\"class\"])\n\t\tnode.className = attrs[\"class\"];\n\tif (html)\n\t\tnode.innerHTML = html;\n\treturn node;\n}\n\n//return node value, different logic for different html elements\nexport function getValue(node){\n\tnode = toNode(node);\n\tif (!node) return \"\";\n\treturn isUndefined(node.value) ? node.innerHTML : node.value;\n}\n\n//remove html node, can process an array of nodes at once\nexport function remove(node){\n\tif (node instanceof Array)\n\t\tfor (var i=0; i < node.length; i++)\n\t\t\tremove(node[i]);\n\telse if (node && node.parentNode)\n\t\tnode.parentNode.removeChild(node);\n}\n\n//insert new node before sibling, or at the end if sibling doesn't exist\nexport function insertBefore(node,before,rescue){\n\tif (!node) return;\n\tif (before && before.parentNode)\n\t\tbefore.parentNode.insertBefore(node, before);\n\telse\n\t\trescue.appendChild(node);\n}\n\n//return custom ID from html element \n//will check all parents starting from event's target\nexport function locate(e,id){\n\tvar trg;\n\tif (e.tagName)\n\t\ttrg = e;\n\telse {\n\t\ttrg = e.target;\n\t}\n \n\twhile (trg){\n\t\tif (trg.getAttribute){\t//text nodes has not getAttribute\n\t\t\tvar test = trg.getAttribute(id);\n\t\t\tif (test) return test;\n\t\t}\n\t\ttrg=trg.parentNode;\n\t}\t\n\treturn null;\n}\n\n//returns position of html element on the page\nexport function offset(elem) {\n\tconst box = elem.getBoundingClientRect();\n\tconst body = document.body;\n\tconst docElem = document.documentElement;\n\tconst scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;\n\tconst scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;\n\tconst clientTop = docElem.clientTop || body.clientTop || 0;\n\tconst clientLeft = docElem.clientLeft || body.clientLeft || 0;\n\tconst top = box.top + scrollTop - clientTop;\n\tconst left = box.left + scrollLeft - clientLeft;\n\treturn { y:Math.round(top), x:Math.round(left), width:elem.offsetWidth, height:elem.offsetHeight };\n}\n\n//returns relative position of event\nexport function posRelative(ev){\n\treturn { x:ev.offsetX, y:ev.offsetY };\n}\n\n//returns position of event\nexport function pos(ev){\n\tif (!ev.type)\t// webix touch event\n\t\treturn {x:ev.x, y:ev.y};\n\n\tif (ev.touches && ev.touches[0])\n\t\tev = ev.touches[0];\n\n\treturn {x:ev.pageX, y:ev.pageY};\n}\n\n//prevent event action\nexport function preventEvent(e){\n\te.preventDefault();\n\treturn stopEvent(e);\n}\n\n//stop event bubbling\nexport function stopEvent(e){\n\te.stopPropagation();\n\treturn false;\n}\n\nexport function triggerEvent(node, type, name, details){\n\tlet event;\n\tif (typeof(window[type]) === \"function\") {\n\t\tdetails = extend(details||{}, { bubbles:true, cancelable:true });\n\t\tevent = new window[type](name, details);\n\t} else {\t\t//IE 11 support\n\t\tevent = document.createEvent(type);\n\t\tevent.initEvent(name, true, true);\n\t}\n\tnode.dispatchEvent(event);\n}\n\n//add css class to the node\nexport function addCss(node,name,check){\n\tif (!check || node.className.indexOf(name) === -1)\n\t\tnode.className += \" \"+name;\n}\n\n//remove css class from the node\nexport function removeCss(node,name){\n\tnode.className = node.className.replace(RegExp(\" \"+name,\"g\"),\"\");\n}\n\nexport function getTextSize(text, css, basewidth){\n\tconst d = create(\"DIV\",{\"class\":\"webix_view webix_measure_size \"+(css||\"\")},\"\");\n\td.style.cssText = \"height:auto;visibility:hidden; position:absolute; top:0px; left:0px; overflow:hidden;\"+(basewidth?(\"width:\"+basewidth+\"px;\"):\"width:auto;white-space:nowrap;\");\n\tdocument.body.appendChild(d);\n\n\tconst all = (typeof text !== \"object\") ? [text] : text;\n\tlet width = 0, height = 0;\n\n\tfor (let i=0; i v.brand.indexOf(browsers[browser]) != -1);\n\n\tif(checkBrowser){\n\t\tenv[\"is\"+browser] = true;\n\t\t//Edge is a chromium-based browser (so we set isChromium:true and isEdge:true)\n\t\tif(browser != \"Chromium\")\n\t\t\tbreak;\n\t}\n}\n\nconst platform = deprecatedAgent || agent.platform;\nenv.isMac = platform.toLowerCase().indexOf(\"mac\") != -1;\nif (/iPad|iPhone|iPod/.test(platform)) env.isIOS = true;\nif (platform.indexOf(\"Android\") != -1) env.isAndroid = true;\n\nif(deprecatedAgent){\n\tif(env.isIOS || env.isAndroid || deprecatedAgent.indexOf(\"Mobile\") != -1 || deprecatedAgent.indexOf(\"Windows Phone\") != -1)\n\t\tenv.mobile = true;\n} else\n\tenv.mobile = agent.mobile;\n\nif (env.mobile || navigator.maxTouchPoints > 1)\n\tenv.touch = true;\n\nenv.fastClick = !env.touch;\n\n//maximum height/width for HTML elements in pixels (rough), bigger values will be ignored by browser\nif (env.isIE || env.isEdge || env.isFF)\n\tenv.maxHTMLElementSize = 10000000;\nif (env.isSafari)\n\tenv.maxHTMLElementSize = 100000000;\n\nenv.transform = \"transform\";\nenv.transition = \"transition\";\nenv.transitionDuration = \"transitionDuration\";\nenv.translate = \"translate3d\";\nenv.transitionEnd = \"transitionend\";\n\n//touch events that can be prevented\nenv.passiveEventListeners = false;\ntry {\n\tconst opts = Object.defineProperty({}, \"passive\", {\n\t\tget: function() { // eslint-disable-line\n\t\t\tenv.passiveEventListeners = true;\n\t\t}\n\t});\n\twindow.addEventListener(\"testPassive\", null, opts);\n\twindow.removeEventListener(\"testPassive\", null, opts);\n} catch (e) {} // eslint-disable-line\n\nenv.svg = (function(){\n\treturn document.implementation.hasFeature(\"http://www.w3.org/TR/SVG11/feature#BasicStructure\", \"1.1\");\n})();\n\nenv.svganimation = (function(){\n\treturn document.implementation.hasFeature(\"https://www.w3.org/TR/SVG11/feature#SVG-animation\", \"1.1\");\n})();\n\nexport default env;","import {extend, bind, isDate, isUndefined} from \"../../webix/helpers\";\nimport env from \"../../webix/env\";\n\nimport Promise from \"../../thirdparty/promiz\";\nimport i18n from \"../../webix/i18n\";\n\nimport require from \"../require\";\nimport jsarray from \"./jsarray\";\n\n\nconst excel = extend({\n\ttoObject:function(data){\n\t\tif(!data.excel){\n\t\t\tvar opts = data.options || {};\n\t\t\tif (opts.dataurl) \n\t\t\t\textend(opts, this._urlToOptions(opts.dataurl));\n\n\t\t\tdata = data.data || data;\n\t\t\tvar promise = Promise.defer();\n\n\t\t\tif(data.name){ //file\n\t\t\t\topts.ext = data.name.split(\".\").pop();\n\t\t\t\tvar reader = new FileReader();\n\n\t\t\t\treader.onload = bind(function (e) {\n\t\t\t\t\tpromise.resolve(this.parseData(e.target.result, opts));\n\t\t\t\t}, this);\n\t\t\t\treader.readAsArrayBuffer(data);\n\t\t\t}\n\t\t\telse //arraybuffer\n\t\t\t\tpromise.resolve(this.parseData(data, opts));\n\n\t\t\treturn promise;\n\t\t}\n\t\t//plain jsarray or hash\n\t\treturn data;\n\t},\n\tparseData:function(data, options){\n\t\tdata = new Uint8Array(data);\n\t\tconst arr = [];\n\t\tfor(let i = 0; i != data.length; ++i)\n\t\t\tarr[i] = String.fromCharCode(data[i]);\n\n\t\tlet ext = (options.ext || options).toLowerCase();\n\t\tif (ext != \"xls\") ext = \"xlsx\";\n\t\treturn require(env.cdn + \"/extras/xlsx.core.styles.min.js\").then(bind(function(){\n\t\t\t/* global XLS, XLSX */\n\t\t\tconst wb = (ext == \"xls\" ? XLS : XLSX).read(arr.join(\"\"), {\n\t\t\t\ttype: \"binary\",\n\t\t\t\tcellStyles: true,\n\t\t\t\tcellDates: isUndefined(options.cellDates) ? true : options.cellDates,\n\t\t\t\tsheetStubs: options.sheetStubs\n\t\t\t});\n\n\t\t\tconst book = wb.Workbook;\n\t\t\tconst res = {\n\t\t\t\tsheets: wb.Sheets,\n\t\t\t\tnames: wb.SheetNames,\n\t\t\t\toptions:options,\n\t\t\t\tranges: book ? (book.Names || []) : [],\n\t\t\t\tstates: book && book.Sheets ? book.Sheets.map(s => [\"visible\", \"hidden\", \"veryHidden\"][s.Hidden]) : wb.SheetNames.map(() => \"visible\")\n\t\t\t};\n\t\t\treturn extend(this.getSheet(res, options), res);\n\t\t}, this));\n\t},\n\tgetSheet:function(data, options){\n\t\tvar name = options.name || data.names[0];\n\t\tdata = this.sheetToArray(data.sheets[name], options);\n\t\tif(options.rows && options.rows.length)\n\t\t\tdata.data = data.data.splice(options.rows[0], Math.min(options.rows[1], data.data.length)-options.rows[0]);\n\t\treturn data;\n\t},\n\tsheetToArray:function(sheet, options){\n\t\tconst all = [];\n\t\tconst spans = [];\n\t\tconst styles = [];\n\t\tconst sizes = [];\n\t\tconst types = [];\n\t\tconst hidden = [];\n\n\t\tconst cellTypes = { n:\"number\", d:\"date\", s:\"string\", b:\"boolean\"};\n\n\t\tif(sheet && sheet[\"!ref\"]){\n\t\t\tvar range = XLS.utils.decode_range(sheet[\"!ref\"]), \n\t\t\t\trow, col, cellCoord, cell,\n\t\t\t\txCorrection = range.s.c,\n\t\t\t\tyCorrection = range.s.r+(options.rows?options.rows[0]:0);\n\n\t\t\tfor (row = range.s.r; row <= range.e.r; row++) {\n\t\t\t\tvar nrow = [];\n\t\t\t\tfor (col = range.s.c; col <= range.e.c; col++) {\n\t\t\t\t\tcellCoord = XLS.utils.encode_cell({ r: row, c: col });\n\t\t\t\t\tcell = sheet[cellCoord];\n\t\t\t\t\tif(!cell)\n\t\t\t\t\t\tnrow.push(\"\");\n\t\t\t\t\telse{\n\t\t\t\t\t\tvar ncell = \"\";\n\t\t\t\t\t\tif(options.math&&cell.f) // get formula\n\t\t\t\t\t\t\tncell = cell.f.charAt(0)==\"=\" ? cell.f : \"=\"+cell.f;\n\t\t\t\t\t\telse if (cell.t ==\"d\" && isDate(cell.v))\n\t\t\t\t\t\t\tncell = i18n.dateFormatStr(cell.v);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tncell = cell.v;\n\t\t\t\t\t\tnrow.push(ncell);\n\n\t\t\t\t\t\tif (cell.s)\n\t\t\t\t\t\t\tstyles.push([row-yCorrection, col-xCorrection, cell.s]);\n\t\t\t\t\t\tif (cell.t)\n\t\t\t\t\t\t\ttypes.push([row-yCorrection, col-xCorrection, cellTypes[cell.t]]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tall.push(nrow);\n\t\t\t}\n\n\t\t\tif(sheet[\"!merges\"]){\n\t\t\t\tvar merges = sheet[\"!merges\"];\n\t\t\t\tfor(let i = 0; i=0 && e.r-yCorrection<=options.rows[1]))\n\t\t\t\t\t\tspans.push([s.r-yCorrection, s.c-xCorrection, e.c-s.c+1, e.r-s.r+1]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(sheet[\"!cols\"]){\n\t\t\t\tvar widths = sheet[\"!cols\"];\n\t\t\t\tfor(let i = 0; i\": \">\",\n\t\"\\\"\": \""\",\n\t\"'\": \"'\",\n\t\"`\": \"`\"\n};\nvar badChars = /[&<>\"'`]/g;\nvar escapeChar = function(chr) {\n\treturn escape[chr] || \"&\";\n};\n\n\nfunction template(str){\n\tif (typeof str == \"function\") return str;\n\tif (_cache[str])\n\t\treturn _cache[str];\n\t\t\n\tstr=(str||\"\").toString();\t\t\t\n\tif (str.indexOf(\"->\")!=-1){\n\t\tvar teststr = str.split(\"->\");\n\t\tswitch(teststr[0]){\n\t\t\tcase \"html\": \t//load from some container on the page\n\t\t\t\tstr = getValue(teststr[1]);\n\t\t\t\tbreak;\n\t\t\tcase \"http\": \t//load from external file\n\t\t\t\tstr = new ajax().sync().get(teststr[1],{uid:uid()}).responseText;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t//do nothing, will use template as is\n\t\t\t\tbreak;\n\t\t}\n\t}\n\t\t\n\t//supported idioms\n\t// {obj.attr} => named attribute or value of sub-tag in case of xml\n\tstr=(str||\"\").toString();\t\t\n\n\t// Content Security Policy enabled\n\tif(env.strict){\n\t\tif (!_csp_cache[str]){\n\t\t\t_csp_cache[str] = [];\n\n\t\t\t// get an array of objects (not sorted by position)\n\t\t\tvar temp_res = [];\n\t\t\tstr.replace(/\\{obj\\.([^}?]+)\\?([^:]*):([^}]*)\\}/g,function(search,s1,s2,s3,pos){\n\t\t\t\ttemp_res.push({pos: pos, str: search, fn: function(obj){\n\t\t\t\t\treturn obj[s1]?s2:s3;\n\t\t\t\t}});\n\t\t\t});\n\t\t\tstr.replace(/\\{common\\.([^}(]*)\\}/g,function(search,s,pos){\n\t\t\t\ttemp_res.push({pos: pos, str: search, fn: function(_,common){\n\t\t\t\t\treturn common[s]||\"\";\n\t\t\t\t}});\n\t\t\t});\n\t\t\tstr.replace(/\\{common\\.([^}(]*)\\(\\)\\}/g,function(search,s,pos){\n\t\t\t\ttemp_res.push({pos: pos, str: search, fn: function(obj,common){\n\t\t\t\t\treturn (common[s]?common[s].apply(this, arguments):\"\");\n\t\t\t\t}});\n\t\t\t});\n\t\t\tstr.replace(/\\{obj\\.([^:}]*)\\}/g,function(search,s,pos){\n\t\t\t\ttemp_res.push({pos: pos, str: search, fn: function(obj){\n\t\t\t\t\treturn obj[s];\n\t\t\t\t}});\n\t\t\t});\n\t\t\tstr.replace(\"{obj}\",function(search,pos){\n\t\t\t\ttemp_res.push({pos: pos, str: search, fn: function(obj){\n\t\t\t\t\treturn obj;\n\t\t\t\t}});\n\t\t\t});\n\t\t\tstr.replace(/#([^#'\";, ]+)#/gi,function(search,s,pos){\n\t\t\t\tif(s.charAt(0)==\"!\"){\n\t\t\t\t\ts = s.substr(1);\n\t\t\t\t\ttemp_res.push({pos: pos, str: search, fn: function(obj){\n\t\t\t\t\t\tif(s.indexOf(\".\")!= -1)\n\t\t\t\t\t\t\tobj = CodeParser.collapseNames(obj); // apply complex properties\n\t\t\t\t\t\treturn template.escape(obj[s]);\n\t\t\t\t\t}});\n\t\t\t\t}\n\t\t\t\telse{\n\t\t\t\t\ttemp_res.push({pos: pos, str: search, fn: function(obj){\n\t\t\t\t\t\tif(s.indexOf(\".\")!= -1)\n\t\t\t\t\t\t\tobj = CodeParser.collapseNames(obj); // apply complex properties\n\t\t\t\t\t\treturn obj[s];\n\t\t\t\t\t}});\n\t\t\t\t}\n\n\t\t\t});\n\n\t\t\t// sort template parts by position\n\t\t\ttemp_res.sort(function(a,b){\n\t\t\t\treturn (a.pos > b.pos)?1:-1;\n\t\t\t});\n\n\t\t\t// create an array of functions that return parts of html string\n\t\t\tif(temp_res.length){\n\t\t\t\tvar lastPos = 0;\n\t\t\t\tvar addStr = function(str,n0,n1){\n\t\t\t\t\t_csp_cache[str].push(function(){\n\t\t\t\t\t\treturn str.slice(n0,n1);\n\t\t\t\t\t});\n\t\t\t\t};\n\t\t\t\tfor(var i = 0; i< temp_res.length; i++){\n\t\t\t\t\tvar pos = temp_res[i].pos;\n\t\t\t\t\taddStr(str,lastPos,pos);\n\t\t\t\t\t_csp_cache[str].push(temp_res[i].fn);\n\t\t\t\t\tlastPos = pos + temp_res[i].str.length;\n\t\t\t\t}\n\t\t\t\taddStr(str,lastPos,str.length);\n\t\t\t}\n\t\t\telse\n\t\t\t\t_csp_cache[str].push(function(){return str;});\n\t\t}\n\t\treturn function(){\n\t\t\tvar s = \"\";\n\t\t\tfor(var i=0; i < _csp_cache[str].length;i++){\n\t\t\t\ts += _csp_cache[str][i].apply(this,arguments);\n\t\t\t}\n\t\t\treturn s;\n\t\t};\n\t}\n\n\tlet helpers = false;\n\tstr=str.replace(slashes,\"\\\\\\\\\");\n\tstr=str.replace(newlines,\"\\\\n\");\n\tstr=str.replace(quotes,\"\\\\\\\"\");\n\n\tstr=str.replace(/\\{obj\\.([^}?]+)\\?([^:]*):([^}]*)\\}/g,\"\\\"+(obj.$1?\\\"$2\\\":\\\"$3\\\")+\\\"\");\n\tstr=str.replace(/\\{common\\.([^}(]*)\\}/g,\"\\\"+(common.$1||'')+\\\"\");\n\tstr=str.replace(/\\{common\\.([^}(]*)\\(\\)\\}/g,\"\\\"+(common.$1?common.$1.apply(this, arguments):\\\"\\\")+\\\"\");\n\tstr=str.replace(/\\{obj\\.([^}]*)\\}/g,\"\\\"+(obj.$1)+\\\"\");\n\tstr=str.replace(\"{obj}\",\"\\\"+obj+\\\"\");\n\tstr=str.replace(/#([^#'\";, ]+)#/gi,function(str, key){\n\t\tif (key.charAt(0)==\"!\"){\n\t\t\thelpers = true;\n\t\t\treturn \"\\\"+template.escape(obj.\"+key.substr(1)+\")+\\\"\";\n\t\t} else\n\t\t\treturn \"\\\"+(obj.\"+key+\")+\\\"\";\n\t});\n\n\ttry {\n\t\tif (helpers){\n\t\t\tconst temp = Function(\"obj\",\"common\",\"marks\", \"value\", \"template\", \"return \\\"\"+str+\"\\\";\");\n\t\t\t_cache[str] = function(a,b,c,d){ \n\t\t\t\treturn temp(a,b,c,d,template);\n\t\t\t};\n\t\t} else {\n\t\t\t_cache[str] = Function(\"obj\",\"common\",\"return \\\"\"+str+\"\\\";\");\n\t\t}\n\t} catch(e){\n\t\tassert(0, \"Invalid template:\"+str);\n\t}\n\n\treturn _cache[str];\n}\n\n\n\ntemplate.escape = function(str){\n\tif (str === undefined || str === null) return \"\";\n\treturn (str.toString() || \"\" ).replace(badChars, escapeChar);\n};\ntemplate.empty=function(){\treturn \"\";\t};\n\nexport default template;","import { assert } from \"./debug\";\nimport { toNode, uid, bind, isUndefined } from \"./helpers\";\nimport env from \"./env\";\n\n//hash of attached events\nconst _events = {};\n\nexport function _events_final_destructor(){\n\t//detach all known DOM events\n\tfor (var a in _events)\n\t\teventRemove(a);\n}\n\n//private version of API, do not register ID for event detaching\nexport function _event(a,b,c,d){\n\td = d || {};\n\td.inner = true;\n\tevent(a,b,c,d);\n}\n\n//attach event to the DOM element\nexport function event(node,event,handler,context){\n\tcontext = context || {};\n\tnode = toNode(node);\n\tassert(node, \"Invalid node as target for webix.event\");\n\t\n\tvar id = context.id || uid();\n\n\tif (context.bind)\n\t\thandler = bind(handler,context.bind);\n\n\tvar info = [node,event,handler,context.capture];\n\tif (!context.inner)\n\t\t_events[id] = info;\t//store event info, for detaching\n\n\tvar capture = !!context.capture;\n\tif (!isUndefined(context.passive) && env.passiveEventListeners)//blockable touch events\n\t\tcapture = { passive:context.passive, capture:capture };\n\t\t\n\tnode.addEventListener(event, handler, capture);\n\n\treturn id;\t//return id of newly created event, can be used in eventRemove\n}\n\n//remove previously attached event\nexport function eventRemove(id){\n\tif (!id) return;\n\tassert(_events[id],\"Removing non-existing event\");\n\n\tconst ev = _events[id];\n\tev[0].removeEventListener(ev[1], ev[2], !!ev[3]);\n\n\tdelete _events[id];\t//delete all traces\n}\n","import {assert} from \"../webix/debug\";\n\nimport {uid, isArray, toNode, isUndefined, toFunctor} from \"../webix/helpers\";\nimport {attachEvent} from \"../webix/customevents\";\nimport {locate} from \"../webix/html\";\nimport {use} from \"../services\";\n\nimport type from \"../webix/type\";\nimport state from \"../core/state\";\n\n//global click events for UI\nimport \"./click\";\n\nconst views = {};\n\nfunction ui(config, parent, id){\n\tvar res;\n\tstate._ui_creation++;\n\t// save old value of global scope\n\tconst temp_scope = state._global_scope;\n\t// save old value of global collection\n\tconst temp_collection = state._global_collection;\n\t// set global scope to the scope of new UI or to previous value\n\t// as result inner webix.ui calls will have access the scope of master view\n\t// mainly necessary for suggests\n\tstate._global_scope = config.$scope || temp_scope;\n\ttry {\n\t\tres = _ui_creator(config, parent, id);\n\t} finally {\n\t\tstate._ui_creation--;\n\t\t// restore global scope\n\t\tstate._global_scope = temp_scope;\n\t\t// restore global collection\n\t\t// if an error occurred while creating the isolated layout\n\t\tstate._global_collection = temp_collection;\n\t}\n\treturn res;\n}\nui.views = views;\n\n\nfunction _ui_creator(config, parent, id){\n\tvar multiset = isArray(config);\n\tvar node = toNode((config.container||parent)||document.body);\n\n\t// solve problem with non-unique ids\n\tif(node._settings)\n\t\tid = _correctId(node, multiset, id);\n\n\tvar top_node;\n\tvar moving = false;\n\tvar body_child = (node == document.body);\n\tif (config._settings || (node && multiset)){\n\t\ttop_node = config;\n\t\tmoving = true;\n\t} else {\n\t\tif (node && body_child)\n\t\t\tconfig.$topView = true;\n\t\tif (!config._inner)\n\t\t\tconfig._inner = {};\n\n\t\tif (parent && parent.getParentView){\n\t\t\tstate._parent_cell = (!id && id!==0) ? parent.getParentView() : parent;\n\t\t}\n\n\t\ttop_node = _view(config);\n\t}\n\n\tif (body_child && !top_node.setPosition && !top_node.$apiOnly)\n\t\tuse(\"fixHeight\")();\n\n\tif (top_node._settings && top_node._settings._hidden && !node.$view){\n\t\ttop_node._settings._container = node;\n\t} else if (!top_node.$apiOnly){\n\t\tif (node.appendChild)\n\t\t\t_appendDom(node, top_node, config);\n\t\telse if (node.destructor){\n\t\t\tvar target = node;\n\n\t\t\t//addView or view moving with target id\n\t\t\tif (!id && id!==0 && !isArray(top_node)){\n\t\t\t\tid = node;\n\t\t\t\tnode = node.getParentView();\n\t\t\t}\n\n\t\t\t//if target supports view adding\n\t\t\tif (node && node._replace){\n\t\t\t\tif (moving && top_node.getParentView){\n\t\t\t\t\t//if source supports view removing\n\t\t\t\t\tlet parent = top_node.getParentView();\n\t\t\t\t\tif (parent && parent._remove){\n\t\t\t\t\t\tparent._remove(top_node);\n\t\t\t\t\t}\n\t\t\t\t\t//adjust parent link and scope\n\t\t\t\t\ttop_node._parent_cell = node;\n\t\t\t\t\ttop_node.$scope = node.$scope;\n\t\t\t\t}\n\n\t\t\t\tnode._replace(top_node, id);\n\t\t\t} else {\n\t\t\t\tlet parent = target.$view.parentNode;\n\t\t\t\ttarget.destructor();\n\t\t\t\t_appendDom(parent, top_node, config);\n\t\t\t}\n\t\t} else\n\t\t\tassert(0, \"Not existing parent:\"+config.container);\n\t}\n\n\treturn top_node;\n}\n\nfunction _appendDom(node, top_node, config){\n\tnode.appendChild(top_node._viewobj);\n\tif (top_node.getParentView()) return;\n\n\t//resize window with position center or top\n\t//do not resize other windows and elements\n\t// which are attached to custom html containers\n\tif (((!top_node.setPosition || top_node._settings.fullscreen) && node == document.body) || top_node._settings.position )\n\t\tstate.top_views.push(top_node._destructor_handler);\n\tif (!config.skipResize)\n\t\ttop_node.adjust();\n}\n\nfunction _correctId(target, multiset, id){\n\t//replace view\n\tvar views = [target];\n\t//replace content of layout\n\tif (multiset)\n\t\tviews = target.getChildViews();\n\t//replace content of window\n\telse if (target._body_cell)\n\t\tviews = [target._body_cell];\n\t//add cell in layout by number\n\telse if (typeof id == \"number\"){\n\t\treturn id;\n\t//replace cell in layout by id\n\t} else if (id){\n\t\tviews = [$$(id)];\n\t\t_deleteIds(views);\n\t\treturn views[0].config.id;\n\t}\n\n\t_deleteIds(views);\n\treturn id;\n}\n\nfunction _deleteIds(uis){\n\tfor (var i = uis.length - 1; i >= 0; i--){\n\t\tlet current = uis[i];\n\t\t//remove original id\n\t\tdelete views[current.config.id];\n\t\t//create temp id\n\t\tcurrent.config.id = \"x\"+uid();\n\t\tviews[current.config.id] = current;\n\t\t//process childs\n\t\tif (current.getChildViews)\n\t\t\t_deleteIds(current.getChildViews());\n\t\t//process related UI\n\t\tif (current._destroy_with_me)\n\t\t\t_deleteIds(current._destroy_with_me);\n\t}\n}\n\n\nfunction _view(config){\n\n\tif (DEBUG){\n\t\t// check for trailing comma\n\t\tvar coll = config.cells || config.rows || config.elements || config.cols;\n\t\tif (coll)\n\t\t\tfor (let i=0; i0; i--) {\n\t\tassert(origins[i],\"Invalid mixing source\");\n\t\tif (typeof origins[i]== \"function\")\n\t\t\torigins[i]=origins[i].prototype;\n\t\tif (origins[i].$init) \n\t\t\tconstruct.push(origins[i].$init);\n\t\tif (origins[i].defaults){ \n\t\t\tvar defaults = origins[i].defaults;\n\t\t\tif (!compilation.defaults)\n\t\t\t\tcompilation.defaults = {};\n\t\t\tfor (let def in defaults)\n\t\t\t\tif (isUndefined(compilation.defaults[def]))\n\t\t\t\t\tcompilation.defaults[def] = defaults[def];\n\t\t}\n\t\tif (origins[i].type && compilation.type){\n\t\t\tfor (let def in origins[i].type)\n\t\t\t\tif (!compilation.type[def])\n\t\t\t\t\tcompilation.type[def] = origins[i].type[def];\n\t\t}\n\t\t\t\n\t\tfor (var key in origins[i]){\n\t\t\tif (!compilation[key] && compilation[key] !== false)\n\t\t\t\tcompilation[key] = origins[i][key];\n\t\t}\n\t}\n\t\n\tif (has_constructor)\n\t\tconstruct.push(compilation.$init);\n\t\n\t\n\tcompilation.$init = function(){\n\t\tfor (var i=0; i 0 && message.keyboard){\n\t\tconst code = e.which || e.keyCode;\n\t\tif(code != 13 && code != 32 && code != 27)\n\t\t\treturn;\n\n\t\tlet activeBox;\n\n\t\tfor(let i = count - 1; i >= 0; i--){\n\t\t\tconst box = modalbox.pull[ order[i] ];\n\n\t\t\tif(box._box != source && box._box.contains(source) && code == 32) // ignore space inside input\n\t\t\t\treturn;\n\n\t\t\tif(box.container && box.container.contains(source)){\n\t\t\t\tactiveBox = box;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif(!activeBox)\n\t\t\tactiveBox = modalbox.pull[ order[order.length-1] ];\n\n\t\tif (code == 13 || code == 32)\n\t\t\tcallback(activeBox, true);\n\t\telse if (code == 27)\n\t\t\tcallback(activeBox, false);\n\n\t\tpreventEvent(e);\n\t\treturn !(e.cancelBubble = true);\n\t}\n}\n\nevent(document, \"keydown\", modal_key, { capture: true });\n\t\nfunction modality(mode, container){\n\tvar node = container || document.body;\n\tvar cover;\n\tif(isUndefined(node.modality)){\n\t\tcover = create(\"DIV\", {\n\t\t\t\"class\":\"webix_modal_cover\",\n\t\t\tstyle:\"position:\"+(container ? \"absolute\" : \"fixed\")+\";\"\n\t\t});\n\t\tcover.onkeydown = modal_key;\n\n\t\tif(container){\n\t\t\tvar position = window.getComputedStyle(container).position;\n\t\t\tif(position != \"fixed\" && position != \"absolute\" && position != \"sticky\" && position != \"relative\")\n\t\t\t\tnode.style.position = \"relative\";\n\t\t}\n\t\tnode.appendChild(cover);\n\t\tnode.modality = 1;\n\t}\n\telse\n\t\tmode ? node.modality ++ : node.modality --;\n\n\t//trigger visibility only if necessary\n\tif((mode && node.modality === 1) || node.modality === 0){\n\t\tcover = cover || Array.prototype.slice.call(node.querySelectorAll(\".webix_modal_cover\")).filter(el => el.parentNode == node)[0];\n\n\t\tif(cover){\n\t\t\tif(!node.modality){\n\t\t\t\tcover.style.display = \"none\";\n\t\t\t\tremoveCss(node, \"webix_modalbox_inside\");\n\t\t\t}\n\t\t\telse if(node.modality == 1){\n\t\t\t\tcover.style.display = \"inline-block\";\n\t\t\t\taddCss(node, \"webix_modalbox_inside\");\n\t\t\t}\n\t\t}\n\t}\n\treturn cover;\n}\n\nfunction button(text, result, className){\n\treturn \"
\"+text+\"
\";\n}\n\nfunction input(config){\n\treturn \"
\";\n}\n\nfunction info(text){\n\tif (!t.area){\n\t\tt.area = document.createElement(\"DIV\");\n\t\tt.area.className = \"webix_message_area\";\n\t\tt.area.style[t.position]=\"5px\";\n\t\t\n\t\tdocument.body.appendChild(t.area);\n\t}\n\tt.area.setAttribute(\"role\", \"alert\");\n\tt.area.setAttribute(\"aria-atomic\", true);\n\tt.hide(text.id);\n\tvar message = document.createElement(\"DIV\");\n\tmessage.innerHTML = \"
\"+text.text+\"
\";\n\tmessage.className = \"webix_message webix_\" + text.type;\n\tmessage.onclick = function(){\n\t\tif (text) t.hide(text.id);\n\t\ttext = null;\n\t};\n\n\tif (t.position == \"bottom\" && t.area.firstChild)\n\t\tt.area.insertBefore(message,t.area.firstChild);\n\telse\n\t\tt.area.appendChild(message);\n\t\n\tif (text.expire > 0)\n\t\tt.timers[text.id]=window.setTimeout(function(){\n\t\t\tt.hide(text.id);\n\t\t}, text.expire);\n\n\t//styling for animation\n\tmessage.style.height = message.offsetHeight-2+\"px\";\n\n\tt.pull[text.id] = message;\n\tmessage = null;\n\n\treturn text.id;\n}\nfunction _boxStructure(config, ok, cancel, hasInput){\n\tvar box = document.createElement(\"DIV\");\n\tvar css = config.css ? \" \"+config.css : \"\";\n\tbox.className = \"webix_modal_box webix_\"+config.type+css;\n\tbox.setAttribute(\"webixbox\", 1);\n\tbox.setAttribute(\"role\", \"alertdialog\");\n\tbox.setAttribute(\"aria-label\", config.title || \"\");\n\tbox.setAttribute(\"tabindex\", \"0\");\n\n\tvar inner = \"\";\n\tif (config.width)\n\t\tbox.style.width = config.width+(rules.isNumber(config.width)?\"px\":\"\");\n\tif (config.height)\n\t\tbox.style.height = config.height+(rules.isNumber(config.height)?\"px\":\"\");\n\tif (config.title)\n\t\tinner += \"
\"+config.title+\"
\";\n\tinner += \"
\"+(config.content?\"\":(config.text || \"\"))+\"
\";\n\tinner += \"
\";\n\tif (hasInput)\n\t\tinner += input(config.input);\n\tif (cancel)\n\t\tinner += button(config.cancel || i18n.message.cancel, false);\n\tif (ok)\n\t\tinner += button(config.ok || i18n.message.ok, true,\"confirm\");\n\tif (config.buttons && !ok && !cancel){\n\t\tfor (var i=0; i\";\n\tbox.innerHTML = inner;\n\n\tif (config.content){\n\t\tvar node = config.content;\n\t\tif (typeof node == \"string\") \n\t\t\tnode = document.getElementById(node);\n\t\tif (node.style.display == \"none\")\n\t\t\tnode.style.display = \"\";\n\t\tbox.childNodes[config.title?1:0].appendChild(node);\n\t}\n\n\tif (config.type.indexOf(\"prompt\") != -1){\n\t\tconst inputBox = box.querySelector(\".webix_popup_input\");\n\t\tconst input = inputBox.querySelector(\"input\");\n\t\tinput.oninput = function(){\n\t\t\tif (config.input.invalid){\n\t\t\t\tremoveCss(inputBox, \"webix_popup_invalid\");\n\t\t\t\tconfig.input.invalid = false;\n\t\t\t}\n\t\t};\n\t}\n\n\tbox.onclick = function(e){\n\t\tvar source = e.target;\n\t\tif (!source.className) source = source.parentNode;\n\t\tif (source.className.indexOf(\"webix_popup_button\")!=-1){\n\t\t\tlet result = source.getAttribute(\"result\");\n\t\t\tresult = (result == \"true\")||(result == \"false\"?false:result);\n\t\t\tcallback(config, result);\n\t\t}\n\t\te.cancelBubble = true;\n\t};\n\tconfig._box = box;\n\treturn box;\n}\n\nmodalbox.pull = {};\nmodalbox.order = [];\n\nfunction _createBox(config, ok, cancel, hasInput){\n\tconst box = config.tagName ? config : _boxStructure(config, ok, cancel, hasInput);\n\tconst container = config.container;\n\n\tconst containerWidth = container ? container.offsetWidth : (window.innerWidth||document.documentElement.offsetWidth);\n\tconst containerHeight = container ? container.offsetHeight : (window.innerHeight||document.documentElement.offsetHeight);\n\tconst containerLeft = container ? container.scrollLeft : 0;\n\tconst containerTop = container ? container.scrollTop : 0;\n\n\tif(config.container)\n\t\tbox.style.position = \"absolute\";\n\n\ttoNode((config.container || document.body).appendChild(box));\n\tconst cover = modality(true, config.container);\n\n\tconst x = config.left||Math.abs(containerLeft+Math.floor((containerWidth - box.offsetWidth)/2));\n\tconst y = config.top||Math.abs(containerTop+Math.floor((containerHeight - box.offsetHeight)/2));\n\tif (config.position == \"top\")\n\t\tbox.style.top = \"-3px\";\n\telse{\n\t\tbox.style.top = y+\"px\";\n\t\tif(cover){\n\t\t\tcover.style.top = containerTop+\"px\";\n\t\t\tcover.style.left = containerLeft+\"px\";\n\t\t}\n\t}\n\tbox.style.left = x+\"px\";\n\t//necessary for IE only\n\tbox.onkeydown = modal_key;\n\n\tif(hasInput)\n\t\tbox.querySelector(\".webix_popup_input input\").focus();\n\telse\n\t\tbox.focus();\n\n\tif (!config.id)\n\t\tconfig.id = _uid(\"modalbox\");\n\telse if(modalbox.pull[config.id]){\n\t\tmodalbox.hide(config.id);\n\t}\n\n\tmodalbox.order.push(config.id);\n\tmodalbox.pull[config.id] = config;\n\n\tconfig._promise = Promise.defer();\n\treturn config._promise;\n}\n\nfunction alertPopup(config){\n\treturn _createBox(config, true);\n}\nfunction confirmPopup(config){\n\treturn _createBox(config, true, true);\n}\nfunction boxPopup(config){\n\treturn _createBox(config);\n}\nfunction promptPopup(config){\n\treturn _createBox(config, true, true, true);\n}\nfunction box_params(text, type, callback){\n\tif (typeof text != \"object\"){\n\t\tif (typeof type == \"function\"){\n\t\t\tcallback = type;\n\t\t\ttype = \"\";\n\t\t}\n\t\ttext = {text:text, type:type, callback:callback };\n\t}\n\treturn text;\n}\nfunction params(text, type, expire, id){\n\tif (typeof text != \"object\")\n\t\ttext = {text:text, type:type, expire:expire, id:id};\n\ttext.id = text.id||_uid(\"message\");\n\ttext.expire = text.expire||t.expire;\n\treturn text;\n}\nexport function alert(){\n\tvar text = box_params.apply(this, arguments);\n\ttext.type = text.type || \"alert\";\n\treturn alertPopup(text);\n}\nexport function confirm(){\n\tvar text = box_params.apply(this, arguments);\n\ttext.type = text.type || \"confirm\";\n\treturn confirmPopup(text);\n}\n\nexport function modalbox(){\n\tvar text = box_params.apply(this, arguments);\n\ttext.type = text.type || \"alert\";\n\treturn boxPopup(text);\n}\n\nexport function prompt(){\n\tvar text = box_params.apply(this, arguments);\n\ttext.type = text.type || \"prompt\";\n\ttext.input = text.input || {};\n\treturn promptPopup(text);\n}\n\nmodalbox.hide = function(id){\n\tif(id && modalbox.pull[id]){\n\t\tvar node = modalbox.pull[id]._box;\n\t\tif(node){\n\t\t\tnode.parentNode.removeChild(node);\n\t\t\tmodalbox.order.splice(modalbox.order.indexOf(id), 1);\n\t\t\tmodality(false, modalbox.pull[id].container);\n\t\t\tdelete modalbox.pull[id];\n\t\t}\n\t}\n};\n\nmodalbox.hideAll = function(){\n\tfor (var id in modalbox.pull){\n\t\tthis.hide(id);\n\t}\n};\n\nexport function message(text, type, expire, id){ //eslint-disable-line\n\ttext = params.apply(this, arguments);\n\ttext.type = text.type||\"info\";\n\n\tvar subtype = text.type.split(\"-\")[0];\n\tswitch (subtype){\n\t\tcase \"alert\":\n\t\t\treturn alertPopup(text);\n\t\tcase \"confirm\":\n\t\t\treturn confirmPopup(text);\n\t\tcase \"modalbox\":\n\t\t\treturn boxPopup(text);\n\t\tcase \"prompt\":\n\t\t\treturn promptPopup(text);\n\t\tdefault:\n\t\t\treturn info(text);\n\t}\n}\n\nvar t = message;\nt.expire = 4000;\nt.keyboard = true;\nt.position = \"top\";\nt.pull = {};\nt.timers = {};\n\nt.hideAll = function(){\n\tfor (var key in t.pull)\n\t\tt.hide(key);\n};\nt.hide = function(id){\n\tvar obj = t.pull[id];\n\tif (obj && obj.parentNode){\n\t\twindow.setTimeout(function(){\n\t\t\tobj.parentNode.removeChild(obj);\n\t\t\tobj = null;\n\t\t},2000);\n\t\t//styling for animation\n\t\tobj.style.height = 0;\n\t\tobj.className+=\" hidden\";\n\t\tt.area.removeAttribute(\"role\");\n\t\t\n\t\tif(t.timers[id])\n\t\t\twindow.clearTimeout(t.timers[id]);\n\t\tdelete t.pull[id];\n\t}\n};\n\n//override circualr dependencies\ndefine(\"message\", message);\nexport default modalbox;","import ready from \"../webix/ready\";\n\nimport {assert} from \"../webix/debug\";\nimport {event} from \"../webix/htmlevents\";\nimport {delay,uid,_power_array,isUndefined,isArray} from \"../webix/helpers\";\nimport {callEvent} from \"../webix/customevents\";\nimport {locate,preventEvent} from \"../webix/html\";\nimport {modalbox} from \"../webix/message\";\nimport fullscreen from \"../webix/fullscreen\";\n\nimport {$$} from \"../ui/core\";\nimport state from \"../core/state\";\n\nimport {define} from \"../services\";\n\n\nconst UIManager = {\n\t_view: null,\n\t_hotkeys: {},\n\t_focus_time:0,\n\t_controls: {\n\t\t\"esc\": \"escape\",\n\t\t\"up\": \"arrowup\",\n\t\t\"down\": \"arrowdown\",\n\t\t\"left\": \"arrowleft\",\n\t\t\"right\": \"arrowright\",\n\t\t\"pgdown\": \"pagedown\",\n\t\t\"pgup\": \"pageup\",\n\t\t\"space\": \" \",\n\t\t\"multiply\": \"*\",\n\t\t\"add\": \"+\",\n\t\t\"subtract\": \"-\",\n\t\t\"decimal\": \".\",\n\t\t\"divide\": \"/\",\n\t\t\"pausebreak\":\"pause\",\n\t\t\"5numlocked\":\"clear\"\n\t},\n\t_inputs:{\n\t\t\"input\": 1,\n\t\t\"button\":1,\n\t\t\"textarea\":1,\n\t\t\"select\":1\n\t},\n\t_enable: function() {\n\t\t// attaching events here\n\t\tevent(document, \"keydown\", this._keypress, { bind:this });\n\t\tevent(document, \"compositionstart\", ()=> this._startComposition());\n\t\tevent(document, \"compositionend\", ()=> this._endComposition());\n\t\tevent(document.body, \"click\", this._focus_click, { capture:true, bind:this });\n\t\tevent(document.body, \"focus\", this._focus_tab, { capture:true, bind:this });\n\n\t\tstate.destructors.push({obj:this});\n\t},\n\t_startComposition: function(){\n\t\tclearTimeout(this._composition);\n\t\tthis._composition = true;\n\t},\n\t_endComposition: function(){\n\t\t//in some browsers compositionEnd fires before the keyDown event\n\t\tthis._composition = delay(() => delete this._composition);\n\t},\n\tdestructor: function(){\n\t\tUIManager._view = null;\n\t},\n\tgetFocus: function() {\n\t\treturn this._view;\n\t},\n\t_focus_action:function(view){\n\t\tthis._focus_was_there = this._focus_was_there || view._settings.id;\n\t},\n\tsetFocus: function(view, only_api, tab){\n\t\t//view can be empty\n\t\tview = $$(view);\n\t\t//unfocus if view is hidden\n\t\tif (view && !view.$view) view = null;\n\n\t\t//store last click time, it is necessary to prevent refocusing\n\t\t//for example when user moves focus from onclick handler somewher\n\t\t//and we want to prevent autofocusing, when event will reach document.body\n\t\tthis._focus_time = state._focus_time = new Date();\n\n\t\tif (this._view === view) return true;\n\t\tif (this._view && this._view.callEvent)\n\t\t\tthis._view.callEvent(\"onBlur\", [this._view]);\n\n\t\tif (view && view.callEvent){\n\t\t\tview.callEvent(\"onFocus\", [view, this._view]);\n\t\t\tif(tab) view.callEvent(\"onTabFocus\", [view, this._view]);\n\t\t}\n\t\tcallEvent(\"onFocusChange\", [view, this._view]);\n\n\t\tif (this._view && this._view.blur && !only_api) this._view.blur();\n\t\tthis._view = view;\n\t\tif (view && view.focus && !only_api) view.focus();\n\t\treturn true;\n\t},\n\tapplyChanges: function(element){\n\t\tvar view = this.getFocus();\n\t\tif (view && view != element && view._applyChanges)\n\t\t\tview._applyChanges(element);\n\t},\n\thasFocus: function(view) {\n\t\treturn (view === this._view) ? true : false;\n\t},\n\t_focus: function(e){\n\t\tfor(let i = 0; i < modalbox.order.length; i++){\n\t\t\tif(modalbox.pull[ modalbox.order[i] ]._box.contains(e.target))\n\t\t\t\treturn;\n\t\t}\n\n\t\tvar view = locate(e, /*@attr*/\"view_id\") || this._focus_was_there;\n\n\t\t//if html was repainted we can miss the view, so checking last processed one\n\t\tview = $$(view);\n\t\tthis._focus_was_there = null;\n\n\t\t//set timer, to fix issue with Android input focusin\n\t\tstate._focus_time = new Date();\n\n\t\tif (view == this._view) return true;\n\n\t\tif (view){\n\t\t\tif (this.canFocus(view)){\n\t\t\t\t// keep form focus\n\t\t\t\tif (this._view && this._view.getFormView() == view && this._view.focus)\n\t\t\t\t\tthis._view.focus();\n\t\t\t\telse{\n\t\t\t\t\t//radio view with scroll: focus changes onClick event target into radiogroup, so we need call onClick before it happens\n\t\t\t\t\tif(e.target.type == \"radio\" || e.target.getAttribute(\"role\") == \"radio\")\n\t\t\t\t\t\tcallEvent(\"onClick\", [e]);\n\n\t\t\t\t\tthis.setFocus(view);\n\t\t\t\t}\n\t\t\t}\n\t\t\t//remove focus from an unreachable view\n\t\t\telse if (view.$view.contains(e.target))\n\t\t\t\te.target.blur();\n\t\t}\n\t\telse this.setFocus(null);\n\n\t\treturn true;\n\t},\n\t_focus_click:function(e){\n\t\t// if it was onfocus/onclick less then 100ms behore then we ignore it\n\t\tif ((new Date())-this._focus_time < 100) {\n\t\t\tthis._focus_was_there = null;\n\t\t\treturn false;\n\t\t}\n\t\treturn this._focus(e);\n\t},\n\t_focus_tab: function(e){\n\t\tif(!this._inputs[e.target.nodeName.toLowerCase()])\n\t\t\treturn false;\n\t\treturn this._focus(e);\n\t},\n\t_top_modal: function(view){\n\t\tconst modality = state._modality;\n\t\tif (!modality.length) return true;\n\n\t\tconst top = this._getTop(view);\n\t\treturn (top.$view.style.zIndex||0) >= Math.max(...modality);\n\t},\n\t_getTop: function(view){\n\t\tlet top = view.queryView(view => !view.getParentView(), \"parent\") || view;\n\n\t\tconst insideContainer = $$(top.$view.parentNode); //container inside view (like filter in query view list)\n\t\tif(insideContainer)\n\t\t\ttop = this._getTop(insideContainer);\n\n\t\treturn top;\n\t},\n\tcanFocus:function(view){\n\t\tif(document.body.modality || view.$view.modality || view.queryView(view => view.$view.modality, \"parent\")) //modalbox\n\t\t\treturn false;\n\t\treturn view.isVisible() && view.isEnabled() && !view.config.disabled && this._top_modal(view) && !view.queryView({disabled:true}, \"parent\");\n\t},\n\n\t_moveChildFocus: function(check_view){\n\t\tvar focus = this.getFocus();\n\t\t//we have not focus inside of closing item\n\t\tif (check_view && !this._is_child_of(check_view, focus))\n\t\t\treturn false;\n\n\t\tif (!this._focus_logic(\"getPrev\", check_view))\n\t\t\tthis._view = null;\n\t},\n\t_is_child_of: function(parent, child) {\n\t\tif (!parent) return false;\n\t\tif (!child) return false;\n\t\twhile (child) {\n\t\t\tif (child === parent) return true;\n\t\t\tchild = child.getParentView();\n\t\t}\n\t\treturn false;\n\t},\n\t_keypress_timed:function(){\n\t\tif (this && this.callEvent)\n\t\t\tthis.callEvent(\"onTimedKeyPress\",[]);\n\t},\n\t_keypress: function(e) {\n\t\tlet code = e.which || e.keyCode;\n\n\t\t// processing or not found\n\t\tif (code == 229 || code == 0) return;\n\n\t\t// numpad keys\n\t\tif (code > 95 && code < 106) code -= 48;\n\n\t\tconst view = this.getFocus();\n\t\tif (view && view.callEvent) {\n\t\t\tif (view.callEvent(\"onKeyPress\", [code, e]) === false)\n\t\t\t\tpreventEvent(e);\n\t\t\tif (view.hasEvent(\"onTimedKeyPress\")){\n\t\t\t\tclearTimeout(view._key_press_timeout);\n\t\t\t\tview._key_press_timeout = delay(this._keypress_timed, view, [], (view._settings.keyPressTimeout||250));\n\t\t\t}\n\t\t}\n\n\t\tif (this._check_keycode(e) === false) {\n\t\t\tpreventEvent(e);\n\t\t\treturn false;\n\t\t}\n\t},\n\n\t// dir - getNext or getPrev\n\t_focus_logic: function(dir, focus) {\n\t\tvar next = focus||this.getFocus();\n\t\tif(next){\n\t\t\tdir = dir || \"getNext\";\n\t\t\tvar start = next;\n\t\t\tvar marker = uid();\n\n\t\t\twhile (true) { // eslint-disable-line\n\t\t\t\tnext = this[dir](next);\n\t\t\t\t// view with focus ability\n\t\t\t\tif (next && this.canFocus(next))\n\t\t\t\t\treturn this.setFocus(next);\n\n\t\t\t\t// elements with focus ability not found\n\t\t\t\tif (next === start || next.$fmarker == marker){\n\t\t\t\t\tif(focus)\n\t\t\t\t\t\tdocument.activeElement.blur();\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t//prevents infinity loop\n\t\t\t\tnext.$fmarker = marker;\n\t\t\t}\n\t\t}\n\t},\n\t_tab_logic:function(view, e){\n\t\tvar mode = !e.shiftKey;\n\t\tif (view && view._custom_tab_handler && !view._custom_tab_handler(mode, e))\n\t\t\treturn false;\n\n\t\tif (view && view._in_edit_mode){\n\t\t\tif (view.editNext)\n\t\t\t\treturn view.editNext(mode);\n\t\t\telse if (view.editStop){\n\t\t\t\tview.editStop();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else\n\t\t\tdelay(function(){\n\t\t\t\tview = $$(document.activeElement);\n\t\t\t\tif(view && !UIManager.canFocus(view))\n\t\t\t\t\treturn UIManager._focus_logic(mode ? \"getNext\" : \"getPrev\", view);\n\t\t\t\tUIManager.setFocus(view, true, true);\n\t\t\t});\n\t},\n\tgetTop: function(id) {\n\t\tvar next, view = $$(id);\n\n\t\twhile (view && (next = view.getParentView()))\n\t\t\tview = next;\n\t\treturn view;\n\t},\n\n\tgetNext: function(view, _inner_call) {\n\t\tvar cells = view.getChildViews();\n\t\t//tab to first children\n\t\tif (cells.length && !_inner_call)\n\t\t\tfor (var i = 0; i < cells.length; i++)\n\t\t\t\tif(this.canFocus(cells[i]))\n\t\t\t\t\treturn cells[i];\n\n\t\t//unique case - single view without child and parent\n\t\tvar parent = view.getParentView();\n\t\tif (!parent)\n\t\t\treturn view;\n\n\t\tvar p_cells = parent.getChildViews();\n\t\tif (p_cells.length){\n\t\t\tvar index = _power_array.find.call(p_cells, view)+1;\n\t\t\twhile (index < p_cells.length) {\n\t\t\t\t//next visible child\n\t\t\t\tif (this.canFocus(p_cells[index])) \n\t\t\t\t\treturn p_cells[index];\n\n\t\t\t\tindex++;\n\t\t\t}\n\t\t} \n\n\t\t//sibling of parent\n\t\treturn this.getNext(parent, true);\n\t},\n\n\tgetPrev: function(view, _inner_call) {\n\t\tvar cells = view.getChildViews();\n\t\t//last child of last child\n\t\tif (cells.length && _inner_call)\n\t\t\tfor (var i = cells.length - 1; i >= 0; i--)\n\t\t\t\tif(this.canFocus(cells[i]))\n\t\t\t\t\treturn this.getPrev(cells[i], true);\n\n\t\tif (_inner_call && this.canFocus(view)) return view;\n\n\t\t//fallback from top to bottom\n\t\tvar parent = view.getParentView();\n\t\tif (!parent)\n\t\t\treturn this.canFocus(view) ? this.getPrev(view, true) : view;\n\n\t\tvar p_cells = parent.getChildViews();\n\t\tif (p_cells) {\n\t\t\tvar index = _power_array.find.call(p_cells, view)-1;\n\t\t\twhile (index >= 0) {\n\t\t\t\tif (this.canFocus(p_cells[index]))\n\t\t\t\t\treturn this.getPrev(p_cells[index], true);\n\t\t\t\tindex--;\n\t\t\t}\n\t\t}\n\n\t\treturn this.getPrev(parent, true);\n\t},\n\taddHotKey: function(keys, handler, view) {\n\t\tassert(handler, \"Hot key handler is not defined\");\n\t\tconst code = this._parse_keys(keys);\n\n\t\tif (!view) view = null;\n\t\tif (!this._hotkeys[code]) this._hotkeys[code] = [];\n\t\tthis._hotkeys[code].push({ handler, view });\n\n\t\treturn keys;\n\t},\n\tremoveHotKey: function(keys, func, view){\n\t\tconst code = this._parse_keys(keys);\n\t\tif (!func && !view)\n\t\t\tdelete this._hotkeys[code];\n\t\telse {\n\t\t\tvar t = this._hotkeys[code];\n\t\t\tif (t){\n\t\t\t\tfor (var i = t.length - 1; i >= 0; i--) {\n\t\t\t\t\tif (view && t[i].view !== view) continue;\n\t\t\t\t\tif (func && t[i].handler !== func) continue;\n\t\t\t\t\tt.splice(i,1);\n\t\t\t\t}\n\t\t\t\tif (!t.length)\n\t\t\t\t\tdelete this._hotkeys[code];\n\t\t\t}\n\n\t\t}\n\t},\n\t_keycode: function(key, ctrl, shift, alt, meta) {\n\t\t//key can be undefined (browser autofill)\n\t\treturn (key||\"\").toLowerCase()+\"_\"+[\"\", (ctrl ? \"1\" : \"0\"), (shift ? \"1\" : \"0\"), (alt ? \"1\" : \"0\"), (meta ? \"1\" : \"0\")].join(\"\");\n\t},\n\t_check_keycode: function(e){\n\t\tconst keyCode = e.which || e.keyCode;\n\t\tconst is_any = !e.ctrlKey && !e.altKey && !e.metaKey && (keyCode!=9)&&(keyCode!=27)&&(keyCode!=13);\n\t\tconst code = this._keycode(e.key, e.ctrlKey, e.shiftKey, e.altKey, e.metaKey);\n\n\t\tvar focus = this.getFocus();\n\t\tif (this._hotkeys[code])\n\t\t\treturn this._process_calls(this._hotkeys[code], focus, e);\n\t\telse if (is_any && this._hotkeys[\"any_0000\"])\n\t\t\treturn this._process_calls(this._hotkeys[\"any_0000\"], focus, e);\n\n\t\treturn true;\n\t},\n\t_process_calls:function(calls, focus, e){\n\t\tfor (var i = 0; i < calls.length; i++) {\n\t\t\tvar key = calls[i];\n\t\t\tif ((key.view !== null) &&\t\t//common hot-key\n\t\t\t\t(focus !== key.view) &&\t\t//hot-key for current view\n\t\t\t\t//hotkey for current type of view\n\t\t\t\t(typeof(key.view) !== \"string\" || !focus || focus.name !== key.view)) continue;\n\n\t\t\tvar temp_result = key.handler(focus, e);\n\t\t\tif (!!temp_result === temp_result) return temp_result;\n\t\t}\n\t\treturn true;\n\t},\n\t_parse_keys: function(keys) {\n\t\tvar controls = this._controls;\n\t\tvar parts = keys.toLowerCase().split(/[ +\\-_]/);\n\t\tvar ctrl, shift, alt, meta;\n\t\tctrl = shift = alt = meta = 0;\n\t\tvar letter = \"\";\n\t\tfor (var i = 0; i < parts.length; i++) {\n\t\t\tif (parts[i] === \"ctrl\") ctrl = 1;\n\t\t\telse if (parts[i] === \"shift\") shift = 1;\n\t\t\telse if (parts[i] === \"alt\") alt = 1;\n\t\t\telse if (parts[i] === \"command\") meta = 1;\n\t\t\telse {\n\t\t\t\tletter = controls[parts[i]] || parts[i];\n\t\t\t}\n\t\t}\n\n\t\treturn this._keycode(letter, ctrl, shift, alt, meta);\n\t},\n\tgetState:function(node, children) {\n\t\tchildren = (children||false);\n\t\tnode = $$(node);\n\t\tvar state = {\n\t\t\tid: node.config.id,\n\t\t\twidth: node.config.width,\n\t\t\theight: node.config.height,\n\t\t\tgravity: node.config.gravity\n\t\t};\n\t\tif (!isUndefined(node.config.collapsed)) state.collapsed = node.config.collapsed;\n\t\tif (node.name === \"tabs\" || node.name === \"tabbar\") state.activeCell = node.getValue();\n\t\t\n\t\tif (children) {\n\t\t\tstate = [state];\n\t\t\tif (node._cells) {\n\t\t\t\tfor (var i = 0; i < node._cells.length; i++)\n\t\t\t\t\tstate = state.concat(this.getState(node._cells[i], children));\n\t\t\t}\n\t\t}\n\t\treturn state;\n\t},\n\tsetState:function(states) {\n\t\tif (!isArray(states)) states = [states];\n\t\n\t\tfor (var i = 0; i < states.length; i++) {\n\t\t\tvar state = states[i];\n\t\t\tvar node = $$(state.id);\n\t\t\tif (!node) continue;\n\t\n\t\t\tif (!isUndefined(state.collapsed)) node.define(\"collapsed\", state.collapsed);\n\t\t\tif (!isUndefined(state.activeCell)) node.setValue(state.activeCell, \"auto\");\n\t\n\t\t\tnode.define(\"width\", state.width);\n\t\t\tnode.define(\"height\", state.height);\n\t\t\tnode.define(\"gravity\", state.gravity);\n\t\t}\n\t\tvar top = $$(states[0].id);\n\t\tif (top) top.resize();\n\t}\n};\n\nready(function() {\n\tUIManager._enable();\n\n\tUIManager.addHotKey(\"enter\", function(view, ev){\n\t\tif (UIManager._composition)\n\t\t\treturn false;\n\t\tif (view && view.callEvent)\n\t\t\tview.callEvent(\"onEnter\", [ev]);\n\t\tif (view && view.editStop && view._in_edit_mode){\n\t\t\tview.editStop();\n\t\t\treturn true;\n\t\t} else if (view && view.touchable){\n\t\t\tconst form = view.getFormView();\n\t\t\tif (form && !view._skipSubmit)\n\t\t\t\tform.callEvent(\"onSubmit\",[view,ev]);\n\t\t}\n\t});\n\tUIManager.addHotKey(\"esc\", function(view){\n\t\tif (view){\n\t\t\tif (view.editCancel && view._in_edit_mode){\n\t\t\t\tview.editCancel();\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst top = view.getTopParentView();\n\t\t\tif (top && top.setPosition){\n\t\t\t\tif (fullscreen._fullscreen == top)\n\t\t\t\t\tfullscreen.exit();\n\t\t\t\tif (top._editorMaster){\n\t\t\t\t\tconst master = $$(top._editorMaster);\n\t\t\t\t\tif (master.editCancel && master._in_edit_mode)\n\t\t\t\t\t\tmaster.editCancel();\n\t\t\t\t}\n\t\t\t\ttop._hide();\n\t\t\t}\n\t\t}\n\t});\n\tUIManager.addHotKey(\"shift+tab\", UIManager._tab_logic);\n\tUIManager.addHotKey(\"tab\", UIManager._tab_logic);\n});\n\ndefine(\"UIManager\", UIManager);\n\nexport default UIManager;","import {bind} from \"../webix/helpers\";\n\nconst CollectionBind={\n\t$init:function(){\n\t\tthis._cursor = null;\n\t\tthis.attachEvent(\"onSelectChange\", function(){\n\t\t\tvar sel = this.getSelectedId();\n\t\t\tthis.setCursor(sel?(sel.id||sel):null);\n\t\t});\n\t\tthis.attachEvent(\"onAfterCursorChange\", this._update_binds);\t\t\n\t\tthis.attachEvent(\"onAfterDelete\", function(id){\n\t\t\tif (id == this.getCursor())\n\t\t\t\tthis.setCursor(null);\n\t\t});\n\t\tthis.data.attachEvent(\"onStoreUpdated\", bind(function(id, data, mode){\n\t\t\t//paint - ignored\n\t\t\t//delete - handled by onAfterDelete above\n\t\t\tif (id && id == this.getCursor() && mode != \"paint\" && mode != \"delete\")\n\t\t\t\tthis._update_binds();\n\t\t\t\n\t\t},this));\n\t\tthis.data.attachEvent(\"onClearAll\", bind(function(){\n\t\t\tthis._cursor = null;\n\t\t},this));\n\t\tthis.data.attachEvent(\"onIdChange\", bind(function(oldid, newid){\n\t\t\tif (this._cursor == oldid){\n\t\t\t\tthis._cursor = newid;\n\t\t\t\tthis._update_binds();\n\t\t\t}\n\t\t},this));\n\t},\n\trefreshCursor:function(){\n\t\tif (this._cursor)\n\t\t\tthis.callEvent(\"onAfterCursorChange\",[this._cursor]);\n\t},\n\tsetCursor:function(id){\n\t\tif (id == this._cursor || (id !== null && !this.getItem(id))) return;\n\t\t\n\t\tthis.callEvent(\"onBeforeCursorChange\", [this._cursor]);\n\t\tthis._cursor = id;\n\t\tthis.callEvent(\"onAfterCursorChange\",[id]);\n\t},\n\tgetCursor:function(){\n\t\treturn this._cursor;\n\t},\n\t_bind_update:function(target, rule, format){\n\t\tif (rule == \"$level\" && this.data.getBranch)\n\t\t\treturn (target.data || target).importData(this.data.getBranch(this.getCursor()));\n\n\t\tvar data = this.getItem(this.getCursor())|| this._settings.defaultData || null;\n\t\tif (rule == \"$data\"){\n\t\t\tif (typeof format === \"function\")\n\t\t\t\tformat.call(target, data, this);\n\t\t\telse\n\t\t\t\ttarget.data.importData(data?data[format]:[]);\n\t\t\ttarget.callEvent(\"onBindApply\", [data,rule,this]);\n\t\t} else {\n\t\t\tif (format)\n\t\t\t\tdata = format(data);\n\t\t\tthis._bind_update_common(target, rule, data);\n\t\t}\n\t}\n};\n\nexport default CollectionBind;","import {assert} from \"../webix/debug\";\nimport {debug_size_box} from \"../webix/debug\";\n\nimport {callEvent} from \"../webix/customevents\";\nimport {create, createCss, remove, addCss, removeCss, triggerEvent, preventEvent} from \"../webix/html\";\nimport {toNode, extend} from \"../webix/helpers\";\nimport env from \"../webix/env\";\n\nimport {$$,ui,protoUI} from \"../ui/core\";\nimport {_uid, _each} from \"../ui/helpers\";\n\nimport state from \"../core/state\";\nimport UIManager from \"../core/uimanager\";\n\nimport Settings from \"../core/settings\";\nimport Destruction from \"../core/destruction\";\nimport BaseBind from \"../core/basebind\";\n\nconst UIExtension = window.webix_view||{};\n\nconst api = {\n\tname:\"baseview\",\n\t//attribute , which will be used for ID storing\n\t$init:function(config){\n\t\tif (!config.id) \n\t\t\tconfig.id = _uid(this.name);\n\t\t\n\t\tthis._parent_cell = state._parent_cell;\n\t\tstate._parent_cell = null;\n\n\t\t// if scope not provided directly, and there is no parent view\n\t\t// check if we have a global scope\n\t\tthis.$scope = config.$scope || (this._parent_cell ? this._parent_cell.$scope : state._global_scope);\n\t\t\n\t\tif (!this._viewobj){\n\t\t\tthis._contentobj = this._viewobj = create(\"DIV\",{\n\t\t\t\t\"class\":\"webix_view\"\n\t\t\t});\n\t\t\tthis.$view = this._viewobj;\n\t\t}\n\t},\n\t$skin:false,\n\tdefaults:{\n\t\twidth:0,\n\t\theight:0,\n\t\tgravity:1\n\t},\n\tgetNode:function(){\n\t\treturn this._viewobj;\n\t},\n\t// needed only to maintain the deprecated ActiveContent module\n\t// do not use it anywhere else\n\t$setNode:function(node){\n\t\tthis._viewobj = this._dataobj = this.$view = node;\n\t},\n\tgetParentView:function(){\n\t\treturn this._parent_cell||null;\t\n\t},\n\tgetTopParentView:function(){\n\t\tvar parent = this.getParentView();\n\t\treturn parent ? parent.getTopParentView() : this;\n\t},\n\tgetFormView:function(){\n\t\tvar parent = this.getParentView();\n\t\treturn (!parent || parent._recollect_elements) ? parent : parent.getFormView();\n\t},\n\tgetChildViews:function(){ return []; },\n\tqueryView:function(search, all){\n\t\tlet confirm;\n\t\tif (typeof search === \"string\")\n\t\t\tsearch = { view:search };\n\t\tif (typeof search === \"object\")\n\t\t\tconfirm = test => {\n\t\t\t\tconst config = test.config;\n\n\t\t\t\tfor (let key in search){\n\t\t\t\t\tif (config[key] != search[key])\n\t\t\t\t\t\treturn false; \n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t};\n\t\telse\n\t\t\tconfirm = search;\n\n\t\tif (all === \"self\" && confirm(this)) return this;\n\t\tconst results = all === \"all\" ? [] : false;\n\t\tconst direction = all === \"parent\" ? this._queryGoUp : this._queryGoDown;\n\n\t\tconst found = this._queryView(confirm, direction, results);\n\t\treturn all === \"all\" ? results : found;\n\t},\n\t_queryGoDown:function(node){\n\t\treturn node.getChildViews();\n\t},\n\t_queryGoUp:function(node){\n\t\tvar parent = node.getParentView();\n\t\treturn parent ? [parent] : [];\n\t},\n\t_queryView:function(confirm, next, all){\n\t\tvar kids = next(this);\n\t\tfor (var i =0; ix) x = sizes[0];\n\t\t//minHeight\n\t\tif (sizes[2]>y) y = sizes[2];\n\n\t\t//maxWidth rule\n\t\tif ((!fullscreen || this._settings.width) && x>sizes[1]) x = sizes[1];\n\t\t//maxHeight rule\n\t\tif ((!fullscreen || this._settings.height) && y>sizes[3]) y = sizes[3];\n\n\t\tthis.$setSize(x,y);\n\t\tif (state._responsive_exception){\n\t\t\tstate._responsive_exception = false;\n\t\t\tthis.adjust();\n\t\t}\n\t},\n\tresize:function(){\n\t\tif (state._child_sizing_active || state._freeze_resize || state._responsive_tinkery ) return;\n\n\t\tvar parent = this.getParentView();\n\t\tif (parent){\n\t\t\tif (parent.resizeChildren)\n\t\t\t\tparent.resizeChildren();\n\t\t\telse\n\t\t\t\tparent.resize();\n\t\t} else {\n\t\t\tthis.adjust();\n\t\t\tcallEvent(\"onResize\",[]);\n\t\t}\n\t}\n};\n\nconst view = protoUI(api, Settings, Destruction, BaseBind, UIExtension);\nexport default { api, view };","import {isUndefined} from \"../webix/helpers\";\nimport {debug_size_box} from \"../webix/debug\";\nimport {protoUI} from \"../ui/core\";\n\nimport base from \"./baseview\";\n\nconst api = {\n\tname:\"view\",\n\t$init:function(config){\n\t\tthis._set_inner(config);\n\t},\n\n\t//deside, will component use borders or not\n\t_set_inner:function(config){\n\t\tvar border_not_set = isUndefined(config.borderless);\n\t\tif (border_not_set && !this.setPosition && config.$topView){\n\t\t\tconfig.borderless = true;\n\t\t\tborder_not_set = false;\n\t\t}\n\n\t\tif ((border_not_set && this.defaults.borderless) || config.borderless){\n\t\t\t//button and custom borderless\n\t\t\tconfig._inner = { top:true, left:true, bottom:true, right:true };\n\t\t} else {\n\t\t\t//default borders\n\t\t\tif (!config._inner)\n\t\t\t\tconfig._inner = {};\n\t\t\tthis._contentobj.style.borderWidth=\"1px\";\n\t\t}\n\t},\n\n\t$getSize:function(dx, dy){\n\n\t\tvar _borders = this._settings._inner;\n\t\tif (_borders){\n\t\t\tdx += (_borders.left?0:1)+(_borders.right?0:1);\n\t\t\tdy += (_borders.top?0:1)+(_borders.bottom?0:1);\n\t\t}\n\t\t\n\t\tvar size = base.api.$getSize.call(this, dx, dy);\n\t\t\n\t\tif (DEBUG) debug_size_box(this, size, true);\n\t\treturn size;\n\t},\n\t$setSize:function(x,y){\n\t\tif (DEBUG) debug_size_box(this, [x,y]);\n\t\t\t\n\t\tvar _borders = this._settings._inner;\n\t\tif (_borders){\n\t\t\tx -= (_borders.left?0:1)+(_borders.right?0:1);\n\t\t\ty -= (_borders.top?0:1)+(_borders.bottom?0:1);\n\t\t}\n\t\t\t\n\t\treturn base.api.$setSize.call(this,x,y);\n\t}\n};\n\nconst view = protoUI(api, base.view);\nexport default { api, view };\n\n//not necessary anymore\n//preserving for backward compatibility\nview.call(-1);\n","import {create, remove} from \"../webix/html\";\nimport {isUndefined, toNode} from \"../webix/helpers\";\nimport {proto} from \"../ui/core\";\n\nconst Canvas = proto({\n\t$init:function(container){\n\t\tthis._canvas_labels = [];\n\t\tthis._canvas_series = (!isUndefined(container.series)?container.series:container.name);\n\t\tthis._obj = toNode(container.container||container);\n\t\tvar width = container.width*(window.devicePixelRatio||1);\n\t\tvar height = container.height*(window.devicePixelRatio||1);\n\t\tvar style = container.style||\"\";\n\t\tstyle += \";width:\"+container.width+\"px;height:\"+container.height+\"px;\";\n\t\tthis._prepareCanvas(container.name, style ,width, height, container.title);\n\t},\n\t_prepareCanvas:function(name,style,x,y, title){\n\t\t//canvas has the same size as master object\n\t\tthis._canvas = create(\"canvas\",{ title:title, width:x, height:y, canvas_id:name, style:(style||\"\")});\n\t\tthis._obj.appendChild(this._canvas);\n\t\treturn this._canvas;\n\t}, \n\tgetCanvas:function(context){\n\t\tvar ctx = (this._canvas||this._prepareCanvas(this._contentobj)).getContext(context||\"2d\");\n\t\tif(!this._webixDevicePixelRatio){\n\t\t\tthis._webixDevicePixelRatio = true;\n\t\t\tctx.scale(window.devicePixelRatio||1, window.devicePixelRatio||1);\n\t\t}\n\t\treturn ctx;\n\t},\n\t_resizeCanvas:function(x, y){\n\t\tif (this._canvas){\n\t\t\tthis._canvas.setAttribute(\"width\", x*(window.devicePixelRatio||1));\n\t\t\tthis._canvas.setAttribute(\"height\", y*(window.devicePixelRatio||1));\n\t\t\tthis._canvas.style.width = x+\"px\";\n\t\t\tthis._canvas.style.height = y+\"px\";\n\t\t\tthis._webixDevicePixelRatio = false;\n\t\t}\n\t},\n\trenderText:function(x,y,text,css,w){\n\t\tif (!text) return; //ignore empty text\n\t\tif (w) w = Math.max(w,0);\n\t\tif (y) y = Math.max(y,0);\n\t\tvar t = create(\"DIV\",{\n\t\t\t\"class\":\"webix_canvas_text\"+(css?(\" \"+css):\"\"),\n\t\t\t\"style\":\"left:\"+x+\"px; top:\"+y+\"px;\",\n\t\t\t\"aria-hidden\":\"true\"\n\t\t},text);\n\t\tthis._obj.appendChild(t);\n\t\tthis._canvas_labels.push(t); //destructor?\n\t\tif (w)\n\t\t\tt.style.width = w+\"px\";\n\t\treturn t;\n\t},\n\trenderTextAt:function(valign,align, x,y,t,c,w){\n\t\tvar text=this.renderText.call(this,x,y,t,c,w);\n\t\tif (text){\n\t\t\tlet size;\n\t\t\tif(document.body.contains(text))\n\t\t\t\tsize = { width: text.offsetWidth, height: text.offsetHeight };\n\t\t\telse{\n\t\t\t\t// inside window\n\t\t\t\tconst d = create(\"DIV\",{class: \"webix_chart\", style: \"visibility:hidden; position:absolute; top:0px; left:0px;\"}, \"\");\n\t\t\t\tconst parentNode = text.parentNode;\n\t\t\t\tdocument.body.appendChild(d);\n\t\t\t\td.appendChild(text);\n\t\t\t\tsize = { width: text.offsetWidth, height: text.offsetHeight };\n\t\t\t\tparentNode.appendChild(text);\n\t\t\t\tremove(d);\n\t\t\t}\n\n\t\t\tif (valign){\n\t\t\t\tif(valign == \"middle\")\n\t\t\t\t\ttext.style.top = parseInt(y-size.height/2,10) + \"px\";\n\t\t\t\telse\n\t\t\t\t\ttext.style.top = y-size.height + \"px\";\n\t\t\t}\n\t\t\tif (align){\n\t\t\t\tif(align == \"left\")\n\t\t\t\t\ttext.style.left = x-size.width + \"px\";\n\t\t\t\telse\n\t\t\t\t\ttext.style.left = parseInt(x-size.width/2,10) + \"px\";\n\t\t\t}\n\t\t}\n\t\treturn text;\n\t},\n\tclearCanvas:function(skipMap){\n\t\tvar areas=[];\n\n\t\tremove(this._canvas_labels);\n\t\tthis._canvas_labels = [];\n\n\t\tif (!skipMap&&this._obj._htmlmap){\n\n\t\t\t//areas that correspond this canvas layer\n\t\t\tareas = this._getMapAreas();\n\t\t\t//removes areas of this canvas\n\t\t\twhile(areas.length){\n\t\t\t\tareas[0].parentNode.removeChild(areas[0]);\n\t\t\t\tareas.splice(0,1);\n\t\t\t}\n\t\t\tareas = null;\n\n\t\t\t//removes _htmlmap object if all its child nodes are removed\n\t\t\tif(!this._obj._htmlmap.getElementsByTagName(\"AREA\").length){\n\t\t\t\tthis._obj._htmlmap.parentNode.removeChild(this._obj._htmlmap);\n\t\t\t\tthis._obj._htmlmap = null;\n\t\t\t}\n\t\t}\n\t\t//FF breaks, when we are using clear canvas and call clearRect without parameters\n\t\t//width|height are used insead of offsetWidth|offsetHeight for hidden canvas (series)\n\t\tthis.getCanvas().clearRect(0,0,\n\t\t\tthis._canvas.offsetWidth||Math.floor(this._canvas.width/(window.devicePixelRatio||1)), \n\t\t\tthis._canvas.offsetHeight||Math.floor(this._canvas.height/(window.devicePixelRatio||1))\n\t\t);\n\t},\n\ttoggleCanvas:function(){\n\t\tthis._toggleCanvas(this._canvas.style.display==\"none\");\n\t},\n\tshowCanvas:function(){\n\t\tthis._toggleCanvas(true);\n\t},\n\thideCanvas:function(){\n\t\tthis._toggleCanvas(false);\n\t},\n\t_toggleCanvas:function(show){\n\t\tvar areas, i;\n\n\t\tfor(i=0; i < this._canvas_labels.length;i++)\n\t\t\tthis._canvas_labels[i].style.display = (show?\"\":\"none\");\n\n\t\tif (this._obj._htmlmap){\n\t\t\tareas = this._getMapAreas();\n\t\t\tfor( i = 0; i < areas.length; i++){\n\t\t\t\tif(show)\n\t\t\t\t\tareas[i].removeAttribute(\"disabled\");\n\t\t\t\telse\n\t\t\t\t\tareas[i].setAttribute(\"disabled\",\"true\");\n\t\t\t}\n\t\t}\n\t\t//FF breaks, when we are using clear canvas and call clearRect without parameters\n\t\tthis._canvas.style.display = (show?\"\":\"none\");\n\t},\n\t_getMapAreas:function(){\n\t\tvar res = [], areas, i;\n\t\tareas = this._obj._htmlmap.getElementsByTagName(\"AREA\");\n\t\tfor(i = 0; i < areas.length; i++){\n\t\t\tif(areas[i].getAttribute(\"userdata\") == this._canvas_series){\n\t\t\t\tres.push(areas[i]);\n\t\t\t}\n\t\t}\n\n\t\treturn res;\n\t}\n});\n\nexport default Canvas;","const skin = {\n\ttopLayout:\"space\",\n\t//bar in accordion\n\tbarHeight:44,\t\t\t//!!!Set the same in skin.less!!!\n\ttabbarHeight: 42,\n\tsidebarTitleHeight: 44,\n\trowHeight:36,\n\ttoolbarHeight:44,\n\tlistItemHeight:36,\t\t//list, grouplist, dataview, etc.\n\tinputHeight: 38,\n\tbuttonHeight: 38,\n\tinputPadding: 3,\n\tmenuHeight: 36,\n\tlabelTopHeight: 22,\n\tpropertyItemHeight: 28,\n\ttimelineItemHeight:70,\n\tunitHeaderHeight:36,\n\tfontSize: 14,\n\n\tinputSpacing: 4,\n\tborderWidth: 1,\n\n\tsliderHandleWidth: 14,\n\tsliderPadding: 10,\n\tsliderBorder: 1,\n\tvSliderPadding:15,\n\tvSliderHeight:100,\n\tswitchHeight:24,\n\tswitchWidth:50,\n\n\t//margin - distance between cells\n\tlayoutMargin:{ space:10, wide:10, clean:0, head:4, line:-1, toolbar:4, form:8, accordion: 2 },\n\t//padding - distance inside cell between cell border and cell content\n\tlayoutPadding:{ space:10, wide:0, clean:0, head:0, line:0, toolbar:2, form:17, accordion: 0 },\n\t//space between tabs in tabbar\n\ttabMargin: 0,\n\ttabOffset: 0,\n\ttabBottomOffset: 0,\n\ttabTopOffset:0,\n\ttabBorder: true,\n\n\tcustomCheckbox: true,\n\tcustomRadio: true,\n\tsidebarMarkAll: true,\n\tpopupNoPoint: true,\n\tborderlessPopup: true,\n\n\tpopupPadding: 0,\n\n\tdataPadding: 12,\n\n\tcalendarWeekHeaderHeight: 18,\n\tpadding:0,\n\taccordionType: \"accordion\",\n\n\toptionHeight: 32,\n\ttimelineColor:\"#1CA1C1\",\n\n\tbackColor:\"#FFFFFF\",\n\tdataBorderColor:\"#EDEFF0\",\n\n\t//colorboard\n\tcolorPadding: 4\n};\n\nexport default skin;\n","const skin = {\n\ttopLayout:\"space\",\n\t//bar in accordion\n\tbarHeight: 46,\t\t\t//!!!Set the same in skin.less!!!\n\ttabbarHeight: 44,\n\tsidebarTitleHeight: 46,\n\trowHeight:36,\n\ttoolbarHeight:46,\n\tlistItemHeight:36,\t\t//list, grouplist, dataview, etc.\n\tinputHeight: 38,\n\tbuttonHeight: 38,\n\tinputPadding: 3,\n\tmenuHeight: 36,\n\tlabelTopHeight: 22,\n\tpropertyItemHeight: 28,\n\ttimelineItemHeight:64,\n\tunitHeaderHeight:36,\n\tfontSize: 14,\n\n\tinputSpacing: 4,\n\tborderWidth: 1,\n\n\tsliderHandleWidth: 14,\n\tsliderPadding: 10,\n\tsliderBorder: 1,\n\tvSliderPadding:15,\n\tvSliderHeight:100,\n\tswitchHeight:24,\n\tswitchWidth:50,\n\n\t//margin - distance between cells\n\tlayoutMargin:{ space:10, wide:10, clean:0, head:4, line:-1, toolbar:4, form:8, accordion: 2 },\n\t//padding - distance inside cell between cell border and cell content\n\tlayoutPadding:{ space:10, wide:0, clean:0, head:0, line:0, toolbar:3, form:17, accordion: 0 },\n\t//space between tabs in tabbar\n\ttabMargin: 0,\n\ttabOffset: 0,\n\ttabBottomOffset: 0,\n\ttabTopOffset:0,\n\ttabBorder: true,\n\n\tcustomCheckbox: true,\n\tcustomRadio: true,\n\tsidebarMarkAll: true,\n\tpopupNoPoint: true,\n\tborderlessPopup: true,\n\n\tpopupPadding: 0,\n\n\tdataPadding: 12,\n\n\tcalendarWeekHeaderHeight: 18,\n\tpadding:0,\n\taccordionType: \"accordion\",\n\n\toptionHeight: 32,\n\ttimelineColor:\"#37A9EF\",\n\n\tbackColor:\"#FFFFFF\",\n\tdataBorderColor:\"#E6E6E6\",\n\n\t//colorboard\n\tcolorPadding: 4\n};\n\nexport default skin;\n","import env from \"../webix/env\";\nimport ready from \"../webix/ready\";\n\nimport {event} from \"../webix/htmlevents\";\nimport {callEvent} from \"../webix/customevents\";\nimport {preventEvent, removeCss, addCss, addStyle} from \"../webix/html\";\n\n//late binding\nimport {$$} from \"../ui/core\";\n\nconst Touch = {\n\tconfig:{\n\t\tlongTouchDelay:700,\n\t\tscrollDelay:150,\n\t\tgravity:500,\n\t\tdeltaStep:10,\n\t\tspeed:\"0ms\",\n\t\tfinish:1000,\n\t\telastic:true\n\t},\n\tlimit:function(value){\n\t\tTouch._limited = value !== false;\t\n\t},\n\tdisable:function(){\n\t\tTouch._disabled = true;\n\t},\n\tenable:function(){\n\t\tTouch._disabled = false;\n\t},\n\t$init:function(){\n\t\tTouch.$init = function(){};\n\n\t\tevent(document.body, env.touch.down,\tTouch._touchstart, {passive:false});\n\t\tevent(document.body, env.touch.move, \tTouch._touchmove, {passive:false});\n\t\tevent(document, env.touch.up, \tTouch._touchend);\n\n\t\tevent(document.body,\"dragstart\",function(e){\n\t\t\tif(Touch._disabled || Touch._limited) return;\n\t\t\treturn preventEvent(e);\n\t\t});\n\n\t\tTouch._clear_artefacts();\n\t\tTouch._scroll = [null, null];\n\t\tTouch.$active = true;\n\t},\n\t_clear_artefacts:function(){\n\t\tTouch._start_context = Touch._current_context = Touch._prev_context = Touch._scroll_context = null;\n\t\tTouch._scroll_mode = Touch._scroll_node = Touch._scroll_stat = Touch._long_touched = null;\n\t\tTouch._delta = \t{ _x_moment:0, _y_moment:0, _time:0 };\n\n\t\tif (Touch._css_button_remove){\n\t\t\tremoveCss(Touch._css_button_remove,\"webix_touch\");\n\t\t\tTouch._css_button_remove = null;\n\t\t}\n\t\t\n\t\twindow.clearTimeout(Touch._long_touch_timer);\n\t\tTouch._was_not_moved = true;\n\t\tTouch._axis_x = true;\n\t\tTouch._axis_y = true;\n\t\tif (!Touch._active_transion)\n\t\t\tTouch._scroll_end();\n\t},\n\t_touchend:function(e){\n\t\tif (Touch._start_context) {\n\t\t\tif (!Touch._scroll_mode) {\n\t\t\t\tif (!Touch._long_touched && !(Touch._axis_x * Touch._axis_y)) {\n\t\t\t\t\tconst delta = Touch._get_delta(e);\n\t\t\t\t\tif (!Touch._axis_x && delta._x/(delta._y||1) > 4) {\n\t\t\t\t\t\tTouch._translate_event(\"onSwipeX\");\n\t\t\t\t\t} else if (!Touch._axis_y && delta._y/(delta._x||1) > 4) {\n\t\t\t\t\t\tTouch._translate_event(\"onSwipeY\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlet finish = Touch.config.finish;\n\t\t\t\tconst temp = Touch._get_matrix(Touch._scroll_node);\n\t\t\t\tconst x = temp.e;\n\t\t\t\tconst y = temp.f;\n\n\t\t\t\tconst delta = Touch._get_delta(e);\n\t\t\t\tconst view = $$(Touch._scroll_node);\n\n\t\t\t\tconst gravity = (view && view.$scroll) ? view.$scroll.gravity : Touch.config.gravity;\n\t\t\t\tif (delta._time) {\n\t\t\t\t\tconst nx = x + gravity * delta._x_moment / delta._time;\n\t\t\t\t\tconst ny = y + gravity * delta._y_moment / delta._time;\n\n\t\t\t\t\tconst cnx = Touch._scroll[0] ? Touch._correct_minmax(nx, false, false, Touch._scroll_stat.dx, Touch._scroll_stat.px) : x;\n\t\t\t\t\tconst cny = Touch._scroll[1] ? Touch._correct_minmax(ny, false, false, Touch._scroll_stat.dy, Touch._scroll_stat.py) : y;\n\n\t\t\t\t\tconst size = Math.max(Math.abs(cnx - x), Math.abs(cny - y));\n\t\t\t\t\tif (size < 150)\n\t\t\t\t\t\tfinish = finish * size / 150;\n\n\t\t\t\t\tif (cnx != x || cny != y)\n\t\t\t\t\t\tfinish = Math.round(finish * Math.max((cnx - x) / (nx - x), (cny - y) / (ny - y)));\n\n\t\t\t\t\tconst result = {e: cnx, f: cny};\n\t\t\t\t\tif (view && view.adjustScroll)\n\t\t\t\t\t\tview.adjustScroll(result);\n\n\t\t\t\t\tfinish = Math.min(Touch.config.finish, Math.max(100, finish));\n\t\t\t\t\tif (x != result.e || y != result.f) {\n\t\t\t\t\t\tTouch._set_matrix(Touch._scroll_node, result.e, result.f, finish + \"ms\");\n\t\t\t\t\t\tif (Touch._scroll_master)\n\t\t\t\t\t\t\tTouch._scroll_master._sync_scroll(result.e, result.f, finish + \"ms\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tTouch._scroll_end();\n\t\t\t\t\t}\n\t\t\t\t} else\n\t\t\t\t\tTouch._scroll_end();\n\t\t\t}\n\t\t\tTouch._translate_event(\"onTouchEnd\");\n\t\t\tTouch._clear_artefacts();\n\t\t}\n\t},\n\t_touchmove:function(e){\n\t\tif (!Touch._scroll_context || !Touch._start_context) return;\n\n\t\tvar\tdelta = Touch._get_delta(e);\n\t\tTouch._translate_event(\"onTouchMove\");\n\n\t\tif (Touch._scroll_mode){\n\t\t\tTouch._set_scroll_pos();\n\t\t} else {\n\t\t\tTouch._axis_x = Touch._axis_check(delta._x, \"x\", Touch._axis_x);\n\t\t\tTouch._axis_y = Touch._axis_check(delta._y, \"y\", Touch._axis_y);\n\t\t\tif (Touch._scroll_mode){\n\t\t\t\tvar view = Touch._get_event_view(\"onBeforeScroll\", true);\n\t\t\t\tif (view){\n\t\t\t\t\tvar data = {};\n\t\t\t\t\tview.callEvent(\"onBeforeScroll\",[data]);\n\t\t\t\t\tif (data.update){\n\t\t\t\t\t\tTouch.config.speed = data.speed;\n\t\t\t\t\t\tTouch.config.scale = data.scale;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tTouch._init_scroller(); //apply scrolling\n\t\t\t} else {\n\t\t\t\tconst state = Touch._is_scroll();\n\t\t\t\tconst view = $$(state && state[0]);\t\t// support subviews\n\t\t\t\tif (view && view.$hasYScroll && view.$hasYScroll() && e.cancelable){\n\t\t\t\t\treturn preventEvent(e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (Touch._scroll_mode && e.cancelable)\n\t\t\treturn preventEvent(e);\n\t},\n\t_set_scroll_pos:function(){\n\t\tif (!Touch._scroll_node) return;\n\t\tvar temp = Touch._get_matrix(Touch._scroll_node);\n\t\tvar prev = Touch._prev_context || Touch._start_context;\n\n\t\tvar view = $$(Touch._scroll_node);\n\t\tvar elastic = (view && view.$scroll) ? view.$scroll.elastic : Touch.config.elastic;\n\n\t\tif (Touch._scroll[0])\n\t\t\ttemp.e = Touch._correct_minmax( temp.e - prev.x + Touch._current_context.x , elastic, temp.e, Touch._scroll_stat.dx, Touch._scroll_stat.px);\n\t\tif (Touch._scroll[1])\n\t\t\ttemp.f = Touch._correct_minmax( temp.f - prev.y + Touch._current_context.y , elastic, temp.f, Touch._scroll_stat.dy, Touch._scroll_stat.py);\n\n\t\tTouch._set_matrix(Touch._scroll_node, temp.e, temp.f, \"0ms\");\n\t\tif (Touch._scroll_master)\n\t\t\tTouch._scroll_master._sync_scroll(temp.e, temp.f, \"0ms\");\n\t},\n\tscrollTo:function(node, x, y, speed){\n\t\tTouch._set_matrix(node,x,y,speed);\n\t},\n\t_set_matrix:function(node, xv, yv, speed){\n\t\tif (!speed){\n\t\t\tnode.style[env.transform] = \"\";\n\t\t\treturn;\n\t\t}\n\n\t\tTouch._active_transion = true;\n\t\tif (node){\n\t\t\tvar trans = Touch.config.translate || env.translate;\n\t\t\tnode.style[env.transform] = trans+\"(\"+Math.round(xv)+\"px, \"+Math.round(yv)+\"px\"+((trans==\"translate3d\")?\", 0\":\"\")+\")\";\n\t\t\tnode.style[env.transitionDuration] = speed;\n\t\t}\n\t},\n\t_get_matrix:function(node){\n\t\tvar matrix = window.getComputedStyle(node)[env.transform];\n\t\tvar tmatrix;\n\n\t\tif (matrix == \"none\")\n\t\t\ttmatrix = {e:0, f:0};\n\t\telse {\n\t\t\tif(window.WebKitCSSMatrix)\n\t\t\t\t/* global WebKitCSSMatrix */\n\t\t\t\ttmatrix = new WebKitCSSMatrix(matrix);\n\t\t\telse {\n\t\t\t\t// matrix(1, 0, 0, 1, 0, 0) --> 1, 0, 0, 1, 0, 0\n\t\t\t\tvar _tmatrix = matrix.replace(/(matrix\\()(.*)(\\))/gi, \"$2\");\n\t\t\t\t// 1, 0, 0, 1, 0, 0 --> 1,0,0,1,0,0\n\t\t\t\t_tmatrix = _tmatrix.replace(/\\s/gi, \"\");\n\t\t\t\t_tmatrix = _tmatrix.split(\",\");\n\n\t\t\t\ttmatrix = {};\n\t\t\t\tvar tkey = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"];\n\t\t\t\tfor(var i=0; i dx) return 0;\n\n\t\tconst delta = Math.abs(value-current);\n\t\tconst sign = delta/(value-current);\n\t\tif (value > 0)\n\t\t\treturn allow ? (current + sign*Math.sqrt(delta)) : 0;\n\n\t\tconst max = dx - px;\n\t\tif (max + value < 0)\n\t\t\treturn allow ? (current + sign*Math.sqrt(delta)) : -max;\n\n\t\treturn value;\n\t},\t\n\t_init_scroll_node:function(node){\n\t\tif (!node.scroll_enabled){\n\t\t\tnode.scroll_enabled = true;\n\t\t\tnode.parentNode.style.position = \"relative\";\n\t\t\tnode.style.cssText += \"transition:transform; user-select:none; transform-style:flat;\";\n\t\t\tnode.addEventListener(env.transitionEnd, function(e){\n\t\t\t\tif (e.target === this) Touch._scroll_end.call(this);\n\t\t\t}, false);\n\t\t}\n\t},\n\t_init_scroller:function(){\n\t\tif (Touch._scroll_mode.indexOf(\"x\") !== -1) Touch._scroll[0] = true;\n\t\tif (Touch._scroll_mode.indexOf(\"y\") !== -1) Touch._scroll[1] = true;\n\n\t\tif (Touch._scroll[0] || Touch._scroll[1])\n\t\t\tTouch._scroll[2] = Touch._scroll_node;\n\n\t\tTouch._init_scroll_node(Touch._scroll_node);\n\t},\n\t_axis_check:function(value, mode, old){\n\t\tif (value > Touch.config.deltaStep){\n\t\t\tif (Touch._was_not_moved){\n\t\t\t\tTouch._long_move(mode);\n\t\t\t\tTouch._locate(mode);\n\t\t\t\tif ((Touch._scroll_mode||\"\").indexOf(mode) == -1) Touch._scroll_mode = \"\";\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\treturn old;\n\t},\n\t_scroll_end:function(){\n\t\t//sending event to the owner of the scroll only\n\t\tvar result,state,view;\n\t\tview = $$(Touch._scroll_node||this);\n\t\tif (view){\n\t\t\tif (Touch._scroll_node)\n\t\t\t\tresult = Touch._get_matrix(Touch._scroll_node);\n\t\t\telse if(view.getScrollState){\n\t\t\t\tstate = view.getScrollState();\n\t\t\t\tresult = {e:-state.x, f:-state.y};\n\t\t\t}\n\t\t\tcallEvent(\"onAfterScroll\", [result]);\n\t\t\tif (view.callEvent)\n\t\t\t\tview.callEvent(\"onAfterScroll\",[result]);\n\t\t}\n\t\tif (!Touch._scroll_mode)\n\t\t\tTouch._scroll = [null, null];\n\t\tTouch._active_transion = false;\n\t},\n\t_long_move:function(){\n\t\twindow.clearTimeout(Touch._long_touch_timer);\n\t\tTouch._was_not_moved = false;\t\n\t},\t\n\t_stop_old_scroll:function(e){\n\t\tif (Touch._scroll[2]){\n\t\t\tTouch._stop_scroll(e, (Touch._scroll[0] ? \"x\" : \"y\"));\n\t\t} else\n\t\t\treturn true;\n\t},\n\t_touchstart :function(e){\n\t\tif (Touch._disabled) return;\n\n\t\tTouch._long_touched = null;\n\t\tTouch._scroll_context = Touch._start_context = env.touch.context(e);\n\n\t\tif (Touch._limited && !Touch._is_scroll())\n\t\t\tTouch._scroll_context = null;\n\n\t\tTouch._translate_event(\"onTouchStart\");\n\n\t\tif (Touch._stop_old_scroll(e))\n\t\t\tTouch._long_touch_timer = window.setTimeout(Touch._long_touch, Touch.config.longTouchDelay);\n\n\t\tconst element = $$(e);\n\t\tif (element && element.touchable && (!e.target.className || e.target.className.indexOf(\"webix_view\") !== 0)){\n\t\t\tTouch._css_button_remove = element.getNode(e);\n\t\t\taddCss(Touch._css_button_remove,\"webix_touch\");\n\t\t}\n\t},\n\t_long_touch:function(){\n\t\tif(Touch._start_context){\n\t\t\tTouch._long_touched = true;\n\t\t\tTouch._translate_event(\"onLongTouch\");\n\t\t\tcallEvent(\"onClick\", [Touch._start_context]);\n\t\t}\n\t},\n\t_stop_scroll:function(e, stop_mode){\n\t\tTouch._locate(stop_mode);\n\t\tif (Touch._scroll[2]){\n\t\t\tvar view = Touch._get_event_view(\"onBeforeScroll\", true);\n\t\t\tif (view)\n\t\t\t\tview.callEvent(\"onBeforeScroll\", [Touch._start_context,Touch._current_context]);\n\n\t\t\tif (!Touch._scroll_node || Touch._scroll_node.parentNode !== Touch._scroll[2].parentNode){\n\t\t\t\tTouch._clear_artefacts();\n\t\t\t\tTouch._scroll_end();\n\t\t\t\tTouch._start_context = env.touch.context(e);\n\t\t\t}\n\t\t}\n\t\tTouch._touchmove(e);\n\t},\t\n\t_get_delta:function(e){\n\t\tTouch._prev_context = Touch._current_context;\n\t\tTouch._current_context = env.touch.context(e);\n\n\t\tTouch._delta._x = Math.abs(Touch._start_context.x - Touch._current_context.x);\n\t\tTouch._delta._y = Math.abs(Touch._start_context.y - Touch._current_context.y);\n\n\t\tif (Touch._prev_context){\n\t\t\tif (Touch._current_context.time - Touch._prev_context.time < Touch.config.scrollDelay){\n\t\t\t\tTouch._delta._x_moment = Touch._delta._x_moment/1.3+Touch._current_context.x - Touch._prev_context.x;\n\t\t\t\tTouch._delta._y_moment = Touch._delta._y_moment/1.3+Touch._current_context.y - Touch._prev_context.y;\n\t\t\t} else {\n\t\t\t\tTouch._delta._y_moment = Touch._delta._x_moment = 0;\n\t\t\t}\n\t\t\tTouch._delta._time = Touch._delta._time/1.3+(Touch._current_context.time - Touch._prev_context.time);\n\t\t}\n\n\t\treturn Touch._delta;\n\t},\n\t_get_sizes:function(node){\n\t\treturn {\n\t\t\tdx:node.offsetWidth,\n\t\t\tdy:node.offsetHeight,\n\t\t\tpx:node.parentNode.offsetWidth,\n\t\t\tpy:node.parentNode.offsetHeight\n\t\t};\n\t},\n\t_is_scroll:function(locate_mode){\n\t\tvar node = Touch._start_context.target;\n\t\twhile(node && node.tagName != \"BODY\"){\n\t\t\tif (node.getAttribute){\n\t\t\t\tvar mode = node.getAttribute(\"touch_scroll\");\n\t\t\t\tif (mode && (!locate_mode || mode.indexOf(locate_mode) != -1))\n\t\t\t\t\treturn [node, mode];\n\t\t\t}\n\t\t\tnode = node.parentNode;\n\t\t}\n\t\treturn null;\n\t},\n\t_locate:function(locate_mode){\n\t\tvar state = Touch._is_scroll(locate_mode);\n\t\tif (state){\n\t\t\tTouch._scroll_mode = state[1];\n\t\t\tTouch._scroll_node = state[0];\n\t\t\tTouch._scroll_stat = Touch._get_sizes(state[0]);\n\t\t}\n\t\treturn state;\n\t},\n\t_translate_event:function(name){\n\t\tcallEvent(name, [Touch._start_context,Touch._current_context]);\n\t\tvar view = Touch._get_event_view(name);\n\t\tif (view)\n\t\t\tview.callEvent(name, [Touch._start_context,Touch._current_context]);\n\t},\n\t_get_event_view:function(name, active){\n\t\tvar view = $$(active ? Touch._scroll_node : Touch._start_context);\n\t\tif(!view) return null;\n\n\t\twhile (view){\n\t\t\tif (view.hasEvent && view.hasEvent(name))\n\t\t\t\treturn view;\n\t\t\tview = view.getParentView();\n\t\t}\n\n\t\treturn null;\n\t},\t\n\t_get_context:function(e){\n\t\tif (!e.touches[0]) {\n\t\t\tvar temp = Touch._current_context;\n\t\t\ttemp.time = new Date();\n\t\t\treturn temp;\n\t\t}\n\n\t\treturn {\n\t\t\ttarget:e.target,\n\t\t\tx:e.touches[0].pageX,\n\t\t\ty:e.touches[0].pageY,\n\t\t\ttime:new Date()\n\t\t};\n\t},\n\t_get_context_m:function(e){\n\t\treturn {\n\t\t\ttarget:e.target,\n\t\t\tx:e.pageX,\n\t\t\ty:e.pageY,\n\t\t\ttime:new Date()\n\t\t};\n\t}\n};\n\nfunction touchInit(){\n\tif (env.touch){\n\t\tTouch.$init();\n\n\t\t//not full screen mode\n\t\tif (document.body.className.indexOf(\"webix_full_screen\") === -1)\n\t\t\tTouch.limit(true);\n\n\t\tif (env.isSafari && CSS.supports(\"-webkit-overflow-scrolling: touch\"))\n\t\t\taddStyle(\".webix_view{ -webkit-overflow-scrolling:touch; } .webix_scroll_cont{ transform:translateZ(0px); }\");\n\t}\n}\n\nready(touchInit);\n\nenv.mouse = {\n\tdown: \"mousedown\",\n\tmove: \"mousemove\",\n\tup: \"mouseup\",\n\tcontext: Touch._get_context_m\n};\n\nenv.touch = env.touch && {\n\tdown: \"touchstart\",\n\tmove: \"touchmove\",\n\tup: \"touchend\",\n\tcontext: Touch._get_context\n};\n\t\n\nexport default Touch;","import {preventEvent, addCss, removeCss, pos as getPos, remove} from \"../webix/html\";\nimport env from \"../webix/env\";\nimport Touch from \"../core/touch\";\nimport {zIndex} from \"../ui/helpers\";\nimport {_to_array, toNode} from \"../webix/helpers\";\nimport {_event, event, eventRemove} from \"../webix/htmlevents\";\nimport {attachEvent, callEvent} from \"../webix/customevents\";\n\n\n/*\n\tBehavior:DND - low-level dnd handling\n\t@export\n\t\tgetContext\n\t\taddDrop\n\t\taddDrag\n\t\t\n\tDND master can define next handlers\n\t\tonCreateDrag\n\t\tonDragIng\n\t\tonDragOut\n\t\tonDrag\n\t\tonDrop\n\tall are optional\n*/\n\nconst DragControl ={\n\t//has of known dnd masters\n\t_drag_masters : _to_array([\"dummy\"]),\n\t/*\n\t\tregister drop area\n\t\t@param node \t\t\thtml node or ID\n\t\t@param ctrl \t\t\toptions dnd master\n\t\t@param master_mode \t\ttrue if you have complex drag-area rules\n\t*/\n\taddDrop:function(node,ctrl,master_mode){\n\t\tnode = toNode(node);\n\t\tnode.webix_drop=this._getCtrl(ctrl);\n\t\tif (master_mode) node.webix_master=true;\n\t},\n\t//return index of master in collection\n\t//it done in such way to prevent dnd master duplication\n\t//probably useless, used only by addDrop and addDrag methods\n\t_getCtrl:function(ctrl){\n\t\tctrl = ctrl||DragControl;\n\t\tvar index = this._drag_masters.find(ctrl);\n\t\tif (index<0){\n\t\t\tindex = this._drag_masters.length;\n\t\t\tthis._drag_masters.push(ctrl);\n\t\t\tif (ctrl.attachEvent)\n\t\t\t\tctrl.attachEvent(\"onDestruct\", () => DragControl.unlink(ctrl));\n\t\t}\n\t\treturn index;\n\t},\n\tunlink(ctrl){\n\t\tvar index = this._drag_masters.find(ctrl);\n\t\tif (index > -1){\n\t\t\t// if active view was destroyed, stop dnd\n\t\t\tif (DragControl._active && DragControl._active.webix_drag == index)\n\t\t\t\tDragControl._stopDrag();\n\t\t\t// if last target was destroyed, reset it and continue dnd\n\t\t\tif (DragControl._last && DragControl._last.webix_drop == index)\n\t\t\t\tDragControl._last = null;\n\n\t\t\tthis._drag_masters[index] = null;\n\t\t}\n\t},\n\t_createTouchDrag: function(e, pointer){\n\t\tconst dragCtrl = DragControl;\n\t\tconst master = this._getActiveDragMaster();\n\t\t// for data items only\n\t\tif (master && master.$longTouchLimit){\n\t\t\tif (!dragCtrl._html && !dragCtrl.createDrag(e, pointer)) return;\n\t\t\te.longtouch_drag = true;\n\n\t\t\tconst pos = getPos(e);\n\t\t\tconst customPos = dragCtrl.$dragPos(pos, e);\n\n\t\t\tconst ctx = dragCtrl._drag_context;\n\t\t\tdragCtrl._html.style.top= pos.y+dragCtrl.top+(customPos||!ctx.y_offset?0:ctx.y_offset)+\"px\";\n\t\t\tdragCtrl._html.style.left= pos.x+dragCtrl.left+(customPos||!ctx.x_offset?0:ctx.x_offset)+\"px\";\n\t\t}\n\t},\n\t/*\n\t\tregister drag area\n\t\t@param node \thtml node or ID\n\t\t@param ctrl \toptions dnd master\n\t*/\n\taddDrag:function(node,ctrl){\n\t\tnode = toNode(node);\n\t\tnode.webix_drag = this._getCtrl(ctrl);\n\t\t_event(node,\"dragstart\",preventEvent);\n\t\t_event(node, env.mouse.down, e => this._preStart(e, node, \"mouse\"));\n\t\tif (env.touch)\n\t\t\t_event(node, env.touch.down, e => this._preStart(e, node, \"touch\"));\n\t},\n\t//logic of drag - start, we are not creating drag immediately, instead of that we hears mouse moving\n\t_preStart:function(e, node, pointer){\n\t\tif (DragControl._active){\n\t\t\t//if we have nested drag areas, use the top one and ignore the inner one\n\t\t\tif (DragControl._saved_event == e) return;\n\t\t\tDragControl._preStartFalse(e);\n\t\t\tDragControl.destroyDrag(e);\n\t\t}\n\t\tDragControl._active = node;\n\n\t\tconst evobj = env[pointer].context(e);\n\t\tDragControl._start_pos = evobj;\n\t\tDragControl._saved_event = e;\n\n\t\tconst passive = (pointer === \"touch\") ? { passive:false } : null;\n\t\tDragControl._webix_drag_mm = event(document.body, env[pointer].move, e => DragControl._startDrag(e, pointer), passive);\n\t\tDragControl._webix_drag_mu = event(document, env[pointer].up, DragControl._preStartFalse);\n\n\t\t//need to run here, or will not work in IE\n\t\taddCss(document.body,\"webix_noselect\", 1);\n\t},\n\t//if mouse was released before moving - this is not a dnd, remove event handlers\n\t_preStartFalse:function(e){\n\t\tDragControl._clean_dom_after_drag();\n\t\tDragControl._touch_animation = !e.cancelable;\n\t},\n\t//mouse was moved without button released - dnd started, update event handlers\n\t_startDrag:function(e, pointer){\n\t\tconst touch = (pointer === \"touch\");\n\n\t\t// mouse: allow dnd only on left click\n\t\tif(!touch && DragControl._saved_event.button)\n\t\t\treturn;\n\n\t\t// check touch scroll animation\n\t\tDragControl._touch_animation = !e.cancelable;\n\t\tif (touch && DragControl._touch_animation){\n\t\t\tDragControl._clean_dom_after_drag();\n\t\t\treturn DragControl.destroyDrag(e);\n\t\t}\n\n\t\t//prevent unwanted dnd\n\t\tvar pos = env[pointer].context(e);\n\t\tvar master = DragControl._getActiveDragMaster();\n\n\t\t// only long-touched elements can be dragged\n\t\tvar longTouchLimit = (touch && master && master.$longTouchLimit && !Touch._long_touched);\n\t\tif (longTouchLimit || Math.abs(pos.x-DragControl._start_pos.x)<5 && Math.abs(pos.y-DragControl._start_pos.y)<5)\n\t\t\treturn;\n\n\t\tif (!DragControl._html && !DragControl.createDrag(DragControl._saved_event, pointer))\n\t\t\treturn DragControl._clean_dom_after_drag();\n\t\tDragControl._clean_dom_after_drag(true);\n\n\t\tDragControl.sendSignal(\"start\"); //useless for now\n\n\t\tif (touch) {\n\t\t\t// important: for touch events use e.target as EventTarget\n\t\t\tDragControl._webix_drag_mm = event(e.target, env[pointer].move, e => DragControl._moveDrag(e, pointer), { passive:false });\n\t\t\tDragControl._webix_drag_mu = event(e.target, env[pointer].up, DragControl._stopDrag);\n\t\t} else {\n\t\t\tDragControl._webix_drag_mm = event(document.body, env[pointer].move, e => DragControl._moveDrag(e, pointer));\n\t\t\tDragControl._webix_drag_mu = event(document, env[pointer].up, DragControl._stopDrag);\n\t\t}\n\t\tDragControl._moveDrag(e, pointer, true);\n\t},\n\t//mouse was released while dnd is active - process target\n\t_stopDrag:function(e){\n\t\tDragControl._clean_dom_after_drag();\n\t\tDragControl._saved_event = null;\n\n\t\tif (DragControl._last && e){\t//if some drop target was confirmed\n\t\t\tDragControl.$drop(DragControl._active, DragControl._last, e);\n\t\t\tDragControl.$dragOut(DragControl._active, DragControl._last, null, e);\n\t\t}\n\t\tDragControl.destroyDrag(e);\n\t\tDragControl.sendSignal(\"stop\");\t//useless for now\n\t},\n\t_clean_dom_after_drag:function(still_drag){\n\t\tthis._webix_drag_mm = eventRemove(this._webix_drag_mm);\n\t\tthis._webix_drag_mu = eventRemove(this._webix_drag_mu);\n\t\tif (!still_drag)\n\t\t\tremoveCss(document.body,\"webix_noselect\");\n\t},\n\t//dnd is active and mouse position was changed\n\t_moveDrag:function(e, pointer, first){\n\t\tvar dragCtrl = DragControl;\n\t\tvar pos = getPos(e);\n\n\t\t//give possibility to customize drag position\n\t\tvar customPos = dragCtrl.$dragPos(pos, e);\n\t\t//adjust drag marker position\n\t\tvar ctx = dragCtrl._drag_context;\n\t\tdragCtrl._html.style.top=pos.y+dragCtrl.top+(customPos||!ctx.y_offset?0:ctx.y_offset) +\"px\";\n\t\tdragCtrl._html.style.left=pos.x+dragCtrl.left+(customPos||!ctx.x_offset?0:ctx.x_offset)+\"px\";\n\n\t\t// check landing at least once\n\t\tif (first) dragCtrl._skip = false;\n\n\t\tif (dragCtrl._skip)\n\t\t\tdragCtrl._skip = false;\n\t\telse {\n\t\t\tlet evobj = e;\n\t\t\tif (pointer === \"touch\"){\n\t\t\t\tconst scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;\n\t\t\t\tconst scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;\n\n\t\t\t\tconst context = env[pointer].context(e);\n\t\t\t\tconst target = document.elementFromPoint(context.x - scrollLeft, context.y - scrollTop);\n\t\t\t\tevobj = new Proxy(e, {\n\t\t\t\t\tget: function(obj, prop){\n\t\t\t\t\t\tif (prop === \"target\"){\n\t\t\t\t\t\t\treturn target;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst res = obj[prop];\n\t\t\t\t\t\tif (typeof res === \"function\"){\n\t\t\t\t\t\t\treturn res.bind(e);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn res;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tdragCtrl._checkLand((evobj.target), evobj);\n\t\t}\n\t\t\n\t\treturn preventEvent(e);\n\t},\n\t//check if item under mouse can be used as drop landing\n\t_checkLand:function(node,e){\n\t\twhile (node && node.tagName!=\"BODY\"){\n\t\t\tif (node.webix_drop){\t//if drop area registered\n\t\t\t\tif (this._last && (this._last!=node || node.webix_master))\t//if this area with complex dnd master\n\t\t\t\t\tthis.$dragOut(this._active,this._last,node,e);\t\t\t//inform master about possible mouse-out\n\t\t\t\tif (!this._last || this._last!=node || node.webix_master){\t//if this is new are or area with complex dnd master\n\t\t\t\t\tthis._last=null;\t\t\t\t\t\t\t\t\t\t//inform master about possible mouse-in\n\t\t\t\t\tthis._landing=this.$dragIn(DragControl._active,node,e);\n\t\t\t\t\tif (this._landing)\t//landing was rejected\n\t\t\t\t\t\tthis._last=node;\n\t\t\t\t\treturn;\t\t\t\t\n\t\t\t\t} \n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnode=node.parentNode;\n\t\t}\n\t\tif (this._last)\t//mouse was moved out of previous landing, and without finding new one \n\t\t\tthis._last = this._landing = this.$dragOut(this._active,this._last,null,e);\n\t},\n\t//mostly useless for now, can be used to add cross-frame dnd\n\tsendSignal:function(signal){\n\t\tDragControl.active=(signal==\"start\");\n\t\tcallEvent(\"onDragMode\", [signal]);\n\t},\n\t\n\t//return master for html area\n\tgetMaster:function(t){\n\t\treturn this._drag_masters[t.webix_drag||t.webix_drop];\n\t},\n\t//return dhd-context object\n\tgetContext:function(){\n\t\treturn this._drag_context;\n\t},\n\tgetNode:function(){\n\t\treturn this._html;\n\t},\n\t//called when dnd is initiated, must create drag representation\n\tcreateDrag:function(e, pointer){\n\t\tvar a = DragControl._active;\n\n\t\tDragControl._drag_context = {};\n\t\tvar master = this._drag_masters[a.webix_drag];\n\t\tvar drag_container;\n\n\t\t//if custom method is defined - use it\n\t\tif (master.$dragCreate){\n\t\t\tdrag_container = master.$dragCreate(a,e,pointer);\n\t\t\tif (!drag_container) return false;\n\t\t\tthis._setDragOffset(e);\n\t\t\tdrag_container.style.position = \"absolute\";\n\t\t} else {\n\t\t//overvise use default one\n\t\t\tvar text = DragControl.$drag(a,e,pointer);\n\t\t\tDragControl._setDragOffset(e);\n\n\t\t\tif (!text) return false;\n\t\t\tdrag_container = document.createElement(\"DIV\");\n\t\t\tdrag_container.innerHTML=text;\n\t\t\tdrag_container.className=\"webix_drag_zone\";\n\t\t\tdocument.body.appendChild(drag_container);\n\n\t\t\tvar context = DragControl._drag_context;\n\t\t\tif (context.html){\n\t\t\t\tcontext.x_offset = -Math.round(drag_container.offsetWidth * 0.5);\n\t\t\t\tcontext.y_offset = -Math.round(drag_container.offsetHeight * 0.75);\n\t\t\t}\n\t\t}\n\t\t/*\n\t\t\tdragged item must have topmost z-index\n\t\t\tin some cases item already have z-index\n\t\t\tso we will preserve it if possible\n\t\t*/\n\t\tdrag_container.style.zIndex = Math.max(drag_container.style.zIndex,zIndex());\n\n\t\tDragControl._skipDropH = event(drag_container, env[pointer].move, DragControl._skip_mark);\n\n\t\tif (!DragControl._drag_context.from)\n\t\t\tDragControl._drag_context = {source:a, from:a};\n\t\t\n\t\tDragControl._html = drag_container;\n\t\treturn true;\n\t},\n\t//helper, prevents unwanted mouse-out events\n\t_skip_mark:function(){\n\t\tDragControl._skip = true;\n\t},\n\t//after dnd end, remove all traces and used html elements\n\tdestroyDrag:function(e){\n\t\tvar a = DragControl._active;\n\t\tvar master = this._drag_masters[a.webix_drag];\n\n\t\tif (DragControl._skipDropH)\n\t\t\tDragControl._skipDropH = eventRemove(DragControl._skipDropH);\n\t\t\n\t\tif (master && master.$dragDestroy){\n\t\t\tif(DragControl._html)\n\t\t\t\tmaster.$dragDestroy(a,DragControl._html,e);\n\t\t} else\n\t\t\tremove(DragControl._html);\n\n\t\tif (master && master._auto_scroll_delay)\n\t\t\tmaster._auto_scroll_delay = window.clearTimeout(master._auto_scroll_delay);\n\n\t\tif (DragControl._dropHTML)\n\t\t\tremove(DragControl._dropHTML);\n\n\t\tDragControl._landing=DragControl._active=DragControl._last=DragControl._html=DragControl._dropHTML=null;\n\t\tDragControl._drag_context = null;\n\t},\n\t_getActiveDragMaster: function(){\n\t\treturn DragControl._drag_masters[DragControl._active.webix_drag];\n\t},\n\ttop:0,\t //relative position of drag marker to mouse cursor\n\tleft:0,\n\t_setDragOffset:function(e){\n\t\tconst pos = DragControl._start_pos;\n\t\tconst ctx = DragControl._drag_context;\n\n\t\tif(typeof ctx.x_offset != \"undefined\" && typeof ctx.y_offset != \"undefined\")\n\t\t\treturn null;\n\n\t\tctx.x_offset = ctx.y_offset = 0;\n\t\tconst m = DragControl._getActiveDragMaster();\n\t\tif (m._getDragItemPos && m !== this){\n\t\t\tconst itemPos = m._getDragItemPos(pos,e);\n\t\t\tif (itemPos){\n\t\t\t\tctx.x_offset = itemPos.x - pos.x;\n\t\t\t\tctx.y_offset = itemPos.y - pos.y;\n\t\t\t}\n\t\t}\n\t},\n\t$dragPos:function(pos, e){\n\t\tvar m=this._drag_masters[DragControl._active.webix_drag];\n\t\tif (m.$dragPos && m!=this){\n\t\t\tm.$dragPos(pos, e, DragControl._html);\n\t\t\treturn true;\n\t\t}\n\t},\n\t//called when mouse was moved in drop area\n\t$dragIn:function(s,t,e){\n\t\tvar m=this._drag_masters[t.webix_drop];\n\t\tif (m.$dragIn && m!=this) return m.$dragIn(s,t,e);\n\t\tt.className=t.className+\" webix_drop_zone\";\n\t\treturn t;\n\t},\n\t//called when mouse was moved out drop area\n\t$dragOut:function(s,t,n,e){\n\t\tvar m=this._drag_masters[t.webix_drop];\n\t\tif (m.$dragOut && m!=this) return m.$dragOut(s,t,n,e);\n\t\tt.className=t.className.replace(\"webix_drop_zone\",\"\");\n\t\treturn null;\n\t},\n\t//called when mouse was released over drop area\n\t$drop:function(s,t,e){\n\t\tvar m=this._drag_masters[t.webix_drop];\n\t\tDragControl._drag_context.from = DragControl.getMaster(s);\n\t\tif (m.$drop && m!=this) return m.$drop(s,t,e);\n\t\tt.appendChild(s);\n\t},\n\t//called when dnd just started\n\t$drag:function(s,e,p){\n\t\tvar m=this._drag_masters[s.webix_drag];\n\t\tif (m.$drag && m!=this) return m.$drag(s,e,p);\n\t\treturn \"
\"+s.innerHTML+\"
\";\n\t}\t\n};\n\n//global touch-drag handler\nattachEvent(\"onLongTouch\", function(ev){\n\tconst active = DragControl._active;\n\tif(!DragControl._touch_animation && active && active.contains(ev.target))\n\t\tDragControl._createTouchDrag(ev, \"touch\");\n});\n\n\nexport default DragControl;","import {pos as getPos, offset} from \"../webix/html\";\nimport {protoUI, ui, $$} from \"../ui/core\";\nimport animate from \"../webix/animate\";\nimport {$active} from \"../webix/skin\";\n\nimport state from \"../core/state\";\nimport env from \"../webix/env\";\nimport UIManager from \"../core/uimanager\";\nimport Destruction from \"../core/destruction\";\n\nimport {zIndex} from \"../ui/helpers\";\nimport {toNode, delay, clone, uid, extend} from \"../webix/helpers\";\nimport {_event} from \"../webix/htmlevents\";\nimport {assert} from \"../webix/debug\";\nimport {callEvent, attachEvent} from \"../webix/customevents\";\n\nimport EventSystem from \"../core/eventsystem\";\nimport Movable from \"../core/movable\";\nimport Modality from \"../core/modality\";\nimport ResizeArea from \"../core/resizearea\";\n\nimport baseview from \"./baseview\";\nimport base from \"./view\";\n\nconst api = {\n\tname:\"window\",\n\n\t$init:function(config){\n\t\tthis._viewobj.innerHTML = \"
\";\n\n\t\tthis._contentobj = this._viewobj.firstChild;\n\t\tthis._headobj = this._contentobj.childNodes[0];\n\t\tthis._dataobj = this._bodyobj = this._contentobj.childNodes[1];\n\t\tthis._viewobj.className +=\" webix_window\";\n\n\t\tthis._viewobj.setAttribute(\"role\", \"dialog\");\n\t\tthis._viewobj.setAttribute(\"tabindex\", \"0\");\n\n\t\tthis._head_cell = this._body_cell = null;\n\t\tthis._settings._inner = {top:false, left:false, right:false, bottom:false }; //set border flags\n\t\tif (!config.id) config.id = uid();\n\n\t\t_event(this._contentobj, \"click\", this._ignore_clicks, {bind:this});\n\t\t_event(this._contentobj, \"click\", function(){\n\t\t\t// brings a window to the front of other windows\n\t\t\tif(!this._settings.zIndex && this._settings.toFront){\n\t\t\t\tthis._viewobj.style.zIndex = zIndex();\n\t\t\t}\n\t\t}, {bind:this, capture:true});\n\n\t\t// hidden_setter handling\n\t\tif(config.modal)\n\t\t\tthis._modal = true;\n\t\t// head_setter handling\n\t\tif(config.headHeight)\n\t\t\tthis._settings.headHeight = config.headHeight;\n\t\tif(config.close)\n\t\t\tthis._settings.close = config.close;\n\n\t\tthis.attachEvent(\"onViewMoveEnd\", function(){\n\t\t\tif(this._settings.position)\n\t\t\t\tdelete this._settings.position;\n\t\t});\n\t},\n\t_ignore_clicks:function(e){\n\t\tconst popups = state._popups;\n\t\tlet index = popups.find(this);\n\t\tif (index == -1)\n\t\t\tindex = popups.length - 1;\n\n\t\te.click_view = index;\n\t},\n\tgetChildViews:function(){\n\t\tif (this._head_cell)\n\t\t\treturn [this._head_cell, this._body_cell];\n\t\telse\n\t\t\treturn [this._body_cell];\n\t},\n\tzIndex_setter:function(value){\n\t\tthis._viewobj.style.zIndex = value;\n\t\treturn value;\n\t},\n\t_remove:function(){ \n\t\tthis.body_setter();\n\t},\n\t_replace:function(new_view, old_view){\n\t\told_view = old_view || this._body_cell;\n\t\tconst isBody = old_view == this._body_cell;\n\n\t\told_view.destructor();\n\n\t\tif(isBody)\n\t\t\tthis._body_cell = new_view;\n\t\telse \n\t\t\tthis._head_cell = new_view;\n\n\t\t(isBody ? this._bodyobj : this._headobj).appendChild(new_view._viewobj);\n\n\t\tconst cell = new_view._viewobj.style;\n\n\t\tlet settings = { top:true, left:true, right:true, bottom:true };\n\t\tlet size = \"0px\";\n\n\t\tif(new_view.config.borderless === false){\n\t\t\tsettings = clone(this._settings._inner);\n\t\t\tsize = \"1px\";\n\t\t}\n\t\tnew_view._settings._inner = settings;\n\t\tcell.borderTopWidth = cell.borderBottomWidth = cell.borderLeftWidth = cell.borderRightWidth = size;\n\n\t\tthis.resize(true);\n\t},\n\tshow:function(node, mode, point){\n\t\tif (node === true){\n\t\t\t//recursive call from some child item\n\t\t\tif (!this._settings.hidden)\n\t\t\t\treturn;\n\t\t\tnode = null;\n\t\t}\n\n\t\tif(!this.callEvent(\"onBeforeShow\",arguments))\n\t\t\treturn false;\n\n\t\tthis._settings.hidden = false;\n\t\tthis._viewobj.style.zIndex = zIndex(this._settings.zIndex);\n\t\tif (this._settings.modal || this._modal){\n\t\t\tthis._modal_set(true);\n\t\t\tthis._modal = null; // hidden_setter handling\n\t\t}\n\n\t\tlet elPos, dx, dy;\n\t\tmode = mode || {};\n\t\tif (!mode.pos)\n\t\t\tmode.pos = this._settings.relative;\n\n\t\t//get position of source html node\n\t\t//we need to show popup which pointing to that node\n\t\tif (node){\n\t\t\t//if event was provided - get node info from it\n\t\t\tif (typeof node == \"object\" && !node.tagName){\n\t\t\t\t/*below logic is far from ideal*/\n\t\t\t\tif (node.target){\n\t\t\t\t\telPos = getPos(node);\n\t\t\t\t\tdx = 20;\n\t\t\t\t\tdy = 5;\n\t\t\t\t} else\n\t\t\t\t\telPos = node;\n\t\t\t} else {\n\t\t\t\tnode = toNode(node);\n\t\t\t\tassert(node,\"Not existing target for window:show\");\n\t\t\t\telPos = offset(node);\n\t\t\t}\n\n\t\t\t//size of body, we need to fit popup inside\n\t\t\tconst x = Math.max(window.innerWidth || 0, document.body.offsetWidth);\n\t\t\tconst y = Math.max(window.innerHeight || 0, document.body.offsetHeight);\n\n\t\t\t//size of node, near which popup will be rendered\n\t\t\tdx = dx || node.offsetWidth || 0;\n\t\t\tdy = dy || node.offsetHeight || 0;\n\t\t\t//size of popup element\n\t\t\tconst size = this._last_size;\n\n\t\t\tlet fin_x = elPos.x;\n\t\t\tlet fin_y = elPos.y;\n\t\t\tlet point_y = 0;\n\t\t\tlet point_x = 0;\n\t\t\tlet scrollLeft = 0, scrollTop = 0;\n\t\t\tconst fit = this._settings.autofit;\n\t\t\tif (fit){\n\t\t\t\tconst nochange = (fit === \"node\");\n\t\t\t\tlet delta_x = 6, delta_y = 6, delta_point = 6;\n\t\t\t\tif (!this._settings.point)\n\t\t\t\t\tdelta_x = delta_y = delta_point = 0;\n\n\t\t\t\t//default pointer position - top \n\t\t\t\tpoint = \"top\";\n\t\t\t\tfin_y=0; fin_x = 0;\n\n\t\t\t\tscrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;\n\t\t\t\t//if we want to place menu at righ, but there is no place move it to left instead\n\t\t\t\tif (x - elPos.x - dx < size[0] && mode.pos == \"right\" && !nochange)\n\t\t\t\t\tmode.pos = \"left\";\n\n\t\t\t\tif (mode.pos == \"right\"){\n\t\t\t\t\tfin_x = elPos.x+delta_x+dx; \n\t\t\t\t\tdelta_y = -dy;\n\t\t\t\t\tpoint = \"left\";\n\t\t\t\t\tpoint_y = Math.round(elPos.y+dy/2);\n\t\t\t\t\tpoint_x = fin_x - delta_point;\n\t\t\t\t} else if (mode.pos == \"left\"){\n\t\t\t\t\tfin_x = elPos.x-delta_x-size[0]-1;\n\t\t\t\t\tdelta_y = -dy;\n\t\t\t\t\tpoint = \"right\";\n\t\t\t\t\tpoint_y = Math.round(elPos.y+dy/2);\n\t\t\t\t\tpoint_x = fin_x + size[0]+1;\n\t\t\t\t} else {\n\t\t\t\t\t//left border of screen\n\t\t\t\t\tif (elPos.x < scrollLeft){\n\t\t\t\t\t\tfin_x = scrollLeft;\n\t\t\t\t\t//popup exceed the right border of screen\n\t\t\t\t\t} else if (x+scrollLeft-elPos.x > size[0]){\n\t\t\t\t\t\tfin_x = elPos.x; //aligned\n\t\t\t\t\t} else{\n\t\t\t\t\t\tfin_x = x+scrollLeft-delta_x-size[0]; //not aligned\n\t\t\t\t\t}\n\n\t\t\t\t\tpoint_x = Math.round(elPos.x+dx/2);\n\t\t\t\t\t//when we have a small popup, point need to be rendered at center of popup\n\t\t\t\t\tpoint_x = Math.min(point_x, fin_x + size[0] - delta_point*3);\n\t\t\t\t}\n\n\t\t\t\t//if height is not fixed - use default position\n\t\t\t\tscrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;\n\t\t\t\tif (((!size[1] || (y+scrollTop-dy-elPos.y-delta_y > size[1])) || nochange) && mode.pos != \"top\"){\n\t\t\t\t\t//bottom\t\n\t\t\t\t\tfin_y = dy+elPos.y+delta_y - (!this._settings.point ? 0: 4);\n\t\t\t\t\tif (!point_y){\n\t\t\t\t\t\tpoint = \"top\";\n\t\t\t\t\t\tpoint_y = fin_y-delta_point;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t//top\n\t\t\t\t\tfin_y = elPos.y-delta_y - size[1];\n\t\t\t\t\tif (fin_y < 0){\n\t\t\t\t\t\tfin_y = 0; \n\t\t\t\t\t\t//left|right point can be used, but there is no place for top point\n\t\t\t\t\t\tif (point == \"top\") point = false;\n\t\t\t\t\t} else if (!point_y){\n\t\t\t\t\t\tpoint = \"bottom\";\n\t\t\t\t\t\tfin_y --;\n\t\t\t\t\t\tpoint_y = fin_y+size[1]+1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst deltax = (mode.x || 0);\n\t\t\tconst deltay = (mode.y || 0);\n\n\t\t\tconst fixed = this._checkFixedPosition();\n\t\t\tthis.$view.style.position = fixed ? \"fixed\" : \"absolute\";\n\t\t\tif (fixed){\n\t\t\t\tfin_y = fin_y - scrollTop;\n\t\t\t\tpoint_y = point_y - scrollTop;\n\t\t\t}\n\n\t\t\tthis.setPosition(fin_x+deltax, fin_y+deltay);\n\t\t\tif (this._set_point){\n\t\t\t\tif (point && this._settings.point)\n\t\t\t\t\tthis._set_point(point,point_x+deltax, point_y+deltay, fixed);\n\t\t\t\telse\n\t\t\t\t\tthis._hide_point();\n\t\t\t}\n\t\t} else\n\t\t\tthis._setPosition(this._settings.left, this._settings.top);\n\n\t\tthis._viewobj.style.display = \"block\";\n\t\tthis._hide_timer = 1;\n\t\tdelay(function(){ this._hide_timer = 0; }, this, [], (env.fastClick ? 100 : 400));\n\n\t\tthis._render_hidden_views();\n\n\t\tif (this.config.autofocus){\n\t\t\tthis._prev_focus = UIManager.getFocus();\n\t\t\tUIManager.setFocus(this);\n\t\t}\n\n\t\tif (-1 == state._popups.find(this))\n\t\t\tstate._popups.push(this);\n\n\t\tthis.callEvent(\"onShow\",[]);\n\t}, \n\t_hide:function(e){\n\t\t//do not hide modal windows\n\t\tif (this._settings.hidden || this._settings.modal || !this._settings.escHide || this._hide_timer) return;\n\t\t//do not hide submenu when clicking on menu folder\n\t\tif (e && e.showpopup && (e.showpopup == this._settings.id || (this.getTopMenu && this.getTopMenu()._settings.id == e.showpopup))) return;\n\t\t//do not hide popup, when starting dnd with a long touch\n\t\tif (e && env.touch && e.longtouch_drag) return;\n\t\t//do not hide popup, when we have modal layer above the popup\n\t\tif (state._modality.length && this._viewobj.style.zIndex <= Math.max(...state._modality)) return;\n\n\t\t//ignore inside clicks and clicks in child-popups\n\n\t\tif (e){\n\t\t\tlet index = e.click_view;\n\t\t\tif (!index && index !== 0) index = -1;\n\n\t\t\tconst myindex = state._popups.find(this);\n\n\t\t\tif (myindex <= index) return;\n\t\t}\n\n\t\tthis._hide_single();\n\t},\n\thidden_setter:function(value){\n\t\tif(value) \n\t\t\tthis.hide();\n\t\telse\n\t\t\tthis.show();\n\t\treturn !!value;\n\t},\n\thide:function(){\n\t\tconst index = this._hide_single();\n\t\tthis._hide_sub_popups(index);\n\t},\n\t_hide_single:function(){\n\t\tif (this.$destructed || this._settings.hidden) return;\n\n\t\tif (this._settings.modal)\n\t\t\tthis._modal_set(false);\n\n\t\tthis._hiding_process();\n\n\t\tif (this._settings.master){\n\t\t\tconst view = $$(this._settings.master);\n\t\t\tif (view && view.touchable && view._settings.popup === this._settings.id){\n\t\t\t\tconst node = view.getInputNode() || view.getNode();\n\t\t\t\tnode.setAttribute(\"aria-expanded\", false);\n\t\t\t}\n\t\t}\n\n\t\tif (this._settings.autofocus){\n\t\t\tconst el = document.activeElement;\n\t\t\t//as result of hotkey, we can have a activeElement set to document.body\n\t\t\tif (el && this._viewobj && (this._viewobj.contains(el) || el === document.body)){\n\t\t\t\tUIManager.setFocus(this._prev_focus);\n\t\t\t\tthis._prev_focus = null;\n\t\t\t}\n\t\t}\n\n\t\t// clear state\n\t\tconst index = state._popups.find(this);\n\t\tif (index > -1)\n\t\t\tstate._popups.removeAt(index);\n\n\t\treturn index;\n\t},\n\t_hiding_process:function(){\n\t\tif (this._settings.position == \"top\"){\n\t\t\tanimate(this._viewobj, {type: \"slide\", x:0, y:-(this._content_height+20), duration: 300,\n\t\t\t\tcallback:this._hide_callback, master:this});\n\t\t} else \n\t\t\tthis._hide_callback();\n\t},\n\t//hide all child-popups\n\t_hide_sub_popups:function(index){\n\t\tif (index > -1){\n\t\t\tconst order = state._popups;\n\t\t\tfor (let i=order.length-1; i>=index; i--)\n\t\t\t\tif (order[i]._hide_point)\t//hide only popups, skip windows\n\t\t\t\t\torder[i]._hide_single();\n\t\t}\n\t},\n\tdestructor: function() {\n\t\tthis.hide();\n\t\tDestruction.destructor.apply(this, []);\n\t},\n\t_hide_callback:function(){\n\t\tif (!this.$destructed){\n\t\t\tthis._viewobj.style.display = \"none\";\n\t\t\tthis._settings.hidden = true;\n\t\t\tthis.callEvent(\"onHide\",[]);\n\t\t}\n\t},\n\tclose:function(){\n\t\tthis.destructor(); \n\t},\n\t_inner_body_set:function(value){\n\t\tif (typeof value.borderless == \"undefined\")\n\t\t\tvalue.borderless = true;\n\t},\n\tbody_setter:function(value){\n\t\tif (typeof value != \"object\")\n\t\t\tvalue = {template:value };\n\t\tthis._inner_body_set(value);\n\n\t\tstate._parent_cell = this;\n\t\tthis._body_cell = ui._view(value);\n\n\t\tthis._bodyobj.appendChild(this._body_cell._viewobj);\n\t\treturn value;\n\t},\n\thead_setter:function(value){\n\t\tif (value === false) return value;\n\n\t\tconst height = this._settings.headHeight;\n\t\tconst text = typeof value == \"string\";\n\t\tconst config = { height, padding:0, css: \"webix_win_title\", type:\"header\", borderless:true };\n\t\tif(text){\n\t\t\tthis._viewobj.setAttribute(\"aria-label\", value);\n\t\t\tvalue = { template:value };\n\t\t}\n\t\tif(value.view == \"template\" || (!value.view && value.template)){\n\t\t\textend(value, config);\n\t\t}\n\t\tif(text && this.config.close){\n\t\t\tvalue = { padding:{ left: $active.inputHeight+2, right:2 }, cols:[\n\t\t\t\tvalue,\n\t\t\t\t{ height, view:\"icon\", icon:\"wxi-close\", click:()=>{\n\t\t\t\t\tthis.hide();\n\t\t\t\t}}\n\t\t\t]};\n\t\t}\n\t\telse\n\t\t\textend(value, {borderless:true});\n\n\t\tstate._parent_cell = this;\n\t\tthis._head_cell = ui._view(value);\n\n\t\tconst template = this._head_cell._viewobj.querySelector(\".webix_win_title>div\");\n\t\tif(template)\n\t\t\ttemplate.style.lineHeight = height + \"px\";\n\n\t\tthis._headobj.appendChild(this._head_cell._viewobj);\n\t\treturn value;\n\t},\n\tgetBody:function(){\n\t\treturn this._body_cell;\n\t},\n\tgetHead:function(){\n\t\treturn this._head_cell;\n\t},\n\tadjust:function(){ return this.resize(); },\n\tresizeChildren:function(){\n\t\tif (this._body_cell)\n\t\t\tthis.resize();\n\t},\n\tresize:function(){\n\t\tbaseview.api.adjust.call(this);\n\t\tcallEvent(\"onResize\", []);\n\t\tif (this.isVisible()){\n\t\t\tthis._setPosition(this._settings.left, this._settings.top);\n\t\t}\n\t},\n\t_checkFixedPosition: function() {\n\t\tif(this._settings.master) {\n\t\t\tconst top = $$(this._settings.master).getTopParentView().$view;\n\t\t\treturn top && top.style.position === \"fixed\";\n\t\t}\n\t\treturn false;\n\t},\n\t_setPosition:function(x,y){\n\t\tif ((this._settings.position || this._checkFixedPosition())){\n\t\t\tthis.$view.style.position = \"fixed\";\n\n\t\t\tconst width = this._content_width;\n\t\t\tconst height = this._content_height;\n\t\t\tif (width <= 0 || height <= 0) return;\n\n\t\t\tconst maxWidth = (window.innerWidth||document.documentElement.offsetWidth);\n\t\t\tconst maxHeight = (window.innerHeight||document.documentElement.offsetHeight);\n\t\t\tlet left = Math.round((maxWidth-width)/2);\n\t\t\tlet top = Math.round((maxHeight-height)/2);\n\n\t\t\tif (typeof this._settings.position == \"function\"){\n\t\t\t\tconst state = { \tleft:left, top:top, \n\t\t\t\t\twidth:width, height:height, \n\t\t\t\t\tmaxWidth:maxWidth, maxHeight:maxHeight };\n\t\t\t\tthis._settings.position.call(this, state);\n\t\t\t\tif (state.width != width || state.height != height){\n\t\t\t\t\tthis._settings.width = state.width;\n\t\t\t\t\tthis._settings.height = state.height;\n\t\t\t\t\tthis.$setSize(state.width, state.height);\n\t\t\t\t}\n\t\t\t\tthis.setPosition(state.left, state.top);\n\t\t\t} else {\n\t\t\t\tif (this._settings.position == \"top\"){\n\t\t\t\t\ttop = -1*height;\n\t\t\t\t}\n\t\t\t\t//popup inside a fixed win\n\t\t\t\tif(!this._settings.position){\n\t\t\t\t\tleft = this._settings.left || left;\n\t\t\t\t\ttop = this._settings.top || top;\n\t\t\t\t}\n\t\t\t\tthis.setPosition(left, top);\n\t\t\t}\n\n\t\t\tif (this._settings.position == \"top\")\n\t\t\t\tanimate(this._viewobj, {type: \"slide\", x:0, y:height-((this._settings.padding||0)*2), duration: 300 ,callback:this._topPositionCallback, master:this});\n\t\t} else \n\t\t\tthis.setPosition(x,y);\n\t},\n\t_topPositionCallback:function(node){\n\t\tanimate.clear(node);\n\t\tthis._settings.top=-((this._settings.padding||0)*2);\n\t\tthis.setPosition(this._settings.left, this._settings.top);\n\t},\n\tsetPosition:function(x,y){\n\t\tthis._viewobj.style.top = y+\"px\";\n\t\tthis._viewobj.style.left = x+\"px\";\n\t\tthis._settings.left = x; this._settings.top=y;\n\t},\n\t$getSize:function(dx, dy){\n\t\tconst _borders = this._settings._inner;\n\t\tif (_borders){\n\t\t\tdx += (_borders.left?0:1)+(_borders.right?0:1);\n\t\t\tdy += (_borders.top?0:1)+(_borders.bottom?0:1);\n\t\t}\n\t\t//line between head and body\n\t\tif (this._settings.head)\n\t\t\tdy += 1;\n\n\t\tconst size = this._body_cell.$getSize(0,0);\n\t\tlet headMinWidth = 0;\n\t\tif (this._head_cell){\n\t\t\tconst head_size = this._head_cell.$getSize(0,0);\n\t\t\tif (head_size[3]==head_size[2])\n\t\t\t\tthis._settings.headHeight = head_size[3];\n\t\t\tdy += this._settings.headHeight;\n\t\t\theadMinWidth = head_size[0];\n\t\t}\n\n\t\tif (this._settings.fullscreen){\n\t\t\tconst width = window.innerWidth || document.body.clientWidth;\n\t\t\tconst height = window.innerHeight || document.body.clientHeight;\n\t\t\treturn [width, width, height, height];\n\t\t}\n\n\t\t//get layout sizes\n\t\tconst self_size = base.api.$getSize.call(this, 0, 0);\n\n\t\t//use child settings if layout's one was not defined\n\t\tif (headMinWidth && size[1] > 100000)\n\t\t\tsize[0] = Math.max(headMinWidth, size[0]);\n\n\t\tself_size[1] = Math.min(self_size[1],(size[1]>=100000&&self_size[1]>=100000?Math.max(size[0], self_size[0]):size[1])+dx);\n\t\tself_size[3] = Math.min(self_size[3],(size[3]>=100000&&self_size[3]>=100000?Math.max(size[2], self_size[2]):size[3])+dy);\n\n\t\tself_size[0] = Math.min(Math.max(self_size[0],size[0] + dx), self_size[1]);\n\t\tself_size[2] = Math.min(Math.max(self_size[2],size[2] + dy), self_size[3]);\n\n\t\treturn self_size;\n\t},\n\t$setSize:function(x,y){\n\t\tbase.api.$setSize.call(this,x,y);\n\t\tx = this._content_width;\n\t\ty = this._content_height;\n\t\tif (this._settings.head === false) {\n\t\t\tthis._headobj.style.display=\"none\";\n\t\t\tthis._body_cell.$setSize(x,y);\n\t\t} else { \n\t\t\tthis._head_cell.$setSize(x,this._settings.headHeight);\n\t\t\tthis._body_cell.$setSize(x,y-this._settings.headHeight);\n\t\t}\n\t},\n\t$skin:function(){\n\t\tthis.defaults.headHeight = $active.barHeight;\n\t},\n\tdefaults:{\n\t\ttop:0,\n\t\tleft:0,\n\t\tautofit:true,\n\t\trelative:\"bottom\",\n\t\tbody:\"\",\n\t\thead:\"\",\n\t\thidden: true,\n\t\tautofocus:true,\n\t\tminWidth:300,\n\t\tminHeight:200,\n\t\tescHide:true\n\t}\n};\n\n//global longtouch handler\nattachEvent(\"onLongTouch\", function(ev){\n\tif (!ev || !ev.target) return;\n\n\tlet view = $$(ev.target);\n\tif (view){\n\t\tview = view.queryView(a => !a.getParentView(), \"parent\")||view;\n\n\t\tconst popups = state._popups;\n\t\tconst index = popups.find(view);\n\t\tif (index !== -1) ev.click_view = index;\n\t}\n});\n\nconst view = protoUI(api, base.view, Movable, Modality, EventSystem, ResizeArea);\nexport default {api, view};","import {create, insertBefore, remove} from \"../webix/html\";\nimport env from \"../webix/env\";\nimport {extend, bind} from \"../webix/helpers\";\n\n\nconst CustomPrint = {\n\t$customPrint:function(options, htmlOnly){\n\t\tif(this._prePrint(options, htmlOnly))\n\t\t\treturn true;\n\n\t\tvar tableData = this._getTableArray(options);\n\t\tvar table = this._getTableHTML(tableData, options);\n\n\t\tif(htmlOnly)\n\t\t\treturn table;\n\n\t\tvar doc = create(\"div\", { \"class\":\"webix_ui_print\"});\n\t\tdoc.appendChild(table);\n\n\t\tinsertBefore(doc, options.docFooter, document.body);\n\t\twindow.print();\n\t\t\n\t\tremove(doc);\n\t},\n\t_prePrint:function(options, htmlOnly){\n\t\tif(!htmlOnly && (this.config.layout ==\"y\" || options.scroll || this.config.prerender || this.config.autoheight)) return true;\n\t\t\n\t\tif(this.config.layout ==\"x\")\n\t\t\textend(options || {}, {xCount:this.count(), nobreaks:true}, true);\n\t},\n\t_getPageWidth:function(options){\n\t\tvar size = options.size;\n\t\tvar width = size[options.mode == \"portrait\"?\"width\":\"height\"];\n\t\t\n\t\treturn Math.min(width*env.printPPI-2*env.printMargin);\n\t},\n\t_getTableArray:function(options, base, start){\n\t\tvar maxWidth = options.fit ==\"page\" ? Infinity : this._getPageWidth(options);\n\t\tvar xCount = options.xCount || this._getVisibleRange()._dx;\n\n\t\tvar tableArray = [];\n\t\tvar colrow = [];\n\t\tvar width = 0;\n\t\t\n\t\tvar newTableStart, rownum, colnum;\n\n\t\tstart = start || 0;\n\t\tbase = base || [];\n\n\t\tfor(var i = 0; i=start){\n\t\t\t\twidth += this.type.width;\n\t\t\t\t\n\t\t\t\t//start a new table, if cells do not fit page width\n\t\t\t\tif(width > maxWidth && colnum>start){ // 'colnum>start' ensures that a single long cell will have to fit the page\n\t\t\t\t\tnewTableStart = colrow.length+start;\n\t\t\t\t\ttableArray.push(colrow);\n\t\t\t\t\ti = i+(xCount-colrow.length);\n\t\t\t\t\tcolrow = [];\n\t\t\t\t\twidth = 0;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tvar cellValue = this.type.template(obj, this.type);\n\t\t\t\tvar className = this._itemClassName;\n\t\t\t\t\n\t\t\t\tvar style = {\n\t\t\t\t\tdisplay:\"table-cell\",\n\t\t\t\t\theight:this.type.height + \"px\",\n\t\t\t\t\twidth:this.type.width + \"px\"\n\t\t\t\t};\n\t\t\t\t//push a cell to a row\n\t\t\t\tcolrow.push({\n\t\t\t\t\ttxt: cellValue,\n\t\t\t\t\tclassName: className+\" \"+(obj.$css || \"\"),\n\t\t\t\t\tstyle: style\n\t\t\t\t});\n\t\t\t\t//push a row to a table and start a new row\n\t\t\t\tif((i+1)%xCount === 0){\n\t\t\t\t\ttableArray.push(colrow);\n\t\t\t\t\tcolrow = [];\n\t\t\t\t\twidth = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\n\t\tbase.push(tableArray);\n\n\t\tif(newTableStart)\n\t\t\tthis._getTableArray(options, base, newTableStart);\t\n\n\t\treturn base;\n\t},\n\t_getTableHTML:function(tableData, options){\n\t\t\n\t\tvar container = create(\"div\");\n\n\t\ttableData.forEach(bind(function(table, i){\n\n\t\t\tvar tableHTML = create(\"table\", {\n\t\t\t\t\"class\":\"webix_table_print \"+this.$view.className,\n\t\t\t\t\"style\":\"border-collapse:collapse\"\n\t\t\t});\n\n\t\t\ttable.forEach(function(row){\n\t\t\t\tvar tr = create(\"tr\");\n\n\t\t\t\trow.forEach(function(column){\n\t\t\t\t\tvar td = create(\"td\");\n\n\n\t\t\t\t\tif (column.txt) td.innerHTML = column.txt;\n\t\t\t\t\tif (column.className) td.className = column.className;\n\t\t\t\t\tif (column.style) {\n\t\t\t\t\t\tvar keys = Object.keys(column.style);\n\t\t\t\t\t\tkeys.forEach(function(key){\n\t\t\t\t\t\t\tif (column.style[key])\n\t\t\t\t\t\t\t\ttd.style[key] = column.style[key];\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif(column.span){\n\t\t\t\t\t\tif(column.span.colspan > 1)\n\t\t\t\t\t\t\ttd.colSpan = column.span.colspan;\n\t\t\t\t\t\tif(column.span.rowspan > 1)\n\t\t\t\t\t\t\ttd.rowSpan = column.span.rowspan;\n\t\t\t\t\t}\n\t\t\t\t\ttr.appendChild(td);\n\t\t\t\t});\n\t\t\t\ttableHTML.appendChild(tr);\n\t\t\t});\n\t\t\tcontainer.appendChild(tableHTML);\n\n\t\t\tif(!options.nobreaks && i+1 < tableData.length){\n\t\t\t\tvar br = create(\"DIV\", {\"class\":\"webix_print_pagebreak\"});\n\t\t\t\tcontainer.appendChild(br);\n\t\t\t}\n\t\t\t\n\t\t}, this));\n\n\t\treturn container;\n\t}\n};\n\nexport default CustomPrint;","import {pos as getPos, create, remove, removeCss, preventEvent, addCss} from \"../webix/html\";\nimport state from \"../core/state\";\nimport {$$} from \"../ui/core\";\nimport {delay} from \"../webix/helpers\";\n\nimport env from \"../webix/env\";\nimport {$active} from \"../webix/skin\";\nimport {_event, event, eventRemove} from \"../webix/htmlevents\";\nimport {attachEvent} from \"../webix/customevents\";\n\n\nconst CustomScroll = {\n\tscrollStep: 40,\n\tinit:function(){\n\t\tif (!env.scrollSize || env.$customScroll)\n\t\t\treturn !!env.$customScroll;\n\n\t\tthis.scrollStep = $active.rowHeight;\n\t\tenv.$customScroll = true;\n\t\tenv.scrollSize = 0;\n\n\t\tstate.destructors.push({\n\t\t\tobj:{\n\t\t\t\tdestructor:function(){\n\t\t\t\t\tthis._last_active_node = null;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tattachEvent(\"onReconstruct\", CustomScroll._on_reconstruct);\n\t\tattachEvent(\"onResize\", CustomScroll._on_reconstruct);\n\n\t\t//adjusts scroll after view repainting\n\t\t//for example, opening a branch in the tree\n\t\t//it will be better to handle onAfterRender of the related view\n\t\tattachEvent(\"onClick\", CustomScroll._on_reconstruct);\n\t\treturn env.$customScroll;\n\t},\n\tresize:function(){\n\t\tthis._on_reconstruct();\n\t},\n\t_enable_datatable:function(view){\n\t\tview._body._custom_scroll_view = view._settings.id;\n\t\tview.attachEvent(\"onAfterRender\", function(){\n\t\t\tvar scroll = CustomScroll._get_datatable_sizes(this);\n\t\t\tvar y = Math.max(scroll.dy - scroll.py, 0);\n\t\t\tvar x = Math.max(scroll.dx - scroll.px, 0);\n\n\t\t\tif (this._y_scroll && this._scrollTop > y){\n\t\t\t\tthis._y_scroll.scrollTo(y);\n\t\t\t}\n\t\t\telse if (this._x_scroll && this._scrollLeft > x){\n\t\t\t\tthis._x_scroll.scrollTo(x);\n\t\t\t}\n\n\t\t\tif (CustomScroll._last_active_node == this._body)\n\t\t\t\tCustomScroll._on_reconstruct();\n\t\t});\n\n\t\t_event(view._body, \"pointerover\", \tCustomScroll._mouse_in \t);\n\t\t_event(view._body, \"pointerout\", \tCustomScroll._mouse_out\t);\n\t\tif (env.touch){\n\t\t\tview.attachEvent(\"onTouchStart\", () => CustomScroll._touch_start(view._body));\n\t\t\tif (view.config.prerender)\n\t\t\t\tview.attachEvent(\"onSyncScroll\", () => CustomScroll._update_scroll(view._body));\n\t\t}\n\t},\n\tenable:function(view, mode){\n\t\tif (view.mapCells)\n\t\t\treturn this._enable_datatable(view);\n\n\t\tvar node = view;\n\t\tif (view._dataobj)\n\t\t\tnode = view._dataobj.parentNode;\n\n\t\tnode._custom_scroll_mode = mode||\"xy\";\n\t\tnode.className += \" webix_custom_scroll\";\n\n\t\t_event(node, \"pointerover\", CustomScroll._mouse_in \t);\n\t\t_event(node, \"pointerout\", \tCustomScroll._mouse_out\t);\n\t\t_event(node, \"wheel\", CustomScroll._mouse_wheel, { passive:false });\n\t\tif (env.touch)\n\t\t\t_event(node, \"scroll\", () => CustomScroll._update_scroll(node));\n\n\t\tthis._set_additional_handlers(view);\n\t},\n\t_on_reconstruct:function(){\n\t\tconst last = CustomScroll._last_active_node;\n\n\t\tif (last && last._custom_scroll_size){\n\t\t\tconst webixView = $$(last);\n\t\t\tconst scrolls = webixView ? webixView.queryView(view => {\n\t\t\t\tconst node = CustomScroll._getViewNode(view);\n\t\t\t\treturn node && node._custom_scroll_size;\n\t\t\t}, \"all\").map(view => CustomScroll._getViewNode(view)) : [];\n\n\t\t\tscrolls.push(last);\n\n\t\t\tscrolls.forEach(node => {\n\t\t\t\tCustomScroll._mouse_out_timed.call(node);\n\t\t\t\tCustomScroll._mouse_in.call(node, false);\n\t\t\t});\n\t\t}\n\t},\n\t_getViewNode(view){\n\t\treturn view._body || (view._dataobj && view._dataobj.parentNode) || view.$view;\n\t},\n\t_mouse_in:function(e){\n\t\tif (e && e.pointerType !== \"mouse\") return;\n\n\t\tCustomScroll._last_active_node = this;\n\t\tclearTimeout(this._mouse_out_timer);\n\n\t\tif (this.className.indexOf(\"webix_modalbox_inside\") != -1) return;\n\t\tif (this._custom_scroll_size || CustomScroll._active_drag_area) return;\n\n\t\tvar view = $$(this);\n\t\tif (view && !view.isEnabled()) return;\n\n\t\tvar sizes;\n\t\tif (this._custom_scroll_view){\n\t\t\t//ger related view\n\t\t\tview = $$(this._custom_scroll_view);\n\t\t\t//if view was removed, we need not scroll anymore\n\t\t\tif (!view) return;\n\t\t\tsizes = CustomScroll._get_datatable_sizes(view);\n\t\t} else {\n\t\t\tsizes = {\n\t\t\t\tdx:this.scrollWidth,\n\t\t\t\tdy:this.scrollHeight,\n\t\t\t\tpx:this.clientWidth,\n\t\t\t\tpy:this.clientHeight\n\t\t\t};\n\t\t\tsizes._scroll_x = sizes.dx > sizes.px && this._custom_scroll_mode.indexOf(\"x\") != -1;\n\t\t\tsizes._scroll_y = sizes.dy > sizes.py && this._custom_scroll_mode.indexOf(\"y\") != -1;\n\t\t}\n\n\t\tthis._custom_scroll_size = sizes;\n\t\tif (sizes._scroll_x){\n\t\t\tsizes._scroll_x_node = CustomScroll._create_scroll(this, \"x\", sizes.dx, sizes.px, \"width\", \"height\");\n\t\t\tsizes._sx = (sizes.px - sizes._scroll_x_node.offsetWidth - 4);\n\t\t\tsizes._vx = sizes.dx - sizes.px;\n\t\t\tif(CustomScroll.trackBar)\n\t\t\t\tsizes._bar_x = CustomScroll._create_bar(this,\"x\");\n\t\t}\n\t\tif (sizes._scroll_y){\n\t\t\tsizes._scroll_y_node = CustomScroll._create_scroll(this, \"y\", sizes.dy, sizes.py, \"height\", \"width\");\n\t\t\tsizes._sy = (sizes.py - sizes._scroll_y_node.offsetHeight - 4);\n\t\t\tsizes._vy = sizes.dy - sizes.py;\n\n\t\t\tif(CustomScroll.trackBar)\n\t\t\t\tsizes._bar_y = CustomScroll._create_bar(this,\"y\");\n\t\t}\n\n\t\tCustomScroll._update_scroll(this);\n\t},\n\t_create_bar: function(node, mode){\n\t\tvar bar = create(\"DIV\", {\n\t\t\t/*@attr*/\"webixignore\":\"1\",\n\t\t\t\"class\":\"webix_c_scroll_bar_\"+mode\n\t\t},\"\");\n\n\t\tnode.appendChild(bar);\n\t\treturn bar;\n\t},\n\t_adjust_scroll:function(node, old, pos){\n\t\tvar config = node._custom_scroll_size;\n\t\tvar view = node._custom_scroll_view;\n\t\tif (view) view = $$(view);\n\n\t\tif (config._scroll_x_node == node._scroll_drag_enabled){\n\t\t\tlet next = (pos.x - old.x)*config._vx/config._sx;\n\t\t\tif (view)\n\t\t\t\tview._x_scroll.scrollTo(view._scrollLeft+next);\n\t\t\telse\n\t\t\t\tCustomScroll._set_scroll_value(node, \"scrollLeft\", next);\n\t\t}\n\t\tif (config._scroll_y_node == node._scroll_drag_enabled){\n\t\t\tlet next = (pos.y - old.y)*config._vy/config._sy;\n\t\t\tif (view)\n\t\t\t\tview._y_scroll.scrollTo(view._scrollTop+next);\n\t\t\telse\n\t\t\t\tCustomScroll._set_scroll_value(node, \"scrollTop\", next);\n\t\t}\n\n\t\tnode._scroll_drag_pos = pos;\n\t\tCustomScroll._update_scroll(node);\n\t},\n\t_get_datatable_sizes:function(view){\n\t\tvar sizes = {};\n\t\tif (view._x_scroll && view._settings.scrollX){\n\t\t\tsizes.dx = view._x_scroll.getSize();\n\t\t\tsizes.px = view._x_scroll._last_set_size || 1;\n\t\t\tsizes._scroll_x = sizes.dx - sizes.px > 1;\n\t\t}\n\t\tif (view._y_scroll && view._settings.scrollY){\n\t\t\tsizes.dy = view._y_scroll.getSize();\n\t\t\tsizes.py = view._y_scroll._last_set_size || 1;\n\t\t\tsizes._scroll_y = sizes.dy - sizes.py > 1;\n\t\t}\n\t\treturn sizes;\n\t},\n\t_mouse_out:function(e){\n\t\tif (e && e.pointerType !== \"mouse\") return;\n\n\t\tclearTimeout(this._mouse_out_timer);\n\t\tthis._mouse_out_timer = delay(CustomScroll._mouse_out_timed, this, [], 200);\n\t},\n\t_removeScroll:function(scroll){\n\t\tif (scroll){\n\t\t\tremove(scroll);\n\t\t\teventRemove(scroll._webix_event_sc1);\n\t\t\teventRemove(scroll._webix_event_sc2);\n\t\t}\n\t},\n\t_mouse_out_timed:function(){\n\t\tif (this._custom_scroll_size){\n\t\t\tif (this._scroll_drag_enabled){\n\t\t\t\tthis._scroll_drag_released = true;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst sizes = this._custom_scroll_size;\n\t\t\tCustomScroll._removeScroll(sizes._scroll_x_node);\n\t\t\tCustomScroll._removeScroll(sizes._scroll_y_node);\n\n\t\t\tif (sizes._bar_x) remove(sizes._bar_x);\n\t\t\tif (sizes._bar_y) remove(sizes._bar_y);\n\n\t\t\tthis._custom_scroll_size = null;\n\t\t}\n\t},\n\t_mouse_wheel:function(e){\n\t\tif (e.ctrlKey) return false;\n\n\t\tlet toblock = false;\n\t\tconst step = e.deltaMode === 0 ? 30 : 1;\n\t\tconst sizes = this._custom_scroll_size;\n\t\tif (sizes){\n\t\t\tconst forceX = !sizes._scroll_y || e.shiftKey;\n\t\t\tif ((e.deltaX && Math.abs(e.deltaX) > Math.abs(e.deltaY)) || forceX){\n\t\t\t\tconst x_dir = (forceX ? e.deltaY : e.deltaX) / step;\n\t\t\t\t//x-scroll\n\t\t\t\tif (sizes._scroll_x_node)\n\t\t\t\t\ttoblock = CustomScroll._set_scroll_value(this, \"scrollLeft\", x_dir*CustomScroll.scrollStep);\n\t\t\t} else {\n\t\t\t\t//y-scroll\n\t\t\t\tif (sizes._scroll_y_node)\n\t\t\t\t\t//lesser flickering of scroll in IE\n\t\t\t\t\t//also prevent scrolling outside of borders because of scroll-html-elements\n\t\t\t\t\ttoblock = CustomScroll._set_scroll_value(this, \"scrollTop\", (e.deltaY/step)*CustomScroll.scrollStep);\n\t\t\t}\n\t\t}\n\n\t\tCustomScroll._update_scroll(this);\n\t\tif (toblock !== false)\n\t\t\treturn preventEvent(e);\n\t},\n\t_set_scroll_value:function(node, pose, value){\n\t\tconst sizes = node._custom_scroll_size;\n\t\tconst max_scroll = (pose == \"scrollLeft\") ? (sizes.dx - sizes.px) : (sizes.dy - sizes.py);\n\t\tconst now = node[pose];\n\n\t\tif (now + value > max_scroll)\n\t\t\tvalue = max_scroll - now;\n\t\tif (!value || (now + value < 0 && now === 0))\n\t\t\treturn false;\n\n\t\tif (env.isIE){\n\t\t\tCustomScroll._update_scroll(node, pose, value + now);\n\t\t\tnode[pose] += value;\n\t\t} else\n\t\t\tnode[pose] += value;\n\n\t\treturn true;\n\t},\n\t_create_scroll:function(node, mode, dy, py, dim){\n\t\tvar scroll = create(\"DIV\", {\n\t\t\t/*@attr*/\"webixignore\":\"1\",\n\t\t\t\"class\":\"webix_c_scroll_\"+mode\n\t\t},\"
\");\n\n\t\tscroll.style[dim] = Math.max((py*py/dy-7),40)+\"px\";\n\t\tscroll.style[dim == \"height\"?\"top\":\"left\"] = \"0px\";\n\t\tnode.style.position = \"relative\";\n\t\tnode.appendChild(scroll);\n\n\t\tnode._webix_event_sc1 = event(scroll, env.mouse.down, CustomScroll._scroll_drag(node, \"mouse\"));\n\t\tif (env.touch)\n\t\t\tnode._webix_event_sc2 = event(scroll, env.touch.down, CustomScroll._scroll_drag(node, \"touch\"));\n\n\t\treturn scroll;\n\t},\n\t_init_drag:function(e, pointer){\n\t\tif (pointer === \"touch\"){\n\t\t\tCustomScroll._drag_events = [\n\t\t\t\tevent(e.target, env[pointer].move, function(e){\n\t\t\t\t\tCustomScroll._adjust_scroll(CustomScroll._active_drag_area, CustomScroll._active_drag_area._scroll_drag_pos, getPos(e));\n\t\t\t\t}),\n\t\t\t\tevent(e.target, env[pointer].up, CustomScroll._scroll_drop)\n\t\t\t];\n\t\t} else {\n\t\t\tCustomScroll._drag_events = [\n\t\t\t\tevent(document.body, env[pointer].move, function(e){\n\t\t\t\t\tCustomScroll._adjust_scroll(CustomScroll._active_drag_area, CustomScroll._active_drag_area._scroll_drag_pos, getPos(e));\n\t\t\t\t}),\n\t\t\t\tevent(document, env[pointer].up, CustomScroll._scroll_drop),\n\t\t\t\tevent(document.body, \"mouseleave\", CustomScroll._scroll_drop)\n\t\t\t];\n\t\t}\n\t},\n\t_scroll_drag:function(node, pointer){\n\t\treturn function(e){\n\t\t\taddCss(document.body,\"webix_noselect\",1);\n\t\t\tthis.className += \" webix_scroll_active\";\n\t\t\tnode._scroll_drag_enabled = this;\n\t\t\tnode._scroll_drag_pos = getPos(e);\n\n\t\t\tCustomScroll._active_drag_area = node;\n\t\t\tCustomScroll._init_drag(e, pointer);\n\n\t\t\tif (e.cancelable) preventEvent(e);\n\t\t};\n\t},\n\t_scroll_drop:function(){\n\t\tconst node = CustomScroll._active_drag_area;\n\t\tif (node._scroll_drag_enabled){\n\t\t\tremoveCss(document.body,\"webix_noselect\");\n\t\t\tnode._scroll_drag_enabled.className = node._scroll_drag_enabled.className.toString().replace(\" webix_scroll_active\",\"\");\n\t\t\tnode._scroll_drag_enabled = false;\n\t\t\tCustomScroll._active_drag_area = false;\n\t\t\tif (node._scroll_drag_released){\n\t\t\t\tCustomScroll._mouse_out_timed.call(node);\n\t\t\t\tnode._scroll_drag_released = false;\n\t\t\t}\n\t\t}\n\n\t\tif (CustomScroll._drag_events){\n\t\t\tfor (let i=0; i this._resize_scroll(view));\n\t\t\tview.attachEvent(\"onAfterAutoScroll\", () => this._resize_scroll(view));\n\t\t\tif (view._level_up)\t\t// grouplist: resize scroll after animation\n\t\t\t\tview.attachEvent(\"onAfterRender\", () => this._resize_scroll(view));\n\t\t\tif (env.touch)\n\t\t\t\tview.attachEvent(\"onTouchStart\", () => this._touch_start(view._dataobj.parentNode));\n\t\t}\n\n\t\t// update scroll on data change\n\t\tif (view.data && view.data.attachEvent)\n\t\t\tview.data.attachEvent(\"onStoreUpdated\", () => this._resize_scroll(view));\n\t},\n\t_touch_start:function(current){\n\t\tconst node = CustomScroll._last_active_node;\n\t\tif (node !== current){\n\t\t\tif (node) CustomScroll._mouse_out.call(node, false);\n\t\t\tCustomScroll._mouse_in.call(current, false);\n\t\t}\n\t},\n\t_resize_scroll:function(view){\n\t\tconst node = CustomScroll._last_active_node;\n\t\tif (node && view.$view.contains(node))\n\t\t\tCustomScroll._on_reconstruct();\n\t\telse\n\t\t\tCustomScroll._mouse_out_timed.call(view._dataobj.parentNode);\n\t}\n};\n\nexport default CustomScroll;","import {isArray, extend, uid} from \"../webix/helpers\";\nimport {assert} from \"../webix/debug\";\n\n\n/*\n\tBehavior:DataMove - allows to move and copy elements, heavily relays on DataStore.move\n\t@export\n\t\tcopy\n\t\tmove\n*/\nconst DataMove ={\n\t//creates a copy of the item\n\tcopy:function(sid,tindex,tobj, details){\n\t\tdetails = details || {};\n\t\tvar new_id = details.newId || sid;\n\t\ttobj = tobj||this;\n\n\t\tvar data = this.getItem(sid);\n\t\tassert(data,\"Incorrect ID in DataMove::copy\");\n\t\t\n\t\t//make data conversion between objects\n\t\tif (tobj)\n\t\t\tdata = tobj._externalData(data);\n\t\t\n\t\t//adds new element same as original\n\t\treturn tobj.data.add(tobj._externalData(data,new_id),tindex,(details.parent || 0));\n\t},\n\t_next_move_index:function(nid, next, source){\n\t\tif (next && nid){\n\t\t\tvar new_index = this.getIndexById(nid);\n\t\t\treturn new_index + ((source == this && source.getIndexById(next) < new_index) ? 0 : 1);\n\t\t}\n\t},\n\t//move item to the new position\n\tmove:function(sid,tindex,tobj, details){\n\t\tdetails = details || {};\n\t\tconst new_id = details.newId || sid;\n\n\t\ttobj = tobj||this;\n\t\tassert(tobj.data, \"moving attempt to component without datastore\");\n\t\tif (!tobj.data) return;\n\n\t\t//can process an arrya - it allows to use it from onDrag \n\t\tif (isArray(sid)){\n\t\t\t//block separate repaint operations\n\t\t\tif (sid.length > 3) //heuristic value, duplicated below\n\t\t\t\tthis.$blockRender = tobj.$blockRender = true;\n\n\t\t\tfor (let i=0; i 3){\n\t\t\t\t//repaint whole component\n\t\t\t\tthis.refresh();\n\t\t\t\tif (tobj != this)\n\t\t\t\t\ttobj.refresh();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tlet nid = sid; //id after moving\n\t\tconst item = this.getItem(sid);\n\t\tassert(item, \"Incorrect ID in DataMove::move\");\n\t\t\n\t\tif (!tobj || tobj == this){\n\t\t\tif (tindex < 0) tindex = this.data.order.length - 1;\n\t\t\tthis.data.move(this.getIndexById(sid),tindex);\t//move inside the same object\n\t\t\tthis.data.callEvent(\"onDataMove\", [sid, tindex, null, this.data.order[tindex+1]]);\n\t\t} else {\n\t\t\t//copy to the new object\n\t\t\tnid = tobj.data.add(tobj._externalData(item,new_id),tindex, (details.parent || 0));\n\t\t\tthis.data.remove(sid);//delete in old object\n\t\t}\n\t\treturn nid;\t//return ID of item after moving\n\t},\n\t//move item on one position up\n\tmoveUp:function(id,step){\n\t\tconst index = this.getIndexById(id)-(step||1);\n\t\treturn this.move(id,(index<0)?0:index);\n\t},\n\t//move item on one position down\n\tmoveDown:function(id,step){\n\t\treturn this.moveUp(id, (step||1)*-1);\n\t},\n\t//move item to the first position\n\tmoveTop:function(id){\n\t\treturn this.move(id,0);\n\t},\n\t//move item to the last position\n\tmoveBottom:function(id){\n\t\treturn this.move(id,this.data.count()-1);\n\t},\n\t/*\n\t\tthis is a stub for future functionality\n\t\tcurrently it just makes a copy of data object, which is enough for current situation\n\t*/\n\t_externalData:function(data,id){\n\t\tvar newdata = extend({},data);\n\t\tnewdata.id = (!id || this.data.pull[id])?uid():id;\n\t\t\n\n\t\tnewdata.$template=null;\n\n\t\tif (this._settings.externalData)\n\t\t\tnewdata = this._settings.externalData.call(this, newdata, id, data);\n\t\treturn newdata;\n\t}\n};\n\nexport default DataMove;","import {assert} from \"../webix/debug\";\nimport {copy, isUndefined, bind, isArray} from \"../webix/helpers\";\nimport {callEvent} from \"../webix/customevents\";\nimport {define} from \"../services\";\n\nimport {$$, proto} from \"../ui/core\";\n\nimport {ajax} from \"../load/ajax\";\nimport proxy from \"../load/proxy\";\nimport promise from \"../thirdparty/promiz\";\n\nimport Settings from \"../core/settings\";\nimport EventSystem from \"../core/eventsystem\";\nimport ValidateData from \"../core/validatedata\";\n\nconst _pull = {};\n\nexport function dp(name,getOnly){\n\tif (typeof name == \"object\" && name._settings)\n\t\tname = name._settings.id;\n\tif (_pull[name] || getOnly)\n\t\treturn _pull[name];\n\n\tif (typeof name == \"string\"||typeof name == \"number\")\n\t\tname = { master:$$(name) };\n\n\tvar dp = new DataProcessor(name);\n\tvar masterId = dp._settings.master._settings.id;\n\t_pull[masterId]=dp;\n\n\t$$(masterId).attachEvent(\"onDestruct\",function(){\n\t\t_pull[this._settings.id] = null;\n\t\tdelete _pull[this._settings.id];\n\t});\n\n\treturn dp;\n}\n\ndefine(\"dp\", dp);\n\ndp.$$ = function(id){\n\treturn _pull[id];\n};\n\n\nexport const DataProcessor = proto({\n\tdefaults: {\n\t\tautoupdate:true,\n\t\tupdateFromResponse:false,\n\t\tmode:\"post\",\n\t\toperationName:\"webix_operation\",\n\t\ttrackMove:false\n\t},\n\n\n\t/*! constructor\n\t **/\n\t$init: function() {\n\t\tthis.reset();\n\t\tthis._ignore = false;\n\t\tthis.name = \"DataProcessor\";\n\t\tthis.$ready.push(this._after_init_call);\n\t},\n\treset:function(){\n\t\tthis._updates = [];\n\t},\n\turl_setter:function(value){\n\t\t/*\n\t\t\twe can use simple url or mode->url\n\t\t*/\n\t\tvar mode = \"\";\n\t\tif (typeof value == \"string\"){\n\t\t\tvar parts = value.split(\"->\");\n\t\t\tif (parts.length > 1){\n\t\t\t\tvalue = parts[1];\n\t\t\t\tmode = parts[0];\n\t\t\t}\n\t\t} else if (value && value.mode){\n\t\t\tmode = value.mode;\n\t\t\tvalue = value.url;\n\t\t}\n\n\t\tif (mode)\n\t\t\treturn proxy(mode, value);\n\n\t\treturn value;\n\t},\n\tmaster_setter:function(value){\n\t\tvar store = value;\n\t\tif (value.name != \"DataStore\")\n\t\t\tstore = value.data;\n\n\t\tthis._settings.store = store;\n\t\treturn value;\n\t},\n\t_promise:function(handler){\n\t\tconst prev = this._waitSave;\n\t\tthis._waitSave = [];\n\t\t\n\t\thandler();\n\t\tconst result = Promise.all(this._waitSave);\n\n\t\tthis._waitSave = prev;\n\t\tif (prev)\n\t\t\tprev.push(result);\n\n\t\treturn result;\n\t},\n\t/*! attaching onStoreUpdated event\n\t **/\n\t_after_init_call: function(){\n\t\tconst store = this._settings.store;\n\t\tif (store){\n\t\t\tstore.attachEvent(\"onStoreUpdated\", bind(this._onStoreUpdated, this));\n\t\t\tstore.attachEvent(\"onDataMove\", bind(this._onDataMove, this));\n\t\t}\n\t},\n\tignore:function(code,master){\n\t\tvar temp = this._ignore;\n\t\tthis._ignore = true;\n\t\tcode.call((master||this));\n\t\tthis._ignore = temp;\n\t},\n\toff:function(){\n\t\tthis._ignore = true;\n\t},\n\ton:function(){\n\t\tthis._ignore = false;\n\t},\n\n\t_copy_data:function(source){\n\t\tvar obj = {};\n\t\tfor (var key in source)\t\n\t\t\tif (key.indexOf(\"$\")!==0)\n\t\t\t\tobj[key]=source[key];\n\t\treturn obj;\n\t},\n\tsave:function(id, operation, obj){\n\t\toperation = operation || \"update\";\n\t\treturn this._save_inner(id, obj, operation, true);\n\t},\n\t_save_inner:function(id, obj, operation, now){\n\t\tif (typeof id == \"object\") id = id.toString();\n\t\tif (!id || this._ignore === true || !operation || operation == \"paint\") return;\n\n\t\tvar store = this._settings.store;\n\t\tif (store){\n\t\t\tobj = obj || this._settings.store.getItem(id);\n\t\t\tif (store._scheme_serialize)\n\t\t\t\tobj = store._scheme_serialize(obj);\n\t\t}\n\n\t\tvar update = { id: id, data:this._copy_data(obj), operation:operation };\n\t\t//save parent id\n\t\tif (!isUndefined(obj.$parent)) update.data.parent = obj.$parent;\n\n\t\tif (update.operation != \"delete\"){\n\t\t\t//prevent saving of not-validated records\n\t\t\tvar master = this._settings.master;\n\t\t\tif (master && master.data && master.data.getMark && master.data.getMark(id, \"webix_invalid\"))\n\t\t\t\tupdate._invalid = true;\n\n\t\t\tif (!this.validate(null, update.data))\n\t\t\t\tupdate._invalid = true;\n\t\t}\n\n\t\tif (this._check_unique(update))\n\t\t\tthis._updates.push(update);\n\n\t\tif (this._settings.autoupdate || now)\n\t\t\treturn this._sendData(id);\n\t\t\t\n\t\treturn;\n\t},\n\t_onDataMove:function(sid, tindex, parent, targetid){\n\t\tif (this._settings.trackMove){\n\t\t\tvar obj = copy(this._settings.store.getItem(sid));\n\n\t\t\tobj.webix_move_index = tindex;\n\t\t\tobj.webix_move_id = targetid;\n\t\t\tobj.webix_move_parent = parent;\n\t\t\tthis._save_inner(sid, obj, \"order\");\n\t\t}\n\t},\n\t_onStoreUpdated: function(id, obj, operation){\n\t\tswitch (operation) {\n\t\t\tcase \"save\":\n\t\t\t\toperation = \"update\";\n\t\t\t\tbreak;\n\t\t\tcase \"update\":\n\t\t\t\toperation = \"update\";\n\t\t\t\tbreak;\n\t\t\tcase \"add\":\n\t\t\t\toperation = \"insert\";\n\t\t\t\tbreak;\n\t\t\tcase \"delete\":\n\t\t\t\toperation = \"delete\";\t\t\t\t\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn true;\n\t\t}\n\t\treturn this._save_inner(id, obj, operation);\n\t},\n\t_check_unique:function(check){\n\t\tfor (var i = 0; i < this._updates.length; i++){\n\t\t\tvar one = this._updates[i];\n\t\t\tif (one.id == check.id && !one._in_progress){\n\t\t\t\tif (check.operation == \"delete\"){\n\t\t\t\t\tif (one.operation == \"insert\")\n\t\t\t\t\t\tthis._updates.splice(i,1);\n\t\t\t\t\telse \n\t\t\t\t\t\tone.operation = \"delete\";\n\t\t\t\t}\n\t\t\t\tone.data = check.data;\n\t\t\t\tone._invalid = check._invalid;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t},\n\tsend:function(){\n\t\treturn this._sendData();\n\t},\n\t_sendData: function(triggerId){\n\t\tif (!this._settings.url)\n\t\t\treturn;\n\n\t\tvar wait;\n\t\tvar marked = this._updates;\n\t\tvar to_send = [];\n\t\tvar url = this._settings.url;\n\n\t\tfor (let i = 0; i < marked.length; i++) {\n\t\t\tvar tosave = marked[i];\n\n\t\t\tif (tosave._in_progress) continue;\n\t\t\tif (tosave._invalid) continue;\n\n\t\t\tvar id = tosave.id;\n\t\t\t// call to .save(id) without autoupdate mode will send the specific object only\n\t\t\tif (!this._settings.autoupdate && triggerId && triggerId != id)\n\t\t\t\tcontinue;\n\n\t\t\tvar operation = tosave.operation;\n\t\t\tvar precise_url = proxy.$parse((typeof url == \"object\" && !url.$proxy) ? url[operation] : url);\n\t\t\tvar custom = precise_url && (precise_url.$proxy || typeof precise_url === \"function\");\n\n\t\t\tif (!precise_url) continue;\n\n\t\t\tconst store = this._settings.store;\n\t\t\tif (store && store._scheme_save)\n\t\t\t\tstore._scheme_save(tosave.data);\n\n\t\t\tif (!this.callEvent(\"onBefore\"+operation, [id, tosave]))\n\t\t\t\tcontinue;\n\t\t\ttosave._in_progress = true;\n\n\t\t\tif (!this.callEvent(\"onBeforeDataSend\", [tosave])) return;\n\n\t\t\ttosave.data = this._updatesData(tosave.data);\n\n\t\t\tlet result;\n\t\t\tif (precise_url.$proxy){\n\t\t\t\tif (precise_url.save){\n\t\t\t\t\t//proxy\n\t\t\t\t\tresult = precise_url.save(this.config.master, tosave, this);\n\t\t\t\t}\n\t\t\t\tto_send.push(tosave);\n\t\t\t} else {\n\t\t\t\tif (operation == \"insert\")\n\t\t\t\t\tdelete tosave.data.id;\n\t\t\t\t\n\t\t\t\tif (custom){\n\t\t\t\t\t//save function\n\t\t\t\t\tresult = precise_url.call(this.config.master, tosave.id, tosave.operation, tosave.data);\n\t\t\t\t} else {\n\t\t\t\t\t//normal url\n\t\t\t\t\ttosave.data[this._settings.operationName] = operation;\n\n\t\t\t\t\tresult = this._send(precise_url, tosave.data, this._settings.mode);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (result){\n\t\t\t\tresult = this._proxy_on_save(result, { id: tosave.id, status: tosave.operation });\n\t\t\t\tif (triggerId && id === triggerId){\n\t\t\t\t\twait = result;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.callEvent(\"onAfterDataSend\", [tosave]);\n\t\t}\n\n\t\tif (url.$proxy && url.saveAll && to_send.length){\n\t\t\tlet result = url.saveAll(this.config.master, to_send, this);\n\t\t\tif (result){\n\t\t\t\tresult = this._proxy_on_save(result, null);\n\t\t\t\tif (!wait)\n\t\t\t\t\twait = result;\n\t\t\t}\n\t\t}\n\n\t\treturn wait;\n\t},\n\t_proxy_on_save:function(result, state){\n\t\tif(result){\n\t\t\tif(!result.then)\n\t\t\t\tresult = promise.resolve(result);\n\n\t\t\tresult = result.then((data) => {\n\t\t\t\tif (data && typeof data.json == \"function\")\n\t\t\t\t\tdata = data.json();\n\n\t\t\t\tvar processed;\n\t\t\t\tif (state === null){\n\t\t\t\t\tprocessed = this._processResult(data); //array of responses\n\t\t\t\t} else {\n\t\t\t\t\tprocessed = this._processResult(state, \"\", data, -1); //text, data, loader\n\t\t\t\t}\n\n\t\t\t\tif (!processed)\n\t\t\t\t\tthrow processed; // trigger rejection\n\n\t\t\t\treturn processed;\n\t\t\t}, (x) => {\n\t\t\t\tthis._processError(state, \"\", null, x);\n\t\t\t\tthrow x;\n\t\t\t});\n\n\t\t\tif (this._waitSave)\n\t\t\t\tthis._waitSave.push(result);\n\n\t\t\treturn result;\n\t\t}\n\t},\n\n\t/*! process updates list to POST and GET params according dataprocessor protocol\n\t *\t@param updates\n\t *\t\tlist of objects { id: \"item id\", data: \"data hash\", operation: \"type of operation\"}\n\t *\t@return\n\t *\t\tobject { post: { hash of post params as name: value }, get: { hash of get params as name: value } }\n\t **/\n\n\n\n\t_updatesData:function(source){\n\t\tvar target = {};\n\t\tfor (var j in source){\n\t\t\tif (j.indexOf(\"$\")!==0)\n\t\t\t\ttarget[j] = source[j];\n\t\t}\n\t\treturn target;\n\t},\n\n\n\n\t/*! send dataprocessor query to server\n\t *\tand attach event to process result\n\t *\t@param url\n\t *\t\tserver url\n\t *\t@param get\n\t *\t\thash of get params\n\t *\t@param post\n\t *\t\thash of post params\n\t *\t@mode\n\t *\t\t'post' or 'get'\n\t **/\n\t_send: function(url, post, mode) {\n\t\tassert(url, \"url was not set for DataProcessor\");\n\t\treturn ajax()[mode](url, post);\n\t},\n\tattachProgress:function(start, end, error){\n\t\tthis.attachEvent(\"onBeforeDataSend\", start);\n\t\tthis.attachEvent(\"onAfterSync\", end);\n\t\tthis.attachEvent(\"onAfterSaveError\", error);\n\t\tthis.attachEvent(\"onLoadError\", error);\n\t},\n\t_processError:function(id, text, data, loader){\n\t\tif (id)\n\t\t\tthis._innerProcessResult(true, id.id, false, id.status, false, {text:text, data:data, loader:loader});\n\t\telse {\n\t\t\tthis.callEvent(\"onLoadError\", arguments);\n\t\t\tcallEvent(\"onLoadError\", [text, data, loader, this]);\n\t\t}\n\t},\n\t_innerProcessResult:function(error, id, newid, status, obj, details){\n\t\tvar master = this._settings.master;\n\t\tvar update = this.getItemState(id);\n\t\tupdate._in_progress = false;\n\n\n\n\t\tif (error){\n\t\t\tif (this.callEvent(\"onBeforeSaveError\", [id, status, obj, details])){\n\t\t\t\tupdate._invalid = true;\n\t\t\t\tif(this._settings.undoOnError && master._settings.undo){\n\t\t\t\t\tthis.ignore(function(){\n\t\t\t\t\t\tmaster.undo(id);\n\t\t\t\t\t});\n\t\t\t\t\tthis.setItemState(id, false);\n\t\t\t\t}\n\t\t\t\tthis.callEvent(\"onAfterSaveError\", [id, status, obj, details]);\n\t\t\t}\n\t\t\treturn;\n\t\t} else\n\t\t\tthis.setItemState(id, false);\n\n\t\tconst store = this._settings.store;\n\t\tif (store && store.exists(id)){\n\t\t\t//update from response\n\t\t\tif (newid && id != newid)\n\t\t\t\tstore.changeId(id, newid);\n\n\t\t\tif (obj && status != \"delete\" && this._settings.updateFromResponse)\n\t\t\t\tthis.ignore(function(){\t\t\t\t\n\t\t\t\t\tstore.updateItem(newid || id, obj);\n\t\t\t\t});\n\t\t}\n\t\t\t\n\n\t\t//clean undo history, for the saved record\n\t\tif(this._settings.undoOnError && master._settings.undo)\n\t\t\tmaster.removeUndo(newid||id);\n\n\t\tthis.callEvent(\"onAfterSave\",[obj, id, details]);\n\t\tthis.callEvent(\"onAfter\"+status, [obj, id, details]);\n\n\t\treturn obj || {};\n\t},\n\tprocessResult: function(state, hash, details){\n\t\t//compatibility with custom json response\n\t\tvar error = (hash && (hash.status == \"error\" || hash.status == \"invalid\"));\n\t\tvar newid = (hash ? ( hash.newid || hash.id ) : false);\n\n\t\treturn this._innerProcessResult(error, state.id, newid, state.status, hash, details);\n\t},\n\t// process saving from result\n\t_processResult: function(state, text, data, loader){\n\t\tvar finalResult;\n\t\tthis.callEvent(\"onBeforeSync\", [state, text, data, loader]);\n\n\t\tif(isArray(state)){ //saveAll results\n\t\t\tfinalResult = [];\n\t\t\tstate.forEach((one) => {\n\t\t\t\tfinalResult.push(this.processResult(one, one, {}));\n\t\t\t});\n\t\t}\n\t\telse{\n\t\t\tif (loader === -1){\n\t\t\t\t//callback from promise\n\t\t\t\tfinalResult = this.processResult(state, data, {});\n\t\t\t} else {\n\t\t\t\tvar proxy = this._settings.url;\n\t\t\t\tif (proxy.$proxy && proxy.result){\n\t\t\t\t\tfinalResult = proxy.result(state, this._settings.master, this, text, data, loader) || {};\n\t\t\t\t} else {\n\t\t\t\t\tvar hash;\n\t\t\t\t\tif (text){\n\t\t\t\t\t\thash = data.json();\n\t\t\t\t\t\t//invalid response\n\t\t\t\t\t\tif (text && (hash === null || typeof hash == \"undefined\"))\n\t\t\t\t\t\t\thash = { status:\"error\" };\n\t\t\t\t\t}\n\t\t\t\t\tfinalResult = this.processResult(state, hash, {text:text, data:data, loader:loader});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.callEvent(\"onAfterSync\", [state, text, data, loader]);\n\t\treturn finalResult;\n\t},\n\n\n\t/*! if it's defined escape function - call it\n\t *\t@param value\n\t *\t\tvalue to escape\n\t *\t@return\n\t *\t\tescaped value\n\t **/\n\tescape: function(value) {\n\t\tif (this._settings.escape)\n\t\t\treturn this._settings.escape(value);\n\t\telse\n\t\t\treturn encodeURIComponent(value);\n\t},\n\tgetState:function(){\n\t\tif (!this._updates.length) return false;\n\t\tfor (var i = this._updates.length - 1; i >= 0; i--)\n\t\t\tif (this._updates[i]._in_progress)\n\t\t\t\treturn \"saving\";\n\n\t\treturn true;\n\t},\n\tgetItemState:function(id){\n\t\tvar index = this._get_stack_index(id);\n\t\treturn this._updates[index] || null;\n\t},\n\tsetItemState:function(id, state){\n\t\tif (state){\n\t\t\tthis._save_inner(id, null, \"update\");\n\t\t} else{\n\t\t\tvar index = this._get_stack_index(id);\n\t\t\tif (index > -1)\n\t\t\t\tthis._updates.splice(index, 1);\n\t\t}\n\t},\n\t_get_stack_index: function(id) {\n\t\tvar index = -1;\n\t\tfor (var i=0; i < this._updates.length; i++)\n\t\t\tif (this._updates[i].id == id) {\n\t\t\t\tindex = i;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\treturn index;\n\t}\n\n}, Settings, EventSystem, ValidateData);","import {extend, _to_array, uid, isUndefined, copy, isArray, bind} from \"../webix/helpers\";\nimport {$$} from \"../ui/core\";\nimport {assert} from \"../webix/debug\";\nimport {callEvent} from \"../webix/customevents\";\nimport i18n from \"../webix/i18n\";\n\nimport EventSystem from \"./eventsystem\";\nimport DataDriver from \"../load/drivers/index\";\n\n/*\n\tDataStore is not a behavior, it standalone object, which represents collection of data.\n\tCall provideAPI to map data API\n\n\t@export\n\t\texists\n\t\tgetIdByIndex\n\t\tgetIndexById\n\t\tget\n\t\tset\n\t\trefresh\n\t\tcount\n\t\tsort\n\t\tfilter\n\t\tnext\n\t\tprevious\n\t\tclearAll\n\t\tfirst\n\t\tlast\n*/\n\nfunction DataStore(){\n\tthis.name = \"DataStore\";\n\t\n\textend(this, EventSystem);\n\n\tthis.setDriver(\"json\");\t//default data source is an\n\tthis.pull = {};\t\t\t\t\t\t//hash of IDs\n\tthis.order = _to_array();\t\t//order of IDs\n\tthis._marks = {};\n}\n\nDataStore.prototype={\n\t//defines type of used data driver\n\t//data driver is an abstraction other different data formats - xml, json, csv, etc.\n\tsetDriver:function(type){\n\t\tassert(DataDriver[type],\"incorrect DataDriver\");\n\t\tthis.driver = DataDriver[type];\n\t},\n\t//process incoming raw data\n\t_parse:function(data){\n\t\tthis.callEvent(\"onParse\", [this.driver, data]);\n\n\t\tif (this._filter_order)\n\t\t\tthis.filter();\n\t\n\t\t//get size and position of data\n\t\tconst info = this.driver.getInfo(data);\n\n\t\tif (info.config)\n\t\t\tthis.callEvent(\"onServerConfig\",[info.config]);\n\n\t\tconst options = this.driver.getOptions(data);\n\t\tif (options)\n\t\t\tthis.callEvent(\"onServerOptions\", [options]);\n\n\t\t//get array of records\n\t\tconst recs = this.driver.getRecords(data);\n\n\t\tthis._inner_parse(info, recs);\n\n\t\t//in case of tree store we may want to group data\n\t\tif (this._scheme_group && this._group_processing && !this._not_grouped_order)\n\t\t\tthis._group_processing(this._scheme_group);\n\n\t\t//optional data sorting\n\t\tif (this._scheme_sort){\n\t\t\tthis.blockEvent();\n\t\t\tthis.sort(this._scheme_sort);\n\t\t\tthis.unblockEvent();\n\t\t}\n\n\t\tthis.callEvent(\"onStoreLoad\",[this.driver, data]);\n\t\t//repaint self after data loading\n\t\tthis.refresh();\n\t},\n\t_inner_parse:function(info, recs){\n\t\tlet from = info.from;\n\t\tlet subload = true;\n\t\tlet marks = false;\n\n\t\t//some data is loaded and new data doesn't have \"pos\" - assuming update\n\t\tif (!from && from !== 0 && this.order[0]){\n\t\t\tif (this._removeMissed){\n\t\t\t\t//update mode, create kill list\n\t\t\t\tmarks = {};\n\t\t\t\tfor (let i=0; i to){ //can be in case of backward shift-selection\n\t\t\tlet a=to; to=from; from=a;\n\t\t}\n\n\t\treturn this.getIndexRange(from,to);\n\t},\n\t//converts range of indexes to array of all IDs between them\n\tgetIndexRange:function(from,to){\n\t\tto = Math.min((to === 0 ? 0 : (to||Infinity)), this.count()-1);\n\n\t\tconst ret = _to_array(); //result of method is rich-array\n\t\tfor (let i = (from||0); i <= to; i++)\n\t\t\tret.push(this.getItem(this.order[i]));\n\t\treturn ret;\n\t},\n\t//returns total count of elements\n\tcount:function(){\n\t\treturn this.order.length;\n\t},\n\t//returns truy if item with such ID exists\n\texists:function(id){\n\t\treturn !!(this.pull[id]);\n\t},\n\t//nextmethod is not visible on component level, check DataMove.move\n\t//moves item from source index to the target index\n\tmove:function(sindex,tindex){\n\t\tassert(sindex>=0 && tindex>=0, \"DataStore::move\",\"Incorrect indexes\");\n\t\tif (sindex == tindex) return;\n\n\t\tconst id = this.getIdByIndex(sindex);\n\t\tconst obj = this.getItem(id);\n\n\t\tif (this._filter_order)\n\t\t\tthis._move_inner(this._filter_order, 0, 0, this.getIdByIndex(sindex), this.getIdByIndex(tindex));\n\n\t\tthis._move_inner(this.order, sindex, tindex);\n\t\t\n\t\t\n\t\t//repaint signal\n\t\tthis.callEvent(\"onStoreUpdated\",[id,obj,\"move\"]);\n\t},\n\t_move_inner:function(col, sindex, tindex, sid, tid){\n\t\tif (sid||tid){\n\t\t\tsindex = tindex = -1;\n\t\t\tfor (let i = 0; i < col.length; i++){\n\t\t\t\tif (col[i] == sid && sindex<0)\n\t\t\t\t\tsindex = i;\n\t\t\t\tif (col[i] == tid && tindex<0)\n\t\t\t\t\ttindex = i;\n\t\t\t}\n\t\t}\n\t\tconst id = col[sindex];\n\t\tcol.removeAt(sindex);\t//remove at old position\n\t\tcol.insertAt(id,Math.min(col.length, tindex));\t//insert at new position\n\t},\n\tscheme:function(config){\n\t\tthis._scheme = {};\n\t\tthis._scheme_save = config.$save;\n\t\tthis._scheme_init = config.$init||config.$change;\n\t\tthis._scheme_update = config.$update||config.$change;\n\t\tthis._scheme_serialize = config.$serialize;\n\t\tthis._scheme_group = config.$group;\n\t\tthis._scheme_sort = config.$sort;\n\t\tthis._scheme_export = config.$export;\n\n\t\t//ignore $-starting properties, as they have special meaning\n\t\tfor (let key in config)\n\t\t\tif (key.substr(0,1) != \"$\")\n\t\t\t\tthis._scheme[key] = config[key];\n\t},\n\timportData:function(target, silent){\n\t\tconst data = target ? (target.data || target) : [];\n\t\tthis._filter_order = null;\n\n\t\tif (typeof data.serialize == \"function\"){\n\t\t\tthis.order = _to_array([].concat(data.order));\n\n\t\t\t//make full copy, to preserve object properties\n\t\t\t//[WE-CAN-DO-BETTER]\n\t\t\tif (this._make_full_copy){\n\t\t\t\tthis._make_full_copy = false;\n\t\t\t\tconst oldpull = this.pull;\n\t\t\t\tthis.pull = {};\n\t\t\t\tfor (let key in data.pull){\n\t\t\t\t\tconst old = oldpull[key];\n\t\t\t\t\tthis.pull[key] = copy(data.pull[key]);\n\t\t\t\t\tif (old && old.open) this.pull[key].open = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.pull = {};\n\t\t\t\tfor (let key in data.pull)\n\t\t\t\t\tthis.pull[key] = data.pull[key];\n\t\t\t}\n\n\t\t\tif (data.branch && this.branch){\n\t\t\t\tthis.branch = copy(data.branch);\n\t\t\t\tthis._filter_branch = null;\n\t\t\t}\n\n\t\t} else {\n\t\t\tthis.order = _to_array();\n\t\t\tthis.pull = {};\n\t\t\tlet id, obj;\n\n\t\t\tif (isArray(target))\n\t\t\t\tfor (let key=0; key data_size){\n\t\t\tassert(0, \"Warning\",\"DataStore:add\",\"Index of out of bounds\");\n\t\t\tindex = Math.min(order.length,index);\n\t\t}\n\t\tif (this.callEvent(\"onBeforeAdd\", [id, obj, index]) === false) return false;\n\n\t\tassert(!this.exists(id), \"Not unique ID\");\n\n\t\tthis.pull[id]=obj;\n\t\torder.insertAt(id,index);\n\t\tif (this._filter_order){\t//adding during filtering\n\t\t\t//we can't know the location of new item in full dataset, making suggestion\n\t\t\t//put at end of original dataset by default\n\t\t\tlet original_index = this._filter_order.length;\n\t\t\t//if some data exists, put at the same position in original and filtered lists\n\t\t\tif (this.order.length)\n\t\t\t\toriginal_index = Math.min((index || 0), original_index);\n\n\t\t\tthis._filter_order.insertAt(id,original_index);\n\t\t}\n\n\t\t//repaint signal\n\t\tthis.callEvent(\"onStoreUpdated\",[id,obj,\"add\"]);\n\t\tthis.callEvent(\"onAfterAdd\",[id,index]);\n\n\t\treturn obj.id;\n\t},\n\t\n\t//removes element from datastore\n\tremove:function(id){\n\t\t//id can be an array of IDs - result of getSelect, for example\n\t\tif (isArray(id)){\n\t\t\tfor (let i = 0; i < id.length; i++)\n\t\t\t\tthis.remove(id[i]);\n\t\t\treturn;\n\t\t}\n\t\tif (this.callEvent(\"onBeforeDelete\",[id]) === false) return false;\n\t\t\n\t\tassert(this.exists(id), \"Not existing ID in remove command\"+id);\n\n\t\tconst obj = this.getItem(id); //save for later event\n\t\t//clear from collections\n\t\tthis.order.remove(id);\n\t\tif (this._filter_order) \n\t\t\tthis._filter_order.remove(id);\n\t\t\t\n\t\tdelete this.pull[id];\n\t\tif (this._marks[id])\n\t\t\tdelete this._marks[id];\n\n\t\t//repaint signal\n\t\tthis.callEvent(\"onStoreUpdated\",[id,obj,\"delete\"]);\n\t\tthis.callEvent(\"onAfterDelete\",[id]);\n\t},\n\t//deletes all records in datastore\n\tclearAll:function(soft){\n\t\t//instead of deleting one by one - just reset inner collections\n\t\tthis.pull = {};\n\t\tthis._marks = {};\n\t\tthis.order = _to_array();\n\t\t//this.feed = null;\n\t\tthis._filter_order = null;\n\t\tif (!soft)\n\t\t\tthis.url = null;\n\t\tthis.callEvent(\"onClearAll\",[soft]);\n\t\tthis.refresh();\n\t},\n\t//converts index to id\n\tgetIdByIndex:function(index){\n\t\tassert(index >= 0,\"DataStore::getIdByIndex Incorrect index\");\n\t\treturn this.order[index];\n\t},\n\t//converts id to index\n\tgetIndexById:function(id){\n\t\tif (!this.pull[id])\n\t\t\treturn -1;\n\t\telse\n\t\t\treturn this.order.find(id);\t//slower than getIdByIndex\n\t},\n\t//returns ID of next element\n\tgetNextId:function(id,step){\n\t\treturn this.order[this.getIndexById(id)+(step||1)];\n\t},\n\t//returns ID of first element\n\tgetFirstId:function(){\n\t\treturn this.order[0];\n\t},\n\t//returns ID of last element\n\tgetLastId:function(){\n\t\treturn this.order[this.order.length-1];\n\t},\n\t//returns ID of previous element\n\tgetPrevId:function(id,step){\n\t\treturn this.order[this.getIndexById(id)-(step||1)];\n\t},\n\t/*\n\t\tsort data in collection\n\t\t\tby - settings of sorting\n\n\t\tor\n\t\t\tby - array of settings\n\n\t\tor\n\n\t\t\tby - sorting function\n\t\t\tdir - \"asc\" or \"desc\"\n\n\t\tor\n\n\t\t\tby - property\n\t\t\tdir - \"asc\" or \"desc\"\n\t\t\tas - type of sortings\n\n\t\tSorting function will accept 2 parameters and must return 1,0,-1, based on desired order\n\n\t\treturns true if sorting was successful, false otherwise\n\t*/\n\tsort:function(by, dir, as){\n\t\tlet parameters;\n\t\tlet sort = by;\n\n\t\tif (isArray(sort)){\n\t\t\tsort = sort.map(a => this._sort_init(a));\n\t\t\tparameters = [sort];\n\t\t} else {\n\t\t\tsort = this._sort_init(by, dir, as);\n\t\t\tparameters = [sort.by, sort.dir, sort.as, sort];\n\t\t}\n\n\t\tif (!this.callEvent(\"onBeforeSort\", parameters)) return false;\n\t\tconst sorter = this.sorting.create(sort);\n\n\t\tthis.order = this._sort_core(sorter, this.order);\n\t\tif (this._filter_order)\n\t\t\tthis._filter_order = this._sort_core(sorter, this._filter_order);\n\t\tif (this._filter_branch)\t//treestore\n\t\t\tthis._sort_core(sorter, this.order, this._filter_branch);\n\n\t\t//repaint self\n\t\tthis.refresh();\n\n\t\tthis.callEvent(\"onAfterSort\", parameters);\n\t\treturn true;\n\t},\n\t_sort_init:function(by, dir, as){\n\t\tlet sort = by;\n\n\t\tif (typeof by == \"function\")\n\t\t\tsort = {as:by, dir:dir};\n\t\telse if (typeof by == \"string\")\n\t\t\tsort = {by:by, dir:dir, as:as};\n\n\t\tif (typeof sort.by == \"string\")\n\t\t\tsort.by = sort.by.replace(/#/g,\"\");\n\n\t\treturn sort;\n\t},\n\t_sort_core:function(sorter, order){\n\t\tif (this.order.length){\n\t\t\tconst pre = order.splice(0, this.$freeze);\n\t\t\t//get array of IDs\n\t\t\tconst neworder = _to_array();\n\t\t\tfor (let i = order.length-1; i>=0; i--)\n\t\t\t\tneworder[i] = this.pull[order[i]];\n\n\t\t\tneworder.sort(sorter);\n\t\t\treturn _to_array(pre.concat(neworder.map(function(obj){ \n\t\t\t\tassert(obj, \"Client sorting can't be used with dynamic loading\");\n\t\t\t\treturn this.id(obj);\n\t\t\t},this)));\n\t\t}\n\t\treturn order;\n\t},\n\t/*\n\t\tFilter datasource\n\t\t\n\t\ttext - property, by which filter\n\t\tvalue - filter mask\n\t\t\n\t\tor\n\t\t\n\t\ttext - filter method\n\t\t\n\t\tFilter method will receive data object and must return true or false\n\t*/\n\t_filter_reset:function(preserve){\n\t\t//remove previous filtering , if any\n\t\tif (this._filter_order && !preserve){\n\t\t\tthis.order = this._filter_order;\n\t\t\tdelete this._filter_order;\n\t\t}\n\t},\n\t_filter_core:function(filter, value, preserve){\n\t\tconst neworder = _to_array();\n\t\tconst freeze = this.$freeze || 0;\n\n\t\tfor (let i=0; i < this.order.length; i++){\n\t\t\tconst id = this.order[i];\n\t\t\tif (i < freeze || filter(this.getItem(id),value))\n\t\t\t\tneworder.push(id);\n\t\t}\n\t\t//set new order of items, store original\n\t\tif (!preserve || !this._filter_order)\n\t\t\tthis._filter_order = this.order;\n\t\tthis.order = neworder;\n\t},\n\tfind:function(config, first){\n\t\tconst result = [];\n\n\t\tfor(let i in this.pull){\n\t\t\tconst data = this.pull[i];\n\n\t\t\tlet match = true;\n\t\t\tif (typeof config == \"object\"){\n\t\t\t\tfor (let key in config)\n\t\t\t\t\tif (data[key] != config[key]){\n\t\t\t\t\t\tmatch = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t} else if (!config(data))\n\t\t\t\tmatch = false;\n\n\t\t\tif (match)\n\t\t\t\tresult.push(data);\n\t\t\t\n\t\t\tif (first && result.length)\n\t\t\t\treturn result[0];\n\t\t}\n\n\t\treturn first ? null : result;\n\t},\n\tfilter:function(text,value,preserve){\n\t\t//unfilter call but we already in not-filtered state\n\t\tif (!text && !this._filter_order && !this._filter_branch) return;\n\t\tif (!this.callEvent(\"onBeforeFilter\", [text, value])) return;\n\t\t\n\t\tthis._filter_reset(preserve);\n\t\tif (!this.order.length) return;\n\n\t\t//if text not define -just unfilter previous state and exit\n\t\tif (text){\n\t\t\tlet filter = text;\n\t\t\tvalue = value||\"\";\n\t\t\tif (typeof text == \"string\"){\n\t\t\t\ttext = text.replace(/#/g,\"\");\n\t\t\t\tif (typeof value == \"function\")\n\t\t\t\t\tfilter = function(obj){\n\t\t\t\t\t\treturn value(obj[text]);\n\t\t\t\t\t};\n\t\t\t\telse{\n\t\t\t\t\tvalue = value.toString().toLowerCase();\n\t\t\t\t\tfilter = function(obj,value){\t//default filter - string start from, case in-sensitive\n\t\t\t\t\t\tassert(obj, \"Client side filtering can't be used with dynamic loading\");\n\t\t\t\t\t\treturn (obj[text]||\"\").toString().toLowerCase().indexOf(value)!=-1;\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._filter_core(filter, value, preserve, this._filterMode);\n\t\t}\n\t\t//repaint self\n\t\tthis.refresh();\n\t\t\n\t\tthis.callEvent(\"onAfterFilter\", []);\n\t},\n\t/*\n\t\tIterate through collection\n\t*/\n\t_obj_array:function(){\n\t\tconst data = [];\n\t\tfor (let i = this.order.length - 1; i >= 0; i--)\n\t\t\tdata[i]=this.pull[this.order[i]];\n\n\t\treturn data;\n\t},\n\teach:function(method, master, all){\n\t\tlet order = this.order;\n\t\tif (all)\n\t\t\torder = this._filter_order || order;\n\n\t\tfor (let i = 0; i b && a ? \" \" : \"\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!silent) \n\t\t\t\tthis.refresh(id);\n\t\t}\n\t},\n\tgetMark:function(id, mark){\n\t\tconst obj = this._marks[id];\n\t\treturn (obj ? obj[mark] : false);\n\t},\n\tclearMark:function(name, css, silent){\n\t\tfor (const id in this._marks){\n\t\t\tconst obj = this._marks[id];\n\t\t\tif (obj[name]){\n\t\t\t\tdelete obj[name];\n\t\t\t\tif (css && obj.$css){\n\t\t\t\t\tconst re = new RegExp(\"(\\\\s|^)\"+name+\"(\\\\s|$)\");\n\t\t\t\t\tobj.$css = obj.$css.replace(re, (v,b,a) => b && a ? \" \" : \"\");\n\t\t\t\t}\n\t\t\t\tif (!silent)\n\t\t\t\t\tthis.refresh(id);\n\t\t\t}\n\t\t}\n\t},\n\t/*\n\t\tserializes data to a json object\n\t*/\n\tserialize: function(all){\n\t\tlet ids = this.order;\n\t\tif (all && this._filter_order)\n\t\t\tids = this._filter_order;\n\n\t\tconst result = [];\n\t\tfor(let i=0; i< ids.length;i++) {\n\t\t\tlet el = this.pull[ids[i]];\n\t\t\tif (this._scheme_serialize){\n\t\t\t\tel = this._scheme_serialize(el);\n\t\t\t\tif (el===false) continue;\n\t\t\t}\n\t\t\tresult.push(el);\n\t\t}\n\t\treturn result;\n\t},\n\tsorting:{\n\t\tcreate:function(config){\n\t\t\tif (isArray(config))\n\t\t\t\treturn this._multi(config);\n\t\t\treturn this._dir(config.dir, this._by(config.by, config.as));\n\t\t},\n\t\tas:{\n\t\t\t//handled by dataFeed\n\t\t\t\"server\":function(){\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t\"date\":function(a,b){\n\t\t\t\ta = a-0; b = b-0;\n\t\t\t\tif (isNaN(b)) return 1;\n\t\t\t\tif (isNaN(a)) return -1;\n\n\t\t\t\treturn a>b?1:(ab?1:(ab?1:(ab?1:(ab?1:(a this._dir(c.dir, this._by(c.by, c.as)));\n\n\t\t\treturn function(a,b){\n\t\t\t\tlet result, i = 0;\n\t\t\t\tdo {\n\t\t\t\t\tresult = methods[i](a,b);\n\t\t\t\t} while(!result && methods[++i]);\n\t\t\t\treturn result;\n\t\t\t};\n\t\t},\n\t\t_by:function(prop, method){\n\t\t\tlet customMethod;\n\n\t\t\tif (typeof method != \"function\")\n\t\t\t\tmethod = this.as[method||\"string\"];\n\t\t\telse\n\t\t\t\tcustomMethod = true;\n\n\t\t\tassert(method, \"Invalid sorting method\");\n\t\t\treturn function(a,b){\n\t\t\t\tif(!customMethod){\n\t\t\t\t\ta = a[prop];\n\t\t\t\t\tb = b[prop];\n\t\t\t\t}\n\t\t\t\treturn method(a, b, prop);\n\t\t\t};\n\t\t},\n\t\t_dir:function(prop, method){\n\t\t\tif (prop == \"asc\" || !prop)\n\t\t\t\treturn method;\n\t\t\treturn function(a,b){\n\t\t\t\treturn method(a,b)*-1;\n\t\t\t};\n\t\t}\n\t}\n};\n\nexport default DataStore;","import {ajax} from \"../load/ajax\";\nimport {bind, delay, extend, toFunctor, isArray} from \"../webix/helpers\";\nimport {proto} from \"../ui/core\";\n\nimport {dp} from \"../load/dataprocessor\";\nimport proxy from \"../load/proxy\";\nimport promise from \"../thirdparty/promiz\";\n\nimport DataStore from \"../core/datastore\";\nimport AtomDataLoader from \"../core/atomdataloader\";\n\n\n/*\n\tBehavior:DataLoader - load data in the component\n\t\n\t@export\n\t\tload\n\t\tparse\n*/\nconst DataLoader =proto({\n\t$init:function(config){\n\t\t//prepare data store\n\t\tconfig = config || \"\";\n\n\t\tthis._feed_last = {};\n\t\tthis._data_generation = 0;\n\n\t\tthis.data = new DataStore();\n\t\tthis.data.attachEvent(\"onClearAll\", bind(this._call_onclearall, this));\n\t\tthis.data.attachEvent(\"onServerConfig\", bind(this._call_on_config, this));\n\t\tthis.attachEvent(\"onDestruct\", this._call_onclearall);\n\n\t\tthis.data.feed = this._feed;\n\t\tthis.data.owner = config.id;\n\t},\n\t_feed:function(from, count, callback, defer, clear){\n\t\t//allow only single request at same time\n\t\tif (this._load_count){\n\t\t\tdefer = promise.defer();\n\t\t\tthis._load_count = [from,count,callback,defer,clear];\t//save last ignored request\n\t\t\treturn defer;\n\t\t} else\n\t\t\tthis._load_count = true;\n\t\tthis._feed_last.from = from;\n\t\tthis._feed_last.count = count;\n\t\treturn this._feed_common.call(this, from, count, callback, defer, false, clear);\n\t},\n\t_feed_common:function(from, count, callback, defer, details, clear){\n\t\tlet url = this.data.url;\n\t\tif (from < 0) from = 0;\n\n\t\tif(!details)\n\t\t\tdetails = { start: from, count:count };\n\n\t\tif(this.count())\n\t\t\tdetails[\"continue\"] = \"true\";\n\n\t\tconst state = this.getState ? this.getState() : null;\n\t\t// proxy\n\t\tif (url && typeof url != \"string\"){\n\t\t\tif (state){\n\t\t\t\tif (state.sort)\n\t\t\t\t\tdetails.sort = state.sort;\n\t\t\t\tif (state.filter)\n\t\t\t\t\tdetails.filter = state.filter;\n\t\t\t}\n\t\t\treturn this.load(url, 0, details, clear).then(\n\t\t\t\tdata => this._feed_on_load(data, callback, defer),\n\t\t\t\t() => this._feed_callback()\n\t\t\t);\n\t\t} else { // GET\n\t\t\turl = url+((url.indexOf(\"?\")==-1)?\"?\":\"&\");\n\n\t\t\tvar params = [];\n\t\t\tfor(var d in details){\n\t\t\t\tparams.push(d+\"=\"+details[d]);\n\t\t\t}\n\t\t\tif (state){\n\t\t\t\tif (state.sort){\n\t\t\t\t\tvar sort = isArray(state.sort) ? state.sort : [state.sort];\n\t\t\t\t\tfor (var i=0; i this._feed_on_load(data, callback, defer),\n\t\t\t\t\t() => this._feed_callback()\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthis._load_count = false;\n\t\t\t\treturn promise.reject();\n\t\t\t}\n\t\t}\n\t},\n\t_feed_on_load:function(data, callback, defer){\n\t\tdelay(()=> this._feed_callback(), \"\", \"\", 100);\n\t\tif(callback)\n\t\t\tajax.$callback(this, callback, data);\n\t\tif(defer)\n\t\t\tdefer.resolve(data);\n\t\treturn data;\n\t},\n\t_feed_callback:function(){\n\t\t//after loading check if we have some ignored requests\n\t\tvar temp = this._load_count;\n\t\tthis._load_count = false;\n\t\tif (typeof temp ==\"object\")\n\t\t\tthis.data.feed.apply(this, temp);\t//load last ignored request\n\t},\n\t//loads data from external URL\n\tload:function(url){\n\t\turl = proxy.$parse(url);\n\t\tvar ajax = AtomDataLoader.load.apply(this, arguments);\n\n\t\t//prepare data feed for dyn. loading\n\t\tif (!this.data.url)\n\t\t\tthis.data.url = url;\n\n\t\treturn ajax;\n\t},\n\t//load next set of data rows\n\tloadNext:function(count, start, callback, url, now, clear){\n\t\tvar config = this._settings;\n\t\tif (config.datathrottle && !now){\n\t\t\tif (this._throttle_request)\n\t\t\t\twindow.clearTimeout(this._throttle_request);\n\n\t\t\tlet defer = promise.defer();\n\t\t\tthis._throttle_request = delay(function(){\n\t\t\t\tdefer.resolve(this.loadNext(count, start, callback, url, true, clear));\n\t\t\t},this, 0, config.datathrottle);\n\t\t\treturn defer;\n\t\t}\n\n\t\tif (!start && start !== 0) start = this.count();\n\t\tif (!count)\n\t\t\tcount = config.datafetch || this.count();\n\n\t\tthis.data.url = url || this.data.url;\n\t\tif (this.callEvent(\"onDataRequest\", [start,count,callback,url]) && this.data.url)\n\t\t\treturn this.data.feed.call(this, start, count, callback, false, clear);\n\t\treturn promise.reject();\n\t},\n\t_maybe_loading_already:function(count, from){\n\t\tvar last = this._feed_last;\n\t\tif(this._load_count && last.url){\n\t\t\tif (last.from<=from && (last.count+last.from >= count + from )) return true;\n\t\t}\n\t\treturn false;\n\t},\n\tremoveMissed_setter:function(value){\n\t\treturn (this.data._removeMissed = value);\n\t},\n\t//init of dataprocessor delayed after all settings processing\n\t//because it need to be the last in the event processing chain\n\t//to get valid validation state\n\t_init_dataprocessor:function(){\n\t\tvar url = this._settings.save;\n\n\t\tif (url === true)\n\t\t\turl = this._settings.save = this._settings.url;\n\n\t\tvar obj = { master: this };\n\t\t\n\t\tif (url && url.url)\n\t\t\textend(obj, url);\n\t\telse\n\t\t\tobj.url = url;\n\n\t\tdp(obj);\n\t},\n\tsave_setter:function(value){\n\t\tif (value)\n\t\t\tthis.$ready.push(this._init_dataprocessor);\n\n\t\treturn value;\n\t},\n\twaitSave:function(handler){\n\t\treturn dp(this)._promise(() => {\n\t\t\thandler.call(this);\n\t\t}).then(many => many.length == 1 ? many[0] : many);\n\t},\n\tscheme_setter:function(value){\n\t\tthis.data.scheme(value);\n\t},\n\tdataFeed_setter:function(value){\n\t\tvalue = proxy.$parse(value);\n\n\t\tthis.data.attachEvent(\"onBeforeFilter\", bind(function(text, filtervalue){\n\t\t\tvar result;\n\n\t\t\t//complex filtering, can't be routed to dataFeed\n\t\t\tif (typeof text == \"function\") return true;\n\n\t\t\t//we have dataFeed and some text\n\t\t\tif (this._settings.dataFeed && (text || filtervalue)){\n\t\t\t\ttext = text || \"id\";\n\t\t\t\tif (filtervalue && typeof filtervalue == \"object\")\n\t\t\t\t\tfiltervalue = filtervalue.id;\n\n\t\t\t\tvar url = this._settings.dataFeed;\n\n\t\t\t\t//url data feed\n\t\t\t\tif(typeof url ==\"string\"){\n\t\t\t\t\tvar urldata = \"filter[\"+text+\"]=\"+encodeURIComponent(filtervalue);\n\t\t\t\t\tresult = this._fetch(\n\t\t\t\t\t\turl+(url.indexOf(\"?\")<0?\"?\":\"&\")+urldata,\n\t\t\t\t\t\tthis._settings.datatype\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t//js data feed\n\t\t\t\telse{\n\t\t\t\t\tvar filter = {};\n\t\t\t\t\tfilter[text] = filtervalue;\n\t\t\t\t\tif (typeof url == \"function\"){\n\t\t\t\t\t\tresult = url.call(this, filtervalue, filter);\n\t\t\t\t\t} else if (url.$proxy && url.load) {\n\t\t\t\t\t\tresult = url.load(this, { filter });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (result){\n\t\t\t\t\tif (!result.then)\n\t\t\t\t\t\tresult = promise.resolve(result);\n\n\t\t\t\t\tresult.then(\n\t\t\t\t\t\tdata => {\n\t\t\t\t\t\t\tthis._onLoad(data, true);\n\t\t\t\t\t\t\tthis.data.callEvent(\"onAfterFilter\", []);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tx => this._onLoadError(x)\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},this));\n\t\treturn value;\n\t},\n\t_call_onready:function(){\n\t\tif (this._settings.ready && !this._ready_was_used){\n\t\t\tvar code = toFunctor(this._settings.ready, this.$scope);\n\t\t\tif (code)\n\t\t\t\tdelay(code, this, arguments);\n\t\t\tif (this.callEvent)\n\t\t\t\tdelay(this.callEvent, this, [\"onReady\", []]);\n\t\t\tthis._ready_was_used = true;\n\t\t}\n\t},\n\t_call_onclearall:function(soft){\n\t\tthis._data_generation++;\n\t\tif (!soft){\n\t\t\tthis._load_count = false;\n\t\t\tthis._feed_last = {};\n\t\t\tthis.waitData = promise.defer();\n\t\t}\n\t},\n\t_call_on_config:function(config){\n\t\tthis._parseSeetingColl(config);\n\t}\n},AtomDataLoader);\n\n\n\nexport default DataLoader;","import {pos, offset} from \"../webix/html\";\nimport {use} from \"../services\";\nimport Touch from \"../core/touch\";\nimport {extend, delay, _power_array, isArray} from \"../webix/helpers\";\nimport {assert} from \"../webix/debug\";\nimport DragControl from \"../core/dragcontrol\";\nimport AutoScroll from \"../core/autoscroll\";\n\n\n/*\n\tBehavior:DragItem - adds ability to move items by dnd\n\t\n\tdnd context can have next properties\n\t\tfrom - source object\n\t\tto - target object\n\t\tsource - id of dragged item(s)\n\t\ttarget - id of drop target, null for drop on empty space\n\t\tstart - id from which DND was started\n*/\n\nconst DragItem ={\n\t//helper - defines component's container as active zone for dragging and for dropping\n\t_initHandlers:function(obj, source, target){\n\t\tif (!source) DragControl.addDrop(obj._contentobj,obj,true);\n\t\tif (!target) DragControl.addDrag(obj._contentobj,obj);\n\t\tthis.attachEvent(\"onDragOut\",function(a,b){ this.$dragMark(a,b); });\n\t\tthis.attachEvent(\"onBeforeAutoScroll\",function(){\n\t\t\tvar context = DragControl.getContext();\n\t\t\treturn !!(DragControl._active && context && (context.to === this || this._auto_scroll_force));\n\t\t});\n\t},\n\tdrag_setter:function(value){\n\t\tif (value){\n\t\t\textend(this, AutoScroll, true);\n\t\t\tif (value == \"order\" || value == \"move\")\n\t\t\t\textend(this, use(\"DragOrder\"), true);\n\t\t\tif (value == \"inner\" || value == \"order\")\n\t\t\t\tthis._inner_drag_only = true;\n\n\t\t\tthis._initHandlers(this, value == \"source\", value == \"target\");\n\t\t\tdelete this.drag_setter;\t//prevent double initialization\n\t\t}\n\t\treturn value;\n\t},\n\t/*\n\t\ts - source html element\n\t\tt - target html element\n\t\td - drop-on html element ( can be not equal to the target )\n\t\te - native html event \n\t*/\n\t//called when drag moved over possible target\n\t$dragIn:function(s,t,e){\n\t\tvar id = this.locate(e) || null;\n\t\tvar context = DragControl._drag_context;\n\n\t\t//in inner drag mode - ignore dnd from other components\n\t\tif ((this._inner_drag_only || context.from._inner_drag_only) && context.from !== this) return false;\n\n\t\tvar to = DragControl.getMaster(t);\n\t\t//previous target\n\t\tvar html = (this.getItemNode(id, e)||this._dataobj);\n\t\t//prevent double processing of same target\n\t\tif (html == DragControl._landing) return html;\n\t\tcontext.target = id;\n\t\tcontext.to = to;\n\n\t\tif (this._auto_scroll_delay)\n\t\t\tthis._auto_scroll_delay = window.clearTimeout(this._auto_scroll_delay);\n\n\t\tconst fragile = (this._touch_scroll && !this._settings.prerender);\n\t\tif (this._settings.dragscroll !== false && !fragile)\n\t\t\tthis._auto_scroll_delay = delay(function(pos,id){\n\t\t\t\tthis._drag_pause(id);\n\t\t\t\tthis._auto_scroll(pos,id);\n\t\t\t}, this, [pos(e), id], 250);\n\n\t\tif (!this.$dropAllow(context, e) || !this.callEvent(\"onBeforeDragIn\",[context, e])){\n\t\t\tcontext.to = context.target = null;\n\t\t\tif (this._auto_scroll_delay)\n\t\t\t\tthis._auto_scroll_delay = window.clearTimeout(this._auto_scroll_delay);\n\t\t\treturn null;\n\t\t}\n\t\t//mark target only when landing confirmed\n\t\tthis.$dragMark(context,e);\n\t\treturn html;\n\t},\n\t$dropAllow:function(){\n\t\treturn true;\n\t},\n\t_drag_pause:function(){\n\t\t//may be reimplemented in some components\n\t\t// tree for example\n\t},\n\t_target_to_id:function(target){\n\t\treturn target && typeof target === \"object\" ? target.toString() : target;\n\t},\n\t//called when drag moved out from possible target\n\t$dragOut:function(s,t,n,e){\n\t\tvar id = (this._viewobj.contains(n) ? this.locate(e): null) || null;\n\t\tvar context = DragControl._drag_context;\n\n\t\t//still over previous target\n\t\tif ((context.target||\"\").toString() == (id||\"\").toString()) return null;\n\t\tif (this._auto_scroll_delay)\n\t\t\tthis._auto_scroll_delay = window.clearTimeout(this._auto_scroll_delay);\n\n\t\t//unmark previous target\n\t\tcontext.target = context.to = null;\n\t\tthis.callEvent(\"onDragOut\",[context,e]);\n\t\treturn null;\n\t},\n\t//called when drag moved on target and button is released\n\t$drop:function(s,t,e){\n\t\tvar context = DragControl._drag_context;\n\t\t//finalize context details\n\t\tcontext.to = this;\n\t\tthis._define_index(s,t,context);\n\n\t\t//unmark last target\n\t\tthis.$dragMark({}, e);\n\n\t\tif( context.from && context.from != context.to && context.from.callEvent ){\n\t\t\tif(!context.from.callEvent(\"onBeforeDropOut\", [context,e]))\n\t\t\t\treturn;\n\t\t}\n\n\t\tif (!this.callEvent(\"onBeforeDrop\",[context,e])) return;\n\t\t//moving\n\t\tthis._context_to_move(context,e);\n\t\t\n\t\tthis.callEvent(\"onAfterDrop\",[context,e]);\n\t},\n\t_define_index:function(s,t,context){\n\t\tvar target = this._target_to_id(context.target);\n\n\t\tif (this.getBranchIndex){\n\t\t\tif (target){\n\t\t\t\tcontext.parent = this.getParentId(target);\n\t\t\t\tcontext.index = this.getBranchIndex(target);\n\t\t\t} else context.index = -1;\n\t\t} else\n\t\t\tcontext.index = target?this.getIndexById(target):this.count();\n\t},\n\t_context_to_move:function(context){\n\t\tassert(context.from, \"Unsopported d-n-d combination\");\n\t\tif (context.from && context.from.move){\t//from different component with item dnd\n\t\t\tvar details = { parent: context.parent, mode: context.pos };\n\t\t\tcontext.from.move(context.source,context.index,context.to, details);\n\t\t}\n\t},\n\t$longTouchLimit: true,\n\t_getDragItemPos: function(pos,e){\n\t\tif (this.getItemNode){\n\t\t\tvar id = this.locate(e, true);\n\t\t\t//in some case, node may be outiside of dom ( spans in datatable for example )\n\t\t\t//so getItemNode can return null\n\t\t\tvar node = id ? this.getItemNode(id) : null;\n\t\t\treturn node ? offset(node) : node;\n\t\t}\n\t},\n\t//called when drag action started\n\t$drag:function(s,e){\n\t\tvar id = this.locate(e, true);\n\t\tif (id){\n\t\t\tvar list = [id];\n\n\t\t\tif (this.getSelectedId){ //has selection model\n\t\t\t\t//if dragged item is one of selected - drag all selected\n\t\t\t\tvar selection = this.getSelectedId(true, true);\t\n\n\t\t\t\tif (selection && selection.length > 1 && _power_array.find.call(selection,id)!=-1){\n\t\t\t\t\tvar hash = {}; \n\t\t\t\t\tlist = [];\n\t\t\t\t\tfor (let i=0;i 1 )\n\t\t\thtml = this._toMultipleHTML(html, context.source.length);\n\t\treturn html;\n\t},\n\t_toMultipleHTML:function(html, len){\n\t\thtml = \"
\"+html+\"
\";\n\t\tlet multiple = \"
\";\n\t\tif ( len > 2 )\n\t\t\tmultiple = \"
\" + multiple;\n\t\treturn multiple+html+\"\"+len+\"\";\n\t},\n\t$dragMark:function(context){\n\t\tvar target = null;\n\t\tif (context.target)\n\t\t\ttarget = this._target_to_id(context.target);\n\n\t\t//touch webkit will stop touchmove event if source node removed\n\t\tif (this._marked && this._marked != target){\n\t\t\tthis._remove_css([this._marked], \"webix_drag_over\", true);\n\t\t\tthis._marked = null;\n\t\t}\n\n\t\tif (!this._marked && target){\n\t\t\tthis._marked = target;\n\t\t\tthis._add_css([target], \"webix_drag_over\", true);\n\t\t\treturn target;\n\t\t}\n\t\t\n\t\treturn !!context.to;\n\t},\n\t_add_css:function(source, css){\n\t\tfor (let i=0; i ofs[settings[settings.direction]] )\n\t\t\t\ttarget = this.getNextId(target) || \"$webix-last\";\n\t\t}\n\n\t\tif (target == this._marked_item_id || target == \"$webix-drop\")\n\t\t\treturn html;\n\n\t\tthis._marked_item_id = target;\n\t\tthis._set_drop_area(target, t);\n\n\t\treturn html;\n\t},\n\t$dragPos:function(pos){\n\t\tif (!this._inner_drag_only){\n\t\t\tlet context = DragControl._drag_context;\n\t\t\tpos.y += context.y_offset;\n\t\t\tpos.x += context.x_offset;\n\t\t\treturn;\n\t\t}\n\n\t\tlet box = offset(this.$view);\n\t\tlet xdrag = (this._settings.layout == \"x\");\n\n\t\tif (xdrag){\n\t\t\tbox.x -= 12;\n\t\t\tpos.y = box.y - 8;\n\t\t\tpos.x = pos.x - 18;\n\n\t\t\tif (pos.x < box.x)\n\t\t\t\tpos.x = box.x;\n\t\t\telse {\n\t\t\t\tlet max = box.x + box.width;\n\t\t\t\tif (pos.x > max)\n\t\t\t\t\tpos.x = max;\n\t\t\t}\n\t\t} else {\n\t\t\tbox.y += (this._header_height||0) - 12;\n\t\t\tpos.x = box.x + 8 + (this._drag_order_stored_left||0);\n\t\t\tpos.y = pos.y - 18;\n\n\t\t\tif (pos.y < box.y)\n\t\t\t\tpos.y = box.y;\n\t\t\telse {\n\t\t\t\tlet max = box.y + box.height - (this._header_height||0);\n\t\t\t\tif (pos.y > max)\n\t\t\t\t\tpos.y = max;\n\t\t\t}\n\t\t}\n\t},\n\t$dragOut:function(s,ot,nt){\n\t\tif (ot != nt){\n\t\t\tif (this._remove_drop_area) this._remove_drop_area();\n\t\t\telse remove(DragControl._dropHTML);\n\t\t\tthis._marked_item_id = DragControl._dropHTML = null;\n\t\t}\n\t\treturn DragItem.$dragOut.apply(this, arguments);\n\t},\n\t_define_index:function(s,t,context){\n\t\tvar target = this._marked_item_id == \"$webix-last\" ? null : this._marked_item_id;\n\n\t\tif (this.getBranchIndex){\n\t\t\tif (target){\n\t\t\t\tcontext.parent = this.getParentId(target);\n\t\t\t\tcontext.index = this.getBranchIndex(target);\n\t\t\t\tif (s == t && this.getParentId(context.start) == context.parent && this.getBranchIndex(context.start) < context.index)\n\t\t\t\t\tcontext.index -= 1;\n\t\t\t} else context.index = -1;\n\t\t} else {\n\t\t\tcontext.index = target?this.getIndexById(target):this.count();\n\t\t\tcontext.index -= (s == t && this.getIndexById(context.start)= 0 ? start : input.value.length;\n\t\t\t\tinput.selectionEnd = input.value.length;\n\t\t\t}\n\t\t} catch(e){}\t// eslint-disable-line\n\t},\n\t_refocus_inline_editor:function(){\n\t\tconst editor = this.getEditor();\n\t\tif (editor && editor.$inline && !editor.getPopup){\n\t\t\tconst newnode = this._locateInput(editor);\n\t\t\tif (newnode && newnode != editor.node){\n\t\t\t\teditor.node = newnode;\n\t\t\t\tnewnode.focus();\n\n\t\t\t\tconst justOpened = (new Date())-this._edit_open_time > 200;\n\t\t\t\tthis._try_reselecting_text(newnode, justOpened ? -1 : 0);\n\t\t\t}\n\t\t}\n\t},\n\teditable_setter:function(value){\n\t\tif (value)\n\t\t\tthis._init_edit_events_once();\n\t\treturn value;\n\t},\n\t_init_edit_events_once:function(){\n\t\t//will close editor on any click outside\n\t\tconst e1 = attachEvent(\"onEditEnd\", bind(function(){\n\t\t\tif (this._in_edit_mode)\n\t\t\t\tthis.editStop();\n\t\t}, this));\n\t\tconst e2 = attachEvent(\"onClick\", bind(function(e){\n\t\t\t//but ignore click which opens editor\n\t\t\tif (this._in_edit_mode && (new Date())-this._edit_open_time > 200){\n\t\t\t\tif (!this._last_editor || this._last_editor.popupType || !e || ( !this._last_editor.node || !this._last_editor.node.contains(e.target)))\n\t\t\t\t\tthis.editStop();\n\t\t\t}\n\t\t}, this));\n\n\t\tthis.attachEvent(\"onDestruct\", function(){ detachEvent(e1); detachEvent(e2); });\n\t\t\n\t\t//property sheet has simple data object, without events\n\t\tif (this.data.attachEvent)\n\t\t\tthis.data.attachEvent(\"onIdChange\", bind(function(oldid, newid){\n\t\t\t\tthis._changeEditorId(oldid, newid);\n\t\t\t}, this));\n\n\t\t//when clicking on row - will start editor\n\t\tthis.attachEvent(\"onItemClick\", function(id){\n\t\t\tif (this._settings.editable && this._settings.editaction == \"click\")\n\t\t\t\tthis.edit(id);\n\t\t});\n\t\tthis.attachEvent(\"onItemDblClick\", function(id){\n\t\t\tif (this._settings.editable && this._settings.editaction == \"dblclick\")\n\t\t\t\tthis.edit(id);\n\t\t});\n\t\t//each time when we clicking on input, reset timer to prevent self-closing\n\t\tthis._reset_active_editor = bind(function(){\n\t\t\tthis._edit_open_time = new Date();\n\t\t},this);\n\n\t\tthis._init_edit_events_once = function(){};\n\n\t\tif (this._component_specific_edit_init)\n\t\t\tthis._component_specific_edit_init();\n\t},\n\t_handle_live_edits:function(){\n\t\tdelay(function(){\n\t\t\tvar editor = this.getEditor();\n\t\t\tif (editor && editor.config.liveEdit){\n\t\t\t\tvar state = { value:editor.getValue(), old: editor.value };\n\t\t\t\tif (state.value == state.old) return;\n\n\t\t\t\teditor.value = state.value;\n\t\t\t\tthis._set_new_value(editor, state.value, false);\n\t\t\t\tthis.callEvent(\"onLiveEdit\", [state, editor]);\n\t\t\t}\n\t\t}, this);\n\t},\n\t_show_editor_form:function(id){\n\t\tvar form = this._settings.form;\n\t\tif (typeof form != \"string\")\n\t\t\tthis._settings.form = form = ui(form).config.id;\n\n\t\tform = $$(form);\n\t\tvar realform = form.setValues?form:form.getChildViews()[0];\n\t\t\n\t\trealform.setValues(this.getItem(id.row || id), false, \"auto\");\n\t\tform.config.master = this.config.id;\n\t\tform.show( this.getItemNode(id) );\n\n\t\tvar first = realform.getChildViews()[0];\n\t\tif (first.focus)\n\t\t\tfirst.focus();\n\t},\n\tedit:function(id, preserve, show){\n\t\tif (!this._settings.editable || !this.callEvent(\"onBeforeEditStart\", [id])) return;\n\t\tif (this._settings.form)\n\t\t\treturn this._show_editor_form(id);\n\n\t\tvar editor = this._get_editor_type(id);\n\t\tif (editor){\n\t\t\tif (this.getEditor(id)) return;\n\t\t\tif (!preserve) this.editStop();\n\n\t\t\t//render html input\n\t\t\tassert(editors[editor], \"Invalid editor type: \"+editor);\n\t\t\tvar type = extend({}, editors[editor]);\n\n\t\t\tvar node = this._init_editor(id, type, show);\n\t\t\tif (type.config.liveEdit)\n\t\t\t\tthis._live_edits_handler = this.attachEvent(\"onKeyPress\", this._handle_live_edits);\n\n\t\t\tvar area = type.getPopup?type.getPopup(node)._viewobj:node;\n\n\t\t\tif (area)\n\t\t\t\t_event(area, \"click\", this._reset_active_editor);\n\t\t\tif (node)\n\t\t\t\t_event(node, \"input\", this._on_editor_change, { bind:{ view:this, id:id }});\n\t\t\tif (show !== false)\n\t\t\t\ttype.focus();\n\n\t\t\tif (this.$fixEditor)\n\t\t\t\tthis.$fixEditor(type);\n\n\t\t\t//save time of creation to prevent instant closing from the same click\n\t\t\tthis._edit_open_time = globalState.edit_open_time = new Date();\n\n\t\t\tUIManager.setFocus(this, true);\n\t\t\tthis.callEvent(\"onAfterEditStart\", [id]);\n\t\t\treturn type;\n\t\t}\n\t\treturn null;\n\t},\n\tgetEditor:function(id){\n\t\tif (!id)\n\t\t\treturn this._last_editor;\n\n\t\treturn this._editors[id];\n\t},\n\t_changeEditorId:function(oldid, newid)\t{\n\t\tvar editor = this._editors[oldid];\n\t\tif (editor){\n\t\t\tthis._editors[newid] = editor;\n\t\t\teditor.id = newid;\n\t\t\tdelete this._editors[oldid];\n\t\t}\n\t},\n\t_on_editor_change:function(){\n\t\tif (this.view.hasEvent(\"onEditorChange\"))\n\t\t\tthis.view.callEvent(\"onEditorChange\", [this.id, this.view.getEditorValue(this.id) ]);\n\t},\n\t_get_edit_config:function(){\n\t\treturn this._settings;\n\t},\n\t_init_editor:function(id, type, show){\n\t\ttype.config = this._get_edit_config(id);\n\t\tvar node = type.render();\n\n\t\tif (type.$inline)\n\t\t\tnode = this._locateInput(id);\n\t\ttype.node = node;\n\n\t\tvar item = this.getItem(id);\n\t\t//value can be configured by editValue option\n\t\tvar value = item[this._settings.editValue||\"value\"];\n\t\t//if property was not defined - use empty value\n\t\tif (isUndefined(value))\n\t\t\tvalue = \"\";\n\n\t\ttype.setValue(value, item);\n\t\ttype.value = value;\n\n\t\tthis._addEditor(id, type);\n\n\t\tif(type.getPopup)\n\t\t\ttype.getPopup()._editorMaster = this._settings.id;\n\t\t//show it over cell\n\t\tif (show !== false)\n\t\t\tthis.showItem(id);\n\t\tif (!type.$inline)\n\t\t\tthis._sizeToCell(id, node, true);\n\n\t\tif (type.afterRender)\n\t\t\ttype.afterRender();\n\t\treturn node;\n\t},\n\t_locate_cell:function(id){\n\t\treturn this.getItemNode(id);\n\t},\n\t_locateInput:function(id){\n\t\tvar cell = this._locate_cell(id);\n\t\tif (cell)\n\t\t\tcell = cell.getElementsByTagName(\"input\")[0] || cell;\n\n\t\treturn cell;\n\t},\n\t_get_editor_type:function(){\n\t\treturn this._settings.editor;\n\t},\n\t_addEditor:function(id, type){\n\t\ttype.id = id;\n\t\tthis._editors[id]= this._last_editor = type;\n\t\tthis._in_edit_mode++;\n\t},\n\t_removeEditor:function(editor){\n\t\tif (this._last_editor == editor)\n\t\t\tthis._last_editor = 0;\n\t\t\n\t\tif (editor.destroy)\n\t\t\teditor.destroy();\n\n\t\tdelete editor.popup;\n\t\tdelete editor.node;\n\n\t\tdelete this._editors[editor.id];\n\t\tthis._in_edit_mode--;\n\t},\n\tfocusEditor:function(){\n\t\tvar editor = this.getEditor.apply(this, arguments);\n\t\tif (editor && editor.focus)\n\t\t\teditor.focus();\n\t},\n\teditCancel:function(){\n\t\tthis.editStop(null, null, true);\n\t},\n\t_applyChanges: function(el){\n\t\tif (el){\n\t\t\tvar ed = this.getEditor();\n\t\t\tif (ed && ed.getPopup && ed.getPopup() == el.getTopParentView()) return;\n\t\t}\n\t\tthis.editStop();\n\t},\n\teditStop:function(id){\n\t\tif (this._edit_stop) return;\n\t\tthis._edit_stop = 1;\n\n\n\t\tvar cancel = arguments[2];\n\t\tvar result = 1;\n\t\tif (!id){\n\t\t\tthis._for_each_editor(function(editor){\n\t\t\t\tresult = result * this._editStop(editor, cancel);\n\t\t\t});\n\t\t} else \n\t\t\tresult = this._editStop(this._editors[id], cancel);\n\n\t\tthis._edit_stop = 0;\n\t\treturn result;\n\t},\n\t_cellPosition:function(id){\n\t\tvar html = this.getItemNode(id);\n\t\treturn {\n\t\t\tleft:html.offsetLeft, \n\t\t\ttop:html.offsetTop,\n\t\t\theight:html.offsetHeight,\n\t\t\twidth:html.offsetWidth,\n\t\t\tparent:this._contentobj\n\t\t};\n\t},\n\t_sizeToCell:function(id, node, inline){\n\t\t//fake inputs\n\t\tif (!node.style) return;\n\n\t\tvar pos = this._cellPosition(id, null, true);\n\n\t\tnode.style.top = pos.top + \"px\";\n\t\tnode.style.left = pos.left + \"px\";\n\n\t\tnode.style.width = pos.width-1+\"px\";\n\t\tnode.style.height = pos.height-1+\"px\";\n\n\t\tnode.top = pos.top; //later will be used during y-scrolling\n\n\t\tif (inline) pos.parent.appendChild(node);\n\t\treturn pos;\n\t},\n\t_for_each_editor:function(handler){\n\t\tfor (var editor in this._editors)\n\t\t\thandler.call(this, this._editors[editor]);\n\t},\n\t_editStop:function(editor, ignore){\n\t\tif (!editor || globalState._final_destruction) return;\n\t\tvar state = { \n\t\t\tvalue : this._get_new_value(editor), \n\t\t\told : editor.value\n\t\t};\n\t\tif (this.callEvent(\"onBeforeEditStop\", [state, editor, ignore])){\n\t\t\tif (!ignore){\n\t\t\t\t//special case, state.old = 0, state.value = \"\"\n\t\t\t\t//we need to state.old to string, to detect the change\n\t\t\t\tvar old = state.old;\n\t\t\t\tif (typeof state.value == \"string\") old += \"\";\n\n\t\t\t\tif (old != state.value || editor.config.liveEdit){\n\t\t\t\t\tvar item = this._set_new_value(editor, state.value, true);\t\n\t\t\t\t\tthis.updateItem(editor.row || editor.id, item);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (editor.$inline)\n\t\t\t\teditor.node = null;\n\t\t\telse\n\t\t\t\tremove(editor.node);\n\n\t\t\tvar popup = editor.config.suggest;\n\t\t\tif (popup && typeof popup == \"string\")\n\t\t\t\t$$(popup).hide();\n\n\t\t\tthis._removeEditor(editor);\n\t\t\tif (this._live_edits_handler)\n\t\t\t\tthis.detachEvent(this._live_edits_handler);\n\n\t\t\tthis.callEvent(\"onAfterEditStop\", [state, editor, ignore]);\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n\t},\n\tvalidateEditor:function(id){\n\t\tlet result = true;\n\t\tif (this._settings.rules){\n\t\t\tconst editor = this.getEditor(id);\n\t\t\tconst key = editor.column||this._settings.editValue||\"value\";\n\t\t\tconst rule = this._settings.rules[key];\n\t\t\tconst all = this._settings.rules.$all;\n\t\t\tconst input = editor.getInputNode();\n\n\t\t\tif ((rule || all) && !input._viewobj){ //only for html inputs\n\t\t\t\tconst obj = this.data.getItem(editor.row||editor.id);\n\t\t\t\tconst value = editor.getValue();\n\n\t\t\t\tif (rule)\n\t\t\t\t\tresult = rule.call(this, value, obj, key);\n\t\t\t\tif (all)\n\t\t\t\t\tresult = all.call(this, value, obj, key) && result;\n\t\t\t\n\t\t\t\tif (result)\n\t\t\t\t\tremoveCss(input, \"webix_invalid\");\n\t\t\t\telse\n\t\t\t\t\taddCss(input, \"webix_invalid\");\n\n\t\t\t\tcallEvent(\"onLiveValidation\", [editor, result, obj, value]);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t},\n\tgetEditorValue:function(id){\n\t\tvar editor;\n\t\tif (arguments.length === 0)\n\t\t\teditor = this._last_editor;\n\t\telse\n\t\t\teditor = this.getEditor(id);\n\n\t\tif (editor)\n\t\t\treturn editor.getValue();\n\t},\n\tgetEditState:function(){\n\t\treturn this._last_editor || false;\n\t},\n\teditNext:function(next, from){ \n\t\tnext = next !== false; //true by default\n\t\tif (this._in_edit_mode == 1 || from){\n\t\t\t//only if one editor is active\n\t\t\tvar editor_next = this._find_cell_next((this._last_editor || from), function(id){\n\t\t\t\tif (this._get_editor_type(id))\n\t\t\t\t\treturn true;\n\t\t\t\treturn false;\n\t\t\t}, next);\n\n\t\t\tif (this.editStop()){\t//if we was able to close previous editor\n\t\t\t\tif (editor_next){\t//and there is a new target\n\t\t\t\t\tthis.edit(editor_next);\t//init new editor\n\t\t\t\t\tthis._after_edit_next(editor_next);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t},\n\t//stab, used in datatable\n\t_after_edit_next:function(){},\n\t_find_cell_next:function(start, check, direction){\n\t\tvar row = this.getIndexById(start.id);\n\t\tvar order = this.data.order;\n\t\t\n\t\tif (direction){\n\t\t\tfor (let i=row+1; i=0; i--){\n\t\t\t\tif (check.call(this, order[i]))\n\t\t\t\t\treturn order[i];\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t},\n\t_get_new_value(editor){\n\t\treturn editor.getValue();\n\t},\n\t_set_new_value:function(editor, new_value, copy){\n\t\tvar item = copy ? {} : this.getItem(editor.id);\n\t\titem[this._settings.editValue||\"value\"] = new_value;\n\t\treturn item;\n\t}\n};\n\nexport default EditAbility;","\n\nconst GroupMethods = {\n\tsum:function(property, data){\n\t\tdata = data || this;\n\t\tvar summ = 0;\n\t\tfor (var i = 0; i < data.length; i++){\n\t\t\tconst num = parseFloat(property(data[i]), 10);\n\t\t\tif (!isNaN(num))\n\t\t\t\tsumm+=num;\n\t\t}\n\n\t\treturn summ;\n\t},\n\tmin:function(property, data){\n\t\tdata = data || this;\n\t\tvar min = Infinity;\n\n\n\t\tfor (var i = 0; i < data.length; i++){\n\t\t\tconst num = parseFloat(property(data[i]), 10);\n\t\t\tif (isNaN(num)) continue;\n\t\t\tif (num < min) min = num;\n\t\t}\n\n\t\treturn min === Infinity ? 0 : min*1;\n\t},\n\tmax:function(property, data){\n\t\tdata = data || this;\n\t\tvar max = -Infinity;\n\n\t\tfor (var i = 0; i < data.length; i++){\n\t\t\tconst num = parseFloat(property(data[i]), 10);\n\t\t\tif (isNaN(num)) continue;\n\t\t\tif (num > max) max = num;\n\t\t}\n\n\t\treturn max === -Infinity ? 0 : max*1;\n\t},\n\tcount:function(property, data){\n\t\tvar count = 0;\n\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\tvar some = property(data[i]);\n\t\t\tif (some !== null && typeof some !== \"undefined\")\n\t\t\t\tcount++;\n\t\t}\n\t\treturn count;\n\t},\n\tany:function(property, data){\n\t\treturn property(data[0]);\n\t},\n\tstring:function(property){\n\t\treturn property.$name;\n\t}\n};\n\nexport default GroupMethods;","import {preventEvent} from \"../webix/html\";\nimport {_power_array} from \"../webix/helpers\";\nimport {_event} from \"../webix/htmlevents\";\nimport UIManager from \"./uimanager\";\n\n\n/*aria-style handling for options of multiple-value controls (radio, segmented, tabbar)*/\n\nconst HTMLOptions = {\n\t$init: function(){\n\t\tthis.$ready.push(()=>{\n\t\t\tif(!this.customRadio_setter || this.config.customRadio)\n\t\t\t\t_event( this.$view, \"keydown\", this._moveSelection, {bind:this});\n\t\t});\n\t},\n\t_focus: function(){\n\t\tif(!UIManager.canFocus(this))\n\t\t\treturn false;\n\n\t\tconst input = this._getInputNode();\n\t\tif (input)\n\t\t\tfor (let i=0; i34 && code <41){\n\t\t\tconst inp = this._getInputNode();\n\t\t\tlet index = false;\n\n\t\t\tif (!inp.length) return;\n\t\t\tpreventEvent(e);\n\n\t\t\tconst dir = (code === 37 || code === 38 || code === 35)?-1:1;\n\t\t\tif (code === 35) index = inp.length-1;\n\t\t\telse if (code === 36 ) index = 0;\n\t\t\telse {\n\t\t\t\tfor (let i=0; i= inp.length) i = 0;\n\t\t\t\t\tif (i < 0) i = inp.length-1;\n\n\t\t\t\t\tif (!inp[i].getAttribute(\"webix_disabled\")){\n\t\t\t\t\t\tconst id = inp[i].getAttribute(/*@attr*/\"button_id\");\n\n\t\t\t\t\t\tthis.setValue(id, \"user\");\n\t\t\t\t\t\tinp[i].focus();\n\t\t\t\t\t\ti = \"success\";\n\t\t\t\t\t}\n\t\t\t\t\telse i += dir;\n\n\t\t\t\t} while(i !== \"success\" && i !== index);\n\t\t\t}\n\t\t}\n\t},\n\t_get_tooltip_data: function(t,e){\n\t\tlet id,\n\t\t\tnode = e.target;\n\t\twhile (node && !node.webix_tooltip){\n\t\t\tid = node.getAttribute(\"webix_t_id\");\n\t\t\tif (id)\n\t\t\t\treturn this.getOption(id);\n\t\t\tnode = node.parentNode;\n\t\t}\n\t\treturn null;\n\t},\n\toptionIndex: function(id){\n\t\tconst options = this._settings.options;\n\t\tfor (let i=0; i=0; i--)\n\t\t\t\tif (!options[i].hidden)\n\t\t\t\t\treturn this.setValue(options[i].id,\"auto\");\n\t\t}\n\n\t\t//nothing found\t\t\n\t\tthis.setValue(\"\",\"auto\");\n\t},\n\t_getFirstActive(first){\n\t\tconst options = this._settings.options;\n\n\t\tif (options.length){\n\t\t\tfor (let i=0; i\");\n\t\tthis._areas.push({index: userdata, points:coords, itemId: id});\n\n\t},\n\taddSector:function(id, alpha0, alpha1, x, y, r, ky, userdata, dr, height){\n\t\tlet points = [];\n\n\t\tif(dr)\n\t\t\tpoints = points.concat(this._getArcPoints(x, y, dr, alpha1, alpha0, ky, -1));\n\t\telse{\n\t\t\tpoints.push(x);\n\t\t\tpoints.push(Math.floor(y));\n\t\t}\n\t\tif(!height)\n\t\t\tpoints = points.concat(this._getArcPoints(x, y, r, alpha0, alpha1, ky));\n\t\telse{\n\t\t\tif(alpha0 < 0 && alpha1 >= 0){\n\t\t\t\tpoints = points.concat(this._getArcPoints(x, y, r, alpha0, 0, ky));\n\t\t\t\tpoints = points.concat(this._getArcPoints(x, y + height, r, 0, alpha1, ky));\n\t\t\t\tpoints = points.concat(this._getPointByAngle(x, y, r, alpha1, ky));\n\t\t\t}\n\t\t\telse if(alpha0 < Math.PI && alpha1>=Math.PI){\n\t\t\t\tpoints = points.concat(this._getPointByAngle(x, y, r, alpha0, ky));\n\t\t\t\tpoints = points.concat(this._getArcPoints(x, y + height, r, alpha0, Math.PI, ky));\n\t\t\t\tpoints = points.concat(this._getArcPoints(x, y, r, Math.PI, alpha1, ky));\n\t\t\t}\n\t\t\telse{\n\t\t\t\tpoints = points.concat(this._getPointByAngle(x, y, r, alpha0, ky));\n\t\t\t\tpoints = points.concat(this._getArcPoints(x, y + height, r, alpha0, alpha1, ky));\n\t\t\t\tpoints = points.concat(this._getPointByAngle(x, y, r, alpha1, ky));\n\t\t\t}\n\t\t}\n\t\tpoints.push(points[0]);\n\t\tpoints.push(points[1]);\n\t\treturn this.addPoly(id, points, userdata);\n\t},\n\t_getArcPoints: function(x, y, r, a0, a1, ky, dir){\n\t\tlet points = [];\n\t\tdir = dir || 1;\n\n\t\tfor(let i = a0; (dir>0 && i < a1) || (dir<0 && i > a1); i += dir*Math.PI/18)\n\t\t\tpoints = points.concat(this._getPointByAngle(x, y, r, i, ky));\n\t\tpoints = points.concat(this._getPointByAngle(x, y, r, a1, ky));\n\t\treturn points;\n\t},\n\t_getPointByAngle: function(x, y, r, a, ky){\n\t\tconst point = [];\n\t\tpoint.push(Math.floor(x + r * Math.cos(a)));\n\t\tpoint.push(Math.floor(y + r * Math.sin(a)* ky));\n\t\treturn point;\n\t},\n\thide:function(obj, data, mode){\n\t\tif (obj.querySelectorAll){\n\t\t\tvar nodes = obj.querySelectorAll(\"area[userdata=\\\"\"+data+\"\\\"]\");\n\t\t\tfor (var i = 0; i < nodes.length; i++){\n\t\t\t\tvar nod = nodes[i];\n\t\t\t\tif (mode){\n\t\t\t\t\tif (nod.getAttribute(\"coords\")){\n\t\t\t\t\t\tnod.coordsdis = nod.getAttribute(\"coords\");\n\t\t\t\t\t\tnod.setAttribute(\"coords\", \"\");\n\t\t\t\t\t\tnod.coords = \"\";\n\t\t\t\t\t}\n\t\t\t\t} else if (!mode){\n\t\t\t\t\tif (nod.coordsdis){\n\t\t\t\t\t\tnod.setAttribute(\"coords\", nod.coordsdis);\n\t\t\t\t\t\tnod.coords = nod.coordsdis;\n\t\t\t\t\t\tnod.coordsdis = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnodes[i].style.display = mode?\"none\":\"\";\n\t\t\t}\n\t\t}\n\t},\n\trender:function(obj){\n\t\tconst d = create(\"DIV\");\n\t\td.style.cssText=\"position:absolute; width:100%; height:100%; top:0px; left:0px;\";\n\t\tobj.appendChild(d);\n\n\t\td.innerHTML=`\n\t\t\t${this._map.join(\"\\n\")}\n\t\t\t`;\n\n\t\tobj._htmlmap = d; //for clearing routine\n\n\t\tthis._map = [];\n\t}\n});\n\nexport default HtmlMap;","import {uid,isArray} from \"../webix/helpers\";\nimport {$$} from \"../ui/core\";\n\nimport i18n from \"../webix/i18n\";\nimport {use} from \"../services\";\n\nimport template from \"../webix/template\";\nimport editors from \"../webix/editors\";\n\n/*Data collection mapping logic */\n\nconst MapCollection = {\n\t$init:function(){\n\t\tthis.$ready.push(this._create_scheme_init);\n\t\tthis.attachEvent(\"onStructureUpdate\", this._create_scheme_init);\n\t\tthis.attachEvent(\"onStructureLoad\", function(){\n\t\t\tif(!this._scheme_init_order.length)\n\t\t\t\tthis._create_scheme_init();\n\t\t});\n\t},\n\t_create_scheme_init:function(){\n\t\tvar stack = this._scheme_init_order = [];\n\t\tvar config = this._settings;\n\n\t\tif (config.columns)\n\t\t\tthis._build_data_map(config.columns);\n\t\tif (this._settings.map)\n\t\t\tthis._process_field_map(config.map);\n\n\t\tif (stack.length){\n\t\t\tthis.data._scheme_init = function(obj){\n\t\t\t\tfor (var i=0; i a[target];\n\t\t} else {\n\t\t\tif (source.indexOf(\"#\") === -1 && source.indexOf(\"{\") === -1){\n\t\t\t\tsource = \"#\"+source+\"#\";\n\t\t\t}\n\t\t\tgetSource = template(source);\n\t\t}\n\n\t\tif (map.indexOf(\"(date)\")===0){\n\t\t\tif (extra && !extra.format) extra.format = i18n.dateFormatStr;\n\n\t\t\treturn function(obj){\n\t\t\t\tconst dateStr = (getSource(obj) || \"\").toString();\n\t\t\t\tobj[target] = i18n.parseFormatDate(dateStr);\n\t\t\t};\n\t\t} else if (map.indexOf(\"(number)\")===0){\n\t\t\treturn function(obj){\n\t\t\t\tobj[target] = getSource(obj)*1;\n\t\t\t};\n\t\t} else {\n\t\t\treturn function(obj){\n\t\t\t\tobj[target] = getSource(obj) || \"\";\n\t\t\t};\n\t\t}\n\t},\n\t_build_data_map:function(columns){ //for datatable\n\t\tfor (let i=0; i {\n\t\t\t\t\tif(this.refreshFilter)\n\t\t\t\t\t\tthis.refreshFilter(config.columnId);\n\t\t\t\t});\n\t\t\t\tthis.attachEvent(\"onDestruct\", function(){\n\t\t\t\t\tif (!options.$destructed) options.data.detachEvent(id);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t},\n\t_bind_collection:function(options, column){\n\t\tif (column){\n\t\t\tdelete column.options;\n\t\t\tcolumn.collection = options;\n\t\t\tcolumn.template = column.template || this._bind_template(column.optionslist);\n\t\t\tlet id = options.data.attachEvent(\"onStoreUpdated\", () => {\n\t\t\t\tthis.refresh();\n\t\t\t\tif(this.refreshFilter)\n\t\t\t\t\tthis.refreshFilter(column.id);\n\t\t\t});\n\t\t\tthis.attachEvent(\"onDestruct\", function(){\n\t\t\t\tif (!options.$destructed) options.data.detachEvent(id);\n\t\t\t});\n\t\t}\n\t},\n\t_bind_template:function(multi){\n\t\tif (multi) {\n\t\t\tconst separator = typeof multi === \"string\" ? multi : \",\";\n\t\t\treturn function(obj, common, value, column){\n\t\t\t\tif (!value) return \"\";\n\n\t\t\t\tconst ids = value.toString().split(separator);\n\t\t\t\tfor (let i = 0; i < ids.length; i++){\n\t\t\t\t\tconst data = column.collection.data.pull[ids[i]];\n\t\t\t\t\tids[i] = data ? (data.value || \"\") : \"\";\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn ids.join(\", \");\n\t\t\t};\n\t\t} else {\n\t\t\treturn function(obj, common, value, column){\n\t\t\t\tconst data = column.collection.data.pull[value];\n\t\t\t\tif (data && (data.value || data.value === 0))\n\t\t\t\t\treturn data.value;\n\t\t\t\treturn \"\";\n\t\t\t};\n\t\t}\n\t},\n\t_map_editor: function(id, config){\n\t\tconst editor = editors[config.editor];\n\t\tif(editor && editor.masterFormat)\n\t\t\tconfig.format = editor.masterFormat;\n\t}\n};\n\nexport default MapCollection;","import {_getClassName, locate} from \"../webix/html\";\nimport UIManager from \"../core/uimanager\";\nimport {extend, delay, toFunctor} from \"../webix/helpers\";\nimport {_event} from \"../webix/htmlevents\";\nimport env from \"../webix/env\";\n\n\nconst MouseEvents={\n\t$init: function(config){\n\t\tconfig = config || {};\n\n\t\tthis._clickstamp = 0;\n\t\tthis._dbl_sensetive = env.touch ? 500 : 300;\n\t\tthis._item_clicked = null;\n\n\t\tthis._mouse_action_extend(config.onClick, \"on_click\");\n\t\tthis._mouse_action_extend(config.onContext, \"on_context\");\n\t\tthis._mouse_action_extend(config.onDblClick, \"on_dblclick\");\n\t\tthis._mouse_action_extend(config.onMouseMove, \"on_mouse_move\");\n\n\t\t//attach dom events if related collection is defined\n\t\tif (this.on_click)\n\t\t\t_event(this._contentobj, \"click\", this._onClick, {bind:this});\n\n\t\tif (this.on_context)\n\t\t\t_event(this._contentobj, \"contextmenu\", this._onContext, {bind:this});\n\n\t\tif (this.on_mouse_move)\n\t\t\tthis._enable_mouse_move();\n\t},\n\n\t_enable_mouse_move:function(){\n\t\tif (!this._mouse_move_enabled){\n\t\t\tthis.on_mouse_move = this.on_mouse_move || {};\n\t\t\t_event(this._contentobj,\"mousemove\",this._onMouse,{bind:this});\n\t\t\t_event(this._contentobj,\"mouseout\",this._onMouse,{bind:this});\n\t\t\tthis._mouse_move_enabled = 1;\n\t\t\tthis.attachEvent(\"onDestruct\", function(){\n\t\t\t\tif (this._mouse_move_timer)\n\t\t\t\t\twindow.clearTimeout(this._mouse_move_timer);\n\t\t\t});\n\t\t}\n\n\t},\n\n\t_mouse_action_extend:function(config, key){\n\t\tif (config){\n\t\t\tconst now = this[key];\n\t\t\tconst step = now ? extend({}, now) : {};\n\t\t\tthis[key] = extend(step, config);\n\t\t}\n\t},\n\n\t//inner onclick object handler\n\t_onClick: function(e){\n\t\tif(!this.isEnabled())\n\t\t\treturn false;\n\n\t\tUIManager._focus_action(this);\n\n\t\tif(this.on_dblclick && this.locate){\n\t\t\tif(this._clickHandler && this._item_clicked+\"\" == this.locate(e)+\"\"){\n\t\t\t\tclearTimeout(this._clickHandler);\n\t\t\t\tthis._clickHandler = null;\n\t\t\t\treturn this._onDblClick(e);\n\t\t\t}\n\n\t\t\tthis._item_clicked = this.locate(e);\n\t\t\tthis._clickHandler = delay(()=> {\n\t\t\t\tthis._clickHandler = null;\n\t\t\t\treturn this._mouseEvent(e, this.on_single_click, \"ItemSingleClick\");\n\t\t\t}, null, [e], this._dbl_sensetive);\n\t\t}\n\n\t\treturn this._mouseEvent(e, this.on_click, \"ItemClick\");\n\t},\n\t//inner ondblclick object handler\n\t_onDblClick: function(e) {\n\t\treturn this._mouseEvent(e,this.on_dblclick,\"ItemDblClick\");\n\t},\n\t//process oncontextmenu events\n\t_onContext: function(e) {\n\t\tthis._mouseEvent(e, this.on_context, \"BeforeContextMenu\", \"AfterContextMenu\");\n\t},\n\t/*\n\t\tevent throttler - ignore events which occurs too fast\n\t\tduring mouse moving there are a lot of event firing - we need no so much\n\t\talso, mouseout can fire when moving inside the same html container - we need to ignore such fake calls\n\t*/\n\t_onMouse:function(e){\n\t\tif (this.$destructed) return;\n\t\tif (document.createEventObject)\t//make a copy of event, will be used in timed call\n\t\t\te = document.createEventObject(event);\n\n\t\tif (this._mouse_move_timer)\t//clear old event timer\n\t\t\twindow.clearTimeout(this._mouse_move_timer);\n\n\t\t//this event just inform about moving operation, we don't care about details\n\t\tthis.callEvent(\"onMouseMoving\",[e]);\n\t\t//set new event timer\n\t\tthis._mouse_move_timer = delay(function(e){\n\t\t\t//called only when we have at least 100ms after previous event\n\t\t\tif (e.type == \"mousemove\")\n\t\t\t\tthis._onMouseMove(e);\n\t\t\telse\n\t\t\t\tthis._onMouseOut(e);\n\t\t}, this, [e], (this._settings.mouseEventDelay||500));\n\t},\n\n\t//inner mousemove object handler\n\t_onMouseMove: function(e) {\n\t\tif (!this._mouseEvent(e,this.on_mouse_move,\"MouseMove\"))\n\t\t\tthis._onMouseOut(e);\n\t},\n\t//inner mouseout object handler\n\t_onMouseOut: function(e) {\n\t\tthis.callEvent(\"onMouseOut\",[e]);\n\t},\n\t//common logic for click and dbl-click processing\n\t_mouseEvent:function(e, hash, name, pair){\n\t\tif (e.processed || !this._viewobj) return;\n\t\te.processed = true;\n\n\t\tlet trg = e.target;\n\n\t\tlet css = \"\";\n\t\tlet id = null;\n\t\tlet found = false;\n\t\t//loop through all parents\n\t\t//we need to check for this._viewobj as some handler can destroy the view\n\t\twhile (trg && trg.parentNode && this._viewobj && trg != this._viewobj.parentNode){\n\t\t\tif (!found && trg.getAttribute){ //if element with ID mark is not detected yet\n\t\t\t\tid = trg.getAttribute(this._id); //check id of current one\n\t\t\t\tif (id){\n\t\t\t\t\t// prevent clicking on disabled items\n\t\t\t\t\tif (trg.getAttribute(\"webix_disabled\")){\n\t\t\t\t\t\tthis._item_clicked = null;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._item_clicked = id;\n\t\t\t\t\tif (this.callEvent){\n\t\t\t\t\t\t//it will be triggered only for first detected ID, in case of nested elements\n\t\t\t\t\t\tif (!this.callEvent(\"on\"+name,[id,e,trg])) return;\n\t\t\t\t\t\tif (pair) this.callEvent(\"on\"+pair,[id,e,trg]);\n\t\t\t\t\t}\n\t\t\t\t\t//set found flag\n\t\t\t\t\tfound = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcss=_getClassName(trg);\n\t\t\t//check if pre-defined reaction for element's css name exists\n\t\t\tif (hash && css){\n\t\t\t\tcss = css.toString().split(\" \");\n\t\t\t\tfor (let i = 0; i < css.length; i++){\n\t\t\t\t\tif (hash[css[i]]){\n\t\t\t\t\t\tconst functor = toFunctor(hash[css[i]], this.$scope);\n\t\t\t\t\t\tconst res = functor.call(this,e,id||locate(e, this._id),trg);\n\t\t\t\t\t\tif(res === false)\n\t\t\t\t\t\t\treturn found;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\ttrg = trg.parentNode;\n\t\t}\n\t\treturn found; //returns true if item was located and event was triggered\n\t}\n};\n\nexport default MouseEvents;\n","import {create} from \"../webix/html\";\nimport {delay} from \"../webix/helpers\";\nimport env from \"../webix/env\";\nimport {_event} from \"../webix/htmlevents\";\n\nimport CustomScroll from \"../core/customscroll\";\n\nconst Scrollable = {\n\t$init:function(config){\n\t\t//do not spam unwanted scroll containers for templates \n\t\tif (config && !config.scroll && this._one_time_scroll) \n\t\t\treturn (this._dataobj = (this._dataobj||this._contentobj));\n\n\t\t(this._dataobj||this._contentobj).appendChild(create(\"DIV\",{ \"class\" : \"webix_scroll_cont\" },\"\"));\n\t\tthis._dataobj = (this._dataobj||this._contentobj).firstChild;\n\n\t\tif (this.callEvent && !this.$hasYScroll)\n\t\t\t_event(this._viewobj, \"scroll\", function(){\n\t\t\t\tdelay(function(){\n\t\t\t\t\tthis.callEvent(\"onAfterScroll\", []);\n\t\t\t\t}, this);\n\t\t\t}, { bind:this });\n\t},\n\tscroll_setter:function(value){\n\t\tif (!value) return false;\n\n\t\tconst auto = value === \"auto\";\n\t\tconst marker = (value==\"x\"?\"x\":(value==\"xy\"?\"xy\":(auto?\"xy\":\"y\")));\n\n\t\tif (env.$customScroll)\n\t\t\tCustomScroll.enable(this, marker);\n\n\t\tconst style = this._dataobj.parentNode.style;\n\t\tif (auto && !env.$customScroll){\n\t\t\tstyle.overflowX = style.overflowY = \"auto\";\n\t\t} else {\n\t\t\tif (marker.indexOf(\"x\") !== -1){\n\t\t\t\tthis._scroll_x = true;\n\t\t\t\tstyle.overflowX = \"scroll\";\n\t\t\t}\n\t\t\tif (marker.indexOf(\"y\") !== -1){\n\t\t\t\tthis._scroll_y = true;\n\t\t\t\tstyle.overflowY = \"scroll\";\n\t\t\t}\n\t\t}\n\t\treturn marker;\n\t},\n\t_onoff_scroll:function(mode, dir){\n\t\tif (!!this._settings.scroll == !!mode) return;\n\n\t\tif (!env.$customScroll){\n\t\t\tvar style = this._dataobj.parentNode.style;\n\t\t\tstyle[dir === \"x\" ? \"overflowX\" : \"overflowY\"] = mode ? \"auto\" : \"hidden\";\n\t\t}\n\n\t\tif (dir === \"x\"){\n\t\t\tthis._scroll_x = mode;\n\t\t} else {\n\t\t\tthis._scroll_y = mode;\n\t\t}\n\t\tthis._settings.scroll = mode?dir:false;\n\t},\n\tgetScrollState:function(){\n\t\treturn { x: this._dataobj.parentNode.scrollLeft, y: this._dataobj.parentNode.scrollTop };\n\t},\n\tscrollTo:function(x,y){\n\t\tthis._dataobj.parentNode.scrollLeft = x;\n\t\tthis._dataobj.parentNode.scrollTop = y;\n\t}\n};\n\nexport default Scrollable;","import {createCss} from \"../../webix/html\";\nimport {extend, copy} from \"../../webix/helpers\";\n\nimport SVG from \"./svg\";\n\nvar defaults = {\n\tpaddingX: 6,\n\tpaddingY: 6,\n\tradius: 2,\n\tminHeight: 4,\n\teventRadius: 8\n};\nfunction Line(config){\n\tthis.config = extend(copy(defaults),config||{},true);\n}\n\nLine.prototype.draw = function(data, width, height){\n\tvar points = this.getPoints(data, width, height);\n\tvar config = this.config;\n\tvar renderer = SVG;\n\tvar styles = config.color?this._applyColor(renderer,config.color):null;\n\t// draw line\n\tvar path = renderer.definePath(this._getLinePoints(points));\n\tvar graph = renderer.group(renderer.getPath(path,\"webix_sparklines_line\"+(styles?\" \"+styles.line:\"\")));\n\t// draw items\n\tgraph += this._drawItems(renderer, points, config.radius, \"webix_sparklines_item\"+(styles?\" \"+styles.item:\"\"));\n\t// draw event items\n\tvar eventRadius = Math.min(data.length?(width-2*(config.paddingX||0))/data.length:0,config.eventRadius);\n\tgraph += this._drawEventItems(renderer, points, eventRadius);\n\treturn renderer.draw(graph, width, height, \"webix_sparklines_line_chart\"+(config.css?\" \"+config.css:\"\"));\n};\nLine.prototype._applyColor = function(renderer,color){\n\tvar config = {\"line\":{},\"item\":{}},\n\t\tmap = renderer.styleMap;\n\tif(color){\n\t\tconfig.line[map.lineColor] = color;\n\t\tconfig.item[map.color] = color;\n\t\tfor(var name in config)\n\t\t\tconfig[name] = createCss(config[name]);\n\t}\n\treturn config;\n};\nLine.prototype._drawItems = function(renderer,points,radius,css,attrs){\n\tvar items = [];\n\tfor(var i = 0; i< points.length; i++){\n\t\titems.push(renderer.getCircle(points[i], radius, css,attrs));\n\t}\n\treturn renderer.group(items.join(\"\"));\n};\nLine.prototype._drawEventItems = function(renderer,points,radius){\n\tvar items = [];\n\tfor(var i = 0; i< points.length; i++){\n\t\titems.push(renderer.getCircle(points[i], radius, \"webix_sparklines_event_area\", {webix_area:i}));\n\t}\n\treturn renderer.group(items.join(\"\"));\n};\n\nLine.prototype._getLinePoints = function(points){\n\tvar i, type, result =[];\n\tfor( i =0; i< points.length; i++){\n\t\ttype = i?\"L\":\"M\";\n\t\tresult.push([type,points[i]]);\n\t}\n\treturn result;\n};\nLine.prototype.getPoints = function(data, width, height) {\n\tvar config = this.config;\n\tvar minValue = Math.min.apply(null,data);\n\tif (typeof config.origin !== \"undefined\")\n\t\tminValue = Math.min(config.origin, minValue);\n\n\tvar maxValue = Math.max.apply(null,data);\n\tvar result = [];\n\tvar x = config.paddingX||0;\n\tvar y = config.paddingY||0;\n\twidth = (width||100)-x*2;\n\tvar minHeight = config.minHeight||0;\n\theight = (height||100)-y*2;\n\tif(data.length){\n\t\tif(data.length==1)\n\t\t\tresult.push({x: width/2+x, y: height/2+x});\n\t\telse{\n\t\t\tvar unitX = width/(data.length-1);\n\t\t\tvar yNum = config.scale || (maxValue - minValue);\n\t\t\tvar unitY = (height- minHeight)/(yNum?yNum:1);\n\t\t\tif(!yNum)\n\t\t\t\theight /= 2;\n\t\t\tfor(var i=0; i < data.length; i++){\n\t\t\t\tresult.push({x: Math.ceil(unitX*i)+x, y: height-Math.ceil(unitY*(data[i]-minValue))+y-minHeight});\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n};\n\nexport default Line;","import {extend, copy} from \"../../webix/helpers\";\n\nimport SVG from \"./svg\";\nimport BaseLine from \"./line\";\nimport Area from \"./area\";\n\nconst defaults = {\n\tpadding: 6,\n\tradius: 2,\n\teventRadius: 8\n};\n\nfunction Radar(config){\n\tthis.config = extend(copy(defaults),config||{},true);\n}\n\nRadar.prototype.draw = function(data, width, height){\n\tconst line = BaseLine.prototype;\n\tconst area = Area.prototype;\n\n\tconst config = this.config;\n\tconst renderer = SVG;\n\tconst x0 = width/2;\n\tconst y0 = height/2;\n\n\tconst radius = Math.min(x0,y0) - config.padding;\n\n\tlet origin = \"\";\n\tconst points = [];\n\tconst originPoints = [];\n\tconst ratios = this._getRatios(data.length);\n\n\tdata = data.map(v => isNaN(v) ? 0 : v);\n\tconst max = Math.max(...data);\n\tlet min = Math.min(...data);\n\tif(min > 0)\n\t\tmin = 0;\n\n\tfor (let i = 0; i < data.length; i++) {\n\t\tconst angle = -Math.PI/2 +ratios[i];\n\n\t\toriginPoints.push(this._getPositionByAngle(angle, x0, y0, radius));\n\t\tconst x1 = originPoints[i].x;\n\t\tconst y1 = originPoints[i].y;\n\n\t\torigin += renderer.getLine({x:x0, y:y0},{x: x1, y: y1},\"webix_sparklines_origin\");\n\n\t\tlet x, y;\n\t\tif(data[i] == min){\n\t\t\tx = x0; y = y0;\n\t\t}\n\t\telse if(data[i] == max){\n\t\t\tx = x1; y = y1;\n\t\t}\n\t\telse{\n\t\t\tconst ratio = Math.abs(data[i]-min)/Math.abs(max - data[i]);\n\t\t\tx = (x0 + x1 * ratio) / (1 + ratio);\n\t\t\ty = (y0 + y1 * ratio) / (1 + ratio);\n\t\t}\n\n\t\tpoints.push({x, y});\n\t}\n\n\tconst styles = config.color ? area._applyColor(renderer, config.color) : null;\n\tconst originPath = renderer.definePath(line._getLinePoints(originPoints), true);\n\tconst path = renderer.definePath(line._getLinePoints(points), true);\n\n\tconst graph =\n\t\trenderer.group(origin + renderer.getPath(originPath, \"webix_sparklines_origin\")) +\n\t\trenderer.group(renderer.getPath(path, \"webix_sparklines_area\"+(styles?\" \"+styles.area:\"\"))) +\n\t\trenderer.group(renderer.getPath(path, \"webix_sparklines_line\"+(styles?\" \"+styles.line:\"\"))) +\n\t\tline._drawItems(renderer, points, config.radius, \"webix_sparklines_item\"+(styles?\" \"+styles.item:\"\")) +\n\t\tline._drawEventItems(renderer, points, config.eventRadius);\n\n\treturn renderer.draw(graph, width, height, \"webix_sparklines_radar_chart\"+(config.css?\" \"+config.css:\"\"));\n};\n\nRadar.prototype._getPositionByAngle = function(a,x,y,r){\n\ta *= (-1);\n\tx = x+Math.cos(a)*r;\n\ty = y-Math.sin(a)*r;\n\treturn {x,y};\n};\n\nRadar.prototype._getRatios = function(count){\n\tconst ratios = [];\n\tfor(let i = 0; i < count; i++){\n\t\tratios[i] = Math.PI*2*(i/count);\n\t}\n\treturn ratios;\n};\n\nexport default Radar;","import {assert} from \"../webix/debug\";\n\n\nconst TreeAPI = {\n\topen: function(id, show) {\n\t\tif (!id) return;\n\t\t//ignore open for leaf items\n\t\tvar item = this.getItem(id);\n\t\tassert(item,\"Incorrect ID to open: \"+id);\n\n\t\tif (!item.$count || item.open) return;\n\n\t\tif (this.callEvent(\"onBeforeOpen\",[id])){\n\t\t\titem.open=true;\n\t\t\tthis.data.callEvent(\"onStoreUpdated\",[id, 0, \"branch\"]);\n\t\t\tthis.callEvent(\"onAfterOpen\",[id]);\n\t\t}\n\n\t\tif (show && id != \"0\")\n\t\t\tthis.open(this.getParentId(id), show);\n\t},\n\tclose: function(id) {\n\t\tif (!id) return;\n\t\tvar item = this.getItem(id);\n\t\tif (!item.open) return;\n\n\t\tif (this.callEvent(\"onBeforeClose\",[id])){\n\t\t\titem.open=false;\n\t\t\tthis.data.callEvent(\"onStoreUpdated\",[id, 0, \"branch\"]);\n\t\t\tthis.callEvent(\"onAfterClose\",[id]);\n\t\t}\n\t},\n\topenAll: function(id){\n\t\tthis.data.eachSubItem((id||0), function(obj, branch){\n\t\t\tif (branch)\n\t\t\t\tobj.open = true;\n\t\t});\n\t\tthis.data.refresh();\n\t},\n\tcloseAll: function(id){\n\t\tthis.data.eachSubItem((id||0), function(obj, branch){\n\t\t\tif (branch)\n\t\t\t\tobj.open = false;\n\t\t});\n\t\tthis.data.refresh();\n\t},\n\t_tree_check_uncheck:function(id,mode,e){\n\t\tif(this._settings.threeState)\n\t\t\treturn this._tree_check_uncheck_3(id,(mode !== null?mode:\"\"));\n\n\t\tvar value,\n\t\t\titem = this.getItem(id),\n\t\t\ttrg = (e?e.target:null);\n\n\t\t//read actual value from HTML tag when possible\n\t\t//as it can be affected by dbl-clicks\n\t\tif(trg && trg.type == \"checkbox\")\n\t\t\tvalue = trg.checked?true:false;\n\t\telse\n\t\t\tvalue = (mode !== null?mode:!item.checked);\n\n\t\titem.checked = value;\n\t\tthis.callEvent(\"onItemCheck\", [id, item.checked, e]);\n\t},\n\tisBranchOpen:function(search_id){\n\t\tif (search_id == \"0\") return true;\n\n\t\tvar item = this.getItem(search_id);\n\t\tif (item.open)\n\t\t\treturn this.isBranchOpen(item.$parent);\n\t\treturn false;\n\t},\n\tgetOpenItems: function() {\n\t\tvar open = [];\n\t\tfor (var id in this.data.branch) {\n\t\t\tif (this.exists(id) && this.getItem(id).open)\n\t\t\t\topen.push(id);\n\t\t}\n\t\treturn open;\n\t},\n\tgetState: function(){\n\t\treturn {\n\t\t\topen: this.getOpenItems(),\n\t\t\tselect: this.getSelectedId(true)\n\t\t};\n\t},\n\t_repeat_set_state:function(tree, open){\n\t\tvar event = this.data.attachEvent(\"onStoreLoad\", function(){\n\t\t\ttree.setState.call(tree,open);\n\t\t\ttree.data.detachEvent(event);\n\t\t\ttree = null;\n\t\t});\n\t},\n\tsetState: function(state){\n\t\tif (state.open){\n\t\t\tthis.closeAll();\t\n\t\t\tvar open = state.open;\n\t\t\tfor (let i = 0; i < open.length; i++){\n\t\t\t\tvar item = this.getItem(open[i]);\n\t\t\t\tif (item && item.$count){\n\t\t\t\t\titem.open=true;\n\t\t\t\t\t//dynamic loading\n\t\t\t\t\tif (item.$count == -1){\n\t\t\t\t\t\t//call the same method after data loading\n\t\t\t\t\t\tthis._repeat_set_state(this, state);\n\t\t\t\t\t\tthis.refresh();\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t\t//end processing\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.refresh();\n\t\t}\n\n\n\t\tif (state.select && this.select){\t\t\t\n\t\t\tvar select = state.select;\n\t\t\tthis.unselect();\n\t\t\tfor (let i = 0; i < select.length; i++)\n\t\t\t\tif (this.exists(select[i]))\n\t\t\t\t\tthis.select(select[i], true);\n\t\t}\n\n\t\treturn 1;\n\t}\n};\n\nexport default TreeAPI;","import {insertBefore, remove, create} from \"../webix/html\";\nimport {assert} from \"../webix/debug\";\n\n\nconst TreeRenderStack ={\n\t$init:function(){\n\t\tassert(this.render,\"TreeRenderStack :: Object must use RenderStack first\");\n\t},\n\t_toHTMLItem:function(obj){\n\t\tvar mark = this.data._marks[obj.id];\n\t\tthis.callEvent(\"onItemRender\",[obj]);\n\t\treturn 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();\n\t},\n\t_toHTMLItemObject:function(obj){\n\t\tthis._html.innerHTML = this._toHTMLItem(obj);\n\t\treturn this._html.firstChild;\n\t},\n\t//convert single item to HTML text (templating)\n\t_toHTML:function(obj){\n\t\t//check if related template exist\n\t\tassert((!obj.$template || this.type[\"template\"+obj.$template]),\"RenderStack :: Unknown template: \"+obj.$template);\n\t\tvar html=\"\";\n\n\t\treturn html;\n\t},\n\t_toHTMLLevel:function(id){\n\t\tvar html = \"\";\n\t\tvar leaves = this.data.branch[id];\n\t\tif (leaves){\n\t\t\thtml+=\"\";\n\t\t}\n\t\treturn html;\n\t},\n\t//return true when some actual rendering done\n\trender:function(id,data,type){\n\t\tTreeRenderStack._obj = this;\t//can be used from complex render\n\n\t\tif (!this.isVisible(this._settings.id) || this.$blockRender)\n\t\t\treturn;\n\n\t\tif (id){\n\t\t\tvar cont, node;\n\t\t\tvar item = this.getItem(id);\n\t\t\tif (type!=\"add\"){\n\t\t\t\tcont = this.getItemNode(id);\n\t\t\t\tif (!cont) return;\n\t\t\t}\n\t\t\t\n\t\t\tswitch(type){\n\t\t\t\tcase \"branch\":\n\t\t\t\t\tvar branch = cont.parentNode;\n\t\t\t\t\tnode = this._toHTMLObject(item);\n\t\t\t\t\t\n\t\t\t\t\tinsertBefore(node, branch); \n\t\t\t\t\tremove(branch);\n\t\t\t\t\tthis._htmlmap = null;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"paint\":\n\t\t\t\tcase \"update\":\n\t\t\t\t\tnode = this._htmlmap[id] = this._toHTMLItemObject(item);\n\t\t\t\t\tinsertBefore(node, cont); \n\t\t\t\t\tremove(cont);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"delete\":\n\t\t\t\t\t//deleting not item , but full branch\n\t\t\t\t\tremove(cont.parentNode);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"add\":\n\t\t\t\t\tvar parent;\n\t\t\t\t\t//we want process both empty value and 0 as string\n\t\t\t\t\t//jshint -W041:true\n\t\t\t\t\tif (item.$parent == 0){\n\t\t\t\t\t\tparent = this._dataobj.firstChild;\n\t\t\t\t\t} else if(this.getItem(item.$parent).open){\n\t\t\t\t\t\tparent = this.getItemNode(item.$parent);\n\t\t\t\t\t\tif (parent){\n\t\t\t\t\t\t\t//when item created by the script, it will miss the container for child notes\n\t\t\t\t\t\t\t//create it on demand\n\t\t\t\t\t\t\tif (!parent.nextSibling){\n\t\t\t\t\t\t\t\tvar leafs = create(\"DIV\", { \"class\" : \"webix_tree_leaves\" },\"\");\n\t\t\t\t\t\t\t\tparent.parentNode.appendChild(leafs);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tparent = parent.nextSibling;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (parent){\n\t\t\t\t\t\tvar next = this.data.getNextSiblingId(id);\n\t\t\t\t\t\tnext = this.getItemNode(next);\n\t\t\t\t\t\tif (next)\n\t\t\t\t\t\t\tnext = next.parentNode;\n\n\t\t\t\t\t\tnode = this._toHTMLObject(item);\n\t\t\t\t\t\tthis._htmlmap[id] = node.firstChild;\n\t\t\t\t\t\tinsertBefore(node, next, parent);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthis.callEvent(\"onPartialRender\", [id,data,type]);\n\t\t} else {\n\t\t\t//full reset\n\t\t\tif (this.callEvent(\"onBeforeRender\",[this.data])){\n\t\t\t\t//will be used for lines management\n\t\t\t\tthis.type._tree_branch_render_state = [];\n\t\t\t\t//getTopRange - returns all elements on top level\n\t\t\t\tthis._dataobj.innerHTML = this._toHTMLLevel(0);\n\t\t\t\t\t\n\t\t\t\tthis._htmlmap = null; //clear map, it will be filled at first getItemNode\n\t\t\t\tthis.callEvent(\"onAfterRender\",[]);\n\t\t\t}\n\t\t}\n\n\t\t//clear after usage\n\t\tthis.type._tree_branch_render_state = 0;\n\t\tTreeRenderStack._obj = null;\n\t\treturn true;\n\t},\n\tgetItemNode:function(search_id){\n\t\tif (this._htmlmap)\n\t\t\treturn this._htmlmap[search_id];\n\t\t\t\n\t\t//fill map if it doesn't created yet\n\t\tthis._htmlmap={};\n\t\t\n\t\tvar t = this._dataobj.getElementsByTagName(\"DIV\");\n\t\tfor (var i=0; i < t.length; i++){\n\t\t\tvar id = t[i].getAttribute(this._id); //get item's\n\t\t\tif (id) \n\t\t\t\tthis._htmlmap[id]=t[i];\n\t\t}\n\t\t//call locator again, when map is filled\n\t\treturn this.getItemNode(search_id);\n\t},\n\t_branch_render_supported:1\n};\n\nexport default TreeRenderStack;","import {bind, extend, _to_array, copy, clone, isArray, uid, _power_array} from \"../webix/helpers\";\nimport {assert} from \"../webix/debug\";\nimport DataStore from \"../core/datastore\";\nimport DataDriver from \"../load/drivers/index\";\n\n\n// #include core/datastore.js\n// #include core/bind.js\n// #include core/treemove.js\n\nconst TreeStore = {\n\tname:\"TreeStore\",\n\t$init:function() {\n\t\tthis._filterMode={\n\t\t\t//level:1,\n\t\t\tshowSubItems:true\n\t\t};\n\t\tthis.branch = { 0:[] };\n\t\tthis.attachEvent(\"onParse\", function(driver){\n\t\t\tthis._set_child_scheme(driver.child);\n\t\t});\n\t\tthis.attachEvent(\"onClearAll\", bind(function(){\n\t\t\tthis._filter_branch = null;\n\t\t},this));\n\t},\n\tfilterMode_setter:function(mode){\n\t\treturn extend(this._filterMode, mode, true);\n\t},\n\t_filter_reset:function(preserve){\n\t\t//remove previous filtering , if any\n\t\tif (this._filter_branch && !preserve){\n\t\t\tthis.branch = this._filter_branch;\n\t\t\tthis.order = _to_array(copy(this.branch[0]));\n\t\t\tfor (var key in this.branch)\n\t\t\t\tif (key != \"0\")\t//exclude 0 - virtual root\n\t\t\t\t\tthis.getItem(key).$count = this.branch[key].length;\n\t\t\tdelete this._filter_branch;\n\t\t}\n\t},\n\t_filter_core:function(filter, value, preserve, filterMode){\n\t\t//for tree we have few filtering options\n\t\t//- filter leafs only\n\t\t//- filter data on specific level\n\t\t//- filter data on all levels\n\t\t//- in all cases we can show or hide empty folder\n\t\t//- in all cases we can show or hide childs for matched item\n\t\t\n\t\t//set new order of items, store original\n\t\tif (!preserve || !this._filter_branch){\n\t\t\tthis._filter_branch = this.branch;\n\t\t\tthis.branch = clone(this.branch);\n\t\t}\n\n\t\tthis.branch[0] = this._filter_branch_rec(filter, value, this.branch[0], 1, (filterMode||{}));\n\t},\n\t_filter_branch_rec:function(filter, value, branch, level, config){\n\t\t//jshint -W041\n\t\tvar neworder = [];\n\t\t\n\t\tvar allow = (config.level && config.level != level);\n\n\t\tfor (var i=0; i < branch.length; i++){\n\t\t\tvar id = branch[i];\n\t\t\tvar item = this.getItem(id);\n\t\t\tvar child_run = false;\n\t\t\tvar sub = this.branch[id];\n\n\t\t\tif (allow){\n\t\t\t\tchild_run = true;\n\t\t\t} else if (filter(this.getItem(id),value)){\n\t\t\t\tneworder.push(id);\n\t\t\t\t// open all parents of the found item\n\t\t\t\tif (config.openParents !== false){\n\t\t\t\t\tvar parentId = this.getParentId(id);\n\t\t\t\t\twhile(parentId && parentId != \"0\"){\n\t\t\t\t\t\tthis.getItem(parentId).open = 1;\n\t\t\t\t\t\tparentId = this.getParentId(parentId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t//in case of of fixed level filtering - do not change child-items\n\t\t\t\tif (config.level || config.showSubItems)\n\t\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\t//filtering level, not match\n\t\t\t\tchild_run = true;\n\t\t\t}\t\n\n\t\t\t//if \"filter by all levels\" - filter childs\n\t\t\tif (allow || !config.level){ \n\t\t\t\tif (sub){\n\t\t\t\t\tvar newsub = this.branch[id] = this._filter_branch_rec(filter, value, sub, level+1, config);\n\t\t\t\t\titem.$count = newsub.length;\n\t\t\t\t\tif (child_run && newsub.length)\n\t\t\t\t\t\tneworder.push(id);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn neworder;\n\t},\n\tcount:function(){\n\t\tif (this.order.length)\n\t\t\treturn this.order.length;\n\n\t\t//we must return some non-zero value, or logic of selection will think that we have not data at all\n\t\tvar count=0;\n\t\tthis.eachOpen(function(){ count++; });\n\t\treturn count;\n\t},\n\t_change_branch_id:function(branches, parent, old, newid){\n\t\tif (branches[old]){\n\t\t\tvar branch = branches[newid] = branches[old];\n\t\t\tfor (var i = 0; i < branch.length; i++)\n\t\t\t\tthis.getItem(branch[i]).$parent = newid;\n\t\t\tdelete branches[old];\n\t\t}\n\t\tif (branches[parent]){\n\t\t\tvar index = _power_array.find.call(branches[parent], old);\n\t\t\tif (index >= 0)\n\t\t\t\tbranches[parent][index] = newid;\n\t\t}\n\t},\n\tchangeId:function(old, newid){\n\t\tif(old == newid) return;\n\t\t\n\t\tvar parent = this.getItem(old).$parent;\n\t\tthis._change_branch_id(this.branch, parent, old, newid);\n\n\t\t//in case of filter applied, update id in filtered state as well\n\t\tif (this._filter_branch)\n\t\t\tthis._change_branch_id(this._filter_branch, parent, old, newid);\n\n\t\treturn DataStore.prototype.changeId.call(this, old, newid);\n\t},\n\tclearAll:function(soft){\n\t\tthis.branch = { 0:[] };\n\t\tDataStore.prototype.clearAll.call(this, soft);\t\n\t},\n\tgetPrevSiblingId:function(id){\n\t\tvar order = this.branch[this.getItem(id).$parent];\n\t\tvar pos = _power_array.find.call(order, id)-1;\n\t\tif (pos>=0)\n\t\t\treturn order[pos];\n\t\treturn null;\n\t},\n\tgetNextSiblingId:function(id){\n\t\tvar order = this.branch[this.getItem(id).$parent];\n\t\tvar pos = _power_array.find.call(order, id)+1;\n\t\tif (pos=0; i--)\n\t\t\t\tnewbranch[i] = this.pull[bset[i]];\n\n\t\t\tnewbranch.sort(sorter);\n\t\t\tbranch[key] = newbranch.map(a => a.id);\n\t\t}\n\t\treturn order;\n\t},\n\tadd:function(obj, index, pid){\n\t\tvar refresh_parent = false;\n\n\t\tvar parent = this.getItem(pid||0);\n\t\tif(parent){\n\t\t\t//when adding items to leaf item - it need to be repainted\n\t\t\tif (!this.branch[parent.id])\n\t\t\t\trefresh_parent = true;\n\n\t\t\tparent.$count++;\n\t\t\t//fix for the adding into dynamic loading branch\n\t\t\t//dynamic branch has $count as -1\n\t\t\tif (!parent.$count) parent.$count = 1;\n\t\t}\n\n\t\tthis.branch[pid||0] = this.order = _to_array(this.branch[pid||0]);\n\n\t\tobj.$count = obj.webix_kids ? -1 : 0; \n\t\tobj.$level= (parent?parent.$level+1:1); \n\t\tobj.$parent = (parent?parent.id:0);\n\n\t\tif (this._filter_branch){\t//adding during filtering\n\t\t\tvar origin = this._filter_branch[pid||0];\n\t\t\t//newly created branch\n\t\t\tif (!origin) origin = this._filter_branch[pid] = this.order;\n\n\t\t\t//branch can be shared bettwen collections, ignore such cases\n\t\t\tif (this.order !== origin){\n\t\t\t\t//we can't know the location of new item in full dataset, making suggestion\n\t\t\t\t//put at end by default\n\t\t\t\tvar original_index = origin.length;\n\t\t\t\t//put at start only if adding to the start and some data exists\n\t\t\t\tif (!index && this.branch[pid||0].length)\n\t\t\t\t\toriginal_index = 0;\n\n\t\t\t\torigin = _to_array(origin);\n\t\t\t\tobj.id = obj.id || uid();\n\t\t\t\torigin.insertAt(obj.id,original_index);\n\t\t\t}\n\t\t}\n\n\t\t//call original adding logic\n\t\tvar result = DataStore.prototype.add.call(this, obj, index);\n\n\n\t\tif (refresh_parent)\n\t\t\tthis.refresh(pid);\n\n\t\treturn result;\n\t},\n\t_rec_remove:function(id){\n\t\tvar obj = this.pull[id];\n\t\tif(this.branch[obj.id] && this.branch[obj.id].length > 0){\n\t\t\tvar branch = this.branch[id];\n\t\t\tfor(var i=0;i 250) {\n\t\t\t\tthis.fileDialog();\n\t\t\t}\n\t\t}, this));\n\n\t\t_event(this._viewobj, \"dragenter\", preventEvent);\n\t\t_event(this._viewobj, \"dragexit\", preventEvent);\n\t\t_event(this._viewobj, \"dragover\", preventEvent);\n\t},\n\t_directoryEntry: function(value) {\n\t\treturn value.isDirectory;\n\t},\n\t_directoryDrop: function(item, state, path) {\n\t\tif (item.isFile){\n\t\t\titem.file(function(file){\n\t\t\t\tstate.addFile(file, null, null, { name : path+\"/\"+file.name });\n\t\t\t});\n\t\t} else if (item.isDirectory) {\n\t\t\t// Get folder contents\n\t\t\tvar dirReader = item.createReader();\n\t\t\tdirReader.readEntries(function(entries){\n\t\t\t\tfor (var i = 0; i < entries.length; i++){\n\t\t\t\t\tstate._directoryDrop(entries[i], state, (path ? (path + \"/\") : \"\") + item.name);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\t// adding files by drag-n-drop\n\t$drop: function(e) {\n\t\tvar files = e.dataTransfer.files;\n\t\tvar items = e.dataTransfer.items;\n\n\t\t// non-file drop\n\t\tif (!files.length) return;\n\n\t\tif (this.callEvent(\"onBeforeFileDrop\", [files, e])) {\n\t\t\titems = items || files; //IE10+\n\t\t\tfor (var i = 0; i < items.length; i++) {\n\t\t\t\t//https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/webkitGetAsEntry\n\t\t\t\tvar item = items[i];\n\t\t\t\tif (item.webkitGetAsEntry){\n\t\t\t\t\titem = item.webkitGetAsEntry();\n\t\t\t\t\tif (item.isDirectory){\n\t\t\t\t\t\tthis._directoryDrop(item, this, \"\");\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.addFile(files[i]);\n\t\t\t}\n\t\t}\n\t\tthis.callEvent(\"onAfterFileDrop\", [files, e]);\n\t},\n\tfileDialog:function(context){\n\t\tthis._upload_timer_click = new Date();\n\t\tthis._last_file_context = context;\n\t\tvar inputs = this._viewobj.getElementsByTagName(\"INPUT\");\n\t\tinputs[inputs.length-1].click();\n\t},\n\tsend: function(id){\n\t\t//alternative syntx send(callback)\n\t\tif (typeof id == \"function\"){\n\t\t\tthis._last_assigned_upload_callback = id;\n\t\t\tid = 0;\n\t\t}\n\n\t\tif (!id){\n\t\t\tvar order = this.files.data.order;\n\t\t\tvar complete = true;\n\n\t\t\tif (order.length)\n\t\t\t\tfor (var i=0; i !this.elements[v]);\n\t\tthis._inner_setValues(data, update, config);\n\t},\n\t_inner_setValues:function(data, update, config){\n\t\tthis._is_form_dirty = update;\n\t\t//prevent onChange calls from separate controls\n\t\tthis.blockEvent();\n\n\t\tif (!update || !this._values)\n\t\t\tthis._values = {};\n\n\t\tfor (let name in data)\n\t\t\tif (!this.elements[name])\n\t\t\t\tthis._values[name] = data[name];\n\n\t\tfor (let name in this.elements){\n\t\t\tconst input = this.elements[name];\n\t\t\tif (input){\n\t\t\t\tif (!isUndefined(data[name]))\n\t\t\t\t\tinput.setValue(data[name], config);\n\t\t\t\telse if (!update && input.$allowsClear)\n\t\t\t\t\tinput.setValue(\"\", config);\n\t\t\t\tthis._values[name] = input.getValue();\n\t\t\t}\n\t\t}\n\n\t\tthis.unblockEvent();\n\t\tthis.callEvent(\"onValues\",[]);\n\t},\n\tisDirty:function(){\n\t\treturn !!this._is_form_dirty || this.getDirtyValues(true) === true;\n\t},\n\tsetDirty:function(flag){\n\t\tthis._is_form_dirty = flag;\n\t\tif (!flag)\n\t\t\tthis._values = this._inner_getValues();\n\t},\n\tgetDirtyValues:function(){\n\t\tconst result = {};\n\t\tif (this._values){\n\t\t\tfor (let name in this.elements){\n\t\t\t\tconst view = this.elements[name];\n\t\t\t\tconst value = view.getValue();\n\t\t\t\tconst defaultValue = this._values[name];\n\n\t\t\t\tconst isDirty = view.$compareValue ? !view.$compareValue(defaultValue, value) : defaultValue != value;\n\t\t\t\tif (isDirty){\n\t\t\t\t\tresult[name] = value;\n\t\t\t\t\tif (arguments[0])\n\t\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t},\n\tgetCleanValues:function(){\n\t\treturn this._values;\n\t},\n\tgetValues:function(filter){\n\t\tlet data = this._inner_getValues(filter);\n\t\tif (this._settings.complexData)\n\t\t\tdata = CodeParser.expandNames(data);\n\n\t\treturn data;\n\t},\n\t_inner_getValues:function(filter){\n\t\t//get original data\t\t\n\t\tlet success,\n\t\t\telem = null;\n\n\t\tconst data = (this._values?copy(this._values):{});\n\n\t\t//update properties from linked controls\n\t\tfor (let name in this.elements){\n\t\t\telem = this.elements[name];\n\t\t\tsuccess = true;\n\t\t\tif(filter){\n\t\t\t\tif(typeof filter == \"object\"){\n\t\t\t\t\tif(filter.hidden === false)\n\t\t\t\t\t\tsuccess = elem.isVisible();\n\t\t\t\t\tif(success && filter.disabled === false)\n\t\t\t\t\t\tsuccess = elem.isEnabled();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tsuccess = filter.call(this,elem);\n\t\t\t}\n\t\t\tif(success)\n\t\t\t\tdata[name] = elem.getValue();\n\t\t\telse\n\t\t\t\tdelete data[name]; //in case of this._values[name]\n\t\t}\n\t\treturn data;\n\t},\n\tclear:function(config){\n\t\tthis._is_form_dirty = false;\n\t\tconst data = {};\n\t\tfor (let name in this.elements)\n\t\t\tif (this.elements[name].$allowsClear)\n\t\t\t\tdata[name] = \"\";\n\t\t\n\t\tthis._inner_setValues(data, false, config);\n\t},\n\tmarkInvalid: function(name, state){\n\t\t// remove 'invalid' mark\n\t\tif(state === false){\n\t\t\tthis._clear_invalid(name);\n\t\t}\n\t\t// add 'invalid' mark\n\t\telse{\n\t\t\tlet messageChanged;\n\t\t\t// set invalidMessage\n\t\t\tif(typeof state == \"string\"){\n\t\t\t\tconst input = this.elements[name];\n\t\t\t\tif(input && input._settings.invalidMessage != state){\n\t\t\t\t\tinput._settings.invalidMessage = state;\n\t\t\t\t\tmessageChanged = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//add mark to current validation process\n\t\t\tif (this._validate_details)\n\t\t\t\tthis._validate_details[name] = true;\n\n\t\t\tthis._mark_invalid(name, messageChanged);\n\t\t}\n\t},\n\t_mark_invalid:function(id, messageChanged){\n\t\tconst input = this.elements[id];\n\n\t\tif(input){\n\t\t\tconst config = input._settings;\n\t\t\tconst valid = !config.invalid;\n\n\t\t\tif (valid || messageChanged){\n\t\t\t\tif(valid){\n\t\t\t\t\taddCss(input._viewobj, \"webix_invalid\", true);\n\t\t\t\t\tconfig.invalid = true;\n\t\t\t\t}\n\n\t\t\t\tconst message = config.invalidMessage;\n\t\t\t\tif (typeof message === \"string\" && input.setBottomText)\n\t\t\t\t\tinput.setBottomText();\n\t\t\t}\n\t\t}\n\t},\n\t_clear_invalid:function(id){\n\t\tconst input = this.elements[id];\n\t\tif (input && input._settings.invalid){\n\t\t\tremoveCss(input._viewobj, \"webix_invalid\");\n\t\t\tinput._settings.invalid = false;\n\n\t\t\tconst message = input._settings.invalidMessage;\n\t\t\tif (typeof message === \"string\" && input.setBottomText)\n\t\t\t\tinput.setBottomText();\n\t\t}\n\t}\n};\n\n\nexport default Values;","import {$active} from \"../../webix/skin\";\nimport {extend, isUndefined} from \"../../webix/helpers\";\n\nexport const errorMessage = \"non-existing view for export\";\n\nfunction getDataHelper(key, column, raw){\n\tif (!raw && column.format)\n\t\treturn function(obj){ return column.format(obj[key]); };\n\n\treturn function(obj){ return obj[key]; };\n}\n\nfunction getHeaderText(view, header){\n\tlet text = header.text;\n\tif (header.contentId){\n\t\tconst content = view.getHeaderContent(header.contentId);\n\t\tif (content && !content.type.$icon)\n\t\t\ttext = content.getValue(true);\n\t}\n\treturn (text||\"\").toString().replace( /<[^>]*>/gi, \"\");\n}\n\nexport function getStyles(r, c, styles){\n\t//row index, column index, styles array\n\tif(styles[r] && styles[r][c])\n\t\treturn styles[r][c];\n\treturn {};\n}\n\nexport function getExportScheme(view, options){\n\tconst scheme = [];\n\tlet h_count = 0, f_count = 0;\n\tconst isTable = view.getColumnConfig;\n\tlet columns = options.columns;\n\tconst raw = !!options.rawValues;\n\tconst isTree = view.data.name == \"TreeStore\";\n\n\tlet treeLines = options.treeLines;\n\tif(treeLines === true || isUndefined(treeLines))\n\t\ttreeLines = \"value\";\n\n\tscheme.heights = {};\n\n\tif(options.hidden || options.hide){\n\t\tscheme.hiddenCols = {};\n\t\tscheme.hiddenRows = {};\n\t}\n\n\tif (!columns){\n\t\tcolumns = [];\n\t\tif (isTable){\n\t\t\tconst order = view._hidden_column_order;\n\t\t\tif(options.hidden && order.length){\n\t\t\t\tfor (let i = 0; i < order.length; i++){\n\t\t\t\t\tconst col = view.getColumnConfig(order[i]);\n\t\t\t\t\tif(!view.isColumnVisible(col.id))\n\t\t\t\t\t\tscheme.hiddenCols[col.id] = 1;\n\t\t\t\t\tcolumns.push(col);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t\tcolumns = columns.concat(view._columns);\n\t\t}\n\t\telse {\n\t\t\tconst obj = view.data.pull[view.data.order[0]];\n\t\t\tfor (let key in obj)\n\t\t\t\tif(key !== \"id\" && key[0] != \"$\")\n\t\t\t\t\tcolumns.push({id:key, isTree: isTree && key === treeLines});\n\t\t}\n\t}\n\telse if(!columns.length){\n\t//export options are set as - columns:{ rank:true, title:{ header:\"custom\"}}\n\t\tconst arr = [];\n\t\tfor(let key in columns)\n\t\t\tarr.push(extend({ id:key}, extend({}, columns[key])));\n\t\tcolumns = arr;\n\t}\n\n\tif (options.ignore)\n\t\tfor (let i=columns.length-1; i>=0; i--)\n\t\t\tif (options.ignore[columns[i].id])\n\t\t\t\tcolumns.splice(i,1);\n\n\tif (options.id)\n\t\tscheme.push({ id:\"id\", width:50, header:\" \", template:function(obj){ return obj.id; }});\n\n\tif (options.flatTree){\n\t\tconst flatKey = options.flatTree.id;\n\t\tconst copy = [].concat(options.flatTree.columns);\n\t\tconst fill = [];\n\t\tconst fillMode = !!options.flatTree.fill;\n\t\tfor (let i = 1; i <= copy.length; i++)\n\t\t\tcopy[i-1].template = (function(i){ \n\t\t\t\treturn function(obj){ \n\t\t\t\t\treturn obj.$level == i ? (fill[i]=obj[flatKey]) : ((fillMode && i= 0; i--)\n\t\t\tif (columns[i].id === flatKey)\n\t\t\t\tindex = i;\n\n\t\tcolumns = [].concat(columns.slice(0,index)).concat(copy).concat(columns.slice(index+1));\n\t}\n\n\tlet treeColumn;\n\n\tfor (let j = 0; j < columns.length; j++) {\n\t\tlet column = columns[j];\n\t\tlet key = column.id;\n\n\t\tif (column.noExport) continue;\n\n\t\t// raw mode has sense only for datatable\n\t\t// in other cases we don't have built-in data templates\n\t\tlet rawColumn = raw && isTable;\n\t\tif (isTable){\n\t\t\tconst sourceColumn = view.getColumnConfig(key);\n\t\t\t// when these's no column to take raw data from, or custom template defined - ignore raw mode\n\t\t\tif (column.template && (!sourceColumn || sourceColumn.template != column.template))\n\t\t\t\trawColumn = false;\n\t\t\tif(sourceColumn)\n\t\t\t\tcolumn = extend(extend({}, column), sourceColumn);\n\t\t}\n\n\t\tconst record = {\n\t\t\tid: column.id,\n\t\t\ttemplate: (( rawColumn || !column.template) ? getDataHelper(key, column, raw) : column.template ),\n\t\t\twidth: ((column.width || 200) * (options.export_mode===\"excel\"?8.43/70:1 )),\n\t\t\theader: (column.header!==false?(column.header||key) : \"\")\n\t\t};\n\n\t\tif (column.collection) record.collection = column.collection;\n\n\t\tif(isTree && key === treeLines)\n\t\t\trecord.isTree = treeColumn = true;\n\n\t\tif(options.export_mode === \"excel\"){\n\t\t\textend(record, {\n\t\t\t\ttype: column.exportType || \"\",\n\t\t\t\tformat:column.exportFormat || \"\"\n\t\t\t});\n\t\t\tif(column.hidden){\n\t\t\t\tif(!scheme.hiddenCols)\n\t\t\t\t\tscheme.hiddenCols = {};\n\t\t\t\tscheme.hiddenCols[column.id] = 1;\n\t\t\t}\n\t\t}\n\n\t\tif(typeof record.header === \"string\") record.header = [{text:record.header}];\n\t\telse record.header = [].concat(record.header);\n\n\t\tfor(let i = 0; i:*|\"]/g, \"\").substring(0, 150);\n\treturn `${name || \"Data\"}.${extension}`;\n}\n\nexport function getExportData(view, options, scheme){\n\tconst filterHTML = !!options.filterHTML;\n\tconst htmlFilter = /<[^>]*>/gi;\n\tlet data = [];\n\tlet header, headers;\n\tconst mode = options.export_mode;\n\n\tif((mode === \"excel\" || mode == \"csv\") && options.docHeader){\n\t\tdata = [[(options.docHeader.text || options.docHeader).toString()], [\"\"]];\n\t\tif(mode === \"excel\" && options.docHeader.height)\n\t\t\tscheme.heights[0] = options.docHeader.height;\n\t}\n\n\tif( options.header !== false && scheme.length){\n\t\tfor(let h=0; h < scheme[0].header.length; h++){\n\t\t\theaders = [];\n\t\t\tfor (let i = 0; i < scheme.length; i++){ \n\t\t\t\theader = \"\";\n\t\t\t\tif(scheme[i].header[h]){\n\t\t\t\t\theader = scheme[i].header[h];\n\t\t\t\t\tif (filterHTML)\n\t\t\t\t\t\theader = scheme[i].header[h] = header.replace(htmlFilter, \"\");\n\t\t\t\t}\n\t\t\t\theaders.push(header);\n\t\t\t}\n\n\t\t\tif(mode ==\"excel\" && view._columns && options.heights !==false &&\n\t\t\t(view._headers[h] !== $active.barHeight || options.heights == \"all\")\n\t\t\t) scheme.heights[data.length] = view._headers[h];\n\n\t\t\tif (mode !== \"pdf\")\n\t\t\t\tdata[data.length] = headers;\n\t\t}\n\t}\n\toptions.yCorrection = (options.yCorrection||0)-data.length;\n\n\tconst treeline = (options.flatTree || options.plainOutput) ? \"\" : \"-\";\n\n\tview.data.each(function(item, index){\n\t\tif(!options.filter || options.filter(item)){\n\t\t\tconst reallyHidden = options.hidden && view.data._filter_order && view.getIndexById(item.id) == -1;\n\t\t\tif((options.hide && options.hide(item)) || reallyHidden){\n\t\t\t\tconst header = (options.docHeader?2:0)+(options.header===false?0:scheme[0].header.length);\n\t\t\t\tscheme.hiddenRows[header+index] = 1;\n\t\t\t}\n\n\t\t\tif(this.data._scheme_export){\n\t\t\t\titem = view.data._scheme_export(item);\n\t\t\t}\n\n\t\t\tlet line = [];\n\t\t\tfor (let i = 0; i < scheme.length; i++){\n\t\t\t\tlet column = scheme[i], cell = null;\n\t\t\t\t//spreadsheet use muon to store data, get value via $getExportValue\n\t\t\t\tif(view.$getExportValue)\n\t\t\t\t\tcell = view.$getExportValue(item.id, column.id, options);\n\t\t\t\telse {\n\t\t\t\t\t//datatable math\n\t\t\t\t\tlet formula;\n\t\t\t\t\tif(options.math && item[\"$\"+column.id] && item[\"$\"+column.id].charAt(0) ==\"=\"){\n\t\t\t\t\t\tif(mode == \"excel\")\n\t\t\t\t\t\t\tformula = item[\"$\"+column.id];\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcell = item[\"$\"+column.id];\n\t\t\t\t\t}\n\n\t\t\t\t\tif(this._spans_pull){\n\t\t\t\t\t\tlet span = this.getSpan(item.id, column.id);\n\t\t\t\t\t\tif(span && span[4] && span[0] == item.id && span[1] == column.id){\n\t\t\t\t\t\t\tcell = span[4];\n\t\t\t\t\t\t\tif(filterHTML && typeof cell === \"string\")\n\t\t\t\t\t\t\t\tcell = cell.replace(htmlFilter, \"\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(!cell){\n\t\t\t\t\t\tcell = column.template(item, view.type, item[column.id], column, i);\n\t\t\t\t\t\tif (!cell && cell !== 0) cell = \"\";\n\t\t\t\t\t\tif(column.isTree && treeline)\n\t\t\t\t\t\t\tcell = \" \"+Array(item.$level).join(treeline)+\" \"+cell;\n\t\t\t\t\t\tif (filterHTML && typeof cell === \"string\"){\n\t\t\t\t\t\t\tcell = cell.replace(htmlFilter, \"\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//remove end/start spaces(ex.hierarchy data)\n\t\t\t\t\t\tif (typeof cell === \"string\" && mode === \"csv\")\n\t\t\t\t\t\t\tcell = cell.trim();\n\t\t\t\t\t\t//for multiline data\n\t\t\t\t\t\tif (typeof cell === \"string\" && (mode === \"excel\" || mode === \"csv\")){\n\t\t\t\t\t\t\tcell = cell.replace(//mg,\"\\n\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(formula)\n\t\t\t\t\t\tcell = { formula, value: cell };\n\t\t\t\t}\n\n\t\t\t\tline.push(cell);\n\t\t\t}\n\n\t\t\tif(mode ==\"excel\" && view._columns && options.heights !== false &&\n\t\t\t((item.$height && item.$height !== $active.rowHeight) || options.heights == \"all\")\n\t\t\t) scheme.heights[data.length] = item.$height || this.config.rowHeight;\n\n\t\t\tdata.push(line);\n\t\t}\n\t}, view, options.hidden);\n\n\tif( options.footer !==false ){\n\t\tlet f_count = scheme[0].footer?scheme[0].footer.length:0;\n\t\tfor (let f = 0; f < f_count; f++){\n\t\t\tlet footers = [];\n\t\t\tfor(let i = 0; i
\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn html.join(\"\");\n\t},\n\ttype:{\n\t\theight:24,\n\t\ttemplateStart:template(\"\"),\n\t\ttemplateEnd:template(\"\")\n\t},\n\t$skin: function(){\n\t\tthis.type.height = $active.propertyItemHeight;\n\t}\n};\n\n\nconst view = protoUI(api, AutoTooltip, EditAbility, MapCollection, MouseEvents, Scrollable, SingleRender, AtomDataLoader, EventSystem, base.view);\nexport default {api, view};","import {index, triggerEvent, preventEvent} from \"../webix/html\";\nimport {protoUI, $$} from \"../ui/core\";\nimport {$active} from \"../webix/skin\";\nimport {extend, copy, toFunctor, isArray} from \"../webix/helpers\";\nimport {_event} from \"../webix/htmlevents\";\nimport template from \"../webix/template\";\n\nimport i18n from \"../webix/i18n\";\nimport MouseEvents from \"../core/mouseevents\";\nimport EventSystem from \"../core/eventsystem\";\nimport base from \"../views/view\";\nimport DateHelper from \"../core/date\";\nimport KeysNavigation from \"../core/keysnavigation\";\n\n\nconst api = {\n\tname:\"calendar\",\n\n\tdefaults:{\n\t\tdate: DateHelper.datePart(new Date()), //selected date, not selected by default\n\t\tnavigation: true,\n\t\tmonthSelect: true,\n\t\tweekHeader: true,\n\t\tmonthHeader: true,\n\t\tweekNumber: false,\n\t\tskipEmptyWeeks: false,\n\t\tcalendarHeader: \"%F %Y\",\n\t\t//calendarTime: \"%H:%i\",\n\t\tevents:DateHelper.isHoliday,\n\t\tminuteStep: 5,\n\t\ttimeIcon:\"wxi-clock\",\n\t\ticons: false,\n\t\ttimepickerHeight: 30,\n\t\theaderHeight: 30,\n\t\tdayTemplate: function(d){\n\t\t\treturn d.getDate();\n\t\t},\n\t\twidth: 260,\n\t\theight: 250,\n\t\tseparator:\", \"\n\t},\n\n\tdayTemplate_setter: template,\n\tcalendarHeader_setter:DateHelper.dateToStr,\n\tcalendarTime_setter:function(format){\n\t\tthis._calendarTime = format;\n\t\treturn DateHelper.dateToStr(format);\n\t},\n\tdate_setter:function(date){\n\t\tdate = DateHelper.copy( this._string_to_date(date) );\n\t\tdate.setDate(1);\n\t\treturn date;\n\t},\n\tmaxDate_setter:function(date){\n\t\treturn DateHelper.datePart( this._string_to_date(date) );\n\t},\n\tminDate_setter:function(date){\n\t\treturn DateHelper.datePart( this._string_to_date(date) );\n\t},\n\tminTime_setter:function(time){\n\t\tif(typeof(time) == \"string\"){\n\t\t\ttime = i18n.parseTimeFormatDate(time);\n\t\t\ttime = [time.getHours(), time.getMinutes()];\n\t\t}\n\t\treturn time;\n\t},\n\tmaxTime_setter:function(time){\n\t\tif(typeof(time) == \"string\"){\n\t\t\ttime = i18n.parseTimeFormatDate(time);\n\t\t\ttime = [time.getHours(), time.getMinutes()];\n\t\t}\n\t\treturn time;\n\t},\n\t_ariaFocus:function(){\n\t\t_event(this.$view, \"mousedown\", () => {\n\t\t\tthis._mouse_time = new Date();\n\t\t});\n\t\t_event(this.$view, \"focus\", e => {\n\t\t\t// in daterange\n\t\t\tif (this._settings.master) return;\n\n\t\t\tconst prev = e.relatedTarget;\n\t\t\tconst css = e.target.className.indexOf(\"webix_cal_day\") !== -1;\n\t\t\tif (prev && (new Date() - this._mouse_time > 100) && css && this.$view.contains(prev)){\n\t\t\t\tconst day = this._locate_day(e.target);\n\t\t\t\tif (!this._selectedDay(day)) this._moveSelection(day);\n\t\t\t}\n\t\t}, { capture: true });\n\t},\n\t$init: function() {\n\t\tthis._viewobj.className += \" webix_calendar\";\n\t\tthis._viewobj.setAttribute(\"role\", \"region\");\n\t\tthis._viewobj.setAttribute(\"aria-label\", i18n.aria.calendar);\n\n\t\t//special dates\n\t\tthis._special_dates = {};\n\t\tthis._selected_days = {};\n\t\tthis._zoom_level = 0;\n\n\t\t//navigation and aria\n\t\tthis._ariaFocus();\n\t\tthis.attachEvent(\"onKeyPress\", this._onKeyPress);\n\t},\n\t_onKeyPress:function(code, e){\n\t\tconst target = e.target, role = target.getAttribute(\"role\");\n\t\tif((code === 13 || code === 32) && (role == \"button\" || role == \"log\") && !this._settings.disabled){\n\t\t\ttriggerEvent(target, \"MouseEvent\", \"click\");\n\t\t\tpreventEvent(e);\n\t\t}\n\t},\n\tminuteStep_setter(value){\n\t\treturn Math.max( Math.min(value, 60), this.defaults.minuteStep );\n\t},\n\ttype_setter: function(value){\n\t\tif(value == \"time\"){\n\t\t\tthis._zoom_in = true;\n\t\t\tthis._zoom_level = -1;\n\t\t}\n\t\telse if(value == \"year\"){\n\t\t\tthis._fixed = true;\n\t\t}\n\t\treturn value;\n\t},\n\t$setSize:function(x,y){\n\n\t\tif(base.api.$setSize.call(this,x,y)){\n\t\t\t//repaint calendar when size changed\n\t\t\tthis.render();\n\t\t}\n\t},\n\t$getSize:function(dx, dy){\n\t\tconst s = this._settings;\n\t\tif (s.cellHeight && !s.type){\n\t\t\tconst state = this._getDateBoundaries(s.date);\n\t\t\ts.height = s.cellHeight * state._rows + s.headerHeight + (s.weekHeader?$active.calendarWeekHeaderHeight:0) +\n\t\t\t\t(s.timepicker||this._icons?s.timepickerHeight:0) + (this._content_padding+$active.borderWidth)*2;\n\t\t}\n\t\treturn base.api.$getSize.call(this, dx,dy);\n\t},\n\tmoveSelection:function(mode, details, focus){\n\t\tif (this.config.master) return; //in daterange\n\t\tvar start = this.getSelectedDate(true);\n\t\tvar date = DateHelper.copy(start || this.getVisibleDate());\n\t\tthis._moveSelection(date, mode, focus);\n\t},\n\t_moveSelection:function(date, mode, focus){\n\t\tconst css = this._zoom_logic[this._zoom_level]._keyshift(date, mode, this);\n\t\tif (focus !== false)\n\t\t\tthis._restore_focus(css);\n\t},\n\t_restore_focus:function(css, ind){\n\t\tlet sel;\n\t\tif (ind) {\n\t\t\tsel = this._viewobj.querySelector(\".webix_cal_body\");\n\t\t\tsel = sel.childNodes[ind.rind].childNodes[ind.cind + (this._settings.weekNumber?1:0)];\n\t\t} else\n\t\t\tsel = this._viewobj.querySelector(\".\"+css+\"[tabindex='0']\");\n\t\tif (sel) sel.focus();\n\t},\n\t_getDateBoundaries: function(date, reset) {\n\t\t// addition information about rendering event:\n\t\t// how many days from the previous month,\n\t\t// next,\n\t\t// number of weeks to display and so on\n\t\t\n\t\tif (!this._set_date_bounds || reset){\n\t\t\tvar month = date.getMonth();\n\t\t\tvar year = date.getFullYear();\n\n\t\t\tvar next = new Date(year, month+1, 1);\n\t\t\tvar start = DateHelper.weekStart(new Date(year, month, 1));\n\n\t\t\tvar days = Math.round((next.valueOf() - start.valueOf())/(60*1000*60*24));\n\t\t\tvar rows = this._settings.skipEmptyWeeks?Math.ceil(days/7):6;\n\n\t\t\tthis._set_date_bounds = { _month: month, _start:start, _next:next, _rows: rows};\n\t\t}\n\n\t\treturn this._set_date_bounds;\n\t},\n\t$skin:function(){\n\t\tif($active.calendar){\n\t\t\tif( $active.calendar.width)\n\t\t\t\tthis.defaults.width = $active.calendar.width;\n\t\t\tif( $active.calendar.height)\n\t\t\t\tthis.defaults.height = $active.calendar.height;\n\t\t\tif( $active.calendar.headerHeight)\n\t\t\t\tthis.defaults.headerHeight = $active.calendar.headerHeight;\n\t\t\tif( $active.calendar.timepickerHeight)\n\t\t\t\tthis.defaults.timepickerHeight = $active.calendar.timepickerHeight;\n\t\t}\n\t\tthis._content_padding = $active.layoutPadding.form;\n\t},\n\t_getColumnConfigSizes: function(date){ \n\t\tvar bounds = this._getDateBoundaries(date);\n\n\t\tvar s = this._settings;\n\t\tvar _columnsHeight = [];\n\t\tvar _columnsWidth = [];\n\n\t\tvar containerWidth = this._content_width - (this._content_padding+$active.borderWidth)*2;\n\n\t\tvar containerHeight = this._content_height - (s.monthHeader?s.headerHeight:0) - (s.weekHeader?$active.calendarWeekHeaderHeight:0) -\n\t\t\t(s.timepicker||this._icons?s.timepickerHeight:0) - (this._content_padding+$active.borderWidth)*2;\n\n\t\tvar columnsNumber = (s.weekNumber)?8:7;\n\t\tfor(var i=0; i\"+i18n.calendar.today+\"\";\n\t\t\t},\n\t\t\ton_click:{\n\t\t\t\t\"webix_cal_icon_today\": function(){\n\t\t\t\t\tvar date = new Date();\n\t\t\t\t\tif(!this._settings.timepicker)\n\t\t\t\t\t\tdate = DateHelper.datePart(date);\n\t\t\t\t\tthis.setValue(date, \"user\");\n\t\t\t\t\tthis.callEvent(\"onTodaySet\",[this.getSelectedDate()]);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\ttemplate: function(){\n\t\t\t\treturn \"\"+i18n.calendar.clear+\"\";\n\t\t\t},\n\t\t\ton_click:{\n\t\t\t\t\"webix_cal_icon_clear\": function(){\n\t\t\t\t\tthis.setValue(\"\", \"user\");\n\t\t\t\t\tthis.callEvent(\"onDateClear\",[this.getSelectedDate()]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t],\n\trefresh:function(){ this.render(); },\n\trender: function() {\n\t\t//reset zoom level\n\t\tthis._zoom_level = 0;\n\t\tthis._zoom_size = false;\n\n\t\tvar s = this._settings;\n\n\t\tif (!this.isVisible(s.id)) return;\n\t\tthis._current_time = DateHelper.datePart(new Date());\n\n\t\tthis.callEvent(\"onBeforeRender\",[]);\n\n\t\tvar date = this.getVisibleDate();\n\n\t\tvar bounds = this._getDateBoundaries(date, true);\n\t\tvar sizes = this._getColumnConfigSizes(date);\n\t\tvar cpad = this._content_padding + \"px\";\n\t\tvar width = sizes[0];\n\t\tvar height = sizes[1];\n\n\t\tvar html = \"\";\n\t\tif (s.monthHeader){\n\t\t\thtml += \"
\"+s.calendarHeader(date)+\"\";\n\t\t\tif (s.navigation)\n\t\t\t\thtml += \"
\";\n\t\t\thtml += \"
\";\n\t\t}\n\n\t\tif(s.weekHeader)\n\t\t\thtml += \"\";\n\t\thtml += \"
\"+this._body_template(width, height, bounds)+\"
\";\n\n\t\tif (s.timepicker || this._icons){\n\t\t\thtml += \"\";\n\t\t}\n\n\t\tthis._contentobj.innerHTML = html;\n\t\tthis._contentobj.firstChild.style.marginTop = cpad;\n\n\t\tif(s.type == \"time\"){\n\t\t\tthis._changeZoomLevel(-1,date);\n\t\t}\n\t\telse if(s.type == \"month\"){\n\t\t\tthis._changeZoomLevel(1,date);\n\t\t}\n\t\telse if(s.type == \"year\"){\n\t\t\tthis._changeZoomLevel(2,date);\n\t\t}\n\n\t\tthis._fix_cover();\n\t\tthis.callEvent(\"onAfterRender\",[]);\n\t},\n\t_icons_template: function(date){\n\t\tvar html =\t\"
\";\n\t\tvar icons = this._icons;\n\n\t\tfor(var i=0; i < icons.length; i++){\n\t\t\tif(icons[i].template){\n\t\t\t\tvar template = (typeof(icons[i].template) == \"function\"?icons[i].template: template(icons[i].template));\n\t\t\t\thtml += template.call(this,date);\n\t\t\t}\n\t\t\tif(icons[i].on_click){\n\t\t\t\textend(this.on_click,icons[i].on_click);\n\t\t\t}\n\t\t}\n\t\thtml += \"
\";\n\t\treturn html;\n\t},\n\t_timepicker_template:function(date){\n\t\tconst sel = this.getSelectedDate(true);\n\t\tif (sel)\n\t\t\tdate.setFullYear(sel.getFullYear(), sel.getMonth(), sel.getDate());\n\t\tconst timeFormat = this._settings.calendarTime||i18n.timeFormatStr;\n\t\tconst clock = this._settings.timeIcon;\n\t\tlet tpl = \"\";\n\n\t\tif(!this._settings.master)\n\t\t\ttpl = \"
\"+timeFormat(date)+\"
\";\n\t\telse{\n\t\t\t//daterange needs two clocks\n\t\t\tconst range_date = copy($$(this._settings.master)._settings.value);\n\t\t\tif(DateHelper.equal(range_date.end, date))\n\t\t\t\trange_date.start = range_date.end;\n\n\t\t\tfor(let i in range_date){\n\t\t\t\ttpl += \"
\"+timeFormat(range_date[i])+\"
\";\n\t\t\t}\n\t\t}\n\t\treturn tpl;\n\t},\n\t_week_template: function(widths){\n\t\tvar s = this._settings;\n\t\tvar week_template = \"\";\n\t\tvar correction = 0;\n\n\t\tif(s.weekNumber) {\n\t\t\tcorrection = 1;\n\t\t\tweek_template += \"
\"+(s.calendarWeekHeader||\"\")+\"
\";\n\t\t}\n\t\t\n\t\tvar k = (DateHelper.startOnMonday)?1:0;\n\t\tfor (var i=0; i<7; i++){ // 7 days total\n\t\t\tvar day_index = (k + i) % 7; // 0 - Sun, 6 - Sat as in Locale.date.day_short\n\t\t\tvar day = i18n.calendar.dayShort[day_index]; // 01, 02 .. 31\n\t\t\tweek_template += \"
\"+day+\"
\";\n\t\t}\n\t\t\n\t\treturn week_template;\n\t},\n\tblockDates_setter:function(value){\n\t\treturn toFunctor(value, this.$scope);\n\t},\n\t_day_css:function(day, bounds){\n\t\tvar css = \"\", isOutside = false;\n\t\tif (DateHelper.equal(day, this._current_time))\n\t\t\tcss += \" webix_cal_today\";\n\t\tif (!this._checkDate(day))\n\t\t\tcss += \" webix_cal_day_disabled\";\n\t\tif (day.getMonth() != bounds._month){\n\t\t\tisOutside = true;\n\t\t\tcss += \" webix_cal_outside\";\n\t\t}\n\t\tif (!isOutside && this._selectedDay(day))\n\t\t\tcss += \" webix_cal_select\";\n\t\tif (this._settings.events)\n\t\t\tcss+=\" \"+(this._settings.events(day, isOutside) || \"\");\n\t\tcss += \" webix_cal_day\";\n\t\treturn css;\n\t},\n\t_body_template: function(widths, heights, bounds){\n\t\tconst s = this._settings;\n\t\tconst start = s.weekNumber ? 1 : 0;\n\t\tlet day = DateHelper.datePart(DateHelper.copy(bounds._start));\n\t\tlet weekNumber = DateHelper.getISOWeek(DateHelper.add(day, 2, \"day\", true));\n\n\t\tlet html = \"\", focusable, sqSize;\n\t\tfor (let y=0; y\";\n\n\t\t\tif (start){\n\t\t\t\t// recalculate week number for the first week of a year\n\t\t\t\tif(!day.getMonth() && day.getDate()<7)\n\t\t\t\t\tweekNumber = DateHelper.getISOWeek(DateHelper.add(day,2,\"day\", true));\n\t\t\t\thtml += \"\";\n\t\t\t}\n\n\t\t\tfor (let x=start; x\";\n\t\t\t\tday = DateHelper.add(day, 1, \"day\");\n\n\t\t\t\tif (day.getHours())\n\t\t\t\t\tday = DateHelper.datePart(day);\n\t\t\t}\n\n\t\t\thtml += \"\";\n\t\t\tweekNumber++;\n\t\t}\n\t\treturn html.replace(\"$webix_tabindex\", (focusable || s.master) ? \"-1\" : \"0\");\n\t},\n\t_changeDate:function(dir, step){\n\t\tif(!step) { step = this._zoom_logic[this._zoom_level]._changeStep; }\n\n\t\tconst now = this._settings.date;\n\t\tconst next = DateHelper.add(now, dir*step, \"month\", true);\n\t\tthis._changeDateInternal(now, next, dir);\n\t},\n\t_changeDateInternal:function(now, next, dir){\n\t\tif(this.callEvent(\"onBeforeMonthChange\", [now, next])){\n\t\t\tif (this._zoom_level){\n\t\t\t\tthis._update_zoom_level(next);\n\t\t\t} else {\n\t\t\t\tthis.showCalendar(next);\n\t\t\t\tif (this._settings.monthHeader && this._settings.navigation){\n\t\t\t\t\tconst css = \"webix_cal_\"+(dir>0?\"next\":\"prev\")+\"_button\";\n\t\t\t\t\tthis._restore_focus(css);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.callEvent(\"onAfterMonthChange\", [next, now]);\n\t\t}\n\t},\n\t_zoom_logic:{\n\t\t\"-2\":{\n\t\t\t_isBlocked: function(i){\n\t\t\t\tvar config = this._settings,\n\t\t\t\t\tdate = this.getSelectedDate(true) || config.date,\n\t\t\t\t\tisBlocked = false;\n\n\t\t\t\tvar minHour = (config.minTime ? config.minTime[0] : 0);\n\t\t\t\tvar maxHour = (config.maxTime ? (config.maxTime[0] + ( config.maxTime[1] ? 1 : 0 )) : 24);\n\n\t\t\t\tvar minMinute = (config.minTime && (date.getHours()==minHour) ? config.minTime[1] : 0);\n\t\t\t\tvar maxMinute = (config.maxTime && config.maxTime[1] && (date.getHours()==(maxHour-1)) ? config.maxTime[1] : 60);\n\n\t\t\t\tif(this._settings.blockTime){\n\t\t\t\t\tvar d = DateHelper.copy(date);\n\t\t\t\t\td.setMinutes(i);\n\t\t\t\t\tisBlocked = this._settings.blockTime(d);\n\t\t\t\t}\n\t\t\t\treturn (i < minMinute || i >= maxMinute || isBlocked);\n\n\t\t\t},\n\t\t\t_setContent:function(next, i){ next.setMinutes(i); },\n\t\t\t_findActive:function(date, mode, calendar){\n\t\t\t\tif(!this._isBlocked.call(calendar, date.getMinutes()))\n\t\t\t\t\treturn date;\n\t\t\t\telse{\n\t\t\t\t\tvar step = calendar._settings.minuteStep;\n\t\t\t\t\tvar newdate = DateHelper.add(date, mode ==\"right\"?step:-step, \"minute\", true);\n\t\t\t\t\tif(date.getHours() === newdate.getHours())\n\t\t\t\t\t\treturn this._findActive(newdate, mode, calendar);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"-1\":{\n\t\t\t_isBlocked: function(i){\n\t\t\t\tvar config = this._settings,\n\t\t\t\t\tdate = this.getSelectedDate(true) || config.date;\n\n\t\t\t\tvar minHour = (config.minTime? config.minTime[0]:0);\n\t\t\t\tvar maxHour = (config.maxTime? config.maxTime[0]+(config.maxTime[1]?1:0):24);\n\n\t\t\t\tif (i < minHour || i >= maxHour) return true;\n\n\t\t\t\tif(config.blockTime){\n\t\t\t\t\tvar d = DateHelper.copy(date);\n\t\t\t\t\td.setHours(i);\n\t\t\t\t\t\n\t\t\t\t\tvar minMinute = (config.minTime && (i==minHour) ? config.minTime[1] : 0);\n\t\t\t\t\tvar maxMinute = (config.maxTime && config.maxTime[1] && (i==(maxHour-1)) ? config.maxTime[1] : 60);\n\n\t\t\t\t\tfor (var j=minMinute; j= (60-step)) inc = step-60;\n\t\t\t\t\tinc -= date.getMinutes()%step;\n\t\t\t\t\tnewdate = calendar._zoom_logic[\"-2\"]._findActive(DateHelper.add(date, inc, \"minute\"), mode, calendar);\n\t\t\t\t}\n\t\t\t\telse if(mode === \"up\" || mode === \"down\"){ //hours\n\t\t\t\t\tinc = mode===\"down\"?1:-1;\n\t\t\t\t\tif(mode === \"down\" && date.getHours() === 23) inc = -23;\n\t\t\t\t\tif(mode === \"up\" && date.getHours() === 0) inc = 23;\n\t\t\t\t\tnewdate = this._findActive(DateHelper.add(date, inc, \"hour\"), mode, calendar);\n\t\t\t\t}\n\t\t\t\telse if(mode === false)\n\t\t\t\t\tnewdate = this._findActive(date, mode, calendar);\n\n\t\t\t\tif(newdate){\n\t\t\t\t\tcalendar._update_zoom_level(newdate);\n\t\t\t\t\tcalendar.selectDate(newdate, false, false, \"user\");\n\t\t\t\t}\n\n\t\t\t\treturn \"webix_cal_block\"+(mode === \"left\" || mode === \"right\"?\"_min\":\"\");\n\t\t\t},\n\t\t\t_findActive:function(date, mode, calendar){\n\t\t\t\tif(!this._isBlocked.call(calendar, date.getHours()))\n\t\t\t\t\treturn date;\n\t\t\t\telse{\n\t\t\t\t\tvar newdate = DateHelper.add(date, mode ==\"down\"?1:-1, \"hour\", true);\n\t\t\t\t\tif(date.getDate() === newdate.getDate())\n\t\t\t\t\t\treturn this._findActive(newdate, mode, calendar);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"0\":{//days\n\t\t\t_changeStep:1,\n\t\t\t_keyshift:function(date, mode, calendar){\n\t\t\t\tvar newdate = date;\n\t\t\t\tif(mode === \"pgup\" || mode === \"pgdown\")\n\t\t\t\t\tnewdate = DateHelper.add(date, (mode===\"pgdown\"?1:-1), \"month\");\n\t\t\t\telse if(mode === \"bottom\")\n\t\t\t\t\tnewdate = new Date(date.getFullYear(), date.getMonth()+1, 0);\n\t\t\t\telse if(mode === \"top\")\n\t\t\t\t\tnewdate = new Date(date.setDate(1));\n\t\t\t\telse if(mode === \"left\" || mode === \"right\")\n\t\t\t\t\tnewdate = DateHelper.add(date, (mode===\"right\"?1:-1), \"day\");\n\t\t\t\telse if(mode === \"up\" || mode === \"down\")\n\t\t\t\t\tnewdate = DateHelper.add(date, (mode===\"down\"?1:-1), \"week\");\n\t\t\t\t\n\t\t\t\tif(!calendar._checkDate(newdate))\n\t\t\t\t\tnewdate = calendar._findActive(date, mode);\n\t\t\t\t\n\t\t\t\tif(newdate)\n\t\t\t\t\tcalendar._selectDate(newdate, false, \"user\");\n\t\t\t\treturn \"webix_cal_day\";\n\t\t\t},\n\t\t\t\n\t\t},\n\t\t\"1\":{\t//months\n\t\t\t_isBlocked: function(i){\n\t\t\t\tconst date = this.getVisibleDate();\n\t\t\t\tdate.setMonth(i);\n\t\t\t\tlet blocked = this._isDateBlocked(date, 1);\n\n\t\t\t\tvar min = this._settings.minDate,\n\t\t\t\t\tmax = this._settings.maxDate,\n\t\t\t\t\tyear = this._settings.date.getFullYear();\n\n\t\t\t\tif (min && !blocked){\n\t\t\t\t\tvar minYear = min.getFullYear();\n\t\t\t\t\tblocked = yeari);\n\t\t\t\t}\n\n\t\t\t\tif (max && !blocked){\n\t\t\t\t\tvar maxYear = max.getFullYear();\n\t\t\t\t\tblocked = year>maxYear || (year==maxYear && max.getMonth() calendar._settings.maxDate){\n\t\t\t\t\tdate = DateHelper.copy(calendar._settings.maxDate);\n\t\t\t\t}\n\t\t\t\tlet blocked = calendar._isDateBlocked(date);\n\t\t\t\tif(blocked){\n\t\t\t\t\tconst d = DateHelper.copy(date);\n\t\t\t\t\twhile(blocked && d.getMonth() == date.getMonth()){\n\t\t\t\t\t\tblocked = calendar._isDateBlocked(d);\n\t\t\t\t\t\tif(blocked)\n\t\t\t\t\t\t\tDateHelper.add(d, 1, \"day\");\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tdate = d;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn date;\n\t\t\t},\n\t\t\t_getTitle:function(date){ return date.getFullYear(); },\n\t\t\t_getContent:function(i){ return i18n.calendar.monthShort[i]; },\n\t\t\t_setContent:function(next, i){ if(i!=next.getMonth()) next.setDate(1);next.setMonth(i); },\n\t\t\t_changeStep:12,\n\t\t\t_keyshift:function(date, mode, calendar){\n\t\t\t\tvar newdate = date;\n\t\t\t\tif(mode === \"pgup\" || mode === \"pgdown\")\n\t\t\t\t\tnewdate = DateHelper.add(date, (mode===\"pgdown\"?1:-1), \"year\");\n\t\t\t\telse if(mode === \"bottom\")\n\t\t\t\t\tnewdate = new Date(date.setMonth(11));\n\t\t\t\telse if(mode === \"top\")\n\t\t\t\t\tnewdate = new Date(date.setMonth(0));\n\t\t\t\telse if(mode === \"left\" || mode === \"right\")\n\t\t\t\t\tnewdate = DateHelper.add(date, (mode===\"right\"?1:-1), \"month\");\n\t\t\t\telse if(mode === \"up\" || mode === \"down\")\n\t\t\t\t\tnewdate = DateHelper.add(date, (mode===\"down\"?4:-4), \"month\");\n\n\t\t\t\tnewdate = calendar._correctDate(newdate);\n\n\t\t\t\tif(!calendar._checkDate(newdate)){\n\t\t\t\t\tnewdate = calendar._findActive(date, mode);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(newdate){\n\t\t\t\t\tcalendar._update_zoom_level(newdate);\n\t\t\t\t\tcalendar.selectDate(newdate, false, false, \"user\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn \"webix_cal_block\";\n\t\t\t}\n\t\t},\n\t\t\"2\":{\t//years\n\t\t\t_isBlocked: function(i){\n\t\t\t\ti += this._zoom_start_date;\n\n\t\t\t\tconst date = this.getVisibleDate();\n\t\t\t\tdate.setFullYear(i);\n\n\t\t\t\tconst blocked = this._isDateBlocked(date, 2);\n\t\t\t\tvar min = this._settings.minDate;\n\t\t\t\tvar max = this._settings.maxDate;\n\n\t\t\t\tif (blocked || (min && min.getFullYear() > i) || (max && max.getFullYear() < i))\n\t\t\t\t\treturn true;\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t_correctDate: function(date,calendar){\n\t\t\t\tdate = DateHelper.yearStart(date);\n\t\t\t\tif (date < calendar._settings.minDate){\n\t\t\t\t\tdate = DateHelper.copy(calendar._settings.minDate);\n\t\t\t\t}\n\t\t\t\telse if (date > calendar._settings.maxDate){\n\t\t\t\t\tdate = DateHelper.copy(calendar._settings.maxDate);\n\t\t\t\t}\n\t\t\t\tlet blocked = calendar._isDateBlocked(date);\n\t\t\t\tif(blocked){\n\t\t\t\t\tconst d = DateHelper.copy(date);\n\t\t\t\t\twhile(blocked && d.getFullYear() == date.getFullYear()){\n\t\t\t\t\t\tblocked = calendar._isDateBlocked(d);\n\t\t\t\t\t\tif(blocked)\n\t\t\t\t\t\t\tDateHelper.add(d, 1, \"day\");\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tdate = d;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn date;\n\t\t\t},\n\t\t\t_getTitle:function(date, calendar){\n\t\t\t\tvar start = date.getFullYear();\n\t\t\t\tcalendar._zoom_start_date = start = start - start%10 - 1;\n\t\t\t\treturn start+\" - \"+(start+10 + 1);\n\t\t\t},\n\t\t\t_getContent:function(i, calendar){ return calendar._zoom_start_date+i; },\n\t\t\t_setContent:function(next, i, calendar){ next.setFullYear(calendar._zoom_start_date+i); },\n\t\t\t_changeStep:12*10,\n\t\t\t_keyshift:function(date, mode, calendar){\n\t\t\t\tvar newdate = date;\n\t\t\t\tif(mode === \"pgup\" || mode === \"pgdown\")\n\t\t\t\t\tnewdate = DateHelper.add(date, (mode===\"pgdown\"?10:-10), \"year\");\n\t\t\t\telse if(mode === \"bottom\")\n\t\t\t\t\tnewdate = new Date(date.setYear(calendar._zoom_start_date+10));\n\t\t\t\telse if(mode === \"top\")\n\t\t\t\t\tnewdate = new Date(date.setYear(calendar._zoom_start_date));\n\t\t\t\telse if(mode === \"left\" || mode === \"right\")\n\t\t\t\t\tnewdate = DateHelper.add(date, (mode===\"right\"?1:-1), \"year\");\n\t\t\t\telse if(mode === \"up\" || mode === \"down\")\n\t\t\t\t\tnewdate = DateHelper.add(date, (mode===\"down\"?4:-4), \"year\");\n\n\t\t\t\tnewdate = calendar._correctDate(newdate);\n\n\t\t\t\tif(!calendar._checkDate(newdate))\n\t\t\t\t\tnewdate = calendar._findActive(date, mode);\n\t\t\t\t\n\t\t\t\tif(newdate){\n\t\t\t\t\tcalendar._update_zoom_level(newdate);\n\t\t\t\t\tcalendar.selectDate(newdate, false, false, \"user\");\n\t\t\t\t}\n\n\t\t\t\treturn \"webix_cal_block\";\n\t\t\t}\n\t\t}\n\t},\n\t_correctBlockedTime: function(){\n\t\tvar i, isDisabledHour, isDisabledMinutes;\n\t\tisDisabledHour = this._zoom_logic[-1]._isBlocked.call(this,this._settings.date.getHours());\n\t\tif(isDisabledHour){\n\t\t\tfor (i= 0; i< 24; i++){\n\t\t\t\tif(!this._zoom_logic[-1]._isBlocked.call(this,i)){\n\t\t\t\t\tthis._settings.date.setHours(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tisDisabledMinutes = this._zoom_logic[-2]._isBlocked.call(this,this._settings.date.getMinutes());\n\t\tif(isDisabledMinutes){\n\t\t\tfor (i=0; i<60; i+=this._settings.minuteStep){\n\t\t\t\tif(!this._zoom_logic[-2]._isBlocked.call(this,i)){\n\t\t\t\t\tthis._settings.date.setMinutes(i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t_update_zoom_level:function(date){\n\t\tvar config, css, height, i, index, sections, selected, type, width, zlogic, temp, sqSize;\n\t\tvar html = \"\";\n\t\tvar cpad = this._content_padding + \"px\";\n\n\t\tconfig = this._settings;\n\t\tindex = 2 - (config.weekHeader?0:1) - (config.monthHeader?0:1);\n\t\tzlogic = this._zoom_logic[this._zoom_level];\n\t\tsections = this._contentobj.childNodes;\n\n\t\tif (date)\n\t\t\tthis.define(\"date\", date);\n\t\ttype = config.type;\n\n\t\t//store width and height of draw area\n\t\tif (!this._zoom_size){\n\n\t\t\tthis._reserve_box_height = this._contentobj.offsetHeight - (config.monthHeader||this._zoom_in?config.headerHeight:0) -\n\t\t\t\t(this._content_padding+$active.borderWidth)*2;\n\t\t\tif(type != \"year\" && type != \"month\")\n\t\t\t\tthis._reserve_box_height -= config.timepickerHeight;\n\n\t\t\tthis._reserve_box_width = sections[index].offsetWidth;\n\t\t\tthis._zoom_size = 1;\n\t\t}\n\n\t\t//main section\n\t\tif (this._zoom_in){\n\t\t\t//hours and minutes\n\t\t\theight = this._reserve_box_height/6;\n\t\t\tvar timeColNum = 6;\n\t\t\tvar timeFormat = this._calendarTime||i18n.timeFormat;\n\t\t\tvar enLocale = timeFormat.match(/%([a,A])/);\n\t\t\tif(enLocale)\n\t\t\t\ttimeColNum++;\n\t\t\twidth = parseInt((this._reserve_box_width-3)/timeColNum,10);\n\t\t\tsqSize = Math.min(width,height);\n\n\t\t\thtml += \"
\"+this._timeHeaderTemplate(width,enLocale)+\"
\";\n\t\t\thtml += \"
\";\n\n\t\t\t// check and change blocked selected time\n\t\t\tthis._correctBlockedTime();\n\n\t\t\thtml += \"
\";\n\t\t\tselected = config.date.getHours();\n\t\t\ttemp = DateHelper.copy(config.date);\n\n\t\t\tfor (i= 0; i< 24; i++){\n\t\t\t\tcss=\"\";\n\t\t\t\tif(enLocale){\n\t\t\t\t\tif(i%4===0){\n\t\t\t\t\t\tvar label = (!i ? i18n.am[0] : (i==12?i18n.pm[0]:\"\"));\n\t\t\t\t\t\thtml += \"
\"+label+\"
\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(this._zoom_logic[-1]._isBlocked.call(this,i)){\n\t\t\t\t\tcss += \" webix_cal_day_disabled\";\n\t\t\t\t}\n\t\t\t\telse if(selected == i)\n\t\t\t\t\tcss += \" webix_selected\";\n\n\t\t\t\t\n\t\t\t\ttemp.setHours(i);\n\n\t\t\t\thtml += \"
\"+DateHelper.toFixed(enLocale?(!i||i==12?12:i%12):i)+\"
\";\n\t\t\t}\n\t\t\thtml += \"
\";\n\n\t\t\thtml += \"
\";\n\t\t\tselected = config.date.getMinutes();\n\t\t\ttemp = DateHelper.copy(config.date);\n\n\n\t\t\tfor (i=0; i<60; i+=config.minuteStep){\n\t\t\t\tcss = \"\";\n\t\t\t\tif(this._zoom_logic[-2]._isBlocked.call(this,i)){\n\t\t\t\t\tcss = \" webix_cal_day_disabled\";\n\t\t\t\t}\n\t\t\t\telse if(selected == i)\n\t\t\t\t\tcss = \" webix_selected\";\n\n\t\t\t\ttemp.setMinutes(i);\n\n\t\t\t\thtml += \"
\"+DateHelper.toFixed(i)+\"
\";\n\t\t\t}\n\t\t\thtml += \"
\";\n\n\t\t\thtml += \"
\";\n\t\t\thtml += \"\";\n\t\t\tthis._contentobj.innerHTML = html;\n\t\t\tthis._contentobj.firstChild.style.marginTop = cpad;\n\t\t} else {\n\t\t\t//years and months\n\n\t\t\t//reset header\n\t\t\tif (config.monthHeader){\n\t\t\t\tconst header = sections[0].childNodes;\n\t\t\t\tconst title = zlogic._getTitle(config.date, this);\n\t\t\t\tif (header[0].innerHTML != title) header[0].innerHTML = title;\n\n\t\t\t\tif (config.navigation){\n\t\t\t\t\tconst labels = i18n.aria[\"nav\"+(this._zoom_level==1?\"Year\":\"Decade\")];\n\t\t\t\t\theader[1].setAttribute(\"aria-label\", labels[0]);\n\t\t\t\t\theader[2].setAttribute(\"aria-label\", labels[1]);\n\t\t\t\t}\n\t\t\t} else\t//needed for \"year\" to set start value\n\t\t\t\tzlogic._getTitle(config.date, this);\n\n\t\t\theight = Math.floor(this._reserve_box_height/3);\n\t\t\twidth = Math.floor(this._reserve_box_width/4);\n\t\t\tsqSize = Math.min(height, width);\n\n\t\t\tselected = (this._zoom_level === 1) ? config.date.getMonth() : config.date.getFullYear() - this._zoom_start_date;\n\t\t\tfor (i=0; i<12; i++){\n\t\t\t\tcss = \"\";\n\t\t\t\tif (zlogic._isBlocked.call(this, i)) {\n\t\t\t\t\tcss = \" webix_cal_day_disabled\";\n\t\t\t\t}\n\t\t\t\telse if(selected == i)\n\t\t\t\t\tcss = \" webix_selected\";\n\n\t\t\t\tvar format = i18n.aria[(this._zoom_level==1?\"month\":\"year\")+\"Format\"];\n\t\t\t\thtml+=\"
\"+zlogic._getContent(i, this)+\"
\";\n\t\t\t}\n\t\t\tif (config.weekHeader){\n\t\t\t\tsections[index-1].style.display = \"none\";\n\t\t\t\tif (index === 1) sections[index].style.marginTop = cpad;\n\t\t\t}\n\t\t\tsections[index].innerHTML = \"
\" + html + \"
\";\n\t\t\tif (type != \"year\" && type != \"month\"){\n\t\t\t\tif(!sections[index+1])\n\t\t\t\t\tthis._contentobj.innerHTML += \"\";\n\t\t\t\telse\n\t\t\t\t\tsections[index+1].innerHTML = this._timeButtonsTemplate();\n\t\t\t} else if (sections[index+1]){\n\t\t\t\tsections[index+1].style.display = \"none\";\n\t\t\t}\n\t\t\tsections[index].style.height = this._reserve_box_height+\"px\";\n\t\t}\n\t},\n\t_getCalSizesString: function(width,height){\n\t\treturn \"width:\"+width+\"px; height:\"+height+\"px; line-height:\"+height+\"px;\";\n\t},\n\t_timeButtonsTemplate: function(){\n\t\treturn \"\";\n\t},\n\t_timeHeaderTemplate: function(width,enLocale){\n\t\tvar w1 = width*(enLocale?5:4);\n\t\tvar w2 = width*2;\n\t\treturn \"
\"+i18n.calendar.hours+\"
\"+i18n.calendar.minutes+\"
\";\n\t},\n\t_changeZoomLevel: function(zoom,date){\n\t\tvar oldzoom = this._zoom_level;\n\t\tif(this.callEvent(\"onBeforeZoom\",[zoom, oldzoom])){\n\t\t\tthis._zoom_level = zoom;\n\n\t\t\tif(zoom)\n\t\t\t\tthis._update_zoom_level(date);\n\t\t\telse\n\t\t\t\tthis.showCalendar(date);\n\t\t\tthis.callEvent(\"onAfterZoom\",[zoom, oldzoom]);\n\t\t}\n\t},\n\t_correctDate:function(date){\n\t\tif(this._zoom_logic[this._zoom_level]._correctDate && !this._checkDate(date))\n\t\t\tdate = this._zoom_logic[this._zoom_level]._correctDate(date,this);\n\t\treturn date;\n\t},\n\t_mode_selected:function(target, config){\n\t\tvar next = this._locate_date(target);\n\t\tvar zoom = this._zoom_level-(this._fixed?0:1);\n\n\t\tnext = this._correctDate(next);\n\t\tif(this._checkDate(next)){\n\t\t\tthis._changeZoomLevel(zoom, next);\n\t\t\tvar type = this._settings.type;\n\t\t\tif(type == \"month\" || type == \"year\")\n\t\t\t\tthis._selectDate(next, false, config);\n\t\t}\n\t},\n\t// selects date and redraw calendar\n\t_selectDate: function(date, add, config){\n\t\tif(this.callEvent(\"onBeforeDateSelect\", [date])){\n\t\t\tthis.selectDate(date, true, add, config);\n\t\t\tthis.callEvent(\"onAfterDateSelect\", [date]);\n\t\t}\n\t},\n\t_locate_day:function(target, ind){\n\t\tconst cind = index(target) - (this._settings.weekNumber?1:0);\n\t\tconst rind = index(target.parentNode);\n\t\tif (ind) return { cind, rind };\n\n\t\tconst date = DateHelper.add(this._getDateBoundaries()._start, cind + rind*7, \"day\", true);\n\t\tif (this._settings.timepicker){\n\t\t\tdate.setHours(this._settings.date.getHours());\n\t\t\tdate.setMinutes(this._settings.date.getMinutes());\n\t\t}\n\t\treturn date;\n\t},\n\t_locate_date:function(target){\n\t\tvar value = target.getAttribute(\"data-value\")*1;\n\t\tvar level = (target.className.indexOf(\"webix_cal_block_min\")!=-1?this._zoom_level-1:this._zoom_level);\n\t\tvar next = this.getVisibleDate();\n\n\t\tthis._zoom_logic[level]._setContent(next, value, this);\n\t\treturn next;\n\t},\n\ton_click:{\n\t\twebix_cal_prev_button: function(){\n\t\t\tthis._changeDate(-1);\n\t\t},\n\t\twebix_cal_next_button: function(){\n\t\t\tthis._changeDate(1);\n\t\t},\n\t\twebix_cal_day_disabled: function(){\n\t\t\treturn false;\n\t\t},\n\t\twebix_cal_outside: function(){\n\t\t\tif(!this._settings.navigation)\n\t\t\t\treturn false;\n\t\t},\n\t\twebix_cal_day: function(e, id, target){\n\t\t\tconst date = this._locate_day(target);\n\t\t\tconst ind = this._settings.multiselect ? this._locate_day(target, true) : null;\n\n\t\t\tconst add = this._settings.multiselect === \"touch\" || (e.ctrlKey || e.metaKey);\n\t\t\tthis._selectDate(date, add, \"user\");\n\n\t\t\tthis._restore_focus(\"webix_cal_day\", ind);\n\t\t},\n\t\twebix_cal_time:function(){\n\t\t\tif(this._zoom_logic[this._zoom_level-1]){\n\t\t\t\tthis._zoom_in = true;\n\t\t\t\tvar zoom = this._zoom_level - 1;\n\t\t\t\tthis._changeZoomLevel(zoom);\n\t\t\t}\n\t\t},\n\t\twebix_range_time_start:function(){\n\t\t\t$$(this._settings.master)._time_mode = \"start\";\n\t\t},\n\t\twebix_range_time_end:function(){\n\t\t\t$$(this._settings.master)._time_mode = \"end\";\n\t\t},\n\t\twebix_cal_done:function(){\n\t\t\tlet date = this.getVisibleDate();\n\t\t\tif (this._zoom_in) {\n\t\t\t\tconst start = this.getSelectedDate(true);\n\t\t\t\tif (start) {\n\t\t\t\t\tstart.setHours(date.getHours());\n\t\t\t\t\tstart.setMinutes(date.getMinutes());\n\t\t\t\t\tdate = start;\n\t\t\t\t}\n\t\t\t}\n\t\t\tdate = this._correctDate(date);\n\t\t\tthis._selectDate(date, false, \"user\");\n\t\t},\n\t\twebix_cal_month_name:function(){\n\t\t\tif (!this._settings.navigation) return;\n\n\t\t\tthis._zoom_in = false;\n\t\t\t//maximum zoom reached\n\t\t\tif (this._zoom_level == 2 || !this._settings.monthSelect) return;\n\n\t\t\tvar zoom = Math.max(this._zoom_level, 0) + 1;\n\t\t\tthis._changeZoomLevel(zoom);\n\t\t},\n\t\twebix_cal_block:function(e, id, trg){\n\t\t\tif (this._zoom_in){\n\t\t\t\tif (trg.className.indexOf(\"webix_cal_day_disabled\") !== -1)\n\t\t\t\t\treturn false;\n\n\t\t\t\tconst next = this._locate_date(trg);\n\t\t\t\tthis._update_zoom_level(next);\n\n\t\t\t\tlet css = \"webix_cal_block\";\n\t\t\t\tif (trg.className.indexOf(\"webix_cal_block_min\") !== -1)\n\t\t\t\t\tcss = \"webix_cal_block_min\";\n\t\t\t\tthis._restore_focus(css);\n\t\t\t} else {\n\t\t\t\tif (trg.className.indexOf(\"webix_cal_day_disabled\") == -1)\n\t\t\t\t\tthis._mode_selected(trg, \"user\");\n\t\t\t}\n\t\t}\n\t},\n\t_string_to_date: function(date, format){\n\t\tif (!date)\n\t\t\treturn DateHelper.datePart(new Date());\n\n\t\tif (typeof date == \"string\"){\n\t\t\tif (format)\n\t\t\t\tdate = DateHelper.strToDate(format)(date);\n\t\t\telse\n\t\t\t\tdate = i18n.parseFormatDate(date);\n\t\t}\n\t\treturn date;\n\t},\n\t_checkDate: function(date){\n\t\tconst blockedDate = this._isDateBlocked(date);\n\t\tconst minDate = this._settings.minDate;\n\t\tconst maxDate = this._settings.maxDate;\n\t\tconst outOfRange = (minDate && date < minDate) || (maxDate && date >= DateHelper.add(maxDate, 1, \"day\", true));\n\t\treturn !blockedDate && !outOfRange;\n\t},\n\t_isDateBlocked: function(date, zoom){\n\t\tconst blockDates = this._settings.blockDates;\n\t\tlet blocked = (blockDates && blockDates.call(this, date));\n\t\tif(blocked && zoom){\n\t\t\tconst d = DateHelper.copy(date);\n\t\t\tconst method = zoom == 1? \"getMonth\" : \"getFullYear\";\n\t\t\td.setDate(1);\n\t\t\twhile(blocked && d[method]() == date[method]()){\n\t\t\t\tblocked = blockDates.call(this, d);\n\t\t\t\tDateHelper.add(d, 1, \"day\");\n\t\t\t}\n\t\t}\n\t\treturn blocked;\n\t},\n\t_findActive:function(date, mode){\n\t\tvar dir = (mode === \"top\" || mode === \"left\" || mode === \"pgup\" || mode === \"up\") ? -1 : 1;\n\t\tvar newdate = DateHelper.add(date, dir, \"day\", true);\n\t\tif (this._checkDate(newdate))\n\t\t\treturn newdate;\n\t\telse {\n\t\t\tvar compare;\n\t\t\tif(this._zoom_level === 0) compare = (date.getMonth() === newdate.getMonth());\n\t\t\telse if(this._zoom_level === 1 ) compare = (date.getFullYear() === newdate.getFullYear());\n\t\t\telse if(this._zoom_level === 2) compare = (newdate.getFullYear() > this._zoom_start_date && newdate.getFullYear() < this._zoom_start_date+10);\n\n\t\t\tif(compare)\n\t\t\t\treturn this._findActive(newdate, mode);\n\t\t}\n\t},\n\tshowCalendar: function(date) {\n\t\tthis.define(\"date\", date);\n\t\tthis.render();\n\t\tthis.resize();\n\t},\n\t_selectedDay: function(day){\n\t\treturn day && this._selected_days[day.valueOf()];\n\t},\n\tgetSelectedDate: function(first) {\n\t\tconst result = [];\n\n\t\tconst keys = Object.keys(this._selected_days);\n\t\tconst length = first ? Math.min(1, keys.length) : keys.length;\n\t\tfor (let i=0; i this._formatValue(date, format));\n\t\t\tif(this._settings.stringResult)\n\t\t\t\tdate = date.join(this._settings.separator);\n\t\t}\n\t\telse\n\t\t\tdate = this._formatValue(date, format);\n\n\t\treturn date;\n\t},\n\t_formatValue: function(date, format){\n\t\tif (format)\n\t\t\tdate = DateHelper.dateToStr(format)(date);\n\t\telse if(this._settings.stringResult){\n\t\t\tif(this._settings.type == \"time\")\n\t\t\t\tdate = i18n.parseTimeFormatStr(date);\n\t\t\telse\n\t\t\t\tdate = i18n.parseFormatStr(date);\n\t\t}\n\t\treturn date;\n\t},\n\tselectDate: function(date, show, add, config){\n\t\tif (!date || !add || !this.config.multiselect)\n\t\t\tthis._selected_days = {};\n\n\t\tif (date){\n\t\t\tif(typeof date == \"string\")\n\t\t\t\tdate = date.split(this._settings.separator);\n\t\t\telse if (!isArray(date)) date = [date];\n\t\t\tfor (let i=0; i {\n\t\t\treturn `
`;\n\t\t},\n\t\tpalette:null,\n\t\theight:250,\n\t\twidth:260,\n\t\tcols:11,\n\t\trows:10,\n\t\tminLightness:0.15,\n\t\tmaxLightness:1,\n\t\tnavigation:true,\n\t\tgrayScale:true,\n\t\ttype:\"material\" // \"classic\"\n\t},\n\t$init:function(){\n\t\t_event(this._viewobj, \"click\", bind(function(e){\n\n\t\t\t// prevent selection the main item container\n\t\t\tconst node = e.target.parentNode;\n\t\t\tlet value = locate(node, /*@attr*/\"webix_val\");\n\t\t\t// locate can return null in case of drag\n\t\t\tif (value){\n\t\t\t\tconst oldvalue = this._settings.value;\n\t\t\t\tthis.setValue(value, \"user\");\n\n\t\t\t\t//value can be changed via setValue\n\t\t\t\tvalue = this._settings.value;\n\n\t\t\t\tthis.callEvent(\"onItemClick\", [value, e]);\n\t\t\t\tif (value != oldvalue)\n\t\t\t\t\tthis.callEvent(\"onSelect\", [value]);\n\t\t\t}\n\t\t}, this));\n\n\t\tthis.$view.setAttribute(\"role\", \"grid\");\n\t\tthis._viewobj.setAttribute(\"aria-readonly\", \"true\");\n\t},\n\t_get_clear_palette:function(){\n\t\treturn [\n\t\t\t\"#F34336\",\n\t\t\t\"#FF9700\",\n\t\t\t\"#FFEA3B\",\n\t\t\t\"#4CB050\",\n\t\t\t\"#009788\",\n\t\t\t\"#00BCD4\",\n\t\t\t\"#2196F3\",\n\t\t\t\"#3F51B5\",\n\t\t\t\"#673BB7\",\n\t\t\t\"#9C28B1\",\n\t\t\t\"#EA1E63\",\n\t\t];\n\t},\n\t_set_item_focus:function(){\n\t\tif(!this.getValue())\n\t\t\tthis.moveSelection(\"up\");\n\t},\n\t_findIndex:function(value){\n\t\tconst pal = this._settings.palette;\n\t\tvalue = (value || \"\").toUpperCase();\n\t\tfor(let r= 0, rows= pal.length; r < rows; r++)\n\t\t\tfor(let c= 0, cols = pal[r].length; c < cols; c++){\n\t\t\t\tif(pal[r][c].toUpperCase() == value){\n\t\t\t\t\treturn {row:r, col:c};\n\t\t\t\t}\n\t\t\t}\n\t\treturn null;\n\t},\n\t$setSize:function(x,y){\n\t\tif(base.api.$setSize.call(this,x,y)){\n\t\t\tthis.render();\n\t\t}\n\t},\n\tgetValue:function(){\n\t\treturn this._settings.value;\n\t},\n\t_getBox:function(){\n\t\treturn this._viewobj.firstChild;\n\t},\n\t$prepareValue:function(value){\n\t\tvalue = value ? value.toString(16) : \"\";\n\t\tif (value && value.charAt(0) != \"#\" && /^[0-9a-fA-F]+$/.test(value))\n\t\t\tvalue = \"#\" + value;\n\t\treturn value;\n\t},\n\tvalue_setter:function(value){\n\t\treturn this.$prepareValue(value);\n\t},\n\tsetValue:function(value, config){\n\t\tvalue = this.$prepareValue(value);\n\t\tconst oldvalue = this._settings.value;\n\n\t\tif (oldvalue != value){\n\t\t\tthis._settings.value = value;\n\t\t\tthis.$setValue(value);\n\t\t\tthis.callEvent(\"onChange\", [value, oldvalue, config]);\n\t\t}\n\t},\n\t$setValue:function(value){\n\t\tif(this.isVisible(this._settings.id)){\n\t\t\t// clear previous\n\t\t\tif (this._activeSelection){\n\t\t\t\tconst oldCell = this._getCell(this._activeSelection);\n\t\t\t\tthis._setSelection(oldCell, false);\n\t\t\t}\n\n\t\t\tconst ind = this._activeSelection = this._findIndex(value);\n\t\t\tif (ind){\n\t\t\t\tconst cell = this._getCell(ind);\n\t\t\t\tthis._setSelection(cell, true);\n\t\t\t}\n\t\t}\n\t},\n\t_getCell(ind){\n\t\treturn this._viewobj.lastChild.childNodes[ind.row].childNodes[ind.col];\n\t},\n\t_setSelection(cell, state){\n\t\tif (state){\n\t\t\tcell.setAttribute(\"tabindex\", \"0\");\n\t\t\tcell.setAttribute(\"aria-selected\", \"true\");\n\t\t\taddCss(cell, \"webix_color_selected\");\n\t\t} else {\n\t\t\tcell.setAttribute(\"tabindex\", \"-1\");\n\t\t\tcell.removeAttribute(\"aria-selected\");\n\t\t\tremoveCss(cell, \"webix_color_selected\");\n\t\t}\n\t},\n\t/* handle colors */\n\t_numToHex:function(n){\n\t\treturn color.toHex(n, 2);\n\t},\n\t_rgbToHex:function(r,g,b){\n\t\treturn \"#\"+this._numToHex( Math.floor(r)) +this._numToHex( Math.floor(g)) + this._numToHex(Math.floor(b));\n\t},\n\t_hslToRgb:function(h, s, l){\n\t\tlet r, g, b;\n\t\tif(!s){\n\t\t\tr = g = b = l; // achromatic\n\t\t}else{\n\t\t\tlet q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n\t\t\tlet p = 2 * l - q;\n\t\t\tr = this._hue2rgb(p, q, h + 1/3);\n\t\t\tg = this._hue2rgb(p, q, h);\n\t\t\tb = this._hue2rgb(p, q, h - 1/3);\n\t\t}\n\n\t\treturn {r:r * 255, g:g * 255, b:b * 255};\n\t},\n\t_hue2rgb:function(p, q, t){\n\t\tif(t < 0) t += 1;\n\t\tif(t > 1) t -= 1;\n\t\tif (t < 1/6)\n\t\t\treturn p + (q - p) * 6 * t; \n\t\telse if (t <= 1/2)\n\t\t\treturn q;\n\t\telse if (t < 2/3) \n\t\t\treturn p + (q - p) * (2/3 - t) * 6;\n\t\telse\n\t\t\treturn p;\n\t},\n\t_lightenRgb:function(rgb, lt){\n\t\t/*\tcolor = color * alpha + background * (1 - alpha); */\n\t\tconst r = rgb[0]*lt + 255*(1-lt);\n\t\tconst g = rgb[1]*lt + 255*(1-lt);\n\t\tconst b = rgb[2]*lt + 255*(1-lt);\n\t\treturn {r, g, b};\n\t},\n\t_getGrayScale:function(colCount){\n\t\tconst gray = [];\n\t\tlet\tval = 255,\n\t\t\tstep = val / colCount;\n\n\t\tfor(let i=0; i < colCount; i++){\n\t\t\tval = Math.round(val > 0 ? val : 0);\n\t\t\tgray.push(this._rgbToHex(val, val, val));\n\t\t\tval -= step;\n\t\t}\n\t\tgray[gray.length - 1] = \"#000000\";\n\t\treturn gray;\n\t},\n\t_initPalette:function(config){\n\t\t/* default palette (material and custom) */\n\t\tconst clearColors = this._get_clear_palette();\t\t\n\t\tconfig.cols = clearColors.length; // always use the same set\n\n\t\tconst colors = [];\n\n\t\tlet colorRows = config.rows - 1; // a row is reserved for clear colors\t\t\n\t\tlet lightStep = 1/config.rows;\n\t\tlet colorRange = null;\n\n\t\tif (this._settings.grayScale){\n\t\t\tconst grayColors = this._getGrayScale(config.cols);\n\t\t\tcolors.push(grayColors.reverse()); // inverted order\n\t\t\tlightStep = 1/colorRows;\n\t\t\tcolorRows -= 1;\n\t\t}\n\n\t\tcolors.push(clearColors);\n\n\t\tfor(let step = 0, lt = config.maxLightness; step < colorRows; step++){\n\t\t\tlt-=lightStep;\n\t\t\tcolorRange = [];\n\t\t\tfor(let col = 0; col < config.cols; col++ ){\n\t\t\t\tconst clearRgb = color.toRgb(clearColors[col]);\n\t\t\t\tconst val = this._lightenRgb(clearRgb, lt);\n\t\t\t\tcolorRange.push(this._rgbToHex(val.r, val.g, val.b));\n\t\t\t}\n\t\t\tcolors.push(colorRange);\n\t\t}\n\t\tthis._settings.palette = colors;\n\t},\n\t_initOldPalette:function(config){\n\t\t/* old (classic) palette */\n\t\tconst colors = [];\n\t\tconst colorStep = 1/config.cols;\n\n\t\tlet colorRows = config.rows;\n\t\tlet colorRange = null;\n\n\t\tif (this._settings.grayScale){\n\t\t\tcolors.push(this._getGrayScale(config.cols));\n\t\t\tcolorRows -= 1;\n\t\t}\n\n\t\tlet lightStep = (config.maxLightness - config.minLightness)/colorRows;\n\n\t\tfor(let step = 0, lt = config.minLightness; step < colorRows; step++){\n\t\t\tcolorRange = [];\n\t\t\tfor(let c = 0, col = 0; c < config.cols; c++ ){\n\t\t\t\tconst val = this._hslToRgb(col, 1, lt );\n\t\t\t\tcolorRange.push(this._rgbToHex(val.r, val.g, val.b));\n\t\t\t\tcol += colorStep;\n\t\t\t}\n\t\t\tcolors.push(colorRange);\n\t\t\tlt+=lightStep;\n\t\t}\n\n\t\tthis._settings.palette = colors;\n\t},\n\tmoveSelection:function(mode, details, focus){\n\t\tlet value = this.getValue(), ind, cell;\n\n\t\tif(value) ind = this._findIndex(value);\n\t\tif(!ind) ind = {row:0, col:0};\n\n\t\tif(ind){\n\t\t\tif(mode == \"up\" || mode == \"down\")\n\t\t\t\tind.row = ind.row + (mode == \"up\"?-1:1);\n\t\t\telse if(mode == \"right\" || mode == \"left\")\n\t\t\t\tind.col = ind.col +(mode == \"right\"?1:-1);\n\t\t\telse if(mode == \"top\" )\n\t\t\t\tind.row = ind.col = 0;\n\t\t\telse if(mode == \"bottom\"){\n\t\t\t\tind.row = this._viewobj.lastChild.querySelectorAll(\".webix_color_row\").length-1;\n\t\t\t\tind.col = this._viewobj.lastChild.childNodes[ind.row].childNodes.length-1;\n\t\t\t}\n\t\t\tind.row = Math.max(ind.row, 0);\n\t\t\tif(ind.row>=0){\n\t\t\t\t// check if this is a last row\n\t\t\t\tconst row = this._viewobj.lastChild.childNodes[ind.row];\n\t\t\t\tif (row) cell = row.childNodes[ind.col];\n\t\t\t}\n\t\t\tif(cell){\n\t\t\t\tvalue = cell.getAttribute(/*@attr*/\"webix_val\");\n\t\t\t\tconst config = (details && details.e instanceof KeyboardEvent) ? \"user\" : \"auto\";\n\t\t\t\tthis.setValue(value, config);\n\t\t\t\tthis.callEvent(\"onSelect\", [this._settings.value]);\n\n\t\t\t\tif(focus !== false){\n\t\t\t\t\tconst sel = this._viewobj.querySelector(\"div[tabindex='0']\");\n\t\t\t\t\tif(sel) sel.focus();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t_renderRow:function(row, widths, height){\n\t\tconst data = {width: 0, height:0, val:0};\n\t\tlet rowHtml = \"
\";\n\n\t\tfor(let cell = 0; cell < row.length; cell++){\n\t\t\tdata.width = widths[cell];\n\t\t\tdata.height = height;\n\t\t\tdata.val = row[cell];\n\t\t\trowHtml += this._renderItem(data);\n\t\t}\n\t\trowHtml += \"
\";\n\t\treturn rowHtml;\n\t},\n\t_renderItem:function(obj){\n\t\tconst colorTemplate = template(this._settings.template||\"\");\n\t\treturn `
${colorTemplate(obj)}
`;\n\t},\n\trender:function(){\n\t\tif(!this.isVisible(this._settings.id))\n\t\t\treturn;\n\n\t\tconst type = this._settings.type;\n\t\tif(!this._settings.palette){\n\t\t\tif (type === \"classic\")\n\t\t\t\tthis._initOldPalette(this._settings);\n\t\t\telse \n\t\t\t\tthis._initPalette(this._settings);\n\t\t}\n\t\tconst palette = this._settings.palette;\n\n\t\tthis.callEvent(\"onBeforeRender\",[]);\n\t\tconst padding = type === \"classic\" ? 0 : $active.colorPadding;\n\t\tconst single = typeof palette[0] == \"object\";\n\t\tconst firstRow = single ? palette[0] : palette;\n\n\t\tconst deltaWidth = padding*2 + padding*(firstRow.length-1);\n\t\tconst deltaHeight = padding*2 + padding*(single ? palette.length-1 : 0);\n\n\t\tlet width = this.$width - deltaWidth,\n\t\t\theight = this.$height - deltaHeight,\n\t\t\twidths = [];\n\n\t\tlet html = `
`;\n\t\t\n\t\tfor(let i=0; i < firstRow.length; i++){\n\t\t\twidths[i] = Math.floor(width/(firstRow.length - i));\n\t\t\twidth -= widths[i];\n\t\t}\n\n\t\tif(typeof palette[0] == \"object\"){\n\t\t\tfor(let r=0; r < palette.length; r++){\n\t\t\t\tconst cellHeight = Math.floor(height/(palette.length - r));\n\t\t\t\theight -= cellHeight;\n\t\t\t\tconst row = palette[r];\n\t\t\t\thtml += this._renderRow(row, widths, cellHeight);\n\t\t\t}\n\t\t} else\n\t\t\thtml += this._renderRow(palette, widths, height);\n\t\thtml += \"
\";\n\n\t\tthis._viewobj.innerHTML = html;\n\n\t\tif(this._settings.value)\n\t\t\tthis.$setValue(this._settings.value);\n\t\telse\n\t\t\tthis._viewobj.lastChild.childNodes[0].childNodes[0].setAttribute(\"tabindex\", \"0\");\n\n\t\tthis._fix_cover();\n\t\tthis.callEvent(\"onAfterRender\",[]);\n\t},\n\trefresh:function(){ this.render(); }\n};\n\nconst view = protoUI(api, KeysNavigation, base.view, EventSystem);\nexport default {api, view};","import {pos as getPos, addCss, removeCss, offset, preventEvent} from \"../webix/html\";\nimport {protoUI} from \"../ui/core\";\nimport {_event, event, eventRemove} from \"../webix/htmlevents\";\nimport {$active} from \"../webix/skin\";\nimport i18n from \"../webix/i18n\";\nimport env from \"../webix/env\";\n\nimport color from \"../webix/color\";\n\nimport EventSystem from \"../core/eventsystem\";\nimport base from \"../views/view\";\n\nconst api = {\n\tname:\"colorselect\",\n\tdefaults:{\n\t\twidth: 260,\n\t\theight: 250,\n\t\tvalue:\"#751FE0\"\n\t},\n\t$init:function(){\n\t\tthis._hValue = this._sValue = this._vValue = 0;\n\n\t\t_event(this.$view, \"keydown\", (e) => this._handle_move_keyboard(e));\n\t\tthis.attachEvent(\"onAfterRender\", function(){\n\t\t\t_event(this._colorBlock, env.mouse.down, (e) => this._handle_dnd(e, \"mouse\"));\n\t\t\t_event(this._colorLine, env.mouse.down, (e) => this._handle_dnd(e, \"mouse\", true));\n\t\t\tif (env.touch) {\n\t\t\t\t_event(this._colorBlock, env.touch.down, (e) => this._handle_dnd(e, \"touch\"));\n\t\t\t\t_event(this._colorLine, env.touch.down, (e) => this._handle_dnd(e, \"touch\", true));\n\t\t\t}\n\t\t\t_event(this._colorOutText, \"change\", () => this.setValue(this._colorOutText.value, \"user\"));\n\t\t\tif (this._settings.button)\n\t\t\t\t_event(this._viewobj.querySelector(\".webix_button\"), \"click\", () => {\n\t\t\t\t\tthis.callEvent(\"onColorSelect\", [this.getValue()]);\n\t\t\t\t});\n\t\t});\n\t\tthis.attachEvent(\"onDestruct\", function(){\n\t\t\tthis._colorCircle = this._colorLineCircle = this._colorBlock = null;\n\t\t\tthis._colorLine = this._colorOutText = this._colorOutBlock = this._offset = null;\n\t\t});\n\t},\n\t$skin:function(){\n\t\tthis._inpHeight = $active.inputHeight - 2*$active.inputPadding;\n\t},\n\t$setSize:function(x,y){\n\t\tif(base.api.$setSize.call(this,x,y)){\n\t\t\tthis.render();\n\t\t}\n\t},\n\tgetValue:function(){\n\t\treturn this._settings.value;\n\t},\n\t$prepareValue:function(value){\n\t\tvalue = value ? value.toString(16) : \"\";\n\t\tif (value && value.charAt(0) != \"#\" && /^[0-9a-fA-F]+$/.test(value))\n\t\t\tvalue = \"#\" + value;\n\t\treturn value;\n\t},\n\tvalue_setter:function(value){\n\t\treturn this.$prepareValue(value);\n\t},\n\tsetValue:function(value, config){\n\t\tvalue = this.$prepareValue(value);\n\t\tconst oldvalue = this._settings.value;\n\n\t\tif (oldvalue != value){\n\t\t\tthis._settings.value = value;\n\t\t\tthis.$setValue(value);\n\t\t\tthis.callEvent(\"onChange\", [value, oldvalue, config]);\n\t\t}\n\t},\n\t$setValue:function(value){\n\t\tif(this.isVisible(this._settings.id)){\n\t\t\tconst rgb = color.toRgb(value);\n\n\t\t\tif(value !==this._current_value){//set by API\n\t\t\t\tconst hsv = color.rgbToHsv(...rgb);\n\t\t\t\tthis._hValue = hsv[0];\n\t\t\t\tthis._sValue = hsv[1];\n\t\t\t\tthis._vValue = hsv[2];\n\t\t\t}\n\n\t\t\tconst left = (this._hValue*this._offset.width)/359;\n\t\t\tthis._colorLineCircle.style.left = left+\"px\";\n\n\t\t\tconst x = this._sValue*(this._offset.width);\n\t\t\tconst y = Math.abs((this._offset.height)*(this._vValue-1));\n\n\t\t\tthis._colorCircle.style.left = Math.max(Math.min(x, this._offset.width), 0)+\"px\";\n\t\t\tthis._colorCircle.style.top = Math.max(Math.min(y, this._offset.height), 0)+\"px\";\n\n\t\t\tthis._colorCircle.setAttribute(\"aria-valuetext\", value);\n\t\t\tthis._colorLineCircle.setAttribute(\"aria-valuetext\", value);\n\n\t\t\tthis._setOutColors(rgb, value);\n\t\t\tthis._setBlockColors();\n\t\t}\n\t},\n\t_setOutColors:function(rgb, hex){\n\t\tif(!rgb) rgb = color.hsvToRgb(this._hValue, this._sValue, this._vValue);\n\t\tif(!hex) hex = \"#\"+color.rgbToHex(rgb);\n\n\t\tconst bgColor = `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;\n\t\tthis._colorCircle.style.backgroundColor = bgColor;\n\t\tthis._colorOutBlock.style.backgroundColor = bgColor;\n\t\tthis._colorOutText.value = hex.toUpperCase();\n\n\t\tthis._current_value = hex;\n\t},\n\t_setBlockColors:function(){\n\t\tconst rgb = color.hsvToRgb(this._hValue, 1, 1);\n\t\tconst rgbStr = `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;\n\t\tthis._colorLineCircle.style.backgroundColor = rgbStr;\n\t\tthis._colorBlock.style.backgroundColor = rgbStr;\n\t},\n\n\t// dragging to set value\n\t_move_block:function(e){\n\t\tconst pos = getPos(e);\n\n\t\tlet x = pos.x - this._offset.x;\n\t\tlet y = pos.y - this._offset.y;\n\n\t\tx = Math.max(Math.min(x, this._offset.width), 0);\n\t\ty = Math.max(Math.min(y, this._offset.height), 0);\n\n\t\tthis._colorCircle.style.left = x+\"px\";\n\t\tthis._colorCircle.style.top = y+\"px\";\n\n\t\tconst pxX = (this._offset.width)/100;\n\t\tconst pxY = (this._offset.height)/100;\n\n\t\tconst s = Math.ceil(x/pxX)/100;\n\t\tconst v = Math.ceil(Math.abs(y/pxY-100))/100;\n\n\t\tthis._sValue = s;\n\t\tthis._vValue = v;\n\n\t\tthis._setOutColors();\n\t},\n\t_move_line:function(e){\n\t\tconst pos = getPos(e);\n\n\t\tlet x = pos.x - this._offset.x;\n\t\tx = Math.max(Math.min(x, this._offset.width), 0);\n\n\t\tthis._colorLineCircle.style.left = x+\"px\";\n\n\t\tconst h = Math.round(x*359/this._offset.width);\n\t\tthis._hValue = Math.max(Math.min(h, 359), 0);\n\n\t\tthis._setOutColors();\n\t\tthis._setBlockColors();\n\t},\n\t_handle_dnd:function(e, pointer, line){\n\t\tthis._offset = offset(this._colorBlock);\n\n\t\tif (line){\n\t\t\taddCss(this._colorLine, \"webix_color_area_active\");\n\t\t\tthis._move_line(e);\n\t\t} else {\n\t\t\taddCss(this._colorBlock, \"webix_color_area_active\");\n\t\t\tthis._move_block(e);\n\t\t}\n\n\t\tconst passive = (pointer === \"touch\") ? { passive:false } : null;\n\t\tthis._handle_drag_events = [\n\t\t\tevent(document.body, env[pointer].move, e => this._handle_move_process(e, pointer, line), passive),\n\t\t\tevent(document, env[pointer].up, () => this._handle_move_stop(line))\n\t\t];\n\t\taddCss(document.body,\"webix_noselect\");\n\t},\n\t_handle_move_process:function(e, pointer, line){\n\t\tif (line) this._move_line(e);\n\t\telse this._move_block(e);\n\n\t\tif (pointer === \"touch\") preventEvent(e);\n\t},\n\t_handle_move_stop:function(line){\n\t\t//detach event handlers\n\t\teventRemove(this._handle_drag_events[0]);\n\t\teventRemove(this._handle_drag_events[1]);\n\t\tthis._handle_drag_events = null;\n\n\t\tthis.setValue(this._current_value, \"user\");\n\n\t\tif (line){\n\t\t\tremoveCss(this._colorLine, \"webix_color_area_active\");\n\t\t\tthis._colorLineCircle.focus();\n\t\t} else {\n\t\t\tremoveCss(this._colorBlock, \"webix_color_area_active\");\n\t\t\tthis._colorCircle.focus();\n\t\t}\n\t\tremoveCss(document.body, \"webix_noselect\");\n\t},\n\t_move_block_value(val, inc){\n\t\treturn Math.min(Math.max(val+inc/100, 0), 1);\n\t},\n\t_move_line_value(val, inc){\n\t\treturn Math.min(Math.max(val+inc, 0), 359);\n\t},\n\t_handle_move_keyboard:function(e){\n\t\tconst code = e.which || e.keyCode;\n\n\t\tif(code>32 && code <41){\n\t\t\tconst match = /webix_color_(\\w*)circle/.exec(e.target.className);\n\t\t\tif(!match) return;\n\t\t\tpreventEvent(e);\n\n\t\t\tif(match[1].length){ //line\n\t\t\t\tif(code === 36) this._hValue = 0;\n\t\t\t\telse if(code === 35) this._hValue = 359;\n\t\t\t\telse{\n\t\t\t\t\tlet inc = (code === 37 || code === 40 || code === 34) ? -1 : 1;\n\t\t\t\t\tthis._hValue = this._move_line_value(this._hValue, inc);\n\t\t\t\t}\n\t\t\t\tthis._setBlockColors();\n\t\t\t} else {\n\t\t\t\tif(code === 36){\n\t\t\t\t\tthis._sValue = 0;\n\t\t\t\t\tthis._vValue = 1;\n\t\t\t\t}\n\t\t\t\telse if(code === 35) \n\t\t\t\t\tthis._sValue = this._vValue = 1;\n\t\t\t\telse if(code === 39 || code === 37){\n\t\t\t\t\tlet inc = code === 39 ? 1: -1;\n\t\t\t\t\tthis._sValue = this._move_block_value(this._sValue, inc);\n\t\t\t\t}\n\t\t\t\telse{\n\t\t\t\t\tlet inc = (code === 33 || code === 38) ? 1 : -1;\n\t\t\t\t\tthis._vValue = this._move_block_value(this._vValue, inc);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._setOutColors();\n\n\t\t\t//paint value, black colors may have a bigger step\n\t\t\tif(this._settings.value == this._current_value)\n\t\t\t\tthis.$setValue(this._current_value);\n\t\t\telse\n\t\t\t\tthis.setValue(this._current_value, \"user\");\n\t\t}\n\t},\n\tmoveSelection:function(mode){\n\t\tif(mode == \"pgup\" || mode == \"pgdown\"){ //line\n\t\t\tlet inc = mode === \"pgup\" ? -1 : 1;\n\t\t\tthis._hValue = this._move_line_value(this._hValue, inc);\n\t\t\tthis._setBlockColors();\n\t\t}\n\t\telse if(mode !=\"top\" && mode !==\"bottom\"){\n\t\t\tlet inc = (mode == \"up\" || mode == \"right\") ? 1 : -1;\n\t\t\tif(mode == \"down\" || mode == \"up\")\n\t\t\t\tthis._vValue = this._move_block_value(this._vValue, inc);\n\t\t\telse\n\t\t\t\tthis._sValue = this._move_block_value(this._sValue, inc);\n\t\t}\n\t\tthis._setOutColors();\n\t\tthis.setValue(this._current_value, \"auto\");\n\t},\n\trender:function(){\n\t\tif(!this.isVisible(this._settings.id))\n\t\t\treturn;\n\n\t\tthis.callEvent(\"onBeforeRender\",[]);\n\n\t\tconst inpWidth = (this.$width - $active.dataPadding*3)/2;\n\t\t//8+14 color line, 3(or 4) data paddings \n\t\tconst bHeight = this.$height - 3*$active.dataPadding - 22 - this._inpHeight - (this._settings.button ? (this._inpHeight+$active.dataPadding) : 0);\n\n\t\tlet html = \"
\";\n\t\thtml += `\n\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\n\t\t\t
\n\t\t`;\n\n\t\tif(this._settings.button)\n\t\t\thtml += `
`;\n\t\thtml += \"
\";\n\n\t\tthis._viewobj.innerHTML = html;\n\n\t\tthis._collect_vars();\n\t\tthis.$setValue(this._settings.value);\n\n\t\tthis._fix_cover();\n\t\tthis.callEvent(\"onAfterRender\",[]);\n\t},\n\t_collect_vars:function(){\n\t\tthis._colorCircle = this._viewobj.querySelector(\".webix_color_circle\");\n\t\tthis._colorLineCircle = this._viewobj.querySelector(\".webix_color_line_circle\");\n\t\tthis._colorBlock = this._viewobj.querySelector(\".webix_color_block\");\n\t\tthis._colorLine = this._viewobj.querySelector(\".webix_color_line\");\n\t\tthis._colorOutText = this._viewobj.querySelector(\".webix_color_out_text\");\n\t\tthis._colorOutBlock = this._viewobj.querySelector(\".webix_color_out_block\");\n\n\t\tthis._offset = offset(this._colorBlock);\n\t},\n\trefresh:function(){ this.render(); }\n};\n\nconst view = protoUI(api, base.view, EventSystem);\nexport default {api, view};","import {triggerEvent, preventEvent, getTextSize, locate} from \"../webix/html\";\nimport {protoUI, ui} from \"../ui/core\";\nimport {$active} from \"../webix/skin\";\nimport {isUndefined, isArray} from \"../webix/helpers\";\nimport {assert} from \"../webix/debug\";\nimport template from \"../webix/template\";\n\nimport baseview from \"../views/baseview\";\nimport base from \"../views/view\";\n\nimport AutoTooltip from \"../core/autotooltip\";\nimport UIManager from \"../core/uimanager\";\nimport EventSystem from \"../core/eventsystem\";\nimport AtomRender from \"../core/atomrender\";\nimport Settings from \"../core/settings\";\n\n\nconst api = {\n\tname:\"button\",\n\ttouchable:true,\n\t$skin:function(){\n\t\tthis.defaults.height = $active.buttonHeight||$active.inputHeight;\n\t},\n\tdefaults:{\n\t\ttemplate:function(obj, common){\n\t\t\tlet text = common.$renderInput(obj, common);\n\t\t\tif (obj.popup)\n\t\t\t\ttext = text.replace(\"