{"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/mini/config.js","../sources/css/skins/willow/config.js","../sources/core/touch.js","../sources/core/dragcontrol.js","../sources/views/window.js","../sources/webix/clipbuffer.js","../sources/core/customprint.js","../sources/core/customscroll.js","../sources/core/validatedata.js","../sources/load/dataprocessor.js","../sources/core/datastore.js","../sources/core/dataloader.js","../sources/core/dragitem.js","../sources/core/undo.js","../sources/webix/editors.js","../sources/core/editability.js","../sources/core/groupmethods.js","../sources/core/htmloptions.js","../sources/core/idspace.js","../sources/core/mapcollection.js","../sources/core/navigationbuttons.js","../sources/core/progressbar.js","../sources/core/selectionmodel.js","../sources/webix/color.js","../sources/core/sparklines/area.js","../sources/core/sparklines/pie.js","../sources/core/sparklines/radar.js","../sources/core/treedataloader.js","../sources/core/treerenderstack.js","../sources/core/treestore.js","../sources/core/uploaddriver.js","../sources/core/virtualrenderstack.js","../sources/webix/export/common.js","../sources/webix/export/topdf.js","../sources/webix/export/toexcel.js","../sources/core/date.js","../sources/core/number.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/fullscreen.js","../sources/i18n/es.js","../sources/i18n/fr.js","../sources/i18n/ja.js","../sources/i18n/zh.js","../sources/i18n/ru.js","../sources/views/template.js","../sources/views/accordion.js","../sources/views/accordionitem.js","../sources/views/resizer.js","../sources/views/carousel.js","../sources/views/portlet.js","../sources/views/dashboard.js","../sources/views/datalayout.js","../sources/views/fieldset.js","../sources/views/property.js","../sources/views/calendar.js","../sources/views/colorboard.js","../sources/views/colorselect.js","../sources/views/button.js","../sources/views/text.js","../sources/core/textpattern.js","../sources/views/radio.js","../sources/views/datepicker.js","../sources/views/richselect.js","../sources/views/icon.js","../sources/views/textarea.js","../sources/views/proto.js","../sources/views/multiselect.js","../sources/views/multicombo.js","../sources/views/slider.js","../sources/views/rangeslider.js","../sources/views/switch.js","../sources/views/tabbar.js","../sources/views/richtext.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}\nelse\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\tconst cellDates = isUndefined(options.cellDates) ? true : options.cellDates;\n\t\t\t/* global XLS, XLSX */\n\t\t\tconst wb = (ext == \"xls\") ?\n\t\t\t\tXLS.read(arr.join(\"\"), {type: \"binary\", cellStyles:true, cellDates}) :\n\t\t\t\tXLSX.read(arr.join(\"\"), {type: \"binary\", cellStyles:true, cellDates});\n\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:wb.Workbook?(wb.Workbook.Names ||[]):[],\n\t\t\t\tstates: wb.Workbook.Sheets.map(s => [\"visible\", \"hidden\", \"veryHidden\"][s.Hidden])\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 = state._global_scope;\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;\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;\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\tvar 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\t\t\tvar 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:36,\t\t\t//!!!Set the same in skin.less!!!\n\ttabbarHeight: 34,\n\tsidebarTitleHeight: 36,\n\trowHeight:28,\n\ttoolbarHeight:36,\n\tlistItemHeight:28,\t//list, grouplist, dataview, etc.\n\tinputHeight: 30,\n\tbuttonHeight: 30,\n\tinputPadding: 3,\n\tmenuHeight: 28,\n\tlabelTopHeight: 16,\n\tpropertyItemHeight: 24,\n\tunitHeaderHeight:28,\n\ttimelineItemHeight:50,\n\n\tinputSpacing: 4,\n\tborderWidth: 1,\n\n\tsliderHandleWidth: 12,\n\tsliderPadding: 10,\n\tsliderBorder: 1,\n\tvSliderPadding:13,\n\tvSliderHeight:100,\n\tswitchHeight:22,\n\tswitchWidth:40,\n\n\t//margin - distance between cells\n\tlayoutMargin:{ space:5, wide:5, 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:5, wide:0, clean:0, head:0, line:0, toolbar:2, form:12, 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: 24,\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\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) {\n\t\t\t\t\tif (Touch._axis_y && !Touch._axis_x) {\n\t\t\t\t\t\tTouch._translate_event(\"onSwipeX\");\n\t\t\t\t\t} else if (Touch._axis_x && !Touch._axis_y) {\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\tvar temp = Touch._get_matrix(Touch._scroll_node);\n\t\t\t\tvar x = temp.e;\n\t\t\t\tvar y = temp.f;\n\t\t\t\tvar finish = Touch.config.finish;\n\n\t\t\t\tvar delta = Touch._get_delta(e);\n\t\t\t\tvar view = $$(Touch._scroll_node);\n\n\t\t\t\tvar gravity = (view && view.$scroll ? view.$scroll.gravity : Touch.config.gravity);\n\t\t\t\tif (delta._time) {\n\t\t\t\t\tvar nx = x + gravity * delta._x_moment / delta._time;\n\t\t\t\t\tvar ny = y + gravity * delta._y_moment / delta._time;\n\n\t\t\t\t\tvar cnx = Touch._scroll[0] ? Touch._correct_minmax(nx, false, false, Touch._scroll_stat.dx, Touch._scroll_stat.px) : x;\n\t\t\t\t\tvar cny = Touch._scroll[1] ? Touch._correct_minmax(ny, false, false, Touch._scroll_stat.dy, Touch._scroll_stat.py) : y;\n\n\n\t\t\t\t\tvar 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\tvar result = {e: cnx, f: cny};\n\n\n\t\t\t\t\tview = $$(Touch._scroll_node);\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,Touch._scroll_end,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\tif(DragControl._active && !DragControl._touch_animation)\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.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 state from \"../core/state\";\nimport UIManager from \"../core/uimanager\";\nimport {bind, delay} from \"../webix/helpers\";\nimport {event} from \"../webix/htmlevents\";\n\n\nconst clipbuffer = {\n\n\t_area: null,\n\t_blur_id: null,\n\t_ctrl: 0,\n\n\t/*! create textarea or returns existing\n\t **/\n\tinit: function() {\n\t\t// returns existing textarea\n\t\tif (this._area !== null)\n\t\t\treturn this._area;\n\n\t\tstate.destructors.push({ obj: this });\n\t\t// creates new textarea\n\t\tthis._area = document.createElement(\"textarea\");\n\t\tthis._area.className = \"webix_clipbuffer\";\n\t\tthis._area.setAttribute(/*@attr*/\"webixignore\", 1);\n\t\tthis._area.setAttribute(\"spellcheck\", \"false\");\n\t\tthis._area.setAttribute(\"autocapitalize\", \"off\");\n\t\tthis._area.setAttribute(\"autocorrect\", \"off\");\n\t\tthis._area.setAttribute(\"autocomplete\", \"off\");\n\t\tdocument.body.appendChild(this._area);\n\n\t\tevent(document.body, \"keydown\", bind(function(e){\n\t\t\tvar key = e.which || e.keyCode;\n\t\t\tvar ctrl = !!(e.ctrlKey || e.metaKey);\n\t\t\tif (key === 86 && ctrl){\n\t\t\t\tthis._area.value = \"\";\n\t\t\t\tdelay(this._paste, this, [e], 100);\n\t\t\t}\n\t\t}, this));\n\n\t\treturn this._area;\n\t},\n\tdestructor: function(){\n\t\tthis._area = null;\n\t},\n\t/*! set text into buffer\n\t **/\n\tset: function(text) {\n\t\tthis.init();\n\t\ttext = text === \"\" ? \"\\n\" : text;\n\t\tthis._area.value = text;\n\t\tthis.focus();\n\t},\n\t/*! select text in textarea\n\t **/\n\tfocus: function() {\n\t\t// if there is native browser selection, skip focus\n\t\tif(!this._isSelectRange()){\n\t\t\tthis.init();\n\t\t\tthis._area.focus();\n\t\t\tthis._area.select();\n\t\t}\n\n\t},\n\t/*! checks document selection\n\t **/\n\t_isSelectRange: function() {\n\t\tvar text = \"\";\n\t\tif (typeof window.getSelection != \"undefined\") {\n\t\t\ttext = window.getSelection().toString();\n\t\t} else if (typeof document.selection != \"undefined\" && document.selection.type == \"Text\") {\n\t\t\ttext = document.selection.createRange().text;\n\t\t}\n\t\treturn !!text;\n\t},\n\t/*! process ctrl+V pressing\n\t **/\n\t_paste: function(e) {\n\t\tvar trg = e.target;\n\t\tif (trg === this._area) {\n\t\t\tvar text = this._area.value;\n\t\t\tvar last_active = UIManager.getFocus();\n\t\t\tif (last_active && (!last_active.getEditor || !last_active.getEditor())){\n\t\t\t\tlast_active.callEvent(\"onPaste\", [text]);\n\t\t\t\tthis._area.select();\n\t\t\t}\n\t\t}\n\t}\n};\n\nexport default clipbuffer;","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 {assert} from \"../webix/debug\";\nimport CodeParser from \"../core/codeparser\";\nimport rules from \"../webix/rules\";\n\n\n\nconst ValidateData = {\n\t$init:function(){\n\t\tif(this._events)\n\t\t\tthis.attachEvent(\"onChange\",this.clearValidation);\n\t},\n\tclearValidation:function(){\n\t\tif(this.elements){\n\t\t\tfor(var id in this.elements){\n\t\t\t\tthis._clear_invalid(id);\n\t\t\t}\n\t\t}\n\t},\n\tvalidate:function(mode, obj) {\n\t\tassert(this.callEvent, \"using validate for eventless object\");\n\t\t\n\t\tthis.callEvent(\"onBeforeValidate\", []);\n\n\t\tvar failed = this._validate_details = {};\n\n\t\t//optimistic by default :) \n\t\tvar result =true;\n\t\tvar rules = this._settings.rules;\n\t\t\n\t\tvar isHidden = this.isVisible && !this.isVisible();\n\t\tvar validateHidden = mode && mode.hidden;\n\t\tvar validateDisabled = mode && mode.disabled;\n\n\t\t//prevent validation of hidden elements\n\t\tvar elements = {}, hidden = {};\n\t\tfor(var i in this.elements){\n\t\t\tvar name = this.elements[i].config.name;\n\t\t\t//we are ignoring hidden and disabled fields during validation\n\t\t\t//if mode doesn not instruct us otherwise\n\t\t\t//if form itself is hidden, we can't separate hidden fiels,\n\t\t\t//so we will vaidate all fields\n\t\t\tif((isHidden || this.elements[i].isVisible() || validateHidden) && (this.elements[i].isEnabled() || validateDisabled))\n\t\t\t\telements[name] = this.elements[i];\n\t\t\telse{\n\t\t\t\thidden[name]=true;\n\t\t\t}\n\t\t}\n\t\tif (rules || elements)\n\t\t\tif(!obj && this.getValues)\n\t\t\t\tobj = this.getValues();\n\n\t\tif (rules){\n\t\t\t//complex rule, which may chcek all properties of object\n\t\t\tif (rules.$obj)\n\t\t\t\tresult = this._validate(rules.$obj, obj, obj, \"\") && result;\n\t\t\t\n\t\t\t//all - applied to all fields\n\t\t\tvar all = rules.$all;\n\t\t\tvar data = obj;\n\n\t\t\tif (this._settings.complexData)\n\t\t\t\tdata = CodeParser.collapseNames(obj, \"\", {}, (v) => !rules[v]);\n\n\t\t\tif (all)\n\t\t\t\tfor (let key in obj){\n\t\t\t\t\tif(hidden[key]) continue;\n\t\t\t\t\tlet subresult = this._validate(all, data[key], obj, key);\n\t\t\t\t\tif (!subresult)\n\t\t\t\t\t\tfailed[key] = true;\n\t\t\t\t\tresult = subresult && result;\n\t\t\t\t}\n\n\n\t\t\t//per-field rules\n\t\t\tfor (let key in rules){\n\t\t\t\tif(hidden[key]) continue;\n\t\t\t\tif (key.indexOf(\"$\")!==0 && !failed[key]){\n\t\t\t\t\tassert(rules[key], \"Invalid rule for:\"+key);\n\t\t\t\t\tlet subresult = this._validate(rules[key], data[key], obj, key);\n\t\t\t\t\tif (!subresult)\n\t\t\t\t\t\tfailed[key] = true;\n\t\t\t\t\tresult = subresult && result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//check personal validation rules\n\t\tif (elements){\n\t\t\tfor (var key in elements){\n\t\t\t\tif (failed[key]) continue;\n\n\t\t\t\tvar subview = elements[key];\n\t\t\t\tif (subview.validate){\n\t\t\t\t\tlet subresult = subview.validate();\n\t\t\t\t\tresult = subresult && result;\n\t\t\t\t\tif (!subresult)\n\t\t\t\t\t\tfailed[key] = true;\n\t\t\t\t} else {\n\t\t\t\t\tvar input = subview._settings;\n\t\t\t\t\tif (input){\t//ignore non webix inputs\n\t\t\t\t\t\tvar validator = input.validate;\n\t\t\t\t\t\tif (!validator && input.required)\n\t\t\t\t\t\t\tvalidator = rules.isNotEmpty;\n\n\t\t\t\t\t\tif (validator){\n\t\t\t\t\t\t\tlet subresult = this._validate(validator, obj[key], obj, key);\n\t\t\t\t\t\t\tif (!subresult)\n\t\t\t\t\t\t\t\tfailed[key] = true;\n\t\t\t\t\t\t\tresult = subresult && result;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\n\t\tthis.callEvent(\"onAfterValidation\", [result, this._validate_details]);\n\t\treturn result;\n\t},\n\t_validate:function(rule, data, obj, key){\n\t\tif (typeof rule == \"string\")\n\t\t\trule = rules[rule];\n\t\tif (rule.call(this, data, obj, key)){\n\t\t\tif(this.callEvent(\"onValidationSuccess\",[key, obj]) && this._clear_invalid)\n\t\t\t\tthis._clear_invalid(key);\n\t\t\treturn true;\n\t\t} else {\n\t\t\tif(this.callEvent(\"onValidationError\",[key, obj]) && this._mark_invalid)\n\t\t\t\tthis._mark_invalid(key);\n\t\t}\n\t\treturn false;\n\t}\n};\n\nexport default ValidateData;","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\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 undoLimit)\n\t\t\t\tthis._undoHistory.splice(0,1);\n\t\t\tif(!this._skipCursorInc)\n\t\t\t\tthis._undoCursor = this._undoHistory.length - 1;\n\t\t}\n\t},\n\tignoreUndo: function(func, master){\n\t\tthis._skipHistory = true;\n\t\tfunc.call(master||this);\n\t\tthis._skipHistory = false;\n\t},\n\tremoveUndo: function(id){\n\t\tfor( var i = this._undoHistory.length-1; i >=0; i--){\n\t\t\tif(this._undoHistory[i].id == id){\n\t\t\t\tif(this._undoHistory[i].action == \"id\"){\n\t\t\t\t\tid = this._undoHistory[i].data;\n\t\t\t\t}\n\t\t\t\tthis._undoHistory.removeAt(i);\n\t\t\t}\n\t\t}\n\t\tthis._undoCursor = this._undoHistory.length - 1;\n\t},\n\tundo: function(id){\n\t\tif(id){\n\t\t\tthis.ignoreUndo(function(){\n\t\t\t\tvar data, i;\n\t\t\t\tfor( i = this._undoHistory.length-1; !data && i >=0; i--){\n\t\t\t\t\tif(this._undoHistory[i].id == id)\n\t\t\t\t\t\tdata = this._undoHistory[i];\n\t\t\t\t}\n\n\t\t\t\tif(data){\n\t\t\t\t\t/*if(data.action == \"id\")\n\t\t\t\t\t\tid = data.data;*/\n\t\t\t\t\tthis._undoAction(data);\n\t\t\t\t\tthis._undoHistory.removeAt(i+1);\n\t\t\t\t\tthis._undoCursor = this._undoHistory.length - 1;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\telse{\n\t\t\tvar data = this._undoHistory[this._undoCursor];\n\t\t\tif(data){\n\t\t\t\tthis.ignoreUndo(function(){\n\t\t\t\t\tthis._undoAction(data);\n\t\t\t\t\tthis._undoHistory.removeAt(this._undoCursor);\n\t\t\t\t});\n\t\t\t\tthis._undoCursor--;\n\t\t\t\t/*if(data.action == \"id\")\n\t\t\t\t\tthis.undo();*/\n\t\t\t}\n\t\t}\n\t},\n\t_undoAction: function(obj){\n\t\tif(obj.action == \"delete\"){\n\t\t\tvar branch = null,\n\t\t\t\tparentId = obj.data.$parent;\n\n\t\t\tif(obj.data.$branch){\n\t\t\t\tbranch = {\n\t\t\t\t\tparent: obj.id,\n\t\t\t\t\tdata: copy(obj.data.$branch)\n\t\t\t\t};\n\t\t\t\tdelete obj.data.$branch;\n\t\t\t\tif(parentId && !this.data.pull[parentId])\n\t\t\t\t\tparentId = 0;\n\t\t\t}\n\n\t\t\tthis.add(obj.data, obj.data.$index, parentId);\n\t\t\tif(branch){\n\t\t\t\tthis.parse(branch);\n\t\t\t}\n\t\t}\n\t\telse if(obj.action == \"add\"){\n\t\t\tthis.remove(obj.id);\n\t\t}\n\t\telse if(obj.action == \"update\"){\n\t\t\tthis.updateItem(obj.id, obj.data);\n\t\t}\n\t\telse if(obj.action == \"move\"){\n\t\t\tif(obj.data.$parent){\n\t\t\t\tif(this.getItem(obj.data.$parent))\n\t\t\t\t\tthis.move(obj.id, obj.data.$index, null, {parent: obj.data.$parent});\n\t\t\t}\n\t\t\telse\n\t\t\t\tthis.move(obj.id, obj.data.$index);\n\t\t}\n\t\t/*else if(obj.action == \"id\"){\n\t\t\tthis.data.changeId(obj.id, obj.data);\n\t\t}*/\n\t}\n};\n\nexport default Undo;","import {create} from \"../webix/html\";\nimport {isArray, isUndefined, copy, toNode, delay, extend} from \"../webix/helpers\";\nimport {ui, $$} from \"../ui/core\";\nimport i18n from \"../webix/i18n\";\nimport {_event} from \"../webix/htmlevents\";\nimport {assert} from \"../webix/debug\";\nimport {callEvent} from \"../webix/customevents\";\n\nfunction init_suggest(editor, input){\n\tconst suggest = editor.config.suggest;\n\tif (suggest){\n\t\tconst box = editor.config.suggest = create_suggest(suggest);\n\t\tconst boxobj = $$(box);\n\t\tif (boxobj && input)\n\t\t\tboxobj.linkInput(input);\n\t\treturn boxobj;\n\t}\n}\n\nfunction attach_editend(suggest){\n\tif (suggest && suggest.setMasterValue && !suggest._editor_initialized){\n\t\tsuggest._editor_initialized = true;\n\t\tsuggest.attachEvent(\"onValueSuggest\", function(){\n\t\t\tdelay(()=>callEvent(\"onEditEnd\", []));\n\t\t});\n\t}\n}\n\nfunction create_suggest(config){\n\tif (typeof config == \"string\") return config;\n\tif (config.linkInput) return config._settings.id;\n\n\tif (typeof config == \"object\"){\n\t\tif (isArray(config))\n\t\t\tconfig = { data: config };\n\t\tconfig.view = config.view || \"suggest\";\n\t} else if (config === true)\n\t\tconfig = { view:\"suggest\" };\n\n\tconst obj = ui(config);\n\treturn obj.config.id;\n}\n\nfunction getLabel(config){\n\tconst text = (config.header && config.header[0]) ? config.header[0].text : config.editValue||config.label;\n\treturn (text || \"\").toString().replace(/<[^>]*>/g, \"\");\n}\n\n/*\nthis.node - html node, available after render call\nthis.config - editor config\nthis.value - original value\nthis.popup - id of popup \n*/\nconst editors = {\n\t\"text\":{\n\t\tfocus:function(){\n\t\t\tthis.getInputNode(this.node).focus();\n\t\t\tthis.getInputNode(this.node).select();\n\t\t},\n\t\tgetValue:function(){\n\t\t\treturn this.getInputNode(this.node).value;\n\t\t},\n\t\tsetValue:function(value){\n\t\t\tconst input = this.getInputNode(this.node);\n\t\t\tinput.value = value;\n\n\t\t\tconst suggest = init_suggest(this, input);\n\t\t\tattach_editend(suggest);\n\t\t},\n\t\tgetInputNode:function(){\n\t\t\treturn this.node.firstChild;\n\t\t},\n\t\trender:function(){\n\t\t\treturn create(\"div\", {\n\t\t\t\t\"class\":\"webix_dt_editor\"\n\t\t\t}, \"\");\n\t\t}\n\t},\n\t\"inline-checkbox\":{\n\t\trender:function(){ return {}; },\n\t\tgetValue:function(){\n\t\t\treturn this.node.checked;\n\t\t},\n\t\tsetValue:function(){},\n\t\tfocus:function(){\n\t\t\tthis.node.focus();\n\t\t},\n\t\tgetInputNode:function(){},\n\t\t$inline:true\n\t},\n\t\"inline-text\":{\n\t\trender:function(){ return {}; },\n\t\tgetValue:function(){\n\t\t\treturn this.node.value;\n\t\t},\n\t\tsetValue:function(){},\n\t\tfocus:function(){\n\t\t\tthis.node.focus();\n\t\t\tthis.node.select();\n\t\t},\n\t\tgetInputNode:function(){},\n\t\t$inline:true\n\t},\n\t\"checkbox\":{\n\t\tfocus:function(){\n\t\t\tthis.getInputNode().focus();\n\t\t},\n\t\tgetValue:function(){\n\t\t\treturn this.getInputNode().checked;\n\t\t},\n\t\tsetValue:function(value){\n\t\t\tthis.getInputNode().checked = !!value;\n\t\t},\n\t\tgetInputNode:function(){\n\t\t\treturn this.node.firstChild.firstChild;\n\t\t},\n\t\trender:function(){\n\t\t\treturn create(\"div\", {\n\t\t\t\t\"class\":\"webix_dt_editor\"\n\t\t\t}, \"
\");\n\t\t}\n\t},\n\t\"select\":{\n\t\tfocus:function(){\n\t\t\tthis.getInputNode().focus();\n\t\t},\n\t\tgetValue:function(){\n\t\t\treturn this.getInputNode().value;\n\t\t},\n\t\tsetValue:function(value){\n\t\t\tthis.getInputNode().value = value;\n\t\t},\n\t\tgetInputNode:function(){\n\t\t\treturn this.node.firstChild;\n\t\t},\n\t\trender:function(){\n\t\t\tlet html = \"\";\n\t\t\tconst options = this.config.options || this.config.collection;\n\t\t\tassert(options,\"options not defined for select editor\");\n\n\t\t\tif (options.data && options.data.each)\n\t\t\t\toptions.data.each(function(obj){\n\t\t\t\t\thtml +=\"\";\n\t\t\t\t});\n\t\t\telse {\n\t\t\t\tif (isArray(options)){\n\t\t\t\t\tfor (let i = 0; i < options.length; i++){\n\t\t\t\t\t\tconst rec = options[i];\n\t\t\t\t\t\tconst isplain = isUndefined(rec.id);\n\t\t\t\t\t\tconst id = isplain ? rec : rec.id;\n\t\t\t\t\t\tconst label = isplain ? rec : rec.value;\n\n\t\t\t\t\t\thtml +=\"\";\n\t\t\t\t\t}\n\t\t\t\t} else for (let key in options){\n\t\t\t\t\thtml +=\"\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn create(\"div\", {\n\t\t\t\t\"class\":\"webix_dt_editor\"\n\t\t\t}, \"\");\n\t\t}\n\t},\n\tpopup:{\n\t\tfocus:function(){\n\t\t\tthis.getInputNode().focus();\n\t\t},\n\t\tdestroy:function(){\n\t\t\tthis.getPopup().hide();\n\t\t},\n\t\tgetValue:function(){\n\t\t\treturn this.getInputNode().getValue()||\"\";\n\t\t},\n\t\tsetValue:function(value){\n\t\t\tthis.getPopup().show(this.node);\n\t\t\tthis.getInputNode().setValue(value);\n\t\t},\n\t\tgetInputNode:function(){\n\t\t\treturn this.getPopup().getChildViews()[0];\n\t\t},\n\t\tgetPopup:function(){\n\t\t\tlet id = this.config.$popup;\n\n\t\t\tif (!(id && $$(id)))\n\t\t\t\tid = this.config.$popup = this.createPopup();\n\n\t\t\treturn $$(id);\n\t\t},\n\t\tcreatePopup:function(){\n\t\t\tconst popup = this.config.popup || this.config.suggest;\n\t\t\tif (popup){\n\t\t\t\tlet pobj;\n\t\t\t\tif (typeof popup == \"object\" && !popup.name){\n\t\t\t\t\tpopup.view = popup.view || \"suggest\";\n\t\t\t\t\tpobj = ui(copy(popup));\n\t\t\t\t} else\n\t\t\t\t\tpobj = $$(popup);\n\n\t\t\t\t//custom popup may be linked already\n\t\t\t\tif(!pobj._linked){\n\t\t\t\t\tif (pobj.linkInput)\n\t\t\t\t\t\tpobj.linkInput(document.body);\n\t\t\t\t\telse if(this.linkInput)\n\t\t\t\t\t\tthis.linkInput(document.body);\n\t\t\t\t\tpobj._linked = true;\n\t\t\t\t}\n\t\t\t\tattach_editend(pobj);\n\n\t\t\t\treturn pobj;\n\t\t\t}\n\n\t\t\tconst editor = editors.$popup[this.popupType];\n\t\t\tlet popupId = editor.$popup;\n\n\t\t\tif(!(popupId && $$(popupId))){\n\t\t\t\tconst popup = ui(copy(editor));\n\t\t\t\tif(!popup.linkInput && !popupId)\n\t\t\t\t\tthis.linkInput(document.body);\n\t\t\t\teditor.$popup = popupId = popup._settings.id;\n\t\t\t\tthis.popupInit(popup);\n\t\t\t}\n\n\t\t\treturn popupId;\n\t\t},\n\t\tlinkInput:function(node){\n\t\t\t_event(toNode(node), \"keydown\", e => {\n\t\t\t\t//abort, when editor was not initialized yet\n\t\t\t\tif (!this.config.$popup) return;\n\n\t\t\t\tconst code = e.which || e.keyCode, list = this.getInputNode();\n\t\t\t\tif(!list.isVisible()) return;\n\n\t\t\t\tif(list.moveSelection && code < 41 && code > 32){\n\t\t\t\t\tlet dir;\n\t\t\t\t\tif(code == 33) dir = \"pgup\";\n\t\t\t\t\telse if(code == 34) dir = \"pgdown\";\n\t\t\t\t\telse if(code == 35) dir = \"bottom\";\n\t\t\t\t\telse if(code == 36) dir = \"top\";\n\t\t\t\t\telse if(code == 37) dir = \"left\";\n\t\t\t\t\telse if(code == 38) dir = \"up\";\n\t\t\t\t\telse if(code == 39) dir = \"right\";\n\t\t\t\t\telse if(code == 40) dir = \"down\";\n\n\t\t\t\t\tlist.moveSelection(dir);\n\t\t\t\t}\n\t\t\t\t// shift+enter support for 'popup' editor\n\t\t\t\telse if(code === 13 && ( e.target.nodeName !==\"TEXTAREA\" || !e.shiftKey))\n\t\t\t\t\tcallEvent(\"onEditEnd\", []);\n\t\t\t\n\t\t\t});\n\t\t},\n\n\t\tpopupInit:function(){},\n\t\tpopupType:\"text\",\n\t\trender:function(){ return {}; },\n\t\t$inline:true\n\t}\n};\n\neditors.color = extend({\n\tfocus:function(){},\n\tpopupType:\"color\",\n\tpopupInit:function(popup){\n\t\tpopup.getChildViews()[0].attachEvent(\"onItemClick\", function(value){\n\t\t\tcallEvent(\"onEditEnd\",[value]);\n\t\t});\n\t}\n}, editors.popup);\n\neditors.date = extend({\n\tfocus:function(){},\n\tpopupType:\"date\",\n\tsetValue:function(value){\n\t\tthis._is_string = this.config.stringResult || (value && typeof value == \"string\");\n\t\teditors.popup.setValue.call(this, value);\n\t},\n\tgetValue:function(){\n\t\treturn this.getInputNode().getValue(this._is_string?i18n.parseFormatStr:\"\")||\"\";\n\t},\n\tpopupInit:function(popup){\n\t\tpopup.getChildViews()[0].attachEvent(\"onAfterDateSelect\", function(value){\n\t\t\tcallEvent(\"onEditEnd\",[value]);\n\t\t});\n\t}\n}, editors.popup);\n\neditors.combo = extend({\n\t_create_suggest:function(config){\n\t\tlet suggest, id;\n\t\tif (this.config.popup){\n\t\t\tsuggest = this.config.popup;\n\t\t\tid = suggest.config.id;\n\t\t}\n\t\telse if (config){\n\t\t\tid = create_suggest(config);\n\t\t\tsuggest = $$(id);\n\t\t} else\n\t\t\tid = this._shared_suggest(config);\n\n\t\tattach_editend(suggest);\n\t\treturn id;\n\t},\n\t_shared_suggest:function(){\n\t\tconst e = editors.combo;\n\n\t\tif(e._suggest && $$(e._suggest))\n\t\t\treturn e._suggest;\n\n\t\treturn e._suggest = this._create_suggest(true);\n\t},\n\trender:function(){\n\t\tconst node = create(\"div\", {\n\t\t\t\"class\":\"webix_dt_editor\"\n\t\t}, \"\");\n\n\t\t//save suggest id for future reference\t\t\n\t\tconst suggest = this.config.suggest = this._create_suggest(this.config.suggest);\n\n\t\tif (suggest){\n\t\t\t$$(suggest).linkInput(node.firstChild, true);\n\t\t\t_event(node.firstChild, \"click\", () => this.showPopup());\n\t\t}\n\t\treturn node;\n\t},\n\tgetPopup:function(){\n\t\treturn $$(this.config.suggest);\n\t},\n\tshowPopup:function(){\n\t\tconst popup = this.getPopup();\n\t\tconst list = popup.getList();\n\t\tconst input = this.getInputNode();\n\t\tconst value = this._initial_value;\n\n\t\tpopup.show(input);\n\t\tinput.setAttribute(\"aria-expanded\", \"true\");\n\t\tif (value){\n\t\t\tassert(list.exists(value), \"Option with ID \"+value+\" doesn't exist\");\n\t\t\tif (list.exists(value)){\n\t\t\t\tlist.select(value);\n\t\t\t\tlist.showItem(value);\n\t\t\t}\n\t\t} else {\n\t\t\tlist.unselect();\n\t\t\tlist.showItem(list.getFirstId());\n\t\t}\n\t\tpopup._last_input_target = input;\n\t},\n\tafterRender:function(){\n\t\tthis.showPopup();\n\t},\n\tsetValue:function(value){\n\t\tthis._initial_value = value;\n\t\tif (this.config.suggest){\n\t\t\tconst sobj = $$(this.config.suggest);\n\t\t\tconst data = this.config.collection || this.config.options;\n\t\t\tif (data)\n\t\t\t\tsobj.getList().data.importData(data);\n\n\t\t\tthis.getInputNode(this.node).value = sobj.getItemText(value);\n\t\t}\n\t},\n\tgetValue:function(){\n\t\tlet value = this.getInputNode().value;\n\t\tif (this.config.suggest){\n\t\t\tconst suggest = $$(this.config.suggest),\n\t\t\t\tlist = suggest.getList();\n\t\t\tif (value || (list.getSelectedId && list.getSelectedId()))\t\n\t\t\t\tvalue = suggest.getSuggestion(value);\n\t\t}\n\t\treturn value;\n\t}\n}, editors.text);\n\neditors.richselect = extend({\n\tfocus:function(){},\n\tgetValue:function(){\n\t\treturn this.getPopup().getValue();\n\t},\n\tsetValue:function(value){\n\t\tconst suggest = this.config.collection || this.config.options;\n\t\tthis.getInputNode();\n\t\tif (suggest)\n\t\t\tthis.getPopup().getList().data.importData(suggest);\n\n\t\tthis.getPopup().show(this.node);\n\t\tthis.getPopup().setValue(value);\n\t},\n\tgetInputNode:function(){\n\t\treturn this.getPopup().getList();\n\t},\n\tpopupInit:function(popup){\n\t\tpopup.linkInput(document.body);\n\t\tattach_editend(popup);\n\t},\n\tpopupType:\"richselect\"\n}, editors.popup);\n\neditors.password = extend({\n\trender:function(){\n\t\tconst node = create(\"div\", {\n\t\t\t\"class\":\"webix_dt_editor webix_password_editor\"\n\t\t}, \"\");\n\n\t\tconst icon = node.querySelector(\".webix_icon\");\n\t\t_event(icon, \"click\", () => {\n\t\t\tthis.toggleInput();\n\t\t\tthis.getInputNode(this.node).focus();\n\t\t});\n\t\treturn node;\n\t},\n\ttoggleInput:function(){\n\t\tconst input = this.getInputNode(this.node);\n\t\tconst isPassword = input.getAttribute(\"type\") === \"password\";\n\t\tinput.setAttribute(\"type\", isPassword ? \"text\" : \"password\");\n\n\t\tconst icon = input.nextSibling;\n\t\ticon.className = `webix_icon wxi-eye${isPassword ? \"-slash\" : \"\"}`;\n\t},\n\tmasterFormat: function(value){\n\t\treturn !value && value !== 0 ? \"\" : \"•\".repeat(value.toString().length);\n\t}\n}, editors.text);\n\neditors.$popup = {\n\ttext:{\n\t\tview:\"popup\", width:250, height:150,\n\t\tbody:{ view:\"textarea\" }\n\t},\n\tcolor:{\n\t\tview:\"popup\",\n\t\tbody:{ view:\"colorboard\" }\n\t},\n\tdate:{\n\t\tview:\"popup\", width:250, height:250, padding:0,\n\t\tbody:{ view:\"calendar\", icons:true, borderless:true }\n\t},\n\trichselect:{\n\t\tview:\"suggest\",\n\t\tbody:{ view:\"list\", select:true }\n\t},\n\tmultiselect:{\n\t\tview:\"multisuggest\",\n\t\tsuggest:{\n\t\t\tbutton:true\n\t\t}\n\t}\n};\n\nexport default editors;","import {remove, removeCss, addCss} from \"../webix/html\";\nimport UIManager from \"../core/uimanager\";\nimport {extend, bind, delay, isUndefined} from \"../webix/helpers\";\nimport {ui, $$} from \"../ui/core\";\nimport {_event} from \"../webix/htmlevents\";\nimport {assert} from \"../webix/debug\";\nimport {attachEvent, callEvent, detachEvent} from \"../webix/customevents\";\nimport Undo from \"../core/undo\";\n\n\nimport globalState from \"../core/state\";\nimport editors from \"../webix/editors\";\n/*\n\tBehavior:EditAbility - enables item operation for the items\n\t\n\t@export\n\t\tedit\n\t\tstopEdit\n*/\n\nconst EditAbility ={\n\tdefaults:{\n\t\teditaction:\"click\"\n\t},\n\t$init:function(config){\n\t\tthis._editors = {};\n\t\tthis._in_edit_mode = 0;\n\t\tthis._edit_open_time = 0;\n\t\tthis._contentobj.style.position = \"relative\";\n\t\tif (config)\n\t\t\tconfig.onDblClick = config.onDblClick || {};\n\n\t\tthis.attachEvent(\"onAfterRender\", this._refocus_inline_editor);\n\n\t\t//when we call extend the editable prop can be already set\n\t\tif (this._settings.editable)\n\t\t\tthis._init_edit_events_once();\n\n\t\textend(this,Undo);\n\t},\n\t_refocus_try:function(newnode){\n\t\ttry{ //Chrome throws an error if selectionStart is not accessible\n\t\t\tif (typeof newnode.selectionStart == \"number\") {\n\t\t\t\tnewnode.selectionStart = newnode.selectionEnd = newnode.value.length;\n\t\t\t} else if (typeof newnode.createTextRange != \"undefined\") {\n\t\t\t\tvar range = newnode.createTextRange();\n\t\t\t\trange.collapse(false);\n\t\t\t\trange.select();\n\t\t\t}\n\t\t} catch(e){} // eslint-disable-line\n\t},\n\t_refocus_inline_editor:function(){\n\t\tvar editor = this.getEditor();\n\t\tif (editor && editor.$inline && !editor.getPopup){\n\t\t\tvar newnode = this._locateInput(editor);\n\t\t\tif (newnode && newnode != editor.node){\n\t\t\t\tvar text = editor.node.value;\n\t\t\t\teditor.node = newnode;\n\t\t\t\tnewnode.value = text;\n\t\t\t\tnewnode.focus();\n\n\t\t\t\tthis._refocus_try(newnode);\n\t\t\t} else \n\t\t\t\tthis.editStop();\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 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 {preventEvent, remove, create} from \"../webix/html\";\nimport {bind} from \"../webix/helpers\";\nimport {$$} from \"../ui/core\";\nimport i18n from \"../webix/i18n\";\nimport {event} from \"../webix/htmlevents\";\n\n\n/*\n UI: navigation control\n*/\nconst NavigationButtons = {\n\t$init:function(){\n\t\tthis.$ready.push(function(){\n\t\t\tthis.attachEvent(\"onKeyPress\", this._onKeyPress);\n\t\t});\n\t},\n\t_moveActive:function(code, e){\n\t\tif(code === 37 || code === 39){\n\t\t\tpreventEvent(e);\n\t\t\tthis._showNavItem(code===37?-1:1);\n\n\t\t\tvar node = this._navPanel.querySelector(\"[tabindex='0']\");\n\t\t\tif(node) node.focus();\n\t\t}\n\t},\n\t_renderPanel:function(){\n\t\tremove(this._navPanel);\n\n\n\t\tthis._navPanel = create(\"DIV\",{\n\t\t\t\"class\":\"webix_nav_panel \"+\"webix_nav_panel_\"+this._settings.navigation.type,\n\t\t\t\"role\":\"tablist\"\n\t\t},\"\");\n\n\t\tthis._viewobj.appendChild(this._navPanel);\n\n\n\t\tthis._renderNavItems();\n\t\tthis._renderNavButtons();\n\t\tthis._setLinkEventHandler();\n\t},\n\t_setLinkEventHandler: function(){\n\t\tvar h = [];\n\t\tif(this._navPanel)\n\t\t\th[0] = event(this._navPanel,\"click\", bind(function(e){\n\t\t\t\tvar elem = e.target;\n\t\t\t\tvar found = false;\n\t\t\t\twhile(elem != this._navPanel && !found){\n\t\t\t\t\tvar bindId = elem.getAttribute(this._linkAttr);\n\t\t\t\t\tif(bindId){\n\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\tthis._showPanelBind(bindId);\n\t\t\t\t\t}\n\t\t\t\t\telem = elem.parentNode;\n\t\t\t\t}\n\t\t\t},this));\n\t\tif(this._prevNavButton)\n\t\t\th[1] = event(this._prevNavButton,\"click\", bind(function(){\n\t\t\t\tthis._showNavItem(-1);\n\t\t\t},this));\n\t\tif(this._nextNavButton)\n\t\t\th[1] = event(this._nextNavButton,\"click\", bind(function(){\n\t\t\t\tthis._showNavItem(1);\n\t\t\t},this));\n\t\tthis.attachEvent(\"onDestruct\", function(){\n\t\t\tfor(var i=0;i< h.length; i++){\n\t\t\t\tthis.detachEvent(h[i]);\n\t\t\t}\n\t\t\th = null;\n\t\t});\n\t},\n\t_showNavItem: function(inc){\n\t\tif(this._cells){\n\t\t\tvar index = this._active_cell + inc;\n\t\t\tif(index >= this._cells.length || index < 0){\n\t\t\t\tindex = (index < 0?this._cells.length-1:0);\n\t\t\t}\n\t\t\tthis.setActiveIndex(index);\n\t\t}\n\t},\n\t_showPanelBind: function(id){\n\t\tif(this._cells)\n\t\t\t$$(id).show();\n\t},\n\t_renderNavItems:function(){\n\t\tvar item, config;\n\t\tconfig = this._settings.navigation;\n\t\tif(config.items){\n\t\t\tthis._linkAttr = config.linkAttr || /*@attr*/\"bind_id\";\n\n\t\t\tif(!this._navPanel)\n\t\t\t\tthis._renderPanel();\n\t\t\telse\n\t\t\t\tthis._clearPanel();\n\n\t\t\tvar data = (this._cells?this._cells:this.data.order);\n\t\t\tif(data.length>1){\n\t\t\t\tfor (var i=0; i < data.length; i++){\n\n\t\t\t\t\titem = create(\"DIV\",{\n\t\t\t\t\t\t\"class\":\"webix_nav_item webix_nav_\"+(i==this._active_cell?\"active\":\"inactive\"),\n\t\t\t\t\t\t\"role\":\"tab\",\n\t\t\t\t\t\t\"tabindex\":(i==this._active_cell?\"0\":\"-1\")\n\t\t\t\t\t});\n\t\t\t\t\tvar id = this._cells?this._cells[i]._settings.id:data[i];\n\t\t\t\t\tif(id)\n\t\t\t\t\t\titem.setAttribute(this._linkAttr, id);\n\t\t\t\t\tthis._navPanel.appendChild(item);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t_clearPanel:function(){\n\t\tif (this._navPanel){\n\t\t\tvar coll = this._navPanel.childNodes;\n\t\t\tfor (var i = coll.length - 1; i >= 0; i--)\n\t\t\t\tremove(coll[i]);\n\t\t}\n\t},\n\t_renderNavButtons: function(){\n\t\tvar config = this._settings.navigation;\n\t\tif(config.buttons){\n\n\t\t\tif(this._prevNavButton)\n\t\t\t\tremove(this._prevNavButton);\n\t\t\tif(this._prevNavButton)\n\t\t\t\tremove(this._nextNavButton);\n\n\n\t\t\tthis._prevNavButton = create(\n\t\t\t\t\"DIV\",\n\t\t\t\t{\n\t\t\t\t\t\"class\":\"webix_nav_button_\"+config.type+\" webix_nav_button_prev \"\n\t\t\t\t},\n\t\t\t\t\"
\"\n\t\t\t);\n\t\t\tthis._viewobj.appendChild(this._prevNavButton);\n\n\t\t\tthis._nextNavButton = create(\n\t\t\t\t\"DIV\",\n\t\t\t\t{\n\t\t\t\t\t\"class\":\"webix_nav_button_\"+config.type+\" webix_nav_button_next \"\n\t\t\t\t},\n\t\t\t\t\"
\"\n\t\t\t);\n\t\t\tthis._viewobj.appendChild(this._nextNavButton);\n\t\t}\n\t}\n};\n\nexport default NavigationButtons;","import {create, insertBefore, remove} from \"../webix/html\";\nimport env from \"../webix/env\";\nimport {isUndefined, extend, delay} from \"../webix/helpers\";\n\n\nconst ProgressBar = {\n\t$init:function(){\n\t\tif (isUndefined(this._progress) && this.attachEvent){\n\t\t\tthis.attachEvent(\"onBeforeLoad\", () => this.showProgress());\n\t\t\tthis.attachEvent(\"onAfterLoad\", () => this.hideProgress());\n\t\t\tthis._progress = null;\n\t\t}\n\t},\n\tshowProgress:function(config){\n\t\t// { position: 0 - 1, delay: 2000ms by default, css : name of css class to use }\n\t\tvar width;\n\t\tif (!this._progress){\n\n\t\t\tconfig = extend({\n\t\t\t\tposition:0,\n\t\t\t\tdelay: 2000,\n\t\t\t\ttype:\"icon\",\n\t\t\t\ticon:\"wxi-sync\",\n\t\t\t\thide:false\n\t\t\t}, (config||{}), true);\n\n\t\t\tvar incss = (config.type == \"icon\") ? (config.icon+\" webix_spin\") : \"\";\n\n\t\t\tthis._progress = create(\n\t\t\t\t\"DIV\",\n\t\t\t\t{\n\t\t\t\t\t\"class\":\"webix_progress_\"+config.type,\n\t\t\t\t\t\"role\":\"progressbar\",\n\t\t\t\t\t\"aria-valuemin\":\"0\",\n\t\t\t\t\t\"aria-valuemax\":\"100\",\n\t\t\t\t\t\"tabindex\":\"0\"\n\t\t\t\t},\n\t\t\t\t\"
\"\n\t\t\t);\n\n\t\t\tif(!this.setPosition)\n\t\t\t\tthis._viewobj.style.position = \"relative\";\n\n\t\t\tinsertBefore(this._progress, this._viewobj.firstChild, this._viewobj);\n\t\t\tthis._viewobj.setAttribute(\"aria-busy\", \"true\");\n\n\t\t\tif(!this._touch_scroll){\n\t\t\t\tif (this.getScrollState){\n\t\t\t\t\tvar scroll = this.getScrollState();\n\t\t\t\t\tif (this._viewobj.scrollWidth != this.$width){\n\t\t\t\t\t\tthis._progress.style.left = scroll.x +\"px\";\n\t\t\t\t\t}\n\t\t\t\t\tif (this._viewobj.scrollHeight != this.$height){\n\t\t\t\t\t\tif(config.type != \"bottom\"){\n\t\t\t\t\t\t\tthis._progress.style.top = scroll.y + \"px\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis._progress.style.top = scroll.y + this.$height - this._progress.offsetHeight +\"px\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._progress_animate = config.type != \"icon\";\n\t\t}\n\n\t\tif (!config) return;\n\n\t\tif (this._progress_animate){\n\t\t\tvar position = config.position || 1;\n\t\t\tif (config.delay){\n\t\t\t\t// force reflow\n\t\t\t\twidth = this._viewobj.firstChild.offsetWidth;\n\t\t\t\tthis._progress.firstChild.style[env.transitionDuration] = config.delay+\"ms\";\n\t\t\t}\n\n\t\t\t// animate to new value\n\t\t\tthis._progress.firstChild.style.width = position*100+\"%\";\n\t\t}\n\n\t\tif (this._progress_hide)\n\t\t\tclearTimeout(this._progress_hide);\n\n\t\tif (config.hide)\n\t\t\tthis._progress_hide = delay(this.hideProgress, this, [true], config.delay);\n\n\t\t// necessary to prevent code optimization\n\t\treturn width;\n\t},\n\thideProgress:function(now){\n\t\tif (this._progress){\n\t\t\tif (now || !this._progress_animate){\n\t\t\t\tremove(this._progress);\n\t\t\t\tthis._progress = null;\n\t\t\t\tthis._viewobj.removeAttribute(\"aria-busy\");\n\t\t\t} else {\n\t\t\t\tthis.showProgress({ position:1.1, delay:300 , hide:true });\n\t\t\t}\n\t\t}\n\t}\n};\n\nexport default ProgressBar;","import {addCss, removeCss} from \"../webix/html\";\nimport {_to_array, bind, isArray} from \"../webix/helpers\";\nimport {_event, event} from \"../webix/htmlevents\";\nimport {assert} from \"../webix/debug\";\nimport env from \"../webix/env\";\n\nimport ready from \"../webix/ready\";\nimport state from \"../core/state\";\n\n\n/*\n\tBehavior:SelectionModel - manage selection states\n\t@export\n\t\tselect\n\t\tunselect\n\t\tselectAll\n\t\tunselectAll\n\t\tisSelected\n\t\tgetSelectedId\n*/\nconst SelectionModel ={\n\t$init:function(){\n\t\t//collection of selected IDs\n\t\tthis._selected = _to_array();\n\t\tassert(this.data, \"SelectionModel :: Component doesn't have DataStore\");\n\n\t\t//remove selection from deleted items\n\t\tthis.data.attachEvent(\"onStoreUpdated\",bind(this._data_updated,this));\n\t\tthis.data.attachEvent(\"onStoreLoad\", bind(this._data_loaded,this));\n\t\tthis.data.attachEvent(\"onAfterFilter\", bind(this._data_filtered,this));\n\t\tthis.data.attachEvent(\"onSyncApply\", bind(this._select_check,this));\n\t\tthis.data.attachEvent(\"onIdChange\", bind(this._id_changed,this));\n\t\tthis.$ready.push(this._set_noselect);\n\t},\n\t_set_noselect: function(){\n\t\tif (this._settings.select==\"multiselect\" || this._settings.multiselect || this._settings.select==\"area\")\n\t\t\t_event(this.$view,\"mousedown\", function(e){\n\t\t\t\tif (e.shiftKey || (env.isIE && e.ctrlKey)){\n\t\t\t\t\tconst node = env.isIE ? document.body : this;\n\t\t\t\t\tstate._noselect_element = node;\n\t\t\t\t\taddCss(node, \"webix_noselect\", true);\n\t\t\t\t}\n\t\t\t});\n\t},\n\t_id_changed:function(oldid, newid){\n\t\tfor (var i = this._selected.length - 1; i >= 0; i--)\n\t\t\tif (this._selected[i]==oldid)\n\t\t\t\tthis._selected[i]=newid;\n\t},\n\t_data_filtered:function(){\n\t\tfor (var i = this._selected.length - 1; i >= 0; i--){\n\t\t\tif (this.data.getIndexById(this._selected[i]) < 0) {\n\t\t\t\tvar id = this._selected[i];\n\t\t\t\tthis.removeCss(id, \"webix_selected\", true);\n\t\t\t\tthis._selected.splice(i,1);\n\t\t\t\tthis.callEvent(\"onSelectChange\",[id]);\n\t\t\t}\n\t\t}\n\t},\n\t//helper - linked to onStoreUpdated\n\t_data_updated:function(id,obj,type){\n\t\tif (type == \"delete\"){\t\t\t\t//remove selection from deleted items\n\t\t\tif (this.loadBranch){\n\t\t\t\t//hierarchy, need to check all\n\t\t\t\tthis._select_check();\n\t\t\t} else{\n\t\t\t\tthis._selected.remove(id);\n\t\t\t\tthis.callEvent(\"onSelectChange\",[this._selected]);\n\t\t\t}\n\t\t}\n\t\telse if (!id && !this.data.count() && !this.data._filter_order && !this.data._filter_branch){\t//remove selection for clearAll\n\t\t\tthis._selected = _to_array();\n\t\t}\n\t},\n\t_data_loaded:function(){\n\t\tif (this._settings.select)\n\t\t\tthis.data.each(function(obj){\n\t\t\t\tif (obj && obj.$selected) this.select(obj.id);\n\t\t\t}, this);\n\t},\n\t_select_check:function(){\n\t\tlet selectionChanged;\n\t\tfor (let i = this._selected.length - 1; i >= 0; i--)\n\t\t\tif (!this.exists(this._selected[i])){\n\t\t\t\tselectionChanged = true;\n\t\t\t\tthis._selected.splice(i,1);\n\t\t\t}\n\t\tif(selectionChanged)\n\t\t\tthis.callEvent(\"onSelectChange\",[this._selected]);\n\t},\n\t//helper - changes state of selection for some item\n\t_select_mark:function(id,state,refresh,need_unselect){\n\t\tvar sname = state ? \"onBeforeSelect\" : \"onBeforeUnSelect\";\n\t\tif (!this.callEvent(sname,[id,state])) return false;\n\n\t\tif (need_unselect){\n\t\t\tthis._silent_selection = true;\n\t\t\tthis.unselectAll();\n\t\t\tthis._silent_selection = false;\n\t\t}\n\t\t\n\t\tif (state)\n\t\t\tthis.addCss(id, \"webix_selected\", true);\n\t\telse\n\t\t\tthis.removeCss(id, \"webix_selected\", true);\n\n\t\tif (refresh)\n\t\t\trefresh.push(id);\t\t\t\t//if we in the mass-select mode - collect all changed IDs\n\t\telse{\n\t\t\tif (state)\n\t\t\t\tthis._selected.push(id);\t\t//then add to list of selected items\n\t\t\telse\n\t\t\t\tthis._selected.remove(id);\n\t\t\tthis._refresh_selection(id);\t//othervise trigger repainting\n\t\t}\n\n\t\tvar ename = state ? \"onAfterSelect\" : \"onAfterUnSelect\";\n\t\tthis.callEvent(ename,[id]);\n\n\t\treturn true;\n\t},\n\t//select some item\n\tselect:function(id,preserve){\n\t\tvar ctrlKey = arguments[2];\n\t\tvar shiftKey = arguments[3];\n\t\t//if id not provide - works as selectAll\n\t\tif (!id) return this.selectAll();\n\n\t\t//allow an array of ids as parameter\n\t\tif (isArray(id)){\n\t\t\tfor (var i=0; i < id.length; i++)\n\t\t\t\tthis.select(id[i], (i?1:preserve), ctrlKey, shiftKey);\n\t\t\treturn;\n\t\t}\n\n\t\tassert(this.data.exists(id), \"Incorrect id in select command: \"+id);\n\t\t\n\t\t//block selection mode\n\t\tif (shiftKey && this._selected.length)\n\t\t\treturn this.selectAll(this._selected[this._selected.length-1],id);\n\n\t\t//single selection mode\n\t\tvar need_unselect = false;\n\t\tif (!ctrlKey && !preserve && (this._selected.length!=1 || this._selected[0]!=id))\n\t\t\tneed_unselect = true;\n\n\t\tif (!need_unselect && this.isSelected(id)){\n\t\t\tif (ctrlKey) this.unselect(id);\t//ctrl-selection of already selected item\n\t\t\treturn;\n\t\t}\n\n\t\tthis._select_mark(id, true, null, need_unselect);\n\t},\n\t//unselect some item\n\tunselect:function(id){\n\t\t//if id is not provided - unselect all items\n\t\tif (!id) return this.unselectAll();\n\t\tif (!this.isSelected(id)) return;\n\t\t\n\t\tthis._select_mark(id,false);\n\t},\n\t//select all items, or all in defined range\n\tselectAll:function(from,to){\n\t\tvar range;\n\t\tvar refresh=[];\n\t\t\n\t\tif (from||to)\n\t\t\trange = this.data.getRange(from||null,to||null);\t//get limited set if bounds defined\n\t\telse\n\t\t\trange = this.data.getRange();\t\t\t//get all items in other case\n\t\t//in case of paging - it will be current page only\n\t\trange.each(function(obj){ \n\t\t\tif (!this.data.getMark(obj.id, \"webix_selected\")){\n\t\t\t\tif(this._select_mark(obj.id,true,refresh))\n\t\t\t\t\tthis._selected.push(obj.id);\n\t\t\t}\n\t\t},this);\n\t\t//repaint self\n\t\tthis._refresh_selection(refresh);\n\t},\n\t//remove selection from all items\n\tunselectAll:function(){\n\t\tvar refresh=[];\n\t\t\n\t\tthis._selected.each(function(id){\n\t\t\tthis._select_mark(id,false,refresh);\t//unmark selected only\n\t\t},this);\n\t\t\n\t\tthis._selected=_to_array();\n\t\tthis._refresh_selection(refresh);\t//repaint self\n\t},\n\t//returns true if item is selected\n\tisSelected:function(id){\n\t\treturn this._selected.find(id)!=-1;\n\t},\n\t/*\n\t\treturns ID of selected items or array of IDs\n\t\tto make result predictable - as_array can be used, \n\t\t\twith such flag command will always return an array \n\t\t\tempty array in case when no item was selected\n\t*/\n\tgetSelectedId:function(as_array){\t\n\t\tswitch(this._selected.length){\n\t\t\tcase 0: return as_array?[]:\"\";\n\t\t\tcase 1: return as_array?[this._selected[0]]:this._selected[0];\n\t\t\tdefault: return ([].concat(this._selected)); //isolation\n\t\t}\n\t},\n\tgetSelectedItem:function(as_array){\n\t\tvar sel = this.getSelectedId(true);\n\t\tif (sel.length > 1 || as_array){\n\t\t\tfor (var i = sel.length - 1; i >= 0; i--)\n\t\t\t\tsel[i] = this.getItem(sel[i]);\n\t\t\treturn sel;\n\t\t} else if (sel.length)\n\t\t\treturn this.getItem(sel[0]);\n\t},\n\t//detects which repainting mode need to be used\n\t_is_mass_selection:function(obj){\n\t\t// crappy heuristic, but will do the job\n\t\treturn obj.length>100 || obj.length > this.data.count/2;\n\t},\n\t_refresh_selection:function(refresh){\n\t\tif (typeof refresh != \"object\") refresh = [refresh];\n\t\tif (!refresh.length) return;\t//nothing to repaint\n\t\t\n\t\tif (this._is_mass_selection(refresh))\t\n\t\t\tthis.data.refresh();\t//many items was selected - repaint whole view\n\t\telse\n\t\t\tfor (var i=0; i < refresh.length; i++)\t//repaint only selected\n\t\t\t\tthis.render(refresh[i],this.data.getItem(refresh[i]),\"update\");\n\t\t\t\n\t\tif (!this._silent_selection)\t\n\t\t\tthis.callEvent(\"onSelectChange\",[refresh]);\n\t}\n};\n\nready(function(){\n\tevent(document.body,\"mouseup\", function(){\n\t\tif(state._noselect_element){\n\t\t\tremoveCss(state._noselect_element,\"webix_noselect\");\n\t\t\tstate._noselect_element = null;\n\t\t}\n\t});\n});\n\nexport default SelectionModel;","import {isArray} from \"../webix/helpers\";\nimport {create, remove} from \"../webix/html\";\n\nconst color = {\n\t_toHex:[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"A\",\"B\",\"C\",\"D\",\"E\",\"F\"],\n\ttoHex:function(number, length){\n\t\tnumber=parseInt(number,10);\n\t\tvar str = \"\";\n\t\twhile (number>0){\n\t\t\tstr=this._toHex[number%16]+str;\n\t\t\tnumber=Math.floor(number/16);\n\t\t}\n\t\twhile (str.length 255)\n\t\t\tr = 0;\n\t\tif (g < 0 || g > 255)\n\t\t\tg = 0;\n\t\tif (b < 0 || b > 255)\n\t\t\tb = 0;\n\t\treturn [r,g,b];\n\t},\n\thsvToRgb:function(h, s, v){\n\t\tvar hi,f,p,q,t,r,g,b;\n\t\thi = Math.floor((h/60))%6;\n\t\tf = h/60-hi;\n\t\tp = v*(1-s);\n\t\tq = v*(1-f*s);\n\t\tt = v*(1-(1-f)*s);\n\t\tr = 0;\n\t\tg = 0;\n\t\tb = 0;\n\t\tswitch(hi) {\n\t\t\tcase 0:\n\t\t\t\tr = v; g = t; b = p;\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tr = q; g = v; b = p;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tr = p; g = v; b = t;\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tr = p; g = q; b = v;\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tr = t; g = p; b = v;\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tr = v; g = p; b = q;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\tr = Math.floor(r*255);\n\t\tg = Math.floor(g*255);\n\t\tb = Math.floor(b*255);\n\t\treturn [r, g, b];\n\t},\n\trgbToHsv:function(r, g, b){\n\t\tvar r0,g0,b0,min0,max0,s,h,v;\n\t\tr0 = r/255;\n\t\tg0 = g/255;\n\t\tb0 = b/255;\n\t\tmin0 = Math.min(r0, g0, b0);\n\t\tmax0 = Math.max(r0, g0, b0);\n\t\th = 0;\n\t\ts = max0===0?0:(1-min0/max0);\n\t\tv = max0;\n\t\tif (max0 == min0) {\n\t\t\th = 0;\n\t\t} else if (max0 == r0 && g0>=b0) {\n\t\t\th = 60*(g0 - b0)/(max0 - min0)+0;\n\t\t} else if (max0 == r0 && g0 < b0) {\n\t\t\th = 60*(g0 - b0)/(max0 - min0)+360;\n\t\t} else if (max0 == g0) {\n\t\t\th = 60*(b0 - r0)/(max0-min0)+120;\n\t\t} else if (max0 == b0) {\n\t\t\th = 60*(r0 - g0)/(max0 - min0)+240;\n\t\t}\n\t\treturn [h, s, v];\n\t}\n};\n\nexport default color;","import {createCss} from \"../../webix/html\";\nimport {extend, copy} from \"../../webix/helpers\";\n\nimport SVG from \"./svg\";\nimport BaseLine from \"./line\";\n\n\n\nvar defaults = {\n\tpaddingX: 3,\n\tpaddingY: 4,\n\tradius: 1,\n\tminHeight: 4,\n\teventRadius: 8\n};\n\nfunction Area(config){\n\tthis.config = extend(copy(defaults),config||{},true);\n}\n\nArea.prototype.draw = function(data, width, height){\n\tvar eventRadius, graph, path, points, styles,\n\t\tconfig = this.config,\n\t\tLine = BaseLine.prototype,\n\t\trenderer = SVG;\n\n\t// draw area\n\tpoints = this.getPoints(data, width, height);\n\tpath = renderer.definePath(Line._getLinePoints(points),true);\n\n\tif(config.color)\n\t\tstyles = this._applyColor(renderer,config.color);\n\n\tgraph = renderer.group(renderer.getPath(path,\"webix_sparklines_area\"+(styles?\" \"+styles.area:\"\")));\n\t// draw line\n\tpoints.splice(points.length - 3, 3);\n\tpath = renderer.definePath(Line._getLinePoints(points));\n\tgraph += renderer.group(renderer.getPath(path,\"webix_sparklines_line\"+(styles?\" \"+styles.line:\"\")));\n\t// draw items\n\tgraph += Line._drawItems(renderer, points, config.radius, \"webix_sparklines_item\"+(styles?\" \"+styles.item:\"\"));\n\t// draw event areas\n\teventRadius = Math.min(data.length?(width-2*(config.paddingX||0))/data.length:0,config.eventRadius);\n\tgraph += Line._drawEventItems(renderer, points, eventRadius);\n\treturn renderer.draw(graph, width, height, \"webix_sparklines_area_chart\"+(config.css?\" \"+config.css:\"\"));\n};\nArea.prototype._applyColor = function(renderer,color){\n\tvar config = {\"area\": {}, \"line\":{},\"item\":{}},\n\t\tmap = renderer.styleMap;\n\tif(color){\n\t\tconfig.area[map.color] = renderer.setOpacity(color,0.2);\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\n\treturn config;\n};\nArea.prototype.getPoints = function(data, width, height){\n\tvar Line = BaseLine.prototype;\n\tvar points =Line.getPoints.call(this, data, width, height);\n\tvar x = this.config.paddingX || 0;\n\tvar y = this.config.paddingY || 0;\n\tpoints.push({x: width - x, y: height - y},{x: x, y: height - y},{x: x, y: points[0].y});\n\treturn points;\n};\n\nexport default Area;","import {extend, copy} from \"../../webix/helpers\";\n\nimport SVG from \"./svg\";\n\nvar defaults = {\n\tpaddingY: 2\n};\n\nfunction Pie(config){\n\tthis.config = extend(copy(defaults),config||{},true);\n}\nPie.prototype._defColorsCursor = 0;\nPie.prototype._defColors = [\n\t\"#f55b50\",\"#ff6d3f\",\"#ffa521\",\"#ffc927\",\"#ffee54\",\"#d3e153\",\"#9acb61\",\"#63b967\",\n\t\"#21a497\",\"#21c5da\",\"#3ea4f5\",\"#5868bf\",\"#7b53c0\",\"#a943ba\",\"#ec3b77\",\"#9eb0b8\"\n];\nPie.prototype._getColor = function(i,data){\n\tvar count = data.length;\n\tvar colorsCount = this._defColors.length;\n\tif(colorsCount > count){\n\t\tif(i){\n\t\t\tif(i < colorsCount - count)\n\t\t\t\ti = this._defColorsCursor +2;\n\t\t\telse\n\t\t\t\ti = this._defColorsCursor+1;\n\t\t}\n\t\tthis._defColorsCursor = i;\n\t}\n\telse\n\t\ti = i%colorsCount;\n\treturn this._defColors[i];\n};\nPie.prototype.draw = function(data, width, height){\n\tvar attrs, graph, i, sectors,\n\t\tconfig = this.config,\n\t\tcolor = config.color||this._getColor,\n\t\tpoints = this.getAngles(data),\n\t\trenderer = SVG,\n\t\ty = config.paddingY|| 0,\n\t\t// radius\n\t\tr = height/2 - y,\n\t\t// center\n\t\tx0 = width/2, y0 = height/2;\n\n\t// draw sectors\n\tif(typeof color != \"function\")\n\t\tcolor = function(){return color;};\n\tsectors = \"\";\n\tfor( i =0; i < points.length; i++){\n\t\tattrs = {};\n\t\tattrs[renderer.styleMap[\"color\"]] = color.call(this,i,data,this._context);\n\t\tsectors += renderer.getSector({x:x0,y:y0},r,points[i][0],points[i][1],\"webix_sparklines_sector\", attrs);\n\t}\n\tgraph = renderer.group(sectors);\n\n\t// draw event areas\n\tsectors = \"\";\n\tfor(i =0; i < points.length; i++){\n\t\tsectors += renderer.getSector({x:x0,y:y0},r,points[i][0],points[i][1],\"webix_sparklines_event_area\",{\"webix_area\":i});\n\t}\n\tgraph += renderer.group(sectors);\n\n\tif(config.donut)\n\t\tgraph += SVG.getCircle({x:x0,y:y0}, config.innerRadius || r*0.5, \"webix_sparklines_donut_hole\");\n\n\treturn renderer.draw(graph, width, height, \"webix_sparklines_pie_chart\"+(config.css?\" \"+config.css:\"\"));\n};\nPie.prototype.getAngles = function(data){\n\tvar a0 = -Math.PI/ 2, a1,\n\t\ti, result = [];\n\n\tvar ratios = this._getRatios(data);\n\n\tfor( i =0; i < data.length; i++){\n\t\ta1= -Math.PI/2+ratios[i]-0.0001;\n\t\tresult.push([a0,a1]);\n\t\ta0 = a1;\n\t}\n\treturn result;\n};\nPie.prototype._getTotalValue = function(data){\n\tvar t=0;\n\tfor(var i = 0; i < data.length;i++)\n\t\tt += data[i]*1;\n\treturn t;\n};\nPie.prototype._getRatios = function(data){\n\tvar i, value,\n\t\tratios = [],\n\t\tprevSum = 0,\n\t\ttotalValue = this._getTotalValue(data);\n\tfor(i = 0; i < data.length;i++){\n\t\tvalue = data[i]*1;\n\t\tratios[i] = Math.PI*2*(totalValue?((value+prevSum)/totalValue):(1/data.length));\n\t\tprevSum += value;\n\t}\n\treturn ratios;\n};\n\nexport default Pie;","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 {bind} from \"../webix/helpers\";\nimport DataLoader from \"../core/dataloader\";\nimport promise from \"../thirdparty/promiz\";\n\n\nconst TreeDataLoader = {\n\t$init:function(){\n\t\tthis.data.attachEvent(\"onStoreUpdated\", bind(this._sync_hierarchy, this), null, true);\n\t\t//redefine methods\n\t\tthis._feed_common = this._feed_commonA;\n\t},\n\t_feed_commonA:function(from, count, callback, defer, details, clear){\n\t\t// branch loading\n\t\tdetails = (count === 0) ? {parent: encodeURIComponent(from)} : null;\n\t\treturn DataLoader.prototype._feed_common.call(this, from, count, callback, defer, details, clear);\n\t},\n\t//load next set of data rows\n\tloadBranch:function(id, callback, url){\n\t\tid = id || 0;\n\t\tthis.data.url = url || this.data.url;\n\t\tif (this.callEvent(\"onDataRequest\", [id,callback,this.data.url]) && this.data.url)\n\t\t\treturn this.data.feed.call(this, id, 0, callback);\n\t\treturn promise.reject();\n\t},\n\t_sync_hierarchy:function(id, data, mode){\n\t\tif (!mode || mode == \"add\" || mode == \"delete\" || mode == \"branch\"){\n\t\t\tthis.data._sync_to_order(this);\n\t\t}\n\t}\n};\n\nexport default TreeDataLoader;","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){\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= state.y + this._content_height)\n\t\t\tthis.scrollTo(0, dy);\n\t},\n\t//repain self after changes in DOM\n\t//for add, delete, move operations - render is delayed, to minify performance impact\n\trender:function(id,data,type){\n\t\tif (!this.isVisible(this._settings.id) || this.$blockRender)\n\t\t\treturn;\n\t\t\n\t\tif (id){\n\t\t\tvar cont = this.getItemNode(id);\t//old html element\n\t\t\tswitch(type){\n\t\t\t\tcase \"update\":\n\t\t\t\t\tif (!cont) return;\n\t\t\t\t\t//replace old with new\n\t\t\t\t\tvar t = this._htmlmap[id] = this._toHTMLObject(data);\n\t\t\t\t\tinsertBefore(t, cont); \n\t\t\t\t\tremove(cont);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: // \"move\", \"add\", \"delete\"\n\t\t\t\t\t/*\n\t\t\t\t\t\tfor all above operations, full repainting is necessary\n\t\t\t\t\t\tbut from practical point of view, we need only one repainting per thread\n\t\t\t\t\t\tcode below initiates double-thread-rendering trick\n\t\t\t\t\t*/\n\t\t\t\t\tthis._render_delayed();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\t//full repainting\n\t\t\tif (this.callEvent(\"onBeforeRender\",[this.data])){\n\t\t\t\tthis._htmlmap = {}; \t\t\t\t\t//nulify links to already rendered elements\n\t\t\t\tthis._render_visible_rows(null, true);\t\n\t\t\t\t// clear delayed-rendering, because we already have repaint view\n\t\t\t\tthis._wait_for_render = false;\t\t\t\n\t\t\t\tthis.callEvent(\"onAfterRender\",[]);\n\t\t\t}\n\t\t}\n\t},\n\t//implement double-thread-rendering pattern\n\t_render_delayed:function(){\n\t\t//this flag can be reset from outside, to prevent actual rendering \n\t\tif (this._wait_for_render) return;\n\t\tthis._wait_for_render = true;\t\n\t\t\n\t\twindow.setTimeout(bind(function(){\n\t\t\tthis.render();\n\t\t},this),1);\n\t},\n\t//create empty placeholders, which will take space before rendering\n\t_create_placeholder:function(height){\n\t\tif(env.maxHTMLElementSize)\n\t\t\theight = Math.min(env.maxHTMLElementSize, height);\n\t\tvar node = document.createElement(\"DIV\");\n\t\tnode.style.cssText = \"height:\"+height+\"px; width:100%; overflow:hidden;\";\n\t\treturn node;\n\t},\n\t/*\n\t\tMethods get coordinatest of visible area and checks that all related items are rendered\n\t\tIf, during rendering, some not-loaded items was detected - extra data loading is initiated.\n\t\treset - flag, which forces clearing of previously rendered elements\n\t*/\n\t_render_visible_rows:function(e,reset){\n\t\tthis._unrendered_area=[]; //clear results of previous calls\n\t\t\n\t\tvar viewport = this._getVisibleRange();\t//details of visible view\n\n\t\tif (!this._dataobj.firstChild || reset){\t//create initial placeholder - for all view space\n\t\t\tthis._dataobj.innerHTML=\"\";\n\t\t\tthis._dataobj.appendChild(this._create_placeholder(viewport._max));\n\t\t\t//register placeholder in collection\n\t\t\tthis._htmlrows = [this._dataobj.firstChild];\n\t\t}\n\t\t\n\t\t/*\n\t\t\tvirtual rendering breaks all view on rows, because we know widht of item\n\t\t\twe can calculate how much items can be placed on single row, and knowledge \n\t\t\tof that, allows to calculate count of such rows\n\t\t\t\n\t\t\teach time after scrolling, code iterate through visible rows and render items \n\t\t\tin them, if they are not rendered yet\n\t\t\t\n\t\t\tboth rendered rows and placeholders are registered in _htmlrows collection\n\t\t*/\n\n\t\t//position of first visible row\n\t\tvar t = viewport._from;\n\t\t\t\n\t\twhile(t<=viewport._height){\t//loop for all visible rows\n\t\t\t//skip already rendered rows\n\t\t\twhile(this._htmlrows[t] && this._htmlrows[t]._filled && t<=viewport._height){\n\t\t\t\tt++; \n\t\t\t}\n\t\t\t//go out if all is rendered\n\t\t\tif (t>viewport._height) break;\n\t\t\t\n\t\t\t//locate nearest placeholder\n\t\t\tvar holder = t;\n\t\t\twhile (!this._htmlrows[holder]) holder--;\n\t\t\tvar holder_row = this._htmlrows[holder];\n\t\t\t\n\t\t\t//render elements in the row\t\t\t\n\t\t\tvar base = t*viewport._dx+(this.data.$min||0);\t//index of rendered item\n\t\t\tif (base > (this.data.$max||Infinity)) break;\t//check that row is in virtual bounds, defined by paging\n\t\t\tvar nextpoint = Math.min(base+viewport._dx-1,(this.data.$max?this.data.$max-1:Infinity));\n\t\t\tvar node = this._create_placeholder(viewport._y);\n\t\t\t//all items in rendered row\n\t\t\tvar range = this.data.getIndexRange(base, nextpoint);\n\t\t\tif (!range.length) break; \n\t\t\t\n\t\t\tvar loading = { $template:\"Loading\" };\n\t\t\tfor (let i=0; i0){\n\t\t\t\tholder_row.style.height = delta2+\"px\";\n\t\t\t\tthis._htmlrows[t+1] = holder_row;\n\t\t\t} else {\n\t\t\t\tif (delta<0)\n\t\t\t\t\tremove(holder_row);\n\t\t\t\telse\n\t\t\t\t\tholder_row.style.height = delta+\"px\";\n\t\t\t\tif (delta2>0){ \n\t\t\t\t\tvar new_space = this._htmlrows[t+1] = this._create_placeholder(delta2);\n\t\t\t\t\tinsertBefore(new_space,node.nextSibling,this._dataobj);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t\tt++;\n\t\t}\n\t\t\n\t\t//when all done, check for non-loaded items\n\t\tif (this._unrendered_area.length){\n\t\t\t//we have some data to load\n\t\t\t//detect borders\n\t\t\tvar from = this._unrendered_area[0];\n\t\t\tvar to = this._unrendered_area.pop()+1;\n\t\t\tif (to>from){\n\t\t\t\t//initiate data loading\n\t\t\t\tvar count = to - from;\n\t\t\t\tif (this._maybe_loading_already(count, from)) return;\n\n\t\t\t\tcount = Math.max(count, (this._settings.datafetch||this._settings.loadahead||0));\n\t\t\t\tthis.loadNext(count, from);\n\t\t\t}\n\t\t}\n\t},\n\t//calculates visible view\n\t_getVisibleRange:function(){\n\t\tvar state = this.getScrollState();\n\t\tvar top = Math.max(0, state.y);\n\t\tvar tpadding = this._tilesPadding||0;\n\t\tvar width = this._content_width - tpadding; \n\t\tvar height = this._content_height - tpadding/2;\n\n\t\t//size of single item\n\t\tvar t = this.type;\n\n\t\tvar dx = Math.floor(width/t.width)||1; //at least single item per row\n\t\t\n\t\tvar min = Math.floor(top/t.height);\t\t\t\t//index of first visible row\n\t\tvar dy = Math.ceil((height+top)/t.height)-1;\t\t//index of last visible row\n\t\t//total count of items, paging can affect this math\n\t\tvar count = this.data.$max?(this.data.$max-this.data.$min):this.data.count();\n\t\tvar max = Math.ceil(count/dx)*t.height;\t\t\t//size of view in rows\n\n\t\treturn { _from:min, _height:dy, _top:top, _max:max, _y:t.height, _dx:dx};\n\t},\n\t_cellPosition:function(id){\n\t\tvar html = this.getItemNode(id);\n\t\tif (!html){\n\t\t\tthis.showItem(id);\n\t\t\tthis._render_visible_rows();\n\t\t\thtml = this.getItemNode(id);\n\t\t}\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};\n\nexport default VirtualRenderStack;","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\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\tvar timeFormat = this._settings.calendarTime||i18n.timeFormatStr;\n\t\tvar clock = this._settings.timeIcon;\n\t\tvar 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\tvar 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\t\t\t\t\n\t\t\tfor(var 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 = 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 = 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, true, 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\n\t\t\t\tvar blocked = (this._settings.blockDates && this._settings.blockDates.call(this,date));\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\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\tvar blocked = (this._settings.blockDates && this._settings.blockDates.call(this,date));\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\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\tvar blockedDate = (this._settings.blockDates && this._settings.blockDates.call(this,date));\n\t\tvar minDate = this._settings.minDate;\n\t\tvar maxDate = this._settings.maxDate;\n\t\tvar outOfRange = (minDate && date < minDate) || (maxDate && date >= DateHelper.add(maxDate, 1, \"day\", true));\n\t\treturn !blockedDate && !outOfRange;\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} 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\tvar text = common.$renderInput(obj, common);\n\t\t\tif (obj.badge||obj.badge===0) text = text.replace(\"\", \"\"+obj.badge+\"\");\n\t\t\treturn \"
\"+ text + \"
\";\n\t\t},\n\t\tlabel:\"\",\n\t\tvalue:\"\",\n\t\tborderless:true\n\t},\n\t$renderInput:function(obj){\n\t\treturn \"\";\n\t},\n\t$init:function(config){\n\t\tthis._viewobj.className += \" webix_control webix_el_\"+(this.$cssName||this.name);\n\n\t\tthis._destroy_with_me = [];\n\t\tthis._set_default_css(config);\n\n\t\tthis.data = this._settings;\n\t\tthis._dataobj = this._viewobj;\n\n\t\tthis.$ready.push(function(){ this._calc_size(this.config); });\n\t},\n\thotkey_setter: function(key){\n\t\tvar control = this;\n\t\tthis._addElementHotKey(key, function(view,ev){\n\t\t\tif(control.isVisible()){\n\t\t\t\tvar elem = control.$view.firstChild;\n\t\t\t\ttriggerEvent(elem, \"MouseEvent\", \"click\");\n\t\t\t\tpreventEvent(ev);\n\t\t\t}\n\t\t});\n\t},\n\t_set_default_css: function(config){\n\t\tif (!config.css || !this._get_class(config.css) || (this.defaults.css && !this._get_class(this.defaults.css))){\n\t\t\tthis._viewobj.className += \" webix_secondary\";\n\t\t}\n\t},\n\t_get_class:function(css){\n\t\tif(typeof css == \"string\"){\n\t\t\tconst classes = { webix_danger:1, webix_transparent:1, webix_primary:1 };\n\t\t\tfor(let i in classes){\n\t\t\t\tif(css.indexOf(i)!==-1)\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t},\n\t_addElementHotKey: function(key, func, view){\n\t\tvar keyCode = UIManager.addHotKey(key, func, view);\n\t\tthis.attachEvent(\"onDestruct\", function(){\n\t\t\tUIManager.removeHotKey(keyCode, func, view);\n\t\t});\n\t},\n\ttype_setter:function(value){\n\t\tif (this._types[value])\n\t\t\tthis.$renderInput = template(this._types[value]);\n\t\treturn value;\n\t},\n\t_set_inner_size:false,\n\t_types:{\n\t\timage:\"\",\n\t\timageTop:\"\",\n\n\t\ticon:\"\",\n\t\ticonTop:\"\",\n\t},\n\t_findAllInputs: function(){\n\t\tvar result = [];\n\t\tvar tagNames = [\"input\",\"select\",\"textarea\",\"button\"];\n\t\tfor(var i=0; i< tagNames.length; i++){\n\t\t\tvar inputs = this.$view.getElementsByTagName(tagNames[i]);\n\t\t\tfor(var j = 0; j< inputs.length; j++){\n\t\t\t\tresult.push(inputs[j]);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t},\n\tdisable: function(){\n\t\tvar i, node, elem = this._getBox();\n\t\tbaseview.api.disable.apply(this, arguments);\n\t\tif(elem && elem.className.indexOf(\" webix_disabled_box\")== -1){\n\t\t\telem.className += \" webix_disabled_box\";\n\t\t\tvar inputs = this._findAllInputs();\n\t\t\tfor(i=0; i< inputs.length; i++)\n\t\t\t\tinputs[i].setAttribute(\"disabled\",true);\n\n\t\t\t// richselect and based on it\n\t\t\tnode = this.getInputNode();\n\t\t\tif(node && node.tagName.toLowerCase() == \"div\"){\n\t\t\t\tthis._disabledTabIndex = node.getAttribute(\"tabIndex\");\n\t\t\t\tnode.removeAttribute(\"tabIndex\");\n\t\t\t}\n\n\t\t\tif(this._settings.labelPosition == \"top\"){\n\t\t\t\tvar label = this._dataobj.firstChild;\n\t\t\t\tif(label)\n\t\t\t\t\tlabel.className += \" webix_disabled_top_label\";\n\t\t\t}\n\t\t}\n\t},\n\tenable: function(){\n\t\tbaseview.api.enable.apply(this, arguments);\n\t\tvar node,\n\t\t\telem = this._getBox();\n\t\tif(elem){\n\t\t\telem.className = elem.className.replace(\" webix_disabled_box\",\"\");\n\t\t\tvar inputs = this._findAllInputs();\n\t\t\tfor(var i=0; i< inputs.length; i++)\n\t\t\t\tinputs[i].removeAttribute(\"disabled\");\n\n\t\t\tnode = this.getInputNode();\n\t\t\tif(node && !isUndefined(this._disabledTabIndex))\n\t\t\t\tnode.setAttribute(\"tabIndex\",this._disabledTabIndex);\n\n\t\t\tif(this._settings.labelPosition == \"top\"){\n\t\t\t\tvar label = this._dataobj.firstChild;\n\t\t\t\tif(label)\n\t\t\t\t\tlabel.className = label.className.replace(\" webix_disabled_top_label\",\"\");\n\t\t\t}\n\t\t}\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\tsetValue:function(value, config){\n\t\tvalue = this.$prepareValue(value);\n\t\tconst oldvalue = this._settings.value;\n\n\t\tif (this.$compareValue(oldvalue, value)){\n\t\t\t//controls with post formating, we need to repaint value\n\t\t\tif(this._rendered_input && this._pattern){\n\t\t\t\tvalue = this._pattern(value);\n\t\t\t\tconst input = this.getInputNode();\n\t\t\t\tif(input && !isUndefined(input.value) && input.value != value)\n\t\t\t\t\tthis.$setValue(value);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis._settings.value = value;\n\t\tif (this._rendered_input)\n\t\t\tthis.$setValue(value);\n\n\t\tthis.callEvent(\"onChange\", [value, oldvalue, config]);\n\t},\n\t$compareValue:function(oldvalue, value){ \n\t\tif (typeof value === \"number\") value = value.toString();\n\t\tif (typeof oldvalue === \"number\") oldvalue = oldvalue.toString();\n\t\treturn oldvalue == value;\n\t},\n\t$prepareValue:function(value){ return value === 0 ? \"0\" : (value || \"\").toString(); },\n\tvalue_setter:function(value){\n\t\treturn this.$prepareValue(value);\n\t},\n\t//visual part of setValue\n\t$setValue:function(value){\n\t\tconst node = this.getInputNode();\n\t\tif (node && !this._types[this._settings.type]){\n\t\t\tvalue = this._settings.label || value;\n\t\t\tif (node.tagName==\"BUTTON\") node.innerHTML = value;\n\t\t\telse node.value = value;\n\t\t}\n\t},\n\tgetValue:function(){\n\t\t//if button was rendered - returning actual value\n\t\t//otherwise - returning last set value\n\t\tvar value = this._rendered_input ? this.$getValue() : this._settings.value;\n\t\treturn (typeof value == \"undefined\") ? \"\" : value;\n\t},\n\t$getValue:function(){\n\t\treturn this._settings.value||\"\";\t\n\t},\n\tfocus:function(){\n\t\tif(!UIManager.canFocus(this))\n\t\t\treturn false;\n\t\t\n\t\tvar input = this.getInputNode();\n\t\tif (input && input.focus) input.focus();\n\t},\n\tblur:function() {\n\t\tvar input = this.getInputNode();\n\t\tif (input && input.blur) input.blur();\n\t},\n\t//get input element\n\tgetInputNode: function() {\n\t\treturn this._dataobj.getElementsByTagName(\"input\")[0]||this._dataobj.getElementsByTagName(\"button\")[0];\n\t},\n\t//get top-level sub-container\n\t_getBox:function(){\n\t\tfor(var i=0;i< this._dataobj.childNodes.length;i++){\n\t\t\tif(this._dataobj.childNodes[i].className.indexOf(\"webix_el_box\")>=0)\n\t\t\t\treturn this._dataobj.childNodes[i];\n\t\t}\n\t\treturn null;\n\t},\n\t_get_tooltip_data:function(t,e){\n\t\tlet node = e.target;\n\t\tlet box = this._getBox();\n\n\t\tconst isTopLabel = this._settings.labelPosition == \"top\" && this._dataobj.firstChild.contains(node);\n\n\t\tif (isTopLabel || box && box.contains(node))\n\t\t\treturn this._settings;\n\t\treturn null;\n\t},\n\t_sqrt_2:Math.sqrt(2),\n\t_calc_size:function(config){\n\t\tconfig = config || this._settings;\n\t\tif (config.autowidth){\n\t\t\tlet width = getTextSize((config.value||config.label || \"\"), \"webixbutton\").width +\n\t\t\t\t(config.badge||config.badge===0 ? getTextSize(config.badge, \"webix_badge\").width * 2 - 32 : 0) +\n\t\t\t\t(config.type === \"icon\" ? 24 : 0) +\n\t\t\t\t(config.type === \"image\" ? config.height-$active.inputPadding : 0);\n\n\t\t\twidth = Math.max(config.minWidth || 0, width);\n\t\t\tconfig.width = Math.min(config.maxWidth || Infinity, width);\n\t\t}\n\t},\n\t_calck_input_size:function(){\n\t\t//use width for both width and inputWidth settings in clever way\n\t\t//in form, we can define width for some element smaller than for siblings\n\t\t//it will use inputWidth to render the desired view\n\t\tthis._input_width = this._settings.inputWidth || \n\t\t\t((this._content_width - this._settings.width > 2)?this._settings.width:0) || this._content_width;\n\t\tthis._input_height = this._settings.inputHeight||this._inputHeight||0;\n\t},\n\tresize: function(){\n\t\tthis._calc_size();\n\t\treturn base.api.resize.apply(this,arguments);\n\t},\n\trender:function(){\n\t\tthis._calck_input_size();\n\t\tthis._settings.awidth = this._input_width||this._content_width;\n\t\tthis._settings.aheight = this._input_height||this._content_height;\n\n\t\t//image button - image width\n\t\tthis._settings.bheight = this._settings.aheight+2;\n\t\tthis._settings.cheight = this._settings.aheight- 2*$active.inputPadding;\n\t\tthis._settings.dheight = this._settings.cheight - 2; // - borders\n\n\t\tif(AtomRender.render.call(this)){\n\t\t\tthis._rendered_input = true;\n\t\t\tif (this._set_inner_size) this._set_inner_size();\n\t\t\tif (this._settings.align){\n\t\t\t\tvar handle = this._dataobj.firstChild;\n\t\t\t\tif (this._settings.labelPosition == \"top\" && handle.nextSibling)\n\t\t\t\t\thandle = handle.nextSibling;\n\n\t\t\t\tswitch(this._settings.align){\n\t\t\t\t\tcase \"right\":\n\t\t\t\t\t\thandle.style.cssFloat = \"right\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"center\":\n\t\t\t\t\t\thandle.style.display = \"inline-block\";\n\t\t\t\t\t\thandle.parentNode.style.textAlign = \"center\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"middle\":\n\t\t\t\t\t\thandle.style.marginTop = Math.round((this._content_height-this._input_height)/2)+\"px\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"bottom\": \n\t\t\t\t\t\thandle.style.marginTop = (this._content_height-this._input_height)+\"px\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"left\":\n\t\t\t\t\t\thandle.style.cssFloat = \"left\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tassert(false, \"Unknown align mode: \"+this._settings.align);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.$render)\n\t\t\t\tthis.$render(this.data);\n\n\t\t\tif (this._settings.disabled)\n\t\t\t\tthis.disable();\n\n\t\t\tif (this._init_once){\n\t\t\t\tthis._init_once(this.data);\n\t\t\t\tthis._init_once = 0;\n\t\t\t}\n\t\t}\n\t},\n\n\trefresh:function(){ this.render(); },\n\n\ton_click:{\n\t\t_handle_tab_click: function(ev){\n\t\t\tconst id = locate(ev, /*@attr*/\"button_id\");\n\t\t\tconst opt = this.getOption(id);\n\n\t\t\tif (opt && !opt.disabled && this.callEvent(\"onBeforeTabClick\", [id, ev])){\n\t\t\t\tthis.setValue(id, \"user\");\n\t\t\t\tthis.focus();\n\t\t\t\tthis.callEvent(\"onAfterTabClick\", [id, ev]);\n\t\t\t}\n\t\t},\n\t\twebix_all_segments:function(ev, button){\n\t\t\tthis.on_click._handle_tab_click.call(this, ev, button);\n\t\t},\n\t\twebix_all_tabs:function(ev, button){\n\t\t\tthis.on_click._handle_tab_click.call(this, ev, button);\n\t\t},\n\t\twebix_inp_counter_next:function(){\n\t\t\tif (!this._settings.readonly)\n\t\t\t\tthis.next(this._settings.step, \"user\");\n\t\t},\n\t\twebix_inp_counter_prev:function(){\n\t\t\tif (!this._settings.readonly)\n\t\t\t\tthis.prev(this._settings.step, \"user\");\n\t\t},\n\t\twebix_input_icon:function(){\n\t\t\tthis.getInputNode().focus();\n\t\t},\n\t\twebix_clear_icon:function(){\n\t\t\tif (this.$allowsClear) this.setValue(\"\", \"user\");\n\t\t\treturn false;\n\t\t},\n\t\twebix_inp_checkbox_border: function(e) {\n\t\t\tif (!this._settings.disabled && e.target.tagName != \"DIV\" && !this._settings.readonly)\n\t\t\t\tthis.toggle(\"user\");\n\t\t},\n\t\twebix_inp_checkbox_label: function() {\n\t\t\tif (!this._settings.readonly)\n\t\t\t\tthis.toggle(\"user\");\n\t\t},\n\t\twebix_inp_radio_border: function(e) {\n\t\t\tconst id = locate(e, /*@attr*/\"radio_id\");\n\t\t\tconst opt = this.getOption(id);\n\n\t\t\tif (opt && !opt.disabled){\n\t\t\t\tthis.setValue(id, \"user\");\n\t\t\t\tthis.focus();\n\t\t\t}\n\t\t},\n\t\twebix_tab_more_icon: function(ev,obj,node){\n\t\t\tconst popup = this.getPopup();\n\t\t\tif (!popup.isVisible()){\n\t\t\t\tpopup.resize();\n\t\t\t\tpopup.show(node, null, true);\n\t\t\t} else\n\t\t\t\tpopup.hide();\n\t\t},\n\t\twebix_tab_close:function(e){\n\t\t\tconst id = locate(e, /*@attr*/\"button_id\");\n\t\t\tconst opt = this.getOption(id);\n\n\t\t\tif (opt && !opt.disabled && this.callEvent(\"onBeforeTabClose\", [id, e]))\n\t\t\t\tthis.removeOption(id);\n\t\t\treturn false;\n\t\t}\n\t},\n\n\t//method do not used by button, but used by other child-views\n\t_check_options:function(opts){\n\t\tassert(!!opts, this.name+\": options not defined\");\n\t\tassert(isArray(opts), this.name+\": options must be an array\");\n\n\t\tfor(var i=0;i\"+placeholder+\"\":\"\");\n\t}\n};\n\nconst view = protoUI(api, base.view, AutoTooltip, AtomRender, Settings, EventSystem);\nexport default {api, view};","import {protoUI, ui, $$} from \"../ui/core\";\nimport {$active} from \"../webix/skin\";\nimport {isUndefined, isArray, extend, uid, delay} from \"../webix/helpers\";\nimport {_event} from \"../webix/htmlevents\";\nimport {getSelectionRange, setSelectionRange, getTextSize} from \"../webix/html\";\nimport {assert} from \"../webix/debug\";\nimport template from \"../webix/template\";\n\nimport rules from \"../webix/rules\";\nimport button from \"./button\";\nimport base from \"../views/view\";\n\nimport TextPattern from \"../core/textpattern\";\n\nconst api = {\n\tname:\"text\",\n\t$allowsClear:true,\n\t_init_onchange:function(){\n\t\tif (this.$allowsClear){\n\t\t\tconst c = this._settings;\n\t\t\tconst node = this.getInputNode();\n\t\t\t//attach onChange handler only for controls which do not manage blur on their own\n\t\t\t//for example - combo\n\t\t\tif (!this.$onBlur)\n\t\t\t\t_event(node, \"change\", () => this._applyChanges(\"user\"));\n\t\t\tif (c.suggest)\n\t\t\t\t$$(c.suggest).linkInput(this);\n\t\t\tif (c.clear && !this.addSection){\n\t\t\t\tthis._clear_icon = this.$view.querySelector(\".webix_input_icon:last-child\");\n\t\t\t\tif (node.tagName == \"INPUT\" || node.tagName == \"SELECT\")\n\t\t\t\t\t_event(node, \"input\", (e) => this._toggleClearIcon(e.target.value));\n\n\t\t\t\tconst text = this.getText ? this.getText() : c.text||c.value;\n\t\t\t\tthis._toggleClearIcon(text);\n\t\t\t}\n\t\t}\n\t},\n\t_applyChanges: function(c){\n\t\tconst value = this.getValue();\n\t\tthis.setValue(value, c);\n\t},\n\t_toggleClearIcon:function(value){\n\t\tconst c = this._settings;\n\t\tif (c.readonly || !c.clear || !this._clear_icon) return;\n\n\t\tif (c.clear == \"hover\" || c.clear == \"replace\"){\n\t\t\tconst css = value ? \"webix_clear_icon \"+(c.clear == \"hover\" ? c.icon : \"wxi-close\") : c.icon;\n\t\t\tthis._clear_icon.className = \"webix_input_icon \" + css;\n\t\t} else {\n\t\t\tconst state = value ? \"\" : \"hidden\";\n\t\t\tif (this._clear_icon.style.visibility !== state)\n\t\t\t\tthis._clear_icon.style.visibility = state;\n\t\t}\n\t},\n\t$skin:function(){\n\t\tbutton.api.$skin.call(this);\n\n\t\tthis.defaults.height = $active.inputHeight;\n\t\tthis.defaults.inputPadding = $active.inputPadding;\n\t\tthis._inputSpacing = $active.inputSpacing;\n\t\tthis._labelTopHeight = $active.labelTopHeight;\n\t},\n\t$init:function(config){\n\t\tif (config.labelPosition == \"top\" && isUndefined(config.height) && this.defaults.height) // textarea\n\t\t\tconfig.height = this.defaults.height + (config.label?this._labelTopHeight:0);\n\n\t\t// used in clear_setter\n\t\tif (!isUndefined(config.icon))\n\t\t\tthis._settings.icon = config.icon;\n\n\t\tif (this.$onBlur)\n\t\t\tthis.attachEvent(\"onBlur\", function(){\n\t\t\t\tif (this._rendered_input) this.$onBlur();\n\t\t\t});\n\t\tthis.attachEvent(\"onAfterRender\", this._init_onchange);\n\t\tthis.attachEvent(\"onDestruct\", function(){\n\t\t\tthis._clear_icon = null;\n\t\t});\n\t},\n\tclear_setter:function(value){\n\t\tif (value){\n\t\t\tif (!this._settings.icon) value = true;\n\n\t\t\tif (value !== \"hover\" && value !== \"replace\")\n\t\t\t\tvalue = !!value;\n\t\t}\n\t\treturn value;\n\t},\n\t$renderIcon:function(c){\n\t\tconst height = c.aheight - 2*c.inputPadding;\n\t\tconst padding = (height - 18)/2 -1;\n\t\tlet right = this._inputSpacing/2 - 24;\n\t\tlet html = \"\";\n\n\t\tif (c.icon){\n\t\t\tright += 24;\n\t\t\thtml += \"\";\n\t\t}\n\n\t\tif (!c.readonly && c.clear === true){\n\t\t\tright += 24;\n\t\t\thtml += \"\";\n\t\t}\n\n\t\treturn html;\n\t},\n\trelatedView_setter:function(value){\n\t\tthis.attachEvent(\"onChange\", function(){\n\t\t\tconst value = this.getValue();\n\t\t\tconst mode = this._settings.relatedAction;\n\t\t\tconst viewid = this._settings.relatedView;\n\t\t\tlet view = $$(viewid);\n\t\t\tif (!view){\n\t\t\t\tconst top = this.getTopParentView();\n\t\t\t\tif (top && top.$$)\n\t\t\t\t\tview = top.$$(viewid);\n\t\t\t}\n\n\t\t\tassert(view, \"Invalid relatedView: \"+viewid);\n\n\t\t\tif (mode == \"enable\"){\n\t\t\t\tif (value) view.enable(); else view.disable();\n\t\t\t} else {\n\t\t\t\tif (value) view.show(); else view.hide();\n\t\t\t}\n\t\t});\n\t\treturn value;\n\t},\n\tvalidateEvent_setter:function(value){\n\t\tif (value == \"blur\")\n\t\t\tthis.attachEvent(\"onBlur\", this.validate);\n\n\t\tif (value == \"key\")\n\t\t\tthis.attachEvent(\"onTimedKeyPress\", this.validate);\n\n\t\treturn value;\n\t},\n\tvalidate:function(){\n\t\tlet rule = this._settings.validate;\n\t\tif (!rule && this._settings.required)\n\t\t\trule = rules.isNotEmpty;\n\n\t\tconst form =this.getFormView();\n\t\tconst name = this._settings.name;\n\t\tconst value = this.getValue();\n\t\tconst data = {}; data[name] = value;\n\n\t\tassert(form, \"Validation works only for fields in the form\");\n\t\tassert(name, \"Validation works only for fields with name\");\n\n\t\tif (rule && !form._validate(rule, value, data, name))\n\t\t\treturn false;\n\t\treturn true;\n\t},\n\t_getInvalidText: function(){\n\t\tconst text = this._settings.invalidMessage;\n\t\tif(typeof text == \"function\"){\n\t\t\ttext.call(this);\n\t\t}\n\t\treturn text;\n\t},\n\tbottomLabel_setter: function(text){\n\t\t// this._get_input_width returns 0\n\t\t// use delay to wait for the end of the render\n\t\tdelay(() => {\n\t\t\tif(!this.$destructed)\n\t\t\t\tthis.setBottomText(text);\n\t\t});\n\t},\n\tsetBottomText: function(text){\n\t\tconst config = this._settings;\n\t\tif (!isUndefined(text)){\n\t\t\tif (config.bottomLabel == text) return;\n\t\t\tconfig.bottomLabel = text;\n\t\t}\n\n\t\tlet sel;\n\t\tconst input = this.getInputNode();\n\t\tif (input && !isUndefined(input.value)){\n\t\t\tif (input == document.activeElement) sel = getSelectionRange(input);\n\t\t\t// save input value before rendering\n\t\t\tthis._applyChanges(\"auto\");\n\t\t}\n\n\t\tconst message = (config.invalid ? config.invalidMessage : \"\") || config.bottomLabel;\n\t\tif (!message && !config.bottomPadding)\n\t\t\tconfig.inputHeight = 0;\n\n\t\tif (message && (!config.bottomPadding || this._restorePadding)){\n\t\t\tthis._restorePadding = 1;\n\t\t\tconfig.bottomPadding = getTextSize(message, \"webix_inp_bottom_label\", this._get_input_width(config)).height;\n\n\t\t\tthis.render();\n\t\t\tthis.adjust();\n\t\t\tthis.resize();\n\t\t} else if (!message && this._restorePadding){\n\t\t\tconfig.bottomPadding = this._restorePadding = 0;\n\t\t\t//textarea\n\t\t\tif (!config.height) this.render();\n\t\t\tthis.adjust();\n\t\t\tthis.resize();\n\t\t} else\n\t\t\tthis.render();\n\n\t\tif (sel)\n\t\t\tsetSelectionRange(this.getInputNode(), sel.start, sel.end);\n\t},\n\t$getSize: function(){\n\t\tconst sizes = base.api.$getSize.apply(this,arguments);\n\t\tconst heightInc = this.config.bottomPadding;\n\t\tif(heightInc){\n\t\t\tsizes[2] += heightInc;\n\t\t\tsizes[3] += heightInc;\n\t\t}\n\t\treturn sizes;\n\t},\n\t$setSize:function(x,y){\n\t\tconst config = this._settings;\n\n\t\tif(base.api.$setSize.call(this,x,y)){\n\t\t\tif (!x || !y) return;\n\n\t\t\tif (config.labelPosition == \"top\"){\n\t\t\t\tconfig.labelWidth = 0;\n\t\t\t\t// textarea\n\t\t\t\tif (!config.inputHeight)\n\t\t\t\t\tthis._inputHeight = this._content_height - (config.label?this._labelTopHeight:0) - (this.config.bottomPadding||0);\n\t\t\t} else {\n\t\t\t\tif(config.label)\n\t\t\t\t\tconfig.labelWidth = this._getLabelWidth(config.labelWidth, config.label, config.required);\n\t\t\t\tif (config.bottomPadding)\n\t\t\t\t\tconfig.inputHeight = this._content_height - this.config.bottomPadding;\n\t\t\t}\n\t\t\tthis.render();\n\t\t}\n\t},\n\t_get_input_width: function(config){\n\t\tconst width = (this._input_width||0) - (config.label?config.labelWidth:0) - this._inputSpacing - (config.iconWidth || 0);\n\n\t\t//prevent js error in IE\n\t\treturn (width < 0)?0:width;\n\t},\n\t_render_div_block:function(obj, common){\n\t\tconst id = \"x\"+uid();\n\t\tconst width = common._get_input_width(obj);\n\t\tconst inputAlign = obj.inputAlign || \"left\";\n\t\tconst height = obj.aheight - 2*$active.inputPadding - 2*$active.borderWidth;\n\t\tconst rightPadding = obj.clear === true ? \"padding-right:51px;\" : \"\";\n\t\tconst text = (obj.text||obj.value||this._get_div_placeholder(obj));\n\t\tconst html = \"
\"+text+\"
\";\n\t\treturn common.$renderInput(obj, html, id);\n\t},\n\t_baseInputHTML:function(tag){\n\t\tlet html = \"<\"+tag+(this._settings.placeholder?\" placeholder='\"+template.escape(this._settings.placeholder)+\"' \":\" \");\n\t\tif (this._settings.readonly)\n\t\t\thtml += \"readonly='true' aria-readonly=''\";\n\t\tif(this._settings.required)\n\t\t\thtml += \"aria-required='true'\";\n\t\tif(this._settings.invalid)\n\t\t\thtml += \"aria-invalid='true'\";\n\n\t\tconst attrs = this._settings.attributes;\n\t\tif (attrs)\n\t\t\tfor(const prop in attrs)\n\t\t\t\thtml += prop+\"='\"+attrs[prop]+\"' \";\n\t\treturn html;\n\t},\n\t$renderLabel: function(config, id){\n\t\tlet label = \"\";\n\n\t\tif (config.label){\n\t\t\tlet top = this._settings.labelPosition == \"top\";\n\t\t\tlet style = `text-align:${config.labelAlign||\"left\"}; line-height:${this._getLabelHeight(top)}px; `;\n\n\t\t\tif (top)\n\t\t\t\tstyle += \"display:block;\";\n\t\t\telse\n\t\t\t\tstyle += config.labelWidth ? `width:${config.labelWidth}px;` : \"display:none;\";\n\n\t\t\tlabel = \"\";\n\t\t}\n\t\treturn label;\n\t},\n\t_getLabelHeight:function(top){\n\t\treturn top ? this._labelTopHeight-this._settings.inputPadding : (this._settings.aheight - 2*this._settings.inputPadding);\n\t},\n\t$renderInput: function(config, div_start, id) {\n\t\tconst inputAlign = (config.inputAlign||\"left\");\n\t\tconst top = (config.labelPosition == \"top\");\n\t\tconst inputWidth = this._get_input_width(config);\n\n\t\tid = id||uid();\n\n\t\tconst label = this.$renderLabel(config,id);\n\t\tlet html = \"\";\n\t\tif(div_start){\n\t\t\thtml += div_start;\n\t\t} else {\n\t\t\tconst value = template.escape(config.text || this._pattern(config.value));\n\t\t\tlet rightPadding = (config.icon || config.clear ? 27 : 0) + (config.icon && config.clear === true ? 24 : 0);\n\t\t\trightPadding = rightPadding && !this.addSection ? \"padding-right:\"+rightPadding+\"px;\" : \"\";\n\n\t\t\thtml += this._baseInputHTML(\"input\")+\"id='\"+id+\"' type='\"+(config.type||this.name)+\"'\"+(config.editable?\" role='combobox'\":\"\")+\n\t\t\t\t\" value='\"+value+\"' style='width:\"+inputWidth+\"px;text-align:\"+inputAlign+\";\"+rightPadding+\"'\";\n\n\t\t\tconst attrs = config.attributes;\n\t\t\tif (attrs)\n\t\t\t\tfor(let prop in attrs)\n\t\t\t\t\thtml += \" \"+prop+\"='\"+attrs[prop]+\"'\";\n\t\t\thtml += \" />\";\n\t\t}\n\t\thtml += this.$renderIcon ? this.$renderIcon(config) : \"\";\n\n\t\tlet result = \"\";\n\t\t//label position, top or left\n\t\tif (top)\n\t\t\tresult = label+\"
\"+html+\"
\";\n\t\telse\n\t\t\tresult = \"
\"+label+html+\"
\";\n\n\t\t//bottom message text\n\t\tconst message = (config.invalid ? config.invalidMessage : \"\") || config.bottomLabel;\n\t\tif (message){\n\t\t\tconst padding = config.awidth - inputWidth - $active.inputPadding;\n\t\t\tresult += \"
\"+message+\"
\";\n\t\t}\n\n\t\treturn result;\n\t},\n\tdefaults:{\n\t\ttemplate:function(obj, common){\n\t\t\treturn common.$renderInput(obj);\n\t\t},\n\t\tlabel:\"\",\n\t\tlabelWidth:80\n\t},\n\t_getLabelWidth: function(width, label, required){\n\t\tif(width == \"auto\")\n\t\t\twidth = getTextSize(label, \"webix_inp_label\"+(required ? \" webix_required\" : \"\")).width;\n\t\treturn width ? Math.max(width, $active.dataPadding) : 0;\n\t},\n\ttype_setter:function(value){ return value; },\n\t_set_inner_size:false,\n\t_set_default_css:function(){},\n\t_pattern:function(value){ return value; },\n\t$setValue:function(value){\n\t\tvalue = this._pattern(value);\n\n\t\tif(this.getInputNode())\n\t\t\tthis.getInputNode().value = value;\n\n\t\tthis._toggleClearIcon(value);\n\t},\n\t$getValue:function(){\n\t\treturn this._pattern(this.getInputNode().value, false);\n\t},\n\tsetValueHere:function(v, data, details){\n\t\tif (details && details.symbol){\n\t\t\tconst s = details.symbol;\n\t\t\tlet value = this.getValue();\n\t\t\tlet last = value.substring(details.pos);\n\n\t\t\tvalue = value.substring(0, details.pos);\n\t\t\tvalue = value.substring(0, value.lastIndexOf(s)+s.length) + v;\n\n\t\t\tthis.setValue(value + last, details.config);\n\t\t\tsetSelectionRange(this.getInputNode(), value.length);\n\t\t} else\n\t\t\tthis.setValue(v, details && details.config);\n\t},\n\tsuggest_setter:function(value){\n\t\tif (value){\n\t\t\tassert(value !== true, \"suggest options can't be set as true, data need to be provided instead\");\n\n\t\t\tif (typeof value == \"string\"){\n\t\t\t\tconst attempt = $$(value);\n\t\t\t\tif (attempt) \n\t\t\t\t\treturn $$(value)._settings.id;\n\n\t\t\t\tvalue = { body: { url:value , dataFeed:value }};\n\t\t\t}\n\t\t\telse if (value.getItem)\n\t\t\t\tvalue = { body: { data:value }};\n\t\t\telse if (isArray(value))\n\t\t\t\tvalue = { body: { data: this._check_options(value) }};\n\t\t\telse if (!value.body)\n\t\t\t\tvalue.body = { };\n\n\t\t\textend(value, { view:\"suggest\" });\n\n\t\t\tconst view = ui(value);\n\t\t\tthis._destroy_with_me.push(view);\n\n\t\t\tthis.$ready.push(() => view._settings.master = this._settings.id);\n\t\t\treturn view._settings.id;\n\t\t}\n\t\treturn false;\n\t}\n};\n\nconst view = protoUI(api, TextPattern, button.view);\nexport default {api, view};","import Number from \"../core/number\";\n\nimport patterns from \"../webix/patterns\";\n\nimport {getSelectionRange, setSelectionRange} from \"../webix/html\";\nimport {bind, isUndefined} from \"../webix/helpers\";\nimport {_event} from \"../webix/htmlevents\";\n\nconst nav_controls = {\n\t9:\"tab\",\n\t38:\"up\",\n\t40:\"down\",\n\t37:\"left\",\n\t39:\"right\"\n};\n\nconst TextPattern = {\n\t$init:function(config){\n\t\tconst pattern = this.defaults.pattern || config.pattern;\n\t\tlet format = this.defaults.format || config.format;\n\t\tconfig.value = isUndefined(config.value) ? \"\" :config.value;\n\n\t\tif (pattern || (format && !this.format_setter)){\n\t\t\tthis.attachEvent(\"onKeyPress\", function(code, e){\n\t\t\t\tif(e.ctrlKey || e.altKey || this._settings.readonly || this._custom_format)\n\t\t\t\t\treturn;\n\n\t\t\t\tif(code>105 && code<112) //numpad operators\n\t\t\t\t\tcode -=64;\n\n\t\t\t\tif(nav_controls[code] && code !== 8 && code !==46){ //del && bsp\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis._on_key_pressed(e, code);\n\t\t\t\treturn false;\n\t\t\t});\n\n\t\t\tthis.attachEvent(\"onAfterRender\", this._after_render);\n\t\t\tthis.getText = function(){ return this.getInputNode().value; };\n\t\t\tthis.$prepareValue = function(value){ return this._pattern(value, false); };\n\t\t\tthis._pattern = function(value, mode){\n\t\t\t\tif (mode === false)\n\t\t\t\t\treturn this._getRawValue(value);\n\t\t\t\telse\n\t\t\t\t\treturn this._matchPattern(value);\n\t\t\t};\n\n\t\t\tif (format){\n\t\t\t\tif (typeof format === \"object\"){\n\t\t\t\t\tthis._custom_format = format;\n\t\t\t\t} else {\n\t\t\t\t\tformat = Number.getConfig(format);\n\t\t\t\t\tthis._custom_format = {\n\t\t\t\t\t\tparse : function(value){ return Number.parse(value, format); },\n\t\t\t\t\t\tedit : function(value){ return Number.format(value, format); },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// initialize pattern before value_setter\n\t\tif (pattern){\n\t\t\tthis._settings.pattern = this.pattern_setter(pattern);\n\t\t\tdelete config.pattern;\n\t\t}\n\t},\n\tpattern_setter:function(value){\n\t\tlet pattern = patterns[value] || value;\n\n\t\tif (typeof pattern == \"string\") pattern = { mask: pattern };\n\t\tpattern.allow = pattern.allow || /[A-Za-z0-9]/g;\n\n\t\tthis._patternScheme(pattern);\n\t\treturn pattern;\n\t},\n\t_init_validation:function(){\n\t\tthis.config.validate = this.config.validate || bind(function(){\n\t\t\tconst value = this.getText();\n\t\t\tconst raw = value.replace(this._pattern_chars, \"\");\n\t\t\tconst matches = (value.toString().match(this._pattern_allows) || []).join(\"\");\n\t\t\treturn (matches.length == raw.length && value.length == this._settings.pattern.mask.length);\n\t\t}, this);\n\t},\n\t_after_render:function(){\n\t\tif (!this._custom_format) \n\t\t\t_event(this.getInputNode(), \"input\", function(){\n\t\t\t\tconst stamp = (new Date()).valueOf();\n\t\t\t\tif(!this._property_stamp || stamp-this._property_stamp>100){\n\t\t\t\t\tthis._property_stamp = stamp;\n\t\t\t\t\tthis.$setValue(this.getText());\n\t\t\t\t}\n\t\t\t}, {bind:this});\n\n\t\t_event(this.getInputNode(), \"blur\", () => this._applyChanges(\"user\"));\n\t},\n\t_patternScheme:function(pattern){\n\t\tlet mask = pattern.mask, scheme = {}, chars = \"\", count = 0;\n\t\t\n\t\tfor(let i = 0; i0) pos += rest;\n\t\t}\n\t\treturn pos;\n\t},\n\t_fixCaretPos:function(pos, code){\n\t\tconst prev = pos-(code !== 46)*1;\n\n\t\tif(this._pattern_scheme[prev] === false){\n\t\t\tpos = pos+(code ==8 ? -1: 1);\n\t\t\treturn this._fixCaretPos(pos, code);\n\t\t}\n\t\tif(this._pattern_scheme[pos] === false && code !==8)\n\t\t\treturn this._fixCaretPos(pos+1, code)-1;\n\t\treturn pos;\n\t},\n\t_getRawValue:function(value){\n\t\tif (this._custom_format)\n\t\t\treturn this._custom_format.parse(value);\n\n\t\tvalue = value || value === 0 ? value : \"\";\n\t\tconst matches = value.toString().match(this._pattern_allows) || [];\n\t\treturn matches.join(\"\").replace(this._pattern_chars, \"\");\n\t},\n\t_matchPattern:function(value){\n\t\tif (this._custom_format)\n\t\t\treturn this._custom_format.edit(this._custom_format.parse(value));\n\n\t\tlet raw = this._getRawValue(value),\n\t\t\tpattern = this._settings.pattern.mask,\n\t\t\tmask = this._settings.pattern.mask,\n\t\t\tscheme = this._pattern_scheme,\n\t\t\tend = false,\n\t\t\tindex = 0,\n\t\t\trawIndex = 0,\n\t\t\trawLength = 0;\n\n\t\tfor(let i in scheme){\n\t\t\tif(scheme[i]!==false){\n\t\t\t\tif(!end){\n\t\t\t\t\tindex = i*1;\n\t\t\t\t\trawIndex = scheme[i];\n\t\t\t\t\tconst rchar = raw[rawIndex]||\"\";\n\t\t\t\t\tconst next = raw[rawIndex+1];\n\n\t\t\t\t\tpattern = (rchar?pattern.substr(0, index):\"\") + rchar +(rchar && next?pattern.substr(index + 1):\"\");\n\t\t\t\t\tif(!next) end = true;\n\t\t\t\t}\n\t\t\t\trawLength++;\n\t\t\t}\n\t\t}\n\n\t\t//finalize value with subsequent mask chars \n\t\tconst icode = this._input_code;\n\t\tif((icode && icode !== 8) || (!icode && rawLength-1 === rawIndex && pattern.length < mask.length)){\n\t\t\tif(raw){\n\t\t\t\tconst nind = index+1;\n\t\t\t\tif(mask.charAt(nind)!==\"#\" && pattern.length < mask.length){\n\t\t\t\t\tlet lind = mask.indexOf(\"#\", nind);\n\t\t\t\t\tif(lind<0) lind = mask.length;\n\t\t\t\t\tpattern += mask.substr(nind, lind-nind);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(icode !==46){\n\t\t\t\tpattern += mask.substr(0, mask.indexOf(\"#\"));\n\t\t\t}\n\t\t}\n\t\tthis._input_code = null;\n\t\treturn pattern;\n\t}\n};\n\nexport default TextPattern;\n","import {protoUI} from \"../ui/core\";\nimport {$active} from \"../webix/skin\";\nimport {uid} from \"../webix/helpers\";\n\nimport template from \"../webix/template\";\nimport HTMLOptions from \"../core/htmloptions\";\n\nimport button from \"../views/button\";\nimport text from \"../views/text\";\n\nconst api = {\n\tname:\"radio\",\n\tdefaults:{\n\t\ttemplate: function(config,common) {\n\t\t\tcommon._check_options(config.options);\n\n\t\t\tconst options = common._filterOptions(config.options);\n\t\t\tconst active = common._getFirstActive();\n\t\t\tlet id, eachid, isChecked, isDisabled, label, tooltip, customRadio, optlabel, rd, input, focusable;\n\t\t\tlet html = [];\n\n\t\t\tfor (let i=0; i < options.length; i++) {\n\t\t\t\teachid = \"x\"+uid();\n\t\t\t\tid = id || eachid;\n\n\t\t\t\tif (i && (options[i].newline || config.vertical))\n\t\t\t\t\thtml.push(\"
\");\n\n\t\t\t\tisChecked = (options[i].id == config.value);\n\t\t\t\tfocusable = isChecked || (!config.value && options[i].id === active);\n\t\t\t\tisDisabled = !!options[i].disabled;\n\t\t\t\tlabel = options[i].value || \"\";\n\t\t\t\ttooltip = config.tooltip ? \" webix_t_id='\"+options[i].id+\"'\" : \"\";\n\t\t\t\t\n\t\t\t\tcustomRadio = config.customRadio|| \"\";\n\t\t\t\tif (customRadio){\n\t\t\t\t\toptlabel = (i === 0 ? config.label+\" \" : \"\")+label;\n\t\t\t\t\tcustomRadio = customRadio.replace(/(aria-label=')\\w*(?=')/, \"$1\"+template.escape(optlabel));\n\t\t\t\t\tcustomRadio = customRadio.replace(/(aria-checked=')\\w*(?=')/, \"$1\"+(isChecked?\"true\":\"false\"));\n\t\t\t\t\tcustomRadio = customRadio.replace(/(tabindex=')\\w*(?=')/, \"$1\"+(!isDisabled && focusable?\"0\":\"-1\"));\n\t\t\t\t\tcustomRadio = customRadio.replace(/(aria-invalid=')\\w*(?=')/, \"$1\"+(config.invalid?\"true\":\"false\"));\n\t\t\t\t\tcustomRadio = customRadio.replace(/(button_id=')\\w*(?=')/, \"$1\"+options[i].id);\n\t\t\t\t\tif (isDisabled)\n\t\t\t\t\t\tcustomRadio = customRadio.replace(\"role='radio'\", \"role='radio' webix_disabled='true'\");\n\t\t\t\t}\n\t\t\t\trd = common._baseInputHTML(\"input\")+\" name='\"+(config.name || config.id)+\"' type='radio' \"+(isChecked?\"checked='1'\":\"\")+\"tabindex=\"+(!isDisabled && focusable?\"0\":\"-1\")+\n\t\t\t\t\t\" value='\"+options[i].id+\"' id='\"+eachid+\"'\"+(isDisabled?\" disabled='true'\":\"\")+\" style='\"+(customRadio?\"display:none\":\"\")+\"' />\";\n\t\t\t\tinput = \"\";\n\n\t\t\t\tif (label)\n\t\t\t\t\tlabel = \"\";\n\n\t\t\t\thtml.push(`
${input+label}
`);\n\t\t\t}\n\t\t\thtml = \"
\"+html.join(\"\")+\"
\";\n\n\t\t\treturn common.$renderInput(config, html, id);\n\t\t}\n\t},\n\trefresh:function(){\n\t\tthis.render();\n\t\tif (this._last_size && this.$getSize(0,0)[2] != this._last_size[1])\n\t\t\tthis.resize();\n\t},\n\t$getSize:function(dx, dy){\n\t\tvar size = button.api.$getSize.call(this, dx, dy);\n\t\tvar options = this._filterOptions(this._settings.options);\n\t\tif (options){\n\t\t\tvar count = this._settings.vertical?0:1;\n\t\t\tfor (var i=0; i < options.length; i++)\n\t\t\t\tif (this._settings.vertical || options[i].newline)\n\t\t\t\t\tcount++;\n\t\t\tsize[3] = size[2] = Math.max(size[2], (this._settings.optionHeight||25) * count+this._settings.inputPadding*2+ (this._settings.labelPosition == \"top\"?this._labelTopHeight:0));\n\t\t}\n\t\tvar heightInc = this.config.bottomPadding;\n\t\tif(heightInc){\n\t\t\tsize[2] += heightInc;\n\t\t\tsize[3] += heightInc;\n\t\t}\n\t\treturn size;\n\t},\n\t_getInputNode: function(){\n\t\treturn this._dataobj.getElementsByTagName(this._settings.customRadio ? \"button\" : \"input\");\n\t},\n\t$setValue:function(value){\n\t\tconst inp = this._dataobj.getElementsByTagName(\"input\");\n\t\tconst active = this._getFirstActive();\n\t\tlet id, option, focusable, parentNode, button;\n\n\t\tfor (let i=0; i < inp.length; i++){\n\t\t\tid = inp[i].parentNode.getAttribute(/*@attr*/\"radio_id\");\n\t\t\toption = this.getOption(id);\n\n\t\t\tinp[i].checked = (id == value);\n\t\t\tfocusable = option && !option.disabled && (inp[i].checked || (!value && option.id == active));\n\t\t\tinp[i].setAttribute(\"tabindex\", focusable?\"0\":\"-1\");\n\n\t\t\tparentNode = inp[i]?inp[i].parentNode:null;\n\t\t\tif (parentNode){\n\t\t\t\tparentNode.className = parentNode.className.replace(/(webix_radio_)\\d/,\"$1\"+(inp[i].checked?1:0));\n\t\t\t\tif (this._settings.customRadio){\n\t\t\t\t\tbutton = parentNode.getElementsByTagName(\"BUTTON\");\n\t\t\t\t\tif (button[0]){\n\t\t\t\t\t\tbutton[0].setAttribute(\"aria-checked\", inp[i].checked?\"true\":\"false\");\n\t\t\t\t\t\tbutton[0].setAttribute(\"tabindex\", focusable?\"0\":\"-1\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tgetValue:function(){\n\t\treturn this._settings.value;\n\t},\n\tfocus: function(){ return this._focus(); },\n\tblur: function(){ this._blur(); },\n\tcustomRadio_setter: function(value){\n\t\tif(value === true && $active.customRadio)\n\t\t\tvalue = \"\";\n\t\treturn value;\n\t},\n\t$skin:function(){\n\t\ttext.api.$skin.call(this);\n\n\t\tthis.defaults.customRadio = !!$active.customRadio;\n\t\tif ($active.optionHeight)\n\t\t\tthis.defaults.optionHeight = $active.optionHeight;\n\t}\n};\n\nconst view = protoUI(api, text.view, HTMLOptions);\nexport default {api, view};","import {protoUI, $$} from \"../ui/core\";\nimport {$active} from \"../webix/skin\";\nimport {isUndefined, isArray} from \"../webix/helpers\";\n\nimport i18n from \"../webix/i18n\";\nimport wDate from \"../core/date\";\n\nimport text from \"./text\";\n\n\nconst api = {\n\tname:\"datepicker\",\n\t_editable:true,\n\t$init:function(config){\n\t\t// value_setter handling\n\t\tif (config.multiselect) {\n\t\t\tthis._settings.multiselect = config.multiselect;\n\t\t}\n\t\tif (config.type){\n\t\t\tthis._settings.type = config.type;\n\t\t}\n\n\t\tthis.$ready.push(this._init_popup);\n\t},\n\tdefaults:{\n\t\ttemplate:function(obj, common){\n\t\t\tif(common._settings.type == \"time\"){\n\t\t\t\tcommon._settings.icon = common._settings.timeIcon;\n\t\t\t}\n\t\t\t//temporary remove obj.type [[DIRTY]]\n\t\t\tconst t = obj.type; obj.type = \"\";\n\t\t\tconst res = obj.editable ? common.$renderInput(obj) : common._render_div_block(obj, common);\n\t\t\tobj.type = t;\n\t\t\treturn res;\n\t\t},\n\t\tstringResult:false,\n\t\ttimepicker:false,\n\t\ticon:\"wxi-calendar\",\n\t\ticons: true,\n\t\ttimeIcon: \"wxi-clock\",\n\t\tseparator:\", \"\n\t},\n\t$onBlur:function(){\n\t\tconst text = this.getText();\n\t\tif (this._settings.text == text)\n\t\t\treturn;\n\n\t\tconst value = this._settings.editable ? this.getValue() : this.getPopup().getValue();\n\t\tthis.setValue(value||\"\", \"user\");\n\t},\n\t$skin:function(){\n\t\ttext.api.$skin.call(this);\n\n\t\tthis.defaults.inputPadding = $active.inputPadding;\n\t\tthis.defaults.point = !$active.popupNoPoint;\n\t},\n\tgetPopup: function(){\n\t\treturn $$(this._settings.popup);\n\t},\n\t_init_popup:function(){ \n\t\tconst obj = this._settings;\n\t\tif (obj.suggest)\n\t\t\tobj.popup = obj.suggest;\n\t\telse if (!obj.popup){\n\t\t\tconst timepicker = this._settings.timepicker;\n\t\t\tobj.popup = obj.suggest = this.suggest_setter({\n\t\t\t\ttype: \"calendar\",\n\t\t\t\tpoint: this._settings.point === false ? false : true,\n\t\t\t\tpadding: 0,\n\t\t\t\tbody: {\n\t\t\t\t\theight: 240 + (timepicker || this._settings.icons ? 30 : 0),\n\t\t\t\t\twidth: 250,\n\t\t\t\t\tmultiselect: this._settings.multiselect, \n\t\t\t\t\ttimepicker: timepicker,\n\t\t\t\t\ttype: this._settings.type,\n\t\t\t\t\ticons: this._settings.icons,\n\t\t\t\t\ttimeIcon: this._settings.timeIcon\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tthis._init_once = function(){};\n\t},\n\t$render:function(obj){\n\t\tthis.$setValue(obj.value);\n\t},\n\t$prepareValue:function(value){\n\t\tif (this._settings.multiselect){\n\t\t\tif (typeof value === \"string\")\n\t\t\t\tvalue = value.split(this._settings.separator);\n\t\t\telse if (value instanceof Date)\n\t\t\t\tvalue = [value];\n\t\t\telse if (!value)\n\t\t\t\tvalue = [];\n\n\t\t\tfor (let i = 0; i < value.length; i++)\n\t\t\t\tvalue[i] = this._prepareSingleValue(value[i]);\n\n\t\t\treturn value;\n\t\t}\n\t\telse\n\t\t\treturn this._prepareSingleValue(value);\n\t},\n\t_prepareSingleValue: function(value) {\n\t\tconst type = this._settings.type;\n\t\tconst timeMode = type == \"time\";\n\n\t\t//setValue(\"1980-12-25\")\n\t\tif (!isNaN(parseFloat(value)))\n\t\t\tvalue = \"\"+value;\n\n\t\tif (typeof value == \"string\" && value){\n\t\t\tlet formatDate = null;\n\t\t\tif ((type == \"month\" || type == \"year\") && this._formatDate)\n\t\t\t\tformatDate = this._formatDate;\n\t\t\telse\n\t\t\t\tformatDate = (timeMode ? i18n.parseTimeFormatDate : i18n.parseFormatDate);\n\t\t\tvalue = formatDate(value);\n\t\t}\n\n\t\tif (value){\n\t\t\t//time mode\n\t\t\tif(timeMode){\n\t\t\t\t//setValue([16,24])\n\t\t\t\tif(isArray(value)){\n\t\t\t\t\tconst time = new Date();\n\t\t\t\t\ttime.setHours(value[0]);\n\t\t\t\t\ttime.setMinutes(value[1]);\n\t\t\t\t\tvalue = time;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//setValue(invalid date)\n\t\t\tif(isNaN(value.getTime()))\n\t\t\t\tvalue = \"\";\n\t\t}\n\n\t\treturn value;\n\t},\n\t_get_visible_text:function(value){\n\t\tif (this._settings.multiselect)\n\t\t\treturn []\n\t\t\t\t.concat(value)\n\t\t\t\t.map(a => this._get_visible_text_single(a))\n\t\t\t\t.join(this.config.separator);\n\t\telse\n\t\t\treturn this._get_visible_text_single(value);\n\t},\n\t_get_visible_text_single:function(value){\n\t\tlet formatStr = this._formatStr;\n\t\tif(!formatStr){\n\t\t\tif(this._settings.type == \"time\")\n\t\t\t\tformatStr = i18n.timeFormatStr;\n\t\t\telse if(this.config.timepicker)\n\t\t\t\tformatStr = i18n.fullDateFormatStr;\n\t\t\telse\n\t\t\t\tformatStr = i18n.dateFormatStr;\n\t\t}\n\t\treturn formatStr(value);\n\t},\n\t_set_visible_text:function(){\n\t\tconst node = this.getInputNode();\n\t\tif(isUndefined(node.value))\n\t\t\tnode.innerHTML = this._settings.text || this._get_div_placeholder();\n\t\telse\n\t\t\tnode.value = this._settings.text || \"\";\n\t},\n\t$compareValue:function(oldvalue, value){\n\t\tif(!oldvalue && !value) return true;\n\t\treturn wDate.equal(oldvalue, value);\n\t},\n\t$setValue:function(value){\n\t\tthis._settings.text = (value?this._get_visible_text(value):\"\");\n\t\tthis._set_visible_text();\n\t\tthis._toggleClearIcon(this._settings.text);\n\t},\n\tformat_setter:function(value){\n\t\tif(value){\n\t\t\tif (typeof value === \"function\")\n\t\t\t\tthis._formatStr = value;\n\t\t\telse {\n\t\t\t\tthis._formatStr = wDate.dateToStr(value);\n\t\t\t\tthis._formatDate = wDate.strToDate(value);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\tthis._formatStr = this._formatDate = null;\n\t\treturn value;\n\t},\n\tgetInputNode: function(){\n\t\treturn this._settings.editable ? this._dataobj.getElementsByTagName(\"input\")[0] : this._dataobj.getElementsByTagName(\"DIV\")[1];\n\t},\n\tgetValue:function(){\n\t\tif (this._settings.multiselect){\n\t\t\tconst value = this._settings.value;\n\t\t\tif (!value) return [];\n\n\t\t\tconst result = []\n\t\t\t\t.concat(value)\n\t\t\t\t.map(a => this._get_value_single(a));\n\n\t\t\tif (this._settings.stringResult)\n\t\t\t\treturn result.join(this._settings.separator);\n\n\t\t\treturn result;\n\t\t}\n\n\t\treturn this._get_value_single(this._settings.value);\n\t},\n\t_get_value_single:function(value){\n\t\tconst type = this._settings.type;\n\t\tconst timeMode = type == \"time\";\n\n\t\t//input was not rendered, we need to parse value from setValue method\n\t\tif (!this._rendered_input)\n\t\t\tvalue = this.$prepareValue(value) || null;\n\t\t//rendere and in edit mode\n\t\telse if (this._settings.editable){\n\t\t\tlet formatDate = this._formatDate;\n\t\t\tif(!formatDate){\n\t\t\t\tif(timeMode)\n\t\t\t\t\tformatDate = i18n.timeFormatDate;\n\t\t\t\telse if(this.config.timepicker)\n\t\t\t\t\tformatDate = i18n.fullDateFormatDate;\n\t\t\t\telse\n\t\t\t\t\tformatDate = i18n.dateFormatDate;\n\t\t\t}\n\n\t\t\tconst time = formatDate(this.getInputNode().value);\n\n\t\t\tif(timeMode && value != \"\"){\n\t\t\t\tvalue.setHours(time.getHours());\n\t\t\t\tvalue.setMinutes(time.getMinutes());\n\t\t\t\tvalue.setSeconds(time.getSeconds());\n\t\t\t\tvalue.setMilliseconds(time.getMilliseconds());\n\t\t\t} else\n\t\t\t\tvalue = time;\n\t\t}\n\n\t\t//return string from getValue\n\t\tif(this._settings.stringResult){\n\t\t\tlet formatStr = i18n.parseFormatStr;\n\t\t\tif(timeMode)\n\t\t\t\tformatStr = i18n.parseTimeFormatStr;\n\t\t\tif(this._formatStr && (type == \"month\" || type == \"year\")){\n\t\t\t\tformatStr = this._formatStr;\n\t\t\t}\n\n\t\t\tif(this._settings.multiselect)\n\t\t\t\treturn [].concat(value).map(a => a ? formatStr(a) : \"\");\n\t\t\treturn (value?formatStr(value):\"\");\n\t\t}\n\n\t\treturn value||null;\n\t},\n\tgetText:function(){\n\t\tconst node = this.getInputNode();\n\t\tif (!node) return \"\";\n\t\tif (isUndefined(node.value)){\n\t\t\tif (node.firstChild && node.firstChild.className === \"webix_placeholder\")\n\t\t\t\treturn \"\";\n\t\t\treturn node.innerHTML;\n\t\t}\n\t\treturn node.value;\n\t}\n};\n\nconst view = protoUI(api, text.view);\nexport default {api, view};","import {protoUI, $$} from \"../ui/core\";\nimport {$active} from \"../webix/skin\";\nimport {isUndefined, bind} from \"../webix/helpers\";\nimport {assert} from \"../webix/debug\";\nimport {preventEvent} from \"../webix/html\";\n\nimport text from \"./text\";\n\n\nconst api = {\n\tname:\"richselect\",\n\tdefaults:{\n\t\ttemplate:function(obj,common){\n\t\t\treturn common._render_div_block(obj, common);\n\t\t},\n\t\tpopupWidth:200,\n\t\ticon: \"wxi-menu-down\"\n\t},\n\t$onBlur:function(){\n\t\tconst text = this.getText();\n\t\tif (this._settings.text == text || (isUndefined(this._settings.text) && !text))\n\t\t\treturn;\n\n\t\tconst suggest = this.getPopup();\n\t\t//handle clicks on suggest items\n\t\tif (suggest.$view.contains(document.activeElement)) \n\t\t\treturn;\n\n\t\tconst newValues = this.config.newValues;\n\t\tconst nodeValue = this.getInputNode().value;\n\t\tconst list = this.getList();\n\n\t\tlet value;\n\t\tif(newValues){\n\t\t\tvalue = list.find(obj => suggest.getItemText(obj.id) == nodeValue, true);\n\t\t\tif(value)\n\t\t\t\tvalue = value.id;\n\t\t\telse if(nodeValue)\n\t\t\t\tvalue = list.add({ value:nodeValue });\n\t\t}\n\t\telse\n\t\t\tvalue = suggest.getSuggestion(nodeValue);\n\n\t\tconst oldvalue = this.getValue();\n\n\t\t//non-empty value that differs from old value and matches filtering rule\n\t\tif (value && value!=oldvalue && !(nodeValue===\"\" && suggest.getItemText(value)!==\"\"))\n\t\t\tthis.setValue(value, \"user\");\n\t\telse if (nodeValue === \"\")\n\t\t\tthis.setValue(\"\", \"user\");\n\t\telse if (this._revertValue)\n\t\t\tthis._revertValue();\n\t},\n\tsuggest_setter:function(value){\n\t\treturn this.options_setter(value);\n\t},\n\toptions_setter:function(value){\n\t\tvalue = this._suggest_config ? this._suggest_config(value) : value;\n\t\tvar suggest = (this._settings.popup = this._settings.suggest = text.api.suggest_setter.call(this, value));\n\t\tvar list = $$(suggest).getList();\n\t\tif (list)\n\t\t\tlist.attachEvent(\"onAfterLoad\", bind(this._reset_value, this));\n\n\t\treturn suggest;\n\t},\n\tgetList: function(){\n\t\tvar suggest = $$(this._settings.suggest);\n\t\tassert(suggest, \"Input doesn't have a list\");\n\t\treturn suggest.getList();\n\t},\n\t_reset_value:function(){\n\t\t// multiselect requires value as an array\n\t\tconst value = this._settings.value||[];\n\t\tif (value.length && !this.getPopup().isVisible() && this.getInputNode() && !(this._settings.text || this.getText()))\n\t\t\tthis.$setValue(value);\n\t},\n\t$skin:function(){\n\t\ttext.api.$skin.call(this);\n\n\t\tthis.defaults.inputPadding = $active.inputPadding;\n\t},\n\t$render:function(obj){\n\t\tthis.$setValue(obj.value);\n\t},\n\tgetInputNode: function(){\n\t\treturn this._dataobj.getElementsByTagName(\"DIV\")[1];\n\t},\n\tgetPopup: function(){\n\t\treturn $$(this._settings.popup);\n\t},\n\tgetText:function(){\n\t\tvar value = this._settings.value,\n\t\t\tnode = this.getInputNode();\n\t\tif(!node)\n\t\t\treturn value?this.getPopup().getItemText(value):\"\";\n\t\tif (isUndefined(node.value)){\n\t\t\tif (node.firstChild && node.firstChild.className === \"webix_placeholder\")\n\t\t\t\treturn \"\";\n\t\t\treturn node.innerHTML;\n\t\t}\n\t\treturn node.value;\n\t},\n\t$prepareValue:function(value){\n\t\tif (value && value.id)\n\t\t\treturn value;\t\t\t//don't convert new items\n\n\t\treturn text.api.$prepareValue.call(this, value);\n\t},\n\t$setValue:function(value){\n\t\tlet text = value;\n\n\t\tconst popup = this.getPopup();\n\t\tif (popup)\n\t\t\ttext = popup.getItemText(value);\n\n\t\tif (value && value.id){ //add new value\n\t\t\tconst list = popup.getList();\n\t\t\tconst exists = list.exists(value.id);\n\n\t\t\t// add new item only when item with such id doesn't exists yet\n\t\t\tif (!exists) list.add(value);\n\n\t\t\ttext = popup.getItemText(value.id);\n\n\t\t\t// in case of dynamic list, we can't add extra items\n\t\t\t// to not interfere with dynamic loading\n\t\t\tif (list._settings.dynamic && !exists)\n\t\t\t\tlist.remove(value.id);\n\n\t\t\tthis._settings.value = this.$prepareValue(value.id);\n\t\t}\n\n\t\tconst node = this.getInputNode();\n\t\tif (isUndefined(node.value))\n\t\t\tnode.innerHTML = text || this._get_div_placeholder();\n\t\telse \n\t\t\tnode.value = text = text.replace(/<[^>]*>/g,\"\");\n\n\t\tthis._settings.text = text;\n\t\tthis._toggleClearIcon(text);\n\t},\n\tgetValue:function(){\n\t\treturn this._settings.value||\"\";\n\t},\n\t_ignoreLabelClick:function(ev){\n\t\tif (ev.type) {\n\t\t\tthis.focus();\n\t\t\tpreventEvent(ev);\n\t\t}\n\t}\n};\n\nconst view = protoUI(api, text.view);\nexport default {api, view};","import {protoUI} from \"../ui/core\";\nimport {$active} from \"../webix/skin\";\n\nimport button from \"./button\";\n\n\nconst api = {\n\tname:\"icon\",\n\t$skin:function(){\n\t\tbutton.api.$skin.call(this);\n\n\t\tthis.defaults.height = $active.inputHeight;\n\t\tthis.defaults.width = $active.inputHeight;\n\t},\n\tdefaults:{\n\t\ttemplate:function(obj, view){\n\t\t\tconst min = Math.min(obj.awidth, obj.aheight);\n\t\t\tconst top = Math.round((view._content_height-obj.aheight)/2);\n\t\t\tconst inner = \"\";\n\n\t\t\tconst lineHeight = obj.aheight != min ? obj.aheight : 0;\n\t\t\treturn \"
\"+inner+(obj.badge||obj.badge===0 ? \"\"+obj.badge+\"\":\"\")+\n\t\t\t\t\"
\";\n\t\t}\n\t},\n\t_set_inner_size:false,\n\t_set_default_css:function(){},\n\t$setValue:function(){}\n};\n\nconst view = protoUI(api, button.view);\nexport default {api, view};","import {protoUI} from \"../ui/core\";\nimport {delay, uid} from \"../webix/helpers\";\nimport {_event} from \"../webix/htmlevents\";\nimport text from \"./text\";\nimport {create, remove, addCss, removeCss, preventEvent} from \"../webix/html\";\nimport {$active} from \"../webix/skin\";\nimport env from \"../webix/env\";\n\nconst autoheight = {\n\t$init: function(){\n\t\t_event(this.$view, \"keydown\", (e) => this._checkPageUp(e));\n\t\tthis.$ready.push(function(){\n\t\t\tif(this._settings.autoheight){\n\t\t\t\taddCss(this.$view, \"webix_noscroll\");\n\t\t\t\tif(!this._settings.maxHeight)\n\t\t\t\t\tthis._settings.maxHeight = 100;\n\t\t\t\t_event(this.$view,\"input\", ()=>{\n\t\t\t\t\tthis._sizeToContent(true);\n\t\t\t\t},{capture: true});\n\t\t\t\tthis.attachEvent(\"onAfterRender\", ()=>{\n\t\t\t\t\tthis._sizeToContent();\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t},\n\t_checkPageUp: function(e){\n\t\t//chrome bug: textarea with typed text is not correctly resized when pushing PageUp/PageDown key\n\t\tconst pageUp = e.key == \"PageUp\";\n\t\tif(env.isChromium && (pageUp || e.key == \"PageDown\")){\n\t\t\tconst input = this.getInputNode();\n\t\t\tconst cursorPos = pageUp ? 0 : input.value.length;\n\t\t\tconst scrollPos = pageUp ? 0 : input.scrollHeight;\n\n\t\t\tpreventEvent(e);\n\t\t\tinput.setSelectionRange(cursorPos, cursorPos);\n\t\t\tinput.scrollTo(0, scrollPos);\n\t\t}\n\t},\n\t_sizeToContent: function(focus){\n\t\tif(this._skipSizing)\n\t\t\treturn (this._skipSizing = false);\n\t\tlet txt = this.getInputNode();\n\t\tlet height = this._getTextHeight(txt.value, txt.offsetWidth);\n\t\tconst padding = 2*$active.inputPadding + 2*$active.borderWidth;\n\t\theight = Math.max(height+padding, this._settings.minHeight);\n\t\tif(height > this._settings.maxHeight){\n\t\t\tremoveCss(this.$view, \"webix_noscroll\");\n\t\t\theight = this._settings.maxHeight;\n\t\t}\n\t\telse\n\t\t\taddCss(this.$view, \"webix_noscroll\",true);\n\t\tconst topView = this.getTopParentView();\n\t\tclearTimeout(topView._template_resize_timer);\n\t\ttopView._template_resize_timer = delay(()=>{\n\t\t\tif (this.config.height != height){\n\t\t\t\tthis.config.height = height;\n\t\t\t\tlet caretPos = txt.selectionEnd;\n\t\t\t\tthis._skipSizing = true;\n\t\t\t\tconst value = text.api.getValue.call(this);\n\t\t\t\tthis.resize();\n\t\t\t\tthis.callEvent(\"onInputResize\",[]);\n\t\t\t\tif(focus){\n\t\t\t\t\ttxt = this.getInputNode();\n\t\t\t\t\t// needed to restore \"\\n\" value after resize\n\t\t\t\t\ttext.api.$setValue.call(this,value);\n\t\t\t\t\ttxt.setSelectionRange(caretPos,caretPos);\n\t\t\t\t\ttxt.focus();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\t_getTextHeight: function(value, width){\n\t\tconst d = create(\"textarea\",{\"class\":\"webix_textarea_measure\", rows: \"1\"},\"\");\n\t\td.style.cssText = \"height:auto;visibility:hidden; position:absolute; top:0px; left:0px; width:\"+width+\"px;\";\n\t\tdocument.body.appendChild(d);\n\t\td.value = value;\n\t\tconst height = d.scrollHeight;\n\t\tremove(d);\n\t\treturn height;\n\t},\n\t$setValue: function(value){\n\t\ttext.api.$setValue.call(this,value);\n\t\tif(this._settings.autoheight)\n\t\t\tthis._sizeToContent();\n\t}\n};\n\nconst api = {\n\tname:\"textarea\",\n\tdefaults:{\n\t\ttemplate:function(obj, common){\n\t\t\tvar name = obj.name || obj.id;\n\t\t\tvar id = \"x\"+uid();\n\n\t\t\tvar html = common._baseInputHTML(\"textarea\")+\"style='width:\"+common._get_input_width(obj)+\"px;'\";\n\t\t\thtml +=\" id='\"+id+\"' name='\"+name+\"' class='webix_inp_textarea'>\"+common._pattern(obj.value)+\"\";\n\n\t\t\treturn common.$renderInput(obj, html, id);\n\t\t},\n\t\tminHeight:60,\n\t},\n\n\t$skin:function(){\n\t\ttext.api.$skin.call(this);\n\t\tthis.defaults.height = 0;\n\t},\n\t_skipSubmit: true,\n\t_getLabelHeight:function(top){\n\t\treturn top ? this._labelTopHeight-this._settings.inputPadding : \"\";\n\t},\n\t$renderIcon:function(){\n\t\treturn \"\";\n\t},\n\t//get input element\n\tgetInputNode: function() {\n\t\treturn this._dataobj.getElementsByTagName(\"textarea\")[0];\n\t}\n};\n\nconst view = protoUI(api, autoheight, text.view);\nexport default {api, view, autoheight};","import base from \"../views/view\";\nimport PagingAbility from \"../core/pagingability\";\nimport DataMarks from \"../core/datamarks\";\nimport AutoTooltip from \"../core/autotooltip\";\nimport ValidateCollection from \"../core/validatecollection\";\nimport RenderStack from \"../core/renderstack\";\nimport DataLoader from \"../core/dataloader\";\nimport EventSystem from \"../core/eventsystem\";\nimport Settings from \"../core/settings\";\n\nimport {protoUI} from \"../ui/core\";\nimport {bind} from \"../webix/helpers\";\n\nconst api = {\n\tname:\"proto\",\n\t$init:function(){\n\t\tthis.data.provideApi(this, true);\n\t\tthis._dataobj = this._dataobj || this._contentobj;\n\t\t\n\t\t//render self , each time when data is updated\n\t\tthis.data.attachEvent(\"onStoreUpdated\",bind(function(){\n\t\t\tthis.render.apply(this,arguments);\n\t\t},this));\n\t},\n\t$setSize:function(){\n\t\tif (base.api.$setSize.apply(this, arguments))\n\t\t\tthis.render();\n\t},\n\t_id:/*@attr*/\"webix_item\",\n\ton_mouse_move:{\n\t},\n\ttype:{}\n};\n\n\nconst view = protoUI(api, PagingAbility, DataMarks, AutoTooltip, ValidateCollection, RenderStack, DataLoader, base.view, EventSystem, Settings);\nexport default {api, view};","import richselect from \"../views/richselect\";\nimport button from \"../views/button\";\nimport list from \"../views/list\";\n\nimport {protoUI, ui, $$} from \"../ui/core\";\nimport {isArray, extend} from \"../webix/helpers\";\n\nimport type from \"../webix/type\";\nimport template from \"../webix/template\";\nimport editors from \"../webix/editors\";\n\nconst api = {\n\tname:\"multiselect\",\n\t$cssName:\"richselect\",\n\tdefaults:{\n\t\tseparator: \",\",\n\t\tstringResult: true\n\t},\n\t_suggest_config:function(value){\n\t\tvar isobj = !isArray(value) && typeof value == \"object\" && !value.name; \n\t\tvar suggest = { view:\"checksuggest\", separator:this.config.separator, buttonText: this.config.buttonText, button: this.config.button };\n\n\t\tif (this._settings.optionWidth)\n\t\t\tsuggest.width = this._settings.optionWidth;\n\t\telse\n\t\t\tsuggest.fitMaster = true;\n\n\t\tif (isobj)\n\t\t\textend(suggest, value, true);\n\n\t\tvar view = ui(suggest);\n\t\tvar list = view.getList();\n\t\tif (typeof value == \"string\")\n\t\t\tlist.load(value);\n\t\telse if (!isobj)\n\t\t\tlist.parse(value);\n\n\t\tview.attachEvent(\"onShow\",function(){\n\t\t\tview.setValue($$(view._settings.master).config.value, \"auto\");\n\t\t});\n\n\t\treturn view;\n\t},\n\t$compareValue:function(oldvalue, value){\n\t\treturn oldvalue.toString() == value.toString();\n\t},\n\t$prepareValue:function(value){\n\t\tvalue = value || [];\n\t\tif (typeof value === \"string\")\n\t\t\treturn value.split(this._settings.separator);\n\t\treturn isArray(value) ? value : [ button.api.$prepareValue.call(this, value) ];\n\t},\n\t$setValue:function(value){\n\t\tif (!this._rendered_input) return;\n\n\t\tconst popup = this.getPopup();\n\t\tlet text = \"\";\n\t\tif (popup){\n\t\t\ttext = popup.setValue(value, \"auto\");\n\t\t\tif (typeof text == \"object\")\n\t\t\t\ttext = text.join(this.config.separator + \" \");\n\t\t}\n\t\tthis._settings.text = text;\n\t\tthis._toggleClearIcon(text);\n\n\t\tconst node = this.getInputNode();\n\t\tnode.innerHTML = text || this._get_div_placeholder();\n\t},\n\tgetValue:function(){\n\t\tconst value = this._settings.value||[];\n\n\t\tif (this._settings.stringResult)\n\t\t\treturn value.join(this._settings.separator);\n\t\treturn value;\n\t},\n};\n\neditors.multiselect = extend({\n\tpopupType:\"multiselect\",\n\tpopupInit:function(popup){\n\t\tpopup.linkInput(document.body);\n\t},\n}, editors.richselect);\n\ntype(list.view, {\n\tname:\"multilist\",\n\ttemplateStart:template(\"
\")\n}, \"default\");\n\ntype(list.view, {\n\tname:\"checklist\",\n\ttemplateStart:template(\"
{common.checkbox()}\"),\n\tcheckbox: function(obj){\n\t\tvar icon = (obj.$checked ? \"wxi-checkbox-marked\" : \"wxi-checkbox-blank\");\n\t\treturn \"\";\n\t},\n\taria:function(obj){\n\t\treturn \"role='option' tabindex='-1' \"+(obj.$checked?\"aria-selected='true'\":\"\")+(obj.disabled?\" aria-disabled=\\\"true\\\" webix_disabled=\\\"true\\\"\":\"\");\n\t},\n\ttemplate: template(\"#value#\")\n}, \"default\");\n\nconst view = protoUI(api, richselect.view);\nexport default {api, view};","import richselect from \"../views/richselect\";\nimport button from \"../views/button\";\nimport {protoUI, ui, $$} from \"../ui/core\";\nimport UIManager from \"../core/uimanager\";\nimport {$active} from \"../webix/skin\";\nimport {_to_array, copy, isArray, extend, uid, delay, isUndefined} from \"../webix/helpers\";\nimport popup from \"../views/popup\";\nimport base from \"../views/view\";\nimport i18n from \"../webix/i18n\";\nimport {create, offset} from \"../webix/html\";\nimport {_event} from \"../webix/htmlevents\";\nimport template from \"../webix/template\";\n\n\nconst api = {\n\tname:\"multicombo\",\n\t$cssName:\"text\",\n\tdefaults:{\n\t\tkeepText: false,\n\t\tseparator: \",\",\n\t\tstringResult: true,\n\t\ticon: false,\n\t\ticonWidth: 0,\n\t\ttagMode: true,\n\t\ttagTemplate: function(values){\n\t\t\treturn (values.length?values.length+\" item(s)\":\"\");\n\t\t},\n\t\ttemplate:function(obj,common){\n\t\t\treturn common._render_value_block(obj, common);\n\t\t}\n\t},\n\t$init:function(){\n\t\tthis.$view.className += \" webix_multicombo\";\n\n\t\tthis.attachEvent(\"onAfterRender\", function(){\n\t\t\tthis._last_size = null;\n\t\t});\n\t\t// prevent scroll to input\n\t\t_event(this.$view, \"scroll\", () => { this.$view[\"scrollTop\"] = 0; });\n\t},\n\t$skin:function(){\n\t\trichselect.api.$skin.call(this);\n\n\t\tthis._inputHeight = $active.inputHeight;\n\t},\n\ton_click: {\n\t\t\"webix_multicombo_delete\": function(e,view,node){\n\t\t\tif(!this._settings.readonly && node)\n\t\t\t\tthis._removeValue(node.parentNode.getAttribute(\"optvalue\"));\n\t\t\treturn false;\n\t\t},\n\t\t\"webix_inp_label\": function(e){this._ignoreLabelClick(e);},\n\t\t\"webix_inp_top_label\": function(e){this._ignoreLabelClick(e);}\n\t},\n\t$onBlur:function(){\n\t\tconst input = this.getInputNode();\n\t\tlet value = input.value;\n\n\t\t//blurring caused by clicks in the suggest list cannot affect new values\n\t\tif (value && this._settings.newValues && new Date()-(this.getPopup()._click_stamp||0)>100){\n\t\t\tvalue = value.trim();\n\t\t\tthis._addNewValue(value, \"user\");\n\t\t}\n\n\t\tthis._inputValue = input.value = (this._settings.keepText) ? value : \"\";\n\t\tthis.$setValue();\n\t},\n\t_reset_value:function(){\n\t\tconst value = this._settings.value||[];\n\t\tif (value.length && !this.getPopup().isVisible())\n\t\t\tthis.$setValue();\n\t},\n\t_removeValue: function(value){\n\t\tconst values = _to_array(copy(this._settings.value||[]));\n\n\t\tlet index;\n\t\tif (value && (index = values.find(value)) !== -1){\n\t\t\tvalues.removeAt(index);\n\t\t\tthis.setValue(values, \"user\");\n\n\t\t\tconst suggest = $$(this.config.suggest);\n\t\t\tif (suggest && suggest._settings.selectAll)\n\t\t\t\tsuggest.getBody()._cells[0].setValue(0, \"auto\");\n\t\t}\n\t},\n\t_addValue: function(newValue, config){\n\t\tvar suggest = $$(this.config.suggest);\n\t\tvar list = suggest.getList();\n\t\tvar item = list.getItem(newValue);\n\n\t\tif(item){\n\t\t\tvar values = suggest.getValue();\n\t\t\tif(values && typeof values == \"string\")\n\t\t\t\tvalues = values.split(suggest.config.separator);\n\t\t\tvalues = _to_array(values||[]);\n\t\t\tif(values.find(newValue)<0){\n\t\t\t\tvalues.push(newValue);\n\t\t\t\tsuggest.setValue(values, config);\n\t\t\t\tthis.setValue(suggest.getValue(), config);\n\t\t\t}\n\t\t}\n\t},\n\t_addNewValue: function(value, config){\n\t\tconst suggest = $$(this.config.suggest);\n\t\tconst list = suggest.getList();\n\n\t\tvalue = template.escape( value.trim() );\n\n\t\tlet id;\n\t\tif (value){\n\t\t\tfor (let i in list.data.pull)\n\t\t\t\tif (suggest.getItemText(i) == value) id = i;\n\n\t\t\tif (!id) id = list.add({value: value});\n\t\t\tthis._addValue(id, config);\n\t\t}\n\t},\n\t_suggest_config:function(value){\n\t\tvar isObj = !isArray(value) && typeof value == \"object\" && !value.name,\n\t\t\tsuggest = { view:\"checksuggest\", separator:this.config.separator, buttonText: this.config.buttonText, button: this.config.button },\n\t\t\tcombo = this;\n\t\t\n\t\tif (isObj){\n\t\t\textend(suggest, value, true);\n\t\t}\n\t\tif (!suggest.width && this._settings.optionWidth){\n\t\t\textend(suggest, {width:this._settings.optionWidth, fitMaster: false}, true);\n\t\t}\n\t\tsuggest.width = suggest.fitMaster || isUndefined(suggest.fitMaster) ? 0 : suggest.width;\n\n\t\tvar view = ui(suggest);\n\t\tif(!suggest.width)\n\t\t\tview.$customWidth = function(){\n\t\t\t\tthis.config.width = combo._get_input_width(combo._settings);\n\t\t\t};\n\t\tview.attachEvent(\"onBeforeShow\",function(node,mode, point){\n\t\t\tif(this._settings.master){\n\t\t\t\tthis.setValue($$(this._settings.master).config.value, \"auto\");\n\n\t\t\t\tif($$(this._settings.master).getInputNode().value || this.isVisible()){\n\t\t\t\t\tthis.getList().refresh();\n\t\t\t\t\tthis._dont_unfilter = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tthis.getList().filter();\n\n\t\t\t\tif(node.tagName && node.tagName.toLowerCase() == \"input\"){\n\t\t\t\t\tpopup.api.show.apply(this, [node.parentNode,mode, point]);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t});\n\n\t\tvar list = view.getList();\n\t\tif (typeof value == \"string\")\n\t\t\tlist.load(value);\n\t\telse if (!isObj)\n\t\t\tlist.parse(value);\n\n\t\t//prevent default show-hide logic\n\t\tview._suggest_after_filter = function(){\n\t\t\tif (!this._resolve_popup) return true;\n\t\t\tthis._resolve_popup = false;\n\n\t\t\tthis.show(combo._getInputDiv());\n\t\t};\n\n\t\treturn view;\n\t},\n\t_render_value_block:function(obj, common){\n\t\tvar id, input, inputAlign,inputStyle, inputValue, inputWidth,\n\t\t\theight, html, label, list, message, padding, readOnly, width,\n\t\t\tbottomLabel = \"\",\n\t\t\ttop = this._settings.labelPosition == \"top\";\n\n\t\tid = \"x\"+uid();\n\t\twidth = common._get_input_width(obj);\n\t\tinputAlign = obj.inputAlign || \"left\";\n\n\t\theight = this._input_height - 2*$active.inputPadding -2;\n\n\t\tinputValue = (this._inputValue||\"\");\n\t\tlist = \"
    \";\n\n\t\tinputWidth = Math.min(width,(common._inputWidth||7));\n\n\t\tinputStyle = \"width:\"+inputWidth+\"px;height:\"+height+\"px;max-width:\"+(width-20)+\"px\";\n\n\t\treadOnly = obj.readonly?\" readonly \":\"\";\n\t\tinput = \"\";\n\t\thtml = \"
    \"+list+input +\"
    \";\n\n\t\tlabel = common.$renderLabel(obj,id);\n\n\t\tpadding = this._settings.awidth - width - $active.inputPadding*2;\n\t\tmessage = (obj.invalid ? obj.invalidMessage : \"\") || obj.bottomLabel;\n\t\tif (message)\n\t\t\tbottomLabel = \"
    \"+message+\"
    \";\n\n\t\tif (top)\n\t\t\treturn label+\"
    \"+html+bottomLabel+\"
    \";\n\t\telse\n\t\t\treturn \"
    \"+label+html+bottomLabel+\"
    \";\n\t},\n\t_getValueListBox: function(){\n\t\treturn this._getBox().getElementsByTagName(\"UL\")[0];\n\t},\n\t_set_inner_size: function(){\n\t\tconst popup = this.getPopup();\n\t\tif (popup) {\n\t\t\tconst textArr = (popup ? popup.setValue(this._settings.value, \"auto\") : null);\n\t\t\tif (popup._toMultiValue)\n\t\t\t\tthis._settings.value = popup._toMultiValue(this._settings.value);\n\t\t\tlet html = \"\";\n\t\t\tconst listbox = this._getValueListBox();\n\t\t\tconst text = textArr && textArr.length;\n\t\t\tif (text){\n\t\t\t\t// 2px border; 6px margin\n\t\t\t\tconst width = this._get_input_width(this._settings) - 2 - 6;\n\t\t\t\tconst height = this._input_height - 2*$active.inputPadding - 2 - 6;\n\t\t\t\tconst values = this._settings.value || [];\n\n\t\t\t\tif (this._settings.tagMode) {\n\t\t\t\t\tfor (let i = 0; i < textArr.length; i++){\n\t\t\t\t\t\thtml += this.$renderTag(textArr[i], width, height, values[i]);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\thtml += \"
  • \"+this._settings.tagTemplate(values)+\"
  • \";\n\t\t\t\t}\n\n\t\t\t}\n\t\t\tlistbox.innerHTML = html;\n\t\t\t// reset placeholder\n\t\t\tconst inp = this.getInputNode();\n\t\t\tif (this._settings.placeholder) {\n\t\t\t\tif (text) {\n\t\t\t\t\tinp.placeholder = \"\";\n\t\t\t\t\tif (!inp.value && inp.offsetWidth > 20)\n\t\t\t\t\t\tinp.style.width = \"20px\";\n\t\t\t\t} else if (!inp.value) {\n\t\t\t\t\tinp.placeholder = this._settings.placeholder;\n\t\t\t\t\tinp.style.width = this._get_input_width(this._settings)+\"px\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!this._settings.tagMode && listbox.firstChild)\n\t\t\t\tinp.style.width = this._getMultiComboInputWidth() +\"px\";\n\t\t}\n\t\tif(this._resizedToContent)\n\t\t\tdelete this._resizedToContent;\n\t\telse\n\t\t\tthis._resizeToContent();\n\t},\n\t$renderTag(text, width, height, value){\n\t\tconst c = this._settings;\n\t\tconst content = \"\"+text+\"\";\n\t\tconst remove = c.readonly ? \"\" : \"\";\n\t\treturn \"
  • \"+content+remove+\"
  • \";\n\t},\n\t_focusAtEnd: function(input){\n\t\tinput = input||this.getInputNode();\n\t\tif (input){\n\t\t\tconst length = input.value.length;\n\t\t\tinput.selectionStart = length;\n\t\t\tinput.selectionEnd = length;\n\t\t\tinput.focus();\n\t\t}\n\t},\n\t_resizeToContent: function(enter){\n\t\tconst top = this._settings.labelPosition == \"top\";\n\t\tconst inputDiv = this._getInputDiv();\n\t\tlet inputHeight = Math.max(inputDiv.offsetHeight + 2*$active.inputPadding, this._input_height);\n\n\t\tif (top) inputHeight += this._labelTopHeight;\n\t\tinputHeight += this._settings.bottomPadding ||0;\n\n\t\tconst sizes = this.$getSize(0,0);\n\t\tif(inputHeight != sizes[2]){\n\t\t\tconst calcHeight = inputDiv.offsetHeight + (top?this._labelTopHeight:0) + 2*$active.inputPadding;\n\t\t\tconst topView = this.getTopParentView();\n\n\t\t\tclearTimeout(topView._template_resize_timer);\n\t\t\ttopView._template_resize_timer = delay(function(){\n\t\t\t\tif (this.config.height != calcHeight){\n\t\t\t\t\tthis.config.height = calcHeight;\n\t\t\t\t\tthis._resizedToContent = true;\n\t\t\t\t\tthis.resize();\n\t\t\t\t}\n\n\t\t\t\tif (UIManager.getFocus() === this){\n\t\t\t\t\tif (enter)\n\t\t\t\t\t\tthis.getInputNode().select();\n\t\t\t\t\telse\n\t\t\t\t\t\tthis._focusAtEnd(this.getInputNode());\n\t\t\t\t}\n\n\t\t\t\tconst suggest = this.getPopup();\n\t\t\t\tif (suggest.isVisible()){\n\t\t\t\t\tconst inputDiv = this._getInputDiv();\n\n\t\t\t\t\tlet pos;\n\t\t\t\t\tconst scroll = this.queryView(view => view.config.scroll && view.config.scroll.indexOf(\"y\") != -1, \"parent\");\n\n\t\t\t\t\tif(scroll){\n\t\t\t\t\t\tconst inputPos = offset(inputDiv);\n\t\t\t\t\t\tconst scrollPos = offset(scroll.$view);\n\n\t\t\t\t\t\tif(inputPos.y + inputPos.height > scrollPos.y + scrollPos.height)\n\t\t\t\t\t\t\tpos = {pos:\"top\"};\n\t\t\t\t\t}\n\n\t\t\t\t\tsuggest.show(inputDiv, pos);\n\t\t\t\t}\n\n\t\t\t}, this);\n\t\t}\n\t\tif (enter)\n\t\t\tthis.getInputNode().select();\n\t},\n\t_getInputDiv: function(){\n\t\tvar parentNode = this._getBox();\n\t\tvar nodes = parentNode.childNodes;\n\t\tfor(var i=0; i < nodes.length; i++){\n\t\t\tif(nodes[i].className && nodes[i].className.indexOf(\"webix_inp_static\")!=-1)\n\t\t\t\treturn nodes[i];\n\t\t}\n\t\treturn parentNode;\n\t},\n\tgetInputNode: function(){\n\t\treturn this._dataobj.getElementsByTagName(\"INPUT\")[0];\n\t},\n\t$compareValue:function(oldvalue, value){\n\t\treturn oldvalue.toString() == value.toString();\n\t},\n\t$prepareValue:function(value){\n\t\tvalue = value || [];\n\t\tif (typeof value === \"string\")\n\t\t\treturn value.split(this._settings.separator);\n\t\treturn isArray(value) ? value : [ button.api.$prepareValue.call(this, value) ];\n\t},\n\t$setValue:function(){\n\t\tif (this._rendered_input)\n\t\t\tthis._set_inner_size();\n\t},\n\tgetValue:function(config){\n\t\tif(typeof config == \"object\" && config.options)\n\t\t\treturn this._getSelectedOptions();\n\n\t\tconst value = this._settings.value||[];\n\n\t\tif (this._settings.stringResult)\n\t\t\treturn value.join(this._settings.separator);\n\t\treturn value;\n\t},\n\tgetText:function(){\n\t\tvar value = this._settings.value||[];\n\t\tif(!value.length) return \"\";\n\n\t\tvar text = [];\n\t\tfor(var i = 0; i${value.replace(/&/g,\"&\").replace(//g,\">\")}`;\n\n\t\tdocument.body.appendChild(tmp);\n\t\tconst width = tmp.offsetWidth+1;\n\n\t\tdocument.body.removeChild(tmp);\n\t\treturn width;\n\t},\n\t_getMultiComboInputWidth: function(){\n\t\tconst listbox = this._getValueListBox();\n\t\tconst width = listbox.offsetWidth - (listbox.firstChild.offsetWidth + 1);\n\t\treturn (width <= 25)? listbox.offsetWidth-12: width-15;\n\t},\n\t_getLastInputValue:function(value, config){\n\t\tconst newValues = value.split(this._settings.separator);\n\t\tconst suggest = this.getPopup();\n\t\tlet last = \"\";\n\n\t\tfor (let i=0; i -1)){\n\t\t\t\tconst nValue = this._getLastInputValue(input.value, \"user\");\n\t\t\t\tthis._inputValue = input.value = (this._settings.keepText) ? nValue : \"\";\n\t\t\t\tenter = this._settings.keepText;\n\t\t\t}\n\n\t\t\t// to show placeholder\n\t\t\tlet calcWidth, width;\n\t\t\tconst value = this._settings.value||[];\n\t\t\tif (this._settings.placeholder && !input.value && !value.length)\n\t\t\t\twidth = this._get_input_width(this._settings);\n\t\t\telse {\n\t\t\t\twidth = calcWidth = this._calcInputWidth(input.value);\n\t\t\t\tif(!this._settings.tagMode && this._getValueListBox().firstChild)\n\t\t\t\t\twidth = this._getMultiComboInputWidth();\n\t\t\t}\n\n\t\t\t// resize\n\t\t\tinput.style.width = width + \"px\";\n\n\t\t\tif (enter || calcWidth != this._inputWidth){\n\t\t\t\tthis._inputWidth = calcWidth||width;\n\n\t\t\t\t// save value before possible rendering\n\t\t\t\tthis._inputValue = input.value;\n\t\t\t\tthis._resizeToContent(enter);\n\t\t\t}\n\n\t\t},{bind:this});\n\n\t\t_event(this.getInputNode(), \"keydown\", function(e){\n\t\t\tconst input = this.getInputNode();\n\t\t\tconst suggest = this.getPopup();\n\n\t\t\tconst code = e.which || e.keyCode;\n\n\t\t\t// remove the last value on Backspace click\n\t\t\tconst node = this._getValueListBox().lastChild;\n\t\t\tif (code == 8 && !this._settings.readonly && node){\n\t\t\t\tif(!input.value && ((new Date()).valueOf() - (this._backspaceTime||0) > 100)){\n\t\t\t\t\tthis._removeValue(node.getAttribute(\"optvalue\"));\n\t\t\t\t} else {\n\t\t\t\t\tthis._backspaceTime = (new Date()).valueOf();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (code == 13 || code == 9){\n\t\t\t\tlet nValue = input.value;\n\t\t\t\tif (!suggest.getList().getSelectedId()){\n\t\t\t\t\tnValue = this._getLastInputValue(input.value, \"user\");\n\t\t\t\t}\n\t\t\t\tthis._inputValue = input.value = (this._settings.keepText) ? nValue : \"\";\n\n\t\t\t\tconst value = this._settings.value||[];\n\t\t\t\tif (code == 13 && !input.value && !value.length){\n\t\t\t\t\tsuggest.getList().filter();\n\n\t\t\t\t\t// correct input width to show placeholder\n\t\t\t\t\tif (this._settings.placeholder)\n\t\t\t\t\t\tinput.style.width = this._get_input_width(this._settings) + \"px\";\n\t\t\t\t}\n\t\t\t\tthis._resizeToContent(code == 13);\n\t\t\t}\n\t\t},{bind:this});\n\n\t\t$$(this._settings.suggest).linkInput(this);\n\t}\n};\n\n\nconst view = protoUI(api, richselect.view);\nexport default {api, view};","import text from \"../views/text\";\nimport {preventEvent, addCss, removeCss, pos as getPos, offset} from \"../webix/html\";\nimport {protoUI} from \"../ui/core\";\nimport {$active} from \"../webix/skin\";\nimport env from \"../webix/env\";\nimport {uid, bind, isArray, copy} from \"../webix/helpers\";\nimport {_event, event, eventRemove} from \"../webix/htmlevents\";\nimport template from \"../webix/template\";\n\nconst api = {\n\tname:\"slider\",\n\tdefaults:{\n\t\tmin:0,\n\t\tmax:100,\n\t\tvalue:50,\n\t\tstep:1,\n\t\ttitle:false,\n\t\tmoveTitle:true,\n\t\ttemplate:function(obj, common){\n\t\t\tconst id = common._handle_id = \"x\" +uid();\n\t\t\tlet html = \"\";\n\t\t\tconst title = \"
     
    \";\n\t\t\tconst left = \"
     
    \";\n\t\t\tconst right = \"
    \";\n\t\t\tconst handle = \"
     
    \";\n\n\t\t\tif(obj.vertical) html = \"
    \"+right+left+handle+\"
    \"+title;\n\t\t\telse html = title+\"
    \"+left+right+handle+\"
    \";\n\t\t\treturn common.$renderInput(obj, html, id);\n\t\t}\n\t},\n\ttype_setter:function(type){\n\t\tthis._viewobj.className += \" webix_slider_\"+type;\n\t},\n\ttitle_setter:function(value){\n\t\tif (typeof value == \"string\")\n\t\t\treturn template(value);\n\t\treturn value;\n\t},\n\t_get_slider_handle:function(){\n\t\treturn this.$view.querySelector(\".webix_slider_handle\");\n\t},\n\t_set_inner_size:function(){\n\t\tconst handle = this._get_slider_handle();\n\t\tconst config = this._settings;\n\n\t\tif(handle){ //view is rendered for sure\n\t\t\tconst size = config.vertical?this._content_height:this._get_input_width(config); //width or height\n\t\t\tlet value = config.value%config.step?(Math.round(config.value/config.step)*config.step):config.value;\n\t\t\tconst max = config.max - config.min;\n\n\t\t\tvalue = this._safeValue(value);\n\t\t\tvalue = config.vertical?(max-(value-config.min)):(value-config.min);\n\n\t\t\t//top or left\n\t\t\tlet corner1 = Math.ceil((size - 2 * this._sliderPadding) * value / max);\n\t\t\t//bottom or right\n\t\t\tlet corner2 = size - 2 * this._sliderPadding - corner1;\n\n\t\t\tconst cornerStr = config.vertical?\"top\":\"left\";\n\t\t\tconst sizeStr = config.vertical?\"height\":\"width\";\n\n\t\t\thandle.style[cornerStr] = this._sliderPadding + corner1 - this._sliderHandleWidth / 2 + \"px\";\n\t\t\thandle.parentNode.style[sizeStr] = size+\"px\";\n\n\t\t\t//1px border\n\t\t\tcorner2 = this._safeValue(corner2, 2 * this._sliderBorder, size - this._sliderPadding * 2 - 2 * this._sliderBorder);\n\t\t\tcorner1 = this._safeValue(corner1, 2 * this._sliderBorder, size - this._sliderPadding * 2 - 2 * this._sliderBorder);\n\n\t\t\t//width for left/top and right/bottom bars\n\t\t\tconst part = handle.previousSibling;\n\t\t\tpart.style[sizeStr] = corner2 + \"px\";\n\t\t\tconst last = part.previousSibling;\n\t\t\tlast.style[sizeStr] = corner1 + \"px\";\n\n\t\t\tthis._set_title(handle, corner1, corner2, cornerStr);\n\t\t}\n\t},\n\t_set_title:function(handle, corner1, corner2, cornerStr){\n\t\tconst config = this._settings;\n\t\tif (this._settings.title){\n\t\t\tconst title = handle.parentNode[config.vertical?\"nextSibling\":\"previousSibling\"];\n\t\t\ttitle.innerHTML = this._settings.title(this._settings, this);\n\n\t\t\tif(this._settings.moveTitle){\n\t\t\t\tlet pos = 0;\n\t\t\t\tif(config.vertical) pos = corner1+2 * this._sliderBorder-this._sliderHandleWidth/2;\n\t\t\t\telse{\n\t\t\t\t\tconst half = title.clientWidth/2;\n\t\t\t\t\tconst pos1 = half>corner1 ? (half-corner1-2*this._sliderBorder): 0;//left/top text is to large\n\t\t\t\t\tconst pos2 = half>corner2 ? (half-corner2-2*this._sliderBorder-this._sliderHandleWidth/2): 0;//right/bottom text is too large\n\t\t\t\t\tpos = this._sliderPadding + corner1 - half + pos1 - pos2;\n\t\t\t\t}\n\t\t\t\ttitle.style[cornerStr] = pos+ \"px\";\n\t\t\t}\n\t\t}\n\t},\n\t_set_value_now:function(){\n\t\tthis._get_slider_handle().setAttribute(\"aria-valuenow\", this._settings.value);\n\t},\n\t_safeValue: function(value, min, max){\n\t\tmin = min ? min : this._settings.min;\n\t\tmax = max ? max : this._settings.max;\n\t\t\n\t\treturn Math.min(Math.max(value, min), max);\n\t},\n\trefresh:function(){\n\t\tconst handle = this._get_slider_handle();\n\t\tif (handle){\n\t\t\tthis._set_value_now();\n\t\t\tif (this._settings.title)\n\t\t\t\thandle.setAttribute(\"aria-label\", this._settings.label+\" \"+this._settings.title(this._settings, this));\n\n\t\t\tthis._set_inner_size();\n\t\t}\n\t},\n\t$setValue:function(){\n\t\tthis.refresh();\n\t},\n\t$getValue:function(){\n\t\treturn this._settings.value;\n\t},\n\t$prepareValue:function(value){\n\t\tvalue = parseFloat(value);\n\n\t\tif(isNaN(value))\n\t\t\tvalue = this._settings.min;\n\n\t\treturn this._safeValue(value);\n\t},\n\t$init:function(config){\n\t\t_event(this._viewobj, env.mouse.down, e => this._on_mouse_down_start(e, \"mouse\"));\n\t\tif (env.touch)\n\t\t\t_event(this._viewobj, env.touch.down, e => this._on_mouse_down_start(e, \"touch\"));\n\n\t\t_event( this.$view, \"keydown\", bind(this._handle_move_keyboard, this));\n\t\tif (config.vertical){\n\t\t\tconfig.height = config.height || $active.vSliderHeight;\n\t\t\tthis._viewobj.className += \" webix_slider_vertical\";\n\t\t\tthis._sliderPadding = $active.vSliderPadding;\n\t\t}\n\t},\n\t$skin: function(){\n\t\ttext.api.$skin.call(this);\n\n\t\tthis._sliderHandleWidth = $active.sliderHandleWidth; //8 - width of handle / 2\n\t\tthis._sliderPadding = $active.sliderPadding;//10 - padding of webix_slider_box ( 20 = 10*2 )\n\t\tthis._sliderBorder = $active.sliderBorder;//1px border\n\t},\n\t_handle_move_keyboard:function(e){\n\t\tconst code = e.which || e.keyCode;\n\t\tconst c = this._settings;\n\t\tlet value = c.value;\n\n\t\tif(code>32 && code <41){\n\t\t\tpreventEvent(e);\n\n\t\t\tconst trg = e.target;\n\t\t\tconst match = /webix_slider_handle_(\\d)/.exec(trg.className);\n\t\t\tthis._activeIndex = match?parseInt(match[1],10):-1;\n\t\t\tif(match)\n\t\t\t\tvalue = c.value[this._activeIndex];\n\n\t\t\tvalue = valuec.max ? c.max : value);\n\t\t\t\n\t\t\tif(code === 36) value = c.min;\n\t\t\telse if(code === 35) value = c.max;\n\t\t\telse{\n\t\t\t\tlet inc = (code === 37 || code === 40 || code === 34) ? -1 : 1;\n\t\t\t\tif(code === 33 || code === 34 || c.step > 1)\n\t\t\t\t\tinc = inc * c.step;\n\t\t\t\tvalue = value*1 + inc;\n\t\t\t}\n\n\t\t\tif(match){\n\t\t\t\tconst other = c.value[this._activeIndex?0:1];\n\t\t\t\tvalue = ((this._activeIndex && value <= other) || (!this._activeIndex && value >= other )) ? other : value;\n\t\t\t}\n\n\t\t\tif(value >= c.min && value <= c.max){\n\t\t\t\tif(match){\n\t\t\t\t\tconst temp =[];\n\t\t\t\t\tfor(let i = 0; i < c.value.length; i++)\n\t\t\t\t\t\ttemp[i] = i === this._activeIndex ? value : c.value[i];\n\t\t\t\t\tvalue = temp;\n\t\t\t\t}\n\t\t\t\tthis.setValue(value, \"user\");\n\t\t\t\tthis._activeIndex = -1;\n\t\t\t}\n\t\t}\n\t},\n\t_on_mouse_down_start:function(e, pointer){\n\t\tconst config = this._settings;\n\t\tif (config.disabled || config.readonly) return;\n\n\t\tconst trg = e.target;\n\t\tif (this._mouse_down_process)\n\t\t\tthis._mouse_down_process(e);\n\n\t\tlet value = config.value;\n\t\tif (isArray(value)) value = copy(value);\n\n\t\tthis._start_value = value;\n\t\tif (trg.className.indexOf(\"webix_slider\") !== -1)\n\t\t\tconfig.value = this._get_value_from_event(e);\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), passive),\n\t\t\tevent(document, env[pointer].up, () => this._handle_move_stop()),\n\t\t];\n\t\taddCss(document.body,\"webix_noselect\");\n\t},\n\t_handle_move_stop:function(){\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\tlet value = this._settings.value;\n\t\tif (isArray(value)) value = copy(value);\n\n\t\tthis._settings.value = this._start_value;\n\t\tthis.setValue(value, \"user\");\n\n\t\tthis._get_slider_handle(this._activeIndex).focus();\n\t\tthis._activeIndex = -1;\n\n\t\tremoveCss(document.body, \"webix_noselect\");\n\t},\n\t_handle_move_process:function(e, pointer){\n\t\tthis._settings.value = this._get_value_from_event(e);\n\t\tthis.refresh();\n\t\tthis.callEvent(\"onSliderDrag\", []);\n\n\t\tif (pointer === \"touch\") preventEvent(e);\n\t},\n\t_get_value_from_event:function(e){\n\t\tconst ax = this._settings.vertical ? \"y\" : \"x\";\n\t\tconst pos = getPos(e)[ax];\n\t\treturn this._get_value_from_pos(pos);\n\t},\n\t_get_value_from_pos:function(pos){\n\t\tconst config = this._settings;\n\t\tconst max = config.max - config.min;\n\t\tconst ax = config.vertical ? \"y\" : \"x\";\n\n\t\t//top or left depending on slider type\n\t\tconst corner = offset(this._get_slider_handle().parentNode)[ax] + this._sliderPadding;\n\t\t//height or width depending on slider type\n\t\tconst size = (config.vertical?this._content_height:this._get_input_width(config))-2*this._sliderPadding;\n\n\t\tlet newvalue = (size ? (pos-corner) * max / size : 0);\n\t\tif(config.vertical)\n\t\t\tnewvalue = max-newvalue;\n\t\tnewvalue = Math.round((newvalue + 1*config.min) / config.step) * config.step;\n\t\treturn this._safeValue(newvalue);\n\t},\n\t_init_onchange:function(){} //need not ui.text logic\n};\n\nconst view = protoUI(api, text.view);\nexport default {api, view};\n","import slider from \"../views/slider\";\nimport {offset} from \"../webix/html\";\nimport {protoUI} from \"../ui/core\";\nimport {uid, isArray, isUndefined} from \"../webix/helpers\";\n\n\n// #include ui/slider.js\n\nconst api = {\n\tname:\"rangeslider\",\n\t$cssName:\"slider webix_rangeslider\",\n\tdefaults:{\n\t\tseparator: \",\",\n\t\tmin: 0,\n\t\tmax: 100,\n\t\tvalue: [20,80],\n\t\ttemplate:function(obj, common){\n\t\t\tvar id = \"x\" + uid();\n\t\t\tcommon._handle_id = [id+\"_0\",id+\"_1\"];\n\n\t\t\tvar aria = \"role='slider' aria-label='\"+obj.label+(obj.title?(\" \"+obj.title(obj)):\"\")+\"' aria-valuemax='\"+obj.max+\"' aria-valuemin='\"+obj.min+\"' tabindex='0'\";\n\t\t\tvar handles = \"
     
    \";\n\t\t\thandles += \"
     
    \";\n\n\t\t\tvar title = \"
     
    \";\n\t\t\tif(obj.moveTitle)\n\t\t\t\ttitle = \"
    \"+(title+title)+\"
    \";\n\t\t\t\n\t\t\tvar parts = \"
     
    \";\n\t\t\tvar html = \"\";\n\t\t\tif(obj.vertical) html = \"
    \"+parts+handles+\"
    \"+title;\n\t\t\telse html = title+\"
    \"+parts+handles+\"
    \";\n\t\t\treturn common.$renderInput(obj, html, id);\n\t\t}\n\t},\n\t$prepareValue:function(value){\n\t\tconst min = this._settings.min;\n\n\t\tif(!isArray(value)){\n\t\t\tvalue = (value||\"\").toString().split(this._settings.separator);\n\t\t}\n\n\t\tvalue[0] = parseFloat(value[0]);\n\t\tvalue[0] = isNaN(value[0]) ? min : this._safeValue(value[0]);\n\n\t\tif(value.length < 2)\n\t\t\tvalue[1] = value[0];\n\t\telse{\n\t\t\tvalue[1] = parseFloat(value[1]);\n\t\t\tvalue[1] = isNaN(value[1]) ? value[0] : this._safeValue(value[1]);\n\t\t}\n\t\tif(value[0]>value[1]) [value[0], value[1]] = [value[1], value[0]];\n\t\treturn value;\n\t},\n\t_get_slider_handle:function(index){\n\t\tindex = index && index>=0?index:0;\n\t\treturn this.$view.querySelector(\".webix_slider_handle_\"+(index||0));\n\t},\n\t_get_left_pos: function(size,index){\n\t\tvar config, max, value;\n\n\t\tconfig = this._settings;\n\t\tmax = config.max - config.min;\n\t\tvalue = config.value[index]%config.step?(Math.round(config.value[index]/config.step)*config.step):config.value[index];\n\t\tvalue = this._safeValue(value);\n\t\treturn Math.ceil((size - this._sliderPadding*2) * (value-config.min) / max);\n\t},\n\t_set_left_pos:function(size, left, vertical){\n\t\tvar pos = this._sliderPadding + left - (this._sliderHandleWidth / 2 *(vertical?-1:1));\n\t\tpos = vertical? size-pos:pos;\n\t\treturn pos+\"px\";\n\t},\n\t_set_value_pos:function(size, left, length, vertical){\n\t\tvar pos = left+this._sliderPadding + 2 * this._sliderBorder;\n\t\tif(vertical) pos = size-pos-length;\n\t\treturn pos + \"px\";\n\t},\n\t_set_inner_size:function(){\n\t\tvar config, handle0, handle1,\n\t\t\tleft0, left1, max, length, parentBox,\n\t\t\tsizeStr, size, cornerStr;\n\n\t\thandle0 =this._get_slider_handle(0);\n\t\thandle1 = this._get_slider_handle(1);\n\t\tconfig = this._settings;\n\n\t\tif(!isArray(config.value)){\n\t\t\tthis.define(\"value\", config.value);\n\t\t}\n\n\t\tif (handle0){\n\t\t\tsizeStr = config.vertical?\"height\":\"width\";\n\t\t\tcornerStr = config.vertical?\"top\":\"left\";\n\t\t\t\n\t\t\tsize = config.vertical?this._content_height:this._get_input_width(config);\n\t\t\tmax = size - this._sliderPadding * 2 - 2 * this._sliderBorder;\n\t\t\t\n\t\t\tleft0 = this._get_left_pos(size, 0);\n\t\t\tleft1 = this._get_left_pos(size, 1);\n\t\t\tlength = left1 - left0;\n\n\t\t\thandle0.style[cornerStr] = this._set_left_pos(size, left0, config.vertical);\n\t\t\thandle1.style[cornerStr] = this._set_left_pos(size, left1, config.vertical);\n\t\t\t\n\t\t\tparentBox = handle0.parentNode;\n\t\t\tparentBox.style[sizeStr] = size+\"px\";\n\t\t\tparentBox.firstChild.style[sizeStr] = max + \"px\";\n\t\t\tparentBox.childNodes[1].style[sizeStr] = length + \"px\";\n\t\t\tparentBox.childNodes[1].style[cornerStr] = this._set_value_pos(size, left0, length, config.vertical);\n\n\t\t\tthis._set_title(handle0, [left0, left1], max, cornerStr);\n\t\t}\n\t},\n\t_title_hidden:0,\n\t_hide_title:function(title, index){\n\t\tif(!isUndefined(this._title_hidden))\n\t\t\ttitle[this._title_hidden].style.visibility = \"visible\";\n\t\tif(!isUndefined(index)){\n\t\t\ttitle[index].style.visibility = \"hidden\";\n\t\t\tthis._title_hidden = index;\n\t\t}\n\t},\n\t_set_title:function(handle0, left, max, cornerStr){\n\t\tvar config = this._settings;\n\t\tif (this._settings.title){\n\t\t\tvar box = handle0.parentNode;\n\t\t\tvar sibling = config.vertical?\"nextSibling\":\"previousSibling\";\n\n\t\t\tif(!config.moveTitle)\n\t\t\t\tbox[sibling].innerHTML = this._settings.title(this._settings, this);\n\t\t\telse{ //two independent titles\n\t\t\t\tvar title = box[sibling].childNodes;\n\t\t\t\tvar pos = [];\n\t\t\t\tfor(let i = 0; i<2; i++)\n\t\t\t\t\tpos.push(this._set_title_n(title[i], config.value[i], left[i], max, cornerStr, i));\n\n\t\t\t\t//correct for overlapping titles\n\t\t\t\tvar diff = config.vertical? (pos[0]-pos[1]-this._sliderHandleWidth) : (pos[1]-pos[0]);\n\t\t\t\tvar sizeStr = config.vertical?\"clientHeight\":\"clientWidth\";\n\n\t\t\t\t\n\n\t\t\t\tif(title[0][sizeStr]/2+title[1][sizeStr]/2 > diff)\n\t\t\t\t\tthis._hide_title(title, isUndefined(this._activeIndex) ? 0 : (this._activeIndex ? 0 : 1));\n\t\t\t\telse\n\t\t\t\t\tthis._hide_title(title);\n\n\t\t\t\t//set position\n\t\t\t\tfor(let i = 0; i<2; i++)\n\t\t\t\t\ttitle[i].style[cornerStr] = pos[i]+ \"px\";\n\t\t\t}\n\t\t}\n\t},\n\t_set_title_n:function(title, value, left, max, cornerStr, index){\n\t\ttitle.innerHTML = this._settings.title({value:value}, this);\n\t\tvar half = title.clientWidth/2;\n\t\tvar pos = 0;\n\t\t\n\t\tif(this._settings.vertical)\n\t\t\tpos = max-left-this._sliderHandleWidth/2-(index?this._sliderPadding:0)+2 * this._sliderBorder;\n\t\telse{\n\t\t\tpos = left + this._sliderHandleWidth/2 + 2*this._sliderBorder - half;\n\t\t\tpos = (half>left) ? (half-left+pos): pos;//left/top text is to small\n\t\t\tpos = (index && half+left>max)?(pos-half+(max-left)):pos;//right/bottom text is too large\n\t\t}\n\t\treturn pos;\n\t},\n\t_set_value_now:function(){\n\t\tfor(var i=0; i<2; i++){\n\t\t\tthis._get_slider_handle(i).setAttribute(\"aria-valuenow\", this._settings.value[i]);\n\t\t}\n\t},\n\t_mouse_down_process: function(e){\n\t\tvar trg = e.target;\n\t\tvar match = /webix_slider_handle_(\\d)/.exec(trg.className);\n\t\tthis._activeIndex = match?parseInt(match[1],10):-1;\n\n\t\tif(match)\n\t\t\tthis._set_handle_active(this._activeIndex);\n\t},\n\t$compareValue:function(oldvalue, value){\n\t\tvalue = this.$prepareValue(value);\n\t\treturn oldvalue[0] === value[0] && oldvalue[1] === value[1];\n\t},\n\t$getValue:function(){\n\t\tvar value = this._settings.value;\n\t\treturn this._settings.stringResult?value.join(this._settings.separator):value;\n\t},\n\t_set_handle_active: function(index){\n\t\tvar hActive = this._get_slider_handle(index);\n\t\tvar h = this._get_slider_handle(1-index);\n\t\tif(hActive.className.indexOf(\"webix_slider_active\") == -1)\n\t\t\thActive.className += \" webix_slider_active\";\n\t\th.className = h.className.replace(\" webix_slider_active\",\"\");\n\t\thActive.focus();\n\t},\n\t_get_value_from_pos:function(pos){\n\t\tvar config = this._settings;\n\t\tvar value = config.value;\n\t\t//10 - padding of slider box\n\t\tvar max = config.max - config.min;\n\t\tvar ax = config.vertical?\"y\":\"x\";\n\n\t\tvar left = offset(this._get_slider_handle().parentNode)[ax];\n\t\tvar newvalue = Math.ceil((pos-left) * max / (config.vertical?this._content_height:this._get_input_width(config)));\n\t\tnewvalue = Math.round((newvalue + 1*config.min)/config.step) * config.step;\n\t\tif(config.vertical)\n\t\t\tnewvalue = max-newvalue;\n\n\t\tvar index = null;\n\t\tvar pos0 = offset(this._get_slider_handle(0))[ax];\n\t\tvar pos1 = offset(this._get_slider_handle(1))[ax];\n\n\t\tif(pos0==pos1 && (config.value[0] == config.min || config.value[0] == config.max) ){\n\t\t\tthis._activeIndex = index = (config.value[0] == config.min?1:0);\n\t\t\tthis._set_handle_active(index);\n\t\t}\n\t\telse{\n\t\t\tif(this._activeIndex >=0){\n\t\t\t\tindex = this._activeIndex;\n\t\t\t}else{\n\t\t\t\tif(pos0==pos1){\n\t\t\t\t\tindex = (pos < pos0?0:1);\n\t\t\t\t}\n\t\t\t\telse{\n\t\t\t\t\tvar dist0 = Math.abs(pos0-pos);\n\t\t\t\t\tvar dist1 = Math.abs(pos1-pos);\n\t\t\t\t\tindex = dist0\"+config.labelRight+\"\";\n\t\t\t\tif (config.labelWidth)\n\t\t\t\t\tconfig.label = config.label || \" \";\n\t\t\t}\n\t\t\tvar checked = (config.checkValue == config.value);\n\t\t\tvar aria = \"aria-label=\\\"\"+(config.label||config.labelRight||\"\")+\"\\\" role=\\\"checkbox\\\" tabindex=\\\"0\\\" aria-checked=\\\"\"+(checked?\"true\":\"false\")+\"\\\" \"+(config.readonly?\"aria-readonly='true'\":\"\")+\"\\\"\";\n\t\t\tvar html = \n\t\t\t\t\"
    \"+\n\t\t\t\t\t\"\"+((checked?config.onLabel:config.offLabel)||\"\")+\"\"+\n\t\t\t\t\t\"\"+\n\t\t\t\t\"
    \"+rightlabel;\n\n\t\t\treturn common.$renderInput(config, html, id);\n\t\t}\n\t},\n\t$skin:function(){\n\t\tcheckbox.api.$skin.call(this);\n\n\t\tthis._switchHeight = $active.switchHeight;\n\t\tthis._switchWidth = $active.switchWidth;\n\t},\n\t$setValue:function(value){\n\t\tvar config = this._settings;\n\t\tvar checked = (value == config.checkValue);\n\t\tvar box = this.$view.querySelector(\".webix_switch_box\");\n\n\t\tif(box){\n\t\t\tvar handle = box.childNodes[1];\n\t\t\tvar text = (checked?config.onLabel:config.offLabel)||\"\";\n\t\t\tif(checked)\n\t\t\t\taddCss(box, \"webix_switch_on\");\n\t\t\telse\n\t\t\t\tremoveCss(box, \"webix_switch_on\");\n\n\t\t\thandle.style.left = (checked?this._switchWidth-this._switchHeight:0)+\"px\";\n\t\t\thandle.firstChild.checked = checked;\n\t\t\thandle.setAttribute(\"aria-checked\", checked?\"true\":\"false\");\n\n\t\t\tif(text){\n\t\t\t\tbox.childNodes[0].innerHTML = text;\n\t\t\t}\n\t\t}\n\t},\n\t_calck_switch_size:function(){\n\t\tvar config = this._settings;\n\t\tif(config.onLabel || config.offLabel){\n\t\t\tvar onWidth = config.onLabel ? getTextSize(config.onLabel, \"webix_switch_text\").width : 0;\n\t\t\tvar offWidth = config.onLabel ? getTextSize(config.offLabel, \"webix_switch_text\").width : 0;\n\t\t\tthis._switchWidth = Math.max(onWidth, offWidth)+this._switchHeight;\n\t\t}\n\t},\n\ton_click:{\n\t\t\"webix_switch_box\":function(){\n\t\t\tif(!this._settings.readonly)\n\t\t\t\tthis.toggle(\"user\");\n\t\t},\n\t\t\"webix_label_right\":function(){\n\t\t\tif(!this._settings.readonly)\n\t\t\t\tthis.toggle(\"user\");\n\t\t}\n\t}\n};\n\n\nconst view = protoUI(api, checkbox.view);\nexport default {api, view};","import {protoUI, ui, $$} from \"../ui/core\";\nimport UIManager from \"../core/uimanager\";\nimport {$active} from \"../webix/skin\";\nimport {extend} from \"../webix/helpers\";\nimport i18n from \"../webix/i18n\";\nimport template from \"../webix/template\";\n\nimport segmented from \"../views/segmented\";\n\nconst api = {\n\tname:\"tabbar\",\n\t$init:function(){\n\t\tthis.attachEvent(\"onKeyPress\", this._onKeyPress);\n\t},\n\t$skin:function(){\n\t\tvar skin = $active;\n\t\tvar defaults = this.defaults;\n\n\t\tdefaults.topOffset = skin.tabTopOffset||0;\n\t\tdefaults.tabOffset = (typeof skin.tabOffset != \"undefined\"?skin.tabOffset:10);\n\t\tdefaults.bottomOffset = skin.tabBottomOffset||0;\n\t\tdefaults.height = skin.tabbarHeight;\n\n\t\tdefaults.tabMargin = skin.tabMargin;\n\t\tdefaults.inputPadding = skin.inputPadding;\n\t\tdefaults.tabMinWidth = skin.tabMinWidth||100;\n\t\tdefaults.tabMoreWidth = skin.tabMoreWidth||40;\n\t\tdefaults.borderless = !skin.tabBorder;\n\t},\n\t_getTabbarSizes: function(selected){\n\t\tconst config = this._settings;\n\t\tconst inputWidth = this._input_width - config.tabOffset * 2;\n\t\tconst tabs = this._filterOptions(config.options);\n\n\t\tconst width = config.optionWidth || config.tabMinWidth;\n\n\t\t//the selected tab will be rendered anyway\n\t\tlet totalWidth = tabs.find(tab => tab.id == selected).width || width;\n\t\tlet max = 1;\n\n\t\tfor(let i = 0; i < tabs.length; i++){\n\t\t\tif(tabs[i].id == selected)\n\t\t\t\tcontinue;\n\t\t\tif((totalWidth += (tabs[i].width || width)) > inputWidth)\n\t\t\t\treturn { max };\n\t\t\tmax++;\n\t\t}\n\n\t\treturn { width: inputWidth / tabs.length };\n\t},\n\t_init_popup: function () {\n\t\tconst obj = this._settings;\n\n\t\t// if tabbar popup is set as plain object with config\n\t\tif (!obj.tabbarPopup || !$$(obj.tabbarPopup)) {\n\t\t\tconst popupConfig = extend(\n\t\t\t\t{\n\t\t\t\t\tview: \"popup\",\n\t\t\t\t\tautofocus: false,\n\t\t\t\t\twidth: 200,\n\t\t\t\t},\n\t\t\t\tobj.tabbarPopup || {}\n\t\t\t);\n\n\t\t\tconst body = extend(\n\t\t\t\t{\n\t\t\t\t\tview: \"list\",\n\t\t\t\t\tborderless: true,\n\t\t\t\t\tselect: true,\n\t\t\t\t\tautoheight: true,\n\t\t\t\t\tyCount: 7,\n\t\t\t\t\ttemplate: template(\"#value#\"),\n\t\t\t\t},\n\t\t\t\tobj.tabbarPopup ? obj.tabbarPopup.body || {} : {},\n\t\t\t\ttrue\n\t\t\t);\n\t\t\tbody.css = `webix_tab_list ${body.css || \"\"}`;\n\t\t\tpopupConfig.body = body;\n\n\t\t\tconst view = ui(popupConfig);\n\t\t\tconst list = view.getBody();\n\n\t\t\tview.attachEvent(\"onShow\", () => {\n\t\t\t\tlist.unselect();\n\t\t\t\tUIManager.setFocus(list);\n\n\t\t\t\tconst node = list.getItemNode(list.getFirstId());\n\t\t\t\tif (node) node.focus();\n\t\t\t});\n\t\t\tlist.attachEvent(\"onItemClick\", id => this._popupInnerClick(id));\n\t\t\tlist.attachEvent(\"onEnter\", () => this._popupInnerClick());\n\n\t\t\tobj.tabbarPopup = view._settings.id;\n\t\t\tthis._destroy_with_me.push(view);\n\t\t}\n\n\t\tthis._init_popup = function () {};\n\t},\n\t_popupInnerClick(id){\n\t\tconst popup = $$(this._settings.tabbarPopup);\n\t\tid = id || popup.getBody().getSelectedId();\n\n\t\tif (id && this.callEvent(\"onBeforeTabClick\", [id])){\n\t\t\tthis.setValue(id, \"user\");\n\t\t\tpopup.hide();\n\t\t\tthis.callEvent(\"onAfterTabClick\", [id]);\n\t\t\tthis.refresh();\n\t\t\tthis.focus();\n\t\t}\n\t\treturn false;\n\t},\n\tgetPopup: function(){\n\t\tthis._init_popup();\n\t\treturn $$(this._settings.tabbarPopup);\n\t},\n\tmoreTemplate_setter: template,\n\tdefaults:{\n\t\tmoreTemplate: \"\",\n\t\ttemplate:function(obj,common) {\n\t\t\tcommon._check_options(obj.options);\n\n\t\t\tlet tabs = common._filterOptions(obj.options);\n\t\t\tlet contentWidth, html, leafWidth, resultHTML, style, sum, verticalOffset, width;\n\n\t\t\tif (!tabs.length){\n\t\t\t\thtml = \"
    \";\n\t\t\t} else {\n\t\t\t\tif (!obj.value)\n\t\t\t\t\tobj.value = common._getFirstActive(true);\n\n\t\t\t\thtml = \"\";\n\t\t\t\tif (obj.tabOffset)\n\t\t\t\t\thtml += \"
     
    \";\n\t\t\t\tcontentWidth = common._input_width - obj.tabOffset*2-(!obj.type?(obj.tabMargin)*(tabs.length-1):0);\n\t\t\t\tverticalOffset = obj.topOffset+obj.bottomOffset;\n\n\t\t\t\tvar sizes = common._getTabbarSizes(obj.value);\n\n\t\t\t\tif (sizes.max && sizes.max < tabs.length){\n\t\t\t\t\t//we need popup\n\t\t\t\t\tconst popup = common.getPopup();\n\t\t\t\t\tpopup.hide();\n\n\t\t\t\t\tconst body = (popup.getBody()||null);\n\t\t\t\t\tif(body){\n\t\t\t\t\t\tif (sizes.max){\n\t\t\t\t\t\t\tfor (let i=0, found=false; i < tabs.length && !found; i++)\n\t\t\t\t\t\t\t\tif(tabs[i].id== obj.value){\n\t\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t\t\tif((i+1) > sizes.max){\n\t\t\t\t\t\t\t\t\t\tlet selectedTab = tabs.splice(i, 1);\n\t\t\t\t\t\t\t\t\t\tlet displayTabs = tabs.splice(0, sizes.max-1).concat(selectedTab);\n\t\t\t\t\t\t\t\t\t\ttabs = displayTabs.concat(tabs);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbody.clearAll();\n\t\t\t\t\t\t\tbody.parse(tabs.slice(sizes.max));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tbody.clearAll();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (common._settings.tabbarPopup) {\n\t\t\t\t\tconst popup = $$(common._settings.tabbarPopup);\n\t\t\t\t\tif (popup) popup.hide();\n\t\t\t\t}\n\n\t\t\t\tsum = obj.tabOffset;\n\t\t\t\tfor (let i=0, lastTab=false; (i1)?(obj.tabMargin)*(sizes.max-1):0);\n\t\t\t\t\t\twidth = (contentWidth - obj.tabMoreWidth)/sizes.max ;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\twidth = sizes.width;\n\n\t\t\t\t\twidth = (tabs[i].width||obj.optionWidth||width);\n\n\t\t\t\t\tsum += width + (i&&!obj.type?obj.tabMargin:0);\n\n\t\t\t\t\tif(obj.tabMargin>0&&i&&!obj.type)\n\t\t\t\t\t\thtml += \"
    \";\n\n\t\t\t\t\t// tab innerHTML\n\t\t\t\t\thtml += common._getTabHTML(tabs[i], width);\n\n\n\t\t\t\t\tif(lastTab){\n\t\t\t\t\t\thtml += \"
    \"+obj.moreTemplate(obj,common)+\"
    \";\n\t\t\t\t\t\tsum += obj.tabMoreWidth;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\tleafWidth = common._content_width - sum;\n\n\t\t\t\tif (leafWidth>0 && !obj.type)\n\t\t\t\t\thtml += \"
     
    \";\n\t\t\t}\n\n\t\t\tresultHTML = \"\";\n\n\t\t\t// consider top and bottom offset in tabs height (top tabbar)\n\t\t\tstyle = (verticalOffset&& !obj.type)?\"height:\"+(common._content_height-verticalOffset)+\"px\":\"\";\n\n\t\t\t//space above tabs (top tabbar)\n\t\t\tif(obj.topOffset && !obj.type)\n\t\t\t\tresultHTML += \"
    \";\n\n\t\t\t// tabs html\n\t\t\tresultHTML += \"
    \"+html+\"
    \";\n\n\t\t\t//space below to tabs (top tabbar)\n\t\t\tif(obj.bottomOffset && !obj.type)\n\t\t\t\tresultHTML += \"
    \";\n\n\t\t\treturn resultHTML;\n\t\t}\n\t},\n\t_getInputNode:function(){\n\t\treturn this.$view.querySelectorAll(\".webix_item_tab\");\n\t},\n\t_getTabHTML: function(tab, width){\n\t\tvar\thtml,\n\t\t\tclassName = \"\",\n\t\t\ttooltip = \"\",\n\t\t\tisDisabled = !!tab.disabled,\n\t\t\tconfig = this.config;\n\n\t\tif (tab.id == config.value)\n\t\t\tclassName += \" webix_selected\";\n\n\t\tif (isDisabled)\n\t\t\tclassName += \" webix_disabled\";\n\n\t\tif (tab.css)\n\t\t\tclassName+=\" \"+tab.css;\n\n\t\tif (config.tooltip)\n\t\t\ttooltip = \" webix_t_id='\"+tab.id+\"'\";\n\n\t\twidth = (tab.width||width);\n\t\thtml = \"
    \";\n\n\t\t// a tab title\n\t\tif(this._tabTemplate){\n\t\t\tvar calcHeight = this._content_height- config.inputPadding*2 - 2;\n\t\t\tvar height = this._content_height - 2;\n\t\t\tvar temp = extend({ cheight: calcHeight, aheight:height }, tab);\n\t\t\thtml+= this._tabTemplate(temp);\n\t\t}\n\t\telse {\n\t\t\tvar icon = tab.icon?(\" \"):\"\";\n\t\t\thtml+=icon + tab.value;\n\t\t}\n\n\t\tif (!isDisabled && (tab.close || config.close))\n\t\t\thtml+=\"\";\n\n\t\thtml+=\"
    \";\n\t\treturn html;\n\t},\n\t_getBox:function(){\n\t\treturn this._dataobj.firstChild;\n\t},\n\t_types:{\n\t\timage:\"
    #value#
    \",\n\t\ticon:\"
    #value#
    \",\n\t\ticonTop:\"
    #value#
    \"\n\t},\n\ttype_setter:function(value){\n\t\tthis._settings.tabOffset = 0;\n\t\tif (this._types[value])\n\t\t\tthis._tabTemplate = template(this._types[value]);\n\t\treturn value;\n\t}\n};\n\n\nconst view = protoUI(api, segmented.view);\nexport default {api, view};","import layout from \"../views/layout\";\nimport IdSpace from \"../core/idspace\";\nimport UIManager from \"../core/uimanager\";\nimport {protoUI} from \"../ui/core\";\nimport {$active} from \"../webix/skin\";\nimport i18n from \"../webix/i18n\";\nimport {_event} from \"../webix/htmlevents\";\nimport {getTextSize} from \"../webix/html\";\n\nconst api = {\n\tname: \"richtext\",\n\tdefaults:{\n\t\tlabel:\"\",\n\t\tlabelWidth:80,\n\t\tlabelPosition:\"left\"\n\t},\n\t$init: function() {\n\t\tthis._viewobj.className += \" webix_richtext\";\n\t\tthis.$ready.unshift(this._setLayout);\n\t},\n\t$skin:function(){\n\t\tlayout.api.$skin.call(this);\n\n\t\tthis.defaults.paddingX = $active.inputSpacing/2;\n\t\tthis.defaults.paddingY = $active.inputPadding;\n\t},\n\tgetInputNode:function(){\n\t\treturn this.$view.querySelector(\".webix_richtext_editor\"); \n\t},\n\t_button:function(name){\n\t\treturn {\n\t\t\tview: \"toggle\",\n\t\t\ttype: \"icon\",\n\t\t\ticon: \"wxi-\"+name, name: name, id:name,\n\t\t\tlabel: i18n.richtext[name],\n\t\t\tautowidth: true, \n\t\t\taction:name,\n\t\t\tclick: this._add_data\n\t\t};\n\t},\n\t_setLayout: function() {\n\t\tconst top = this;\n\n\t\tconst editField = {\n\t\t\tview: \"template\",\n\t\t\tcss: \"webix_richtext_container\",\n\t\t\tborderless: true,\n\t\t\ttemplate: \"
    \"+this.getValue()+\"
    \",\n\t\t\ton: {\n\t\t\t\tonAfterRender: function() {\n\t\t\t\t\ttop._rendered_input = true;\n\t\t\t\t\ttop.refresh();\n\t\t\t\t\t_event(top.getInputNode(), \"blur\", function(){\n\t\t\t\t\t\ttop._updateValue(this.innerHTML, \"user\");\n\t\t\t\t\t});\n\t\t\t\t\t_event(top.getInputNode(), \"keyup\", function(){\n\t\t\t\t\t\ttop._getselection(\"auto\");\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tonClick: {\n\t\t\t\twebix_richtext_editor: function() {\n\t\t\t\t\ttop._getselection(\"auto\");\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tconst controls = [\n\t\t\tthis._button(\"underline\"),\n\t\t\tthis._button(\"bold\"),\n\t\t\tthis._button(\"italic\"),\n\t\t\t{ }\n\t\t];\n\n\t\tconst editorToolbar = {\n\t\t\tview: \"toolbar\",\n\t\t\tid:\"toolbar\",\n\t\t\telements: controls\n\t\t};\n\n\t\tconst rows = [\n\t\t\teditorToolbar,\n\t\t\teditField\n\t\t];\n\n\t\tconst config = this.config;\n\n\t\tif (config.labelPosition == \"top\"){\n\t\t\teditorToolbar.elements = controls.concat([\n\t\t\t\t{ view:\"label\", label: config.label, align:\"right\"},\n\t\t\t\t{ width:4 }\n\t\t\t]);\n\t\t\tthis.rows_setter(rows);\n\t\t} \n\t\telse{\n\t\t\tconfig.labelWidth = config.label ? this._getLabelWidth(config.labelWidth, config.label, config.required) : 0;\n\t\t\tif(config.labelWidth){\n\t\t\t\tconfig.margin = 0;\n\t\t\t\tthis.cols_setter([{ \n\t\t\t\t\ttemplate: config.label,\n\t\t\t\t\tcss: \"webix_richtext_inp_label\"+(config.required?\" webix_required\":\"\"),\n\t\t\t\t\tborderless: true,\n\t\t\t\t\twidth: config.labelWidth\n\t\t\t\t}, {\n\t\t\t\t\trows\n\t\t\t\t}]);\n\t\t\t}\n\t\t\telse\n\t\t\t\tthis.rows_setter(rows);\n\t\t}\n\t},\n\t_getLabelWidth: function(width, label, required){\n\t\tif(width == \"auto\")\n\t\t\twidth = getTextSize(label, \"webix_inp_label\"+(required ? \" webix_required\" : \"\")).width;\n\t\treturn width ? Math.max(width, $active.dataPadding) : 0;\n\t},\n\t_getselection: function(config) {\n\t\tconst top = this;\n\t\tconst bar = top.$$(\"toolbar\");\n\t\tlet sel;\n\n\t\tbar.setValues({\n\t\t\titalic:false, underline:false, bold:false\n\t\t}, false, config);\n\n\t\tif(window.getSelection) {\n\t\t\tsel = window.getSelection();\n\t\t} else {\n\t\t\tsel = document.selection.createRange();\n\t\t}\n\n\t\tfor (let i = 0; i < sel.rangeCount; ++i) {\n\t\t\tif (top.$view.contains(this.getInputNode())){\n\t\t\t\tif (document.queryCommandState(\"bold\")) {\n\t\t\t\t\ttop.$$(\"bold\").setValue(true,config);\n\t\t\t\t} \n\t\t\t\tif (document.queryCommandState(\"underline\")) {\n\t\t\t\t\ttop.$$(\"underline\").setValue(true,config);\n\t\t\t\t}\n\t\t\t\tif (document.queryCommandState(\"italic\")) {\n\t\t\t\t\ttop.$$(\"italic\").setValue(true,config);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\trefresh: function() {\n\t\tif(this._rendered_input)\n\t\t\tthis.getInputNode().innerHTML = this._settings.value;\n\t},\n\t_execCommandOnElement:function(commandName) {\n\t\tlet sel, selText;\n\n\t\tsel = window.getSelection();\n\t\tselText = sel.toString().length;\n\n\t\tconst input = this.getInputNode();\n\t\tif (!input.contains(sel.anchorNode) || !input.contains(sel.focusNode)) return;\n\n\t\tif(selText > 0) {\n\t\t\tfor (let i = 0; i < sel.rangeCount; ++i) {\n\t\t\t\tconst range = sel.getRangeAt(i);\n\t\t\t\tif (!sel.isCollapsed) {\n\t\t\t\t\tdocument.execCommand(commandName, false, \"\");\n\t\t\t\t} else {\n\t\t\t\t\tconst textValue = sel.focusNode.textContent;\n\t\t\t\t\tconst focusEl = sel.focusNode;\n\t\t\t\t\tconst focustext = sel.anchorOffset;\n\t\t\t\t\tconst wordBegining = textValue.substring(0, focustext).match(/[A-Za-z]*$/)[0];\n\t\t\t\t\tconst wordEnd = textValue.substring(focustext).match(/^[A-Za-z]*/)[0];\n\n\t\t\t\t\tconst startWord = focustext - wordBegining.length;\n\t\t\t\t\tconst endWord = focustext + wordEnd.length;\n\n\t\t\t\t\trange.setStart(focusEl, startWord);\n\t\t\t\t\trange.setEnd(focusEl, endWord);\n\t\t\t\t\tsel.removeAllRanges();\n\n\t\t\t\t\tsel.addRange(range);\n\t\t\t\t\tdocument.execCommand(commandName, false, \"\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t_add_data:function() {\n\t\tconst top = this.getTopParentView();\n\t\ttop._execCommandOnElement(this.config.action);\n\t},\n\tfocus: function() {\n\t\tif(!UIManager.canFocus(this))\n\t\t\treturn false;\n\n\t\tconst editableElement = this.getInputNode();\n\t\teditableElement.focus();\n\t},\n\t_updateValue: 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.callEvent(\"onChange\", [value, oldvalue, config]);\n\t\t}\n\t},\n\tsetValue: function(value, config) {\n\t\tthis._updateValue(value, config);\n\t\tthis.refresh();\n\t},\n\t$prepareValue:function(value){ return value === 0 ? \"0\" : (value || \"\").toString(); },\n\tvalue_setter:function(value){\n\t\treturn this.$prepareValue(value);\n\t},\n\tgetValue: function() {\n\t\tconst input = this.getInputNode();\n\t\tif (input)\n\t\t\treturn input.innerHTML;\n\n\t\treturn this._settings.value;\n\t}\n};\n\n\nconst view = protoUI(api, IdSpace, layout.view);\nexport default {api, view};","import {errorMessage, getFileName} from \"./common\";\n\nimport promise from \"../../thirdparty/promiz\";\nimport require from \"../../load/require\";\nimport env from \"../../webix/env\";\n\nimport {assert} from \"../../webix/debug\";\nimport {toNode} from \"../../webix/helpers\";\nimport {download} from \"../../webix/html\";\nimport {$$} from \"../../ui/core\";\n\nexport const toPNG = function(id, options){\n\tconst defer = promise.defer();\n\n\treturn require(env.cdn + \"/extras/html2canvas-1.0.min.js\").then(function(){\n\t\t//backward compatibility\n\t\tif (typeof options === \"string\") options = { filename: options };\n\t\toptions = options || {};\n\n\t\toptions.export_mode = \"png\";\n\n\t\tlet view = $$(id);\n\t\tif (view && view.$exportView)\n\t\t\tview = view.$exportView(options);\n\t\tassert(view, errorMessage);\n\t\tif(!view) return defer.reject(errorMessage);\n\n\t\tconst node = view ? view.$view : toNode(id);\n\t\tconst filename = getFileName(options.filename, \"png\");\n\n\t\twindow.html2canvas(node, {background:\"#fff\", logging:false, useCORS:true}).then(function(canvas) {\n\t\t\tconst callback = function(data){\n\t\t\t\tif(options.download !== false)\n\t\t\t\t\tdownload(data, filename);\n\t\t\t\tdefer.resolve(data);\n\t\t\t};\n\t\t\tif(canvas.msToBlob)\n\t\t\t\tcallback(canvas.msToBlob());\n\t\t\telse\n\t\t\t\tcanvas.toBlob(callback, \"image/png\");\n\t\t});\n\t\treturn defer;\n\t});\n};","import {errorMessage, getExportScheme, getExportData, getFileName} from \"./common\";\n\nimport csv from \"../../webix/csv\";\nimport promise from \"../../thirdparty/promiz\";\n\nimport {download} from \"../../webix/html\";\nimport {$$} from \"../../ui/core\";\nimport {assert} from \"../../webix/debug\";\nimport {extend} from \"../../webix/helpers\";\n\nexport const toCSV = function(id, options){\n\toptions = options || {};\n\n\tlet view = $$(id);\n\tif (view && view.$exportView)\n\t\tview = view.$exportView(options);\n\tassert(view, errorMessage);\n\tif(!view) return promise.reject(errorMessage);\n\n\toptions.export_mode = \"csv\";\n\n\textend(options, {\n\t\tfilterHTML: true\n\t});\n\n\tconst scheme = getExportScheme(view, options);\n\tconst result = getExportData(view, options, scheme);\n\n\tconst data = getCsvData(result, scheme);\n\tconst filename = getFileName(options.filename, \"csv\");\n\n\tconst blob = new Blob([\"\\uFEFF\" + data], { type: \"text/csv\" });\n\tif(options.download !== false)\n\t\tdownload(blob, filename);\n\n\treturn promise.resolve(blob);\n};\n\nfunction getCsvData(data) {\n\treturn csv.stringify(data);\n}","import {callEvent} from \"./customevents\";\n\nexport function editStop(){\n\tcallEvent(\"onEditEnd\", []);\n}\n","import {create} from \"../webix/html\";\n\n/*submits values*/\nexport default function send(url, values, method, target){\n\tvar form = create(\"FORM\",{\n\t\t\"target\":(target||\"_self\"),\n\t\t\"action\":url,\n\t\t\"method\":(method||\"POST\")\n\t},\"\");\n\tfor (var k in values) {\n\t\tvar field = create(\"INPUT\",{\"type\":\"hidden\",\"name\": k,\"value\": values[k]},\"\");\n\t\tform.appendChild(field);\n\t}\n\tform.style.display = \"none\";\n\tdocument.body.appendChild(form);\n\tform.submit();\n\tdocument.body.removeChild(form);\n}"],"names":["v","d","resolve","getInfo","x","responseText","node","parentNode","removeChild","parts","details","split","event","element","on_click","input","inputBox","querySelector","text","type","decimal","this","_hotkeys","queryView","_borders","left","width","offsetWidth","labelTopHeight","borderlessPopup","Touch","_set_scroll_pos","DragControl","_landing","_active","_last","_html","_dropHTML","value","view","template","height","hidden","url","$proxy","saveAll","to_send","length","_typeof","callEvent","isNaN","_settings","ready","getLabel","nextSibling","className","el","getTopParentView","some","count","i","inp","_destroy_with_me","push","found","_progress","firstChild","style","position","e","shiftKey","env","isIE","ctrlKey","rgbToHsv","path","renderer","definePath","config","css","loadBranch","parent","$count","item","getItem","_htmlrows","footer","toString","options","res","minusPosition","format","_padding","right","top","bottom","$prepareValue","dir","next","getMonth","class","pageWidth","lessOrEqual","filter","resize","collapse","_headobj","y","index","addDrag","drag","size","dy","prop","_last_body_size","_string_to_date","s","monthSelect","navigation","isBlocked","blockTime","date","define","add","r","palette","code","_sValue","_vValue","_move_block_value","iconTop","opt","disabled","padding","message","lind","nind","customRadio","suggest","getList","obj","awidth","aheight","lineHeight","inner","common","$renderInput","data","attachEvent","popup","pos","vertical","corner1","_sliderBorder","_sliderHandleWidth","offLabel","isDisabled","tab","id","getValue","filename","export_mode","$$","$exportView","$view","toNode","getFileName","window","html2canvas","background","logging","useCORS","then","canvas","callback","download","defer","msToBlob","toBlob","reject","errorMessage","promise","extend","filterHTML","scheme","getExportScheme","result","getExportData","csv","stringify","blob","Blob","box_params","apply","arguments","alertPopup","promptPopup","values","method","target","k","form","create","action","field","name","appendChild","display","document","body","submit"],"mappings":";;;;;;;;;AAgHE,OAAIA,EACIC,EAAEC;AC1EXC,QAAQ;AC8HW,OAAOC,EAAEC;AC1EpB,OACCC,GAAQA,EAAKC,YACrBD,EAAKC,WAAWC;AC1Dd;ACkHF,IAAIC,EAAQC,EAAQC;AC1GnB,IAAK;ACtBD,SAASC;ACmUC,CAAA,IADCC,EAAQC;ACrUjBC,EAAQC,EAASC;AAwSzB,OADAC,EAAKC,KAAOD,EAAKC,MAAQ;ACzRxBC,QAAW;AAmTeC,KAAKC;ACrUT;ACqDvBC,UAAU;AChCDC,EAASC,KAAK,EAAE;ACuBbC,MAAOR,EAAKS;AC7CxBC,eAAgB;AC+BhBC,gBAAiB,CAAA;CCkFfC,EAAMC;AAgTG;ACpGVC,EAAYC,GAASD,EAAYE,GAAQF,EAAYG,GAAMH,EAAYI,GAAMJ,EAAYK,GAAU;;ACuDlF,YAAdC,EAAMC,MAAuB,CAACD,EAAMC,MAAQD,EAAME;ACzW7B;ACgDrBC,OAAOpB,KAAKF,KAAKsB,OAAS;ACoM5B;AC1OkBC,EAAS;AC4Q5B,OATIC,EAAIC,QAAUD,EAAIE,SAAWC,EAAQC;ACnHvB,WAAdC;AA4UJ3B,KAAK4B;AA8WCC;AChnBgB7B,KAAK8B,EAAUC;AClIhC,GAIA/B,KAAK4B;AC7FsB;ACiI5B,uBAAuBI;AA+PdtC,EAAMuC,YACdC;GC/IsCC,EAAGC;ACxOzCC,MAAAA,GACHC,CAAK;ACEA,IAAIC,EAAE,EAAGA,EAAEC,EAAId,OAAQa,CAAC;ACtB/B;AC4ECvC,KAAKyC,GAAiBC;AClDnBC,EAAQ,CAAA;AC2BX3C,KAAK4C,GAAUC,WAAWC,MAAMzC,MAAiB,IAAT0C,EAAa;ACxChDC,EAAEC,UAAaC,EAAIC,MAAQH,EAAEI;AC2EpCC,SAAS;AC5ETC,EAAOC,EAASC;AC6B4B;ACSgCC,EAAOC,IAAI,IAAID,EAAOC,IAAI;ACzDtGC,WAAW;AC0HF;;ACsUHC,EAAOC,QAAQ;ACjQhBC,EAAO9D,KAAK+D;CC7ET/D,KAAKgE;;ECoLqCC,EAAOC;ACrBpCC;AC/GhB,IAAM5B,KAAKlB;ACnJf;AAiKa+C;AC1INX,EAAOY;EC4EoF;ACrBhGpD,EAAQ;ACmGXqD,OAAO;AC0G8B,CAAA;AClRhCtE,KAAKuE,GAASnE,MAAQJ,KAAKuE,GAASC,OAASxE,KAAKuE,GAASE,KAAOzE,KAAKuE,GAASG;AC+BpF,OAAO1E,KAAK2E;GA+O+D,GAAPC,GAAgC,IAApBC,EAAKC;ACnH5DC,QAAU;ACvKjB;ACelBC,UAAU;ACoDVC,YAAa;AC1CE;ACzCZ;ACwFJC,OAAO;ACnBNlF,KAAKmF;ECxBaC;ACuLfpF,KAAKqF,GAASvC,MAAMzC,MAAQiF,EAAI;ACxFjB/C;;ACzHKgD;ECatB5E,EAAY6E;;ACoBbC,EAAK3C,MAAM1B,OAASsE,EAAKC,GAAG;ACwC1B,IAAIC,EAAO5F,KAAK+D;AC9BJ/D,KAAK6F;ACjDkB;ACuBb7F,KAAK8F;AAqO8HC,EAAEC,aAAgBD,EAAEE,WAA+B,+BAAnB;AAoMxLC,EAAYlG,KAAK8B,EAAUqE;AA2Q1BC,GACHpG,KAAKqG;AAuLuBC;ACt2B5B;AA6RI,IAAIC,EAAE,EAAGA,EAAIC,EAAQ9E,OAAQ6E,CAAC;ECtHhB,KAATE,EACPzG,KAAK0G,GAAU1G,KAAK2G,GAAU,EACd,KAATF,GAAwB,KAATA,EAEtBzG,KAAK0G,GAAU1G,KAAK4G;ACzIvBC,QAAQ;AAqOHC,GAAO,CAACA,EAAIC,UAAY/G,KAAK4B;ECzNiC,kBAAkBoF,EAAQ;AA4NvFC;AClH0BC,EAAKC;AC7KnCC,EAAc3D,EAAO2D,aAAc;ACsErC,IAAMtH,EAAOE,KAAK8B,EAAUhC;ACpC5B,OAAOuH,EAAQC;AC9Cd,MAAO,0CAA0CC,EAAIC,OAAO,aAAaD,EAAIE,QAAQ,kBAAkBC,EACtG,iBAAiBjD,EAAI,OAAOkD;AC0EtBC,EAAOC;AC7Ef7H,KAAK8H,KAAKC;ACUN7G;CCoIuB,MAAO,CAAA;AAoNjC4C,EAAOkE,EAAMV;AChSQW,EAAjBxE,EAAOyE,SAAgBC,EAAQ,EAAInI,KAAKoI,GAAcpI,KAAKqI,GAAmB;AC9BnD;ACQa5E,EAAO6E;ACwL0BC,GAAcC,EAAIC,IAAIhF,EAAOxC,MAAU,KAAJ;ACrClHyH,SAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACnMwBvE,EAAV,UAAnB,OAAOA,EAAgC,CAAEwE,SAAUxE,GAC7CA,IAAW,IAEbyE,YAAc,MAEtB,IAOMD,EAPFzH,EAAO2H,EAAGJ,CAAD,EAIb,OAFCvH,EADGA,GAAQA,EAAK4H,YACT5H,EAAK4H,YAAY3E,CAAjB,EAEJjD,IAEEjC,EAAOiC,EAAOA,EAAK6H,MAAQC,EAAOP,CAAD,EACjCE,EAAWM,GAAY9E,EAAQwE,SAAU,KAAnB,EAE5BO,OAAOC,YAAYlK,EAAM,CAACmK,WAAW,OAAQC,QAAQ,CAAA,EAAOC,QAAQ,CAAA,EAApE,EAA2EC,KAAK,SAASC,GACxF,IAAMC,EAAW,SAAS3B,GACD,CAAA,IAArB3D,EAAQuF,UACVA,GAAS5B,EAAMa,CAAP,EACTgB,EAAM9K,QAAQiJ,CAAd,GAEE0B,EAAOI,SACTH,EAASD,EAAOI,UAAR,EAERJ,EAAOK,OAAOJ,EAAU,WAAxB,EATF,EAWOE,GAhBUA,EAAMG,OAAOC,EAAb,EAXX,CA6BP,UCjCoB,SAAStB,EAAItE,GACjCA,EAAUA,GAAW,GAEjBjD,EAAO2H,EAAGJ,CAAD,EAIb,GAAG,EAFFvH,EADGA,GAAQA,EAAK4H,YACT5H,EAAK4H,YAAY3E,CAAjB,EAEJjD,GAAM,OAAO8I,EAAQF,OAAOC,EAAf,EAEjB5F,EAAQyE,YAAc,MAEtBqB,SAAO9F,EAAS,CACf+F,WAAY,CAAA,EADP,EAIN,IAAMC,EAASC,GAAgBlJ,EAAMiD,CAAP,EACxBkG,EAASC,GAAcpJ,EAAMiD,EAASgG,CAAhB,EAEtBrC,EAWCyC,GAAIC,UAXaH,CAWjB,EAVD1B,EAAWM,GAAY9E,EAAQwE,SAAU,KAAnB,EAEtB8B,EAAO,IAAIC,KAAK,CAAC,SAAW5C,GAAO,CAAEhI,KAAM,WAApC,EAIb,MAHwB,CAAA,IAArBqE,EAAQuF,UACVA,GAASe,EAAM9B,CAAP,EAEFqB,EAAQnL,QAAQ4L,CAAhB,CACP,kCtF8QM,WACN,IAAI5K,EAAO8K,GAAWC,MAAM5K,KAAM6K,SAAvB,EAEX,OADAhL,EAAKC,KAAOD,EAAKC,MAAQ,QAClBgL,GAAWjL,CAAD,CACjB,sCAaM,WACN,IAAIA,EAAO8K,GAAWC,MAAM5K,KAAM6K,SAAvB,EAGX,OAFAhL,EAAKC,KAAOD,EAAKC,MAAQ,SACzBD,EAAKH,MAAQG,EAAKH,OAAS,GACpBqL,GAAYlL,CAAD,CAClB,qCuFrUA+B,EAAU,YAAa,EAAd,CACT,kGCDc,SAAcN,EAAK0J,EAAQC,EAAQC,GACjD,IAKSC,EALLC,EAAOC,EAAO,OAAO,CACxBH,OAAUA,GAAQ,QAClBI,OAAShK,EACT2J,OAAUA,GAAQ,QACjB,EAJe,EAKjB,IAASE,KAAKH,EAAQ,CACrB,IAAIO,EAAQF,EAAO,QAAQ,CAACvL,KAAO,SAAS0L,KAAQL,EAAElK,MAAS+J,EAAOG,IAAI,EAAxD,EAClBC,EAAKK,YAAYF,CAAjB,EAEDH,EAAKtI,MAAM4I,QAAU,OACrBC,SAASC,KAAKH,YAAYL,CAA1B,EACAA,EAAKS,SACLF,SAASC,KAAKzM,YAAYiM,CAA1B,CACA"}