Introduce a new script file luci.js which is included by default and intended to be the common location of functions currently scattered in cbi.js and xhr.js. The luci.js file provides a LuCI() class which - among other things - implements helpers to construct URL paths and making HTTP requests. A singleton instance of the class is instantiated as window.L upon load and preset with the necessary environment information. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
165 lines
4.1 KiB
JavaScript
165 lines
4.1 KiB
JavaScript
(function(window, document) {
|
|
var modalDiv = null,
|
|
tooltipDiv = null,
|
|
tooltipTimeout = null;
|
|
|
|
LuCI.prototype = {
|
|
/* URL construction helpers */
|
|
path: function(prefix, parts) {
|
|
var url = [ prefix || '' ];
|
|
|
|
for (var i = 0; i < parts.length; i++)
|
|
if (/^(?:[a-zA-Z0-9_.%,;-]+\/)*[a-zA-Z0-9_.%,;-]+$/.test(parts[i]))
|
|
url.push('/', parts[i]);
|
|
|
|
if (url.length === 1)
|
|
url.push('/');
|
|
|
|
return url.join('');
|
|
},
|
|
|
|
url: function() {
|
|
return this.path(this.env.scriptname, arguments);
|
|
},
|
|
|
|
resource: function() {
|
|
return this.path(this.env.resource, arguments);
|
|
},
|
|
|
|
location: function() {
|
|
return this.path(this.env.scriptname, this.env.requestpath);
|
|
},
|
|
|
|
|
|
/* HTTP resource fetching */
|
|
get: function(url, args, cb) {
|
|
return this.poll(0, url, args, cb, false);
|
|
},
|
|
|
|
post: function(url, args, cb) {
|
|
return this.poll(0, url, args, cb, true);
|
|
},
|
|
|
|
poll: function(interval, url, args, cb, post) {
|
|
var data = post ? { token: this.env.token } : null;
|
|
|
|
if (!/^(?:\/|\S+:\/\/)/.test(url))
|
|
url = this.url(url);
|
|
|
|
if (typeof(args) === 'object' && args !== null) {
|
|
data = data || {};
|
|
|
|
for (var key in args)
|
|
if (args.hasOwnProperty(key))
|
|
switch (typeof(args[key])) {
|
|
case 'string':
|
|
case 'number':
|
|
case 'boolean':
|
|
data[key] = args[key];
|
|
break;
|
|
|
|
case 'object':
|
|
data[key] = JSON.stringify(args[key]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (interval > 0)
|
|
return XHR.poll(interval, url, data, cb, post);
|
|
else if (post)
|
|
return XHR.post(url, data, cb);
|
|
else
|
|
return XHR.get(url, data, cb);
|
|
},
|
|
|
|
|
|
/* Modal dialog */
|
|
showModal: function(title, children) {
|
|
var dlg = modalDiv.firstElementChild;
|
|
|
|
while (dlg.firstChild)
|
|
dlg.removeChild(dlg.firstChild);
|
|
|
|
dlg.setAttribute('class', 'modal');
|
|
dlg.appendChild(E('h4', {}, title));
|
|
|
|
if (!Array.isArray(children))
|
|
children = [ children ];
|
|
|
|
for (var i = 0; i < children.length; i++)
|
|
if (isElem(children[i]))
|
|
dlg.appendChild(children[i]);
|
|
else
|
|
dlg.appendChild(document.createTextNode('' + children[i]));
|
|
|
|
document.body.classList.add('modal-overlay-active');
|
|
|
|
return dlg;
|
|
},
|
|
|
|
hideModal: function() {
|
|
document.body.classList.remove('modal-overlay-active');
|
|
},
|
|
|
|
|
|
/* Tooltip */
|
|
showTooltip: function(ev) {
|
|
var target = findParent(ev.target, '[data-tooltip]');
|
|
|
|
if (!target)
|
|
return;
|
|
|
|
if (tooltipTimeout !== null) {
|
|
window.clearTimeout(tooltipTimeout);
|
|
tooltipTimeout = null;
|
|
}
|
|
|
|
var rect = target.getBoundingClientRect(),
|
|
x = rect.left + window.pageXOffset,
|
|
y = rect.top + rect.height + window.pageYOffset;
|
|
|
|
tooltipDiv.className = 'cbi-tooltip';
|
|
tooltipDiv.innerHTML = '▲ ';
|
|
tooltipDiv.firstChild.data += target.getAttribute('data-tooltip');
|
|
|
|
if (target.hasAttribute('data-tooltip-style'))
|
|
tooltipDiv.classList.add(target.getAttribute('data-tooltip-style'));
|
|
|
|
if ((y + tooltipDiv.offsetHeight) > (window.innerHeight + window.pageYOffset)) {
|
|
y -= (tooltipDiv.offsetHeight + target.offsetHeight);
|
|
tooltipDiv.firstChild.data = '▼ ' + tooltipDiv.firstChild.data.substr(2);
|
|
}
|
|
|
|
tooltipDiv.style.top = y + 'px';
|
|
tooltipDiv.style.left = x + 'px';
|
|
tooltipDiv.style.opacity = 1;
|
|
},
|
|
|
|
hideTooltip: function(ev) {
|
|
if (ev.target === tooltipDiv || ev.relatedTarget === tooltipDiv)
|
|
return;
|
|
|
|
if (tooltipTimeout !== null) {
|
|
window.clearTimeout(tooltipTimeout);
|
|
tooltipTimeout = null;
|
|
}
|
|
|
|
tooltipDiv.style.opacity = 0;
|
|
tooltipTimeout = window.setTimeout(function() { tooltipDiv.removeAttribute('style'); }, 250);
|
|
}
|
|
};
|
|
|
|
function LuCI(env) {
|
|
this.env = env;
|
|
|
|
modalDiv = document.body.appendChild(E('div', { id: 'modal_overlay' }, E('div', { class: 'modal' })));
|
|
tooltipDiv = document.body.appendChild(E('div', { 'class': 'cbi-tooltip' }));
|
|
|
|
document.addEventListener('mouseover', this.showTooltip.bind(this), true);
|
|
document.addEventListener('mouseout', this.hideTooltip.bind(this), true);
|
|
document.addEventListener('focus', this.showTooltip.bind(this), true);
|
|
document.addEventListener('blur', this.hideTooltip.bind(this), true);
|
|
}
|
|
|
|
window.LuCI = LuCI;
|
|
})(window, document);
|