forked from deleteme/params.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
params.coffee
139 lines (117 loc) · 3.54 KB
/
params.coffee
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
# params.js 0.6.0
# a small library to create a URL by adding and removing params while
# preserving existing params
do ->
root = exports ? this
class root.Params
constructor: (_location)->
@_location = _location or root.location
@_search = @_location.search
@_prefix = @_location.protocol + '//' + @_location.host + @_location.pathname
@_params = {}
@_pairs = []
# setup
# warn if invalid object
unless @validate @_search
#throw "Initializing Params with invalid location.search."
return false;
# build _params keys
@_params = Params.parse @_search
@_buildPairs()
# internal setting of a single pair
_set: (key, value)->
@_params[key] = value
@_buildPairs()
value
# internal helper method to build an array of pairs
_buildPairs: ->
@_pairs = for key of @_params
if Object.prototype.toString.call(@_params[key]) is "[object Array]"
(for item of @_params[key]
"#{key}=#{@_params[key][item]}"
).join('&')
else
"#{key}=#{@_params[key]}"
# build the full url, similar to location.href
href: ->
@_prefix + @search()
# build only the params, similar to location.search
search: ->
if @_pairs.length
"?" + @_pairs.join('&')
else
""
# add data to the params
# usage:
# set(key, value)
# set({
# key: value,
# anotherKey: anotherValue
# })
#
# returns the params object, so it's chainable
set: ->
arg = arguments[0]
# if a simple pair
if typeof arg is 'string' or typeof arg is 'number'
@_set String(arg), arguments[1]
else if typeof arg is 'object'
for key of arg
@_set key, arg[key]
else
throw "Unexpected data type for: #{arg}. Should be a string, number, or object"
@
# removes a pair
# returns the params object, so you can chain it
unset: (key)->
value = @_params[key]
delete @_params[key]
@_buildPairs()
@
# an internal array of validations
# if it passes the validation, it returns true
_validations: [
# it's a string
(string)-> typeof string is 'string'
# should start with ?
(string)-> if string.length then string.match(/^\?/) else true,
# it shouldn't end with &
(string)-> !string.match(/&$/)
]
# validates the internal params
# or a string passed to it
validate: (string) ->
# innocent until proven guilty
valid = true
# try each validation
for validation in @_validations
valid = validation(string)
if not valid
break
valid
get: (key)-> @_params[key]
# shallow copy the @_params
object: ->
obj = {}
for key of @_params
obj[key] = @_params[key]
obj
# a static method to turn a param string into an object
root.Params.parse = (paramString)->
paramObj = {}
paramArray = []
if paramString.length > 1
# build _params keys
# remove the leading ? character, and split on &
paramArray = paramString[(1 + paramString.indexOf('?'))...paramString.length].split('&')
for pair in paramArray
pair = pair.split '='
k = pair[0]
v = pair[1]
if k of paramObj
if Object.prototype.toString.call(paramObj[k]) isnt '[object Array]'
paramObj[k] = [paramObj[k]]
paramObj[k].push decodeURIComponent v
else
paramObj[k] = decodeURIComponent v
paramObj