charts/src/js/utils/dom.js
2018-06-06 06:26:42 +05:30

152 lines
3.6 KiB
JavaScript

export function $(expr, con) {
return typeof expr === "string"? (con || document).querySelector(expr) : expr || null;
}
export function findNodeIndex(node)
{
var i = 0;
while (node.previousSibling) {
node = node.previousSibling;
i++;
}
return i;
}
$.create = (tag, o) => {
var element = document.createElement(tag);
for (var i in o) {
var val = o[i];
if (i === "inside") {
$(val).appendChild(element);
}
else if (i === "around") {
var ref = $(val);
ref.parentNode.insertBefore(element, ref);
element.appendChild(ref);
} else if (i === "onClick" ) {
element.addEventListener('click', val);
} else if (i === "onInput" ) {
element.addEventListener('input', function(e) {
val(element.value);
});
} else if (i === "onChange" ) {
element.addEventListener('change', function(e) {
val(element.value);
});
} else if (i === "styles") {
if(typeof val === "object") {
Object.keys(val).map(prop => {
element.style[prop] = val[prop];
});
}
} else if (i in element ) {
element[i] = val;
}
else {
element.setAttribute(i, val);
}
}
return element;
};
export function getOffset(element) {
let rect = element.getBoundingClientRect();
return {
// https://stackoverflow.com/a/7436602/6495043
// rect.top varies with scroll, so we add whatever has been
// scrolled to it to get absolute distance from actual page top
top: rect.top + (document.documentElement.scrollTop || document.body.scrollTop),
left: rect.left + (document.documentElement.scrollLeft || document.body.scrollLeft)
};
}
export function isElementInViewport(el) {
// Although straightforward: https://stackoverflow.com/a/7557433/6495043
var rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
);
}
export function getElementContentWidth(element) {
var styles = window.getComputedStyle(element);
var padding = parseFloat(styles.paddingLeft) +
parseFloat(styles.paddingRight);
return element.clientWidth - padding;
}
export function bind(element, o){
if (element) {
for (var event in o) {
var callback = o[event];
event.split(/\s+/).forEach(function (event) {
element.addEventListener(event, callback);
});
}
}
}
export function unbind(element, o){
if (element) {
for (var event in o) {
var callback = o[event];
event.split(/\s+/).forEach(function(event) {
element.removeEventListener(event, callback);
});
}
}
}
export function fire(target, type, properties) {
var evt = document.createEvent("HTMLEvents");
evt.initEvent(type, true, true );
for (var j in properties) {
evt[j] = properties[j];
}
return target.dispatchEvent(evt);
}
// https://css-tricks.com/snippets/javascript/loop-queryselectorall-matches/
export function forEachNode(nodeList, callback, scope) {
if(!nodeList) return;
for (var i = 0; i < nodeList.length; i++) {
callback.call(scope, nodeList[i], i);
}
}
export function activate($parent, $child, commonSelector, activeClass='active', index = -1) {
let $children = $parent.querySelectorAll(`${commonSelector}.${activeClass}`);
if (typeof $child === 'string') {
$child = $parent.querySelector($child);
}
this.forEachNode($children, (node, i) => {
if(index >= 0 && i <= index) return;
node.classList.remove(activeClass);
})
$child.classList.add(activeClass);
}
export function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}