Zapatec Utils Overview

Overview | File | Class | Tree | Index | Help

Zapatec Utils

PREV NEXT | FRAMES NO FRAMES

## dom.js

#### Summary

No overview generated for 'dom.js'

    //$Id: dom.js 7436 2007-06-14 20:09:05Z vkulov $
    /**
     * Gets the width of the HTML element. This
     * is used to take out the measurement of sizing.
     * Currently offset measurement is used, cause
     * its equal for different box sizings.
     * @param el {HTML element} element to get width of.
     * @return {number} the measurement width of the element,
     * if not HTML element then false.
     */
    Zapatec.Utils.getWidth = function(el) {
    	//checking for valid element type
    	if (!Zapatec.isHtmlElement(el)) {
    		return false;
    	}
    	//returning the width
    	return el.offsetWidth
    };

    /**
     * Gets the height of the HTML element. This
     * is used to take out the measurement of sizing.
     * Currently offset measurement is used, cause
     * its equal for different box sizings.
     * @param el {HTML element} element to get height of.
     * @return {number} the measurement height of the element,
     * if not HTML element then false.
     */
    Zapatec.Utils.getHeight = function(el) {
    	//checking for valid element type
    	if (!Zapatec.isHtmlElement(el)) {
    		return false;
    	}
    	//returning the height
    	return el.offsetHeight
    };

    /**
     * Sets the width of the HTML element. This is
     * cross-browser implementation that is based on
     * Zapatec.Utils.getWidth value for this element.
     * @param el {HTML element} element to set width.
     * @param width {number} width to set.
     * @return {boolean} true if width set, otherwise false.
     */
    Zapatec.Utils.setWidth = function(el, width) {
    	//getting integer value
    	width = Math.round(width);
    	//checking for valid element type and valid width
    	if (!Zapatec.isHtmlElement(el) || width <= 0) {
    		return false;
    	}
    	//saving old style width to restore if fail
    	var oldWidth = el.style.width, newWidth;
    	//trying to set width (first try)
    	el.style.width = width + "px";
    	//checking if it was set correctly
    	if (Zapatec.Utils.getWidth(el) != width) {
    		//if not lets try to calculate correct value
    		newWidth = width - (Zapatec.Utils.getWidth(el) - width);
    		if (newWidth > 0) {
    			//and if its a valid number for size let's try again to set it
    			el.style.width = newWidth + "px";
    			//if still wrong result we need to restore old size,
    			//report the warning and return false
    			if (Zapatec.Utils.getWidth(el) != width) {
    				el.style.width = oldWidth;
    				Zapatec.Log({description : "Can't set the width - " + width + "px!", type : "warning"});
    				return false;
    			}
    		} else {
    			//if number isn't valid we need to restore old size,
    			//report the warning and return false
    			el.style.width = oldWidth;
    			Zapatec.Log({description : "Can't set the width - " + width + "px!", type : "warning"});
    			return false;
    		}
    	}
    	//returning success
    	return true;
    };

    /**
     * Sets the height of the HTML element. This is
     * cross-browser implementation that is based on
     * Zapatec.Utils.getHeight value for this element.
     * @param el {HTML element} element to set height.
     * @param width {number} height to set.
     * @return {boolean} true if height set, otherwise false.
     */
    Zapatec.Utils.setHeight = function(el, height) {
    	//getting integer value
    	height = Math.round(height);
    	//checking for valid element type and valid height
    	if (!Zapatec.isHtmlElement(el) || height <= 0) {
    		return false;
    	}
    	//saving old style height to restore if fail
    	var oldHeight = el.style.height, newHeight;
    	//trying to set height (first try)
    	el.style.height = height + "px";
    	//checking if it was set correctly
    	if (Zapatec.Utils.getHeight(el) != height) {
    		//if not lets try to calculate correct value
    		newHeight = height - (Zapatec.Utils.getHeight(el) - height);
    		if (newHeight > 0) {
    			//and if its a valid number for size let's try again to set it
    			el.style.height = newHeight + "px";
    			//if still wrong result we need to restore old size,
    			//report the warning and return false
    			if (Zapatec.Utils.getHeight(el) != height) {
    				el.style.height = oldHeight;
    				Zapatec.Log({description : "Can't set the height - " + height + "px!", type : "warning"});
    				return false;
    			}
    		} else {
    			//if number isn't valid we need to restore old size,
    			//report the warning and return false
    			el.style.height = oldHeight;
    			Zapatec.Log({description : "Can't set the height - " + height + "px!", type : "warning"});
    			return false;
    		}
    	}
    	//returning success
    	return true;
    };

    /**
     * Fixates the width of HTML element in pixels.
     * @param el {HTML element} element to fixate width of.
     * @return {boolean} true if success, otherwise false.
     */
    Zapatec.Utils.fixateWidth = function(el) {
    	return Zapatec.Utils.setWidth(el, Zapatec.Utils.getWidth(el));
    };

    /**
     * Fixates the height of HTML element in pixels.
     * @param el {HTML element} element to fixate height of.
     * @return {boolean} true if success, otherwise false.
     */
    Zapatec.Utils.fixateHeight = function(el) {
    	return Zapatec.Utils.setHeight(el, Zapatec.Utils.getHeight(el));
    };

    /**
     * Makes some routines to make element correctly sizable.
     * This is mostly preserving sizes and making overflow
     * "hidden" or "scroll" (depends on "scrollable" parameter).
     * @param el {HTML element} element to make safely sizable.
     * @param restorer {object} Zapatec.SRProp object.
     * @return {boolean} true if success, otherwise false.
     */
    Zapatec.Utils.makeSafelySizable = function(el, restorer) {
    	if (el.sizable) {
    		return true;
    	}
    	//checking if HTML element was passed
    	if (!Zapatec.isHtmlElement(el)) {
    		return false;
    	}
    	//trying to take the exsistant restorer
    	if (!restorer) {
    		restorer = el.restorer;
    	}
    	//checking for restorer, if there is no or the one given won't do
    	//we create new one
    	if (!restorer || !restorer.getObject || restorer.getObject() != el) {
    		restorer = new Zapatec.SRProp(el);
    	}
    	//saving properties that will be changed
    	restorer.saveProps("style.width", "style.height", "style.overflow");
    	//fixateing sizes
    	Zapatec.Utils.fixateWidth(el);
    	Zapatec.Utils.fixateHeight(el);
    	//getting overflow to know if we are sizing correct
    	var overflow = Zapatec.Utils.getStyleProperty(el, "overflow");
    	if (overflow == "" || overflow == "visible") {
    		Zapatec.Log({description : "There is the chance that this element with overflow visible will not be sized correctly!", type : "warning"});
    	}
    	el.sizable = true;

    	return true;
    };

    /**
     * Restores the element of sizing, if it was prepared
     * by Zapatec.Utils.makeSafelySizable function.
     * @param el {HTML element} element to restore.
     * @return {boolean} true if success, otherwise false.
     */
    Zapatec.Utils.restoreOfSizing = function(el) {
    	//checking if something was saved
    	if (!el || !el.restorer || !el.sizable) {
    		return false;
    	}
    	//restoreing needed properties
    	el.restorer.restoreProps("style.width", "style.height", "style.overflow");
    	if (el.restorer.isEmpty()) {
    		el.restorer.destroy();
    	}
    	el.sizable = false;

    	return true;
    };

    /**
     * Prepares elelement to be safely moved by Zapatec.Utils.moveTo. To be moved element should be positioned
     * absolute and should be direct child of within parameter, should have margin set to 0px.
     * @param el {HTML element} the element to move
     * @param within {HTML element} if you want to move the element within some other element,
     * @param restorer {SRProp object} the SRProp object you want to use to restore our
     * elements properties, if you have already one.
     * pass the refference to it through this var (default is document.body)
     * @return {boolean} true if success, otherwise false
     */
    Zapatec.Utils.makeSafelyMovable = function(el, within, restorer) {
    	//Checking if the element is of the right type
    	if (!Zapatec.isHtmlElement(el)) {
    		return false;
    	}
    	//take default within element
    	if (!within) {
    		within = document.body;
    	}
    	//maybe element is already prepared
    	if (el.within == within) {
    		return true;
    	}
    	//trying to take the exsistant restorer
    	if (!restorer) {
    		restorer = el.restorer;
    	}
    	//checking for restorer and creating new one if existing does not
    	//fit our needs
    	if (!restorer || !restorer.getObject || restorer.getObject() != el) {
    		restorer = new Zapatec.SRProp(el);
    	}
    	//To make it work we need the 'within' to be positioned relatively
    	//except it is BODY (which means screen)
    	el.within = within;
    	if (within != document.body && within.style.position != "absolute") {
    		restorer.saveProp("within.style.position");
    		within.style.position = "relative";
    	}
    	//Need to preserve elements position after we prepare it for move
    	if (within != document.body) {
    		var pos1 = Zapatec.Utils.getElementOffset(within);
    	} else {
    		var pos1 = {x : 0, y : 0};
    	}
    	var pos2 = Zapatec.Utils.getElementOffset(el);
    	var x = pos2.x - pos1.x;
    	var y = pos2.y - pos1.y;
    	restorer.saveProps("style.left", "style.top");
    	el.style.left = x + "px";
    	el.style.top = y + "px";
    	//Checks if the element is positioned absolute.
    	if (el.style.position != "absolute") {
    		restorer.saveProp("style.position");
    		el.style.position = "absolute";
    	}
    	//withon should be direct parent of the draggable element
    	if (el.parentNode != within) {
    		restorer.saveProps("parentNode", "nextSibling");
    		within.appendChild(el);
    	}
    	//element must have margin 0px.
    	restorer.saveProp("style.margin");
    	el.style.margin = "0px";

    	return true;
    };

    /**
     * Moves elelement to the specified position. To be moved element should be positioned absolute
     * and should be direct child of 'within' element. If there is no el.within property,
     * document.body will be taken. If you want safe move use Zapatec.Utils.makeSafelyMovable.
     * @param el {HTML element} - the element to move
     * @param x {number} - the x coordinate to move to
     * @param y {number} - the y coordinate to move to
     * @return {boolean} true if success, otherwise false
     */
    Zapatec.Utils.moveTo = function(el, x, y) {
    	//Checking if the element is of the right type
    	if (!Zapatec.isHtmlElement(el)) {
    		return false;
    	}
    	var pos = null;
    	if (Zapatec.FixateOnScreen.isRegistered(el)) {
    		pos = Zapatec.FixateOnScreen.correctCoordinates(x, y);
    		if (Zapatec.is_ie && !Zapatec.is_ie7) {
    			el.style.setExpression("left", pos.x);
    			el.style.setExpression("top", pos.y);
    			return true;
    		}
    	} else {
    		pos = {
    			x : parseInt(x, 10) + "px",
    			y : parseInt(y, 10) + "px"
    		};
    	}
    	//setting of coordinates
    	if (x || x === 0) {
    		el.style.left = pos.x;
    	}
    	if (y || y === 0) {
    		el.style.top = pos.y;
    	}

    	return true;
    };

    /**
     * Gets the element position within another one (this depends on your implementation).
     * @param el {HTML element} - we are getting the position of this element
     * @return {object} object with x and y properties or false if failed.
     */
    Zapatec.Utils.getPos = function(el) {
    	//Checking if the element is of the right type
    	if (!Zapatec.isHtmlElement(el)) {
    		return false;
    	}
    	var pos = null;
    	if (pos = Zapatec.FixateOnScreen.parseCoordinates(el)) {
    		return pos;
    	}
    	//parsing coordinates
    	return {
    		x : el.offsetLeft,
    		y : el.offsetTop
    	}
    };

    /**
     * Moves element by the given offset in the 'within' element.
     * @param el {HTML element} - element to move
     * @param offsetX {number} - x offset to move for
     * @param offsetY {number} - y offset to move for
     * @return {boolean} true if succeeds, otherwise false
     */
    Zapatec.Utils.moveFor = function(el, offsetX, offsetY) {
    	//getting current position
    	var oldPos = Zapatec.Utils.getPos(el);
    	//assigning the offset
    	if (oldPos) {
    		return Zapatec.Utils.moveTo(el, oldPos.x + offsetX, oldPos.y + offsetY);
    	} else {
    		return false;
    	}
    };

    /**
     * Restores all the changes made in the elelement by Zapatec.Utils.makeSafelyMovable.
     * @param el {HTML element} - the element to restore
     * @return {boolean} true if successful, otherwise false
     */
    Zapatec.Utils.restoreOfMove = function(el) {
    	if (!el.within) return false;
    	//restoreing properies if everything is okay
    	el.restorer.restoreProps(
    		"style.position",
    		"parentNode",
    		"style.margin",
    		"nextSibling",
    		"within.style.position",
    		"style.left",
    		"style.top"
    	);
    	if (el.restorer.isEmpty()) {
    		el.restorer.destroy();
    	}
    	el.within = null;
    	return true;
    };

    /**
     * returns array of elements which has attribute 'attr' with value 'val'
     * by giving 'el' you can finetune your search
     * @param attribute {string} attribute to search
     * @param value {mixed} searched attributes value.
     * @param within {HTML element} reference to the element.
     * @param recursive {boolean} searches in childs.
     * @param match {boolean} if true and attribute is string,
     * tries to seek within it.
     * @return {array} array of elements found.
     */
    Zapatec.Utils.getElementsByAttribute = function(attribute, value, within, recursive, match){
    	//no attributte to seek - no action
    	if (!attribute) {
    		return false;
    	}
    	//trying to get element within what we need to search
    	within = Zapatec.Widget.getElementById(within);
    	//if none given taking document.body
    	within || (within = document.body);
    	//iterating through all the elements childs
    	var element = within.firstChild; result = [];
    	while (element) {
    		//element has attribute???
    		if (element[attribute]) {
    			//than if there's no value passed or values match adding it to resulting array
    			if (typeof value == "undefined" || element[attribute] == value) {
    				result.push(element);
    			} else if (match && typeof element[attribute] == "string" && element[attribute].indexOf(value) != -1) {
    				result.push(element);
    			}
    		};
    		//if recursive, going through all the childs
    		if (recursive && element.hasChildNodes()) {
    			result = result.concat(Zapatec.Utils.getElementsByAttribute(attribute, value, element, recursive, match));
    		}
    		//taking next sibling
    		element = element.nextSibling
    	};
    	//returning result
    	return Zapatec.Array(result);
    };

    /**
     * Creates an instance of object using passed
     * constructor, for each element in array.
     * The element will be passed as a "container"
     * option by default, but you can redefine
     * it using parameter configOption. Using
     * third parameter you can pass other config
     * options for the constructor.
     * @param constructor {function} constructor function.
     * @param elements {array} array of elements that the
     * consstructor will be apllied to.
     * @param config {object} config obect for constructor.
     * @param configOption {string} config option that will
     * be filled with the element, default is "container".
     * @return {array} array of created widgets.
     */
    Zapatec.Utils.applyToElements = function(constructor, elements, config, configOption) {
    	if (typeof constructor != "function" || !Zapatec.isArray(elements)) {
    		return false;
    	}
    	elements = Zapatec.Array(elements);
    	if (!configOption) {
    		configOption = "container";
    	}
    	//correcting or creating config object
    	if (!config || typeof config != "object") {
    		config = {};
    	}
    	//resulting array of Zapoatec.Utils.Draggable objects
    	var result = Zapatec.Array();
    	elements.each(function(index, element) {
    		//filling config with current element
    		config[configOption] = element;
    		//saving resulting object
    		result.push(new constructor(config));
    	});
    	//returning result
    	return result;
    };

    /**
     * Replaces the image with DIV element, and sets the image as background-image.
     * this is not good for images with changed size, because you cant change the background-image size and it will tile.
     * @param el {HTML element} reference to the element.
     * @return {HTML element} the needed element.
     */
    Zapatec.Utils.img2div = function(el){
    	if (!Zapatec.isHtmlElement(el)) {
    		return null;
    	}
    	//FIX ME: maybe this can be changed to div/img from just div with background
    	if ((/img/i).test(el.nodeName)) {
    		var div = document.createElement('div');
    	    // Set div width and height when image is loaded
    	    var objImage = new Image();
    	    objImage.onload = function() {
    	      div.style.width = objImage.width + 'px';
    	      div.style.height = objImage.height + 'px';
    	      div.style.fontSize = '0px';
    	      objImage.onload = null;
    	    };
    	    objImage.src = el.src;
    	    // Replace image with the div
    	    div.style.backgroundImage = 'url(' + el.src + ')';
    	    div.style.backgroundColor = 'transparent';
    		var id = el.id;
    		var className = el.className;
    		el.parentNode.replaceChild(div, el);
    		div.id = id;
    		div.className = className;
    		return div
    	} else {
    		return el
    	}
    };

    /**
     * Returns the string with numbers representing
     * the path in the DOM tree from the element
     * passed as parent to the element you need.
     * Example - "1-3-1-8".
     * @param element {HTML element} element to get path of.
     * @param parent {HTML element} we stop on this element.
     * @return {string} string representing path.
     */
    Zapatec.Utils.getElementPath = function(element, parent) {
    	//there always should be parameters passed
    	if (!Zapatec.isHtmlElement(element) || !Zapatec.isHtmlElement(parent)) {
    		return false;
    	}
    	//array of numbers from path
    	var res = [];
    	var el = element;
    	//going up the tree and counting previous siblings
    	while(el && el != parent) {
    		//at first we think that this is the first node :)
    		var number = 1;
    		//counting previous siblings
    		while(el.previousSibling) {
    			++number;
    			el = el.previousSibling;
    		}
    		//adding a number in the beggining of the array
    		res.unshift(number);
    		//taking parent node
    		el = el.parentNode;
    	}
    	//joining the resulting array to have a string value.
    	return res.join("-");
    };

    //This is an HTML element used as a cover to imitate mousemove action correctly.
    Zapatec.Utils.cover = Zapatec.Utils.createElement("div");
    Zapatec.Utils.cover.style.overflow = "hidden";
    //This is the workaround for IE who doesn't firest needed events if the element is empty
    Zapatec.Utils.cover.style.backgroundImage = "url(" + Zapatec.zapatecPath + "zpempty.gif)";
    Zapatec.Utils.cover.style.display = "none";
    Zapatec.Utils.cover.id = "zpCoverControl";

    /**
     * Shows the cover.
     * @param zIndex {number} - z-index of the cover.
     * @param cursor {string} - cursor to be assigned.
     * @param mouseMoveHandler {function} - handler function for mouse move
     * @param mouseUpHandler {function} - handler function for mouse up
     */
    Zapatec.Utils.cover.show = function(zIndex, cursor, mouseMoveHandler, mouseUpHandler) {
    	if (!this.parentNode) {
    		document.body.appendChild(this);
    	}
    	if (this.style.display != "none") {
    		this.hide();
    	}
    	this.style.display = "block";
    	//formatting it to be over all the others(even our draggable element)
    	Zapatec.Utils.makeSafelyMovable(this, null, document.body);
    	//initial position
    	var x = 0;
    	var y = 0;
    	//need to correct it with window scrolling
    	y += Zapatec.Utils.getPageScrollY();
    	x += Zapatec.Utils.getPageScrollX();
    	//moving cover
    	Zapatec.Utils.moveTo(this, x, y);
    	//setting sizes
    	var dim = Zapatec.Utils.getWindowSize();
    	this.style.width = dim.width + "px";
    	this.style.height = dim.height + "px";
    	//registering it to scroll
    	Zapatec.FixateOnScreen.register(this);
    	//setting proper cursor and z-index
    	this.style.zIndex = zIndex;
    	this.style.cursor = cursor;
    	//adding event listeners
    	if (typeof mouseMoveHandler == "function") {
    		Zapatec.Utils.addEvent(this, 'mousemove', mouseMoveHandler);
    	}
    	if (typeof mouseUpHandler == "function") {
    		Zapatec.Utils.addEvent(this, 'mouseup', mouseUpHandler);
    	}
    	//saving references to the event hanlers to remove them on hide.
    	this.mouseMoveHandler = mouseMoveHandler;
    	this.mouseUpHandler = mouseUpHandler;
    };

    /**
     * Hides the cover.
     */
    Zapatec.Utils.cover.hide = function() {
    	//unregistering cover from being scrolled with window
    	Zapatec.FixateOnScreen.unregister(this);
    	//removing event handlers
    	if (typeof this.mouseMoveHandler == "function") {
    		Zapatec.Utils.removeEvent(this, 'mousemove', this.mouseMoveHandler);
    	}
    	if (typeof this.mouseUpHandler == "function") {
    		Zapatec.Utils.removeEvent(this, 'mouseup', this.mouseUpHandler);
    	}
    	//mouse move handler
    	this.mouseMoveHandler = null;
    	this.mouseUpHandler = null;
    	//clearing the cursor and z-index
    	this.style.zIndex = "";
    	this.style.cursor = "";
    	//hiding elements
    	this.style.display = "none";
    };

Overview | File | Class | Tree | Index | Help

Zapatec Utils

PREV NEXT | FRAMES NO FRAMES

Documentation generated by JSDoc on Thu Aug 16 12:18:39 2007