backbone-relational-hal-rails 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,398 @@
1
+ var UriTemplate = (function () {
2
+
3
+ var uriTemplateGlobalModifiers = {
4
+ "+": true,
5
+ "#": true,
6
+ ".": true,
7
+ "/": true,
8
+ ";": true,
9
+ "?": true,
10
+ "&": true
11
+ };
12
+ var uriTemplateSuffices = {
13
+ "*": true
14
+ };
15
+
16
+ function notReallyPercentEncode(string) {
17
+ return encodeURI(string).replace(/%25[0-9][0-9]/g, function (doubleEncoded) {
18
+ return "%" + doubleEncoded.substring(3);
19
+ });
20
+ }
21
+
22
+ function uriTemplateSubstitution(spec) {
23
+ var modifier = "";
24
+ if (uriTemplateGlobalModifiers[spec.charAt(0)]) {
25
+ modifier = spec.charAt(0);
26
+ spec = spec.substring(1);
27
+ }
28
+ var separator = "";
29
+ var prefix = "";
30
+ var shouldEscape = true;
31
+ var showVariables = false;
32
+ var trimEmptyString = false;
33
+ if (modifier == '+') {
34
+ shouldEscape = false;
35
+ } else if (modifier == ".") {
36
+ prefix = ".";
37
+ separator = ".";
38
+ } else if (modifier == "/") {
39
+ prefix = "/";
40
+ separator = "/";
41
+ } else if (modifier == '#') {
42
+ prefix = "#";
43
+ shouldEscape = false;
44
+ } else if (modifier == ';') {
45
+ prefix = ";";
46
+ separator = ";",
47
+ showVariables = true;
48
+ trimEmptyString = true;
49
+ } else if (modifier == '?') {
50
+ prefix = "?";
51
+ separator = "&",
52
+ showVariables = true;
53
+ } else if (modifier == '&') {
54
+ prefix = "&";
55
+ separator = "&",
56
+ showVariables = true;
57
+ }
58
+
59
+ var varNames = [];
60
+ var varList = spec.split(",");
61
+ var varSpecs = [];
62
+ var varSpecMap = {};
63
+ for (var i = 0; i < varList.length; i++) {
64
+ var varName = varList[i];
65
+ var truncate = null;
66
+ if (varName.indexOf(":") != -1) {
67
+ var parts = varName.split(":");
68
+ varName = parts[0];
69
+ truncate = parseInt(parts[1]);
70
+ }
71
+ var suffices = {};
72
+ while (uriTemplateSuffices[varName.charAt(varName.length - 1)]) {
73
+ suffices[varName.charAt(varName.length - 1)] = true;
74
+ varName = varName.substring(0, varName.length - 1);
75
+ }
76
+ var varSpec = {
77
+ truncate: truncate,
78
+ name: varName,
79
+ suffices: suffices
80
+ };
81
+ varSpecs.push(varSpec);
82
+ varSpecMap[varName] = varSpec;
83
+ varNames.push(varName);
84
+ }
85
+ var subFunction = function (valueFunction) {
86
+ var result = "";
87
+ var startIndex = 0;
88
+ for (var i = 0; i < varSpecs.length; i++) {
89
+ var varSpec = varSpecs[i];
90
+ var value = valueFunction(varSpec.name);
91
+ if (value == null || (Array.isArray(value) && value.length == 0) || (typeof value == 'object' && Object.keys(value).length == 0)) {
92
+ startIndex++;
93
+ continue;
94
+ }
95
+ if (i == startIndex) {
96
+ result += prefix;
97
+ } else {
98
+ result += (separator || ",");
99
+ }
100
+ if (Array.isArray(value)) {
101
+ if (showVariables) {
102
+ result += varSpec.name + "=";
103
+ }
104
+ for (var j = 0; j < value.length; j++) {
105
+ if (j > 0) {
106
+ result += varSpec.suffices['*'] ? (separator || ",") : ",";
107
+ if (varSpec.suffices['*'] && showVariables) {
108
+ result += varSpec.name + "=";
109
+ }
110
+ }
111
+ result += shouldEscape ? encodeURIComponent(value[j]).replace(/!/g, "%21") : notReallyPercentEncode(value[j]);
112
+ }
113
+ } else if (typeof value == "object") {
114
+ if (showVariables && !varSpec.suffices['*']) {
115
+ result += varSpec.name + "=";
116
+ }
117
+ var first = true;
118
+ for (var key in value) {
119
+ if (!first) {
120
+ result += varSpec.suffices['*'] ? (separator || ",") : ",";
121
+ }
122
+ first = false;
123
+ result += shouldEscape ? encodeURIComponent(key).replace(/!/g, "%21") : notReallyPercentEncode(key);
124
+ result += varSpec.suffices['*'] ? '=' : ",";
125
+ result += shouldEscape ? encodeURIComponent(value[key]).replace(/!/g, "%21") : notReallyPercentEncode(value[key]);
126
+ }
127
+ } else {
128
+ if (showVariables) {
129
+ result += varSpec.name;
130
+ if (!trimEmptyString || value != "") {
131
+ result += "=";
132
+ }
133
+ }
134
+ if (varSpec.truncate != null) {
135
+ value = value.substring(0, varSpec.truncate);
136
+ }
137
+ result += shouldEscape ? encodeURIComponent(value).replace(/!/g, "%21"): notReallyPercentEncode(value);
138
+ }
139
+ }
140
+ return result;
141
+ };
142
+ var guessFunction = function (stringValue, resultObj) {
143
+ if (prefix) {
144
+ if (stringValue.substring(0, prefix.length) == prefix) {
145
+ stringValue = stringValue.substring(prefix.length);
146
+ } else {
147
+ return null;
148
+ }
149
+ }
150
+ if (varSpecs.length == 1 && varSpecs[0].suffices['*']) {
151
+ var varSpec = varSpecs[0];
152
+ var varName = varSpec.name;
153
+ var arrayValue = varSpec.suffices['*'] ? stringValue.split(separator || ",") : [stringValue];
154
+ var hasEquals = (shouldEscape && stringValue.indexOf('=') != -1); // There's otherwise no way to distinguish between "{value*}" for arrays and objects
155
+ for (var i = 1; i < arrayValue.length; i++) {
156
+ var stringValue = arrayValue[i];
157
+ if (hasEquals && stringValue.indexOf('=') == -1) {
158
+ // Bit of a hack - if we're expecting "=" for key/value pairs, and values can't contain "=", then assume a value has been accidentally split
159
+ arrayValue[i - 1] += (separator || ",") + stringValue;
160
+ arrayValue.splice(i, 1);
161
+ i--;
162
+ }
163
+ }
164
+ for (var i = 0; i < arrayValue.length; i++) {
165
+ var stringValue = arrayValue[i];
166
+ if (shouldEscape && stringValue.indexOf('=') != -1) {
167
+ hasEquals = true;
168
+ }
169
+ var innerArrayValue = stringValue.split(",");
170
+ for (var j = 0; j < innerArrayValue.length; j++) {
171
+ if (shouldEscape) {
172
+ innerArrayValue[j] = decodeURIComponent(innerArrayValue[j]);
173
+ }
174
+ }
175
+ if (innerArrayValue.length == 1) {
176
+ arrayValue[i] = innerArrayValue[0];
177
+ } else {
178
+ arrayValue[i] = innerArrayValue;
179
+ }
180
+ }
181
+
182
+ if (showVariables || hasEquals) {
183
+ var objectValue = resultObj[varName] || {};
184
+ for (var j = 0; j < arrayValue.length; j++) {
185
+ var innerValue = stringValue;
186
+ if (typeof arrayValue[j] == "string") {
187
+ var stringValue = arrayValue[j];
188
+ var innerVarName = stringValue.split("=", 1)[0];
189
+ var stringValue = stringValue.substring(innerVarName.length + 1);
190
+ innerValue = stringValue;
191
+ } else {
192
+ var stringValue = arrayValue[j][0];
193
+ var innerVarName = stringValue.split("=", 1)[0];
194
+ var stringValue = stringValue.substring(innerVarName.length + 1);
195
+ arrayValue[j][0] = stringValue;
196
+ innerValue = arrayValue[j];
197
+ }
198
+ if (objectValue[innerVarName] !== undefined) {
199
+ if (Array.isArray(objectValue[innerVarName])) {
200
+ objectValue[innerVarName].push(innerValue);
201
+ } else {
202
+ objectValue[innerVarName] = [objectValue[innerVarName], innerValue];
203
+ }
204
+ } else {
205
+ objectValue[innerVarName] = innerValue;
206
+ }
207
+ }
208
+ if (Object.keys(objectValue).length == 1 && objectValue[varName] !== undefined) {
209
+ resultObj[varName] = objectValue[varName];
210
+ } else {
211
+ resultObj[varName] = objectValue;
212
+ }
213
+ } else {
214
+ if (resultObj[varName] !== undefined) {
215
+ if (Array.isArray(resultObj[varName])) {
216
+ resultObj[varName] = resultObj[varName].concat(arrayValue);
217
+ } else {
218
+ resultObj[varName] = [resultObj[varName]].concat(arrayValue);
219
+ }
220
+ } else {
221
+ if (arrayValue.length == 1 && !varSpec.suffices['*']) {
222
+ resultObj[varName] = arrayValue[0];
223
+ } else {
224
+ resultObj[varName] = arrayValue;
225
+ }
226
+ }
227
+ }
228
+ } else {
229
+ var arrayValue = (varSpecs.length == 1) ? [stringValue] : stringValue.split(separator || ",");
230
+ var specIndexMap = {};
231
+ for (var i = 0; i < arrayValue.length; i++) {
232
+ // Try from beginning
233
+ for (var firstStarred = 0; firstStarred < varSpecs.length - 1 && firstStarred < i; firstStarred++) {
234
+ if (varSpecs[firstStarred].suffices['*']) {
235
+ break;
236
+ }
237
+ }
238
+ if (j == i) {
239
+ // The first [i] of them have no "*" suffix
240
+ specIndexMap[i] = i;
241
+ continue;
242
+ } else {
243
+ // Try from the end
244
+ for (var lastStarred = varSpecs.length - 1; lastStarred > 0 && (varSpecs.length - lastStarred) < (arrayValue.length - i); lastStarred--) {
245
+ if (varSpecs[lastStarred].suffices['*']) {
246
+ break;
247
+ }
248
+ }
249
+ if ((varSpecs.length - lastStarred) == (arrayValue.length - i)) {
250
+ // The last [length - i] of them have no "*" suffix
251
+ specIndexMap[i] = lastStarred;
252
+ continue;
253
+ }
254
+ }
255
+ // Just give up and use the first one
256
+ specIndexMap[i] = firstStarred;
257
+ }
258
+ for (var i = 0; i < arrayValue.length; i++) {
259
+ var stringValue = arrayValue[i];
260
+ var innerArrayValue = stringValue.split(",");
261
+
262
+ if (showVariables) {
263
+ var stringValue = innerArrayValue[0]; // using innerArrayValue
264
+ var varName = stringValue.split("=", 1)[0];
265
+ var stringValue = stringValue.substring(varName.length + 1);
266
+ innerArrayValue[0] = stringValue;
267
+ var varSpec = varSpecMap[varName] || varSpecs[0];
268
+ } else {
269
+ var varSpec = varSpecs[specIndexMap[i]];
270
+ var varName = varSpec.name;
271
+ }
272
+
273
+ for (var j = 0; j < innerArrayValue.length; j++) {
274
+ if (shouldEscape) {
275
+ innerArrayValue[j] = decodeURIComponent(innerArrayValue[j]);
276
+ }
277
+ }
278
+
279
+ if ((showVariables || varSpec.suffices['*'])&& resultObj[varName] !== undefined) {
280
+ if (Array.isArray(resultObj[varName])) {
281
+ resultObj[varName] = resultObj[varName].concat(innerArrayValue);
282
+ } else {
283
+ resultObj[varName] = [resultObj[varName]].concat(innerArrayValue);
284
+ }
285
+ } else {
286
+ if (innerArrayValue.length == 1 && !varSpec.suffices['*']) {
287
+ resultObj[varName] = innerArrayValue[0];
288
+ } else {
289
+ resultObj[varName] = innerArrayValue;
290
+ }
291
+ }
292
+ }
293
+ }
294
+ };
295
+ subFunction.varNames = varNames;
296
+ return {
297
+ prefix: prefix,
298
+ substitution: subFunction,
299
+ unSubstitution: guessFunction
300
+ };
301
+ }
302
+
303
+ function UriTemplate(template) {
304
+ if (!(this instanceof UriTemplate)) {
305
+ return new UriTemplate(template);
306
+ }
307
+ var parts = template.split("{");
308
+ var textParts = [parts.shift()];
309
+ var prefixes = [];
310
+ var substitutions = [];
311
+ var unSubstitutions = [];
312
+ var varNames = [];
313
+ while (parts.length > 0) {
314
+ var part = parts.shift();
315
+ var spec = part.split("}")[0];
316
+ var remainder = part.substring(spec.length + 1);
317
+ var funcs = uriTemplateSubstitution(spec);
318
+ substitutions.push(funcs.substitution);
319
+ unSubstitutions.push(funcs.unSubstitution);
320
+ prefixes.push(funcs.prefix);
321
+ textParts.push(remainder);
322
+ varNames = varNames.concat(funcs.substitution.varNames);
323
+ }
324
+ this.fill = function (valueFunction) {
325
+ var result = textParts[0];
326
+ for (var i = 0; i < substitutions.length; i++) {
327
+ var substitution = substitutions[i];
328
+ result += substitution(valueFunction);
329
+ result += textParts[i + 1];
330
+ }
331
+ return result;
332
+ };
333
+ this.fromUri = function (substituted) {
334
+ var result = {};
335
+ for (var i = 0; i < textParts.length; i++) {
336
+ var part = textParts[i];
337
+ if (substituted.substring(0, part.length) !== part) {
338
+ return undefined;
339
+ }
340
+ substituted = substituted.substring(part.length);
341
+ if (i >= textParts.length - 1) {
342
+ if (substituted == "") {
343
+ break;
344
+ } else {
345
+ return undefined;
346
+ }
347
+ }
348
+ var nextPart = textParts[i + 1];
349
+ var offset = i;
350
+ while (true) {
351
+ if (offset == textParts.length - 2) {
352
+ var endPart = substituted.substring(substituted.length - nextPart.length);
353
+ if (endPart !== nextPart) {
354
+ return undefined;
355
+ }
356
+ var stringValue = substituted.substring(0, substituted.length - nextPart.length);
357
+ substituted = endPart;
358
+ } else if (nextPart) {
359
+ var nextPartPos = substituted.indexOf(nextPart);
360
+ var stringValue = substituted.substring(0, nextPartPos);
361
+ substituted = substituted.substring(nextPartPos);
362
+ } else if (prefixes[offset + 1]) {
363
+ var nextPartPos = substituted.indexOf(prefixes[offset + 1]);
364
+ var stringValue = substituted.substring(0, nextPartPos);
365
+ substituted = substituted.substring(nextPartPos);
366
+ } else if (textParts.length > offset + 2) {
367
+ // If the separator between this variable and the next is blank (with no prefix), continue onwards
368
+ offset++;
369
+ nextPart = textParts[offset + 1];
370
+ continue;
371
+ } else {
372
+ var stringValue = substituted;
373
+ substituted = "";
374
+ }
375
+ break;
376
+ }
377
+ unSubstitutions[i](stringValue, result);
378
+ }
379
+ return result;
380
+ }
381
+ this.varNames = varNames;
382
+ }
383
+ UriTemplate.prototype = {
384
+ fillFromObject: function (obj) {
385
+ return this.fill(function (varName) {
386
+ return obj[varName];
387
+ });
388
+ }
389
+ };
390
+
391
+ if (typeof module != 'undefined') {
392
+ module.exports = UriTemplate;
393
+ }
394
+ if (this) {
395
+ this.UriTemplate = UriTemplate;
396
+ }
397
+ return UriTemplate;
398
+ }).call(this);
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: backbone-relational-hal-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Simon Oulevay
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ description: Javascript assets for the latest backbone-relational-hal release.
28
+ email:
29
+ - simon.oulevay@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE.txt
35
+ - README.md
36
+ - VERSION
37
+ - lib/backbone-relational-hal-rails.rb
38
+ - lib/backbone-relational-hal-rails/engine.rb
39
+ - lib/backbone-relational-hal-rails/version.rb
40
+ - vendor/assets/javascripts/backbone-relational-hal/backbone-relational-hal.js
41
+ - vendor/assets/javascripts/backbone-relational-hal/backbone-relational.js
42
+ - vendor/assets/javascripts/backbone-relational-hal/backbone.js
43
+ - vendor/assets/javascripts/backbone-relational-hal/index.js
44
+ - vendor/assets/javascripts/backbone-relational-hal/jquery.js
45
+ - vendor/assets/javascripts/backbone-relational-hal/underscore.js
46
+ - vendor/assets/javascripts/backbone-relational-hal/uri-templates.js
47
+ homepage: https://github.com/AlphaHydrae/backbone-relational-hal-rails
48
+ licenses:
49
+ - MIT
50
+ metadata: {}
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 2.2.0
68
+ signing_key:
69
+ specification_version: 4
70
+ summary: Backbone-relational-hal assets for Ruby on Rails.
71
+ test_files: []