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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181 | 1
1
1
1
1
1
6
6
1
816
816
951
870
870
870
870
858
3846
3846
3884
8388
3846
1240
1070
1072
1070
10
1070
823
823
823
823
823
18602
823
823
20044
823
17779
418623
34716
383907
823
797
797
2029
2029
17147
2029
440
440
54
440
361
361
1008
776
361
| var shim = require('./shim');
var forEach = shim.forEach;
var filter = shim.filter;
var reduce = shim.reduce;
var getKeys = shim.getKeys;
var errorMethodBlacklist = reduce(['message', 'line', 'sourceId', 'sourceURL', 'stack', 'stackArray'], function (result, prop) {
result[prop] = true;
return result;
}, {});
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;
},
cloneError: function (e) {
var newError = new Error();
forEach(getKeys(e), function (key) {
if (!errorMethodBlacklist[key]) {
newError[key] = e[key];
}
});
return newError;
}
};
|