Matthias Jentsch aec59d9941 Use current filter to highlight active rows instead of storing active rows in JS
Clean up selection code and move it into separate behavior and parse filter query to fetch selectable rows.

refs #9054
refs #9346
2015-06-29 18:48:42 +02:00

314 lines
9.5 KiB
JavaScript

/*! Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
/**
* Icinga utility functions
*/
(function(Icinga, $) {
'use strict';
Icinga.Utils = function (icinga) {
/**
* Utility functions may need access to their Icinga instance
*/
this.icinga = icinga;
/**
* We will use this to create an URL helper only once
*/
this.urlHelper = null;
};
Icinga.Utils.prototype = {
timeWithMs: function (now) {
if (typeof now === 'undefined') {
now = new Date();
}
var ms = now.getMilliseconds() + '';
while (ms.length < 3) {
ms = '0' + ms;
}
return now.toLocaleTimeString() + '.' + ms;
},
timeShort: function (now) {
if (typeof now === 'undefined') {
now = new Date();
}
return now.toLocaleTimeString().replace(/:\d{2}$/, '');
},
formatHHiiss: function (date) {
var hours = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
if (hours < 10) hours = '0' + hours;
if (minutes < 10) minutes = '0' + minutes;
if (seconds < 10) seconds = '0' + seconds;
return hours + ':' + minutes + ':' + seconds;
},
/**
* Format the given byte-value into a human-readable string
*
* @param {number} The amount of bytes to format
* @returns {string} The formatted string
*/
formatBytes: function (bytes) {
var log2 = Math.log(bytes) / Math.LN2;
var pot = Math.floor(log2 / 10);
var unit = (['b', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB'])[pot];
return ((bytes / Math.pow(1024, pot)).toFixed(2)) + ' ' + unit;
},
/**
* Return whether the given element is visible in the users view
*
* Borrowed from: http://stackoverflow.com/q/487073
*
* @param {selector} element The element to check
* @returns {Boolean}
*/
isVisible: function(element)
{
var $element = $(element);
if (!$element.length) {
return false;
}
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $element.offset().top;
var elemBottom = elemTop + $element.height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom) &&
(elemBottom <= docViewBottom) && (elemTop >= docViewTop));
},
getUrlHelper: function () {
if (this.urlHelper === null) {
this.urlHelper = document.createElement('a');
}
return this.urlHelper;
},
/**
* Parse a given Url and return an object
*/
parseUrl: function (url) {
var a = this.getUrlHelper();
a.href = url;
var result = {
source : url,
protocol: a.protocol.replace(':', ''),
host : a.hostname,
port : a.port,
query : a.search,
file : (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
hash : a.hash.replace('#',''),
path : a.pathname.replace(/^([^\/])/,'/$1'),
relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],
segments: a.pathname.replace(/^\//,'').split('/'),
params : this.parseParams(a)
};
a = null;
return result;
},
// Local URLs only
addUrlParams: function (url, params) {
var parts = this.parseUrl(url),
result = parts.path,
newparams = parts.params;
$.each(params, function (key, value) {
// We overwrite existing params
newparams[key] = value;
});
if (Object.keys(newparams).length > 0) {
var queryString = '?';
$.each(newparams, function (key, value) {
if (queryString !== '?') {
queryString += '&';
}
queryString += encodeURIComponent(key) + '=' + encodeURIComponent(value);
});
result += queryString;
}
if (parts.hash.length > 0) {
result += '#' + parts.hash;
}
return result;
},
// Local URLs only
removeUrlParams: function (url, params) {
var parts = this.parseUrl(url),
result = parts.path,
newparams = parts.params;
$.each(params, function (idx, key) {
delete newparams[key];
});
if (Object.keys(newparams).length > 0) {
var queryString = '?';
$.each(newparams, function (key, value) {
if (queryString !== '?') {
queryString += '&';
}
queryString += encodeURIComponent(key) + '=' + encodeURIComponent(value);
});
result += queryString;
}
if (parts.hash.length > 0) {
result += '#' + parts.hash;
}
return result;
},
/**
* Parse url params
*/
parseParams: function (a) {
var params = {},
segment = a.search.replace(/^\?/,'').split('&'),
len = segment.length,
i = 0,
s;
for (; i < len; i++) {
if (!segment[i]) {
continue;
}
s = segment[i].split('=');
params[s[0]] = decodeURIComponent(s[1]);
}
return params;
},
/**
* Check whether two HTMLElements overlap
*
* @param a {HTMLElement}
* @param b {HTMLElement}
*
* @returns {Boolean} whether elements overlap, will return false when one
* element is not in the DOM
*/
elementsOverlap: function(a, b)
{
// a bounds
var aoff = $(a).offset();
if (!aoff) {
return false;
}
var at = aoff.top;
var ah = a.offsetHeight || (a.getBBox && a.getBBox().height);
var al = aoff.left;
var aw = a.offsetWidth || (a.getBBox && a.getBBox().width);
// b bounds
var boff = $(b).offset();
if (!boff) {
return false;
}
var bt = boff.top;
var bh = b.offsetHeight || (b.getBBox && b.getBBox().height);
var bl = boff.left;
var bw = b.offsetWidth || (b.getBBox && b.getBBox().width);
return !(at > (bt + bh) || bt > (at + ah)) && !(bl > (al + aw) || al > (bl + bw));
},
/**
* Create a selector that can be used to fetch the element the same position in the DOM-Tree
*
* Create the path to the given element in the DOM-Tree, comparable to an X-Path. Climb the
* DOM tree upwards until an element with an unique ID is found, this id is used as the anchor,
* all other elements will be addressed by their position in the parent.
*
* @param {HTMLElement} el The element to extract the path for.
*
* @returns {Array} The path of the element, that can be passed to getElementByPath
*/
getDomPath: function (el) {
if (! el) {
return [];
}
if (el.id !== '') {
return ['#' + el.id];
}
if (el === document.body) {
return ['body'];
}
var siblings = el.parentNode.childNodes;
var index = 0;
for (var i = 0; i < siblings.length; i ++) {
if (siblings[i].nodeType === 1) {
index ++;
}
if (siblings[i] === el) {
var p = this.getDomPath(el.parentNode);
p.push(':nth-child(' + (index) + ')');
return p;
}
}
},
/**
* Climbs up the given dom path and returns the element
*
* This is the counterpart
*
* @param path {Array} The selector
* @returns {HTMLElement} The corresponding element
*/
getElementByDomPath: function (path) {
var $element;
$.each(path, function (i, selector) {
if (! $element) {
$element = $(selector);
} else {
$element = $element.children(selector).first();
if (! $element[0]) {
return false;
}
}
});
return $element[0];
},
objectKeys: Object.keys || function (obj) {
var keys = [];
$.each(obj, function (key) {
keys.push(key);
});
return keys;
},
/**
* Cleanup
*/
destroy: function () {
this.urlHelper = null;
this.icinga = null;
}
};
}(Icinga, jQuery));