Tuesday, May 05, 2009

Some Core Javascript Functions

I recently worked on two different projects that involved a fair amount of Javascript centering around using the Google Maps API. In doing so I began to factor out some of the components to be reusable in a general Google Maps project. While I usually use the excellent Prototype Javascript library I didn't want to leak Prototype code into these reusable components. This led me to using these functions, borrowed / evolved from various places, as the core functions to support the components:

if (!window.CAMBER) CAMBER = {};
// create a bound function, forcing this
CAMBER.createBoundFunction = function(object, method) {
return function() {
return method.apply(object, arguments);
};
};
// constructor to create DOM element applying attributes and styles
CAMBER.Element = function(tag, attrs, styles) {
var elt = document.createElement(tag);
CAMBER.Element.setAttrs(elt, attrs);
CAMBER.Element.setStyle(elt, styles);
return elt;
};
// beware cross browser issues {"class": "yourclass", className: "yourclass"}
CAMBER.Element.setAttrs = function(elts, attrs) {
if (!CAMBER.isArray(elts)) elts = [elts];
attrs = attrs || {};
for (var i = 0, l = elts.length; i < l; ++i) {
for (var name in attrs) elts[i].setAttribute(name, attrs[name]);
}
};
// set styles on elements
CAMBER.Element.setStyle = function(elts, styles) {
if (!CAMBER.isArray(elts)) elts = [elts];
styles = styles || {};
for (var i = 0, l = elts.length; i < l; ++i) {
for (var style in styles) elts[i].style[style] = styles[style];
}
};
// taken from http://tinyurl.com/8yew89
CAMBER.isArray = function(obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
};
CAMBER.hasClassName = function(elt, className) {
var regex = new RegExp("(^|\\s)" + className + "(\\s|$)");
return regex.test(elt.className);
};
CAMBER.addClassName = function(elt, className) {
if (!CAMBER.hasClassName(elt, className)) {
elt.className += (elt.className ? " " : "") + className;
}
return elt;
};
CAMBER.removeClassName = function(elt, className) {
var regex = new RegExp("(^|\\s)" + className + "(\\s|$)");
elt.className = CAMBER.trim(elt.className.replace(regex, " "));
return elt;
};
CAMBER.trim = function(str) {
return str.replace(/^\s*|\s*$/g, "");
};
// taken from gmaps-utility-library
CAMBER.getMousePosition = function(evt) {
var posX = 0;
var posY = 0;
if (!evt) evt = window.event;
if (evt.pageX || evt.pageY) {
posX = evt.pageX;
posY = evt.pageY;
} else if (evt.clientX || evt.clientY){
posX = evt.clientX +
(document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
posY = evt.clientY +
(document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
}
return {left: posX, top: posY};
};
// taken from gmaps-utility-library
CAMBER.getElementPosition = function(elt) {
var leftPos = elt.offsetLeft;
var topPos = elt.offsetTop;
var parElement = elt.offsetParent;
while (parElement != null ) {
leftPos += parElement.offsetLeft;
topPos += parElement.offsetTop;
parElement = parElement.offsetParent;
}
return {left: leftPos, top: topPos};
};
view raw gistfile1.js hosted with ❤ by GitHub


I think these functions are a pretty good representation of the baseline support you will want in many Javascript projects.