/*
* linotype
* https://github.com/typesettin/linotype
* @author yaw joseph etse
* Copyright (c) 2014 Typesettin. All rights reserved.
*/
'use strict';
var classie = require('classie');
// extend = require('util-extend'),
// events = require('events'),
// util = require('util');
/**
* A module that adds simple dom utility functionality.
* @author yaw joseph etse
* @constructor
*/
var domhelper = {
/**
* returns the highest zindex
* @param {string} selector - query selector
* @return {number} highest z-index
* @public
*/
getHighIndex: function(selector){
if (!selector) {
selector = "*";
}
var elements = document.querySelectorAll(selector),
i = 0,
e, s,
max = elements.length,
found = [];
for (; i < max; i += 1) {
e = elements[i].style.zIndex;
s = elements[i].style.position;
if (e && s !== "static") {
found.push(parseInt(e, 10));
}
}
return found.length ? Math.max.apply(null, found) : 0;
},
/**
* toggles class across nodelist/elementcollection
* @param {object} elementCollection - html dom element
* @param {object} element - html dom element
* @param {string} name of class!
* @public
*/
removeAllClassAndToggle: function(element,elementCollection,toggleClass){
//updating the active class
for(var h =0; h <elementCollection.length; h++){
classie.removeClass(elementCollection[h],toggleClass);
}
classie.addClass(element,toggleClass);
},
/**
* removes element from dom
* @param {object} elementCollection - html dom element
* @public
*/
removeElement: function(element){
//updating the active class
element.parentNode.removeChild(element);
},
/**
* converts idnex of node in nodelist
* @param {object} nodelist - html dom element
* @param {object} element - html dom element
* @return {number} index of element in nodelist
* @method
*/
nodeIndexOfNodeList: function(nodelist,element){
return domhelper.nodelistToArray(nodelist,true).indexOf(element.outerHTML);
},
/**
* converts nodelists to arrays
* @param {node} nl - html dom element
* @return { array} array of html nodes
* @method
*/
nodelistToArray: function(nl,useStrings){
var arr = [];
for (var i = 0, ref = arr.length = nl.length; i < ref; i++) {
arr[i] = (useStrings) ? nl[i].outerHTML : nl[i];
}
return arr;
},
/**
* Returns cloaset DOM element.
* @param {node} element - html dom element
* @return {node} - closet node element
* @method
*/
closetElement: function(element){
if(typeof element.length === 'number'){
return undefined;
}
var matches = domhelper.nodelistToArray(document.querySelectorAll(element.nodeName+'.'+element.className.trim().split(" ").join("."))),
cleanMatches = [];
// console.log("matches",matches.length,matches);
for (var x =0; x < matches.length; x++){
// console.log('x',x,'element',element,'matches[x]',matches[x],'isEqualNode',matches[x].isEqualNode(element),'compareDocumentPosition',element.compareDocumentPosition(matches[x]));
if(element.compareDocumentPosition(matches[x])<4 && !matches[x].isEqualNode(element)){
cleanMatches.push(matches[x]);
}
}
function compareNumbers(a, b) {
return a.compareDocumentPosition( b ) - b.compareDocumentPosition( a );
}
// console.log("matches cleaned",cleanMatches.length,cleanMatches);
// console.log("matches sorted",cleanMatches.sort(compareNumbers));
return cleanMatches[0];
},
/**
* Hides DOM elements.
* @method
* @param {node} element - html dom element
*/
elementHideCss: function(element){
element.style.display="none";
},
/**
* Shows DOM elements.
* @method
* @param {node} element - html dom element
*/
elementShowCss: function(element){
element.setAttribute('style',element.getAttribute('style').replace("display: none;"));
},
/**
* Wraps inner elements
* @method
* @param {node} element - html dom element
* @param {node} innerElement - element to wrap html dom element
*/
elementContentWrapInner: function(element,innerElement){
var wrapper = element,
w = innerElement,
len = element.childElementCount,
wrapper_clone = wrapper.cloneNode(true);
wrapper.innerHTML='';
wrapper.appendChild(w);
var newFirstChild = wrapper.firstChild;
newFirstChild.innerHTML=wrapper_clone.innerHTML;
},
/**
* Wraps element with wrapper
* @method
* @param {node} element - html dom element
* @param {node} wrapperElement - element to wrap html dom element
*/
elementWrap: function(element,wrapperElement){
var elementParent =element.parentNode,
element_clone = element.cloneNode(true);
elementParent.replaceChild(wrapperElement,element);
wrapperElement.appendChild(element);
},
/**
* get scroll position of element
* @method
* @param {node} element - html dom element
* @return {number} position of scroll
*/
getScrollTop: function(element){
// console.log(typeof element);
if(element === window && typeof window.pageYOffset!== 'undefined'){
//most browsers except IE before #9
return window.pageYOffset;
}
else if(typeof element ==="object"){
return element.scrollTop;
}
else {
var B= document.body; //IE 'quirks'
var D= document.documentElement; //IE with doctype
D= (D.clientHeight)? D: B;
return D.scrollTop;
}
},
/**
* get scroll position of element
* @method
* @param {node} element - html dom element
* @return {object} position element
*/
getPosition: function(element) {
var xPosition = 0;
var yPosition = 0;
while(element) {
xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
element = element.offsetParent;
}
return { x: xPosition, y: yPosition, left: xPosition, top: yPosition };
},
/**
* get element selector
* @method
* @param {node} element - html dom element
* @return {string} query selector string
*/
getElementSelector: function(element){
var tagSelector = (element.tagName) ? element.tagName:'',
idSelector = (element.id) ? '#'+element.id+'':'',
classSelector='';
if(element.classList){
for(var x=0; x < element.classList.length; x++){
classSelector+='.'+element.classList[x]+"";
}
}
return tagSelector+idSelector+classSelector;
},
/**
* get parent element
* @method
* @param {node} element - html dom element
* @param {string} selector - selector
* @param {string} selectorType - selector type (id or class)
*/
getParentElement: function(element,selector,selectorType){
if(element.tagName==='BODY' || element.tagName==='HTML' || selector==='body' || selector==='html' || selector===undefined){
// console.log('body selected');
return undefined;
}
else if( (selectorType==='id' && element.parentNode.id === selector) || element.parentNode.className.match(new RegExp(selector,'g'))){
// console.log("parent node");
return element.parentNode;
//new RegExp(pattern,modifiers)
}
else {
// console.log("look up higher");
return domhelper.getParentElement(element.parentNode,selector,selectorType);
}
},
getPreviousElements: function(element,returnArray){
if(element.previousElementSibling){
returnArray.push(element.previousElementSibling);
return domhelper.getPreviousElements(element.previousElementSibling,returnArray);
}
else{
return returnArray;
}
},
getNextElements: function(element,returnArray){
if(element.nextElementSibling){
returnArray.push(element.nextElementSibling);
return domhelper.getNextElements(element.nextElementSibling,returnArray);
}
else{
return returnArray;
}
},
insertAllBefore: function(element,elementsToInsert){
var parentElement = element.parentNode;
// console.log("parentElement",parentElement,"element",element,"elementsToInsert",elementsToInsert);
if(elementsToInsert.length){
for(var x =0; x<elementsToInsert.length; x++){
// console.log(x,"elementsToInsert[x]",elementsToInsert[x])
parentElement.insertBefore(elementsToInsert[x],element);
}
}
else{
parentElement.insertBefore(elementsToInsert,element);
}
},
insertAllAfter: function(element,elementsToInsert){
var parentElement = element.parentNode;
var nextSibling = element.nextSibling;
// console.log("parentElement",parentElement,"element",element,"elementsToInsert",elementsToInsert);
if(elementsToInsert.length){
for(var x =0; x<elementsToInsert.length; x++){
// console.log(x,"elementsToInsert[x]",elementsToInsert[x])
// elementsToInsert[x].style.background="green";
parentElement.insertBefore(elementsToInsert[x],nextSibling);
}
}
else{
parentElement.insertBefore(elementsToInsert,nextSibling);
}
},
unwrapElement: function(element){
var parentNodeElem = element.parentNode;
if(parentNodeElem.nodeName !== "BODY"){
var parentParentNodeElem = parentNodeElem.parentNode;
parentParentNodeElem.innerHTML='';
parentParentNodeElem.appendChild(element);
}
},
onWindowLoaded: function(callback){
var readyStateCheckInterval = setInterval(function() {
if (document.readyState === "complete") {
callback();
clearInterval(readyStateCheckInterval);
}
}, 10);
}
};
module.exports = domhelper;
// If there is a window object, that at least has a document property,
// define linotype
if ( typeof window === "object" && typeof window.document === "object" ) {
window.domhelper = domhelper;
}