PageSourceSearch

https://web.rosknroll.fi/rosknroll/js/dhtmlxSuite/sources/dhtmlxCommon/codebase/dhtmlxcommon.js

js rosknroll.fi collected 2026-09-26 03:00:10 UTC 54,130 bytes, 1,813 lines download raw bytes

1/*
2Product Name: dhtmlxSuite 
3Version: 5.1.0 
4Edition: Professional 
5License: content of this file is covered by DHTMLX Commercial or Enterprise license. Usage without proper license is prohibited. To obtain it contact [email protected]
6Copyright UAB Dinamenta http://www.dhtmlx.com
7*/
8
9/* dhtmlx.com */
10
11if (typeof(window.dhx) == "undefined") {
12	
13	window.dhx = window.dhx4 = {
14		
15		version: "5.1.0",
16		
17		skin: null, // allow to be set by user
18		
19		skinDetect: function(comp) {
20			var i = Math.floor(dhx4.readFromCss(comp+"_skin_detect")/10)*10;
21			return {10:"dhx_skyblue",20:"dhx_web",30:"dhx_terrace",40:"material"}[i]||null;
22		},
23		
24		// read value from css
25		readFromCss: function(className, property, innerHTML) {
26			var t = document.createElement("DIV");
27			t.className = className;
28			if (document.body.firstChild != null) document.body.insertBefore(t, document.body.firstChild); else document.body.appendChild(t);
29			if (typeof(innerHTML) == "string") t.innerHTML = innerHTML;
30			var w = t[property||"offsetWidth"];
31			t.parentNode.removeChild(t);
32			t = null;
33			return w;
34		},
35		
36		// id manager
37		lastId: 1,
38		newId: function() {
39			return this.lastId++;
40		},
41		
42		// z-index manager
43		zim: {
44			data: {},
45			step: 5,
46			first: function() {
47				return 100;
48			},
49			last: function() {
50				var t = this.first();
51				for (var a in this.data) t = Math.max(t, this.data[a]);
52				return t;
53			},
54			reserve: function(id) {
55				this.data[id] = this.last()+this.step;
56				return this.data[id];
57			},
58			clear: function(id) {
59				if (this.data[id] != null) {
60					this.data[id] = null;
61					delete this.data[id];
62				}
63			}
64		},
65		
66		// string to boolean
67		s2b: function(r) {
68			if (typeof(r) == "string") r = r.toLowerCase();
69			return (r == true || r == 1 || r == "true" || r == "1" || r == "yes" || r == "y" || r == "on");
70		},
71		
72		// string to json
73		s2j: function(s) {
74			var obj = null;
75			dhx4.temp = null;
76			try { eval("dhx4.temp="+s); } catch(e) { dhx4.temp = null; }
77			obj = dhx4.temp;
78			dhx4.temp = null;
79			return obj;
80		},
81		
82		// absolute top/left position on screen
83		absLeft: function(obj) {
84			if (typeof(obj) == "string") obj = document.getElementById(obj);
85			return this.getOffset(obj).left;
86		},
87		absTop: function(obj) {
88			if (typeof(obj) == "string") obj = document.getElementById(obj);
89			return this.getOffset(obj).top;
90		},
91		_aOfs: function(elem) {
92			var top = 0, left = 0;
93			while (elem) {
94				top = top + parseInt(elem.offsetTop);
95				left = left + parseInt(elem.offsetLeft);
96				elem = elem.offsetParent;
97			}
98			return {top: top, left: left};
99		},
100		_aOfsRect: function(elem) {
101			var box = elem.getBoundingClientRect();
102			var body = document.body;
103			var docElem = document.documentElement;
104			var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
105			var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
106			var clientTop = docElem.clientTop || body.clientTop || 0;
107			var clientLeft = docElem.clientLeft || body.clientLeft || 0;
108			var top  = box.top +  scrollTop - clientTop;
109			var left = box.left + scrollLeft - clientLeft;
110			return { top: Math.round(top), left: Math.round(left) };
111		},
112		getOffset: function(elem) {
113			if (elem.getBoundingClientRect) {
114				return this._aOfsRect(elem);
115			} else {
116				return this._aOfs(elem);
117			}
118		},
119		
120		// copy obj
121		_isObj: function(k) {
122			return (k != null && typeof(k) == "object" && typeof(k.length) == "undefined");
123		},
124		_copyObj: function(r) {
125			if (this._isObj(r)) {
126				var t = {};
127				for (var a in r) {
128					if (typeof(r[a]) == "object" && r[a] != null) t[a] = this._copyObj(r[a]); else t[a] = r[a];
129				}
130			} else {
131				var t = [];
132				for (var a=0; a<r.length; a++) {
133					if (typeof(r[a]) == "object" && r[a] != null) t[a] = this._copyObj(r[a]); else t[a] = r[a];
134				}
135			}
136			return t;
137		},
138		
139		// screen dim
140		screenDim: function() {
141			var isIE = (navigator.userAgent.indexOf("MSIE") >= 0);
142			var dim = {};
143			dim.left = document.body.scrollLeft;
144			dim.right = dim.left+(window.innerWidth||document.body.clientWidth);
145			dim.top = Math.max((isIE?document.documentElement:document.getElementsByTagName("html")[0]).scrollTop, document.body.scrollTop);
146			dim.bottom = dim.top+(isIE?Math.max(document.documentElement.clientHeight||0,document.documentElement.offsetHeight||0):window.innerHeight);
147			return dim;
148		},
149		
150		// input/textarea range selection
151		selectTextRange: function(inp, start, end) {
152			
153			inp = (typeof(inp)=="string"?document.getElementById(inp):inp);
154			
155			var len = inp.value.length;
156			start = Math.max(Math.min(start, len), 0);
157			end = Math.min(end, len);
158			
159			if (inp.setSelectionRange) {
160				try {inp.setSelectionRange(start, end);} catch(e){}; // combo in grid under IE requires try/catch
161			} else if (inp.createTextRange) {
162				var range = inp.createTextRange();
163				range.moveStart("character", start);
164				range.moveEnd("character", end-len);
165				try {range.select();} catch(e){};
166			}
167		},
168		// transition
169		transData: null,
170		transDetect: function() {
171			
172			if (this.transData == null) {
173				
174				this.transData = {transProp: false, transEv: null};
175				
176				// transition, MozTransition, WebkitTransition, msTransition, OTransition
177				var k = {
178					"MozTransition": "transitionend",
179					"WebkitTransition": "webkitTransitionEnd",
180					"OTransition": "oTransitionEnd",
181					"msTransition": "transitionend",
182					"transition": "transitionend"
183				};
184				
185				for (var a in k) {
186					if (this.transData.transProp == false && document.documentElement.style[a] != null) {
187						this.transData.transProp = a;
188						this.transData.transEv = k[a];
189					}
190				}
191				k = null;
192			}
193			
194			return this.transData;
195			
196		},
197		
198		// xml parser
199		_xmlNodeValue: function(node) {
200			var value = "";
201			for (var q=0; q<node.childNodes.length; q++) {
202				value += (node.childNodes[q].nodeValue!=null?node.childNodes[q].nodeValue.toString().replace(/^[\n\r\s]{0,}/,"").replace(/[\n\r\s]{0,}$/,""):"");
203			}
204			return value;
205		}
206		
207	};
208	
209	// browser
210	window.dhx4.isIE = (navigator.userAgent.indexOf("MSIE") >= 0 || navigator.userAgent.indexOf("Trident") >= 0);
211	window.dhx4.isIE6 = (window.XMLHttpRequest == null && navigator.userAgent.indexOf("MSIE") >= 0);
212	window.dhx4.isIE7 = (navigator.userAgent.indexOf("MSIE 7.0") >= 0 && navigator.userAgent.indexOf("Trident") < 0);
213	window.dhx4.isIE8 = (navigator.userAgent.indexOf("MSIE 8.0") >= 0 && navigator.userAgent.indexOf("Trident") >= 0);
214	window.dhx4.isIE9 = (navigator.userAgent.indexOf("MSIE 9.0") >= 0 && navigator.userAgent.indexOf("Trident") >= 0);
215	window.dhx4.isIE10 = (navigator.userAgent.indexOf("MSIE 10.0") >= 0 && navigator.userAgent.indexOf("Trident") >= 0 && window.navigator.pointerEnabled != true);
216	window.dhx4.isIE11 = (navigator.userAgent.indexOf("Trident") >= 0 && window.navigator.pointerEnabled == true);
217	window.dhx4.isEdge = (navigator.userAgent.indexOf("Edge") >= 0);
218	window.dhx4.isOpera = (navigator.userAgent.indexOf("Opera") >= 0);
219	window.dhx4.isChrome = (navigator.userAgent.indexOf("Chrome") >= 0) && !window.dhx4.isEdge;
220	window.dhx4.isKHTML = (navigator.userAgent.indexOf("Safari") >= 0 || navigator.userAgent.indexOf("Konqueror") >= 0) && !window.dhx4.isEdge;
221	window.dhx4.isFF = (navigator.userAgent.indexOf("Firefox") >= 0);
222	window.dhx4.isIPad = (navigator.userAgent.search(/iPad/gi) >= 0);
223	
224	// dnd data
225	window.dhx4.dnd = {
226		evs: {},
227		p_en: ((window.dhx4.isIE || window.dhx4.isEdge) && (window.navigator.pointerEnabled || window.navigator.msPointerEnabled)), // touch/pointer
228		_mTouch: function(e) {
229			// mouse touch type in ie10/11/Edge
230			return (window.dhx4.isIE10 && e.pointerType == e.MSPOINTER_TYPE_MOUSE || window.dhx4.isIE11 && e.pointerType == "mouse" || window.dhx4.isEdge && e.pointerType == "mouse");
231		},
232		_touchOn: function(obj) {
233			if (obj == null) obj = document.body;
234			obj.style.touchAction = obj.style.msTouchAction = "";
235			obj = null;
236		},
237		_touchOff: function(obj) {
238			if (obj == null) obj = document.body;
239			obj.style.touchAction = obj.style.msTouchAction = "none";
240			obj = null;
241		}
242	};
243	
244	// dnd events
245	if (window.navigator.pointerEnabled == true) { // edge/ie11
246		window.dhx4.dnd.evs = {start: "pointerdown", move: "pointermove", end: "pointerup"};
247	} else if (window.navigator.msPointerEnabled == true) { // ie10-
248		window.dhx4.dnd.evs = {start: "MSPointerDown", move: "MSPointerMove", end: "MSPointerUp"};
249	} else if (typeof(window.addEventListener) != "undefined") { // rest touch devices
250		window.dhx4.dnd.evs = {start: "touchstart", move: "touchmove", end: "touchend"};
251	};
252	
253};
254
255if (typeof(window.dhx4.template) == "undefined") {
256	
257	// trim
258	window.dhx4.trim = function(t) {
259		return String(t).replace(/^\s{1,}/,"").replace(/\s{1,}$/,"");
260	};
261	
262	// template parsing
263	window.dhx4.template = function(tpl, data, trim) {
264		
265		// tpl - template text, #value|func:param0:param1:paramX#
266		// data - object with key-value
267		// trim - true/false, trim values
268		return tpl.replace(/#([a-z0-9_-]{1,})(\|([^#]*))?#/gi, function(){
269			
270			var key = arguments[1];
271			
272			var t = window.dhx4.trim(arguments[3]);
273			var func = null;
274			var args = [data[key]];
275			
276			if (t.length > 0) {
277				
278				t = t.split(":");
279				var k = [];
280				
281				// check escaped colon
282				for (var q=0; q<t.length; q++) {
283					if (q > 0 && k[k.length-1].match(/\\$/) != null) {
284						k[k.length-1] = k[k.length-1].replace(/\\$/,"")+":"+t[q];
285					} else {
286						k.push(t[q]);
287					}
288				}
289				
290				func = k[0];
291				for (var q=1; q<k.length; q++) args.push(k[q]);
292				
293			}
294			
295			// via inner function
296			if (typeof(func) == "string" && typeof(window.dhx4.template[func]) == "function") {
297				return window.dhx4.template[func].apply(window.dhx4.template, args
297);
298			}
299			
300			// value only
301			if (key.length > 0 && typeof(data[key]) != "undefined") {
302				if (trim == true) return window.dhx4.trim(data[key]);
303				return String(data[key]);
304			}
305			
306			// key not found
307			return "";
308			
309		});
310		
311	};
312	
313	window.dhx4.template.date = function(value, format) {
314		// Date obj + format	=> convert to string
315		// timestamp + format	=> convert to string
316		// string		=> no convert
317		// any other value	=> empty string
318		if (value != null) {
319			if (value instanceof Date) {
320				return window.dhx4.date2str(value, format);
321			} else {
322				value = value.toString();
323				if (value.match(/^\d*$/) != null) return window.dhx4.date2str(new Date(parseInt(value)), format);
324				return value;
325			}
326		}
327		return "";
328	};
329	
330	window.dhx4.template.maxlength = function(value, limit) {
331		return String(value).substr(0, limit);
332	};
333	
334	window.dhx4.template.number_format = function(value, format, group_sep, dec_sep) {
335		var fmt = window.dhx4.template._parseFmt(format, group_sep, dec_sep);
336		if (fmt == false) return value;
337		return window.dhx4.template._getFmtValue(value, fmt);
338	};
339	
340	window.dhx4.template.lowercase = function(value) {
341		if (typeof(value) == "undefined" || value == null) value = "";
342		return String(value).toLowerCase();
343	};
344	window.dhx4.template.uppercase = function(value) {
345		if (typeof(value) == "undefined" || value == null) value = "";
346		return String(value).toUpperCase();
347	};
348	
349	// number format helpers
350	window.dhx4.template._parseFmt = function(format, group_sep, dec_sep) {
351		
352		var t = format.match(/^([^\.\,0-9]*)([0\.\,]*)([^\.\,0-9]*)/);
353		if (t == null || t.length != 4) return false; // invalid format
354		
355		var fmt = {
356			// int group
357			i_len: false,
358			i_sep: (typeof(group_sep)=="string"?group_sep:","),
359			// decimal
360			d_len: false,
361			d_sep: (typeof(dec_sep)=="string"?dec_sep:"."),
362			// chars before and after
363			s_bef: (typeof(t[1])=="string"?t[1]:""),
364			s_aft: (typeof(t[3])=="string"?t[3]:"")
365		};
366		
367		var f = t[2].split(".");
368		if (f[1] != null) fmt.d_len = f[1].length;
369		
370		var r = f[0].split(",");
371		if (r.length > 1) fmt.i_len = r[r.length-1].length;
372		
373		return fmt;
374		
375	};
376	
377	window.dhx4.template._getFmtValue = function(value, fmt) {
378		
379		var r = String(value).match(/^(-)?([0-9]{1,})(\.([0-9]{1,}))?$/); // r = [complete value, minus sign, integer, full decimal, decimal]
380		
381		if (r != null && r.length == 5) {
382			var v0 = "";
383			// minus sign
384			if (r[1] != null) v0 += r[1];
385			// chars before
386			v0 += fmt.s_bef;
387			// int part
388			if (fmt.i_len !== false) {
389				var i = 0; var v1 = "";
390				for (var q=r[2].length-1; q>=0; q--) {
391					v1 = ""+r[2].charAt(q)+v1;
392					if (++i == fmt.i_len && q > 0) { v1=fmt.i_sep+v1; i=0; }
393				}
394				v0 += v1;
395			} else {
396				v0 += r[2];
397			}
398			// dec part
399			if (fmt.d_len !== false) {
400				if (r[4] == null) r[4] = "";
401				while (r[4].length < fmt.d_len) r[4] += "0";
402				eval("dhx4.temp = new RegExp(/\\d{"+fmt.d_len+"}/);");
403				var t1 = (r[4]).match(dhx4.temp);
404				if (t1 != null) v0 += fmt.d_sep+t1;
405				dhx4.temp = t1 = null;
406			}
407			// chars after
408			v0 += fmt.s_aft;
409			
410			return v0;
411		}
412		
413		return value;
414	};
415	
416};
417
418if (typeof(window.dhx4.dateLang) == "undefined") {
419	
420	window.dhx4.dateLang = "en";
421	window.dhx4.dateStrings = {
422		en: {
423			monthFullName:	["January","February","March","April","May","June","July","August","September","October","November","December"],
424			monthShortName:	["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],
425			dayFullName:	["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
426			dayShortName:	["Su","Mo","Tu","We","Th","Fr","Sa"]
427		}
428	};
429	window.dhx4.dateFormat = {
430		en: "%Y-%m-%d"
431	};
432	
433	window.dhx4.date2str = function(val, format, strings) {
434		
435		if (format == null || typeof(format) == "undefined") format = window.dhx4.dateFormat[window.dhx4.dateLang];
436		if (strings == null || typeof(strings) == "undefined") strings = window.dhx4.dateStrings[window.dhx4.dateLang];
437		
438		if (val instanceof Date) {
439			var z = function(t) {
440				return (String(t).length==1?"0"+String(t):t);
441			}
442			var k = function(t) {
443				switch(t) {
444					case "%d": return z(val.getDate());
445					case "%j": return val.getDate();
446					case "%D": return strings.dayShortName[val.getDay()];
447					case "%l": return strings.dayFullName[val.getDay()];
448					case "%m": return z(val.getMonth()+1);
449					case "%n": return val.getMonth()+1;
450					case "%M": return strings.monthShortName[val.getMonth()];
451					case "%F": return strings.monthFullName[val.getMonth()];
452					case "%y": return z(val.getYear()%100);
453					case "%Y": return val.getFullYear();
454					case "%g": return (val.getHours()+11)%12+1;
455					case "%h": return z((val.getHours()+11)%12+1);
456					case "%G": return val.getHours();
457					case "%H": return z(val.getHours());
458					case "%i": return z(val.getMinutes());
459					case "%s": return z(val.getSeconds());
460					case "%a": return (val.getHours()>11?"pm":"am");
461					case "%A": return (val.getHours()>11?"PM":"AM");
462					case "%%": return "%";
463					case "%u": return val.getMilliseconds();
464					case "%P":
465						if (window.dhx4.temp_calendar != null && window.dhx4.temp_calendar.tz != null) return window.dhx4.temp_calendar.tz;
466						var ofs = val.getTimezoneOffset();
467						var h = Math.abs(Math.floor(ofs/60));
468						var m = Math.abs(ofs)-h*60;
469						return (ofs>0?"-":"+")+z(h)+":"+z(m);
470					default: return t;
471				}
472			}
473			var t = String(format||window.dhx4.dateFormat).replace(/%[a-zA-Z]/g, k);
474		}
475		
476		return (t||String(val));
477		
478	};
479	
480	window.dhx4.str2date = function(val, format, strings) {
481		
482		if (format == null || typeof(format) == "undefined") format = window.dhx4.dateFormat[window.dhx4.dateLang];
483		if (strings == null || typeof(strings) == "undefined") strings = window.dhx4.dateStrings[window.dhx4.dateLang];
484		
485		// escape custom chars
486		format = format.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\\:|]/g, "\\$&");
487		
488		var v = [];
489		var f = [];
490		
491		// escape required chars
492		format = format.replace(/%[a-z]/gi, function(t){
493			switch (t) {
494				case "%d": case "%m": case "%y": case "%h": case "%H": case "%i": case "%s": f.push(t); return "(\\d{2})"; // 2 digits
495				case "%D": case "%l": case "%M": case "%F": f.push(t); return "([a-zéûä\u0430-\u044F\u0451]{1,})"; // chars
496				case "%j": case "%n": case "%g": case "%G": f.push(t); return "(\\d{1,2})"; // 1-2 digits
497				case "%Y": f.push(t); return "(\\d{4})"; // 4 digits
498				case "%a": f.push(t); return "([a|p]m)"; // am/pm
499				case "%A": f.push(t); return "([A|P]M)"; // AM/PM
500				case "%u": f.push(t); return "(\\d{1,6})"; // 1-6 digits, micro/milliseconds
501				case "%P": f.push(t); return "([+-]\\d{1,2}:\\d{1,2})"; // zone offset
502			}
503			return t;
504		});
505		
506		var re = new RegExp(format, "i");
507		var e = val.match(re);
508		
509		if (e == null || e.length-1 != f.length) return "Invalid Date";
510		
511		// sorting
512		/*
513		Year	y,Y	1
514		Month	n,m,M,F	2
515		Day	d,j	3
516		AM/PM	a,A	4
517		Hours	H,G,h,g	5
518		Minutes	i	6
519		Seconds	s	7
520		MSec	u	7
521		Zone 	P	7
522		*/
523		
524		for (var q=1; q<e.length; q++) v.push(e[q]);
525		
526		var p = {"%y":1,"%Y":1,"%n":2,"%m":2,"%M":2,"%F":2,"%d":3,"%j":3,"%a":4,"%A":4,"%H":5,"%G":5,"%h":5,"%g":5,"%i":6,"%s":7,"%u":7,"%P":7};
527		var v2 = {};
528		var f2 = {};
529		for (var q=0; q<f.length; q++) {
530			if (typeof(p[f[q]]) != "undefined") {
531				var ind = p[f[q]];
532				if (!v2[ind]){v2[ind]=[];f2[ind]=[];}
533				v2[ind].push(v[q]);
534				f2[ind].push(f[q]);
535			}
536		}
537		v = [];
538		f = [];
539		for (var q=1; q<=7; q++) {
540			if (v2[q] != null) {
541				for (var w=0; w<v2[q].length; w++) {
542					v.push(v2[q][w]);
543					f.push(f2[q][w]);
544				}
545			}
546		}
547		
548		// parsing date
549		var r = new Date();
550		r.setDate(1); // fix for 31th
551		r.setHours(0);
552		r.setMinutes(0);
553		r.setSeconds(0);
554		r.setMilliseconds(0);
555		
556		// get index by value
557		var getInd = function(val, ar) {
558			for (var q=0; q<ar.length; q++) if (ar[q].toLowerCase() == val) return q;
559			return -1;
560		}
561		
562		for (var q=0; q<v.length; q++) {
563			switch (f[q]) {
564				case "%d": case "%j": case "%n": case "%m": case "%Y": case "%H": case "%G": case "%i": case "%s": case "%u":
565					if (!isNaN(v[q])) r[{"%d":"setDate","%j":"setDate","%n":"setMonth","%m":"setMonth","%Y":"setFullYear","%H":"setHours","%G":"setHours","%i":"setMinutes","%s":"setSeconds","%u":"setMilliseconds"}[f[q]]](Number(v[q])+(f[q]=="%m"||f[q]=="%n"?-1:0));
566					break;
567				//
568				case "%M": case "%F":
569					var k = getInd(v[q].toLowerCase(),strings[{"%M":"monthShortName","%F":"monthFullName"}[f[q]]]);
570					if (k >= 0) r.setMonth(k);
571					break;
572				//
573				case "%y":
574					if (!isNaN(v[q])) {
575						var v0 = Number(v[q]);
576						r.setFullYear(v0+(v0>50?1900:2000));
577					}
578					break;
579				//
580				case "%g": case "%h":
581					if (!isNaN(v[q])) {
582						var v0 = Number(v[q]);
583						if (v0 <= 12 && v0 >= 0) r.setHours(v0+(getInd("pm",v)>=0?(v0==12?0:12):(v0==12?-12:0))); // 12:00 AM -> midnight, 12:00 PM -> noon
584					}
585					break;
586				//
587				case "%P":
588					if (window.dhx4.temp_calendar != null) {
589						window.dhx4.temp_calendar.tz = v[q];
590					}
591					break;
592			}
593		}
594		return r;
595	};
596	
597};
598
599if (typeof(window.dhx4.ajax) == "undefined") {
600	
601	window.dhx4.ajax = {
602		
603		// if false - dhxr param will added to prevent caching on client side (default),
604		// if true - do not add extra params
605		cache: false,
606		
607		// default method for load/loadStruct, post/get allowed
608		// get - since 4.1.1, this should fix 412 error for macos safari
609		method: "get",
610		
611		parse: function(data) {
612			if (typeof data !== "string") return data;
613			
614			data = data.replace(/^[\s]+/,"");
615			if (window.DOMParser && !dhx4.isIE) { // ff,ie9
616				var obj = (new window.DOMParser()).parseFromString(data, "text/xml");
617			} else if (window.ActiveXObject !== window.undefined) {
618				var obj = new window.ActiveXObject("Microsoft.XMLDOM");
619				obj.async = "false";
620				obj.loadXML(data);
621			}
622			return obj;
623		},
624		xmltop: function(tagname, xhr, obj) {
625			if (typeof xhr.status == "undefined" || xhr.status < 400) {
626				xml = (!xhr.responseXML) ? dhx4.ajax.parse(xhr.responseText || xhr) : (xhr.responseXML || xhr);
627				if (xml && xml.documentElement !== null) {
628					try {
629						if (!xml.getElementsByTagName("parsererror").length)
630							return xml.getElementsByTagName(tagname)[0];
631					} catch(e){}
632				}
633			}
634			if (obj !== -1) dhx4.callEvent("onLoadXMLError",["Incorrect XML", arguments[1], obj]);
635			return document.createElement("DIV");
636		},
637		xpath: function(xpathExp, docObj) {
638			if (!docObj.nodeName) docObj = docObj.responseXML || docObj;
639			if (dhx4.isIE) {
640				try {
641					return docObj.selectNodes(xpathExp)||[];
642				} catch(e){ return []; }
643			} else {
644				var rows = [];
645				var first;
646				var col = (docObj.ownerDocument||docObj).evaluate(xpathExp, docObj, null, XPathResult.ANY_TYPE, null);
647				while (first = col.iterateNext()) rows.push(first);
648				return rows;
649			}
650		},
651		query: function(config) {
652			return dhx4.ajax._call(
653				(config.method || "GET"),
654				config.url,
655				config.data || "",
656				(config.async || true),
657				config.callback,
658				null,
659				config.headers
660			);
661		},
662		get: function(url, onLoad) {
663			return this._call("GET", url, null, true, onLoad);
664		},
665		getSync: function(url) {
666			return this._call("GET", url, null, false);
667		},
668		put: function(url, postData, onLoad) {
669			return this._call("PUT", url, postData, true, onLoad);
670		},
671		del: function(url, postData, onLoad) {
672			return this._call("DELETE", url, postData, true, onLoad);
673		},
674		post: function(url, postData, onLoad) {
675			if (arguments.length == 1) {
676				postData = "";
677			} else if (arguments.length == 2 && (typeof(postData) == "function" || typeof(window[postData]) == "function")) {
678				onLoad = postData;
679				postData = "";
680			} else {
681				postData = String(postData);
682			}
683			return this._call("POST", url, postData, true, onLoad);
684		},
685		postSync: function(url, postData) {
686			postData = (postData == null ? "" : String(postData));
687			return this._call("POST", url, postData, false);
688		},
689		getLong: function(url, onLoad) {
690			this._call("GET", url, null, true, onLoad, {url:url});
691		},
692		postLong: function(url, postData, onLoad) {
693			if (arguments.length == 2 && (typeof(postData) == "function" || typeof(window[postData]))) {
694				onLoad = postData;
695				postData = "";
696			}
697			this._call("POST", url, postData, true, onLoad, {url:url, postData:postData});
698		},
699		_call: function(method, url, postData, async, onLoad, longParams, headers) {
700			//postData can be a hash of values
701			if (typeof postData === "object"){
702				var _postData = [];
703				for (var a in postData)
704					_postData.push(a+"="+encodeURIComponent(postData[a]));
705				postData = _postData.join("&");
706			}
707
708			var def = dhx.promise.defer();
709			var t = (window.XMLHttpRequest && !dhx4.isIE ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
710			var isQt = (navigator.userAgent.match(/AppleWebKit/) != null && navigator.userAgent.match(/Qt/) != null && navigator.userAgent.match(/Safari/) != null);
711			
712			if (async == true) {
713				t.onreadystatechange = function() {
714					if ((t.readyState == 4) || (isQt == true && t.readyState == 3)) { // what for long response and status 404?
715						if (t.status != 200 || t.responseText == ""){
716							def.reject(t);
717							if (!dhx4.callEvent("onAjaxError", [{xmlDoc:t, filePath:url, async:async}])) return;
718						}
719
720						window.setTimeout(function(){
721							if (typeof(onLoad) == "function") {
722								try {
723									onLoad.apply(window, [{xmlDoc:t, filePath:url, async:async}]); // dhtmlx-compat, response.xmlDoc.responseXML/responseText
724								} catch(e){
725									def.reject(e);
726								}
727								def.resolve(t.responseText);
728							}
729							if (longParams != null) {
730								if (typeof(longParams.postData) != "undefined") {
731									dhx4.ajax.postLong(longParams.url, longParams.postData, onLoad);
732								} else {
733									dhx4.ajax.getLong(longParams.url, onLoad);
734								}
735							}
736							onLoad = null;
737							t = null;
738						},1);
739					}
740				}
741			}
742			
743			if (method == "GET") {
744				url += this._dhxr(url);
745			}
746			
747			t.open(method, url, async);
748			
749			if (headers != null) {
750				for (var key in headers) t.setRequestHeader(key, headers[key]);
751			} else if (method == "POST" || method == "PUT" || method == "DELETE") {
752				t.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
753			} else if (method == "GET") {
754				postData = null;
755			}
756			
757			t.setRequestHeader("X-Requested-With", "XMLHttpRequest");
758			
759			t.send(postData);
760			
761			if (async != true) {
762				if ((t.readyState == 4) || (isQt == true && t.readyState == 3)) {
763					if (t.status != 200 || t.responseText == "") dhx4.callEvent("onAjaxError", [{xmlDoc:t, filePath:url, async:async}]);
764				}
765			}
766			
767
768			def.xmlDoc=t;
769			def.filePath=url;
770			def.async=async;
771			
772			return def;
773		},
774		
775		_dhxr: function(sign, value) {
776			if (this.cache != true) {
777				if (sign.match(/^[\?\&]$/) == null) sign = (sign.indexOf("?")>=0?"&":"?");
778				if (typeof(value) == "undefined") value = true;
779				return sign+"dhxr"+new Date().getTime()+(value==true?"=1":"");
780			}
781			return "";
782		}
783	};
784	
785};
786
787if (typeof(window.dhx4._enableDataLoading) == "undefined") {
788	
789	window.dhx4._enableDataLoading = function(obj, initObj, xmlToJson, xmlRootTag, mode) {
790		
791		if (mode == "clear") {
792			
793			// clear attached functionality
794			
795			for (var a in obj._dhxdataload) {
796				obj._dhxdataload[a] = null;
797				delete obj._dhxdataload[a];
798			};
799			
800			obj._loadData = null;
801			obj._dhxdataload = null;
802			obj.load = null;
803			obj.loadStruct = null;
804			
805			obj = null;
806			
807			return;
808			
809		}
810		
811		obj._dhxdataload = { // move to obj.conf?
812			initObj: initObj,
813			xmlToJson: xmlToJson,
814			xmlRootTag: xmlRootTag,
815			onBeforeXLS: null
816		};
817		
818		obj._loadData = function(data, loadParams, onLoad) {
819			
820			if (arguments.length == 2) {
821				onLoad = loadParams;
822				loadParams = null;
823			}
824			
825			var obj = null;
826			
827			// deprecated from 4.0, compatability with version (url, type[json|xml], onLoad)
828			if (arguments.length == 3) onLoad = arguments[2];
829			
830			this.callEvent("onXLS",[]);
831
832			if (typeof(data) == "string") {
833				
834				var k = data.replace(/^\s{1,}/,"").replace(/\s{1,}$/,"");
835				
836				var tag = new RegExp("^<"+this._dhxdataload.xmlRootTag);
837
838				// xml
839				if (tag.test(k.replace(/^<\?xml[^\?]*\?>\s*/, ""))) { // remove leading <?xml ...?> if any, \n can be also present
840					obj = dhx4.ajax.parse(data);
841					if (obj != null) obj = this[this._dhxdataload.xmlToJson].apply(this, [obj]); // xml to json
842				}
843				
844				if (obj == null && (k.match(/^[\s\S]*{[.\s\S]*}[\s\S]*$/) != null || k.match(/^[\s\S]*\[[.\s\S]*\][\s\S]*$/) != null)) { // check for '{...}' or '[...]', cut leading/trailing \n\r with \s\S
845					obj = dhx4.s2j(k);
846				}
847				
848				if (obj == null) {
849					
850					
851					
852					var params = [];
853					
854					// allow to modify url and add params
855					if (typeof(this._dhxdataload.onBeforeXLS) == "function") {
856						var k = this._dhxdataload.onBeforeXLS.apply(this,[data]);
857						if (k != null && typeof(k) == "object") {
858							if (k.url != null) data = k.url;
859							if (k.params != null) { for (var a in k.params) params.push(a+"="+encodeURIComponent(k.params[a])); }
860						}
861					}
862					
863					var t = this;
864					var callBack = function(r) {
865						
866						var obj = null;
867						
868						if ((r.xmlDoc.getResponseHeader("Content-Type")||"").search(/xml/gi) >= 0 || (r.xmlDoc.responseText.replace(/^\s{1,}/,"")).match(/^</) != null) {
869							obj = t[t._dhxdataload.xmlToJson].apply(t,[r.xmlDoc.responseXML]);
870						} else {
871							obj = dhx4.s2j(r.xmlDoc.responseText);
872						}
873						
874						// init
875						if (obj != null) t[t._dhxdataload.initObj].apply(t,[obj,data]); // data => url
876						
877						t.callEvent("onXLE",[]);
878						
879						if (onLoad != null) {
880							if (typeof(onLoad) == "function") {
881								onLoad.apply(t,[]);
882							} else if (typeof(window[onLoad]) == "function") {
883								window[onLoad].apply(t,[]);
884							}
885						}
886						
887						callBack = onLoad = null;
888						obj = r = t = null;
889						
890					};
891					
892					params = params.join("&")+(typeof(loadParams)=="string"?"&"+loadParams:"");
893					
894					if (dhx4.ajax.method == "post") {
895						return dhx4.ajax.post(data, params, callBack);
896					} else if (dhx4.ajax.method == "get") {
897						return dhx4.ajax.get(data+(params.length>0?(data.indexOf("?")>0?"&":"?")+params:""), callBack);
898					}
899					
900					return;
901				}
902				
903			} else {
904				if (typeof(data.documentElement) == "object" || (typeof(data.tagName) != "undefined" && typeof(data.getElementsByTagName) != "undefined" && data.getElementsByTagName(this._dhxdataload.xmlRootTag).length > 0)) { // xml
905					obj = this[this._dhxdataload.xmlToJson].apply(this, [data]);
906				} else { // json
907					obj = window.dhx4._copyObj(data);
908				}
909			}
910			
911			// init
912			if (obj != null) this[this._dhxdataload.initObj].apply(this,[obj]);
913
914			this.callEvent("onXLE",[]);
915			if (onLoad != null) {
916				if (typeof(onLoad) == "function") {
917					onLoad.apply(this, []);
918				} else if (typeof(window[onLoad]) == "function") {
919					window[onLoad].apply(this, []);
920				}
921				onLoad = null;
922			}
923			
924		};
925		
926		// loadStruct for hdr/conf
927		// load for data
928		if (mode != null) {
929			var k = {struct: "loadStruct", data: "load"};
930			for (var a in mode) {
931				if (mode[a] == true) obj[k[a]] = function() {return this._loadData.apply(this, arguments);}
932			}
933		}
934		
935		obj = null;
936		
937	};
938};
939
940if (typeof(window.dhx4._eventable) == "undefined") {
941	
942	window.dhx4._eventable = function(obj, mode) {
943		
944		if (mode == "clear") {
945			
946			obj.detachAllEvents();
947			
948			obj.dhxevs = null;
949			
950			obj.attachEvent = null;
951			obj.detachEvent = null;
952			obj.checkEvent = null;
953			obj.callEvent = null;
954			obj.detachAllEvents = null;
955			
956			obj = null;
957			
958			return;
959			
960		}
961		
962		obj.dhxevs = { data: {} };
963		
964		obj.attachEvent = function(name, func) {
965			name = String(name).toLowerCase();
966			if (!this.dhxevs.data[name]) this.dhxevs.data[name] = {};
967			var eventId = window.dhx4.newId();
968			this.dhxevs.data[name][eventId] = func;
969			return eventId;
970		}
971		
972		obj.detachEvent = function(eventId) {
973			for (var a in this.dhxevs.data) {
974				var k = 0;
975				for (var b in this.dhxevs.data[a]) {
976					if (b == eventId) {
977						this.dhxevs.data[a][b] = null;
978						delete this.dhxevs.data[a][b];
979					} else {
980						k++;
981					}
982				}
983				if (k == 0) {
984					this.dhxevs.data[a] = null;
985					delete this.dhxevs.data[a];
986				}
987			}
988		}
989		
990		obj.checkEvent = function(name) {
991			name = String(name).toLowerCase();
992			return (this.dhxevs.data[name] != null);
993		}
994		
995		obj.callEvent = function(name, params) {
996			name = String(name).toLowerCase();
997			if (this.dhxevs.data[name] == null) return true;
998			var r = true;
999			for (var a in this.dhxevs.data[name]) {
1000				r = this.dhxevs.data[name][a].apply(this, params) && r;
1001			}
1002			return r;
1003		}
1004		
1005		obj.detachAllEvents = function() {
1006			for (var a in this.dhxevs.data) {
1007				for (var b in this.dhxevs.data[a]) {
1008					this.dhxevs.data[a][b] = null;
1009					delete this.dhxevs.data[a][b];
1010				}
1011				this.dhxevs.data[a] = null;
1012				delete this.dhxevs.data[a];
1013			}
1014		}
1015		
1016		obj = null;
1017	};
1018	
1019	dhx4._eventable(dhx4);
1020	
1021};
1022
1023// validation
1024// all purpose set of rules, based on http://code.google.com/p/validation-js
1025if (!window.dhtmlxValidation) {
1026	dhtmlxValidation = function(){};
1027	dhtmlxValidation.prototype = {
1028		isEmpty: function(value) {
1029			return value == '';
1030		},
1031		isNotEmpty: function(value) {
1032			return (value instanceof Array?value.length>0:!value == ''); // array in case of multiselect
1033		},
1034		isValidBoolean: function(value) {
1035			return !!value.toString().match(/^(0|1|true|false)$/);
1036		},
1037		isValidEmail: function(value) {
1038			return !!value.toString().match(/(^[a-z0-9]([0-9a-z\-_\.]*)@([0-9a-z_\-\.]*)([.][a-z]{3}
1038)$)|(^[a-z]([0-9a-z_\.\-]*)@([0-9a-z_\-\.]*)(\.[a-z]{2,5})$)/i);
1039		},
1040		isValidInteger: function(value) {
1041			return !!value.toString().match(/(^-?\d+$)/);
1042		},
1043		isValidNumeric: function(value) {
1044			return !!value.toString().match(/(^-?\d\d*[\.|,]\d*$)|(^-?\d\d*$)|(^-?[\.|,]\d\d*$)/);
1045		},
1046		isValidAplhaNumeric: function(value) {
1047			return !!value.toString().match(/^[_\-a-z0-9]+$/gi);
1048		},
1049		// 0000-00-00 00:00:00 to 9999:12:31 59:59:59 (no it is not a "valid DATE" function)
1050		isValidDatetime: function(value) {
1051			var dt = value.toString().match(/^(\d{4})-(\d{2})-(\d{2})\s(\d{2}):(\d{2}):(\d{2})$/);
1052			return dt && !!(dt[1]<=9999 && dt[2]<=12 && dt[3]<=31 && dt[4]<=59 && dt[5]<=59 && dt[6]<=59) || false;
1053		},
1054		// 0000-00-00 to 9999-12-31
1055		isValidDate: function(value) {
1056			var d = value.toString().match(/^(\d{4})-(\d{2})-(\d{2})$/);
1057			return d && !!(d[1]<=9999 && d[2]<=12 && d[3]<=31) || false;
1058		},
1059		// 00:00:00 to 59:59:59
1060		isValidTime: function(value) {
1061			var t = value.toString().match(/^(\d{1,2}):(\d{1,2}):(\d{1,2})$/);
1062			return t && !!(t[1]<=24 && t[2]<=59 && t[3]<=59) || false;
1063		},
1064		// 0.0.0.0 to 255.255.255.255
1065		isValidIPv4: function(value) { 
1066			var ip = value.toString().match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
1067			return ip && !!(ip[1]<=255 && ip[2]<=255 && ip[3]<=255 && ip[4]<=255) || false;
1068		},
1069		isValidCurrency: function(value) { // Q: Should I consider those signs valid too ? : ¢|€|₤|₦|¥
1070			return value.toString().match(/^\$?\s?\d+?([\.,\,]?\d+)?\s?\$?$/) && true || false;
1071		},
1072		// Social Security Number (999-99-9999 or 999999999)
1073		isValidSSN: function(value) {
1074			return value.toString().match(/^\d{3}\-?\d{2}\-?\d{4}$/) && true || false;
1075		},
1076		// Social Insurance Number (999999999)
1077		isValidSIN: function(value) {
1078			return value.toString().match(/^\d{9}$/) && true || false;
1079		}
1080	};
1081	dhtmlxValidation = new dhtmlxValidation();
1082};
1083
1084
1085if (typeof(window.dhtmlx) == "undefined") {
1086	window.dhtmlx={
1087		extend:function(a, b){
1088			for (var key in b)
1089				if (!a[key])
1090					a[key]=b[key];
1091			return a;
1092		},
1093		extend_api:function(name,map,ext){
1094			var t = window[name];
1095			if (!t) return; //component not defined
1096			window[name]=function(obj){
1097				if (obj && typeof obj == "object" && !obj.tagName){
1098					var that = t.apply(this,(map._init?map._init(obj):arguments));
1099					//global settings
1100					for (var a in dhtmlx)
1101						if (map[a]) this[map[a]](dhtmlx[a]);			
1102					//local settings
1103					for (var a in obj){
1104						if (map[a]) this[map[a]](obj[a]);
1105						else if (a.indexOf("on")===0){
1106							this.attachEvent(a,obj[a]);
1107						}
1108					}
1109				} else
1110					var that = t.apply(this,arguments);
1111				if (map._patch) map._patch(this);
1112				return that||this;
1113			};
1114			window[name].prototype=t.prototype;
1115			if (ext)
1116				dhtmlx.extend(window[name].prototype,ext);
1117		},
1118		url:function(str){
1119			if (str.indexOf("?") != -1)
1120				return "&";
1121			else
1122				return "?";
1123		}
1124	};
1125};
1126
1127/**  
1128*     @desc: find out what symbol to use as url param delimiters in further params
1129*     @type: private
1130*     @param: str - current url string
1131*     @topic: 0  
1132*/
1133
1134
1135function dhtmlDragAndDropObject(){
1136	if (window.dhtmlDragAndDrop)
1137		return window.dhtmlDragAndDrop;
1138
1139	this.lastLanding=0;
1140	this.dragNode=0;
1141	this.dragStartNode=0;
1142	this.dragStartObject=0;
1143	this.tempDOMU=null;
1144	this.tempDOMM=null;
1145	this.waitDrag=0;
1146	window.dhtmlDragAndDrop=this;
1147
1148	return this;
1149};
1150
1151dhtmlDragAndDropObject.prototype.removeDraggableItem=function(htmlNode){
1152	htmlNode.onmousedown=null;
1153	htmlNode.dragStarter=null;
1154	htmlNode.dragLanding=null;
1155}
1156dhtmlDragAndDropObject.prototype.addDraggableItem=function(htmlNode, dhtmlObject){
1157	htmlNode.onmousedown=this.preCreateDragCopy;
1158	htmlNode.dragStarter=dhtmlObject;
1159	this.addDragLanding(htmlNode, dhtmlObject);
1160}
1161dhtmlDragAndDropObject.prototype.addDragLanding=function(htmlNode, dhtmlObject){
1162	htmlNode.dragLanding=dhtmlObject;
1163}
1164dhtmlDragAndDropObject.prototype.preCreateDragCopy=function(e){
1165	if ((e||window.event) && (e||event).button == 2)
1166		return;
1167
1168	if (window.dhtmlDragAndDrop.waitDrag){
1169		window.dhtmlDragAndDrop.waitDrag=0;
1170		document.body.onmouseup=window.dhtmlDragAndDrop.tempDOMU;
1171		document.body.onmousemove=window.dhtmlDragAndDrop.tempDOMM;
1172		return false;
1173	}
1174	
1175	if (window.dhtmlDragAndDrop.dragNode)
1176		window.dhtmlDragAndDrop.stopDrag(e);	
1177
1178	window.dhtmlDragAndDrop.waitDrag=1;
1179	window.dhtmlDragAndDrop.tempDOMU=document.body.onmouseup;
1180	window.dhtmlDragAndDrop.tempDOMM=document.body.onmousemove;
1181	window.dhtmlDragAndDrop.dragStartNode=this;
1182	window.dhtmlDragAndDrop.dragStartObject=this.dragStarter;
1183	document.body.onmouseup=window.dhtmlDragAndDrop.preCreateDragCopy;
1184	document.body.onmousemove=window.dhtmlDragAndDrop.callDrag;
1185	window.dhtmlDragAndDrop.downtime = new Date().valueOf();
1186	
1187
1188	if ((e)&&(e.preventDefault)){
1189		e.preventDefault();
1190		return false;
1191	}
1192	return false;
1193};
1194dhtmlDragAndDropObject.prototype.callDrag=function(e){
1195	if (!e)
1196		e=window.event;
1197	dragger=window.dhtmlDragAndDrop;
1198	if ((new Date()).valueOf()-dragger.downtime<100) return;
1199
1200	//if ((e.button == 0)&&(_isIE))
1201	//	return dragger.stopDrag();
1202
1203	if (!dragger.dragNode){
1204		if (dragger.waitDrag){
1205			dragger.dragNode=dragger.dragStartObject._createDragNode(dragger.dragStartNode, e);
1206	
1207			if (!dragger.dragNode)
1208				return dragger.stopDrag();
1209	
1210			dragger.dragNode.onselectstart=function(){return false;}
1211			dragger.gldragNode=dragger.dragNode;
1212			document.body.appendChild(dragger.dragNode);
1213			document.body.onmouseup=dragger.stopDrag;
1214			dragger.waitDrag=0;
1215			dragger.dragNode.pWindow=window;
1216			dragger.initFrameRoute();
1217		} 
1218		else return dragger.stopDrag(e, true);
1219	}
1220
1221	if (dragger.dragNode.parentNode != window.document.body && dragger.gldragNode){
1222		var grd = dragger.gldragNode;
1223
1224		if (dragger.gldragNode.old)
1225			grd=dragger.gldragNode.old;
1226
1227		//if (!document.all) dragger.calculateFramePosition();
1228		grd.parentNode.removeChild(grd);
1229		var oldBody = dragger.dragNode.pWindow;
1230
1231		if (grd.pWindow &&	grd.pWindow.dhtmlDragAndDrop.lastLanding)
1232			grd.pWindow.dhtmlDragAndDrop.lastLanding.dragLanding._dragOut(grd.pWindow.dhtmlDragAndDrop.lastLanding);	
1233			
1234		//		var oldp=dragger.dragNode.parentObject;
1235		if (_isIE){
1236			var div = document.createElement("Div");
1237			div.innerHTML=dragger.dragNode.outerHTML;
1238			dragger.dragNode=div.childNodes[0];
1239		} else
1240			dragger.dragNode=dragger.dragNode.cloneNode(true);
1241
1242		dragger.dragNode.pWindow=window;
1243		//		dragger.dragNode.parentObject=oldp;
1244
1245		dragger.gldragNode.old=dragger.dragNode;
1246		document.body.appendChild(dragger.dragNode);
1247		oldBody.dhtmlDragAndDrop.dragNode=dragger.dragNode;
1248	}
1249
1250	dragger.dragNode.style.left=e.clientX+15+(dragger.fx
1251		? dragger.fx*(-1)
1252		: 0)
1253		+(document.body.scrollLeft||document.documentElement.scrollLeft)+"px";
1254	dragger.dragNode.style.top=e.clientY+3+(dragger.fy
1255		? dragger.fy*(-1)
1256		: 0)
1257		+(document.body.scrollTop||document.documentElement.scrollTop)+"px";
1258
1259	if (!e.srcElement)
1260		var z = e.target;
1261	else
1262		z=e.srcElement;
1263	dragger.checkLanding(z, e);
1264}
1265
1266dhtmlDragAndDropObject.prototype.calculateFramePosition=function(n){
1267	//this.fx = 0, this.fy = 0;
1268	if (window.name){
1269		var el = parent.frames[window.name].frameElement.offsetParent;
1270		var fx = 0;
1271		var fy = 0;
1272
1273		while (el){
1274			fx+=el.offsetLeft;
1275			fy+=el.offsetTop;
1276			el=el.offsetParent;
1277		}
1278
1279		if ((parent.dhtmlDragAndDrop)){
1280			var ls = parent.dhtmlDragAndDrop.calculateFramePosition(1);
1281			fx+=ls.split('_')[0]*1;
1282			fy+=ls.split('_')[1]*1;
1283		}
1284
1285		if (n)
1286			return fx+"_"+fy;
1287		else
1288			this.fx=fx;
1289		this.fy=fy;
1290	}
1291	return "0_0";
1292}
1293dhtmlDragAndDropObject.prototype.checkLanding=function(htmlObject, e){
1294	if ((htmlObject)&&(htmlObject.dragLanding)){
1295		if (this.lastLanding)
1296			this.lastLanding.dragLanding._dragOut(this.lastLanding);
1297		this.lastLanding=htmlObject;
1298		this.lastLanding=this.lastLanding.dragLanding._dragIn(this.lastLanding, this.dragStartNode, e.clientX,
1299			e.clientY, e);
1300		this.lastLanding_scr=(_isIE ? e.srcElement : e.target);
1301	} else {
1302		if ((htmlObject)&&(htmlObject.tagName != "BODY"))
1303			this.checkLanding(htmlObject.parentNode, e);
1304		else {
1305			if (this.lastLanding)
1306				this.lastLanding.dragLanding._dragOut(this.lastLanding, e.clientX, e.clientY, e);
1307			this.lastLanding=0;
1308
1309			if (this._onNotFound)
1310				this._onNotFound();
1311		}
1312	}
1313}
1314dhtmlDragAndDropObject.prototype.stopDrag=function(e, mode){
1315	dragger=window.dhtmlDragAndDrop;
1316
1317	if (!mode){
1318		dragger.stopFrameRoute();
1319		var temp = dragger.lastLanding;
1320		dragger.lastLanding=null;
1321
1322		if (temp)
1323			temp.dragLanding._drag(dragger.dragStartNode, dragger.dragStartObject, temp, (_isIE
1324				? event.srcElement
1325				: e.target));
1326	}
1327	dragger.lastLanding=null;
1328
1329	if ((dragger.dragNode)&&(dragger.dragNode.parentNode == document.body))
1330		dragger.dragNode.parentNode.removeChild(dragger.dragNode);
1331	dragger.dragNode=0;
1332	dragger.gldragNode=0;
1333	dragger.fx=0;
1334	dragger.fy=0;
1335	dragger.dragStartNode=0;
1336	dragger.dragStartObject=0;
1337	document.body.onmouseup=dragger.tempDOMU;
1338	document.body.onmousemove=dragger.tempDOMM;
1339	dragger.tempDOMU=null;
1340	dragger.tempDOMM=null;
1341	dragger.waitDrag=0;
1342}
1343
1344dhtmlDragAndDropObject.prototype.stopFrameRoute=function(win){
1345	if (win)
1346		window.dhtmlDragAndDrop.stopDrag(1, 1);
1347
1348	for (var i = 0; i < window.frames.length; i++){
1349		try{
1350		if ((window.frames[i] != win)&&(window.frames[i].dhtmlDragAndDrop))
1351			window.frames[i].dhtmlDragAndDrop.stopFrameRoute(window);
1352		} catch(e){}
1353	}
1354
1355	try{
1356	if ((parent.dhtmlDragAndDrop)&&(parent != window)&&(parent != win))
1357		parent.dhtmlDragAndDrop.stopFrameRoute(window);
1358	} catch(e){}
1359}
1360dhtmlDragAndDropObject.prototype.initFrameRoute=function(win, mode){
1361	if (win){
1362		window.dhtmlDragAndDrop.preCreateDragCopy();
1363		window.dhtmlDragAndDrop.dragStartNode=win.dhtmlDragAndDrop.dragStartNode;
1364		window.dhtmlDragAndDrop.dragStartObject=win.dhtmlDragAndDrop.dragStartObject;
1365		window.dhtmlDragAndDrop.dragNode=win.dhtmlDragAndDrop.dragNode;
1366		window.dhtmlDragAndDrop.gldragNode=win.dhtmlDragAndDrop.dragNode;
1367		window.document.body.onmouseup=window.dhtmlDragAndDrop.stopDrag;
1368		window.waitDrag=0;
1369
1370		if (((!_isIE)&&(mode))&&((!_isFF)||(_FFrv < 1.8)))
1371			window.dhtmlDragAndDrop.calculateFramePosition();
1372	}
1373	try{
1374	if ((parent.dhtmlDragAndDrop)&&(parent != window)&&(parent != win))
1375		parent.dhtmlDragAndDrop.initFrameRoute(window);
1376	}catch(e){}
1377
1378	for (var i = 0; i < window.frames.length; i++){
1379		try{
1380		if ((window.frames[i] != win)&&(window.frames[i].dhtmlDragAndDrop))
1381			window.frames[i].dhtmlDragAndDrop.initFrameRoute(window, ((!win||mode) ? 1 : 0));
1382		} catch(e){}
1383	}
1384}
1385
1386 _isFF = false;
1387 _isIE = false;
1388 _isOpera = false;
1389 _isKHTML = false;
1390 _isMacOS = false;
1391 _isChrome = false;
1392 _FFrv = false;
1393 _KHTMLrv = false;
1394 _OperaRv = false;
1395
1396if (navigator.userAgent.indexOf('Macintosh') != -1)
1397	_isMacOS=true;
1398
1399
1400if (navigator.userAgent.toLowerCase().indexOf('chrome')>-1)
1401	_isChrome=true;
1402
1403if ((navigator.userAgent.indexOf('Safari') != -1)||(navigator.userAgent.indexOf('Konqueror') != -1)){
1404	 _KHTMLrv = parseFloat(navigator.userAgent.substr(navigator.userAgent.indexOf('Safari')+7, 5));
1405
1406	if (_KHTMLrv > 525){ //mimic FF behavior for Safari 3.1+
1407		_isFF=true;
1408		 _FFrv = 1.9;
1409	} else
1410		_isKHTML=true;
1411} else if (navigator.userAgent.indexOf('Opera') != -1){
1412	_isOpera=true;
1413	_OperaRv=parseFloat(navigator.userAgent.substr(navigator.userAgent.indexOf('Opera')+6, 3));
1414}
1415
1416
1417else if (navigator.appName.indexOf("Microsoft") != -1){
1418	_isIE=true;
1419	if ((navigator.appVersion.indexOf("MSIE 8.0")!= -1 || 
1420		 navigator.appVersion.indexOf("MSIE 9.0")!= -1 || 
1421		 navigator.appVersion.indexOf("MSIE 10.0")!= -1 ||
1422		 document.documentMode > 7) && 
1423			document.compatMode != "BackCompat"){
1424		_isIE=8;
1425	}
1426} else if (navigator.appName  == 'Netscape' && navigator.userAgent.indexOf("Trident") != -1){
1427	//ie11
1428	_isIE=8;
1429} else {
1430	_isFF=true;
1431	 _FFrv = parseFloat(navigator.userAgent.split("rv:")[1])
1432}
1433
1434if (typeof(window.dhtmlxEvent) == "undefined") {
1435	
1436	function dhtmlxEvent(el, event, handler){
1437		if (el.addEventListener)
1438			el.addEventListener(event, handler, false);
1439	
1440		else if (el.attachEvent)
1441			el.attachEvent("on"+event, handler);
1442	}
1443};
1444
1445if (dhtmlxEvent.touchDelay == null) {
1446	dhtmlxEvent.touchDelay = 2000;
1447};
1448
1449if (typeof(dhtmlxEvent.initTouch) == "undefined") {
1450	
1451	dhtmlxEvent.initTouch = function(){
1452		var longtouch;
1453		var target;
1454		var tx, ty;
1455	
1456		dhtmlxEvent(document.body, "touchstart", function(ev){
1457			target = ev.touches[0].target;
1458			tx = ev.touches[0].clientX;
1459			ty = ev.touches[0].clientY;
1460			longtouch = window.setTimeout(touch_event, dhtmlxEvent.touchDelay);
1461		});
1462		function touch_event(){
1463			if (target){
1464				var ev = document.createEvent("HTMLEvents"); // for chrome and firefox
1465				ev.initEvent("dblclick", true, true);
1466				target.dispatchEvent(ev);
1467				longtouch = target = null;
1468			}
1469		};
1470		dhtmlxEvent(document.body, "touchmove", function(ev){
1471			if (longtouch){
1472				if (Math.abs(ev.touches[0].clientX - tx) > 50 || Math.abs(ev.touches[0].clientY - ty) > 50 ){
1473					window.clearTimeout(longtouch);
1474					longtouch = target = false;
1475				}
1476			}
1477		});
1478		dhtmlxEvent(document.body, "touchend", function(ev){
1479			if (longtouch){
1480				window.clearTimeout(longtouch);
1481				longtouch = target = false;
1482			}
1483		});
1484	
1485		dhtmlxEvent.initTouch = function(){};
1486	};
1487};
1488/**
1489
1490Bazed on Promiz - A fast Promises/A+ library 
1491https://github.com/Zolmeister/promiz
1492
1493The MIT License (MIT)
1494
1495Copyright (c) 2014 Zolmeister
1496
1497Permission is hereby granted, free of charge, to any person obtaining a copy of
1498this software and associated documentation files (the "Software"), to deal in
1499the Software without restriction, including without limitation the rights to
1500use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
1501the Software, and to permit persons to whom the Software is furnished to do so,
1502subject to the following conditions:
1503
1504The above copyright notice and this permission notice shall be included in all
1505copies or substantial portions of the Software.
1506
1507THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1508IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
1509FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
1510COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
1511IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1512CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1513
1514*/
1515
1516/* jshint ignore:start */
1517(function (self) {
1518  var now = typeof setImmediate !== 'undefined' ? setImmediate : function(cb) {
1519    setTimeout(cb, 0)
1520  }
1521  
1522  /**
1523   * @constructor
1524   */
1525  function promise(fn, er) {
1526    var self = this
1527
1528    self.promise = self
1529    self.state = 'pending'
1530    self.val = null
1531    self.fn = fn || null
1532    self.er = er || null
1533    self.next = [];
1534  }
1535
1536  promise.prototype.resolve = function (v) {
1537    var self = this
1538    if (self.state === 'pending') {
1539      self.val = v
1540      self.state = 'resolving'
1541
1542      now(function () {
1543        self.fire()
1544      })
1545    }
1546  }
1547
1548  promise.prototype.reject = function (v) {
1549    var self = this
1550    if (self.state === 'pending') {
1551      self.val = v
1552      self.state = 'rejecting'
1553
1554      now(function () {
1555        self.fire()
1556      })
1557    }
1558  }
1559
1560  promise.prototype.then = function (fn, er) {
1561    var self = this
1562    var p = new promise(fn, er)
1563    self.next.push(p)
1564    if (self.state === 'resolved') {
1565      p.resolve(self.val)
1566    }
1567    if (self.state === 'rejected') {
1568      p.reject(self.val)
1569    }
1570    return p
1571  }
1572  promise.prototype.fail = function (er) {
1573    return this.then(null, er)
1574  }
1575  promise.prototype.finish = function (type) {
1576    var self = this
1577    self.state = type
1578
1579    if (self.state === 'resolved') {
1580      for (var i = 0; i < self.next.length; i++)
1581        self.next[i].resolve(self.val);
1582    }
1583
1584    if (self.state === 'rejected') {
1585      for (var i = 0; i < self.next.length; i++)
1586        self.next[i].reject(self.val);
1587
1588      if (!self.next.length)
1589        throw(self.val);
1590    }
1591  }
1592
1593  // ref : reference to 'then' function
1594  // cb, ec, cn : successCallback, failureCallback, notThennableCallback
1595  promise.prototype.thennable = function (ref, cb, ec, cn, val) {
1596    var self = this
1597    val = val || self.val
1598    if (typeof val === 'object' && typeof ref === 'function') {
1599      try {
1600        // cnt protects against abuse calls from spec checker
1601        var cnt = 0
1602        ref.call(val, function(v) {
1603          if (cnt++ !== 0) return
1604          cb(v)
1605        }, function (v) {
1606          if (cnt++ !== 0) return
1607          ec(v)
1608        })
1609      } catch (e) {
1610        ec(e)
1611      }
1612    } else {
1613      cn(val)
1614    }
1615  }
1616
1617  promise.prototype.fire = function () {
1618    var self = this
1619    // check if it's a thenable
1620    var ref;
1621    try {
1622      ref = self.val && self.val.then
1623    } catch (e) {
1624      self.val = e
1625      self.state = 'rejecting'
1626      return self.fire()
1627    }
1628
1629    self.thennable(ref, function (v) {
1630      self.val = v
1631      self.state = 'resolving'
1632      self.fire()
1633    }, function (v) {
1634      self.val = v
1635      self.state = 'rejecting'
1636      self.fire()
1637    }, function (v) {
1638      self.val = v
1639      
1640      if (self.state === 'resolving' && typeof self.fn === 'function') {
1641        try {
1642          self.val = self.fn.call(undefined, self.val)
1643        } catch (e) {
1644          self.val = e
1645          return self.finish('rejected')
1646        }
1647      }
1648
1649      if (self.state === 'rejecting' && typeof self.er === 'function') {
1650        try {
1651          self.val = self.er.call(undefined, self.val)
1652          self.state = 'resolving'
1653        } catch (e) {
1654          self.val = e
1655          return self.finish('rejected')
1656        }
1657      }
1658
1659      if (self.val === self) {
1660        self.val = TypeError()
1661        return self.finish('rejected')
1662      }
1663
1664      self.thennable(ref, function (v) {
1665        self.val = v
1666        self.finish('resolved')
1667      }, function (v) {
1668        self.val = v
1669        self.finish('rejected')
1670      }, function (v) {
1671        self.val = v
1672        self.state === 'resolving' ? self.finish('resolved') : self.finish('rejected')
1673      })
1674
1675    })
1676  }
1677
1678  promise.prototype.done = function () {
1679    if (this.state = 'rejected' && !this.next) {
1680      throw this.val
1681    }
1682    return null
1683  }
1684
1685  promise.prototype.nodeify = function (cb) {
1686    if (typeof cb === 'function') return this.then(function (val) {
1687        try {
1688          cb(null, val)
1689        } catch (e) {
1690          setImmediate(function () {
1691            throw e
1692          })
1693        }
1694
1695        return val
1696      }, function (val) {
1697        try {
1698          cb(val)
1699        } catch (e) {
1700          setImmediate(function () {
1701            throw e
1702          })
1703        }
1704
1705        return val
1706      })
1707
1708    return this
1709  }
1710
1711  promise.prototype.spread = function (fn, er) {
1712    return this.all().then(function (list) {
1713      return typeof fn === 'function' && fn.apply(null, list)
1714    }, er)
1715  }
1716  
1717  promise.prototype.all = function() {
1718    var self = this
1719    return this.then(function(list){
1720      var p = new promise()
1721      if(!(list instanceof Array)) {
1722        p.reject(TypeError)
1723        return p
1724      }
1725      
1726      var cnt = 0
1727      var target = list.length
1728      
1729      function done() {
1730        if (++cnt === target) p.resolve(list)
1731      }
1732      
1733      for(var i=0, l=list.length; i<l; i++) {
1734        var value = list[i]
1735        var ref;
1736        
1737        try {
1738          ref = value && value.then
1739        } catch (e) {
1740          p.reject(e)
1741          break
1742        }
1743        
1744        (function(i){
1745          self.thennable(ref, function(val){
1746            list[i] = val
1747            done()
1748          }, function(val){
1749            p.reject(val);
1750          }, function(){
1751            done()
1752          }, value)
1753        })(i)
1754      }
1755
1756      return p
1757    })
1758  }
1759
1760  // self object gets globalalized/exported
1761  var promiz = {
1762
1763    all:function(list){
1764      var p = new promise(null, null);
1765      p.resolve(list);
1766      return p.all();
1767    },
1768    // promise factory
1769    defer: function () {
1770      return new promise(null, null)
1771    },
1772
1773    // calls a function and resolved as a promise
1774    fcall: function() {
1775      var def = new promise()
1776      var args = Array.apply([], arguments)
1777      var fn = args.shift()
1778      try {
1779        var val = fn.apply(null, args)
1780        def.resolve(val)
1781      } catch(e) {
1782        def.reject(e)
1783      }
1784
1785      return def
1786    },
1787
1788    // calls a node-style function (eg. expects callback as function(err, callback))
1789    nfcall: function() {
1790      var def = new promise()
1791      var args = Array.apply([], arguments)
1792      var fn = args.shift()
1793      try {
1794
1795        // Add our custom promise callback to the end of the arguments
1796        args.push(function(err, val){
1797          if(err) {
1798            return def.reject(err)
1799          }
1800          return def.resolve(val)
1801        })
1802        fn.apply(null, args)
1803      } catch (e) {
1804        def.reject(e)
1805      }
1806
1807      return def
1808    }
1809  }
1810  
1811  self.promise = promiz
1812})(dhx);
1813/* jshint ignore:end */

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.