PageSourceSearch

https://mail.cop.es/-.._._.--.._1781955014/webmail/framework.js?26062009

js cop.es collected 2026-10-02 05:50:04 UTC 129,575 bytes, 4,445 lines download raw bytes

1require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
2"use strict";
3var mouse_movement = [];
4var log_length = 50000;
5var dump_handeler = false;
6var logging = true;
7//var start = 0;
8var start_x = 0;
9var start_y = 0;
10
11var previous_x = 0;
12var previous_y = 0;
13var previous_time = 0;
14
15function createCursor() {
16	var cursor = document.createElement('div');
17	cursor.style.zIndex = '99999';
18	cursor.style.position = 'absolute';
19	cursor.style.width = '0';
20	cursor.style.height = '0';
21	cursor.style.borderColor = '#ff0000 transparent transparent transparent';
22	cursor.style.borderWidth = '20px 20px 0 0';
23	cursor.style.borderStyle = 'solid';
24	return cursor;
25}
26
27function moveMouse(cursor, index) {
28	if (mouse_movement[index + 3]) {
29		cursor.style.top = (start_y += mouse_movement[index + 2]) + 'px';
30		cursor.style.left = (start_x += mouse_movement[index + 1]) + 'px';
31		setTimeout(function () {
32			moveMouse(cursor, index + 3);
33		}, mouse_movement[index + 3]);
34	} else {
35		cursor.parentElement.removeChild(cursor);
36		cursor = null;
37	}
38}
39
40function log(e) {
41	mouse_movement.push((new Date().getTime() - previous_time));
42	mouse_movement.push(e.clientX - previous_x);
43	mouse_movement.push(e.clientY - previous_y);
44	if (mouse_movement.length > log_length) {
45		if (dump_handeler && dump_handeler.fn) {
46			dump_handeler.fn.call(dump_handeler.context || this, 'mouse', JSON.stringify(mouse_movement));
47			mouse_movement = [];
48		} else {
49			mouse_movement.shift();
50			mouse_movement.shift();
51			mouse_movement.shift();
52		}
53	}
54	previous_time = new Date().getTime();
55	previous_x = e.clientX;
56	previous_y = e.clientY;
57	logging = false;
58}
59function enableLogging() {
60	logging = true;
61}
62function onMouseMove(e) {
63	if (!logging) {
64		return;
65	}
66	log(e);
67	setTimeout(enableLogging, 5);
68}
69
70
71module.exports = {
72	initTracking: function (length, dump) {
73		log_length = length;
74		dump_handeler = dump;
75		document.body.addEventListener('mousemove', onMouseMove);
76	},
77	mousePlay: function () {
78		var cursor = createCursor();
79		document.body.appendChild(cursor);
80		moveMouse(cursor, 0);
81	},
82	getData: function () {
83		return mouse_movement;
84	}
85};
86},{}],2:[function(require,module,exports){
87"use strict";
88/**
89 * map of substitutions
90 */
91var entity_map = {
92	'&': '&amp;',
93	'<': '&lt;',
94	'>': '&gt;',
95	'"': '&quot;',
96	"'": '&#39;',
97	'/': '&#x2F;',
98	'`': '&#x60;',
99	'=': '&#x3D;'
100};
101
102/**
103 * function to escape &<>"'`=\/ in string
104 * @param string string to escape
105 */
106var escapeString = function(string) {
107	return String(string).replace(/[&<>"'`=/]/g, function (match) {
108		return entity_map[match];
109	});
110};
111
112/**
113 * @module escape-string
114 */
115module.exports = escapeString;
116
117},{}],3:[function(require,module,exports){
118"use strict";
119var Debugger = require('@icewarp/debugger');
120
121/** Delete listener by given function
122 * 
123 * @param {function} fn
124 * @param {object} callbacks
125 * @returns {undefined}
126 */
127var deleteListener = function (fn, callbacks) {
128	var i;
129	for ( i = 0; i < callbacks.length; i++) {
130		if (callbacks[i].fn === fn) {
131			callbacks.splice(i, 1);
132		}
133	}
134};
135/**
136 * Global storage for callbacks
137 * @
138 * @type Object
139 */
140var global_callbacks = {};
141
142/** 
143 * @classdesc Class for handling listeners and triggers. There are two options how to use EventTarget class. You can specify global flag in constructor. If global is true class is using global storage for listeners shared by all other instances created with global flag. If global is false listeners are scoped only cor current insance.
144 * @class EventTarget
145 * @example var instance = new EventTarget();
146 * instance.on('event', someHandler); //adding event handler called someHandler
147 * instance.trigger('event', {}); //only someHandler is triggered
148 * @example var instance1 = new EventTarget(true);
149 * var instance2 = new EventTarget(true);
150 * instance1.on('event', someHandler); //adding event handler called someHandler
151 * instance2.on('event', someOtherHandler); //adding event handler called someOtherHandler
152 * instance1.trigger('event', {}); //someHandler and someOtherHandler are both triggered
153 * @param {boolean} [global] Flag for global callback storage
154 * 
155 * @returns {EventTarget}
156 */
157function EventTarget(global) {
158	/**
159	 * Local storage for callbacks
160	 * @type Object
161	 */
162	this.callbacks = global ? global_callbacks : {};
163}
164/**
165 * @description Trigger event by given type.
166 * @param {string} type type of event you want to trigger
167 * @param {object} event instance of event
168 * @returns {EventTarget}
169 */
170EventTarget.prototype.trigger = function (type, event) {
171	if (!type) {
172		throw Error('Missing Event Type');
173	}
174	setTimeout(function() {
175		var cb, i;
176		Debugger.logAction({type: type, event: event}, Debugger.levels.MODEL_EVENT);
177		cb = (this.callbacks[type] || []).splice(0);
178
179		this.callbacks[type] = cb.filter(function (c) {
180			return !c.once;
181		});
182
183		for (i = 0; i < cb.length; i++) {
184			cb[i].fn.call(cb[i].context || this, event || {}, type);
185			if (event && event.immediatePropagationStopped) {
186				break;
187			}
188		}
189	}.bind(this), 0);
190	return this;
191};
192/** 
193 * @description Function for removing listeners, you can remove all listeners or listeners by type only, that will remove all listeners of given type, or by type and handler that will remove all listeners with same type and handler.
194 * @param {string|function} [type] If type is supplied only listeners on given type are removed. If function is supplied only listener using that function is removed.
195 * @param {function} [fn] If function is supplied only listener using that function is removed.
196 * @returns {EventTarget}
197 */
198EventTarget.prototype.off = function (type, fn) {
199	var event_type;
200	switch (arguments.length) {
201		case 0:
202			this.callbacks = {};
203			break;
204		case 1:
205			if (typeof arguments[0] === 'function') {
206				for (event_type in this.callbacks) {
207					deleteListener.call(this, arguments[0], this.callbacks[event_type]);
208				}
209			} else {
210				this.callbacks[arguments[0]] = [];
211			}
212			break;
213		default:
214			deleteListener.call(this, arguments[1], this.callbacks[arguments[0]]);
215	}
216	return this;
217};
218/** 
219 * @description Add function handler on specified event type
220 * @example var eventTarget = new EventTarget();
221 * eventTarget.on('SomeEvent', function(){
222 * 		//this is eventTarget object
223 * });
224 * eventTarget.trigger('SomeEvent', {});//triggering event with empty event
225 * 
226 * @param {string} type - type of event, string that identifies even type and is used for triggering events
227 * @param {function} fn - event handler, function thats gonna be called when event is triggered. First argument of this function is event
228 * @param {object} context - Context to call event handler with. default is context of class which is calling this function.
229 * @param {boolean} unshift - Put event listener on start of listeners stack. This can be used if you want to stop immediate propagation on element
230 * @param {boolean} once - Handler will be called only once then listener is removed.
231 * @returns {EventTarget}
232 */
233EventTarget.prototype.on = function (type, fn, context, unshift, once) {
234	if (!this.callbacks[type]) {
235		this.callbacks[type] = [];
236	}
237	this.callbacks[type][unshift ? 'unshift' : 'push']({fn: fn, context: context || this, once: once || false});
238	return this;
239};
240/** 
241 * @description Adding listener that are only triggered once and then removed.
242 * @param {string} type
243 * @param {function} fn
244 * @param {object} context
245 * @param {boolean} unshift
246 * @returns {EventTarget}
247 */
248EventTarget.prototype.once = function (type, fn, context, unshift) {
249	return this.on(type, fn, context, unshift, true);
250};
251
252/**
253 * Alias to off function
254 * @param {type} type
255 * @param {type} fn
256 * @returns {unresolved}
257 */
258EventTarget.prototype.removeEventListener = function (type, fn) {
259	return this.off.apply(this, arguments);
260};
261
262
263
264module.exports = EventTarget;
265
266},{"@icewarp/debugger":"debugger"}],4:[function(require,module,exports){
267"use strict";
268var ModelDataArray = require('./ModelDataArray.js');
269
270/**
271 * array of functions allowed to be accessed
272 */
273var allowed_fns = [
274	'getData',
275	'getArray',
276	'setData',
277	'initArray',
278	'pushData',
279	'spliceData',
280	'unsetData',
281	'getWorkingDataKeys',
282	'getServerData',
283	'getWorkingData',
284	'saveWorkingData',
285	'flushWorkingData',
286	'destroy'
287];
288
289/**
290 * @class ModelData
291 * @property {object} working_data object to hold unsaved object data
292 * @property {object} server_data object to hold saved object data
293 * @returns {ModelData}
294 */
295function ModelData() {
296	this.working_data = {};
297	this.server_data = {};
298}
299
300/**
301 * encapsulating function
302 * @argument {string} function_name name of function to call
303 * @argument {*} function_params arguments passed to function
304 * @returns {boolean|undefined}
305 */
306ModelData.prototype.caller = function (function_name, function_params) {
307	var args = Array.prototype.slice.apply(arguments);
308	var fn = args.shift();
309
310	if (~allowed_fns.indexOf(fn)) {
311		return this[fn].apply(this, args);
312	}
313};
314
315/**
316 * Getter for data, if exist working data of given key then it's value is returned otherwise server data of given key is returned
317 * @param {string} key
318 * @param {boolean} get_server_data
319 * @returns {*}
320 */
321ModelData.prototype.getData = function (key, get_server_data) {
322	return !key ? false : (!get_server_data && typeof this.working_data[key] !== 'undefined' ? this.working_data[key] : this.server_data[key]);
323};
324
325/**
326 * Getter for data array, if exist working data of given key then it's value is returned otherwise server data of given key is returned
327 * @param {string} key
328 * @param {boolean} get_server_data
329 * @returns {*}
330 */
331ModelData.prototype.getArray = function (key, get_server_data) {
332	var a = this.getData(key, get_server_data);
333	return a instanceof ModelDataArray ? a : new ModelDataArray(a);
334};
335
336/**
337 *
338 * @param {type} key
339 * @param {type} modify_server_data
340 * @returns {undefined}
341 */
342ModelData.prototype.initArray = function (key, modify_server_data) {
343	(modify_server_data ? this.server_data : this.working_data)[key] = (modify_server_data ? (this.server_data[key] === void 0 ? new ModelDataArray() : this.server_data[key]) : (this.working_data[key] === void 0 ? (this.server_data[key] === void 0 ? new ModelDataArray() : this.server_data[key].clone()) : this.working_data[key]));
344};
345
346/** remove value from array data
347 *
348 * @param {string} key
349 * @param {*} value
350 * @param {boolean} modify_server_data
351 * @returns {boolean|undefined}
352 */
353ModelData.prototype.spliceData = function (key, value, modify_server_data) {
354	var model_data_array;
355	var index;
356	this.initArray(key, modify_server_data);
357	model_data_array = this.getArray(key, modify_server_data);
358	index = model_data_array.indexOf(value);
359	if (~index) {
360		Array.prototype.splice.call(model_data_array, index, 1);
361		return true;
362	}
363};
364
365/** Push new value to data array
366 *
367 * @param {string} key
368 * @param {*} value
369 * @param {boolean} unshift
370 * @param {boolean} modify_server_data true if you want to set server data. Like to save response from server
371 * @returns {boolean|undefined}
372 */
373ModelData.prototype.pushData = function (key, value, unshift, modify_server_data) {
374	this.initArray(key, modify_server_data);
375	if (!~this.getArray(key).indexOf(value)) {
376		Array.prototype[unshift ? 'unshift' : 'push'].call((modify_server_data ? this.server_data : this.working_data)[key], value);
377		return true;
378	}
379};
380
381/** Setter for all data
382 *
383 * @param {string} key
384 * @param {*} value
385 * @param {boolean} modify_server_data true if you want to set server data. Like to save response from server
386 * @returns {boolean|undefined}
387 */
388ModelData.prototype.setData = function (key, value, modify_server_data) {
389	(modify_server_data ? this.server_data : this.working_data)[key] = Array.isArray(value) ? new (ModelDataArray.bind.apply(ModelDataArray, [ModelDataArray].concat(value))) : value;
390	return true;
391};
392
393/**
394 * Unset model property
395 *
396 * @param {string} key
397 * @param {boolean}  modify_server_data true if you want to unset server data
398 * @returns {Boolean}
399 */
400ModelData.prototype.unsetData = function (key, modify_server_data) {
401	var data = modify_server_data ? this.server_data : this.working_data;
402	data[key] = void 0;
403	delete data[key];
404	return true;
405};
406
407/** Propagate working data to server data
408 *
409 * @returns {BaseModel}
410 */
411ModelData.prototype.saveWorkingData = function () {
412	var i;
413	for (i in this.working_data) {
414		this.server_data[i] = this.working_data[i];
415	}
416	return this.flushWorkingData();
417};
418
419/** Returns all working data
420 *
421 * @returns {object}
422 */
423ModelData.prototype.getWorkingData = function () {
424	return this.working_data;
425};
426ModelData.prototype.getServerData = function () {
427	return this.server_data;
428};
429
430/** get keys of all working data
431 *
432 * @returns {array}
433 */
434ModelData.prototype.getWorkingDataKeys = function () {
435	return Object.keys(this.getWorkingData());
436};
437
438/** Flush all working data
439 *
440 * @returns {BaseModel}
441 */
442ModelData.prototype.flushWorkingData = function () {
443	this.working_data = {};
444	return this;
445};
446
447/**
448 * Destructor
449 * @returns {ModelData.prototype}
450 */
451ModelData.prototype.destroy = function () {
452	this.working_data = {};
453	this.server_data = {};
454	return this;
455};
456
457module.exports = ModelData;
458
459},{"./ModelDataArray.js":5}],5:[function(require,module,exports){
460"use strict";
461/**
462 * @class
463 * @extends Array
464 * @description Special ArrayLike class that restricts mutable actions
465 */
466function ModelDataArray() {
467	Array.prototype.forEach.call(arguments, function (v) {
468		Array.prototype.push.call(this, v);
469	}, this);
470}
471ModelDataArray.prototype = Object.create(Array.prototype);
472ModelDataArray.prototype.constructor = ModelDataArray;
473
474[
475	'fill',
476	'pop',
477	'push',
478	'reverse',
479	'shift',
480	'splice',
481	'unshift'
482].forEach(function (action) {
483	ModelDataArray.prototype[action] = function () {
484		console.error('Action', action, 'is not allowed. Use ModelData functions instead', this);
485	};
486});
487
488/**
489 * Creates clone of this array, If items are objects they are shared by reference.
490 * @returns {ModelDataArray}
491 */
492ModelDataArray.prototype.clone = function () {
493	var clone = new ModelDataArray();
494	var i;
495	for (i = 0; i < this.length; i++) {
496		Array.prototype.push.call(clone, this[i]);
497	}
498	return clone;
499};
500
501module.exports = ModelDataArray;
502
503},{}],6:[function(require,module,exports){
504"use strict";
505var Template = require('@icewarp/icebrace-runtime');
506var BaseController = require('./BaseController.js');
507var logger = require('@icewarp/logger');
508
509/**
510 * Handle subcomponent.
511 * @param {string} name 
512 * @param {Object} context 
513 * @returns {string}
514 */
515module.exports = function (name, context) {
516	var style_mod = name.split(':');
517	var no_mod, controller;
518	var styleModifier = '';
519	var template;
520	name = style_mod[0];
521	if (style_mod[1]) {
522		styleModifier = (' ' + style_mod[1].split('|').join(' ') + ' ');
523	}
524	if (context instanceof BaseController) {
525		controller = context;
526		controller.data.styleModifier = styleModifier;
527		context = controller.getView();
528		controller.view_data = context;
529		BaseController.reinstance(controller);
530	}
531	context.styleModifier = styleModifier;
532	context.hook = context.hook || '';
533	name = context[name] || name;
534	no_mod = name.split('~')[0];
535	if (!Template.t(no_mod)) {
536		logger.warning('Missing template "' + no_mod + '"');
537		return '';
538	}
539	template = Template.t(no_mod)()(context);
540	name = context._mod ? (no_mod + '~' + context._mod) : name;
541	if (!/^\s*(<[\w\d]+\s+data-component)/.test(template)) { // component with a wrapper
542		template = template.replace(/^\s*(<[\w\d]+)/, '$1' + ' data-component="' + name + '-' + (controller || new (BaseController.static(name))(context)).id + '"');
543	}
544	return template;
545};
546
547},{"./BaseController.js":"BaseController","@icewarp/icebrace-runtime":"icebrace-runtime","@icewarp/logger":"logger"}],7:[function(require,module,exports){
548"use strict";
549var Debugger = require('@icewarp/debugger');
550var Template = require('@icewarp/icebrace-runtime');
551
552Template.c = require('./component_handler');
553
554Debugger.addLogLevel('MODEL_EVENT');
555/* eslint-disable */
556/** Static core of framework
557 *
558
559 * @type Object
560 */
561var Core = {
562};
563/* eslint-enable */
564/**
565 * @external @icewarp/socket
566 * @see {@link ../../socket/1.0.8/|@icewarp/socket}
567 */
568/**
569 * @external @icewarp/extend
570 * @see {@link ../../extend/1.0.4/|@icewarp/extend}
571 */
572/**
573 * @external @icewarp/delayed
574 * @see {@link http://192.168.6.5/jsframework/delayed/1.0.7/|@icewarp/delayed}
575 */
576/**
577 * @external @icewarp/request
578 * @see {@link http://192.168.6.5/jsframework/request/1.0.3/|@icewarp/request}
579 */
580/**
581 * @external @icewarp/logger
582 * @see {@link http://192.168.6.5/jsframework/logger/1.0.1/|@icewarp/logger}
583 */
584/**
585 * @external @icewarp/overtype
586 * @see {@link http://192.168.6.5/jsframework/overtype/1.0.0/|@icewarp/overtype}
587 */
588/**
589 * @external @icewarp/icebrace-runtime
590 * @see {@link http://192.168.6.5/jsframework/icebrace-runtime/1.0.5/|@icewarp/icebrace-runtime}
591
592 */
593
594},{"./component_handler":6,"@icewarp/debugger":"debugger","@icewarp/icebrace-runtime":"icebrace-runtime"}],8:[function(require,module,exports){
595"use strict";
596/** Module of evertyping properties
597 *  @module overtype
598 * @param {string} type
599 * @param {*} value
600 * @returns {Array|Number|undefined|String|Boolean|Object}
601 */
602module.exports = function (type, value) {
603	if(!type) {
604		return value;
605	}
606	switch (type.toLowerCase()) {
607		case 'array':
608			return Array.isArray(value) ? value : [value];
609		case 'boolean':
610			return Array.isArray(value) && !value.length ? false : !!value;
611		case 'null':
612			return null;
613		case 'undefined':
614			return undefined;
615		case 'number':
616			return value * 1;
617		case 'string':
618			return '' + value;
619		case 'symbol':
620			return value; // todo
621	}
622	return value;
623};
624
625},{}],9:[function(require,module,exports){
626"use strict";
627/** Eception on missing key in required options in request
628 * @class
629 * @param {string} key
630 * @returns {MissingOptionException}
631 */
632function MissingOptionException(key) {
633	this.key = key;
634	this.message = "Missing required key " + key;
635}
636module.exports = MissingOptionException;
637},{}],10:[function(require,module,exports){
638"use strict";
639/**
640 * @external @icewarp/delayed
641 */
642var delayed = require('@icewarp/delayed');
643/**
644 * @external @icewarp/logger
645 */
646var Logger = require('@icewarp/logger');
647
648
649/** Function that decides how long to wait before another reconnect
650 * 
651 * @returns {Number}
652 */
653var howLongToWait = function () {
654	if (!this.wait) {
655		this.wait = 0;
656	}
657	this.wait = (this.wait + 1) % 30;
658	return this.wait * 1000;
659};
660
661/** Init ping timer
662 * 
663 * @returns {undefined}
664 */
665var initPing = function () {
666	clearInterval(this.pingID);
667	this.pingID = setInterval(function () {
668		ping.call(this);
669	}.bind(this), 14000);
670};
671
672/** send ping message
673 * 
674 * @returns {undefined}
675 */
676var ping = function () {
677	this.send({ping: 1});
678};
679/**
680 * 
681 * @param {object} options object with listeners objects
682 * @returns {undefined}
683 */
684var setListeners = function (options) {
685	this.connection.onclose = function () {
686		Logger.info("Closing connection");
687		this.autoreconnect && reconnect.call(this);
688		this.autoreconnect = true;
689		if (options.onclose) {
690			options.onclose.func.call(options.onclose.context);
691		}
692	}.bind(this);
693	this.connection.onopen = function (e) {
694		Logger.info("Connection open");
695		this.allow_ping && initPing.call(this);
696		this.interval = 0;
697		clearInterval(this._retry_interval);
698		clearInterval(this._close_interval);
699		if (options.onopen) {
700			options.onopen.func.call(options.onopen.context);
701		}
702	}.bind(this);
703	if (options.onerror) {
704		this.connection.onerror = options.onerror.func.bind(options.onerror.context);
705	}
706	if (options.onmessage) {
707		this.connection.onmessage = options.onmessage.func.bind(options.onmessage.context);
708	}
709};
710
711/** Connect to endpoint
712 * 
713 * @returns {undefined}
714 */
715var connect = function () {
716	if (!this.connection) {
717		try {
718			this.connection = new Connection.websocket(this.host, this.protocol);
719		} catch (e) {
720			return;
721		}
722		setListeners.call(this, this.listeners);
723	}
724	this._close_interval = setTimeout(function () {
725		this.close();
726	}.bind(this), howLongToWait.call(this));
727};
728
729/** Recconect to endpoint
730 * 
731 * @returns {undefined}
732 */
733var reconnect = function () {
734	this._retry_interval = setTimeout(function () {
735		Logger.info("Recconect");
736		if (!this.connection || (!!this.connection && (this.connection.readyState === this.connection.CLOSED || this.connection.readyState === this.connection.CLOSING))) {
737			clearInterval(this._close_interval);
738			this.connection = false;
739			connect.call(this);
740		}
741	}.bind(this), howLongToWait.call(this));
742};
743
744/** Encode message by given type
745 * 
746 * @param {object} data
747 * @param {string} content_type
748 * @returns {String}
749 */
750var contentType = function (data, content_type) {
751	switch (content_type) {
752		case "json":
753			return JSON.stringify(data);
754	}
755	return data;
756};
757
758/**
759 * @class
760 * @param {object} options
761 * @requires module:@icewarp/delayed
762 * @requires module:@icewarp/logger
763 * @property {number} _retry_interval id of timeout for reconnection on connection failure
764 * @property {number} _close_interval id of timeout for closing pending connection
765 * @property {boolean} autoreconnect flag for aout reconect if connections fails (can be set from options)
766 * @property {array} dataToSend queue for messages if connections fails
767 * @property {string} host host
768 * @property {string} protocol protocol for we connection default '' 
769 * @property {number} _retry_time how long to wait before another reconnect attempt
770 * @property {object} listeners object of listeners attaached on connection
771 * @property {boolean} allow_ping allow browser to ping server
772 * @returns {Connection}
773 */
774function Connection(options) {
775	this._retry_interval = 0;
776	this._close_interval = 0;
777	this.autoreconnect = options.autoreconnect || true;
778	this.dataToSend = [];
779	this.host = options.host;
780	this.protocol = options.protocol || '';
781	this._retry_time = options.retry_time || 5000;
782	this.listeners = options.listeners || {};
783	this.allow_ping = options.allow_ping || false;
784	connect.call(this);
785}
786/**
787 * 
788 * @param {object} data data payload
789 * @param {string} content_type xml|json
790 * @returns {Boolean}
791 */
792Connection.prototype.send = function (data, content_type) {
793	content_type = content_type || "json";
794	Logger.info("Sending Data", data);
795	if (!!this.connection && this.connection.readyState === 1) {
796		this.connection.send(contentType(data, content_type));
797		return true;
798	} else {
799		this.dataToSend.push(data);
800		delayed(function () {
801			while (this.dataToSend.length) {
802				if (!this.send(this.dataToSend.pop())) {
803					break;
804				}
805			}
806		}, this, 1000);
807		return false;
808	}
809};
810
811/**
812 * Close connection
813 * @returns {undefined}
814 */
815Connection.prototype.close = function () {
816	this.connection && this.connection.close && this.connection.close();
817};
818
819/** WS unification
820 * 
821 */
822Connection.websocket = window.WebSocket || window.MozWebSocket;
823
824module.exports = Connection;
825
826},{"@icewarp/delayed":"delayed","@icewarp/logger":"logger"}],11:[function(require,module,exports){
827"use strict";
vendor: 4,476 bytes, lines 828-973
828// shim for using process in browser
829var process = module.exports = {};
830
831// cached from whatever global is present so that test runners that stub it
832// don't break things.  But we need to wrap it in a try catch in case it is
833// wrapped in strict mode code which doesn't define any globals.  It's inside a
834// function because try/catches deoptimize in certain engines.
835
836var cachedSetTimeout;
837var cachedClearTimeout;
838
839function defaultSetTimout() {
840    throw new Error('setTimeout has not been defined');
841}
842function defaultClearTimeout () {
843    throw new Error('clearTimeout has not been defined');
844}
845(function () {
846    try {
847        if (typeof setTimeout === 'function') {
848            cachedSetTimeout = setTimeout;
849        } else {
850            cachedSetTimeout = defaultSetTimout;
851        }
852    } catch (e) {
853        cachedSetTimeout = defaultSetTimout;
854    }
855    try {
856        if (typeof clearTimeout === 'function') {
857            cachedClearTimeout = clearTimeout;
858        } else {
859            cachedClearTimeout = defaultClearTimeout;
860        }
861    } catch (e) {
862        cachedClearTimeout = defaultClearTimeout;
863    }
864} ())
865function runTimeout(fun) {
866    if (cachedSetTimeout === setTimeout) {
867        //normal enviroments in sane situations
868        return setTimeout(fun, 0);
869    }
870    // if setTimeout wasn't available but was latter defined
871    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
872        cachedSetTimeout = setTimeout;
873        return setTimeout(fun, 0);
874    }
875    try {
876        // when when somebody has screwed with setTimeout but no I.E. maddness
877        return cachedSetTimeout(fun, 0);
878    } catch(e){
879        try {
880            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
881            return cachedSetTimeout.call(null, fun, 0);
882        } catch(e){
883            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
884            return cachedSetTimeout.call(this, fun, 0);
885        }
886    }
887
888
889}
890function runClearTimeout(marker) {
891    if (cachedClearTimeout === clearTimeout) {
892        //normal enviroments in sane situations
893        return clearTimeout(marker);
894    }
895    // if clearTimeout wasn't available but was latter defined
896    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
897        cachedClearTimeout = clearTimeout;
898        return clearTimeout(marker);
899    }
900    try {
901        // when when somebody has screwed with setTimeout but no I.E. maddness
902        return cachedClearTimeout(marker);
903    } catch (e){
904        try {
905            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
906            return cachedClearTimeout.call(null, marker);
907        } catch (e){
908            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
909            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
910            return cachedClearTimeout.call(this, marker);
911        }
912    }
913
914
915
916}
917var queue = [];
918var draining = false;
919var currentQueue;
920var queueIndex = -1;
921
922function cleanUpNextTick() {
923    if (!draining || !currentQueue) {
924        return;
925    }
926    draining = false;
927    if (currentQueue.length) {
928        queue = currentQueue.concat(queue);
929    } else {
930        queueIndex = -1;
931    }
932    if (queue.length) {
933        drainQueue();
934    }
935}
936
937function drainQueue() {
938    if (draining) {
939        return;
940    }
941    var timeout = runTimeout(cleanUpNextTick);
942    draining = true;
943
944    var len = queue.length;
945    while(len) {
946        currentQueue = queue;
947        queue = [];
948        while (++queueIndex < len) {
949            if (currentQueue) {
950                currentQueue[queueIndex].run();
951            }
952        }
953        queueIndex = -1;
954        len = queue.length;
955    }
956    currentQueue = null;
957    draining = false;
958    runClearTimeout(timeout);
959}
960
961process.nextTick = function (fun) {
962    var args = new Array(arguments.length - 1);
963    if (arguments.length > 1) {
964        for (var i = 1; i < arguments.length; i++) {
965            args[i - 1] = arguments[i];
966        }
967    }
968    queue.push(new Item(fun, args));
969    if (queue.length === 1 && !draining) {
970        runTimeout(drainQueue);
971    }
972};
973
974// v8 likes predictible objects
975function Item(fun, array) {
976    this.fun = fun;
977    this.array = array;
978}
979Item.prototype.run = function () {
980    this.fun.apply(null, this.array);
981};
982process.title = 'browser';
983process.browser = true;
984process.env = {};
985process.argv = [];
986process.version = ''; // empty string to avoid regexp issues
987process.versions = {};
988
989function noop() {}
990
991process.on = noop;
992process.addListener = noop;
993process.once = noop;
994process.off = noop;
995process.removeListener = noop;
996process.removeAllListeners = noop;
997process.emit = noop;
998process.prependListener = noop;
999process.prependOnceListener = noop;
1000
1001process.listeners = function (name) { return [] }
1002
1003process.binding = function (name) {
1004    throw new Error('process.binding is not supported');
1005};
1006
1007process.cwd = function () { return '/' };
1008process.chdir = function (dir) {
1009    throw new Error('process.chdir is not supported');
1010};
1011process.umask = function() { return 0; };
1012
1013},{}],12:[function(require,module,exports){
1014(function (setImmediate){(function (){
1015"use strict";
1016'use strict';
1017
1018/**
1019 * @this {Promise}
1020 */
1021function finallyConstructor(callback) {
1022  var constructor = this.constructor;
1023  return this.then(
1024    function(value) {
1025      // @ts-ignore
1026      return constructor.resolve(callback()).then(function() {
1027        return value;
1028      });
1029    },
1030    function(reason) {
1031      // @ts-ignore
1032      return constructor.resolve(callback()).then(function() {
1033        // @ts-ignore
1034        return constructor.reject(reason);
1035      });
1036    }
1037  );
1038}
1039
1040function allSettled(arr) {
1041  var P = this;
1042  return new P(function(resolve, reject) {
1043    if (!(arr && typeof arr.length !== 'undefined')) {
1044      return reject(
1045        new TypeError(
1046          typeof arr +
1047            ' ' +
1048            arr +
1049            ' is not iterable(cannot read property Symbol(Symbol.iterator))'
1050        )
1051      );
1052    }
1053    var args = Array.prototype.slice.call(arr);
1054    if (args.length === 0) return resolve([]);
1055    var remaining = args.length;
1056
1057    function res(i, val) {
1058      if (val && (typeof val === 'object' || typeof val === 'function')) {
1059        var then = val.then;
1060        if (typeof then === 'function') {
1061          then.call(
1062            val,
1063            function(val) {
1064              res(i, val);
1065            },
1066            function(e) {
1067              args[i] = { status: 'rejected', reason: e };
1068              if (--remaining === 0) {
1069                resolve(args);
1070              }
1071            }
1072          );
1073          return;
1074        }
1075      }
1076      args[i] = { status: 'fulfilled', value: val };
1077      if (--remaining === 0) {
1078        resolve(args);
1079      }
1080    }
1081
1082    for (var i = 0; i < args.length; i++) {
1083      res(i, args[i]);
1084    }
1085  });
1086}
1087
1088/**
1089 * @constructor
1090 */
1091function AggregateError(errors, message) {
1092  this.name = 'AggregateError', this.errors = errors;
1093  this.message = message || '';
1094}
1095AggregateError.prototype = Error.prototype;
1096
1097function any(arr) {
1098  var P = this;
1099  return new P(function(resolve, reject) {
1100    if (!(arr && typeof arr.length !== 'undefined')) {
1101      return reject(new TypeError('Promise.any accepts an array'));
1102    }
1103
1104    var args = Array.prototype.slice.call(arr);
1105    if (args.length === 0) return reject();
1106
1107    var rejectionReasons = [];
1108    for (var i = 0; i < args.length; i++) {
1109      try {
1110        P.resolve(args[i])
1111          .then(resolve)
1112          .catch(function(error) {
1113            rejectionReasons.push(error);
1114            if (rejectionReasons.length === args.length) {
1115              reject(
1116                new AggregateError(
1117                  rejectionReasons,
1118                  'All promises were rejected'
1119                )
1120              );
1121            }
1122          });
1123      } catch (ex) {
1124        reject(ex);
1125      }
1126    }
1127  });
1128}
1129
1130// Store setTimeout reference so promise-polyfill will be unaffected by
1131// other code modifying setTimeout (like sinon.useFakeTimers())
1132var setTimeoutFunc = setTimeout;
1133
1134function isArray(x) {
1135  return Boolean(x && typeof x.length !== 'undefined');
1136}
1137
1138function noop() {}
1139
1140// Polyfill for Function.prototype.bind
1141function bind(fn, thisArg) {
1142  return function() {
1143    fn.apply(thisArg, arguments);
1144  };
1145}
1146
1147/**
1148 * @constructor
1149 * @param {Function} fn
1150 */
1151function Promise(fn) {
1152  if (!(this instanceof Promise))
1153    throw new TypeError('Promises must be constructed via new');
1154  if (typeof fn !== 'function') throw new TypeError('not a function');
vendor: 4,160 bytes, lines 1155-1334
1155  /** @type {!number} */
1156  this._state = 0;
1157  /** @type {!boolean} */
1158  this._handled = false;
1159  /** @type {Promise|undefined} */
1160  this._value = undefined;
1161  /** @type {!Array<!Function>} */
1162  this._deferreds = [];
1163
1164  doResolve(fn, this);
1165}
1166
1167function handle(self, deferred) {
1168  while (self._state === 3) {
1169    self = self._value;
1170  }
1171  if (self._state === 0) {
1172    self._deferreds.push(deferred);
1173    return;
1174  }
1175  self._handled = true;
1176  Promise._immediateFn(function() {
1177    var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
1178    if (cb === null) {
1179      (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
1180      return;
1181    }
1182    var ret;
1183    try {
1184      ret = cb(self._value);
1185    } catch (e) {
1186      reject(deferred.promise, e);
1187      return;
1188    }
1189    resolve(deferred.promise, ret);
1190  });
1191}
1192
1193function resolve(self, newValue) {
1194  try {
1195    // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
1196    if (newValue === self)
1197      throw new TypeError('A promise cannot be resolved with itself.');
1198    if (
1199      newValue &&
1200      (typeof newValue === 'object' || typeof newValue === 'function')
1201    ) {
1202      var then = newValue.then;
1203      if (newValue instanceof Promise) {
1204        self._state = 3;
1205        self._value = newValue;
1206        finale(self);
1207        return;
1208      } else if (typeof then === 'function') {
1209        doResolve(bind(then, newValue), self);
1210        return;
1211      }
1212    }
1213    self._state = 1;
1214    self._value = newValue;
1215    finale(self);
1216  } catch (e) {
1217    reject(self, e);
1218  }
1219}
1220
1221function reject(self, newValue) {
1222  self._state = 2;
1223  self._value = newValue;
1224  finale(self);
1225}
1226
1227function finale(self) {
1228  if (self._state === 2 && self._deferreds.length === 0) {
1229    Promise._immediateFn(function() {
1230      if (!self._handled) {
1231        Promise._unhandledRejectionFn(self._value);
1232      }
1233    });
1234  }
1235
1236  for (var i = 0, len = self._deferreds.length; i < len; i++) {
1237    handle(self, self._deferreds[i]);
1238  }
1239  self._deferreds = null;
1240}
1241
1242/**
1243 * @constructor
1244 */
1245function Handler(onFulfilled, onRejected, promise) {
1246  this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
1247  this.onRejected = typeof onRejected === 'function' ? onRejected : null;
1248  this.promise = promise;
1249}
1250
1251/**
1252 * Take a potentially misbehaving resolver function and make sure
1253 * onFulfilled and onRejected are only called once.
1254 *
1255 * Makes no guarantees about asynchrony.
1256 */
1257function doResolve(fn, self) {
1258  var done = false;
1259  try {
1260    fn(
1261      function(value) {
1262        if (done) return;
1263        done = true;
1264        resolve(self, value);
1265      },
1266      function(reason) {
1267        if (done) return;
1268        done = true;
1269        reject(self, reason);
1270      }
1271    );
1272  } catch (ex) {
1273    if (done) return;
1274    done = true;
1275    reject(self, ex);
1276  }
1277}
1278
1279Promise.prototype['catch'] = function(onRejected) {
1280  return this.then(null, onRejected);
1281};
1282
1283Promise.prototype.then = function(onFulfilled, onRejected) {
1284  // @ts-ignore
1285  var prom = new this.constructor(noop);
1286
1287  handle(this, new Handler(onFulfilled, onRejected, prom));
1288  return prom;
1289};
1290
1291Promise.prototype['finally'] = finallyConstructor;
1292
1293Promise.all = function(arr) {
1294  return new Promise(function(resolve, reject) {
1295    if (!isArray(arr)) {
1296      return reject(new TypeError('Promise.all accepts an array'));
1297    }
1298
1299    var args = Array.prototype.slice.call(arr);
1300    if (args.length === 0) return resolve([]);
1301    var remaining = args.length;
1302
1303    function res(i, val) {
1304      try {
1305        if (val && (typeof val === 'object' || typeof val === 'function')) {
1306          var then = val.then;
1307          if (typeof then === 'function') {
1308            then.call(
1309              val,
1310              function(val) {
1311                res(i, val);
1312              },
1313              reject
1314            );
1315            return;
1316          }
1317        }
1318        args[i] = val;
1319        if (--remaining === 0) {
1320          resolve(args);
1321        }
1322      } catch (ex) {
1323        reject(ex);
1324      }
1325    }
1326
1327    for (var i = 0; i < args.length; i++) {
1328      res(i, args[i]);
1329    }
1330  });
1331};
1332
1333Promise.any = any;
1334
1335Promise.allSettled = allSettled;
1336
1337Promise.resolve = function(value) {
1338  if (value && typeof value === 'object' && value.constructor === Promise) {
1339    return value;
1340  }
1341
1342  return new Promise(function(resolve) {
1343    resolve(value);
1344  });
1345};
1346
1347Promise.reject = function(value) {
1348  return new Promise(function(resolve, reject) {
1349    reject(value);
1350  });
1351};
1352
1353Promise.race = function(arr) {
1354  return new Promise(function(resolve, reject) {
1355    if (!isArray(arr)) {
1356      return reject(new TypeError('Promise.race accepts an array'));
1357    }
1358
1359    for (var i = 0, len = arr.length; i < len; i++) {
1360      Promise.resolve(arr[i]).then(resolve, reject);
1361    }
1362  });
1363};
1364
1365// Use polyfill for setImmediate for performance gains
1366Promise._immediateFn =
1367  // @ts-ignore
1368  (typeof setImmediate === 'function' &&
1369    function(fn) {
1370      // @ts-ignore
1371      setImmediate(fn);
1372    }) ||
1373  function(fn) {
1374    setTimeoutFunc(fn, 0);
1375  };
1376
1377Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
1378  if (typeof console !== 'undefined' && console) {
1379    console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
1380  }
1381};
1382
1383module.exports = Promise;
1384
1385}).call(this)}).call(this,require("timers").setImmediate)
1386},{"timers":13}],13:[function(require,module,exports){
1387(function (setImmediate,clearImmediate){(function (){
1388var nextTick = require('process/browser.js').nextTick;
1389var apply = Function.prototype.apply;
1390var slice = Array.prototype.slice;
1391var immediateIds = {};
1392var nextImmediateId = 0;
1393
1394// DOM APIs, for completeness
1395
1396exports.setTimeout = function() {
1397  return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
1398};
1399exports.setInterval = function() {
1400  return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
1401};
1402exports.clearTimeout =
1403exports.clearInterval = function(timeout) { timeout.close(); };
1404
1405function Timeout(id, clearFn) {
1406  this._id = id;
1407  this._clearFn = clearFn;
1408}
1409Timeout.prototype.unref = Timeout.prototype.ref = function() {};
1410Timeout.prototype.close = function() {
1411  this._clearFn.call(window, this._id);
1412};
1413
1414// Does not start the time, just sets up the members needed.
1415exports.enroll = function(item, msecs) {
1416  clearTimeout(item._idleTimeoutId);
1417  item._idleTimeout = msecs;
1418};
1419
1420exports.unenroll = function(item) {
1421  clearTimeout(item._idleTimeoutId);
1422  item._idleTimeout = -1;
1423};
1424
1425exports._unrefActive = exports.active = function(item) {
1426  clearTimeout(item._idleTimeoutId);
1427
1428  var msecs = item._idleTimeout;
1429  if (msecs >= 0) {
1430    item._idleTimeoutId = setTimeout(function onTimeout() {
1431      if (item._onTimeout)
1432        item._onTimeout();
1433    }, msecs);
1434  }
1435};
1436
1437// That's not how node.js implements it but the exposed api is the same.
1438exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) {
1439  var id = nextImmediateId++;
1440  var args = arguments.length < 2 ? false : slice.call(arguments, 1);
1441
1442  immediateIds[id] = true;
1443
1444  nextTick(function onNextTick() {
1445    if (immediateIds[id]) {
1446      // fn.call() is faster so we optimize for the common use-case
1447      // @see http://jsperf.com/call-apply-segu
1448      if (args) {
1449        fn.apply(null, args);
1450      } else {
1451        fn.call(null);
1452      }
1453      // Prevent ids from leaking
1454      exports.clearImmediate(id);
1455    }
1456  });
1457
1458  return id;
1459};
1460
1461exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) {
1462  delete immediateIds[id];
1463};
1464}).call(this)}).call(this,require("timers").setImmediate,require("timers").clearImmediate)
1465},{"process/browser.js":11,"timers":13}],"BaseController":[function(require,module,exports){
1466(function (global){(function (){
1467"use strict";
1468var mix = require('@icewarp/mix');
1469var extend = require('@icewarp/extend');
1470var Callback = require('@icewarp/callback');
1471var EventTarget = require('./EventTarget.js');
1472var Template = require('@icewarp/icebrace-runtime');
1473var logger = require('@icewarp/logger');
1474var escape_string = require('@icewarp/escape-string');
1475var function_name = require('@icewarp/function-name');
1476var Debugger = require('@icewarp/debugger');
1477var Breakpoint = require('./Breakpoint.js');
1478var Promise = window.Promise || (global || {}).Promise || require('promise-polyfill');
1479
1480/**
1481 * @typedef {Object} StoredModelListener
1482 * @description Stored object of listener to model event.
1483 * @property {BaseModel} target - Target model
1484 * @property {string} type - type of event (name of the event)
1485 * @property {function} func - handler function, this function will be executed with `this` of this controller.
1486 */
1487
1488/**
1489 * @typedef {Object} StoredGlobalListener
1490 * @description Stored object of listener to model event.
1491 * @property {BaseController} target - Target is always instance of controller which is adding this listener
1492 * @property {string} type - type of event (name of the event)
1493 * @property {function} func - handler function, this function will be executed with `this` of this controller.
1494 */
1495
1496/**
1497 * @typedef {Object} StoredDOMListener
1498 * @description Stored object of listener to DOM Element.
1499 * @property {HTMLElement} target - Target DOM Element
1500 * @property {string} type - type of event (name of the event)
1501 * @property {function} func - handler function, this function will be executed with `this` of this controller.
1502 */
1503
1504/*             Privates               */
1505
1506/**
1507 * @summary Model listeners storage
1508 * @description Storage for model listeners. Every time `addModelListener` is called `StoredModelListener` is stored here and if `removeListeners` is called with this storage, it's emptied. 
1509 * @type {Object}
1510 * @property {Object} [controller_name]
1511 * @property {StoredModelListener[]} [controller_name.listener_id]
1512 */
1513var modelListeners = {};
1514
1515/**
1516 * @summary global listeners storage
1517 * @description Storage for global listeners, every time `addGlobalListener` is called `StoredGlobalListener` is stored here  and if `removeListeners` is called with this storage, it's emptied. 
1518 * @type {Object}
1519 * @property {Object} [controller_name]
1520 * @property {StoredGlobalListener[]} [controller_name.listener_id]
1521 */
1522var globalListeners = {};
1523
1524/**
1525 * @summary DOM listeners storage
1526 * @description Storage for DOM listeners, every time `addDOMListener` or `addDelegatedDOMListener` is called `StoredGlobalListener` is stored here  and if `removeListeners` is called with this storage, it's emptied. 
1527 * @type {Object}
1528 * @property {Object} [controller_name]
1529 * @property {StoredDOMListener[]} [controller_name.listener_id]
1530 */
1531var DOMListeners = {};
1532
1533/**
1534 * @summary instances storage
1535 * @description Contains instances for all controllers stored by `class_name` and id. This is necessary to target existing instance by ID.
1536 * @type {Object}
1537 */
1538var instances = {};
1539
1540/**
1541 * @summary controllers storage
1542 * @description Storage for all controllers in application. Used as single entry point for creating and getting all controllers in application
1543 * @type {Object}
1544 */
1545var controllers = {};
1546
1547/**
1548 *  IDs storage
1549 */
1550var ids = {};
1551
1552/**
1553 * @summary destructors storage
1554 * @description Contains destructors for all controllers stored by `class_name` and id.
1555 * @type {Object}
1556 */
1557var destructors = {};
1558
1559Callback.addMiddleware(Callback.SUCCESS, function () {
1560	return false; //cancel propagation of callbacks for controllers without dom
1561}, function () {
1562	return this instanceof BaseController && !this.DOMElement && !this.DOMShadowElement;
1563});
1564
1565/**
1566 * Merge two objects
1567 * @param {object} target
1568 * @param {object} source
1569 * @returns {undefined}
1570 */
1571function mergeData(target, source) {
1572	Object.keys(source).forEach(function (key) {
1573		target[key] = source[key];
1574	});
1575}
1576
1577/**
1578 * @description Flats mixed sync and async data into flat promise
1579 * @param {*} data
1580 * @param {number} depth
1581 * @param {array} entities
1582 * @returns {Promise}
1583 */
1584function flatPromisedData(data, depth, entities) {
1585	depth = depth || 0;
1586	entities = entities || [];
1587	if (typeof data !== 'object' || data === null) {
1588		return data;
1589	}
1590	if (data instanceof Promise || (data && function_name(data.constructor) === 'Promise')) {
1591		return data.then(function (data) {
1592			return flatPromisedData(data, depth + 1, entities);
1593		});
1594	}
1595	if (~entities.indexOf(data)) {
1596		return false;
1597	}
1598	entities.push(data);
1599	if (data instanceof Array) {
1600		return Promise.all(data.map(function (data) {
1601			if (depth > 300) {
1602				return new Promise(function (resolve) {
1603					setTimeout(function () {
1604						resolve(flatPromisedData(data, 0, entities.slice(0)));
1605					});
1606				});
1607			}
1608			return flatPromisedData(data, depth + 1, entities.slice(0));
1609		}));
1610	}
1611	if (data instanceof BaseController) {
1612		return data.resolveHelper(depth + 1, entities);
1613	}
1614	return new Promise(function (resolve) {
1615		var resolved = {};
1616		var promises = [];
1617		Object.keys(data).forEach(function (key) {
1618			var value;
1619			if (depth > 300) {
1620				value = new Promise(function (resolve) {
1621					setTimeout(function () {
1622						resolve(flatPromisedData(data[key], 0, entities.slice(0)));
1623					});
1624				});
1625			} else {
1626				value = flatPromisedData(data[key], depth + 1, entities.slice(0));
1627			}
1628			if (value instanceof Promise || (value && function_name(value.constructor) === 'Promise')) {
1629				return promises.push(value.then(function (value) {
1630					resolved[key] = value;
1631				}));
1632			}
1633			resolved[key] = value;
1634		});
1635		resolve(Promise.all(promises).then(function () {
1636			return resolved;
1637		}));
1638	});
1639}
1640
1641/**
1642 * Convert camelcase to snake case
1643 * @param {string} camelcase 
1644 * @returns {string}
1645 */
1646function camelcaseToLowercaseWithDashes(camelcase) {
1647	return camelcase.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
1648}
1649
1650/**
1651 * Returns name of template used in Controller
1652 * @this {BaseController}
1653 * @returns {string}
1654 */
1655function getTemplateName() {
1656	return camelcaseToLowercaseWithDashes(this.getClassname()).match(/((?:[a-zA-Z-]|_{2})+)/g)[0];
1657}
1658/**
1659 * returns modifier string
1660 * @returns {string}
1661 */
1662function getTemplateModifier() {
1663	return camelcaseToLowercaseWithDashes(this.getClassname()).match(/((?:[a-zA-Z-]|_{2})+)/g)[1];
1664}
1665
1666/**
1667 * Remove bound listeners
1668 * @param {type} listeners
1669 * @returns {nm$_BaseController.prototype}
1670 */
1671function removeListeners(listeners) {
1672	var listener;
1673	if (!listeners) {
1674		throw new Error('listeners to remove not specified');
1675	}
1676	while (listeners[this._name] && listeners[this._name][this.id] && listeners[this._name][this.id].length) {
1677		listener = listeners[this._name][this.id].pop();
1678		listener.target.removeEventListener(listener.type, listener.func);
1679	}
1680	return this;
1681}
1682
1683/**
1684 * Removes breakpoint listeners attached to the controller
1685 * @returns {nm$_BaseController.prototype}
1686 */
1687function removeBreakpointListeners() {
1688	Breakpoint.removeListeners(this);
1689	return this;
1690}
1691
1692/** Push listener to listener storage
1693 *
1694 * @param {array} listeners listeners storage
1695 * @param {object} listener listener object {target,type,function}
1696 * @returns {BaseController.prototype}
1697 */
1698function pushListener(listeners, listener) {
1699	if (!listeners[this._name]) {
1700		listeners[this._name] = {};
1701	}
1702	if (!listeners[this._name][this.id]) {
1703		listeners[this._name][this.id] = [];
1704	}
1705	listeners[this._name][this.id].push(listener);
1706	return this;
1707}
1708
1709/**
1710 *
1711 * @param {function} fn
1712 * @param {object} data
1713 * @param {string} selector
1714 * @param {string} event_type
1715 * @param {boolean} once
1716 * @param {object} listeners
1717 * @param {Event} event
1718 * @returns {Array|undefined}
1719 */
1720function eventHandler(fn, data, selector, event_type, once, listeners, event) {
1721	var elements;
1722	Debugger.logEvent(fn, data, selector, event_type, event, this);
1723	if (!fn) {
1724		return logger.error(this._name, this.id, 'Missing callback function for ' + selector);
1725	}
1726	elements = selector ? (typeof selector === 'string' ? this.selectAll(selector) : [selector]) : [this.DOMElement || this.DOMShadowElement];
1727	if (!elements.length) {
1728		return logger.warning('No elements for selector "' + selector + '" found');
1729	}
1730	if (event_type === 'clickoutside') {
1731		return [].forEach.call(elements, function (element) {
1732			if (element !== event.target && !element.contains(event.target)) {
1733				logger.groupCollapsed(selector + ' ' + event_type);
1734				logger.info(event, element);
1735				logger.groupEnd();
1736				fn.call(this, event, data);
1737				if (once) {
1738					listeners[this._name][this.id] = listeners[this._name][this.id].filter(function (listener) {
1739						if (listener.fn === fn && listener.type === 'click') {
1740							listener.target.removeEventListener(listener.type, listener.func);
1741						} else {
1742							return true;
1743						}
1744					});
1745				}
1746			}
1747		}, this);
1748	}
1749	[].forEach.call(elements, function (element) {
1750		if (element === event.target || element === window || element.contains(event.target)) {
1751			event.element = element;
1752			logger.groupCollapsed(selector + ' ' + event_type);
1753			logger.info(event, element);
1754			logger.groupEnd();
1755			fn.call(this, event, data);
1756			if (once) {
1757				listeners[this._name][this.id] = listeners[this._name][this.id].filter(function (listener) {
1758					if (listener.fn === fn && listener.type === event_type) {
1759						listener.target.removeEventListener(listener.type, listener.func);
1760					} else {
1761						return true;
1762					}
1763				});
1764			}
1765		}
1766	}, this);
1767}
1768
1769/**
1770 *
1771 * @param {Node} parent_element
1772 * @param {function} controller_callback
1773 * @returns {undefined}
1774 */
1775function subcontrollersCallback(parent_element, controller_callback) {
1776	[].forEach.call(parent_element.querySelectorAll('[data-component]'), function (element) {
1777		controller_callback(this.getInstanceByElement(element), element);
1778	}, this);
1779}
1780
1781/**
1782 * Remove listeners, call beforeDestroy, unbind DOMElements if soft === false, call all destructors and call afterDestroy
1783 * @param {type} soft unbind DOMElements if soft === false
1784 * @returns {nm$_BaseController.prototype}
1785 */
1786function destroy(soft) {
1787	if (!instances[this._name][this.id]) {
1788		return this;
1789	}
1790
1791	removeListeners.call(this, DOMListeners);
1792	removeListeners.call(this, globalListeners);
1793	removeListeners.call(this, modelListeners);
1794	removeBreakpointListeners.call(this);
1795
1796	this.beforeDestroy && this.beforeDestroy(soft);
1797
1798	destructors[this._name][this.id] = destructors[this._name][this.id].filter(function (destructor) {
1799		destructor.call(this);
1800		return false;
1801	}, this);
1802
1803	if (!soft) {
1804		this.DOMElement = null;
1805		this.DOMShadowElement = null;
1806		setTimeout(function () {
1807			if (!this.DOMElement) {
1808				delete instances[this._name][this.id];
1809			}
1810		}.bind(this), 5);
1811	}
1812
1813	this.afterDestroy && this.afterDestroy(soft);
1814
1815	return this;
1816}
1817
1818/** Check if storage for class is already initialized
1819 *
1820 * @param {string} class_name
1821 * @returns {undefined}
1822 */
1823function checkInstance(class_name) {
1824	if (!instances[class_name]) {
1825		instances[class_name] = {};
1826		ids[class_name] = 0;
1827	}
1828}
1829
1830/**
1831 *
1832 * @param {Object} instance
1833 * @returns {undefined}
1834 */
1835function set(instance) {
1836	var id;
1837	checkInstance(instance._name);
1838	id = ++ids[instance._name];
1839	instances[instance._name][id] = instance;
1840	instance.setId(id);
1841}
1842
1843/*            /Privates               */
1844
1845/** Control for view module
1846 * @class
1847 *
1848 * @param {object} context data to render module with
1849 * @returns {BaseController}
1850 */
1851function BaseController(context) {
1852	this.data = context || this.data || {};
1853	this._name = getTemplateName.call(this);
1854	this._mod = getTemplateModifier.call(this);
1855	this._resolved_helper = {};
1856
1857	set(this);
1858
1859	destructors[this._name] = destructors[this._name] || {};
1860	destructors[this._name][this.id] = destructors[this._name][this.id] || [];
1861
1862	EventTarget.call(this, true);
1863}
1864extend(EventTarget, BaseController);
1865
1866/**
1867 * Add BaseController instance to instances storage
1868 * @param {BaseController} instance
1869 * @returns {BaseController}
1870 */
1871BaseController.reinstance = function (instance) {
1872	instances[instance._name][instance.id] = instance;
1873	return instance;
1874};
1875
1876/**
1877 * @description Persistent data to be cloned on every rerender.
1878 * @type String[]
1879 */
1880BaseController.PERSISTENT_DATA_KEYS = ['styleModifier'];
1881
1882/** Default function for adding listeners, this is called on every execute
1883 *  To be overridden by child
1884 *
1885 * @returns {undefined}
1886 */
1887BaseController.prototype.addListeners = function () {};
1888
1889/** Function called before render, To be overridden by child
1890 *
1891 * @returns {undefined}
1892 */
1893BaseController.prototype.beforeRender = function () {};
1894
1895/** Function called befor destroy, To be overridden by child
1896 *
1897 * @returns {undefined}
1898 */
1899BaseController.prototype.beforeDestroy = function () {};
1900
1901/** function called after render, To be overridden by child
1902 *
1903 * @returns {undefined}
1904 */
1905BaseController.prototype.afterRender = function () {};
1906
1907/** Function called after destroy. To be overridden by child
1908 *
1909 * @returns {undefined}
1910 */
1911BaseController.prototype.afterDestroy = function () {};
1912
1913/**
1914 *
1915 * @param {number|string} id
1916 * @returns {BaseController.prototype}
1917 */
1918BaseController.prototype.setId = function (id) {
1919	this.id = id;
1920	return this;
1921};
1922
1923/**
1924 *
1925 * @param {DOMElement|string} element - element or selector
1926 * @returns {BaseController}
1927 */
1928BaseController.prototype.getInstanceByElement = function (element) {
1929	var parts, id;
1930	if (!element) {
1931		return null;
1932	}
1933	parts = (typeof element === 'string' ? this.select(element) : element).getAttribute('data-component');
1934	if (!parts) {
1935		return null;
1936	}
1937	parts = parts.split('-');
1938	id = parts.pop();
1939	return instances[parts.join('-').split('~')[0]][id];
1940};
1941
1942/**
1943 * Return parent controller
1944 * @param {string} name - controller name
1945 * @param {function} [callback]
1946 * @returns {BaseController|null} parent controller or null in case no parent matched
1947 */
1948BaseController.prototype.getParent = function (name, callback) {
1949	var result;
1950	var parent = this.DOMElement || this.DOMShadowElement;
1951	parent && (parent = parent.parentNode);
1952	while (
1953		parent !== null && !(
1954			parent.hasAttribute('data-component') &&
1955			(!name || parent.getAttribute('data-component').match(new RegExp(name + '\\b')))
1956		)
1957	) {
1958		parent = parent.parentNode;
1959		if (parent.classList === void 0) {
1960			return null;
1961		}
1962	}
1963	result = this.getInstanceByElement(parent);
1964	callback && result && callback(result);
1965	return result;
1966};
1967
1968/**
1969 *
1970 * @param {string} name - controller name
1971 * @param {function} [callback]
1972 * @returns {array} array of child controllers
1973 */
1974BaseController.prototype.getChildren = function (name, callback) {
1975	var selector;
1976	name && !Array.isArray(name) && (name = [name]);
1977	selector = name ? name.map(function (name) {
1978		return '[data-component^="' + name + '-"], [data-component^="' + name + '~"]';
1979	}).join(',') : '[data-component]';
1980	if (callback) {
1981		return this.selectAll(selector, function (children) {
1982			callback(children.map(this.getInstanceByElement).filter(Boolean));
1983		}.bind(this));
1984	}
1985	return this.selectAll(selector).map(this.getInstanceByElement).filter(Boolean);
1986};
1987/**
1988 *
1989 * @param {Function|String} constructor
1990 * @param {function} [callback]
1991 * @returns {BaseController[]}
1992 */
1993BaseController.prototype.getChildrenByClass = function (constructor, callback) {
1994	if (callback) {
1995		return this.getChildren(false, function (children) {
1996			callback(children.filter(function (instance) {
1997				return instance instanceof constructor || (instance.mixes && !!~instance.mixes.indexOf(function_name(constructor)));
1998			}));
1999		});
2000	}
2001	return this.getChildren().filter(function (instance) {
2002		return instance instanceof constructor || (instance.mixes && !!~instance.mixes.indexOf(function_name(constructor)));
2003	});
2004};
2005
2006/**
2007 *
2008 * @returns {String}
2009 */
2010BaseController.prototype.getClassname = function () {
2011	return function_name(this.constructor);
2012};
2013
2014/**
2015 * Extract persistent data from this.data property
2016 * @returns {undefined}
2017 */
2018BaseController.prototype.getPersistentData = function () {
2019	var persistent = {};
2020	if (this.data && typeof this.data === 'object') {
2021		BaseController.PERSISTENT_DATA_KEYS.forEach(function (KEY) {
2022			if (this.data[KEY] === void 0) {
2023				return;
2024			}
2025			persistent[KEY] = this.data[KEY];
2026		}, this);
2027	}
2028	return persistent;
2029};
2030
2031/**
2032 * Returns proper parent element tag name (eg. table for tr, tr for td, div otherwise)
2033 * @param {String} tag_name tag name
2034 * @returns {String} parent tag name
2035 */
2036function chooseParentElementTagName(tag_name) {
2037	return {
2038		thead: 'table',
2039		tbody: 'table',
2040		tr: 'tbody',
2041		td: 'tr'
2042	} [tag_name] || 'div';
2043}
2044
2045/**
2046 * Execute template function, parse HTML to DOM and setup listeners
2047 * @param {Object} data
2048 * @returns {Promise}
2049 */
2050BaseController.prototype.execute = function (data) {
2051	var template = getTemplateName.call(this);
2052	var template_data, html, first_tag;
2053	var persistent_data = this.getPersistentData();
2054	if (!Template.t(template)) {
2055		throw new Error(template, 'template not set');
2056	}
2057	this.data = data || this.data || {};
2058	return this.resolveHelper().then(function () {
2059		template_data = this.getView();
2060		mergeData(this.data, persistent_data);
2061		mergeData(template_data, persistent_data);
2062		html = Template.t(template)()(template_data);
2063		first_tag = (html.match(/<([\w-]+)/) || [])[1];
2064		this.DOMShadowElement = document.createElement(chooseParentElementTagName(first_tag));
2065		this.DOMShadowElement.insertAdjacentHTML('afterbegin', html);
2066		this.DOMShadowElement.normalize();
2067		if (this.DOMShadowElement.firstElementChild) {
2068			this.DOMShadowElement = this.DOMShadowElement.firstElementChild;
2069		}
2070		this.DOMShadowElement.setAttribute('data-component', this._name + '-' + this.id);
2071		this.DOMShadowElement.classList.add(this._name);
2072		template !== this._name && this.DOMShadowElement.classList.add(template);
2073		this.addListeners && this.addListeners();
2074		subcontrollersCallback.call(this, this.DOMShadowElement, function (controller, element) {
2075			controller.DOMShadowElement = element;
2076			controller.addListeners && controller.addListeners();
2077		});
2078		return this;
2079	}.bind(this));
2080
2081};
2082
2083/**
2084 * 
2085 * @description Add listener to BaseController global context. Listening to all event across all BaseController instances.
2086 * @param {string} event_type - type of event to listen to
2087 * @param {function} fn  - event handler
2088 * @param {boolean} once - remove after first trigger
2089 * @returns {BaseController}
2090 */
2091BaseController.prototype.addGlobalListener = function (event_type, fn, once) {
2092	var func = fn.bind(this);
2093	this.on(event_type, func, this, false, once);
2094	return pushListener.call(this, globalListeners, {
2095		target: this,
2096		type: event_type,
2097		func: func
2098	});
2099};
2100
2101/**
2102 * @description Add destructor function to controller if not already added to be called on destroy.
2103 * @param {function} fn - destructor function
2104 * @returns {BaseController}
2105 */
2106BaseController.prototype.addDestructor = function (fn) {
2107	!~destructors[this._name][this.id].indexOf(fn) && destructors[this._name][this.id].push(fn);
2108	return this;
2109};
2110
2111/** 
2112 * @description Add a delegated listener on elements specified by selector, Listener is attached to controller root element and triggered if selector is matched in bubbling phase. This can be used for triggering actions from dynamically changed parts of component.
2113 *
2114 * @param {string|DOMElement} selector
2115 * @param {string|string[]} event_type - type of event to listen to; multiple event types as array or space delimited string
2116 * @param {function} fn function to be executed on event
2117 * @param {object} [data] optional data for event callback
2118 * @returns {BaseController}
2119 */
2120BaseController.prototype.addDelegatedDOMListener = function (selector, event_type, fn, data) {
2121	var eventFn;
2122	if (Array.isArray(event_type) || (event_type.split(' ').length > 1 && (event_type = event_type.split(' ')))) {
2123		return event_type.forEach(function (event_type) {
2124			this.addDelegatedDOMListener(selector, event_type, fn, data);
2125		}, this);
2126	}
2127
2128	eventFn = eventHandler.bind(this, fn, data, selector, event_type, false, void 0);
2129	this.DOMShadowElement.addEventListener(event_type, eventFn);
2130	return pushListener.call(this, DOMListeners, {
2131		target: this.DOMShadowElement,
2132		type: event_type,
2133		func: eventFn
2134	});
2135};
2136/** 
2137 * @description Shortcut for adding delegated listener on data-hook, same as delegatedDOMListener, but selector is created dynamically using hook. Hook selector is matched in bubbling phase. This can be used for triggering actions from dynamically changed parts of component.
2138 *
2139 * @param {string} hook - name of the hook
2140 * @param {string} event_type
2141 * @param {function} fn function to be executed on event
2142 * @param {object} [data] optional data for event callback
2143 * @returns {BaseController.prototype}
2144 */
2145BaseController.prototype.addDelegatedHookListener = function (hook, event_type, fn, data) {
2146	return this.addDelegatedDOMListener('[data-hook="' + hook + '"]', event_type, fn, data);
2147};
2148/**
2149 * @description Adding delegated listener on namespaced hook. More on listening on delegated events on addDelegatedHookListener. Namespaced hook is hook created by createNSHook() function, it's hook prefixed by name of the controller.
2150 * @param {string} hook - hook name
2151 * @param {string} event_type - type of event
2152 * @param {function} fn - function to be executed on event trigger
2153 * @param {object} [data] - optional data to be passed to event handler
2154 * @returns {BaseController} 
2155 */
2156BaseController.prototype.addDelegatedNSHookListener = function (hook, event_type, fn, data) {
2157	return this.addDelegatedDOMListener('[data-hook="' + function_name(this.constructor) + '-' + hook + '"]', event_type, fn, data);
2158};
2159
2160BaseController.prototype.addDelegatedPartialListener = function (name, event_type, fn, data) {
2161	return this.addDelegatedDOMListener('[data-component^="' + name + '-"], [data-component^="' + name + '~"]', event_type, fn, data);
2162};
2163
2164/** 
2165 * 
2166 * @description Shortcut for adding listener on data-hook, selector is constructed automatically from hook name, Hook is data attribute create by createHook() function. This data attribute is used for marking some parts of component as controllable. 
2167 *
2168 * @param {string} hook - name of the hook
2169 * @param {string} event_type
2170 * @param {function} fn function to be executed on event
2171 * @param {object} [data] optional data for event callback
2172 * @param {boolean} once fire listener only once
2173 * @returns {BaseController.prototype}
2174 */
2175BaseController.prototype.addHookListener = function (hook, event_type, fn, data, once) {
2176	return this.addDOMListener('[data-hook="' + hook + '"]', event_type, fn, data, once);
2177};
2178
2179/**
2180 * @description Shortcut for adding listener on namespaced data-hook, selector is constructed automatically from hook name and controller name, Namespaced Hook is data attribute create by createNSHook() function.
2181 * @param {string} hook 
2182 * @param {string} event_type 
2183 * @param {function} fn 
2184 * @param {object} [data] 
2185 * @param {boolean} [once] 
2186 * @returns {BaseController}
2187 */
2188BaseController.prototype.addNSHookListener = function (hook, event_type, fn, data, once) {
2189	return this.addDOMListener('[data-hook="' + function_name(this.constructor) + '-' + hook + '"]', event_type, fn, data, once);
2190};
2191
2192BaseController.prototype.addPartialListener = function (name, event_type, fn, data, once) {
2193	return this.addDOMListener('[data-component^="' + name + '-"], [data-component^="' + name + '~"]', event_type, fn, data, once);
2194};
2195
2196/** 
2197 * 
2198 * @description Add a listener on elements specified by css selector. 
2199 *
2200 * @param {string|DOMElement} selector
2201 * @param {string|string[]} event_type Event type, array of event types or space separated event types
2202 * @param {function} fn function to be executed on event
2203 * @param {object} [data] optional data for event callback
2204 * @param {boolean} once fire listener only once
2205 * @returns {BaseController.prototype}
2206 */
2207BaseController.prototype.addDOMListener = function (selector, event_type, fn, data, once) {
2208	var eventFn, elements, i;
2209	if (Array.isArray(event_type) || (event_type.split(' ').length > 1 && (event_type = event_type.split(' ')))) {
2210		return event_type.forEach(function (event_type) {
2211			this.addDOMListener(selector, event_type, fn, data, once);
2212		}, this);
2213	}
2214	eventFn = eventHandler.bind(this, fn, data, selector, event_type, once, DOMListeners);
2215	elements = selector ? (typeof selector === 'string' ? this.selectAll(selector) : [selector]) : [this.DOMShadowElement];
2216	if (!elements.length) {
2217		logger.groupCollapsed('Cannot bind listener to non-existing elements');
2218		logger.error(selector, this);
2219		logger.groupEnd();
2220		return this;
2221	}
2222	for (i in elements) {
2223		elements[i].addEventListener(event_type, eventFn);
2224		pushListener.call(this, DOMListeners, {
2225			target: elements[i],
2226			type: event_type,
2227			func: eventFn,
2228			fn: fn
2229		});
2230	}
2231	return this;
2232};
2233
2234/** Add click-outside listener on elements specified by selector
2235 *
2236 * @param {string|DOMElement} selector
2237 * @param {function} fn function to be executed on event
2238 * @param {object} [data] optional data for event callback
2239 * @param {boolean} once fire listener only once
2240 * @returns {BaseController.prototype}
2241 */
2242BaseController.prototype.addClickOutsideListener = function (selector, fn, data, once) {
2243	var eventFn = eventHandler.bind(this, fn, data, selector, 'clickoutside', once, DOMListeners);
2244	document.body.addEventListener('click', eventFn);
2245	return pushListener.call(this, DOMListeners, {
2246		target: document.body,
2247		type: 'click',
2248		func: eventFn,
2249		fn: fn
2250	});
2251};
2252
2253/** Add listener to given model
2254 *
2255 * @param {BaseModel} model
2256 * @param {string} event_type
2257 * @param {function} fn
2258 * @param {boolean} once listen only once and delete listener
2259 * @returns {BaseController.prototype}
2260 */
2261BaseController.prototype.addModelListener = function (model, event_type, fn, once) {
2262	if (Array.isArray(event_type) || (event_type.split(' ').length > 1 && (event_type = event_type.split(' ')))) {
2263		return event_type.forEach(function (event_type) {
2264			this.addModelListener(model, event_type, fn, once);
2265		}, this);
2266	}
2267	model.on(event_type, fn, this, false, once);
2268	return pushListener.call(this, modelListeners, {
2269		target: model,
2270		type: event_type,
2271		func: fn
2272	});
2273};
2274
2275/**
2276 * Add breakpoint listener
2277 *
2278 * @param {array} breakpoints
2279 * @param {function} fn
2280 * @returns {BaseController.prototype}
2281 */
2282BaseController.prototype.addBreakpointListener = function (breakpoints, fn) {
2283	(Array.isArray(breakpoints) ? breakpoints : [breakpoints]).forEach(function (breakpoint) {
2284		Breakpoint.addListener(this, breakpoint, fn);
2285	}, this);
2286	return this;
2287};
2288
2289/** Rerender this module if already rendered
2290 *
2291 * @param {object} [data] - New data that will replace current controller this.data
2292 * @returns {Promise}
2293 */
2294BaseController.prototype.rerender = function (data) {
2295	if (!this.DOMElement && !this.DOMShadowElement) {
2296		return Promise.resolve(this);
2297	}
2298	this.remove(true);
2299	return this.execute(data).then(function (control) {
2300		control.render(control.DOMElement);
2301		return control;
2302	});
2303};
2304
2305/**
2306 * Renders executed controller to the page
2307 * @param {DOMElement} element
2308 * @param {string} render_type - [beforebegin | afterbegin | beforeend | afterend | replaceWith (default)]
2309 * @returns {BaseController.prototype}
2310 */
2311BaseController.prototype.render = function (element, render_type) {
2312	var replaced_controller = null;
2313	var children = this.getChildren();
2314
2315	this.beforeRender && this.beforeRender();
2316	subcontrollersCallback.call(this, this.DOMShadowElement, function (controller) {
2317		controller.beforeRender && controller.beforeRender();
2318	});
2319	switch (render_type) {
2320		case 'beforebegin':
2321		case 'afterbegin':
2322		case 'beforeend':
2323		case 'afterend':
2324			element.insertAdjacentElement(render_type, this.DOMShadowElement);
2325			break;
2326		default:
2327			subcontrollersCallback.call(this, element || this.DOMElement, function (controller) {
2328				if (!~children.indexOf(controller)) {
2329					destroy.call(controller);
2330				}
2331			});
2332			(element || this.DOMElement).parentNode.replaceChild(this.DOMShadowElement, (element || this.DOMElement));
2333			replaced_controller = this.getInstanceByElement(element);
2334			if (replaced_controller && replaced_controller !== this) {
2335				destroy.call(replaced_controller);
2336			}
2337	}
2338	this.DOMElement = this.DOMShadowElement;
2339	this.DOMShadowElement = null;
2340	subcontrollersCallback.call(this, this.DOMElement, function (controller) {
2341		controller.DOMElement = controller.DOMShadowElement;
2342		controller.DOMShadowElement = null;
2343	});
2344	this.afterRender && this.afterRender();
2345	subcontrollersCallback.call(this, this.DOMElement, function (controller) {
2346		controller.afterRender && controller.afterRender();
2347	});
2348	return this;
2349};
2350
2351/** 
2352 * 
2353 * @description Select node inside this component by given  css selector, Cannot be used for selecting component itself.
2354 *
2355 * @param {string} selector
2356 * @param {function} [callback]
2357 * @returns {Element}
2358 */
2359BaseController.prototype.select = function (selector, callback) {
2360	var result = null;
2361	var element = this.DOMShadowElement || this.DOMElement;
2362	if (!element) {
2363		return result;
2364	}
2365
2366	result = selector ? element.querySelector(selector) : element;
2367	callback && result && callback(result);
2368	return result;
2369};
2370
2371/** 
2372 * @description Select nodes inside this component by given  css selector.
2373 *
2374 * @param {string} selector
2375 * @param {function} [callback]
2376 * @returns {Array}
2377 */
2378BaseController.prototype.selectAll = function (selector, callback) {
2379	var result = [];
2380	var element = this.DOMShadowElement || this.DOMElement;
2381	if (!element) {
2382		return result;
2383	}
2384
2385	result = [].slice.call(element.querySelectorAll(selector));
2386	callback && result && callback(result);
2387	return result;
2388};
2389
2390/**
2391 * Select data-hook="selector"
2392 * @param {String} selector
2393 * @param {function} [callback]
2394 * @returns {Element}
2395 */
2396BaseController.prototype.hook = function (selector, callback) {
2397	return this.select('[data-hook="' + selector + '"]', callback);
2398};
2399/**
2400 * Select data-hook="ns-selector"
2401 * @param {String} selector
2402 * @param {function} [callback]
2403 * @returns {Element}
2404 */
2405BaseController.prototype.nsHook = function (selector, callback) {
2406	return this.select('[data-hook="' + escape_string(this.getClassname() + '-' + selector) + '"]', callback);
2407};
2408
2409/**
2410 * Select all data-hook="selector"
2411 * @param {string} selector
2412 * @param {function} [callback]
2413 * @returns {Element[]}
2414 */
2415BaseController.prototype.hooks = function (selector, callback) {
2416	return this.selectAll('[data-hook="' + selector + '"]', callback);
2417};
2418
2419/**
2420 * Returns closest data-hook="selector"
2421 * @param {string} selector
2422 * @param {Element} element
2423 * @param {function} [callback]
2424 * @returns {Element}
2425 */
2426BaseController.prototype.closestHook = function (selector, element, callback) {
2427	var result = null;
2428	element = element || this.DOMShadowElement || this.DOMElement;
2429	if (!element) {
2430		return result;
2431	}
2432
2433	result = element.closest('[data-hook="' + selector + '"]');
2434	callback && result && callback(result);
2435	return result;
2436};
2437
2438/**
2439 * Creates data-hook attribute
2440 * @param {String} hook
2441 * @returns {String}
2442 */
2443BaseController.prototype.createHook = function (hook) {
2444	return ' data-hook="' + escape_string(hook) + '" ';
2445};
2446
2447/**
2448 * Creates data-hook attribute in module namespace
2449 * @param {String} hook
2450 * @returns {String}
2451 */
2452BaseController.prototype.createNSHook = function (hook) {
2453	return ' data-hook="' + escape_string(function_name(this.constructor) + '-' + hook) + '" ';
2454};
2455
2456/** Default helper for all controllers, to be overridden in children
2457 *
2458 * @returns {object}
2459 */
2460BaseController.prototype.helper = function () {
2461	return this.data;
2462};
2463
2464/**
2465 * Provides custom modifications and adding mod flags for module data
2466 * @returns {object}
2467 */
2468BaseController.prototype.getView = function () {
2469	var _data = this._resolved_helper;
2470	var parts = function_name(this.constructor).match(/((?:[a-zA-Z-]|_{2})+)/g);
2471	if (_data) {
2472		_data._mod = camelcaseToLowercaseWithDashes(parts[1] || '');
2473		_data._name = camelcaseToLowercaseWithDashes(parts[0]);
2474	}
2475	this.view_data = _data;
2476	return _data;
2477};
2478
2479/**
2480 * @description Resolves async data in helper
2481 * @param {number} [depth]
2482 * @param {array} [entities]
2483 * @returns {Promise}
2484 */
2485BaseController.prototype.resolveHelper = function (depth, entities) {
2486	return flatPromisedData(this.helper(), depth, entities).then(function (data) {
2487		this._resolved_helper = data;
2488		return this;
2489	}.bind(this), function (error) {
2490		logger.error(error);
2491		this._resolved_helper = {};
2492		return this;
2493	}.bind(this));
2494};
2495
2496/**
2497 * 
2498 * @param {Object} data 
2499 * @returns {BaseController}
2500 */
2501BaseController.prototype.setViewData = function (data) {
2502	this.view_data = data;
2503	return this;
2504};
2505
2506/**
2507 * Set controllers to work with
2508 * @param {Object} controllersToSet object with controllers {controller_name: controller return function}
2509 * @returns {undefined}
2510 */
2511BaseController.setControllers = function (controllersToSet) {
2512	controllers = controllersToSet;
2513};
2514
2515/**
2516 * Get controller from static_controllers
2517 * @param {String} class_name
2518 * @returns {BaseController}
2519 */
2520BaseController.static = function (class_name) {
2521	class_name = camelcaseToLowercaseWithDashes(class_name);
2522	if (!controllers[class_name]) {
2523		logger.info('Creating non-existing controller ' + class_name);
2524		controllers[class_name] = function () {
2525			return BaseController.create(class_name.replace('~', '_').replace(/(?:^|-|\b)(\w)/g, function (match, $1) {
2526				return $1.toUpperCase();
2527			}));
2528		};
2529	}
2530	return controllers[class_name]();
2531};
2532
2533/**
2534 * Create new instance of BaseController
2535 * @param {string} class_name - name of controller class
2536 * @param {Object} context - data context for inner usage
2537 * @returns {BaseController}
2538 */
2539BaseController.new = function (class_name, context) {
2540	return new(this.static(class_name))(context);
2541};
2542
2543/**
2544 * Creates a controller
2545 * @param {String} controller_name
2546 * @param {Object} extend_controller controller to inherit from
2547 * @param {Object} mixins controller or array of controllers to mix with the new controller
2548 * @returns {BaseController} a class with className as its name
2549 */
2550 BaseController.create = function (controller_name, extend_controller, mixins) {
2551	var controller = new Function('BaseController', 'function ' + controller_name + '(){BaseController.apply(this,arguments);this.onCreate&&this.onCreate()}return ' + controller_name)(BaseController);
2552	extend(extend_controller || BaseController, controller);
2553	mixins && (Array.isArray(mixins) ? mixins : [mixins]).forEach(function (mixin) {
2554		controller.mixes = controller.mixes || [];
2555		controller.mixes.push(function_name(mixin));
2556		mix(mixin, controller);
2557	});
2558	return controller;
2559};
2560
2561/** Remove element from
2562 *
2563 * @param {Boolean} soft Do not remove DOMElement
2564 * @returns {undefined}
2565 */
2566BaseController.prototype.remove = function (soft) {
2567	this.DOMElement && subcontrollersCallback.call(this, this.DOMElement, function (controller) {
2568		destroy.call(controller, soft);
2569	});
2570	!soft && (this.DOMElement || {}).parentNode && this.DOMElement.parentNode.removeChild(this.DOMElement);
2571	destroy.call(this, soft);
2572};
2573
2574module.exports = BaseController;
2575
2576}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
2577},{"./Breakpoint.js":"Breakpoint","./EventTarget.js":3,"@icewarp/callback":"Callback","@icewarp/debugger":"debugger","@icewarp/escape-string":2,"@icewarp/extend":"extend","@icewarp/function-name":"function-name","@icewarp/icebrace-runtime":"icebrace-runtime","@icewarp/logger":"logger","@icewarp/mix":"mix","promise-polyfill":12}],"BaseEvent":[function(require,module,exports){
2578"use strict";
2579/** Parent of all event models
2580 * @class
2581 * 
2582 * @param {object} data data to store inside event
2583 * @returns {BaseEvent}
2584 */
2585function BaseEvent(data) {
2586	this.data = data;
2587	this.immediatePropagationStopped = false;
2588}
2589/** Stop propagation 
2590 * 
2591 * @returns {undefined}
2592 */
2593BaseEvent.prototype.stopImmediatePropagation = function () {
2594	this.immediatePropagationStopped = true;
2595};
2596module.exports =  BaseEvent;
2597
2598},{}],"BaseModel":[function(require,module,exports){
2599"use strict";
2600var extend = require('@icewarp/extend');
2601var delayed = require('@icewarp/delayed');
2602var mix = require('@icewarp/mix');
2603var EventTarget = require('./EventTarget.js');
2604var ModelData = require('./ModelData.js');
2605var BaseEvent = require('./BaseEvent.js');
2606var overtype = require('@icewarp/overtype');
2607
2608var tmp_id = 0;
2609
2610
2611/*             Privates               */
2612
2613
2614/** Instances Storage
2615 *
2616 */
2617var instances = {};
2618
2619/** Models storage, To be filled up in app
2620 *
2621 */
2622var models = {};
2623
2624/**
2625 * Storage for class_name route rules
2626 * @type Object
2627 */
2628var name_route_rule = {};
2629
2630/**
2631 * Storage for class_name routes
2632 * @type Object
2633 */
2634var name_route = {};
2635
2636
2637/**
2638 *
2639 * @param {object} instance
2640 * @returns {undefined}
2641 */
2642var set = function (instance) {
2643	var class_name = instance.getClassname();
2644	checkInstance(class_name);
2645	instances[class_name][instance.getId()] = instance;
2646};
2647var checkInstance = function (class_name) {
2648	if (!instances[class_name]) {
2649		instances[class_name] = {};
2650	}
2651};
2652
2653/**
2654 * Generates auto incremental id for temporary models
2655 * @returns {string}
2656 */
2657function getTmpID() {
2658	return '_tmp_' + ++tmp_id;
2659}
2660
2661/**
2662 * Set itself to working data in all references
2663 * @this BaseModel
2664 * @argument {boolean} [recursive] - propagate recursively in entire reference chain
2665 * @argument {BaseModel[]} [instances] - Array of instances that was already processed
2666 * @returns {undefined}
2667 */
2668function propagateChange(recursive, instances) {
2669	var class_name, id, key;
2670	instances = instances || [];
2671	if (~instances.indexOf(this)) {
2672		return;
2673	}
2674	instances.push(this);
2675	for (class_name in this.references) {
2676		for (id in this.references[class_name]) {
2677			for (key in this.references[class_name][id]) {
2678				BaseModel.instance(class_name, id)[(this.references[class_name][id][key] & BaseModel.REFERENCE_MASK.IS_ARRAY) ? 'pushData' : 'setData'](key, this);
2679				if (recursive) {
2680					propagateChange.call(BaseModel.instance(class_name, id), recursive, instances);
2681				}
2682			}
2683		}
2684	}
2685}
2686
2687/**
2688 * Propagate changes in defined upstream path
2689 * @param {string[]} path - Array of class names defining upstream path
2690 * @returns {undefined}
2691 */
2692function propagateChangeUpstreamPath(path) {
2693	var next_stop, id, key;
2694	if (!path.length) {
2695		return;
2696	}
2697	next_stop = path.shift();
2698	if (!this.references[next_stop]) {
2699		return;
2700	}
2701	for (id in this.references[next_stop]) {
2702		for (key in this.references[next_stop][id]) {
2703			BaseModel.instance(next_stop, id)[(this.references[next_stop][id][key] & BaseModel.REFERENCE_MASK.IS_ARRAY) ? 'pushData' : 'setData'](key, this);
2704			propagateChangeUpstreamPath.call(BaseModel.instance(next_stop, id), path);
2705		}
2706	}
2707
2708}
2709
2710/*             /Privates              */
2711
2712/** Parent of all models
2713 * @class
2714 *
2715 * @requires extend
2716 *
2717 * @param {number|string} id
2718 * @returns {BaseModel}
2719 */
2720function BaseModel(id) {
2721	var data;
2722	EventTarget.call(this);
2723	data = new ModelData();
2724	this.getId = function () {
2725		return id;
2726	};
2727	this.setId = function (new_id) {
2728		if (new_id === this.getId()) {
2729			return;
2730		}
2731		if (instances[this.getClassname()][new_id]) {
2732			throw new Error('Model ' + this.getClassname() + ' with id ' + new_id + ' already exists');
2733		}
2734		this.tmp = (typeof new_id === 'string' && !!~new_id.indexOf('_tmp_'));
2735		delete instances[this.getClassname()][id];
2736		id = new_id;
2737		set.call(BaseModel, this);
2738	};
2739	this.caller = data.caller.bind(data);
2740	this.tmp = (typeof id === 'string' && !!~id.indexOf('_tmp_'));
2741	this.references = {};
2742	set.call(BaseModel, this);
2743}
2744extend(EventTarget, BaseModel);
2745BaseModel.prototype.callback = require('@icewarp/callback');
2746
2747/**
2748 * @type Object
2749 * @property {number} IN_ARRAY - if property is array property
2750 * @property {number} IS_IN_SERVER_DATA - if property is in server data
2751 */
2752BaseModel.REFERENCE_MASK = {
2753	IS_ARRAY: 1,
2754	IS_IN_SERVER_DATA: 2
2755};
2756
2757
2758/**
2759 * Destructor
2760 * @description Clears references in models with references to this instance.
2761 * Removes instance from Instances Storage.
2762 * 
2763 * @returns {undefined}
2764 */
2765BaseModel.prototype.destroy = function () {
2766	this.caller('destroy');
2767	this.clearReferences();
2768	delete instances[this.getClassname()][this.getId()];
2769};
2770/**
2771 * Clear references to this object from other BaseModel object
2772 * @param {BaseModel} [reference] reference to clear 
2773 * @param {String} [modeldata_key] key to clear from
2774 * @returns {BaseModel.prototype}
2775 */
2776BaseModel.prototype.clearReferences = function (reference, modeldata_key) {
2777	var i, model, j, key, instance, tmp_instance;
2778	for (i in this.references) {
2779		model = this.references[i];
2780		for (j in model) {
2781			instance = model[j];
2782			for (key in instance) {
2783				if(modeldata_key && modeldata_key !== key) {
2784					continue;
2785				}
2786				if(reference && reference !== BaseModel.instance(i, j)) {
2787					continue;
2788				}
2789				tmp_instance = instance[key];
2790				delete instance[key];
2791				if (tmp_instance & BaseModel.REFERENCE_MASK.IS_ARRAY) {
2792					BaseModel.instance(i, j).spliceData(key, this, {
2793						server_data: tmp_instance & BaseModel.REFERENCE_MASK.IS_IN_SERVER_DATA
2794					});
2795				} else {
2796					BaseModel.instance(i, j).unsetData(key, {
2797						server_data: tmp_instance & BaseModel.REFERENCE_MASK.IS_IN_SERVER_DATA
2798					});
2799				}
2800			}
2801			if(!Object.keys(instance).length) {
2802				delete model[j];
2803			}
2804		}
2805		if(!Object.keys(model).length) {
2806			delete this.references[i];
2807		}
2808	}
2809
2810	return this;
2811};
2812/**
2813 * @param {boolean} real - Return real class name, not overridden
2814 * @returns {String}
2815 */
2816BaseModel.prototype.getClassname = function (real) {
2817	return this.constructor.getClassname(real);
2818};
2819
2820BaseModel.getClassname = function (real) {
2821	if (!real && this.classNameOverride) {
2822		return this.classNameOverride;
2823	}
2824	return this['name'] || (/function (.*?)\(/.exec((this).toString())[1] || '').trim();
2825};
2826
2827/**
2828 * @type {string}
2829 * @description Can override actual class name of model, This is used when you need several models to share same ID namespace, for example Model A has two children Model B and Model C. But A, B and C has same ID line and you want to prevent duplications so you set classNameOverride for B and C to A.
2830 */
2831BaseModel.classNameOverride = '';
2832
2833/**
2834 * @type {array}
2835 * @description Array of class names which classes can this model overtype to self.
2836 */
2837BaseModel.canOvertype = [];
2838
2839/** Getter for data, if exist working data of given key then it's value is returned otherwise server data of given key is returned
2840 *
2841 * @description gets value from model data by given key.
2842 * @param {string} key
2843 * @param {object} [options]
2844 * @param {boolean} [options.server_data] - return server data directly
2845 * @returns {*} - If no key is provided returned value will be false, If key is provided but there is undefined value in working_data value from server_data is returned, If there is undefined value in both server and working data, undefined is returned.
2846 */
2847BaseModel.prototype.getData = function (key, options) {
2848	return this.caller('getData', key, options && options.server_data);
2849};
2850
2851/** Getter for data array, if exist working data of given key then it's value is returned otherwise server data of given key is returned
2852 *
2853 * @param {string} key
2854 * @param {object} [options]
2855 * @param {boolean} [options.server_data]
2856 * @returns {*}
2857 */
2858BaseModel.prototype.getArray = function (key, options) {
2859	return this.caller('getArray', key, options && options.server_data);
2860};
2861
2862/** Inits an array if undefined
2863 *
2864 * @param {string} key
2865 * @param {object} [options]
2866 * @param {boolean} [options.server_data] (default value: true)
2867 * @returns {*}
2868 */
2869BaseModel.prototype.initArray = function (key, options) {
2870	this.caller('initArray', key, (!options || options.server_data === undefined) ? true : options.server_data);
2871	return this;
2872};
2873
2874/** Setter for all data
2875 *
2876 * @param {string} key
2877 * @param {*} value
2878 * @param {object} [options]
2879 * @param {string} [options.type]
2880 * @param {boolean} [options.server_data] true if you want to set server data. Like to save response from server
2881 * @param {boolean} [options.propagate_change] - propagate change to the upper model
2882 * @param {boolean} [options.propagate_recursive] - propagate change all the way up
2883 * @param {boolean} [options.upstream_path] - propagate change by the specified upstream path
2884 * @returns {BaseModel}
2885 */
2886BaseModel.prototype.setData = function (key, value, options) {
2887	var old_value;
2888	if (!key) {
2889		throw 'Undefined key for setData ' + this.getClassname();
2890	}
2891	old_value = this.getData(key, options);
2892	if(old_value instanceof BaseModel && old_value !== value) {
2893		old_value.clearReferences(this, key);
2894	}
2895	if (options && options.type) {
2896		value = overtype(options.type, value);
2897	}
2898	if (value === undefined) {
2899		return this;
2900	}
2901	if (value instanceof BaseModel) {
2902		value.addReference(this, key);
2903	}
2904	if (options && options.propagate_change) {
2905		propagateChange.call(this, options && options.propagate_recursive);
2906	}
2907	if (options && options.upstream_path) {
2908		propagateChangeUpstreamPath.call(this, options && options.upstream_path);
2909	}
2910	this.caller('setData', key, value, options && options.server_data) && (old_value !== value) && this.trigger(key + '_set', new BaseEvent({
2911		model: this,
2912		old_value: old_value,
2913		new_value: value
2914	})) && update.call(this, key);
2915	return this;
2916};
2917/** Push new value to data array
2918 *
2919 * @param {string} key
2920 * @param {*} value
2921 * @param {object} [options]
2922 * @param {boolean} [options.unshift]
2923 * @param {boolean} [options.server_data] true if you want to set server data. Like to save response from server
2924 * @param {boolean} [options.propagate_change] - propagate change to the upper model
2925 * @param {boolean} [options.propagate_recursive] - propagate change all the way up
2926 * @param {boolean} [options.upstream_path] - propagate change by the specified upstream path
2927 * @returns {BaseModel}
2928 */
2929BaseModel.prototype.pushData = function (key, value, options) {
2930	if (value instanceof BaseModel) {
2931		value.addReference(this, key, true);
2932	}
2933	if (options && options.propagate_change) {
2934		propagateChange.call(this, options && options.propagate_recursive);
2935	}
2936	if (options && options.upstream_path) {
2937		propagateChangeUpstreamPath.call(this, options.upstream_path);
2938	}
2939	this.caller('pushData', key, value, options && options.unshift, options && options.server_data) && this.trigger(key + '_pushed', new BaseEvent({
2940		model: this,
2941		new_value: value
2942	})) && update.call(this, key);
2943	return this;
2944};
2945/** remove value from array data
2946 *
2947 * @param {string} key
2948 * @param {*} value
2949 * @param {options} [options]
2950 * @param {boolean} [options.server_data]
2951 * @param {boolean} [options.propagate_change] - propagate change to the upper model
2952 * @param {boolean} [options.propagate_recursive] - propagate change all the way up
2953 * @param {boolean} [options.upstream_path] - propagate change by the specified upstream path
2954 * @returns {BaseModel}
2955 */
2956BaseModel.prototype.spliceData = function (key, value, options) {
2957	if (options && options.propagate_change) {
2958		propagateChange.call(this, options && options.propagate_recursive);
2959	}
2960	if (options && options.upstream_path) {
2961		propagateChangeUpstreamPath.call(this, options && options.upstream_path);
2962	}
2963	this.caller('spliceData', key, value, options && options.server_data) && this.trigger(key + '_spliced', new BaseEvent({
2964		model: this,
2965		old_value: value
2966	})) && update.call(this, key);
2967	if(value instanceof BaseModel) {
2968		value.clearReferences(this, key);
2969	}
2970	return this;
2971};
2972
2973/**
2974 * Get difference object between server_data array and working_data array
2975 * @param {string} key - key which array to compare
2976 * @returns {Object} - returns object with added property containing items newly added to array and removed property with items removed from array
2977 */
2978BaseModel.prototype.getDataDiff = function (key) {
2979	var i;
2980	var working = this.getArray(key);
2981	var server = this.getArray(key, {
2982		server_data: true
2983	});
2984	var removed = [];
2985	var added = [];
2986	var length = (working.length > server.length ? working.length : server.length);
2987	for (i = 0; i < length; i++) {
2988		working[i] && !~server.indexOf(working[i]) && added.push(working[i]);
2989		server[i] && !~working.indexOf(server[i]) && removed.push(server[i]);
2990	}
2991	return {
2992		added: added,
2993		removed: removed
2994	};
2995};
2996
2997/**
2998 * remove model property
2999 * @param {string} key
3000 * @param {object} [options]
3001 * @param {boolean} [options.server_data]
3002 * @param {boolean} [options.propagate_change] - propagate change to the upper model
3003 * @param {boolean} [options.propagate_recursive] - propagate change all the way up
3004 * @param {boolean} [options.upstream_path] - propagate change by the specified upstream path
3005 * @returns {BaseModel}
3006 */
3007BaseModel.prototype.unsetData = function (key, options) {
3008	if (options && options.propagate_change) {
3009		propagateChange.call(this, options && options.propagate_recursive);
3010	}
3011	if (options && options.upstream_path) {
3012		propagateChangeUpstreamPath.call(this, options && options.upstream_path);
3013	}
3014	this.getArray(key, options).forEach(function(value) {
3015		if(value instanceof BaseModel) {
3016			value.clearReferences(this, key);
3017		}
3018	}, this);
3019	this.caller('unsetData', key, options && options.server_data) && this.trigger(key + '_unset', new BaseEvent({
3020		model: this
3021	})) && update.call(this, key);
3022	return this;
3023};
3024
3025/**
3026 * Filter function to remove duplicity
3027 * @param {*} value 
3028 * @param {number} index 
3029 * @param {Array} self 
3030 * @returns {Boolean}
3031 */
3032function onlyUnique(value, index, self) {
3033	return self.indexOf(value) === index;
3034}
3035
3036/**
3037 * 
3038 * Trigger update event on data change
3039 * @this {BaseModel}
3040 * @param {string} key 
3041 * @returns {undefined}
3042 */
3043function update(key) {
3044	this.keys = this.keys || [];
3045	this.keys.push(key);
3046	delayed(function () {
3047		this.trigger('update', new BaseEvent({
3048			model: this,
3049			keys: this.keys.filter(onlyUnique)
3050		}));
3051		this.keys = [];
3052	}, this, 5, this.getClassname() + '_' + this.getId() + '_update');
3053}
3054
3055/**
3056 * Add model to referential table
3057 * @param {BaseModel} reference_model
3058 * @param {string} key
3059 * @param {boolean} in_array
3060 * @param {boolean} server_data
3061 * @returns {BaseModel}
3062 */
3063BaseModel.prototype.addReference = function (reference_model, key, in_array, server_data) {
3064	this.references = this.references || {};
3065	this.references[reference_model.getClassname()] = this.references[reference_model.getClassname()] || {};
3066	this.references[reference_model.getClassname()][reference_model.getId()] = this.references[reference_model.getClassname()][reference_model.getId()] || {};
3067	this.references[reference_model.getClassname()][reference_model.getId()][key] = 0 + (in_array ? BaseModel.REFERENCE_MASK.IS_ARRAY : 0) + (server_data ? BaseModel.REFERENCE_MASK.IS_IN_SERVER_DATA : 0);
3068	return this;
3069};
3070/** Propagate working data to server data
3071 * @param {object} [options]
3072 * @param {boolean} [options.recursive] - save recursively 
3073 * @returns {BaseModel}
3074 */
3075BaseModel.prototype.saveWorkingData = function (options) {
3076	var working_data, key;
3077	if (options && options.recursive) {
3078		options.saved = options.saved || [];
3079		if (~options.saved.indexOf(this)) {
3080			return this;
3081		}
3082		options.saved.push(this);
3083		working_data = this.getWorkingData();
3084		for (key in working_data) {
3085			if (working_data[key] instanceof BaseModel) {
3086				working_data[key].saveWorkingData(options);
3087			}
3088		}
3089	}
3090	this.caller('saveWorkingData');
3091	return this;
3092};
3093/** Returns all working data
3094 *
3095 * @returns {object}
3096 */
3097BaseModel.prototype.getWorkingData = function () {
3098	return this.caller('getWorkingData');
3099};
3100/** get keys of all working data
3101 *
3102 * @returns {array}
3103 */
3104BaseModel.prototype.getWorkingDataKeys = function () {
3105	return this.caller('getWorkingDataKeys');
3106};
3107/** Flush all working data
3108 * @param {object} [options]
3109 * @param {boolean} [options.recursive] - save recursively 
3110 * @returns {BaseModel}
3111 */
3112BaseModel.prototype.flushWorkingData = function (options) {
3113	var key;
3114	var working_data = this.getWorkingData();
3115	if (options && options.recursive) {
3116		options.flushed = options.flushed || [];
3117		if (~options.flushed.indexOf(this)) {
3118			return this;
3119		}
3120		options.flushed.push(this);
3121		for (key in working_data) {
3122			if (working_data[key] instanceof BaseModel) {
3123				working_data[key].flushWorkingData(options);
3124			}
3125		}
3126	}
3127
3128	this.caller('flushWorkingData');
3129
3130	for (key in working_data) {
3131		this.trigger(key + '_set', new BaseEvent({
3132			model: this,
3133			old_value: working_data[key],
3134			new_value: this.getData(key)
3135		}));
3136	}
3137
3138	return this;
3139};
3140
3141/**
3142 * @description Overtype this to arg model, this function will go thur all references and adds new instance to all references. Calling destroy on old instance will remove model from all references in the end.
3143 * @param {BaseModel} model - static class of overtype target
3144 * @param {array} args - arguments for constructor
3145 * @returns {BaseModel} - returns overtype instance
3146 */
3147BaseModel.prototype.overtypeTo = function (model, args) {
3148	var key, reference_classname, reference_id, new_instance, rm, rmi;
3149	var server_data = this.caller('getServerData');
3150	var working_data = this.getWorkingData();
3151	var references = JSON.parse(JSON.stringify(this.references));
3152	this.destroy();
3153	new_instance = new(model.bind.apply(model, args));
3154	for (reference_classname in references) {
3155		rm = references[reference_classname];
3156		for (reference_id in rm) {
3157			rmi = rm[reference_id];
3158			for (key in rmi) {
3159				BaseModel.instance(reference_classname, reference_id)[rmi[key] & BaseModel.REFERENCE_MASK.IS_ARRAY ? 'pushData' : 'setData'](key, new_instance, {
3160					server_data: rmi[key] & BaseModel.REFERENCE_MASK.IS_IN_SERVER_DATA
3161				});
3162			}
3163		}
3164	}
3165	for (key in server_data) {
3166		new_instance.setData(key, server_data[key], {
3167			server_data: true
3168		});
3169	}
3170	for (key in working_data) {
3171		new_instance.setData(key, working_data[key]);
3172	}
3173	references = null;
3174	return new_instance;
3175};
3176
3177/** Factory for Model instances
3178 *
3179 * @param {string} class_name name of the class you want to create
3180 * @param {string|number} [id] if there is no id given system generates tmp id based on timestamp, models like this are used for temporary data storage before saving on server.
3181 * @param {*} args any arguments will be passed to the constructor and to the onCreate function
3182 * @returns {BaseModel}
3183 */
3184BaseModel.instance = function (class_name, id, args) {
3185	var model = this.static(class_name);
3186	var argumenty = [].slice.call(arguments);
3187	class_name = model.getClassname();
3188	argumenty[1] = id = id !== void 0 ? id : model.singleton ? 0 : (getTmpID());
3189	checkInstance(class_name);
3190	if (instances[class_name][id]) {
3191		if (model.getClassname(true) !== instances[class_name][id].getClassname(true) && ~model.canOvertype.indexOf(class_name)) {
3192			return instances[class_name][id].overtypeTo(model, argumenty);
3193		}
3194		return instances[class_name][id];
3195	}
3196	return new(model.bind.apply(model, argumenty));
3197};
3198
3199BaseModel.instanceExists = function (class_name, id) {
3200	return !!(instances[class_name] && instances[class_name][id]);
3201};
3202
3203/**
3204 * Returns whether passed instance is an instance of class_name
3205 * @param {object} instance
3206 * @param {String} class_name instance class_name to compare with
3207 * @returns {Boolean}
3208 */
3209BaseModel.instanceof = function (instance, class_name) {
3210	return instance instanceof BaseModel && instance.instanceof(class_name);
3211};
3212
3213/**
3214 * Returns whether model is instance of class_name
3215 * @param {String} class_name instance class_name to compare with
3216 * @returns {Boolean}
3217 */
3218BaseModel.prototype.instanceof = function (class_name) {
3219	return this instanceof BaseModel.static(class_name);
3220};
3221
3222BaseModel.modelExists = function (class_name) {
3223	return !!models[this.checkNameRoute(class_name)];
3224};
3225/**
3226 * Sets models to central storage
3227 * @param {object} modelsToSet
3228 * @returns {undefined}
3229 */
3230BaseModel.setModels = function (modelsToSet) {
3231	if (Object.keys(models).length) {
3232		return Object.keys(modelsToSet).forEach(function (key) {
3233			models[key] = modelsToSet[key];
3234		});
3235	}
3236	models = modelsToSet;
3237};
3238/**
3239 * Sets single model to global storage
3240 * @param {BaseModel} model
3241 * @returns {undefined}
3242 */
3243BaseModel.setModel = function (model) {
3244	models[model.getClassname()] = function () {
3245		return model;
3246	};
3247};
3248
3249/**
3250 * @summary Check name_route for remapping to real class name
3251 * @description Check name_route storage for route to real class_name for this link, if there is no route, go thru all rules and test ling againts them. If there is match cache found link to name_route storage.
3252 * @param {String} link
3253 * @returns {unresolved}
3254 */
3255BaseModel.checkNameRoute = function (link) {
3256	var result, match, source;
3257	if (name_route[link]) {
3258		return name_route[link];
3259	}
3260	for (source in name_route_rule) {
3261		if ((result = link.match(name_route_rule[source]))) {
3262			match = source; //partial match
3263			if (result[0] === result.input) {
3264				return name_route[link] = source; //fullmatch
3265			}
3266		}
3267	}
3268	return match ? (name_route[link] = match) : link;
3269};
3270/**
3271 * @summary Register classname routing
3272 * @description Register class_name link to ream class_name, if you register string you are creating direct link from one string to another. You can also register regular expression. Be carful with regular expression, because it will be evaluated against every class_name in eventy BaseModel static call, that may cause performance issues with many registered rules, or with badly written regexp.
3273 * @param {string|RegExp} link
3274 * @param {string} source
3275 * @returns {nm$_BaseModel.BaseModel}
3276 */
3277BaseModel.registerNameRoute = function (link, source) {
3278	if (link instanceof RegExp) {
3279		name_route_rule[source] = link;
3280		return this;
3281	}
3282	name_route[link] = source;
3283	return this;
3284};
3285
3286/**
3287 * Returns static object of class_name
3288 * @param {string} class_name
3289 * @returns {BaseModel}
3290 */
3291BaseModel.static = function (class_name) {
3292	class_name = this.checkNameRoute(class_name);
3293	if (!this.modelExists(class_name)) {
3294		throw class_name + ' model doesn\'t exist';
3295	}
3296	return models[class_name]();
3297};
3298
3299/**
3300 * Creates a model
3301 * @param {type} modelName
3302 * @param {Object} mixins model or array of models to mix with the new model
3303 * @returns {BaseModel}
3304 */
3305BaseModel.create = function (modelName, mixins) {
3306	var model = new Function('BaseModel', 'function ' + modelName + '(){BaseModel.apply(this,arguments);this.onCreate&&this.onCreate.apply(this, arguments)}return ' + modelName)(BaseModel);
3307	extend(this, model);
3308	mixins && (Array.isArray(mixins) ? mixins : [mixins]).forEach(function (mixin) {
3309		mix(mixin, model);
3310	});
3311	return model;
3312};
3313
3314/**
3315 * Get temporary instances by class_name
3316 * @param {string} class_name
3317 * @returns {BaseModel[]}
3318 */
3319BaseModel.getTmpInstances = function (class_name) {
3320	return Object.keys((instances[class_name] || {})).map(function (id) {
3321		return BaseModel.instance(class_name, id);
3322	}).filter(function (instance) {
3323		return instance.tmp;
3324	});
3325};
3326
3327module.exports = BaseModel;
3328
3329},{"./BaseEvent.js":"BaseEvent","./EventTarget.js":3,"./ModelData.js":4,"@icewarp/callback":"Callback","@icewarp/delayed":"delayed","@icewarp/extend":"extend","@icewarp/mix":"mix","@icewarp/overtype":8}],"Breakpoint":[function(require,module,exports){
3330"use strict";
3331var functionName = require('@icewarp/function-name');
3332var delayed = require('@icewarp/delayed');
3333
3334var Breakpoint = {
3335	all: []
3336};
3337
3338var breakpoint_listeners = {};
3339
3340// lower boundries
3341var breakpoints = {
3342	xs: [0, 543],
3343	sm: [544, 767],
3344	md: [768, 991],
3345	lg: [992, 1199],
3346	xl: [1200, 99999]
3347};
3348
3349var i, listeners;
3350
3351for (i in breakpoints) {
3352	Breakpoint['all'].push(i);
3353	Breakpoint[i] = i;
3354	breakpoint_listeners[i] = [];
3355	'matchMedia' in window && matchMedia('(min-width: ' + breakpoints[i][0] + 'px) and (max-width: ' + breakpoints[i][1] + 'px)').addListener(function (breakpoint, event) {
3356		if (!event.matches) {
3357			return;
3358		}
3359		listeners = breakpoint_listeners[breakpoint].slice();
3360		listeners.forEach(function (listener) {
3361			delayed(function () {
3362				if (~breakpoint_listeners[breakpoint].indexOf(listener)) {
3363					listener.fn ? listener.fn.call(listener.context, breakpoint, breakpoints[breakpoint]) : listener.context.rerender();
3364				}
3365			}, this, 50, functionName(listener.context) + listener.context.id);
3366		});
3367	}.bind(null, i));
3368}
3369
3370Breakpoint.getCurrent = function () {
3371	var client_width = document.body.clientWidth;
3372	var i;
3373	for (i in breakpoints) {
3374		if (client_width >= breakpoints[i][0] && client_width <= breakpoints[i][1]) {
3375			return i;
3376		}
3377	}
3378	return i;
3379};
3380
3381Breakpoint.addListener = function (context, breakpoint, fn) {
3382	breakpoint_listeners[breakpoint].push({
3383		context: context,
3384		fn: fn
3385	});
3386};
3387
3388Breakpoint.removeListeners = function (self) {
3389	var breakpoint;
3390	for (breakpoint in breakpoint_listeners) {
3391		breakpoint_listeners[breakpoint] = breakpoint_listeners[breakpoint].filter(function (listener) {
3392			return listener.context !== self;
3393		});
3394	}
3395};
3396
3397module.exports = Breakpoint;
3398
3399},{"@icewarp/delayed":"delayed","@icewarp/function-name":"function-name"}],"Callback":[function(require,module,exports){
3400"use strict";
3401var Logger = require('@icewarp/logger');
3402var defaults = {
3403	error: Logger.error
3404};
3405/**
3406 * @type {Object}
3407 * @description Defined middlewares by type
3408 */
3409var middlewares = {
3410
3411};
3412
3413/**
3414 * @description Applying all middlewares in series
3415 * @param {function} cb  - callback handler for given type
3416 * @param {string} type - type of callback
3417 * @param {Object} ctx - context of callback handler
3418 * @param {array} args  - array of arguments
3419 * @returns {boolean} - true if is should stop propagation and false for continue
3420 */
3421function applyMiddlewares(cb, type, ctx, args) {
3422	var mid_obj;
3423	if (!middlewares[type] || !middlewares[type].length) {
3424		return true;
3425	}
3426	for (var i = 0; i < middlewares[type].length; i++) {
3427		mid_obj = middlewares[type][i];
3428		if (!mid_obj.condition || mid_obj.condition.apply(ctx, args)) {
3429			if (mid_obj.middleware.apply(ctx, args) === false) {
3430				return false;
3431			}
3432		}
3433	}
3434	return true;
3435}
3436/**
3437 * Function to call function by type if exists
3438 * @module Callback
3439 * @param {string} type
3440 * @param {function} callback_object
3441 * @param {*} [args]
3442 * @returns {undefined}
3443 */
3444function Callback(type, callback_object) {
3445	var cb, ctx = null;
3446	var args = [].slice.call(arguments).splice(2);
3447	if (callback_object && typeof callback_object[type] === 'function') {
3448		cb = callback_object[type];
3449		ctx = callback_object.context || null;
3450		if (!applyMiddlewares(cb, type, ctx, args)) {
3451			return;
3452		}
3453	} else if (typeof defaults[type] === 'function') {
3454		cb = defaults[type];
3455	}
3456	cb && cb.apply(ctx, args);
3457}
3458Callback.SUCCESS = 'success';
3459Callback.ERROR = 'error';
3460Callback.DONE = 'done';
3461
3462/**
3463 * Set default Callback[type] function
3464 * @param {String} type
3465 * @param {Function} fn
3466 * @return {Callback}
3467 */
3468Callback.setDefault = function (type, fn) {
3469	defaults[type] = fn;
3470	return this;
3471};
3472
3473/**
3474 * @description Add middleware function before async action and callback execution. Middleware function will be executed with callback function context and can be controller via condition function. Condition function ex executed with context and arguments of callback function
3475 * @param {string} type - type of callback (success, error, done, etc...)
3476 * @param {function} middleware - middleware function to run before
3477 * @param {function} condition - function that returns boolean if middleware should be applied before callback
3478 * @return {Callback}
3479 */
3480Callback.addMiddleware = function (type, middleware, condition) {
3481	middlewares[type] = middlewares[type] || [];
3482	middlewares[type].push({
3483		condition: condition,
3484		middleware: middleware
3485	});
3486	return this;
3487};
3488
3489/**
3490 * @description Remove middleware by middleware function and condition function
3491 * @param {string} type - type of callback (success, error, done, etc...)
3492 * @param {function} middleware - middleware function to run before
3493 * @param {function} condition - function that returns boolean if middleware should be applied before callback
3494 * @return {Callback}
3495 */
3496Callback.removeMiddleware = function (type, middleware, condition) {
3497	var index;
3498	if (!middlewares[type] || !middlewares[type].length) {
3499		return this;
3500	}
3501	middlewares[type].some(function (mid_obj, i) {
3502		if (mid_obj.middleware === middleware && (!mid_obj.condition || mid_obj.condition === condition)) {
3503			index = i;
3504			return true;
3505		}
3506		return false;
3507	});
3508	middlewares[type].splice(index, 1);
3509	return this;
3510};
3511
3512module.exports = Callback;
3513
3514},{"@icewarp/logger":"logger"}],"Library":[function(require,module,exports){
3515"use strict";
3516var Request = require('@icewarp/request');
3517var Callback = require('@icewarp/callback');
3518var Library = {};
3519
3520var storage = {};
3521var path = './libs/';
3522
3523/**
3524 * Set new library path
3525 * @param {string} new_path
3526 * @returns {undefined}
3527 */
3528Library.setPath = function (new_path) {
3529	path = new_path;
3530};
3531
3532/**
3533 * Get library
3534 * @param {string} name
3535 * @param {@icewarp/callback} callback
3536 * @param {string} [custom_path] custom path only for this request
3537 * @param {object} lib_storage custom storage for required lib
3538 * @returns {unresolved}
3539 */
3540Library.get = function (name, callback, custom_path, lib_storage) {
3541	var _storage = lib_storage || storage;
3542	var request;
3543	if (_storage[name]) {
3544		return Callback('success', callback, _storage[name]);
3545	}
3546	request = new Request({
3547		url: (custom_path || path) + name + '.js',
3548		method: 'GET'
3549	});
3550	request.on('load', function (event, response) {
3551		if (response.status === 200) {
3552			new Function('window', response.response)(_storage);
3553			return Callback('success', callback, _storage[name]);
3554		}
3555		Callback('error', callback, response);
3556	});
3557
3558	request.on('error', function () {
3559		Callback('error', callback);
3560	});
3561	request.on('abort', function () {
3562		Callback('error', callback);
3563	});
3564	request.send();
3565};
3566
3567/**
3568 * Clean lib storage
3569 * @param {string} [name]
3570 * @returns {undefined}
3571 */
3572Library.clean = function (name) {
3573	if (name) {
3574		delete storage[name];
3575	} else {
3576		storage = {};
3577	}
3578};
3579
3580module.exports = Library;
3581
3582},{"@icewarp/callback":"Callback","@icewarp/request":"request"}],"debugger":[function(require,module,exports){
3583"use strict";
3584/**
3585 * Log storage
3586 * @type Array
3587 */
3588var log = [];
3589/**
3590 * Actual log level
3591 * @type Number
3592 */
3593var log_level = 0;
3594var MouseTracking = require('./MouseTracking');
3595/**
3596 * Power of last level
3597 * @type Number
3598 */
3599var power = 0;
3600/**
3601 * Dynamic Entry Classes Storage
3602 */
3603var entries = {};
3604
3605/**
3606 * 
3607 * @param {string} name
3608 * @param {number} level
3609 * @returns {debug}
3610 */
3611function entryFactory(name, level) {
3612	name = name.toLowerCase().split('_').map(function (part) {
3613		return part[0].toUpperCase() + part.slice(1);
3614	}).join('');
3615	entries[level] = new Function("return function " + name + "Entry(data){this.data = data;this.data.stamp = Date.now();}")();
3616	return this;
3617}
3618
3619function transform(element, x, y, unit) {
3620	unit = unit || 'px';
3621	['-webkit-', '-ms-', ''].forEach(function (prefix) {
3622		element.style[prefix + "transform"] = "translate(" + x + unit + ", " + y + unit + ")";
3623	});
3624}
3625
3626function rulerEventHandler(event) {
3627	transform(document.getElementById('ruler'), event.clientX, event.clientY);
3628	document.getElementById('rulerCoordinates').textContent = "X: " + event.clientX + " Y: " + event.clientY;
3629}
3630
3631/**
3632 * @class Debugger
3633 * class for logging errors and actions thru App for easier debugging
3634 */
3635var Debugger = {
3636	logEvent: function (fn, data, selector, event_type, event, module) {
3637		this.logAction({module: module.getClassname()/*, fn: fn.toString()*/, data: data, selector: selector.toString(), event_type: event_type/*, event: event*/}, this.levels.EVENT);
3638	},
3639	/**
3640	 * Log action
3641	 * @param {object} data
3642	 * @param {number} type
3643	 * @returns {Debugger}
3644	 */
3645	logAction: function (data, type) {
3646		if (log_level & type) {
3647			log.push(new entries[type](data));
3648			if (log.length > this.log_length) {
3649				if (this.dump && this.dump.fn) {
3650					this.dump.fn.call(this.dump.context || this, 'mouse', JSON.stringify(log));
3651					log = [];
3652				} else {
3653					log.shift();
3654				}
3655			}
3656		}
3657		return this;
3658	},
3659	/**
3660	 * Disable js error handeling
3661	 * @type boolean
3662	 */
3663	swallow: false,
3664	/** length of stored log
3665	 * @type number
3666	 */
3667	log_length: 500,
3668	/**
3669	 * @type object|boolean
3670	 */
3671	error_handler: false,
3672	/**
3673	 * Set external error handler
3674	 * @param {function} fn
3675	 * @param {object} context
3676	 * @returns {undefined}
3677	 */
3678	setErrorHandler: function (fn, context) {
3679		this.error_handler = {fn: fn, context: context};
3680		return this;
3681	},
3682	/**
3683	 * Init Debugger
3684	 * @param {object} options
3685	 * @returns {Debugger}
3686	 */
3687	init: function (options) {
3688		log_level = options.level;
3689		this.swallow = options.swallow || false;
3690		this.log_length = options.log_length || 500;
3691		this.dump = options.dump || false;
3692		options.error_handler && this.setErrorHandler(options.error_handler, options.error_handler_context);
3693		(log_level & this.levels.MOUSE_TRACKING) && MouseTracking.initTracking(options.mouse_log_length, this.dump);
3694		return this;
3695	},
3696	/**
3697	 * Show Logs
3698	 * @returns {undefined}
3699	 */
3700	show: function () {
3701		var data = {};
3702		log.forEach(function (entry, i) {
3703			data[entry.data.stamp + "." + i] = entry;
3704		});
3705		console.log(data);
3706		console.log(MouseTracking.getData());
3707	},
3708	/**
3709	 * Play mouse movements
3710	 * @returns {undefined}
3711	 */
3712	mousePlay: function () {
3713		MouseTracking.mousePlay();
3714	},
3715	/**
3716	 * Dynamic levels storage
3717	 */
3718	levels: {},
3719	/**
3720	 * Add new log level to Debugger, This action will also creates new log entry class
3721	 * @param {string} key
3722	 * @returns {Debugger}
3723	 */
3724	addLogLevel: function (key) {
3725		if (this.levels[key]) {
3726			throw Error('Level ' + key + ' already exists');
3727		}
3728		this.levels[key] = Math.pow(2, power++);
3729		return entryFactory.call(this, key, this.levels[key]);
3730	},
3731	/**
3732	 * enables ruller
3733	 * @returns {Debugger}
3734	 */
3735	enableRuler: function () {
3736		if (document.getElementById('ruler')) {
3737			return;
3738		}
3739
3740		var ruler = document.createElement('i');
3741		ruler.setAttribute('id', 'ruler');
3742		var style = document.createElement('style');
3743		style.textContent = "\
3744			#ruler {\
3745				position: absolute;\
3746				top: 0;\
3747				left: 0;\
3748				will-change: transform;\
3749			}\
3750			#rulerCoordinates {\
3751				position: static;\
3752				opacity: 0.5;\
3753				background-color: #000;\
3754				color: #fff;\
3755				padding: 2px 5px;\
3756			}\
3757			#ruler::after, #ruler::before {\
3758				position: absolute;\
3759				content: '';\
3760				background-color: #00ff00;\
3761			}\
3762			#ruler::before {\
3763				width:1px;\
3764				height: 200vh;\
3765				top: -100vh;\
3766			}\
3767			#ruler::after {\
3768				height:1px;\
3769				width: 200vw;\
3770				left: -100vw;\
3771			}\
3772			body {\
3773				overflow: hidden !important;\
3774			}\
3775			* {\
3776				cursor: none !important;\
3777			}\
3778		";
3779		ruler.appendChild(style);
3780		document.body.appendChild(ruler);
3781
3782		var rulerCoordinates = document.createElement('span');
3783		rulerCoordinates.setAttribute('id', 'rulerCoordinates');
3784		document.body.appendChild(rulerCoordinates);
3785
3786		document.body.addEventListener('mousemove', rulerEventHandler);
3787		return this;
3788	},
3789	/**
3790	 * disables ruler
3791	 * @returns {Debugger}
3792	 */
3793	disableRuler: function () {
3794		document.body.removeEventListener('mousemove', rulerEventHandler);
3795		var ruler = document.getElementById('ruler');
3796		ruler.parentNode.removeChild(ruler);
3797		return this;
3798	}
3799
3800};
3801typeof window !== 'undefined' && (window.onerror = function (message, source, lineno, colno, error) {
3802	Debugger.logAction({message: message, source: source, lineno: lineno, colno: colno, error: error}, Debugger.levels.ERRORS);
3803	this.error_handler && this.error_handler.fn.apply(this.error_handler.context || this, arguments);
3804	if (Debugger.swallow) {
3805		return false;
3806	}
3807});
3808
3809Debugger.addLogLevel("ERROR")
3810	.addLogLevel("XHR")
3811	.addLogLevel("WS")
3812	.addLogLevel("EVENT")
3813	.addLogLevel("MOUSE_TRACKING");
3814module.exports = Debugger;
3815},{"./MouseTracking":1}],"delayed":[function(require,module,exports){
3816"use strict";
3817/**
3818 * stack of delayed functions
3819 * @type {object}
3820 */
3821var list = {};
3822/**
3823 * Function to delay function run
3824 * @param {function} func
3825 * @param {object} context
3826 * @param {number} delay
3827 * @param {string} ns - Namespace
3828 * @returns {undefined}
3829 */
3830function delayed(func, context, delay, ns) {
3831	ns = ns || func.toString().replace(/\s/g, "");
3832	list[ns] && clearTimeout(list[ns].timeout);
3833	list[ns] = {
3834		func: func, context: context, timeout: setTimeout(function () {
3835			func.call(context);
3836			delete list[ns];
3837		}, delay || 1000)
3838	};
3839	return list[ns].timeout;
3840}
3841
3842/**
3843 * @module @icewarp/delayed
3844 */
3845module.exports = delayed;
3846
3847},{}],"extend":[function(require,module,exports){
3848"use strict";
3849function defineFunction(parent, propKey) {
3850	return function () {
3851		return parent[propKey].apply(this, arguments);
3852	};
3853}
3854
3855/** Module for extending
3856 * @description Set child prototype to parent prototype and copy parents static properties to child
3857 * @module extend
3858 * @param {object} parent
3859 * @param {object} child
3860 * @returns {undefined}
3861 */
3862module.exports = function (parent, child) {
3863	var _constructor = child.prototype.constructor;
3864	child.prototype = Object.create(parent.prototype);
3865	child.prototype.constructor = _constructor;
3866	/*for(var propKey in parent) {
3867	 parent.hasOwnProperty(propKey) && Object.defineProperty(child, propKey, Object.getOwnPropertyDescriptor(parent, propKey));
3868	 };*/
3869	for (var propKey in parent) {
3870		if (!parent.hasOwnProperty(propKey)) {
3871			continue;
3872		}
3873		if (typeof parent[propKey] === 'function') {
3874			child[propKey] = defineFunction(parent, propKey);
3875		} else {
3876			Object.defineProperty(child, propKey, Object.getOwnPropertyDescriptor(parent, propKey));
3877		}
3878	}
3879};
3880
3881},{}],"function-name":[function(require,module,exports){
3882"use strict";
3883/**
3884 * Module to return function name
3885 * @param {Object} object
3886 * @returns {String}
3887 */
3888module.exports = function (object) {
3889	return object.name || function() {
3890		var funcNameRegex = /function\s+([^(]+)\s*\(/;
3891		var results = (funcNameRegex).exec(object.toString());
3892		return (results && results.length > 1) ? results[1] : "";
3893	}();
3894};
3895
3896},{}],"icebrace-runtime":[function(require,module,exports){
3897"use strict";
3898var Escape = require('@icewarp/escape-string');
3899
3900/**
3901 * @class Template
3902 */
3903var Template = {
3904	/**
3905	 * object to store template functions
3906	 */
3907	cache: {},
3908	/**
3909	 * @param {string} string - String representation of the compiled template function
3910	 * @returns {function} template function
3911	 */
3912	getFunction: function (string) {
3913		if (Template.cache[string]) {
3914			return Template.cache[string];
3915		}
3916		return Template.cache[string] = new Function('s','c','v','T','return ' + string);
3917	},
3918	/**
3919	 * returns an object with value and context
3920	 * @param {string[]} level array of keys
3921	 * @param {object} data context
3922	 * @param {object} current_data_level current context
3923	 * @returns {object} object with value and context
3924	 */
3925	resolvePath: function (level, data, current_data_level) {
3926		var ret = data.c;
3927		for (var i = 0; i < level.length; i++) {
3928			if (ret.hasOwnProperty(level[i])) {
3929				ret = ret[level[i]];
3930			} else if (data.p) {
3931				return Template.resolvePath(level, data.p, current_data_level);
3932			} else {
3933				return {v: '', c: current_data_level};
3934			}
3935		}
3936		return {v: ret, c: current_data_level};
3937	},
3938	/**
3939	 * 
3940	 * @param {object} context data
3941	 * @param {*} current
3942	 * @param {string} key
3943	 * @returns {mixed} value of the key
3944	 */
3945	getVar: function (context, current, key) {
3946		if (key === '.') {
3947			return (typeof context.c === 'object' ? current : context.c);
3948		}
3949		var value = Template.resolvePath(key.split('.'), context, context.c);
3950		if (typeof value.v === 'function') {
3951			return value.v.call(value.c);
3952		}
3953		return value.v;
3954	},
3955	/**
3956	 * 
3957	 * @param {object} context
3958	 * @param {*} value
3959	 * @param {string} key
3960	 * @returns {string} escaped string
3961	 */
3962	escapedString: function (context, value, key) {
3963		return Escape(toExport.u(context, value, key));
3964	},
3965	/**
3966	 * 
3967	 * @param {object} context
3968	 * @param {*} value
3969	 * @param {string} key
3970	 * @returns {string} non-escaped string
3971	 */
3972	unescapedString: function (context, value, key) {
3973		var variable = Template.getVar(context, value, key);
3974		return (variable !== null && typeof variable !== 'undefined') ? variable : '';
3975	},
3976	/**
3977	 * positive condition
3978	 * @param {object} strings
3979	 * @param {object} context
3980	 * @param {*} value
3981	 * @param {string} key
3982	 * @param {string} callback
3983	 * @returns {string}
3984	 */
3985	section: function (strings, context, value, key, callback) {
3986		var variable = Template.getVar(context, value, key), buffer;
3987		if (!variable) {
3988			return '';
3989		}
3990		if (Array.isArray(variable)) {
3991			buffer = variable.map(function (c) {
3992				return Template.getFunction(callback)(strings, {c: c, p: {c: variable, p: context}}, c, toExport);
3993			}, this).join('');
3994		} else if (typeof variable === 'string' || typeof variable === 'number' || typeof variable === 'boolean') {
3995			buffer = Template.getFunction(callback)(strings, context, variable, toExport);
3996		} else if (typeof variable === 'object' && variable !== null) {
3997			buffer = Template.getFunction(callback)(strings, {c: variable, p: context}, variable, toExport);
3998		}
3999		return buffer ? buffer : '';
4000	},
4001	/**
4002	 * 
4003	 * @param {object} context 
4004	 * @param {string} name name of component
4005	 * @returns {string}
4006	 */
4007	component: function (name, context) {
4008		return (Template.getTemplate(name, context)())(context);
4009	},
4010	/**
4011	 * else condition
4012	 * @param {object} strings
4013	 * @param {object} context
4014	 * @param {*} value
4015	 * @param {string} name
4016	 * @param {string} callback
4017	 * @returns {string}
4018	 */
4019	inverted: function (strings, context, value, name, callback) {
4020		var variable = this.getVar(context, value, name);
4021		return (!variable || (Array.isArray(variable) && !variable.length)) ? Template.getFunction(callback)(strings, context, value, toExport) : '';
4022	},
4023	getTemplate: function (name, context) {
4024		return name ? Template.templates[name] : name === void 0 ? Template.templates : false;
4025	}
4026};
4027/**
4028 * object to store templates
4029 */
4030Template.templates = {};
4031
4032/**
4033 * @typedef {Function} Template~component Component function
4034 * @argument {string} name name of component
4035 * @argument {object} context context to be passed to component
4036 */
4037
4038var toExport = {
4039	i: function () {
4040		return Template.inverted.apply(Template, arguments);
4041	},
4042	s: function () {
4043		return Template.section.apply(Template, arguments);
4044	},
4045	c: function () {
4046		return Template.component.apply(Template, arguments);
4047	},
4048	u: function () {
4049		return Template.unescapedString.apply(Template, arguments);
4050	},
4051	e: function () {
4052		return Template.escapedString.apply(Template, arguments);
4053	},
4054	t: function (name) {
4055		return Template.getTemplate.call(Template, name);
4056	},
4057	setTemplates: function (templates) {
4058		Template.templates = templates;
4059	},
4060	/**
4061	 * Replace component handler with new one for handeling custom template structures
4062	 * @param {Template~component} fn
4063	 * @returns {undefined}
4064	 */
4065	setComponentHandler: function (fn) {
4066		this.c = fn;
4067	}
4068};
4069
4070/**
4071 * @module @icewarp/icebrace
4072 */
4073module.exports = toExport;
4074},{"@icewarp/escape-string":2}],"logger":[function(require,module,exports){
4075"use strict";
4076/**
4077 * function to log arguments to console
4078 * @param {mixed} args
4079 * @param {string} type
4080 * @returns {undefined}
4081 */
4082function log(args, type) {
4083	if (current_level & Logger[type]) {
4084
4085		if (current_group) {
4086			if (current_group.collapsed) {
4087				console.groupCollapsed(current_group.name);
4088			} else {
4089				console.group(current_group.name);
4090			}
4091			current_group = null;
4092		}
4093
4094		args = [].slice.call(args);
4095		if (!console[type.toLowerCase()]) {
4096			type = 'LOG';
4097		}
4098
4099		if (enable_stack_trace) {
4100			console.groupCollapsed(new Date().toLocaleString() + ' ' + args[0]);
4101		} else {
4102			args.unshift(new Date().toLocaleString());
4103		}
4104
4105		for (var i = 0; i < open_groups.length; i++) {
4106			args = args.map(function (arg) {
4107				return typeof arg === "string" ? "    " + arg : arg;
4108			});
4109		}
4110
4111		try {
4112			console[type.toLowerCase()].apply(console, args);
4113		} catch(e) {
4114			console[type.toLowerCase()](args);
4115		}
4116
4117		if (enable_stack_trace) {
4118			console.error('TRACE');
4119			console.groupEnd();
4120		}
4121	}
4122}
4123
4124/**
4125 * Variable to store open console groups if console.group is not defined
4126 * @type String[]
4127 */
4128var open_groups = [];
4129
4130var current_group = null;
4131
4132var enable_stack_trace = false;
4133
4134/**
4135 * @class Logger
4136 */
4137var Logger = {
4138	/**
4139	 * Set logging level
4140	 * @param {number} level
4141	 * @returns {Logger}
4142	 */
4143	setLevel: function (level) {
4144		current_level = level;
4145		return this;
4146	},
4147	/**
4148	 * Enable stack trace in console
4149	 * @param {Boolean} enable
4150	 * @returns {Logger}
4151	 */
4152	enableStackTrace: function (enable) {
4153		enable_stack_trace = enable;
4154		return this;
4155	},
4156	/**
4157	 * Log log message
4158	 * @returns {Logger}
4159	 */
4160	log: function () {
4161		log(arguments, "LOG");
4162		return this;
4163	},
4164	/**
4165	 * Log info message
4166	 * @returns {Logger}
4167	 */
4168	info: function () {
4169		log(arguments, "INFO");
4170		return this;
4171	},
4172	/**
4173	 * Log warn message
4174	 * @returns {Logger}
4175	 */
4176	warning: function () {
4177		log(arguments, "WARN");
4178		return this;
4179	},
4180	/**
4181	 * Log error message
4182	 * @returns {Logger}
4183	 */
4184	error: function () {
4185		log(arguments, "ERROR");
4186		return this;
4187	},
4188	/**
4189	 * Start console group if console.group is defined
4190	 * @param {String} groupname
4191	 * @returns {Logger}
4192	 */
4193	group: function (groupname) {
4194		if (console.group) {
4195			current_group = { name: groupname };
4196		} else {
4197			log([groupname + ' console group start'], "LOG");
4198			open_groups.push(groupname);
4199		}
4200		return this;
4201	},
4202
4203	/**
4204	 * Start collapsed console group if console.group is defined
4205	 * @param {String} groupname
4206	 * @returns {Logger}
4207	 */
4208	groupCollapsed: function (groupname) {
4209		if (console.groupCollapsed) {
4210			current_group = { name: groupname, collapsed: true };
4211		} else {
4212			log([groupname + ' console group start'], "LOG");
4213			open_groups.push(groupname);
4214		}
4215		return this;
4216	},
4217
4218	/**
4219	 * End console group if console.group is defined
4220	 * @returns {Logger}
4221	 */
4222	groupEnd: function () {
4223		if (console.groupEnd) {
4224			console.groupEnd();
4225		} else {
4226			open_groups.shift();
4227		}
4228		return this;
4229	},
4230
4231	/** @const {number} 8 */
4232	LOG: 8,
4233	/** @const {number} 4 */
4234	INFO: 4,
4235	/** @const {number} 2 */
4236	WARN: 2,
4237	/** @const {number} 1 */
4238	ERROR: 1,
4239	/** @const {number} 0 */
4240	NONE: 0,
4241	/** @const {number} 15 */
4242	ALL: 15
4243};
4244
4245/**
4246 * Variable to store current log level
4247 * @type Number
4248 */
4249var current_level = Logger.ALL;
4250
4251console.log = console.log || function () {
4252	alert([].slice.call(arguments).join("\n"));
4253};
4254console.info = console.info || console.log;
4255console.warn = console.warn || console.log;
4256console.error = console.error || console.log;
4257
4258/**
4259 * @module @icewarp/logger
4260 */
4261module.exports = Logger;
4262
4263},{}],"mix":[function(require,module,exports){
4264"use strict";
4265var function_name = require('@icewarp/function-name');
4266
4267function defineOwnFunction(mixin, propKey) {
4268	return function () {
4269		return mixin[propKey].apply(this, arguments);
4270	};
4271}
4272
4273function definePrototypeFunction(mixin, propKey) {
4274	return function () {
4275		return mixin.prototype[propKey].apply(this, arguments);
4276	};
4277}
4278
4279/** Module for mixins
4280 * @description Copy parents properties to child (both static and prototype functions, except for constructor)
4281 * @module mix
4282 * @param {object} mixin
4283 * @param {object} target
4284 * @returns {undefined}
4285 */
4286module.exports = function (mixin, target) {
4287	for (var propKey in mixin) {
4288		if (!mixin.hasOwnProperty(propKey)) {
4289			continue;
4290		}
4291		if (typeof mixin[propKey] === 'function') {
4292			target[propKey] = defineOwnFunction(mixin, propKey);
4293		} else {
4294			Object.defineProperty(target, propKey, Object.getOwnPropertyDescriptor(mixin, propKey));
4295		}
4296	}
4297	for (propKey in mixin.prototype) {
4298		if (propKey === 'constructor' || !mixin.prototype.hasOwnProperty(propKey)) {
4299			continue;
4300		}
4301		if (typeof mixin.prototype[propKey] === 'function') {
4302			target.prototype[propKey] = definePrototypeFunction(mixin, propKey);
4303		} else {
4304			Object.defineProperty(target.prototype, propKey, Object.getOwnPropertyDescriptor(mixin.prototype, propKey));
4305		}
4306	}
4307	target.prototype.mixes = (target.prototype.mixes || []).concat([function_name(mixin)]);
4308};
4309},{"@icewarp/function-name":"function-name"}],"request":[function(require,module,exports){
4310"use strict";
4311/** Allowed events to listen on
4312 * 
4313 */
4314var events = ['progress', 'load', 'error', 'abort', 'always'];
4315/**
4316 * @type MissingOptionException
4317 */
4318var MissingOptionException = require('./missing_option_exception.js');
4319var Debugger = require('@icewarp/debugger');
4320
4321/** Actual XHR event handler
4322 * @listens progress
4323 * @listens load
4324 * @listens error
4325 * @listens abort
4326 * @param {object} e
4327 * @returns {void}
4328 */
4329var eventHandler = function (e) {
4330	this.events[e.type] && this.events[e.type].func.call(this.events[e.type].context, e, this.xhr);
4331	((e.type === 'load' || e.type === 'error') && this.events['always']) && this.events['always'].func.call(this.events['always'].context, e);
4332};
4333
4334/** Check if all required options are present
4335 * 
4336 * @param {object} options
4337 * @throws {MissingOptionException}
4338 * @throws {Error}
4339 * @returns {undefined}
4340 */
4341var validateOptions = function (options) {
4342	var keys = Object.keys(options);
4343	required_options.forEach(function (key) {
4344		if (!~keys.indexOf(key)) {
4345			throw new MissingOptionException(key);
4346		}
4347	});
4348};
4349
4350/** Required options Array
4351 * @type string[]
4352 * 
4353 */
4354var required_options = ['url'];
4355
4356/** Request module for handeling XHR requests
4357 * @class
4358 * @param {object} options
4359 * @returns {Request}
4360 */
4361function Request(options) {
4362	validateOptions(options);
4363	/** Listeners storage
4364	 * @private 
4365	 */
4366	this.events = {};
4367	/** 
4368	 * @private
4369	 * @type XMLHttpRequest
4370	 */
4371	this.xhr = new XMLHttpRequest();
4372	this.xhr.open(options.method || "GET", options.url, options.async === void 0 ? true : options.async, options.user || '', options.password || '');
4373	events.forEach(function (event) {
4374		this.xhr.addEventListener(event, eventHandler.bind(this));
4375	}, this);
4376	this.options = options;
4377	return this;
4378}
4379/** Add listener on XHR object
4380 * 
4381 * @param {string} event
4382 * @param {function} callback
4383 * @param {object} context
4384 * @returns {Request}
4385 */
4386Request.prototype.on = function (event, callback, context) {
4387	this.events[event] = {func: callback, context: context || this};
4388	return this;
4389};
4390/** Send XHR
4391 * 
4392 * @param {object} payload
4393 * @returns {void}
4394 */
4395Request.prototype.send = function (payload) {
4396	Debugger.logAction({options: this.options, payload: payload}, Debugger.levels.XHR);
4397	this.xhr.send(payload || null);
4398};
4399
4400/**
4401 *  @module Request
4402 *  @requires MissingOptionException
4403 */
4404module.exports = Request;
4405},{"./missing_option_exception.js":9,"@icewarp/debugger":"debugger"}],"socket":[function(require,module,exports){
4406"use strict";
4407var Connection = require('./connection.js');
4408
4409
4410/** Object containing all open connections
4411 * @type Object
4412 */
4413var connections = {};
4414
4415/** Socket wrapper class for connection
4416 * @class 
4417 * @returns {nm$_socket.Socket}
4418 */
4419function Socket() {
4420}
4421/**
4422 * 
4423 * @param {string} name
4424 * @param {object} options options to initialize connection with
4425 * @returns {Connection}
4426 */
4427Socket.createConnection = function (name, options) {
4428	return (connections[name] = new Connection(options));
4429};
4430/** Getter for connection instance
4431 * 
4432 * @param {string} name
4433 * @returns {Connection}
4434 */
4435Socket.getConnection = function (name) {
4436	return connections[name];
4437};
4438
4439/**
4440 * @module Socket
4441 * @exports Socket
4442 */
4443module.exports = Socket;
4444
4445},{"./connection.js":10}]},{},[7]);

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.