1/*
2@license
3
4dhtmlxGantt v.6.3.5 Standard
5
6This version of dhtmlxGantt is distributed under GPL 2.0 license and can be legally used in GPL projects.
7
8To use dhtmlxGantt in non-GPL projects (and get Pro version of the product), please obtain Commercial/Enterprise or Ultimate license on our site https://dhtmlx.com/docs/products/dhtmlxGantt/#licensing or contact us at sales@dhtmlx.com
9
10(c) XB Software Ltd.
11
12*/
13(function webpackUniversalModuleDefinition(root, factory) {
14	if(typeof exports === 'object' && typeof module === 'object')
15		module.exports = factory();
16	else if(typeof define === 'function' && define.amd)
17		define("ext/dhtmlxgantt_keyboard_navigation", [], factory);
18	else if(typeof exports === 'object')
19		exports["ext/dhtmlxgantt_keyboard_navigation"] = factory();
20	else
21		root["ext/dhtmlxgantt_keyboard_navigation"] = factory();
22})(window, function() {
23return /******/ (function(modules) { // webpackBootstrap
24/******/ 	// The module cache
25/******/ 	var installedModules = {};
26/******/
27/******/ 	// The require function
28/******/ 	function __webpack_require__(moduleId) {
29/******/
30/******/ 		// Check if module is in cache
31/******/ 		if(installedModules[moduleId]) {
32/******/ 			return installedModules[moduleId].exports;
33/******/ 		}
34/******/ 		// Create a new module (and put it into the cache)
35/******/ 		var module = installedModules[moduleId] = {
36/******/ 			i: moduleId,
37/******/ 			l: false,
38/******/ 			exports: {}
39/******/ 		};
40/******/
41/******/ 		// Execute the module function
42/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
43/******/
44/******/ 		// Flag the module as loaded
45/******/ 		module.l = true;
46/******/
47/******/ 		// Return the exports of the module
48/******/ 		return module.exports;
49/******/ 	}
50/******/
51/******/
52/******/ 	// expose the modules object (__webpack_modules__)
53/******/ 	__webpack_require__.m = modules;
54/******/
55/******/ 	// expose the module cache
56/******/ 	__webpack_require__.c = installedModules;
57/******/
58/******/ 	// define getter function for harmony exports
59/******/ 	__webpack_require__.d = function(exports, name, getter) {
60/******/ 		if(!__webpack_require__.o(exports, name)) {
61/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
62/******/ 		}
63/******/ 	};
64/******/
65/******/ 	// define __esModule on exports
66/******/ 	__webpack_require__.r = function(exports) {
67/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
68/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
69/******/ 		}
70/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
71/******/ 	};
72/******/
73/******/ 	// create a fake namespace object
74/******/ 	// mode & 1: value is a module id, require it
75/******/ 	// mode & 2: merge all properties of value into the ns
76/******/ 	// mode & 4: return value when already ns object
77/******/ 	// mode & 8|1: behave like require
78/******/ 	__webpack_require__.t = function(value, mode) {
79/******/ 		if(mode & 1) value = __webpack_require__(value);
80/******/ 		if(mode & 8) return value;
81/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
82/******/ 		var ns = Object.create(null);
83/******/ 		__webpack_require__.r(ns);
84/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
85/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
86/******/ 		return ns;
87/******/ 	};
88/******/
89/******/ 	// getDefaultExport function for compatibility with non-harmony modules
90/******/ 	__webpack_require__.n = function(module) {
91/******/ 		var getter = module && module.__esModule ?
92/******/ 			function getDefault() { return module['default']; } :
93/******/ 			function getModuleExports() { return module; };
94/******/ 		__webpack_require__.d(getter, 'a', getter);
95/******/ 		return getter;
96/******/ 	};
97/******/
98/******/ 	// Object.prototype.hasOwnProperty.call
99/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
100/******/
101/******/ 	// __webpack_public_path__
102/******/ 	__webpack_require__.p = "/codebase/sources/";
103/******/
104/******/
105/******/ 	// Load entry module and return exports
106/******/ 	return __webpack_require__(__webpack_require__.s = "./sources/ext/keyboard_navigation.js");
107/******/ })
108/************************************************************************/
109/******/ ({
110
111/***/ "./sources/ext/keyboard_navigation.js":
112/*!********************************************!*\
113  !*** ./sources/ext/keyboard_navigation.js ***!
114  \********************************************/
115/*! no static exports found */
116/***/ (function(module, exports, __webpack_require__) {
117
118(function(){
119	var eventable = __webpack_require__(/*! ../utils/eventable */ "./sources/utils/eventable.js");
120	function setupKeyNav(gantt){
121		gantt.config.keyboard_navigation = true;
122		gantt.config.keyboard_navigation_cells = false;
123
124		gantt.$keyboardNavigation = {};
125
126		gantt._compose = function(){
127			var parts = Array.prototype.slice.call(arguments, 0);
128			var res = {};
129			for(var i = 0; i < parts.length; i++){
130				var obj = parts[i];
131				if(typeof obj == "function"){
132					obj = new obj();
133				}
134
135				for(var p in obj){
136					res[p] = obj[p];
137				}
138			}
139			return res;
140		};
141
142		__webpack_require__ (/*! ./keyboard_navigation/common/keyboard_shortcuts */ "./sources/ext/keyboard_navigation/common/keyboard_shortcuts.js")(gantt);
143		__webpack_require__ (/*! ./keyboard_navigation/common/eventhandler */ "./sources/ext/keyboard_navigation/common/eventhandler.js")(gantt);
144		__webpack_require__ (/*! ./keyboard_navigation/common/trap_modal_focus */ "./sources/ext/keyboard_navigation/common/trap_modal_focus.js")(gantt);
145		__webpack_require__ (/*! ./keyboard_navigation/elements/gantt_node */ "./sources/ext/keyboard_navigation/elements/gantt_node.js")(gantt);
146		__webpack_require__ (/*! ./keyboard_navigation/elements/nav_node */ "./sources/ext/keyboard_navigation/elements/nav_node.js")(gantt);
147		__webpack_require__ (/*! ./keyboard_navigation/elements/header_cell */ "./sources/ext/keyboard_navigation/elements/header_cell.js")(gantt);
148		__webpack_require__ (/*! ./keyboard_navigation/elements/task_row */ "./sources/ext/keyboard_navigation/elements/task_row.js")(gantt);
149		__webpack_require__ (/*! ./keyboard_navigation/elements/task_cell */ "./sources/ext/keyboard_navigation/elements/task_cell.js")(gantt);
150		__webpack_require__ (/*! ./keyboard_navigation/modals */ "./sources/ext/keyboard_navigation/modals.js")(gantt);
151		__webpack_require__ (/*! ./keyboard_navigation/core */ "./sources/ext/keyboard_navigation/core.js")(gantt);
152
153		var domHelpers = __webpack_require__(/*! ../utils/dom_helpers */ "./sources/utils/dom_helpers.js");
154
155		(function(){
156			var dispatcher = gantt.$keyboardNavigation.dispatcher;
157
158			dispatcher.isTaskFocused = function(id){
159				var node = dispatcher.activeNode;
160				if(node instanceof gantt.$keyboardNavigation.TaskRow || node instanceof gantt.$keyboardNavigation.TaskCell) {
161					if (node.taskId == id) {
162						return true;
163					}
164				}
165				return false;
166			};
167
168			var keyDownHandler = function(e){
169				if(!gantt.config.keyboard_navigation) return;
170
171				return dispatcher.keyDownHandler(e);
172			};
173
174			var focusHandler = function(e){
175				if(dispatcher.$preventDefault){
176					e.preventDefault();
177					gantt.$container.blur();
178					return false;
179				// do nothing if key-nav focus is already planned
180				} else if (!dispatcher.awaitsFocus()) {
181					// otherwise - re-focus key-nav element on gantt focus
182					dispatcher.focusGlobalNode();
183				}
184
185			};
186
187			var reFocusActiveNode = function(){
188				if(!dispatcher.isEnabled())
189					return;
190
191				var activeNode = dispatcher.getActiveNode();
192				if(!activeNode)
193					return;
194
195				var domElement = activeNode.getNode();
196				var top, left;
197				if(domElement && domElement.parentNode){
198					top = domElement.parentNode.scrollTop;
199					left = domElement.parentNode.scrollLeft;
200
201				}
202
203				activeNode.focus(true);
204
205				if(domElement && domElement.parentNode){
206					domElement.parentNode.scrollTop = top;
207					domElement.parentNode.scrollLeft = left;
208				}
209			};
210
211
212			gantt.attachEvent("onDataRender", function(){
213				if(!gantt.config.keyboard_navigation) return;
214				reFocusActiveNode();
215			});
216
217			gantt.attachEvent("onGanttRender", function(){
218				gantt.eventRemove(document, "keydown", keyDownHandler);
219				gantt.eventRemove(gantt.$container, "focus", focusHandler);
220				gantt.eventRemove(gantt.$container, "mousedown", mousedownHandler);
221
222				if(gantt.config.keyboard_navigation){
223
224					gantt.event(document, "keydown", keyDownHandler);
225					gantt.event(gantt.$container, "focus", focusHandler);
226					gantt.event(gantt.$container, "mousedown", mousedownHandler);
227					gantt.$container.setAttribute("tabindex", "0");
228
229				}else{
230					gantt.$container.removeAttribute("tabindex");
231				}
232			});
233
234			function getTaskNodeConstructor(){
235				if (gantt.config.keyboard_navigation_cells) {
236					return gantt.$keyboardNavigation.TaskCell;
237				} else {
238					return gantt.$keyboardNavigation.TaskRow;
239				}
240			}
241
242			function mousedownHandler(e){
243				if(!gantt.config.keyboard_navigation) return true;
244
245				var focusNode;
246				var locateTask = dispatcher.fromDomElement(e);
247				if(locateTask){
248					//var node = getTaskNodeConstructor();
249					if(dispatcher.activeNode instanceof gantt.$keyboardNavigation.TaskCell && domHelpers.isChildOf(e.target, gantt.$task)){
250						locateTask = new gantt.$keyboardNavigation.TaskCell(locateTask.taskId, dispatcher.activeNode.columnIndex);
251					}
252					focusNode = locateTask;
253				}
254				if (focusNode) {
255					if (!dispatcher.isEnabled()) {
256						dispatcher.activeNode = focusNode;
257					} else {
258						dispatcher.delay(function () {
259							dispatcher.setActiveNode(focusNode);
260						});
261					}
262				} else {
263					// empty click should drop focus from gantt, insert of reselecting default node
264					dispatcher.$preventDefault = true;
265					setTimeout(function(){
266						dispatcher.$preventDefault = false;
267					}, 300);
268				}
269			}
270
271			var onReady = gantt.attachEvent("onGanttReady", function(){
272				// restore focus on repainted tasks
273				gantt.detachEvent(onReady);
274
275				gantt.$data.tasksStore.attachEvent("onStoreUpdated", function(id){
276					if (gantt.config.keyboard_navigation && dispatcher.isEnabled()) {
277						var currentNode = dispatcher.getActiveNode();
278						if(currentNode && currentNode.taskId == id){
279							reFocusActiveNode();
280						}
281					}
282				});
283
284				if(gantt._smart_render){
285					var updateRender = gantt._smart_render._redrawTasks;
286					gantt._smart_render._redrawTasks = function(renderers, items){
287						if(gantt.config.keyboard_navigation && dispatcher.isEnabled()){
288							var currentNode = dispatcher.getActiveNode();
289							if(currentNode && currentNode.taskId !== undefined){
290								var focusedItemVisible = false;
291								for(var i = 0; i < items.length; i++){
292									if(items[i].id == currentNode.taskId && items[i].start_date){
293										focusedItemVisible = true;
294										break;
295									}
296								}
297								if(!focusedItemVisible){
298									items.push(gantt.getTask(currentNode.taskId));
299								}
300							}
301						}
302						var res = updateRender.apply(this, arguments);
303
304						return res;
305					};
306				}
307			});
308
309
310
311			gantt.attachEvent("onAfterTaskAdd", function(id,item){
312				if(!gantt.config.keyboard_navigation) return true;
313				if(dispatcher.isEnabled()){
314
315					var columnIndex = 0;
316					var node = dispatcher.activeNode;
317					if(node instanceof gantt.$keyboardNavigation.TaskCell){
318						columnIndex = node.columnIndex;
319					}
320					var nodeConstructor = getTaskNodeConstructor();
321
322					dispatcher.setActiveNode(new nodeConstructor(id, columnIndex));
323
324
325				}
326			});
327
328			gantt.attachEvent("onTaskIdChange", function(oldId, newId){
329				if(!gantt.config.keyboard_navigation) return true;
330
331				var node = dispatcher.activeNode;
332				if(dispatcher.isTaskFocused(oldId)){
333					node.taskId = newId;
334				}
335
336				return true;
337			});
338
339			function getActiveNode(){
340
341				var activeElement = document.activeElement;
342				if(activeElement === document.body && document.getSelection){
343					activeElement = document.getSelection().focusNode || document.body;
344				}
345
346				return activeElement;
347			}
348
349			var interval = setInterval(function(){
350				if(!gantt.config.keyboard_navigation) return;
351
352				var enable;
353				var focusElement = getActiveNode();
354
355				var parent = gantt.$container;
356				// halt key nav when focus is outside gantt or in quick info popup
357				if(!focusElement || gantt._locate_css(focusElement, "gantt_cal_quick_info")){
358					enable = false;
359				}else{
360					while(focusElement != parent &&  focusElement){
361						focusElement = focusElement.parentNode;
362					}
363
364					if(focusElement == parent){
365						enable = true;
366					}else{
367						enable = false;
368					}
369				}
370
371				if(enable && !dispatcher.isEnabled()){
372					dispatcher.enable();
373				}else if(!enable && dispatcher.isEnabled()){
374					dispatcher.disable();
375				}
376
377			}, 500);
378
379			gantt.attachEvent("onDestroy", function(){
380				clearInterval(interval);
381			});
382
383			function getScopeName(obj){
384				if(obj instanceof gantt.$keyboardNavigation.GanttNode){
385					return "gantt";
386				}else if(obj instanceof gantt.$keyboardNavigation.HeaderCell){
387					return "headerCell";
388				}else if(obj instanceof gantt.$keyboardNavigation.TaskRow){
389					return "taskRow";
390				}else if(obj instanceof gantt.$keyboardNavigation.TaskCell){
391					return "taskCell";
392				}
393				return null;
394			}
395
396			function getScope(mode){
397				var scopes = {
398					"gantt":gantt.$keyboardNavigation.GanttNode,
399					"headerCell": gantt.$keyboardNavigation.HeaderCell,
400					"taskRow": gantt.$keyboardNavigation.TaskRow,
401					"taskCell": gantt.$keyboardNavigation.TaskCell
402				};
403
404				return scopes[mode] || scopes.gantt;
405			}
406
407			function findVisibleColumnIndex(columnName) {
408				var columns = gantt.getGridColumns();
409				for (var i = 0; i < columns.length; i++){
410					if(columns[i].name == columnName){
411						return i;
412					}
413				}
414				return 0;
415			}
416
417			var keyNavFacade = {};
418			eventable(keyNavFacade);
419			gantt.mixin(keyNavFacade, {
420				addShortcut: function(shortcut, handler, scope){
421					var scopeObject = getScope(scope);
422					if(scopeObject){
423						scopeObject.prototype.bind(shortcut, handler);
424					}
425				},
426				getShortcutHandler: function(shortcut, scope){
427					var commands = gantt.$keyboardNavigation.shortcuts.parse(shortcut);
428					if(commands.length){
429						return this.getCommandHandler(commands[0], scope);
430					}
431				},
432				getCommandHandler: function(command, scope){
433					var scopeObject = getScope(scope);
434					if(scopeObject){
435						if(command){
436							return scopeObject.prototype.findHandler(command);
437						}
438					}
439				},
440				removeShortcut: function(shortcut, scope){
441					var scopeObject = getScope(scope);
442					if(scopeObject){
443						scopeObject.prototype.unbind(shortcut);
444					}
445				},
446				focus: function(config){
447					var type = config ? config.type : null;
448					var constructor = getScope(type);
449					var node;
450					switch (type){
451						case "taskCell":
452							node = new constructor(config.id, findVisibleColumnIndex(config.column));
453							break;
454						case "taskRow":
455							node = new constructor(config.id);
456							break;
457						case "headerCell":
458							node = new constructor(findVisibleColumnIndex(config.column));
459							break;
460						default:
461
462							break;
463					}
464					dispatcher.delay(function(){
465						if(node){
466							dispatcher.setActiveNode(node);
467						}else{
468							dispatcher.enable();
469							if(!dispatcher.getActiveNode()){
470
471								dispatcher.setDefaultNode();
472							}else{
473
474								if(!dispatcher.awaitsFocus()){
475									dispatcher.enable();
476								}
477
478							}
479						}
480
481					});
482				},
483
484				getActiveNode: function(){
485					if(dispatcher.isEnabled()){
486						var node = dispatcher.getActiveNode();
487						var scope = getScopeName(node);
488						var columns = gantt.getGridColumns();
489						switch (scope){
490							case "taskCell":
491								return {type:"taskCell", id:node.taskId, column:columns[node.columnIndex].name};
492							case "taskRow":
493								return {type:"taskRow", id:node.taskId};
494							case "headerCell":
495								return {type:"headerCell", column:columns[node.index].name};
496						}
497					}
498					return null;
499				}
500			});
501
502			gantt.$keyboardNavigation.facade = keyNavFacade;
503
504			gantt.ext.keyboardNavigation = keyNavFacade;
505			gantt.focus = function(){
506				keyNavFacade.focus();
507			};
508			gantt.addShortcut = keyNavFacade.addShortcut;
509			gantt.getShortcutHandler = keyNavFacade.getShortcutHandler;
510			gantt.removeShortcut = keyNavFacade.removeShortcut;
511		})();
512
513
514	}
515
516	setupKeyNav(gantt);
517
518
519
520})();
521
522/***/ }),
523
524/***/ "./sources/ext/keyboard_navigation/common/eventhandler.js":
525/*!****************************************************************!*\
526  !*** ./sources/ext/keyboard_navigation/common/eventhandler.js ***!
527  \****************************************************************/
528/*! no static exports found */
529/***/ (function(module, exports) {
530
531module.exports = function(gantt) {
532
533	gantt.$keyboardNavigation.EventHandler = {
534		_handlers: null,
535		findHandler: function (command) {
536			if (!this._handlers) this._handlers = {};
537			var shortcuts = gantt.$keyboardNavigation.shortcuts;
538			var hash = shortcuts.getHash(command);
539
540			return this._handlers[hash];
541		},
542
543		doAction: function (command, e) {
544			var handler = this.findHandler(command);
545			if (handler) {
546				var eventFacade = gantt.$keyboardNavigation.facade;
547
548				if(eventFacade.callEvent("onBeforeAction", [command, e]) === false){
549					return;
550				}
551
552				handler.call(this, e);
553
554				if (e.preventDefault) e.preventDefault();
555				else e.returnValue = false;
556
557			}
558		},
559		bind: function (shortcut, handler) {
560			if (!this._handlers) this._handlers = {};
561
562			var shortcuts = gantt.$keyboardNavigation.shortcuts;
563
564			var commands = shortcuts.parse(shortcut);
565			for (var i = 0; i < commands.length; i++) {
566				this._handlers[shortcuts.getHash(commands[i])] = handler;
567			}
568		},
569		unbind: function (shortcut) {
570			var shortcuts = gantt.$keyboardNavigation.shortcuts;
571
572			var commands = shortcuts.parse(shortcut);
573			for (var i = 0; i < commands.length; i++) {
574				if (this._handlers[shortcuts.getHash(commands[i])]) {
575					delete this._handlers[shortcuts.getHash(commands[i])];
576				}
577			}
578		},
579
580		bindAll: function (map) {
581			for (var i in map) {
582				this.bind(i, map[i]);
583			}
584		},
585		initKeys: function () {
586			if (!this._handlers)
587				this._handlers = {};
588			if (this.keys) {
589				this.bindAll(this.keys);
590			}
591		}
592	};
593
594};
595
596/***/ }),
597
598/***/ "./sources/ext/keyboard_navigation/common/keyboard_shortcuts.js":
599/*!**********************************************************************!*\
600  !*** ./sources/ext/keyboard_navigation/common/keyboard_shortcuts.js ***!
601  \**********************************************************************/
602/*! no static exports found */
603/***/ (function(module, exports) {
604
605module.exports = function(gantt) {
606
607	gantt.$keyboardNavigation.shortcuts = {
608		createCommand: function () {
609			return {
610				modifiers: {
611					"shift": false,
612					"alt": false,
613					"ctrl": false,
614					"meta": false
615				},
616				keyCode: null
617			};
618		},
619		parse: function (shortcut) {
620			var commands = [];
621
622			var expr = this.getExpressions(this.trim(shortcut));
623			for (var i = 0; i < expr.length; i++) {
624				var words = this.getWords(expr[i]);
625
626				var command = this.createCommand();
627
628				for (var j = 0; j < words.length; j++) {
629					if (this.commandKeys[words[j]]) {
630						command.modifiers[words[j]] = true;
631					} else if (this.specialKeys[words[j]]) {
632						command.keyCode = this.specialKeys[words[j]];
633					} else {
634						command.keyCode = words[j].charCodeAt(0);
635					}
636				}
637
638				commands.push(command);
639			}
640			return commands;
641		},
642
643		getCommandFromEvent: function (domEvent) {
644			var command = this.createCommand();
645			command.modifiers.shift = !!domEvent.shiftKey;
646			command.modifiers.alt = !!domEvent.altKey;
647			command.modifiers.ctrl = !!domEvent.ctrlKey;
648			command.modifiers.meta = !!domEvent.metaKey;
649			command.keyCode = domEvent.which || domEvent.keyCode;
650
651			if(command.keyCode >= 96 && command.keyCode <= 105){
652				// numpad keys 96-105 -> 48-57
653				command.keyCode -= 48;//convert numpad  number code to regular number code
654			}
655
656			var printableKey = String.fromCharCode(command.keyCode);
657			if (printableKey) {
658				command.keyCode = printableKey.toLowerCase().charCodeAt(0);
659			}
660			return command;
661		},
662
663		getHashFromEvent: function (domEvent) {
664			return this.getHash(this.getCommandFromEvent(domEvent));
665		},
666
667		getHash: function (command) {
668			var parts = [];
669			for (var i in command.modifiers) {
670				if (command.modifiers[i]) {
671					parts.push(i);
672				}
673			}
674			parts.push(command.keyCode);
675
676			return parts.join(this.junctionChar);
677		},
678
679		getExpressions: function (shortcut) {
680			return shortcut.split(this.junctionChar);
681		},
682		getWords: function (term) {
683			return term.split(this.combinationChar);
684		},
685		trim: function (shortcut) {
686			return shortcut.replace(/\s/g, "");
687		},
688		junctionChar: ",",
689		combinationChar: "+",
690		commandKeys: {
691			"shift": 16,
692			"alt": 18,
693			"ctrl": 17,
694			"meta": true
695		},
696		specialKeys: {
697			"backspace": 8,
698			"tab": 9,
699			"enter": 13,
700			"esc": 27,
701			"space": 32,
702			"up": 38,
703			"down": 40,
704			"left": 37,
705			"right": 39,
706			"home": 36,
707			"end": 35,
708			"pageup": 33,
709			"pagedown": 34,
710			"delete": 46,
711			"insert": 45,
712			"plus": 107,
713			"f1": 112,
714			"f2": 113,
715			"f3": 114,
716			"f4": 115,
717			"f5": 116,
718			"f6": 117,
719			"f7": 118,
720			"f8": 119,
721			"f9": 120,
722			"f10": 121,
723			"f11": 122,
724			"f12": 123
725		}
726	};
727};
728
729/***/ }),
730
731/***/ "./sources/ext/keyboard_navigation/common/trap_modal_focus.js":
732/*!********************************************************************!*\
733  !*** ./sources/ext/keyboard_navigation/common/trap_modal_focus.js ***!
734  \********************************************************************/
735/*! no static exports found */
736/***/ (function(module, exports, __webpack_require__) {
737
738module.exports = function(gantt) {
739
740	(function () {
741		var domHelpers = __webpack_require__(/*! ../../../utils/dom_helpers */ "./sources/utils/dom_helpers.js");
742		gantt.$keyboardNavigation.getFocusableNodes = domHelpers.getFocusableNodes;
743
744		gantt.$keyboardNavigation.trapFocus = function trapFocus(root, e) {
745			if (e.keyCode != 9) return false;
746
747			var focusable = gantt.$keyboardNavigation.getFocusableNodes(root);
748			var currentFocus = document.activeElement;
749			var currentIndex = -1;
750			for (var i = 0; i < focusable.length; i++) {
751				if (focusable[i] == currentFocus) {
752					currentIndex = i;
753					break;
754				}
755			}
756
757			if (e.shiftKey) {
758				// back tab
759				if (currentIndex <= 0) {
760					// go to the last element if we focused on the first
761					var lastItem = focusable[focusable.length - 1];
762					if (lastItem) {
763						lastItem.focus();
764						e.preventDefault();
765						return true;
766					}
767				}
768
769			} else {
770				// forward tab
771				if (currentIndex >= focusable.length - 1) {
772					// forward tab from last element should go back to the first element
773					var firstItem = focusable[0];
774					if (firstItem) {
775						firstItem.focus();
776						e.preventDefault();
777						return true;
778					}
779				}
780			}
781
782			return false;
783		};
784	})();
785
786};
787
788/***/ }),
789
790/***/ "./sources/ext/keyboard_navigation/core.js":
791/*!*************************************************!*\
792  !*** ./sources/ext/keyboard_navigation/core.js ***!
793  \*************************************************/
794/*! no static exports found */
795/***/ (function(module, exports) {
796
797module.exports = function(gantt) {
798
799	gantt.$keyboardNavigation.dispatcher = {
800		isActive: false,
801		activeNode: null,
802		globalNode: new gantt.$keyboardNavigation.GanttNode(),
803
804		enable: function () {
805			this.isActive = true;
806			this.globalNode.enable();
807			this.setActiveNode(this.getActiveNode());
808		},
809
810		disable: function () {
811			this.isActive = false;
812			this.globalNode.disable();
813		},
814
815		isEnabled: function () {
816			return !!this.isActive;
817		},
818
819		getDefaultNode: function () {
820			var node;
821			if (gantt.config.keyboard_navigation_cells) {
822				node = new gantt.$keyboardNavigation.TaskCell();
823			} else {
824				node = new gantt.$keyboardNavigation.TaskRow();
825			}
826
827			if (!node.isValid()) {
828				node = node.fallback();
829			}
830			return node;
831		},
832
833		setDefaultNode: function () {
834			this.setActiveNode(this.getDefaultNode());
835		},
836
837		getActiveNode: function () {
838			var node = this.activeNode;
839			if (node && !node.isValid()) {
840				node = node.fallback();
841			}
842			return node;
843		},
844
845		fromDomElement: function(e){
846			var inputs = [
847				gantt.$keyboardNavigation.TaskRow,
848				gantt.$keyboardNavigation.TaskCell,
849				gantt.$keyboardNavigation.HeaderCell
850			];
851			for(var i = 0; i < inputs.length; i++){
852				if(inputs[i].prototype.fromDomElement){
853					var node = inputs[i].prototype.fromDomElement(e);
854					if(node) return node;
855				}
856			}
857			return null;
858		},
859
860		focusGlobalNode: function () {
861			this.blurNode(this.globalNode);
862			this.focusNode(this.globalNode);
863		},
864
865		setActiveNode: function (el) {
866			//console.trace()
867			var focusChanged = true;
868			if (this.activeNode) {
869				if (this.activeNode.compareTo(el)) {
870					focusChanged = false;
871				}
872			}
873			if (this.isEnabled()) {
874				if(focusChanged)
875					this.blurNode(this.activeNode);
876
877				this.activeNode = el;
878				this.focusNode(this.activeNode, !focusChanged);
879			}
880		},
881
882		focusNode: function (el, keptFocus) {
883			if (el && el.focus) {
884				el.focus(keptFocus);
885			}
886		},
887		blurNode: function (el) {
888			if (el && el.blur) {
889				el.blur();
890			}
891		},
892
893		keyDownHandler: function (e) {
894
895			if (gantt.$keyboardNavigation.isModal())
896				return;
897
898			if (!this.isEnabled())
899				return;
900
901			e = e || window.event;
902
903
904			if(e.defaultPrevented){
905				return;
906			}
907
908			var ganttNode = this.globalNode;
909
910			var command = gantt.$keyboardNavigation.shortcuts.getCommandFromEvent(e);
911
912			var activeElement = this.getActiveNode();
913			var eventFacade = gantt.$keyboardNavigation.facade;
914			if(eventFacade.callEvent("onKeyDown", [command, e]) === false){
915				return;
916			}
917
918			if (!activeElement) {
919				this.setDefaultNode();
920			} else if (activeElement.findHandler(command)) {
921				activeElement.doAction(command, e);
922			} else if (ganttNode.findHandler(command)) {
923				ganttNode.doAction(command, e);
924			}
925
926		},
927		_timeout: null,
928		awaitsFocus: function(){
929			return this._timeout !== null;
930		},
931		delay: function(callback, delay){
932
933			clearTimeout(this._timeout);
934			this._timeout = setTimeout(gantt.bind(function(){
935				this._timeout = null;
936				callback();
937			}, this)  , delay || 1);
938
939		},
940		clearDelay: function(){
941			clearTimeout(this._timeout);
942		}
943	};
944
945};
946
947/***/ }),
948
949/***/ "./sources/ext/keyboard_navigation/elements/gantt_node.js":
950/*!****************************************************************!*\
951  !*** ./sources/ext/keyboard_navigation/elements/gantt_node.js ***!
952  \****************************************************************/
953/*! no static exports found */
954/***/ (function(module, exports) {
955
956module.exports = function(gantt) {
957
958	gantt.$keyboardNavigation.GanttNode = function () {
959	};
960
961	gantt.$keyboardNavigation.GanttNode.prototype = gantt._compose(
962		gantt.$keyboardNavigation.EventHandler,
963		{
964
965			focus: function () {
966				gantt.focus();
967			},
968
969			blur: function () {
970
971			},
972
973			disable: function () {
974				gantt.$container.setAttribute("tabindex", "0");
975			},
976			enable: function () {
977				if (gantt.$container)
978					gantt.$container.removeAttribute("tabindex");
979			},
980			isEnabled: function () {
981				return gantt.$container.hasAttribute("tabindex");
982			},
983
984			scrollHorizontal: function scrollHorizontal(dir) {
985				var date = gantt.dateFromPos(gantt.getScrollState().x);
986				var scale = gantt.getScale();
987				var step = dir < 0 ? -scale.step : scale.step;
988				date = gantt.date.add(date, step, scale.unit);
989				gantt.scrollTo(gantt.posFromDate(date));
990			},
991
992			scrollVertical: function scrollVertical(dir) {
993				var top = gantt.getScrollState().y;
994				var step = gantt.config.row_height;
995				gantt.scrollTo(null, top + (dir < 0 ? -1 : 1) * step);
996			},
997
998			keys: {
999				"alt+left": function (e) {
1000					this.scrollHorizontal(-1);
1001				},
1002				"alt+right": function (e) {
1003					this.scrollHorizontal(1);
1004				},
1005				"alt+up": function (e) {
1006					this.scrollVertical(-1);
1007				},
1008				"alt+down": function (e) {
1009					this.scrollVertical(1);
1010				},
1011
1012				// undo
1013				"ctrl+z": function () {
1014					if (gantt.undo) gantt.undo();
1015				},
1016
1017				// redo
1018				"ctrl+r": function () {
1019					if (gantt.redo) gantt.redo();
1020				}
1021			}
1022		}
1023	);
1024
1025	gantt.$keyboardNavigation.GanttNode.prototype.bindAll(gantt.$keyboardNavigation.GanttNode.prototype.keys);
1026
1027};
1028
1029/***/ }),
1030
1031/***/ "./sources/ext/keyboard_navigation/elements/header_cell.js":
1032/*!*****************************************************************!*\
1033  !*** ./sources/ext/keyboard_navigation/elements/header_cell.js ***!
1034  \*****************************************************************/
1035/*! no static exports found */
1036/***/ (function(module, exports, __webpack_require__) {
1037
1038module.exports = function(gantt) {
1039	var domHelpers = __webpack_require__(/*! ../../../utils/dom_helpers */ "./sources/utils/dom_helpers.js");
1040
1041	gantt.$keyboardNavigation.HeaderCell = function (index) {
1042		this.index = index || 0;
1043	};
1044
1045	gantt.$keyboardNavigation.HeaderCell.prototype = gantt._compose(
1046		gantt.$keyboardNavigation.KeyNavNode,
1047		{
1048			_handlers: null,
1049
1050			isValid: function () {
1051				if (!gantt.config.show_grid) {
1052					if (gantt.getVisibleTaskCount())
1053						return false;
1054				}
1055				return !!gantt.getGridColumns()[this.index] || !gantt.getVisibleTaskCount();
1056			},
1057			fallback: function () {
1058				if (!gantt.config.show_grid) {
1059					if (gantt.getVisibleTaskCount()) {
1060						return new gantt.$keyboardNavigation.TaskRow();
1061					}
1062					return null;
1063				}
1064				var visibleColumns = gantt.getGridColumns();
1065				var index = this.index;
1066				while (index >= 0) {
1067					if (visibleColumns[index])
1068						break;
1069					index--;
1070				}
1071				if (visibleColumns[index]) {
1072					return new gantt.$keyboardNavigation.HeaderCell(index);
1073				} else {
1074					return null;
1075				}
1076			},
1077
1078			fromDomElement: function(el){
1079				var cellElement = domHelpers.locateClassName(el, "gantt_grid_head_cell");
1080				if(cellElement){
1081					var index = 0;
1082					while(cellElement && cellElement.previousSibling){
1083						cellElement = cellElement.previousSibling;
1084						index += 1;
1085					}
1086					return new gantt.$keyboardNavigation.HeaderCell(index);
1087				}else{
1088					return null;
1089				}
1090			},
1091
1092			getNode: function () {
1093				var cells = gantt.$grid_scale.childNodes;
1094				return cells[this.index];
1095			},
1096
1097
1098			keys: {
1099
1100				"left": function () {
1101					if (this.index > 0) {
1102						this.moveTo(new gantt.$keyboardNavigation.HeaderCell(this.index - 1));
1103					}
1104				},
1105				"right": function () {
1106					var columns = gantt.getGridColumns();
1107					if (this.index < columns.length - 1) {
1108						this.moveTo(new gantt.$keyboardNavigation.HeaderCell(this.index + 1));
1109					}
1110				},
1111				"down": function () {
1112					var taskRow;
1113					var rootLevel = gantt.getChildren(gantt.config.root_id);
1114					if (rootLevel[0]) {
1115						taskRow = rootLevel[0];
1116					}
1117					if (taskRow) {
1118						if (gantt.config.keyboard_navigation_cells) {
1119							this.moveTo(new gantt.$keyboardNavigation.TaskCell(taskRow, this.index));
1120						} else {
1121							this.moveTo(new gantt.$keyboardNavigation.TaskRow(taskRow));
1122						}
1123					}
1124				},
1125
1126				"end": function () {
1127					var columns = gantt.getGridColumns();
1128					this.moveTo(new gantt.$keyboardNavigation.HeaderCell(columns.length - 1));
1129				},
1130				"home": function () {
1131					this.moveTo(new gantt.$keyboardNavigation.HeaderCell(0));
1132				},
1133
1134
1135				// press header button
1136				"enter, space": function () {
1137					var node = document.activeElement;
1138					node.click();
1139				},
1140
1141				// add new task
1142				"ctrl+enter": function () {
1143					if (gantt.isReadonly(this)) {
1144						return;
1145					}
1146					gantt.createTask({}, this.taskId);
1147				}
1148			}
1149		}
1150	);
1151
1152	gantt.$keyboardNavigation.HeaderCell.prototype.bindAll(gantt.$keyboardNavigation.HeaderCell.prototype.keys);
1153
1154};
1155
1156/***/ }),
1157
1158/***/ "./sources/ext/keyboard_navigation/elements/nav_node.js":
1159/*!**************************************************************!*\
1160  !*** ./sources/ext/keyboard_navigation/elements/nav_node.js ***!
1161  \**************************************************************/
1162/*! no static exports found */
1163/***/ (function(module, exports) {
1164
1165module.exports = function(gantt) {
1166
1167	gantt.$keyboardNavigation.KeyNavNode = function () {
1168	};
1169
1170	gantt.$keyboardNavigation.KeyNavNode.prototype = gantt._compose(
1171		gantt.$keyboardNavigation.EventHandler,
1172		{
1173			isValid: function () {
1174				return true;
1175			},
1176			fallback: function () {
1177				return null;
1178			},
1179
1180			moveTo: function (element) {
1181				gantt.$keyboardNavigation.dispatcher.setActiveNode(element);
1182			},
1183
1184			compareTo: function (b) {
1185				// good enough comparison of two random objects
1186				if (!b) return false;
1187				for (var i in this) {
1188					if (!!this[i] != !!b[i]) return false;
1189
1190					var canStringifyThis = !!(this[i] && this[i].toString);
1191					var canStringifyThat = !!(b[i] && b[i].toString);
1192					if (canStringifyThat != canStringifyThis) return false;
1193					if (!(canStringifyThat && canStringifyThis)) {
1194						if (b[i] != this[i]) return false;
1195					} else {
1196						if (b[i].toString() != this[i].toString())
1197							return false;
1198					}
1199				}
1200				return true;
1201			},
1202
1203			getNode: function () {
1204			},
1205			focus: function () {
1206				var node = this.getNode();
1207				if(!node)
1208					return;
1209
1210				var eventFacade = gantt.$keyboardNavigation.facade;
1211
1212				if(eventFacade.callEvent("onBeforeFocus", [node]) === false){
1213					return;
1214				}
1215
1216				if (node) {
1217					node.setAttribute("tabindex", "-1");
1218					if(!node.$eventAttached){
1219						node.$eventAttached = true;
1220						gantt.event(node, "focus",function(e){
1221							e = e || event;
1222							e.preventDefault();
1223							return false;
1224						}, false);
1225					}
1226					//node.className += " gantt_focused";
1227					if (node.focus) node.focus();
1228
1229					eventFacade.callEvent("onFocus", [this.getNode()]);
1230				}
1231
1232			},
1233			blur: function () {
1234				var node = this.getNode();
1235				if (node) {
1236					var eventFacade = gantt.$keyboardNavigation.facade;
1237					eventFacade.callEvent("onBlur", [node]);
1238					node.setAttribute("tabindex", "-1");
1239					//node.className = (node.className || "").replace(/ ?gantt_focused/g, "");
1240				}
1241			}
1242		}
1243	);
1244
1245};
1246
1247/***/ }),
1248
1249/***/ "./sources/ext/keyboard_navigation/elements/task_cell.js":
1250/*!***************************************************************!*\
1251  !*** ./sources/ext/keyboard_navigation/elements/task_cell.js ***!
1252  \***************************************************************/
1253/*! no static exports found */
1254/***/ (function(module, exports, __webpack_require__) {
1255
1256module.exports = function(gantt) {
1257	var domHelpers = __webpack_require__(/*! ../../../utils/dom_helpers */ "./sources/utils/dom_helpers.js");
1258
1259	gantt.$keyboardNavigation.TaskCell = function (taskId, index) {
1260		if (!taskId) {
1261			var rootLevel = gantt.getChildren(gantt.config.root_id);
1262			if (rootLevel[0]) {
1263				taskId = rootLevel[0];
1264			}
1265		}
1266		this.taskId = taskId;
1267		this.columnIndex = index || 0;
1268		// provided task may not exist, in this case node will be detectes as invalid
1269		if (gantt.isTaskExists(this.taskId)) {
1270			this.index = gantt.getTaskIndex(this.taskId);
1271		}
1272	};
1273
1274	gantt.$keyboardNavigation.TaskCell.prototype = gantt._compose(
1275		gantt.$keyboardNavigation.TaskRow,
1276		{
1277			_handlers: null,
1278			isValid: function () {
1279
1280				return gantt.$keyboardNavigation.TaskRow.prototype.isValid.call(this) && !!gantt.getGridColumns()[this.columnIndex];
1281			},
1282			fallback: function () {
1283
1284				var node = gantt.$keyboardNavigation.TaskRow.prototype.fallback.call(this);
1285				var result = node;
1286				if (node instanceof gantt.$keyboardNavigation.TaskRow) {
1287					var visibleColumns = gantt.getGridColumns();
1288					var index = this.columnIndex;
1289					while (index >= 0) {
1290						if (visibleColumns[index])
1291							break;
1292						index--;
1293					}
1294					if (visibleColumns[index]) {
1295						result = new gantt.$keyboardNavigation.TaskCell(node.taskId, index);
1296					}
1297				}
1298
1299				return result;
1300			},
1301
1302			fromDomElement: function(el){
1303				if(!gantt.config.keyboard_navigation_cells){
1304					return null;
1305				}
1306
1307				var taskId = gantt.locate(el);
1308				if(gantt.isTaskExists(taskId)){
1309					var index = 0;
1310					var cellElement = domHelpers.locateAttribute(el, "data-column-index");
1311
1312					if(cellElement){
1313						index = cellElement.getAttribute("data-column-index")*1;
1314					}
1315
1316					return new gantt.$keyboardNavigation.TaskCell(taskId, index);
1317				}else{
1318					return null;
1319				}
1320			},
1321
1322			getNode: function () {
1323				if (gantt.isTaskExists(this.taskId) && gantt.isTaskVisible(this.taskId)) {
1324					if (gantt.config.show_grid) {
1325						var row = gantt.$grid.querySelector(".gantt_row[" + gantt.config.task_attribute + "='" + this.taskId + "']");
1326						if(!row)
1327							return null;
1328						return row.querySelector("[data-column-index='"+this.columnIndex+"']");
1329					} else {
1330						return gantt.getTaskNode(this.taskId);
1331					}
1332				}
1333			},
1334
1335			keys: {
1336				"up": function () {
1337
1338					var nextElement = null;
1339					var prevTask = gantt.getPrev(this.taskId);
1340					if (!prevTask) {
1341						nextElement = new gantt.$keyboardNavigation.HeaderCell(this.columnIndex);
1342					} else {
1343						nextElement = new gantt.$keyboardNavigation.TaskCell(prevTask, this.columnIndex);
1344					}
1345					this.moveTo(nextElement);
1346				},
1347				"down": function () {
1348					var nextTask = gantt.getNext(this.taskId);
1349					if (nextTask) {
1350						this.moveTo(new gantt.$keyboardNavigation.TaskCell(nextTask, this.columnIndex));
1351					}
1352				},
1353				"left": function () {
1354					if (this.columnIndex > 0) {
1355						this.moveTo(new gantt.$keyboardNavigation.TaskCell(this.taskId, this.columnIndex - 1));
1356					}
1357				},
1358				"right": function () {
1359					var columns = gantt.getGridColumns();
1360					if (this.columnIndex < columns.length - 1) {
1361						this.moveTo(new gantt.$keyboardNavigation.TaskCell(this.taskId, this.columnIndex + 1));
1362					}
1363				},
1364
1365				"end": function () {
1366					var columns = gantt.getGridColumns();
1367					this.moveTo(new gantt.$keyboardNavigation.TaskCell(this.taskId, columns.length - 1));
1368				},
1369				"home": function () {
1370					this.moveTo(new gantt.$keyboardNavigation.TaskCell(this.taskId, 0));
1371				},
1372				"pagedown": function () {
1373					if (gantt.getVisibleTaskCount()) {
1374						this.moveTo(new gantt.$keyboardNavigation.TaskCell(gantt.getTaskByIndex(gantt.getVisibleTaskCount() - 1).id, this.columnIndex));
1375					}
1376				},
1377				"pageup": function () {
1378					if (gantt.getVisibleTaskCount()) {
1379						this.moveTo(new gantt.$keyboardNavigation.TaskCell(gantt.getTaskByIndex(0).id, this.columnIndex));
1380					}
1381				}
1382			}
1383		}
1384	);
1385
1386
1387	gantt.$keyboardNavigation.TaskCell.prototype.bindAll(gantt.$keyboardNavigation.TaskRow.prototype.keys);
1388	gantt.$keyboardNavigation.TaskCell.prototype.bindAll(gantt.$keyboardNavigation.TaskCell.prototype.keys);
1389
1390};
1391
1392/***/ }),
1393
1394/***/ "./sources/ext/keyboard_navigation/elements/task_row.js":
1395/*!**************************************************************!*\
1396  !*** ./sources/ext/keyboard_navigation/elements/task_row.js ***!
1397  \**************************************************************/
1398/*! no static exports found */
1399/***/ (function(module, exports) {
1400
1401module.exports = function(gantt) {
1402
1403	gantt.$keyboardNavigation.TaskRow = function (taskId) {
1404		if (!taskId) {
1405			var rootLevel = gantt.getChildren(gantt.config.root_id);
1406			if (rootLevel[0]) {
1407				taskId = rootLevel[0];
1408			}
1409		}
1410		this.taskId = taskId;
1411		if (gantt.isTaskExists(this.taskId)) {
1412			this.index = gantt.getTaskIndex(this.taskId);
1413		}
1414	};
1415
1416	gantt.$keyboardNavigation.TaskRow.prototype = gantt._compose(
1417		gantt.$keyboardNavigation.KeyNavNode,
1418		{
1419			_handlers: null,
1420			isValid: function () {
1421				return gantt.isTaskExists(this.taskId) && (gantt.getTaskIndex(this.taskId) > -1);
1422			},
1423			fallback: function () {
1424				if (!gantt.getVisibleTaskCount()) {
1425					var header = new gantt.$keyboardNavigation.HeaderCell();
1426					if (!header.isValid()) return null;
1427					else return header;
1428				} else {
1429
1430					var nextIndex = -1;
1431					if (gantt.getTaskByIndex(this.index - 1)) {
1432						nextIndex = this.index - 1;
1433					} else if (gantt.getTaskByIndex(this.index + 1)) {
1434						nextIndex = this.index + 1;
1435					} else {
1436						var index = this.index;
1437						while (index >= 0) {
1438							if (gantt.getTaskByIndex(index)) {
1439								nextIndex = index;
1440								break;
1441							}
1442							index--;
1443						}
1444
1445					}
1446					if (nextIndex > -1) {
1447						return new gantt.$keyboardNavigation.TaskRow(gantt.getTaskByIndex(nextIndex).id);
1448					}
1449				}
1450			},
1451
1452			fromDomElement: function(el){
1453				if(gantt.config.keyboard_navigation_cells){
1454					return null;
1455				}
1456
1457				var taskId = gantt.locate(el);
1458				if(gantt.isTaskExists(taskId)){
1459					return new gantt.$keyboardNavigation.TaskRow(taskId);
1460				}else{
1461					return null;
1462				}
1463			},
1464
1465			getNode: function () {
1466				if (gantt.isTaskExists(this.taskId) && gantt.isTaskVisible(this.taskId)) {
1467					if (gantt.config.show_grid) {
1468						return gantt.$grid.querySelector(".gantt_row[" + gantt.config.task_attribute + "='" + this.taskId + "']");
1469					} else {
1470						return gantt.getTaskNode(this.taskId);
1471					}
1472				}
1473			},
1474
1475			focus: function (keptFocus) {
1476				if(!keptFocus) {
1477					var pos = gantt.getTaskPosition(gantt.getTask(this.taskId));
1478					var height = gantt.config.row_height;
1479					var scroll = gantt.getScrollState();
1480
1481					var viewWidth;
1482					if(gantt.$task){
1483						viewWidth = gantt.$task.offsetWidth;
1484					}else{
1485						viewWidth = scroll.inner_width;
1486					}
1487
1488					var viewHeight;
1489					if(gantt.$grid_data || gantt.$task_data){
1490						viewHeight = (gantt.$grid_data || gantt.$task_data).offsetHeight;
1491					}else{
1492						viewHeight = scroll.inner_height;
1493					}
1494
1495					if (pos.top < scroll.y || pos.top + height > (scroll.y + viewHeight)) {
1496
1497						gantt.scrollTo(null, pos.top - height * 5);
1498
1499					} else if (gantt.config.show_chart && (pos.left < scroll.x || pos.left > (scroll.x + viewWidth))) {
1500						gantt.scrollTo(pos.left - gantt.config.task_scroll_offset);
1501
1502					}
1503				}
1504
1505				gantt.$keyboardNavigation.KeyNavNode.prototype.focus.apply(this, [keptFocus]);
1506			},
1507
1508			keys: {
1509				"pagedown": function () {
1510					if (gantt.getVisibleTaskCount()) {
1511						this.moveTo(new gantt.$keyboardNavigation.TaskRow(gantt.getTaskByIndex(gantt.getVisibleTaskCount() - 1).id));
1512					}
1513				},
1514				"pageup": function () {
1515					if (gantt.getVisibleTaskCount()) {
1516						this.moveTo(new gantt.$keyboardNavigation.TaskRow(gantt.getTaskByIndex(0).id));
1517					}
1518				},
1519				"up": function () {
1520					var nextElement = null;
1521					var prevTask = gantt.getPrev(this.taskId);
1522					if (!prevTask) {
1523						nextElement = new gantt.$keyboardNavigation.HeaderCell();
1524					} else {
1525						nextElement = new gantt.$keyboardNavigation.TaskRow(prevTask);
1526					}
1527					this.moveTo(nextElement);
1528				},
1529				"down": function () {
1530					var nextTask = gantt.getNext(this.taskId);
1531					if (nextTask) {
1532						this.moveTo(new gantt.$keyboardNavigation.TaskRow(nextTask));
1533					}
1534				},
1535
1536				"shift+down": function(){
1537					if(gantt.hasChild(this.taskId) && !gantt.getTask(this.taskId).$open){
1538						gantt.open(this.taskId);
1539					}
1540				},
1541				"shift+up": function(){
1542					if(gantt.hasChild(this.taskId) && gantt.getTask(this.taskId).$open){
1543						gantt.close(this.taskId);
1544					}
1545				},
1546				"shift+right": function() {
1547					if (gantt.isReadonly(this)) {
1548						return;
1549					}
1550					var prevId = gantt.getPrevSibling(this.taskId);
1551					if(gantt.isTaskExists(prevId) && !gantt.isChildOf(this.taskId, prevId)){
1552						var parent = gantt.getTask(prevId);
1553						parent.$open = true;
1554						var result = gantt.moveTask(this.taskId, -1, prevId);
1555						if(result !== false)
1556							gantt.updateTask(this.taskId);
1557					}
1558				},
1559				"shift+left": function() {
1560					if (gantt.isReadonly(this)) {
1561						return;
1562					}
1563					var parent = gantt.getParent(this.taskId);
1564					if(gantt.isTaskExists(parent)){
1565						var result =  gantt.moveTask(this.taskId, gantt.getTaskIndex(parent) + 1, gantt.getParent(parent));
1566						if(result !== false)
1567							gantt.updateTask(this.taskId);
1568					}
1569				},
1570
1571				// select
1572				"space": function (e) {
1573					if (!gantt.isSelectedTask(this.taskId)) {
1574						gantt.selectTask(this.taskId);
1575					} else {
1576						gantt.unselectTask(this.taskId);
1577					}
1578				},
1579
1580				// collapse
1581				"ctrl+left": function (e) {
1582					gantt.close(this.taskId);
1583				},
1584				// expand
1585				"ctrl+right": function (e) {
1586					gantt.open(this.taskId);
1587				},
1588
1589				// delete task
1590				"delete": function (e) {
1591					if (gantt.isReadonly(this)) {
1592						return;
1593					}
1594					gantt.$click.buttons["delete"](this.taskId);
1595				},
1596
1597				// open lightbox
1598				"enter": function () {
1599					if (gantt.isReadonly(this)) {
1600						return;
1601					}
1602					gantt.showLightbox(this.taskId);
1603				},
1604
1605				// add subtask
1606				"ctrl+enter": function () {
1607					if (gantt.isReadonly(this)) {
1608						return;
1609					}
1610					gantt.createTask({}, this.taskId);
1611				}
1612			}
1613		}
1614	);
1615	gantt.$keyboardNavigation.TaskRow.prototype.bindAll(gantt.$keyboardNavigation.TaskRow.prototype.keys);
1616
1617};
1618
1619/***/ }),
1620
1621/***/ "./sources/ext/keyboard_navigation/modals.js":
1622/*!***************************************************!*\
1623  !*** ./sources/ext/keyboard_navigation/modals.js ***!
1624  \***************************************************/
1625/*! no static exports found */
1626/***/ (function(module, exports) {
1627
1628module.exports = function(gantt) {
1629
1630	(function () {
1631		var modalsStack = [];
1632
1633		function isModal() {
1634			return !!modalsStack.length;
1635		}
1636
1637		function afterPopup(box) {
1638			setTimeout(function () {
1639				if (!isModal())
1640					gantt.focus();
1641			}, 1);
1642		}
1643
1644		function startModal(box) {
1645			gantt.eventRemove(box, "keydown", trapFocus);
1646			gantt.event(box, "keydown", trapFocus);
1647			modalsStack.push(box);
1648			//gantt.$keyboardNavigation.dispatcher.disable();
1649		}
1650
1651		function endModal() {
1652			var box = modalsStack.pop();
1653			if (box) {
1654				gantt.eventRemove(box, "keydown", trapFocus);
1655			}
1656			afterPopup(box);
1657
1658		}
1659
1660
1661		function isTopModal(box) {
1662			return box == modalsStack[modalsStack.length - 1];
1663		}
1664
1665		function trapFocus(event) {
1666			var event = event || window.event;
1667			var target = event.currentTarget;
1668			if (!isTopModal(target)) return;
1669
1670			gantt.$keyboardNavigation.trapFocus(target, event);
1671		}
1672
1673		function traceLightbox() {
1674			startModal(gantt.getLightbox());
1675		}
1676
1677		gantt.attachEvent("onLightbox", traceLightbox);
1678		gantt.attachEvent("onAfterLightbox", endModal);
1679		gantt.attachEvent("onLightboxChange", function () {
1680			endModal();
1681			traceLightbox();
1682		});
1683
1684
1685		gantt.attachEvent("onAfterQuickInfo", function () {
1686			afterPopup();
1687		});
1688
1689		gantt.attachEvent("onMessagePopup", function (box) {
1690			saveFocus();
1691			startModal(box);
1692		});
1693		gantt.attachEvent("onAfterMessagePopup", function () {
1694			endModal();
1695			restoreFocus();
1696		});
1697
1698		var focusElement = null;
1699
1700		function saveFocus() {
1701			focusElement = document.activeElement;
1702		}
1703
1704		function restoreFocus() {
1705			setTimeout(function () {
1706				if (focusElement) {
1707					focusElement.focus();
1708					focusElement = null;
1709				}
1710			}, 1);
1711		}
1712
1713		gantt.$keyboardNavigation.isModal = isModal;
1714
1715
1716	})();
1717
1718};
1719
1720/***/ }),
1721
1722/***/ "./sources/utils/dom_helpers.js":
1723/*!**************************************!*\
1724  !*** ./sources/utils/dom_helpers.js ***!
1725  \**************************************/
1726/*! no static exports found */
1727/***/ (function(module, exports) {
1728
1729//returns position of html element on the page
1730function elementPosition(elem) {
1731	var top=0, left=0, right=0, bottom=0;
1732	if (elem.getBoundingClientRect) { //HTML5 method
1733		var box = elem.getBoundingClientRect();
1734		var body = document.body;
1735		var docElem = (document.documentElement ||
1736			document.body.parentNode ||
1737			document.body);
1738
1739		var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
1740		var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
1741		var clientTop = docElem.clientTop || body.clientTop || 0;
1742		var clientLeft = docElem.clientLeft || body.clientLeft || 0;
1743		top  = box.top +  scrollTop - clientTop;
1744		left = box.left + scrollLeft - clientLeft;
1745
1746		right = document.body.offsetWidth - box.right;
1747		bottom = document.body.offsetHeight - box.bottom;
1748	} else { //fallback to naive approach
1749		while(elem) {
1750			top = top + parseInt(elem.offsetTop,10);
1751			left = left + parseInt(elem.offsetLeft,10);
1752			elem = elem.offsetParent;
1753		}
1754
1755		right = document.body.offsetWidth - elem.offsetWidth - left;
1756		bottom = document.body.offsetHeight - elem.offsetHeight - top;
1757	}
1758	return { y: Math.round(top), x: Math.round(left), width:elem.offsetWidth, height:elem.offsetHeight, right: Math.round(right), bottom: Math.round(bottom) };
1759}
1760
1761function isVisible(node){
1762	var display = false,
1763		visibility = false;
1764	if(window.getComputedStyle){
1765		var style = window.getComputedStyle(node, null);
1766		display = style["display"];
1767		visibility = style["visibility"];
1768	}else if(node.currentStyle){
1769		display = node.currentStyle["display"];
1770		visibility = node.currentStyle["visibility"];
1771	}
1772	return (display != "none" && visibility != "hidden");
1773}
1774
1775function hasNonNegativeTabIndex(node){
1776	return !isNaN(node.getAttribute("tabindex")) && (node.getAttribute("tabindex")*1 >= 0);
1777}
1778
1779function hasHref(node){
1780	var canHaveHref = {"a": true, "area": true};
1781	if(canHaveHref[node.nodeName.loLowerCase()]){
1782		return !!node.getAttribute("href");
1783	}
1784	return true;
1785}
1786
1787function isEnabled(node){
1788	var canDisable = {"input":true, "select":true, "textarea":true, "button":true, "object":true};
1789	if(canDisable[node.nodeName.toLowerCase()]){
1790		return !node.hasAttribute("disabled");
1791	}
1792
1793	return true;
1794}
1795
1796function getFocusableNodes(root){
1797	var nodes = root.querySelectorAll([
1798		"a[href]",
1799		"area[href]",
1800		"input",
1801		"select",
1802		"textarea",
1803		"button",
1804		"iframe",
1805		"object",
1806		"embed",
1807		"[tabindex]",
1808		"[contenteditable]"
1809	].join(", "));
1810
1811	var nodesArray = Array.prototype.slice.call(nodes, 0);
1812	for(var i = 0; i < nodesArray.length; i++){
1813		var node = nodesArray[i];
1814		var isValid = (hasNonNegativeTabIndex(node)  || isEnabled(node) || hasHref(node)) && isVisible(node);
1815		if(!isValid){
1816			nodesArray.splice(i, 1);
1817			i--;
1818		}
1819	}
1820	return nodesArray;
1821}
1822
1823function getScrollSize(){
1824	var div = document.createElement("div");
1825	div.style.cssText="visibility:hidden;position:absolute;left:-1000px;width:100px;padding:0px;margin:0px;height:110px;min-height:100px;overflow-y:scroll;";
1826
1827	document.body.appendChild(div);
1828	var width = div.offsetWidth-div.clientWidth;
1829	document.body.removeChild(div);
1830
1831	return width;
1832}
1833
1834function getClassName(node){
1835	if(!node) return "";
1836
1837	var className = node.className || "";
1838	if(className.baseVal)//'className' exist but not a string - IE svg element in DOM
1839		className = className.baseVal;
1840
1841	if(!className.indexOf)
1842		className = "";
1843
1844	return _trimString(className);
1845}
1846
1847function addClassName(node, className){
1848	if (className && node.className.indexOf(className) === -1) {
1849		node.className += " " + className;
1850	}
1851}
1852
1853function removeClassName(node, name) {
1854	name = name.split(" ");
1855	for (var i = 0; i < name.length; i++) {
1856		var regEx = new RegExp("\\s?\\b" + name[i] + "\\b(?![-_.])", "");
1857		node.className = node.className.replace(regEx, "");
1858	}
1859}
1860
1861function hasClass(element, className){
1862	if ('classList' in element) {
1863		return element.classList.contains(className);
1864	} else {
1865		return new RegExp("\\b" + className + "\\b").test(element.className);
1866	}
1867}
1868
1869function toNode(node) {
1870	if (typeof node === "string") {
1871		return (document.getElementById(node) || document.querySelector(node) || document.body);
1872	}
1873	return node || document.body;
1874}
1875
1876var _slave = document.createElement("div");
1877function insert(node, newone) {
1878	_slave.innerHTML = newone;
1879	var child = _slave.firstChild;
1880	node.appendChild(child);
1881	return child;
1882}
1883
1884function remove(node) {
1885	if (node && node.parentNode) {
1886		node.parentNode.removeChild(node);
1887	}
1888}
1889
1890function getChildren(node, css) {
1891	var ch = node.childNodes;
1892	var len = ch.length;
1893	var out = [];
1894	for (var i = 0; i < len; i++) {
1895		var obj = ch[i];
1896		if (obj.className && obj.className.indexOf(css) !== -1) {
1897			out.push(obj);
1898		}
1899	}
1900	return out;
1901}
1902
1903function getTargetNode(e){
1904	var trg;
1905	if (e.tagName)
1906		trg = e;
1907	else {
1908		e=e||window.event;
1909		trg=e.target||e.srcElement;
1910	}
1911	return trg;
1912}
1913
1914function locateAttribute(e, attribute) {
1915	if(!attribute) return;
1916
1917	var trg = getTargetNode(e);
1918
1919	while (trg){
1920		if (trg.getAttribute){	//text nodes has not getAttribute
1921			var test = trg.getAttribute(attribute);
1922			if (test) return trg;
1923		}
1924		trg=trg.parentNode;
1925	}
1926	return null;
1927}
1928
1929function _trimString(str){
1930	var func = String.prototype.trim || function(){ return this.replace(/^\s+|\s+$/g, ""); };
1931	return func.apply(str);
1932}
1933
1934function locateClassName(e, classname, strict){
1935	var trg = getTargetNode(e);
1936	var css = "";
1937
1938	if(strict === undefined)
1939		strict = true;
1940
1941	while (trg){
1942		css = getClassName(trg);
1943		if(css){
1944			var ind = css.indexOf(classname);
1945			if (ind >= 0){
1946				if (!strict)
1947					return trg;
1948
1949				//check that we have exact match
1950				var left = (ind === 0) || (!_trimString(css.charAt(ind - 1)));
1951				var right = ((ind + classname.length >= css.length)) || (!_trimString(css.charAt(ind + classname.length)));
1952
1953				if (left && right)
1954					return trg;
1955			}
1956		}
1957		trg=trg.parentNode;
1958	}
1959	return null;
1960}
1961
1962/*
1963event position relatively to DOM element
1964 */
1965function getRelativeEventPosition(ev, node){
1966	var d = document.documentElement;
1967	var box = elementPosition(node);
1968
1969	return {
1970		x: ev.clientX + d.scrollLeft - d.clientLeft - box.x + node.scrollLeft,
1971		y: ev.clientY + d.scrollTop - d.clientTop - box.y + node.scrollTop
1972	};
1973}
1974
1975function isChildOf(child, parent){
1976	if(!child || !parent){
1977		return false;
1978	}
1979
1980	while(child && child != parent) {
1981		child = child.parentNode;
1982	}
1983
1984	return child === parent;
1985}
1986
1987function closest(element, selector){
1988	if(element.closest){
1989		return element.closest(selector);
1990	}else if(element.matches || element.msMatchesSelector || element.webkitMatchesSelector){
1991		var el = element;
1992		if (!document.documentElement.contains(el)) return null;
1993		do {
1994			var method = el.matches || el.msMatchesSelector || el.webkitMatchesSelector;
1995
1996			if (method.call(el, selector)) return el;
1997			el = el.parentElement || el.parentNode;
1998		} while (el !== null && el.nodeType === 1);
1999		return null;
2000	}else{
2001		// eslint-disable-next-line no-console
2002		console.error("Your browser is not supported");
2003		return null;
2004	}
2005}
2006
2007module.exports = {
2008	getNodePosition: elementPosition,
2009	getFocusableNodes: getFocusableNodes,
2010	getScrollSize: getScrollSize,
2011	getClassName: getClassName,
2012	addClassName: addClassName,
2013	removeClassName: removeClassName,
2014	insertNode: insert,
2015	removeNode: remove,
2016	getChildNodes: getChildren,
2017	toNode: toNode,
2018	locateClassName:locateClassName,
2019	locateAttribute: locateAttribute,
2020	getTargetNode: getTargetNode,
2021	getRelativeEventPosition: getRelativeEventPosition,
2022	isChildOf: isChildOf,
2023	hasClass: hasClass,
2024	closest: closest
2025};
2026
2027/***/ }),
2028
2029/***/ "./sources/utils/eventable.js":
2030/*!************************************!*\
2031  !*** ./sources/utils/eventable.js ***!
2032  \************************************/
2033/*! no static exports found */
2034/***/ (function(module, exports) {
2035
2036var EventHost = function(){
2037	this._connected = [];
2038	this._silent_mode = false;
2039};
2040
2041EventHost.prototype = {
2042	_silentStart: function() {
2043		this._silent_mode = true;
2044	},
2045	_silentEnd: function() {
2046		this._silent_mode = false;
2047	}
2048};
2049
2050var	createEventStorage = function(obj) {
2051	var dhx_catch = [];
2052	var z = function(){
2053		var res = true;
2054		for (var i = 0; i < dhx_catch.length; i++){
2055			if (dhx_catch[i]){
2056				var zr = dhx_catch[i].apply(obj, arguments);
2057				res=res&&zr;
2058			}
2059		}
2060		return res;
2061	};
2062	z.addEvent=function(ev){
2063		if (typeof (ev) == "function")
2064			return dhx_catch.push(ev)-1;
2065		return false;
2066	};
2067	z.removeEvent=function(id){
2068		dhx_catch[id]=null;
2069	};
2070	return z;
2071};
2072
2073function makeEventable(obj){
2074
2075	var eventHost = new EventHost();
2076	obj.attachEvent=function(name, catcher, callObj){
2077		name='ev_'+name.toLowerCase();
2078		if (!eventHost[name])
2079			eventHost[name] = createEventStorage(callObj||this);
2080
2081		return(name+':'+eventHost[name].addEvent(catcher)); //return ID (event name & event ID)
2082	};
2083	obj.attachAll = function(callback, callObj){
2084		this.attachEvent('listen_all', callback, callObj);
2085	};
2086
2087	obj.callEvent=function(name, arg0, callObj){
2088		if (eventHost._silent_mode) return true;
2089
2090		var handlerName = 'ev_'+name.toLowerCase();
2091
2092		if (eventHost['ev_listen_all']){
2093			eventHost['ev_listen_all'].apply(callObj || this, [name].concat(arg0));
2094		}
2095
2096		if (eventHost[handlerName])
2097			return eventHost[handlerName].apply(callObj || this, arg0);
2098		return true;
2099	};
2100	obj.checkEvent=function(name){
2101		return (!!eventHost['ev_'+name.toLowerCase()]);
2102	};
2103	obj.detachEvent=function(id){
2104		if (id){
2105			var list = id.split(':');//get EventName and ID
2106			var eventName = list[0];
2107			var eventId = list[1];
2108
2109			if(eventHost[eventName]){
2110				eventHost[eventName].removeEvent(eventId); //remove event
2111			}
2112		}
2113	};
2114	obj.detachAllEvents = function(){
2115		for (var name in eventHost){
2116			if (name.indexOf("ev_") === 0)
2117				delete eventHost[name];
2118		}
2119	};
2120
2121}
2122
2123module.exports = makeEventable;
2124
2125/***/ })
2126
2127/******/ });
2128});