Code coverage report for lib/utils.js

Statements: 67.12% (49 / 73)      Branches: 51.22% (21 / 41)      Functions: 87.5% (14 / 16)      Lines: 70% (49 / 70)      Ignored: none     

All files » lib/ » utils.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 1651 1 1 1   1                                         780     780               882       846 846 846         846                     757       3960 3960 3996 8542     3960               1217       1090 1108       1090 10   1090               823 823   823     823 823 18602       823 823 20044       823 17779 418623 34716   383907             823       768 768                             1901 1901 16152 1901             320 320 40   320      
var shim = require('./shim');
var forEach = shim.forEach;
var filter = shim.filter;
var getKeys = shim.getKeys;
 
module.exports = {
    // https://gist.github.com/1044128/
    getOuterHTML: function (element) {
        // jshint browser:true
        if ('outerHTML' in element) return element.outerHTML;
        var ns = "http://www.w3.org/1999/xhtml";
        var container = document.createElementNS(ns, '_');
        var xmlSerializer = new XMLSerializer();
        var html;
        if (document.xmlVersion) {
            return xmlSerializer.serializeToString(element);
        } else {
            container.appendChild(element.cloneNode(false));
            html = container.innerHTML.replace('><', '>' + element.innerHTML + '<');
            container.innerHTML = '';
            return html;
        }
    },
 
    // Returns true if object is a DOM element.
    isDOMElement: function (object) {
        Iif (typeof HTMLElement === 'object') {
            return object instanceof HTMLElement;
        } else {
            return object &&
                typeof object === 'object' &&
                object.nodeType === 1 &&
                typeof object.nodeName === 'string';
        }
    },
 
    isArray: function (ar) {
        return Object.prototype.toString.call(ar) === '[object Array]';
    },
 
    isRegExp: function (re) {
        var s;
        try {
            s = '' + re;
        } catch (e) {
            return false;
        }
 
        return re instanceof RegExp || // easy case
        // duck-type for context-switching evalcx case
        typeof(re) === 'function' &&
            re.constructor.name === 'RegExp' &&
            re.compile &&
            re.test &&
            re.exec &&
            s.match(/^\/.*\/[gim]{0,3}$/);
    },
 
    isError: function (err) {
        return typeof err === 'object' && Object.prototype.toString.call(err) === '[object Error]';
    },
 
    extend: function (target) {
        var sources = Array.prototype.slice.call(arguments, 1);
        forEach(sources, function (source) {
            forEach(getKeys(source), function (key) {
                target[key] = source[key];
            });
        });
        return target;
    },
 
    isUndefinedOrNull: function (value) {
        return value === null || value === undefined;
    },
 
    isArguments: function (object) {
        return Object.prototype.toString.call(object) === '[object Arguments]';
    },
 
    getKeysOfDefinedProperties: function (object) {
        var keys = filter(getKeys(object), function (key) {
            return typeof object[key] !== 'undefined';
        });
        // The 'message' property of Error instances is enumerable for some reason, but we want
        // to include it in the set when comparing:
        if (Object.prototype.toString.call(object) === '[object Error]') {
            keys.push('message');
        }
        return keys;
    },
 
    /**
     * Levenshtein distance algorithm from wikipedia
     * http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript
     */
    levenshteinDistance: function (a, b) {
        Iif (a.length === 0) return b.length;
        Iif (b.length === 0) return a.length;
 
        var matrix = [];
 
        // increment along the first column of each row
        var i;
        for (i = 0; i <= b.length; i += 1) {
            matrix[i] = [i];
        }
 
        // increment each column in the first row
        var j;
        for (j = 0; j <= a.length; j += 1) {
            matrix[0][j] = j;
        }
 
        // Fill in the rest of the matrix
        for (i = 1; i <= b.length; i += 1) {
            for (j = 1; j <= a.length; j += 1) {
                if (b.charAt(i - 1) === a.charAt(j - 1)) {
                    matrix[i][j] = matrix[i - 1][j - 1];
                } else {
                    matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
                                            Math.min(matrix[i][j - 1] + 1, // insertion
                                                     matrix[i - 1][j] + 1)); // deletion
                }
            }
        }
 
        return matrix[b.length][a.length];
    },
 
    truncateStack: function (err, fn) {
        Eif (Error.captureStackTrace) {
            Error.captureStackTrace(err, fn);
        } else if ('stack' in err) {
            // Excludes IE<10, and fn cannot be anonymous for this backup plan to work:
            var stackEntries = err.stack.split(/\r\n?|\n\r?/),
            needle = 'at ' + fn.name + ' ';
            for (var i = 0 ; i < stackEntries.length ; i += 1) {
                if (stackEntries[i].indexOf(needle) !== -1) {
                    stackEntries.splice(1, i);
                    err.stack = stackEntries.join("\n");
                }
            }
        }
    },
 
    findFirst: function (arr, predicate, thisObj) {
        var scope = thisObj || null;
        for (var i = 0 ; i < arr.length ; i += 1) {
            if (predicate.call(scope, arr[i], i, arr)) {
                return arr[i];
            }
        }
        return null;
    },
 
    leftPad: function (str, width, ch) {
        ch = ch || ' ';
        while (str.length < width) {
            str = ch + str;
        }
        return str;
    }
};