js-routes 1.0.1 → 1.2.9

Sign up to get free protection for your applications and to get access to all the features.
data/lib/routes.js CHANGED
@@ -1,6 +1,12 @@
1
+ /*
2
+ File generated by js-routes GEM_VERSION
3
+ Based on Rails routes of APP_CLASS
4
+ */
5
+
1
6
  (function() {
2
- var NodeTypes, ParameterMissing, Utils, createGlobalJsRoutesObject, defaults, root,
3
- __hasProp = {}.hasOwnProperty;
7
+ var NodeTypes, ParameterMissing, ReservedOptions, Utils, createGlobalJsRoutesObject, defaults, root,
8
+ hasProp = {}.hasOwnProperty,
9
+ slice = [].slice;
4
10
 
5
11
  root = typeof exports !== "undefined" && exports !== null ? exports : this;
6
12
 
@@ -17,47 +23,46 @@
17
23
 
18
24
  NodeTypes = NODE_TYPES;
19
25
 
20
- Utils = {
21
- serialize: function(object, prefix) {
22
- var element, i, key, prop, result, s, _i, _len;
26
+ ReservedOptions = ['anchor', 'trailing_slash', 'host', 'port', 'protocol'];
23
27
 
28
+ Utils = {
29
+ default_serializer: function(object, prefix) {
30
+ var element, i, j, key, len, prop, s;
24
31
  if (prefix == null) {
25
32
  prefix = null;
26
33
  }
27
- if (!object) {
34
+ if (object == null) {
28
35
  return "";
29
36
  }
30
37
  if (!prefix && !(this.get_object_type(object) === "object")) {
31
38
  throw new Error("Url parameters should be a javascript hash");
32
39
  }
33
- if (root.jQuery) {
34
- result = root.jQuery.param(object);
35
- return (!result ? "" : result);
36
- }
37
40
  s = [];
38
41
  switch (this.get_object_type(object)) {
39
42
  case "array":
40
- for (i = _i = 0, _len = object.length; _i < _len; i = ++_i) {
43
+ for (i = j = 0, len = object.length; j < len; i = ++j) {
41
44
  element = object[i];
42
- s.push(this.serialize(element, prefix + "[]"));
45
+ s.push(this.default_serializer(element, prefix + "[]"));
43
46
  }
44
47
  break;
45
48
  case "object":
46
49
  for (key in object) {
47
- if (!__hasProp.call(object, key)) continue;
50
+ if (!hasProp.call(object, key)) continue;
48
51
  prop = object[key];
49
- if (!(prop != null)) {
50
- continue;
52
+ if ((prop == null) && (prefix != null)) {
53
+ prop = "";
51
54
  }
52
- if (prefix != null) {
53
- key = "" + prefix + "[" + key + "]";
55
+ if (prop != null) {
56
+ if (prefix != null) {
57
+ key = prefix + "[" + key + "]";
58
+ }
59
+ s.push(this.default_serializer(prop, key));
54
60
  }
55
- s.push(this.serialize(prop, key));
56
61
  }
57
62
  break;
58
63
  default:
59
- if (object) {
60
- s.push("" + (encodeURIComponent(prefix.toString())) + "=" + (encodeURIComponent(object.toString())));
64
+ if (object != null) {
65
+ s.push((encodeURIComponent(prefix.toString())) + "=" + (encodeURIComponent(object.toString())));
61
66
  }
62
67
  }
63
68
  if (!s.length) {
@@ -65,65 +70,35 @@
65
70
  }
66
71
  return s.join("&");
67
72
  },
73
+ custom_serializer: SERIALIZER,
74
+ serialize: function(object) {
75
+ if ((this.custom_serializer != null) && this.get_object_type(this.custom_serializer) === "function") {
76
+ return this.custom_serializer(object);
77
+ } else {
78
+ return this.default_serializer(object);
79
+ }
80
+ },
68
81
  clean_path: function(path) {
69
82
  var last_index;
70
-
71
83
  path = path.split("://");
72
84
  last_index = path.length - 1;
73
85
  path[last_index] = path[last_index].replace(/\/+/g, "/");
74
86
  return path.join("://");
75
87
  },
76
- set_default_url_options: function(optional_parts, options) {
77
- var i, part, _i, _len, _results;
78
-
79
- _results = [];
80
- for (i = _i = 0, _len = optional_parts.length; _i < _len; i = ++_i) {
81
- part = optional_parts[i];
82
- if (!options.hasOwnProperty(part) && defaults.default_url_options.hasOwnProperty(part)) {
83
- _results.push(options[part] = defaults.default_url_options[part]);
84
- }
85
- }
86
- return _results;
87
- },
88
- extract_anchor: function(options) {
89
- var anchor;
90
-
91
- anchor = "";
92
- if (options.hasOwnProperty("anchor")) {
93
- anchor = "#" + options.anchor;
94
- delete options.anchor;
95
- }
96
- return anchor;
97
- },
98
- extract_trailing_slash: function(options) {
99
- var trailing_slash;
100
-
101
- trailing_slash = false;
102
- if (defaults.default_url_options.hasOwnProperty("trailing_slash")) {
103
- trailing_slash = defaults.default_url_options.trailing_slash;
104
- }
105
- if (options.hasOwnProperty("trailing_slash")) {
106
- trailing_slash = options.trailing_slash;
107
- delete options.trailing_slash;
108
- }
109
- return trailing_slash;
110
- },
111
88
  extract_options: function(number_of_params, args) {
112
89
  var last_el;
113
-
114
90
  last_el = args[args.length - 1];
115
- if (args.length > number_of_params || ((last_el != null) && "object" === this.get_object_type(last_el) && !this.look_like_serialized_model(last_el))) {
116
- return args.pop();
91
+ if ((args.length > number_of_params && last_el === void 0) || ((last_el != null) && "object" === this.get_object_type(last_el) && !this.looks_like_serialized_model(last_el))) {
92
+ return args.pop() || {};
117
93
  } else {
118
94
  return {};
119
95
  }
120
96
  },
121
- look_like_serialized_model: function(object) {
97
+ looks_like_serialized_model: function(object) {
122
98
  return "id" in object || "to_param" in object;
123
99
  },
124
100
  path_identifier: function(object) {
125
101
  var property;
126
-
127
102
  if (object === 0) {
128
103
  return "0";
129
104
  }
@@ -147,56 +122,92 @@
147
122
  },
148
123
  clone: function(obj) {
149
124
  var attr, copy, key;
150
-
151
125
  if ((obj == null) || "object" !== this.get_object_type(obj)) {
152
126
  return obj;
153
127
  }
154
128
  copy = obj.constructor();
155
129
  for (key in obj) {
156
- if (!__hasProp.call(obj, key)) continue;
130
+ if (!hasProp.call(obj, key)) continue;
157
131
  attr = obj[key];
158
132
  copy[key] = attr;
159
133
  }
160
134
  return copy;
161
135
  },
162
- prepare_parameters: function(required_parameters, actual_parameters, options) {
163
- var i, result, val, _i, _len;
164
-
165
- result = this.clone(options) || {};
166
- for (i = _i = 0, _len = required_parameters.length; _i < _len; i = ++_i) {
167
- val = required_parameters[i];
136
+ merge: function() {
137
+ var tap, xs;
138
+ xs = 1 <= arguments.length ? slice.call(arguments, 0) : [];
139
+ tap = function(o, fn) {
140
+ fn(o);
141
+ return o;
142
+ };
143
+ if ((xs != null ? xs.length : void 0) > 0) {
144
+ return tap({}, function(m) {
145
+ var j, k, len, results, v, x;
146
+ results = [];
147
+ for (j = 0, len = xs.length; j < len; j++) {
148
+ x = xs[j];
149
+ results.push((function() {
150
+ var results1;
151
+ results1 = [];
152
+ for (k in x) {
153
+ v = x[k];
154
+ results1.push(m[k] = v);
155
+ }
156
+ return results1;
157
+ })());
158
+ }
159
+ return results;
160
+ });
161
+ }
162
+ },
163
+ normalize_options: function(default_parts, required_parameters, optional_parts, actual_parameters) {
164
+ var i, j, key, len, options, result, url_parameters, value;
165
+ options = this.extract_options(required_parameters.length, actual_parameters);
166
+ if (actual_parameters.length > required_parameters.length) {
167
+ throw new Error("Too many parameters provided for path");
168
+ }
169
+ options = this.merge(defaults.default_url_options, default_parts, options);
170
+ result = {};
171
+ url_parameters = {};
172
+ result['url_parameters'] = url_parameters;
173
+ for (key in options) {
174
+ if (!hasProp.call(options, key)) continue;
175
+ value = options[key];
176
+ if (this.indexOf(ReservedOptions, key) >= 0) {
177
+ result[key] = value;
178
+ } else {
179
+ url_parameters[key] = value;
180
+ }
181
+ }
182
+ for (i = j = 0, len = required_parameters.length; j < len; i = ++j) {
183
+ value = required_parameters[i];
168
184
  if (i < actual_parameters.length) {
169
- result[val] = actual_parameters[i];
185
+ url_parameters[value] = actual_parameters[i];
170
186
  }
171
187
  }
172
188
  return result;
173
189
  },
174
- build_path: function(required_parameters, optional_parts, route, args) {
175
- var anchor, opts, parameters, result, trailing_slash, url, url_params;
176
-
190
+ build_route: function(required_parameters, optional_parts, route, default_parts, full_url, args) {
191
+ var options, parameters, result, url, url_params;
177
192
  args = Array.prototype.slice.call(args);
178
- opts = this.extract_options(required_parameters.length, args);
179
- if (args.length > required_parameters.length) {
180
- throw new Error("Too many parameters provided for path");
181
- }
182
- parameters = this.prepare_parameters(required_parameters, args, opts);
183
- this.set_default_url_options(optional_parts, parameters);
184
- anchor = this.extract_anchor(parameters);
185
- trailing_slash = this.extract_trailing_slash(parameters);
193
+ options = this.normalize_options(default_parts, required_parameters, optional_parts, args);
194
+ parameters = options['url_parameters'];
186
195
  result = "" + (this.get_prefix()) + (this.visit(route, parameters));
187
- url = Utils.clean_path("" + result);
188
- if (trailing_slash === true) {
196
+ url = Utils.clean_path(result);
197
+ if (options['trailing_slash'] === true) {
189
198
  url = url.replace(/(.*?)[\/]?$/, "$1/");
190
199
  }
191
200
  if ((url_params = this.serialize(parameters)).length) {
192
201
  url += "?" + url_params;
193
202
  }
194
- url += anchor;
203
+ url += options.anchor ? "#" + options.anchor : "";
204
+ if (full_url) {
205
+ url = this.route_url(options) + url;
206
+ }
195
207
  return url;
196
208
  },
197
209
  visit: function(route, parameters, optional) {
198
210
  var left, left_part, right, right_part, type, value;
199
-
200
211
  if (optional == null) {
201
212
  optional = false;
202
213
  }
@@ -213,7 +224,7 @@
213
224
  case NodeTypes.CAT:
214
225
  left_part = this.visit(left, parameters, optional);
215
226
  right_part = this.visit(right, parameters, optional);
216
- if (optional && !(left_part && right_part)) {
227
+ if (optional && ((this.is_optional_node(left[0]) && !left_part) || ((this.is_optional_node(right[0])) && !right_part))) {
217
228
  return "";
218
229
  }
219
230
  return "" + left_part + right_part;
@@ -233,9 +244,11 @@
233
244
  throw new Error("Unknown Rails node type");
234
245
  }
235
246
  },
247
+ is_optional_node: function(node) {
248
+ return this.indexOf([NodeTypes.STAR, NodeTypes.SYMBOL, NodeTypes.CAT], node) >= 0;
249
+ },
236
250
  build_path_spec: function(route, wildcard) {
237
251
  var left, right, type;
238
-
239
252
  if (wildcard == null) {
240
253
  wildcard = false;
241
254
  }
@@ -264,7 +277,6 @@
264
277
  },
265
278
  visit_globbing: function(route, parameters, optional) {
266
279
  var left, right, type, value;
267
-
268
280
  type = route[0], left = route[1], right = route[2];
269
281
  if (left.replace(/^\*/i, "") !== left) {
270
282
  route[1] = left = left.replace(/^\*/i, "");
@@ -285,18 +297,16 @@
285
297
  },
286
298
  get_prefix: function() {
287
299
  var prefix;
288
-
289
300
  prefix = defaults.prefix;
290
301
  if (prefix !== "") {
291
- prefix = (prefix.match("/$") ? prefix : "" + prefix + "/");
302
+ prefix = (prefix.match("/$") ? prefix : prefix + "/");
292
303
  }
293
304
  return prefix;
294
305
  },
295
- route: function(required_parts, optional_parts, route_spec) {
306
+ route: function(required_parts, optional_parts, route_spec, default_parts, full_url) {
296
307
  var path_fn;
297
-
298
308
  path_fn = function() {
299
- return Utils.build_path(required_parts, optional_parts, route_spec, arguments);
309
+ return Utils.build_route(required_parts, optional_parts, route_spec, default_parts, full_url, arguments);
300
310
  };
301
311
  path_fn.required_params = required_parts;
302
312
  path_fn.toString = function() {
@@ -304,17 +314,51 @@
304
314
  };
305
315
  return path_fn;
306
316
  },
317
+ route_url: function(route_defaults) {
318
+ var hostname, port, protocol;
319
+ if (typeof route_defaults === 'string') {
320
+ return route_defaults;
321
+ }
322
+ protocol = route_defaults.protocol || Utils.current_protocol();
323
+ hostname = route_defaults.host || window.location.hostname;
324
+ port = route_defaults.port || (!route_defaults.host ? Utils.current_port() : void 0);
325
+ port = port ? ":" + port : '';
326
+ return protocol + "://" + hostname + port;
327
+ },
328
+ has_location: function() {
329
+ return typeof window !== 'undefined' && typeof window.location !== 'undefined';
330
+ },
331
+ current_host: function() {
332
+ if (this.has_location()) {
333
+ return window.location.hostname;
334
+ } else {
335
+ return null;
336
+ }
337
+ },
338
+ current_protocol: function() {
339
+ if (this.has_location() && window.location.protocol !== '') {
340
+ return window.location.protocol.replace(/:$/, '');
341
+ } else {
342
+ return 'http';
343
+ }
344
+ },
345
+ current_port: function() {
346
+ if (this.has_location() && window.location.port !== '') {
347
+ return window.location.port;
348
+ } else {
349
+ return '';
350
+ }
351
+ },
307
352
  _classToTypeCache: null,
308
353
  _classToType: function() {
309
- var name, _i, _len, _ref;
310
-
354
+ var j, len, name, ref;
311
355
  if (this._classToTypeCache != null) {
312
356
  return this._classToTypeCache;
313
357
  }
314
358
  this._classToTypeCache = {};
315
- _ref = "Boolean Number String Function Array Date RegExp Object Error".split(" ");
316
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
317
- name = _ref[_i];
359
+ ref = "Boolean Number String Function Array Date RegExp Object Error".split(" ");
360
+ for (j = 0, len = ref.length; j < len; j++) {
361
+ name = ref[j];
318
362
  this._classToTypeCache["[object " + name + "]"] = name.toLowerCase();
319
363
  }
320
364
  return this._classToTypeCache;
@@ -331,15 +375,31 @@
331
375
  } else {
332
376
  return typeof obj;
333
377
  }
378
+ },
379
+ indexOf: function(array, element) {
380
+ if (Array.prototype.indexOf) {
381
+ return array.indexOf(element);
382
+ } else {
383
+ return this.indexOfImplementation(array, element);
384
+ }
385
+ },
386
+ indexOfImplementation: function(array, element) {
387
+ var el, i, j, len, result;
388
+ result = -1;
389
+ for (i = j = 0, len = array.length; j < len; i = ++j) {
390
+ el = array[i];
391
+ if (el === element) {
392
+ result = i;
393
+ }
394
+ }
395
+ return result;
334
396
  }
335
397
  };
336
398
 
337
399
  createGlobalJsRoutesObject = function() {
338
400
  var namespace;
339
-
340
401
  namespace = function(mainRoot, namespaceString) {
341
402
  var current, parts;
342
-
343
403
  parts = (namespaceString ? namespaceString.split(".") : []);
344
404
  if (!parts.length) {
345
405
  return;
@@ -351,6 +411,9 @@
351
411
  namespace(root, "NAMESPACE");
352
412
  root.NAMESPACE = ROUTES;
353
413
  root.NAMESPACE.options = defaults;
414
+ root.NAMESPACE.default_serializer = function(object, prefix) {
415
+ return Utils.default_serializer(object, prefix);
416
+ };
354
417
  return root.NAMESPACE;
355
418
  };
356
419
 
data/lib/routes.js.coffee CHANGED
@@ -1,3 +1,7 @@
1
+ ###
2
+ File generated by js-routes GEM_VERSION
3
+ Based on Rails routes of APP_CLASS
4
+ ###
1
5
  # root is this
2
6
  root = (exports ? this)
3
7
 
@@ -9,67 +13,62 @@ defaults =
9
13
 
10
14
  NodeTypes = NODE_TYPES
11
15
 
16
+ ReservedOptions = [
17
+ 'anchor'
18
+ 'trailing_slash'
19
+ 'host'
20
+ 'port'
21
+ 'protocol'
22
+ ]
23
+
12
24
  Utils =
13
25
 
14
- serialize: (object, prefix = null) ->
15
- return "" unless object
26
+ default_serializer: (object, prefix = null) ->
27
+ return "" unless object?
16
28
  if !prefix and !(@get_object_type(object) is "object")
17
29
  throw new Error("Url parameters should be a javascript hash")
18
30
 
19
- if root.jQuery
20
- result = root.jQuery.param(object)
21
- return (if not result then "" else result)
22
-
23
31
  s = []
24
32
  switch @get_object_type(object)
25
33
  when "array"
26
34
  for element, i in object
27
- s.push @serialize(element, prefix + "[]")
35
+ s.push @default_serializer(element, prefix + "[]")
28
36
  when "object"
29
- for own key, prop of object when prop?
30
- key = "#{prefix}[#{key}]" if prefix?
31
- s.push @serialize(prop, key)
37
+ for own key, prop of object
38
+ if !prop? and prefix?
39
+ prop = ""
40
+
41
+ if prop?
42
+ key = "#{prefix}[#{key}]" if prefix?
43
+ s.push @default_serializer(prop, key)
32
44
  else
33
- if object
45
+ if object?
34
46
  s.push "#{encodeURIComponent(prefix.toString())}=#{encodeURIComponent(object.toString())}"
35
47
 
36
48
  return "" unless s.length
37
49
  s.join("&")
38
50
 
51
+ custom_serializer: SERIALIZER
52
+ serialize: (object) ->
53
+ if @custom_serializer? and @get_object_type(@custom_serializer) is "function"
54
+ @custom_serializer(object)
55
+ else
56
+ @default_serializer(object)
57
+
39
58
  clean_path: (path) ->
40
59
  path = path.split("://")
41
60
  last_index = path.length - 1
42
61
  path[last_index] = path[last_index].replace(/\/+/g, "/")
43
62
  path.join "://"
44
63
 
45
- set_default_url_options: (optional_parts, options) ->
46
- for part, i in optional_parts when (not options.hasOwnProperty(part) and defaults.default_url_options.hasOwnProperty(part))
47
- options[part] = defaults.default_url_options[part]
48
-
49
- extract_anchor: (options) ->
50
- anchor = ""
51
- if options.hasOwnProperty("anchor")
52
- anchor = "##{options.anchor}"
53
- delete options.anchor
54
- anchor
55
-
56
- extract_trailing_slash: (options) ->
57
- trailing_slash = false
58
- if defaults.default_url_options.hasOwnProperty("trailing_slash")
59
- trailing_slash = defaults.default_url_options.trailing_slash
60
- if options.hasOwnProperty("trailing_slash")
61
- trailing_slash = options.trailing_slash
62
- delete options.trailing_slash
63
- trailing_slash
64
-
65
64
  extract_options: (number_of_params, args) ->
66
65
  last_el = args[args.length - 1]
67
- if args.length > number_of_params or (last_el? and "object" is @get_object_type(last_el) and !@look_like_serialized_model(last_el))
68
- args.pop()
66
+ if (args.length > number_of_params and last_el == undefined) or(last_el? and "object" is @get_object_type(last_el) and !@looks_like_serialized_model(last_el))
67
+ args.pop() || {}
69
68
  else
70
69
  {}
71
70
 
72
- look_like_serialized_model: (object) ->
71
+ looks_like_serialized_model: (object) ->
73
72
  # consider object a model if it have a path identifier properties like id and to_param
74
73
  "id" of object or "to_param" of object
75
74
 
@@ -96,33 +95,47 @@ Utils =
96
95
  copy[key] = attr for own key, attr of obj
97
96
  copy
98
97
 
99
- prepare_parameters: (required_parameters, actual_parameters, options) ->
100
- result = @clone(options) or {}
101
- for val, i in required_parameters when i < actual_parameters.length
102
- result[val] = actual_parameters[i]
98
+ merge: (xs...) ->
99
+ tap = (o, fn) -> fn(o); o
100
+ if xs?.length > 0
101
+ tap {}, (m) -> m[k] = v for k, v of x for x in xs
102
+
103
+ normalize_options: (default_parts, required_parameters, optional_parts, actual_parameters) ->
104
+ options = @extract_options(required_parameters.length, actual_parameters)
105
+ if actual_parameters.length > required_parameters.length
106
+ throw new Error("Too many parameters provided for path")
107
+ options = @merge(defaults.default_url_options, default_parts, options)
108
+ result = {}
109
+ url_parameters = {}
110
+ result['url_parameters'] = url_parameters
111
+ for own key, value of options
112
+ if @indexOf(ReservedOptions, key) >= 0
113
+ result[key] = value
114
+ else
115
+ url_parameters[key] = value
116
+
117
+ for value, i in required_parameters when i < actual_parameters.length
118
+ url_parameters[value] = actual_parameters[i]
103
119
  result
104
120
 
105
- build_path: (required_parameters, optional_parts, route, args) ->
121
+ build_route: (required_parameters, optional_parts, route, default_parts, full_url, args) ->
106
122
  args = Array::slice.call(args)
107
- opts = @extract_options(required_parameters.length, args)
108
123
 
109
- if args.length > required_parameters.length
110
- throw new Error("Too many parameters provided for path")
111
- parameters = @prepare_parameters(required_parameters, args, opts)
112
- @set_default_url_options optional_parts, parameters
113
- # options
114
- anchor = @extract_anchor(parameters)
115
- trailing_slash = @extract_trailing_slash(parameters)
124
+ options = @normalize_options(default_parts, required_parameters, optional_parts, args)
125
+ parameters = options['url_parameters']
126
+
116
127
  # path
117
128
  result = "#{@get_prefix()}#{@visit(route, parameters)}"
118
- url = Utils.clean_path("#{result}")
129
+ url = Utils.clean_path(result)
119
130
  # set trailing_slash
120
- url = url.replace(/(.*?)[\/]?$/, "$1/") if trailing_slash is true
131
+ url = url.replace(/(.*?)[\/]?$/, "$1/") if options['trailing_slash'] is true
121
132
  # set additional url params
122
133
  if (url_params = @serialize(parameters)).length
123
134
  url += "?#{url_params}"
124
135
  # set anchor
125
- url += anchor
136
+ url += if options.anchor then "##{options.anchor}" else ""
137
+ if full_url
138
+ url = @route_url(options) + url
126
139
  url
127
140
 
128
141
  #
@@ -148,7 +161,9 @@ Utils =
148
161
  when NodeTypes.CAT
149
162
  left_part = @visit(left, parameters, optional)
150
163
  right_part = @visit(right, parameters, optional)
151
- return "" if optional and not (left_part and right_part)
164
+ if optional and ((@is_optional_node(left[0]) and not left_part) or
165
+ ((@is_optional_node(right[0])) and not right_part))
166
+ return ""
152
167
  "#{left_part}#{right_part}"
153
168
  when NodeTypes.SYMBOL
154
169
  value = parameters[left]
@@ -167,6 +182,9 @@ Utils =
167
182
  else
168
183
  throw new Error("Unknown Rails node type")
169
184
 
185
+
186
+ is_optional_node: (node) -> @indexOf([NodeTypes.STAR, NodeTypes.SYMBOL, NodeTypes.CAT], node) >= 0
187
+
170
188
  #
171
189
  # This method build spec for route
172
190
  #
@@ -217,12 +235,44 @@ Utils =
217
235
  #
218
236
  # route function: create route path function and add spec to it
219
237
  #
220
- route: (required_parts, optional_parts, route_spec) ->
221
- path_fn = -> Utils.build_path(required_parts, optional_parts, route_spec, arguments)
238
+ route: (required_parts, optional_parts, route_spec, default_parts, full_url) ->
239
+ path_fn = -> Utils.build_route(
240
+ required_parts, optional_parts, route_spec, default_parts, full_url, arguments
241
+ )
222
242
  path_fn.required_params = required_parts
223
243
  path_fn.toString = -> Utils.build_path_spec(route_spec)
224
244
  path_fn
225
245
 
246
+
247
+ route_url: (route_defaults) ->
248
+ return route_defaults if typeof route_defaults == 'string'
249
+ protocol = route_defaults.protocol || Utils.current_protocol()
250
+ hostname = route_defaults.host || window.location.hostname
251
+ port = route_defaults.port || (Utils.current_port() unless route_defaults.host)
252
+ port = if port then ":#{port}" else ''
253
+
254
+ protocol + "://" + hostname + port
255
+
256
+
257
+ has_location: ->
258
+ typeof window != 'undefined' && typeof window.location != 'undefined'
259
+
260
+ current_host: ->
261
+ if @has_location() then window.location.hostname else null
262
+
263
+ current_protocol: () ->
264
+ if @has_location() && window.location.protocol != ''
265
+ # location.protocol includes the colon character
266
+ window.location.protocol.replace(/:$/, '')
267
+ else
268
+ 'http'
269
+
270
+ current_port: () ->
271
+ if @has_location() && window.location.port != ''
272
+ window.location.port
273
+ else
274
+ ''
275
+
226
276
  #
227
277
  # This is helper method to define object type.
228
278
  # The typeof operator is probably the biggest design flaw of JavaScript, simply because it's basically completely broken.
@@ -260,6 +310,13 @@ Utils =
260
310
  return "#{obj}" unless obj?
261
311
  (if typeof obj is "object" or typeof obj is "function" then @_classToType()[Object::toString.call(obj)] or "object" else typeof obj)
262
312
 
313
+ # indexOf helper
314
+ indexOf: (array, element) -> if Array::indexOf then array.indexOf(element) else @indexOfImplementation(array, element)
315
+ indexOfImplementation: (array, element) ->
316
+ result = -1
317
+ (result = i for el, i in array when el is element)
318
+ result
319
+
263
320
  # globalJsObject
264
321
  createGlobalJsRoutesObject = ->
265
322
  # namespace function, private
@@ -273,6 +330,8 @@ createGlobalJsRoutesObject = ->
273
330
  namespace(root, "NAMESPACE")
274
331
  root.NAMESPACE = ROUTES
275
332
  root.NAMESPACE.options = defaults
333
+ root.NAMESPACE.default_serializer = (object, prefix) ->
334
+ Utils.default_serializer(object, prefix)
276
335
  root.NAMESPACE
277
336
  # Set up Routes appropriately for the environment.
278
337
  if typeof define is "function" and define.amd
@@ -280,4 +339,4 @@ if typeof define is "function" and define.amd
280
339
  define [], -> createGlobalJsRoutesObject()
281
340
  else
282
341
  # Browser globals
283
- createGlobalJsRoutesObject()
342
+ createGlobalJsRoutesObject()