underscore.util.strings.js
3.6 KB
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
// Underscore-contrib (underscore.util.strings.js 0.3.0)
// (c) 2013 Michael Fogus, DocumentCloud and Investigative Reporters & Editors
// Underscore-contrib may be freely distributed under the MIT license.
(function(root) {
// Baseline setup
// --------------
// Establish the root object, `window` in the browser, or `global` on the server.
var _ = root._ || require('underscore');
// Helpers
// -------
// No reason to create regex more than once
var plusRegex = /\+/g;
var spaceRegex = /\%20/g;
var bracketRegex = /(?:([^\[]+))|(?:\[(.*?)\])/g;
var urlDecode = function(s) {
return decodeURIComponent(s.replace(plusRegex, '%20'));
};
var urlEncode = function(s) {
return encodeURIComponent(s).replace(spaceRegex, '+');
};
var buildParams = function(prefix, val, top) {
if (_.isUndefined(top)) top = true;
if (_.isArray(val)) {
return _.map(val, function(value, key) {
return buildParams(top ? key : prefix + '[]', value, false);
}).join('&');
} else if (_.isObject(val)) {
return _.map(val, function(value, key) {
return buildParams(top ? key : prefix + '[' + key + ']', value, false);
}).join('&');
} else {
return urlEncode(prefix) + '=' + urlEncode(val);
}
};
// Mixing in the string utils
// ----------------------------
_.mixin({
// Explodes a string into an array of chars
explode: function(s) {
return s.split('');
},
// Parses a query string into a hash
fromQuery: function(str) {
var parameters = str.split('&'),
obj = {},
parameter,
key,
match,
lastKey,
subKey,
depth;
// Iterate over key/value pairs
_.each(parameters, function(parameter) {
parameter = parameter.split('=');
key = urlDecode(parameter[0]);
lastKey = key;
depth = obj;
// Reset so we don't have issues when matching the same string
bracketRegex.lastIndex = 0;
// Attempt to extract nested values
while ((match = bracketRegex.exec(key)) !== null) {
if (!_.isUndefined(match[1])) {
// If we're at the top nested level, no new object needed
subKey = match[1];
} else {
// If we're at a lower nested level, we need to step down, and make
// sure that there is an object to place the value into
subKey = match[2];
depth[lastKey] = depth[lastKey] || (subKey ? {} : []);
depth = depth[lastKey];
}
// Save the correct key as a hash or an array
lastKey = subKey || _.size(depth);
}
// Assign value to nested object
depth[lastKey] = urlDecode(parameter[1]);
});
return obj;
},
// Implodes and array of chars into a string
implode: function(a) {
return a.join('');
},
// Converts a string to camel case
camelCase : function( string ){
return string.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
},
// Converts camel case to dashed (opposite of _.camelCase)
toDash : function( string ){
string = string.replace(/([A-Z])/g, function($1){return "-"+$1.toLowerCase();});
// remove first dash
return ( string.charAt( 0 ) == '-' ) ? string.substr(1) : string;
},
// Creates a query string from a hash
toQuery: function(obj) {
return buildParams('', obj);
},
// Reports whether a string contains a search string.
strContains: function(str, search) {
if (typeof str != 'string') throw new TypeError;
return (str.indexOf(search) != -1);
}
});
})(this);