web-apps/apps/common/main/lib/component/FocusManager.js

193 lines
7.4 KiB
JavaScript
Raw Normal View History

/*
*
* (c) Copyright Ascensio System SIA 2010-2020
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
/**
* FocusManager.js
*
* Created by Julia Radzhabova on 24.09.2020
* Copyright (c) 2020 Ascensio System SIA. All rights reserved.
*
*/
if (Common === undefined)
var Common = {};
if (Common.UI === undefined) {
Common.UI = {};
}
2020-10-13 13:17:03 +00:00
Common.UI.FocusManager = new(function() {
2020-10-09 08:59:57 +00:00
var _tabindex = 1,
2020-10-13 10:29:07 +00:00
_windows = [],
_count = 0;
2020-10-09 08:59:57 +00:00
var register = function(fields) {
var arr = [];
if (!fields.forEach) {
fields = [fields];
}
fields.forEach(function(field) {
if (field) {
2021-04-13 07:28:06 +00:00
var item = {};
if (field.cmp && typeof field.selector == 'string')
item = field;
else {
item.cmp = field;
if (field instanceof Common.UI.ListView)
item.selector = '.listview';
else if (field instanceof Common.UI.CheckBox)
item.selector = '.checkbox-indeterminate';
2021-04-14 08:01:41 +00:00
else if (field instanceof Common.UI.RadioBox)
item.selector = '.radiobox';
2021-04-13 22:30:54 +00:00
else if (field instanceof Common.UI.TreeView)
item.selector = '.treeview';
2021-04-14 22:02:11 +00:00
else if (field instanceof Common.UI.Button)
item.selector = 'button';
2021-04-13 07:28:06 +00:00
else
item.selector = '.form-control';
}
item.el = (item.cmp.$el || $(item.cmp.el || item.cmp)).find(item.selector).addBack().filter(item.selector);
item.el && item.el.attr && (item.cmp.setTabIndex ? item.cmp.setTabIndex(_tabindex) : item.el.attr('tabindex', _tabindex.toString()));
2020-10-09 08:59:57 +00:00
arr.push(item);
}
});
return arr;
};
var addTraps = function(current) {
if (!current || current.traps || !current.fields || current.fields.length<1) return;
var trapFirst = $('<span aria-hidden="true" tabindex="' + _tabindex + '"></span>');
trapFirst.on('focus', function() {
if (current.hidden) return;
var fields = current.fields;
2021-01-16 19:57:39 +00:00
for (var i=fields.length-1; i>=0; i--) {
2020-10-09 08:59:57 +00:00
var field = fields[i];
if ((field.cmp.isVisible ? field.cmp.isVisible() : field.cmp.is(':visible')) && !(field.cmp.isDisabled && field.cmp.isDisabled())) {
var el = (field.selector) ? (field.cmp.$el || $(field.cmp.el || field.cmp)).find(field.selector).addBack().filter(field.selector) : field.el;
2021-01-25 13:42:52 +00:00
el && setTimeout(function(){ el.focus(); }, 10);
2020-10-09 08:59:57 +00:00
break;
}
}
});
current.parent.$window.prepend(trapFirst);
var trapLast = $('<span aria-hidden="true" tabindex="' + (_tabindex+1) + '"></span>');
trapLast.on('focus', function() {
if (current.hidden) return;
var fields = current.fields;
2021-01-16 19:57:39 +00:00
for (var i=0; i<fields.length; i++) {
2020-10-09 08:59:57 +00:00
var field = fields[i];
if ((field.cmp.isVisible ? field.cmp.isVisible() : field.cmp.is(':visible')) && !(field.cmp.isDisabled && field.cmp.isDisabled())) {
var el = (field.selector) ? (field.cmp.$el || $(field.cmp.el || field.cmp)).find(field.selector).addBack().filter(field.selector) : field.el;
2021-01-25 13:42:52 +00:00
el && setTimeout(function(){ el.focus(); }, 10);
2020-10-09 08:59:57 +00:00
break;
}
}
});
current.parent.$window.append(trapLast);
current.traps = [trapFirst, trapLast];
};
2020-10-13 10:29:07 +00:00
var updateTabIndexes = function(increment) {
var step = increment ? 1 : -1;
for (var cid in _windows) {
if (_windows.hasOwnProperty(cid)) {
var item = _windows[cid];
if (item && item.index < _count-1 && item.traps)
item.traps[1].attr('tabindex', (parseInt(item.traps[1].attr('tabindex')) + step).toString());
}
}
};
2020-10-09 08:59:57 +00:00
var _add = function(e, fields) {
if (e && e.cid) {
if (_windows[e.cid]) {
2020-10-13 11:31:23 +00:00
_windows[e.cid].fields = (_windows[e.cid].fields || []).concat(register(fields));
2020-10-09 08:59:57 +00:00
} else {
_windows[e.cid] = {
parent: e,
fields: register(fields),
2020-10-13 10:29:07 +00:00
hidden: false,
index: _count++
2020-10-09 08:59:57 +00:00
};
}
addTraps(_windows[e.cid]);
}
};
2020-11-06 09:00:43 +00:00
var _init = function() {
Common.NotificationCenter.on({
'modal:show': function(e){
if (e && e.cid) {
if (_windows[e.cid]) {
_windows[e.cid].hidden = false;
} else {
_windows[e.cid] = {
parent: e,
hidden: false,
index: _count++
};
updateTabIndexes(true);
}
}
},
'window:show': function(e){
if (e && e.cid && _windows[e.cid] && !_windows[e.cid].fields) {
_windows[e.cid].fields = register(e.getFocusedComponents());
addTraps(_windows[e.cid]);
2020-10-09 08:59:57 +00:00
}
2020-10-21 08:10:11 +00:00
2020-11-06 09:00:43 +00:00
var el = e ? e.getDefaultFocusableComponent() : null;
el && setTimeout(function(){ el.focus(); }, 100);
},
'modal:close': function(e, last) {
if (e && e.cid && _windows[e.cid]) {
updateTabIndexes(false);
delete _windows[e.cid];
_count--;
}
},
'modal:hide': function(e, last) {
if (e && e.cid && _windows[e.cid]) {
_windows[e.cid].hidden = true;
}
2020-10-09 08:59:57 +00:00
}
2020-11-06 09:00:43 +00:00
});
};
2020-10-09 08:59:57 +00:00
return {
2020-11-06 09:00:43 +00:00
init: _init,
2020-10-09 08:59:57 +00:00
add: _add
}
})();