var ZPIN = ZPIN || {}; /** * Utils are put her, like wrapper functions. */ ZPIN.Utils = { /** * Returns an HTMLElement which has the given ID * * This function can also take an array of strings and return an array of * HTML elements * * @param {String | Array} element The ID as a string * @return {HTMLElement | Array} HTML element, or elements */ get: function(element) { var elements = [], i; if ( element === undefined ) { return false; } // Checks to see if we have a string if ( (typeof element) === "string" ) { return document.getElementById(element); } // Check if we have an element of type array if ( element.constructor.toString().indexOf('Array') > -1 && elements.length ) { for ( i = 0; i < element.length; i++ ) { elements.push(this.get(element[i])); } } if ( element ) { return element; } return null; }, /** * This method creates new instances of an object * * @param {Object} o Old objekct * @return {Object} New object */ object: function(o) { function F() {} F.prototype = o; return new F(); }, /** * Generates and returns a XMLHttpRequest object * * @return {XMLHttpRequest | null} New XMLHttpRequest object, or null if no * browser supprt */ getXmlHttpRequestObject: function() { /** * Microsoft Acitve X controllers */ var msxml = [ 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP' ], i; try { return new window.XMLHttpRequest(); } catch (e) { // We may be in a IE browser for ( i = 0; i < msxml.length; i++ ) { try { return new ActiveXObject(msxml[i]); } catch(e) {} } } return null; }, /** * Binds a function to an object and makes sure that it is * executed under that scope * * To use, bind it to function with: * Function.prototype.bind = ZPIN.Utils.bind; * * @param {Object} object The object you want bind the function to. */ bind: function(object) { var f = this; var preappliedArguments = []; var i, argLength = arguments.length; /** * Remove first argument, as that is the object itself and * we want to send that on to the function we will call */ for (i = 1; i < argLength; i++) { preappliedArguments.push(arguments[i]); } return function() { var args = []; var i, argLength = arguments.length; for (i = 0; i < argLength; i++) { args.push(arguments[i]); } f.apply(object, preappliedArguments.concat(preappliedArguments, args)); }; }, /** * This methods travers the DOM, and applying the func on all nodes. * * @param {HTMLElement} node The start node * @param {function} func The function to apply */ traverseDOM: function(node, func) { func(node); node = node.firstChild; while( node ) { this.traverseDOM(node, func); // Going down this branch node = node.nextSibling; // Going to the next sibling } }, /** * Checks if an element has given classname * * @param {HTMLElement} element The element we want to see if has the classname * @param {String} classNameToAdd The classname */ hasClass: function(element, className) { return Boolean(element.className.match("(?:^|\\s+)"+className+"(?:\\s+|$)")); }, /** * Legger en class på et element, og tar hensyn til om det evt. skulle være classer alt registrert på elementet. * Hvis det er, vil denne klassen bli "hektet på" til slutt, slik at eksisterende klasse blir tatt vare på. * * @param {HTMLElement} element Elementet som skal få klassen lagt på seg * @param {String} classNameToAdd Klassenavnet */ addClass: function(element, classNameToAdd) { if ( ! this.hasClass(element, classNameToAdd) ) { element.className = [element.className, classNameToAdd].join(" "); } }, /** * Fjerner en classe fra elementet, og gjør dette med hensyn på om det alt eksisterer flere klasser enn * den som skal fjernes i class-stringen. * * @param {HTMLElement} element Elementet som skal få klassen fjernet * @param {String} classNameToRemove Klassenavnet */ removeClass: function(element, classNameToRemove) { var reg = new RegExp("(?:^|\\s+)"+classNameToRemove+"(?:\\s+|$)", "g"); if ( this.hasClass(element, classNameToRemove) ) { element.className = element.className.replace(reg, " "); } }, /** * Returns all the elements of given class. If node is not given, it will start at the body. * * @param {String} className The class name we look for * @param {HTMLElement} node The node from where we should start looking */ getElementsByClass: function(className, node) { var res = []; this.traverseDOM(node || document.body, function(node) { var c = node.className; var cSplit, i; if ( c ) { // Node has classnames, splitting it and checking cSplit = c.split(" "); for (i = 0; i < cSplit.length; i++) { if ( cSplit[i] === className) { res.push(node); break; } } } }); return res; }, /** * Gets you the parent node of incomming start node which has the given classname * * @param {HTMLElement} startNode The node we want to start our search from * @param {string} className The class name you want the parent node to have */ getParentWithClass: function(startNode, className) { var parentNode = startNode.parentNode; while ( ! this.hasClass(parentNode, className) ) { if ( parentNode.tagName === "BODY" ) { return null; } parentNode = parentNode.parentNode; } return parentNode; }, getParentWithId: function(startNode, id) { var parentNode = startNode.parentNode; while ( parentNode.id !== id ) { if ( parentNode.tagName === "BODY" ) { return null; } parentNode = parentNode.parentNode; } return parentNode; }, /** * Gets a parent node of specified type * Will search up in the DOM tree after a node of given type. * * @param {HTMLElement} startNode The node we want to start our search from * @param {string} type The type we are looking for * @return {HTMLElement | null} The parent node of given type, or null if not found within body. */ getParentNodeOfType: function(startNode, type) { var parentNode = startNode.parentNode; while (parentNode.tagName !== type) { if ( parentNode.tagName === "BODY" ) { return null; } parentNode = parentNode.parentNode; } return parentNode; }, /** * Function returns the first node of given nodeType. * * This function is usefull as FF (and opera?) might return * the text node of a newline node in the HTML source, while IE dont do this. * * @param {HTMLElement} startElement The element to start from * @param {type} int The node type we want back */ getNextSiblingOfType: function(startElement, type) { var nextElement = startElement.nextSibling; while (nextElement.nodeType !== type) { nextElement = nextElement.nextSibling; } return nextElement; }, /** * Inserts a element after given element. * * @param {HTMLElement} newElement The new element * @param {HTMLElement} targetElement The element which we will insert the * new after */ insertAfter: function(newElement, targetElement) { var parent = targetElement.parentNode; if(parent.lastChild == targetElement) { parent.appendChild(newElement); } else { parent.insertBefore(newElement, targetElement.nextSibling); } }, /** * Cets the current style from an object * * @param {HTMLElement} element The element we are fetching a propertie from * @param {String} prop The propertie we are looking for */ getCurrentStyle: function(element, prop) { var value = null; if ( window.getComputedStyle ) { // First, W3C's way of doing it value = document.defaultView.getComputedStyle(element, null).getPropertyValue(prop); } else if ( element.currentStyle ) { // IE's way value = element.currentStyle[prop]; } return value; }, /** * Get browser window height * * @return int */ getWinHeight: function() { if (window.self && self.innerHeight) { return self.innerHeight; } if (document.documentElement && document.documentElement.clientHeight) { return document.documentElement.clientHeight; } return 0; }, /** * Get browser window width * * @return int */ getWinWidth: function() { if(window.self && self.innerWidth) { return self.innerWidth; } if(document.documentElement && document.documentElement.clientWidth) { return document.documentElement.clientWidth; } return 0; }, /** * Gets the browsers mousecoords * * @param {Event} ev The event object to fetch coords from */ mouseCoords: function(ev) { if(ev.pageX || ev.pageY){ return { x:ev.pageX, y:ev.pageY }; } return { x:ev.clientX + document.body.scrollLeft - document.body.clientLeft, y:ev.clientY + document.body.scrollTop - document.body.clientTop }; }, getPosition: function(e){ var left = 0; var top = 0; while (e.offsetParent) { left += e.offsetLeft; top += e.offsetTop; e = e.offsetParent; } left += e.offsetLeft; top += e.offsetTop; return { x:left, y:top }; }, /** * Fetch the mouse offset */ getMouseOffset: function(target, ev){ ev = ev || window.event; var docPos = this.getPosition(target); var mousePos = this.mouseCoords(ev); return { x:mousePos.x - docPos.x, y:mousePos.y - docPos.y }; }, /** * Get browser window height * * @return {int} The window's height, or -1 if not found */ getWinHeight: function() { if (window.self && self.innerHeight) { return self.innerHeight; } if (document.documentElement && document.documentElement.clientHeight) { return document.documentElement.clientHeight; } return -1; }, /** * Get browser window width * * @return {int} The window's width, or -1 if not found */ getWinWidth: function() { if(window.self && self.innerWidth) { return self.innerWidth; } if(document.documentElement && document.documentElement.clientWidth) { return document.documentElement.clientWidth; } return -1; }, /** * Escapes HTML entities in a string * * This function escapes HTML entiteis to prevent cross site scripting * and other behavior a user can think of as "strange" if they do not know * that these chars have special meaning in HTML. * * @return {String} A HTML escpaed string */ escapeHTML: function() { var escaped = this; escaped = escaped.replace(/&/g, "&"); escaped = escaped.replace(//g, ">"); return escaped; }, /** * Returns a string like this: Returns A String Like This. * This might be bound to String.prototype */ ucWords: function() { var orgString = this.split(" "); var i; for ( i = 0; i < orgString.length; ++i ) { orgString[i] = ZPIN.Utils.ucFirst.call(orgString[i]); } return orgString.join(" "); }, /** * Returns UC first of a string. * This might be bound to String.prototype */ ucFirst: function() { return this.substr(0,1).toUpperCase() + this.substr(1,this.length).toLowerCase(); }, /** * Pad string with padWith, and a total string length of given length :) * */ padWith: function(padWith, totalStringLength) { if ( padWith.length !== 1 ) { throw new Error("padWith should only be one char!"); } // Building padding string var padString = ""; for ( var i = 0; i < totalStringLength; ++i ) { padString += padWith; } return padString.substr(0, totalStringLength - this.length)+this; }, isValidUrl : function(input) { var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ return regexp.test(input); }, isValidEmail: function(input) { return (input.match(/^[\w\.\-]+@([a-z0-9]+([\.\-]?[a-z\d]+)*\.)+[a-z]{2,7}$/i) ? true : false); } };