Collection of useful JavaScript functions and patterns

This is a collection of useful JavaScript functions and patterns that I often use, when not coding with jQuery. I am still copying example from my projects into this document so it is a bit of a work in progress.

Strings


// Removes any white space to the right and left of the string
function trim(str) {
    return str.replace(/^\s+|\s+$/g, "");
}


// Removes any white space to the left of the string
function ltrim(str) {
    return str.replace(/^\s+/, "");
}


// Removes any white space to the right of the string
function rtrim(str) {
    return str.replace(/\s+$/, "");
}


// Truncate a string to a given length
function truncate(str, len) {
    if (str.length > len) {
        str = str.substring(0, len);
    }
    return str;
};


// Return a string only containing the letters a to z
function onlyLetters(str) {
    return str.toLowerCase().replace(/[^a-z]/g, "");
};


// Return a string only containing the letters a to z and numbers
function onlyLettersNums(str) {
    return str.toLowerCase().replace(/[^a-z,0-9,-]/g, "");
};

Arrays


// Removes an item from a given array
function removeArrayItem(arr, item) {
    var i = 0;
    while (i < arr.length) {
        if (arr[i] == item) {
            arr.splice(i, 1);
        } else {
            i++;
        }
    }
};


// Does a given array contain a item
function contains(a, obj) {
    var i = a.length;
    while (i--) {
        if (a[i] === obj) {
            return true;
        }
    }
    return false;
};


// The index of an item - Javascript 1.6+
['glenn','john'].indexOf('john')  returns 2

Dates


// Converts native date to a ISO date
function isoDateString(d) {
    function pad(n) {
        return n < 10 ? '0' + n : n
    }
    return d.getUTCFullYear() + '-'
        + pad(d.getUTCMonth() + 1) + '-'
        + pad(d.getUTCDate()) + 'T'
        + pad(d.getUTCHours()) + ':'
        + pad(d.getUTCMinutes()) + ':'
        + pad(d.getUTCSeconds()) + 'Z'
}

Objects


// Sorts a array of objects by a property
function sortObjectsByProperty(a, field, reverse, primer) {
    return a.sort(sortObjects(field, reverse, primer));
};


// Object sort
function sortObjects(field, reverse, primer) {
    reverse = (reverse) ? -1 : 1;
    return function (a, b) {
        a = a[field];
        b = b[field];
        if (primer !== undefined && a !== undefined && b !== undefined) {
            a = primer(a);
            b = primer(b);
        }
        if (a < b) return reverse * -1;
        if (a > b) return reverse * 1;
        return 0;
    }
};

DOM


// Does the node have a class
function hasClass(node, className) {
    if (node.className) {
        return node.className.match(
            new RegExp('(\\s|^)' + className + '(\\s|$)'));
    } else {
        return false;
    }
};


// Add a class to an node
function addClass(node, className) {
    if (hasClass(node, className)) node.className += " " + className;
};


// Removes a class from an node
function removeClass(node, className) {
    if (hasClass(node, className)) {
        var reg = new RegExp('(\\s|^)' + className + '(\\s|$)');
        node.className = node.className.replace(reg, ' ');
    }
};


//Returns first ancestor of required class or a null
function getParentByClass(node, className) {
    if (arguments.length === 2) {
        if (node.parentNode && node.nodeName !== "BODY")
            return getParentByClass(node.parentNode, className, 1);
        else
            return null;
    }
    // Recursive calls
    if (node !== null && node !== undefined) {
        if (hasClass(node, className)) {
            return node;
        } else {
            if (node.parentNode && node.nodeName !== "BODY")
                return getParentByClass(node.parentNode, className, 1);
            else
                return null;
        }
    } else {
        return null;
    }
};


// Returns the text of a given node 
function getTextContent(node) {
    if (typeof node.textContent != "undefined") {
        return node.textContent;
    }
    return node.innerText;
};


// Removes all child nodes
function removeAllChildren(node) {
    if (node) {
        while (node.firstChild) {
            node.removeChild(node.firstChild);
        }
    }
}


// Appends a new element to a given node
function append(node, eltName, attArr, strHtml) {
    if (node) {
        var nNode = document.createElement(eltName);
        if (attArr !== undefined) {
            var j = attArr.length;
            while (j--) {
                nNode.setAttribute(attArr[j][0], attArr[j][1]);
            }
        }
        if (strHtml !== undefined) {
            nNode.innerHTML = strHtml;
        }
        node.appendChild(nNode);
        return nNode;
    } else {
        return null;
    }
}


// Get elements by class name (Backwards compatible version)
function getElementsByClassName(rootNode, className) {
    var returnElements = [];
    if (rootNode.getElementsByClassName) {
        // Native getElementsByClassName 
        returnElements = rootNode.getElementsByClassName(className);
    } else if (document.evaluate) {
        // XPath 
        var xpathExpression;
        xpathExpression = ".//*[contains(concat(' ', @class, ' '), ' " 
            + className + " ')]";
        var xpathResult = document.evaluate(
            xpathExpression, rootNode, null, 0, null);
        var node;
        while ((node = xpathResult.iterateNext())) {
            returnElements.push(node);
        }
    } else {
        // Slower DOM fallback 
        className = className.replace(/\-/g, "\\-");
        var elements = rootNode.getElementsByTagName("*");
        for (var x = 0; x < elements.length; x++) {
            if (elements[x].className.match("(^|\\s)" + className 
                + "(\\s|$)")) {
                returnElements.push(elements[x]);
            }
        }
    }
    return returnElements;
}


// Get elements by attribute (Backwards compatible version)
function getElementsByAttribute(
    rootNode, attributeName, attributeValues) {

    var attributeList = attributeValues.split(" ");
    var returnElements = [];
    if (rootNode.querySelectorAll) {
        var selector = '';
        for (var i = 0; i < attributeList.length; i++) {
            selector += '[' + attributeName 
                + '*= "' + attributeList[i] + '"], ';
        }
        returnElements = rootNode.querySelectorAll(
            selector.substring(0, selector.length - 2));
    } else if (document.evaluatex) {
        // XPath 
        var xpathExpression = ".//*[";
        for (var i = 0; i < attributeList.length; i++) {
            if (i !== 0) {
                xpathExpression += " or ";
            }
            xpathExpression += "contains(
                concat(' ', @" + attributeName 
                + ", ' '), ' " + attributeList[i] + " ')";
        }
        xpathExpression += "]";
        var xpathResult = document.evaluate(
            xpathExpression, rootNode, null, 0, null);
        var node;
        while ((node = xpathResult.iterateNext())) {
            returnElements.push(node);
        }
    } else {
        // Slower fallback 
        attributeName = attributeName.replace(/\-/g, "\\-");
        var elements = rootNode.getElementsByTagName("*");
        for (var x = 0; x < elements.length; x++) {
            if (elements[x][attributeName]) {
                var found = false;
                for (var y = 0; y < attributeList.length; y++) {
                    if (elements[x][attributeName].match("(^|\\s)" 
                        + attributeList[y] + "(\\s|$)")) {
                        found = true;
                    }
                }
                if (found)
                    returnElements.push(elements[x]);
            }
        }
    }
    return returnElements;
},

Loops


// While reverse loop - fast
var i = arr.length;
while (i--) {
    // Do Stuff
}


// While loop
var i = arr.length;
var x = 0;
while (x < i) {
    // Do stuff
    x++;
}

Events


    
// Add event (Cross browser old school)
function addEvent(obj, type, fn) {
    if (obj) {
        if (obj.attachEvent) {
            obj['e' + type + fn] = fn;
            obj[type + fn] = function () { 
                obj['e' + type + fn](window.event); 
            };
            obj.attachEvent('on' + type, obj[type + fn]);
        } else {
            obj.addEventListener(type, fn, false);
        }
    }
};


// Remove event (Cross browser old school)
function removeEvent(obj, type, fn) {
    if (obj) {
        if (obj.detachEvent) {
            obj.detachEvent('on' + type, obj[type + fn]);
            obj[type + fn] = null;
        } else {
            obj.removeEventListener(type, fn, false);
        }
    }
};


// Cancel event bubbling to the rest of DOM
function cancelBubble(e) {
    if (window.event)
        window.event.cancelBubble = true;
    else
        e.stopPropagation();
};


// Prevents the events default action from happening.
u.preventDefault = function (e) {
    if (e.preventDefault)
        e.preventDefault();
    try {
        e.returnValue = false;
    } catch (ex) {
        // Do nothing
    }
};

// Cancel bubbling and prevent default action
function eventStop(e) {
    cancelBubble(e);
    preventDefault(e);
}

Type detection


// Is an object a string
function isString(obj) {
    return typeof (obj) == 'string';
};


// Is an object a array
function isArray(obj) {
    return obj && !(obj.propertyIsEnumerable('length')) 
        && typeof obj === 'object' 
        && typeof obj.length === 'number';
};


// Is an object a int
function isInt(obj) {
    var re = /^\d+$/;
    return re.test(obj);
};


// Is an object a email address
function isEmail(obj) {
    if(isString(obj)){
        return obj.match(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/ig);
    }else{
        return false;
    }
};


// Is an object a URL
function isUrl (obj) {
    if(isString(obj)){
        var re = new RegExp("^(http|https)\://([a-zA-Z0-9\.\-]+(\:" +
            "[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|" +
            "[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2" +
            "[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\." +
            "(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|" +
            "[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]" +
            "{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z" +
            "0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name" +
            "|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-z" +
            "A-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$");
        return obj.match(re);
    }else{
        return false;
    }
};

Object/Method detection


    // Checks for Drag and Drop API support
    function hasDragDrop() {
        var element = document.createElement('div');
        var name = 'ondragstart';
        var isSupported = (name in element);
        if (!isSupported && element.setAttribute) {
            element.setAttribute(name, 'return;');
            isSupported = typeof element[name] == 'function';
        }
        element = null;
        return isSupported;
    };

JSON


// Loads a JSON file into document
function getJSON(url) {
    script = document.createElement("script");
    script.setAttribute("type", "text/javascript");
    if (url.indexOf('?') > -1)
        url += '&';
    else
        url += '?';
    url += 'rand=' + Math.random();
    script.setAttribute("src", url);
    document.getElementsByTagName('head')[0].appendChild(script);
};

Module


// The module pattern
var PeopleStore = (function (m) {
    m.newModule = {};
    newModule.version = 0.1;

    return m;

} (PeopleStore || {}));

Closure


// onClick with a external closure
removeBtn.onclick = post(obj.aValue)
function post(aValue) {
  return function() {
    // do somthing with aValue
  };
}


// onClick with a closure
removeBtn.onclick = function (aValue) {
    return function () {
        // do somthing with aValue
    };
} (obj.aValue)


// addEventListener with a closure
removeBtn.addEventListener('click', function (aValue) {
	return function () {
        // do somthing with aValue
    };
}(obj.aValue), false);

I have coded and collected these functions over time. They often follow patterns that are found in the public domain. Everyone sits on the shoulders of others. The RegExp are copied from public sources on the web.