dress
Version:
missing javascript prototypes(experimental)
308 lines (255 loc) • 6.42 kB
text/coffeescript
root = if typeof global == 'undefined' then window else global
root.DRESS =
set: (object)->
if object.methods?
for name, fn of object.methods
root.Object.defineProperty(root[object.name].prototype, "$#{name}", { value: fn })
if object.injectors?
for method in object.injectors
(->
_method = method
root.Object.defineProperty root[object.name].prototype, '$$' + method, value: ->
this.$set(this['$' + _method].apply(this, arguments))
this
)()
if object.aliases?
for alias, method of object.aliases
root.Object.defineProperty root[object.name].prototype, alias, value: root[object.name]::[method]
##########
# ARRAYS #
##########
DRESS.set
name: 'Array'
injectors : ['map', 'slice', 'sort', 'samples', 'where', 'reverse', 'filter', 'reject', 'take', 'drop', 'invoke', 'pluck', 'shuffle']
aliases:
'$map': 'map'
'$filter': 'filter'
methods:
set: (array) ->
this.length = 0
this.push item for item in array
this
first: ->
this[0]
last: ->
this[this.length - 1]
find: (fn) ->
for item in this
return item if fn(item)
contains: (object) ->
if this.indexOf(object) == -1
false
else
true
max: (fn) ->
if fn?
max = fn(this[0])
result = this[0]
for item in this
fn_result = fn(item)
if fn_result > max
result = item
max = fn_result
result
else
Math.max.apply(null, this)
min: (fn) ->
if fn?
min = fn(this[0])
result = this[0]
for item in this
fn_result = fn(item)
if fn_result < min
result = item
min = fn_result
result
else
Math.min.apply(null, this)
sort: (fn = (item)-> item) ->
result = []
result.push(item) for item in this
root.Array::sort.call result, (a, b)->
fn(a) > fn(b)
samples: (count=1)->
checked = []
result = []
while count > 0
index = Math.floor(Math.random() * this.length)
continue if checked.$contains(index)
checked.push(index)
result.push(this[index])
count--
result
sample: ->
this.$samples().$first()
each: (fn)->
this.forEach(fn)
this
where: (object) ->
result = []
for item in this
found = true
for k, v of object
found = false if item[k] isnt v
result.push item if found
result
reject: (fn) ->
this.$filter (item) -> not fn(item)
take: (count) ->
result = []
index = 0
while index != count
result.push this[index]
index++
result
drop: (count) ->
result = []
for i in [count..this.length - 1]
result.push this[i]
result
invoke: (fn_name) ->
result = []
for item in this
delete arguments[0]
result.push item[fn_name].apply(item, arguments.$values())
result
pluck: (key) ->
result = []
result.push(item[key]) for item in this
result
group: (fn) ->
result = {}
for item in this
if fn.$is_function()
result[fn(item)] ?= []
result[fn(item)].push(item)
else
result[item[fn]] ?= []
result[item[fn]].push(item)
result
count: (fn) ->
object = {}
for item in this
object[fn(item)] ?= 0
object[fn(item)]++
object
shuffle: ->
this.$samples(this.length)
###########
# OBJECTS #
###########
DRESS.set
name: 'Object'
injectors: ['pick', 'invert', 'merge', 'omit', 'defaults']
aliases:
'$is_function': '$isFunction'
'$is_array': '$isArray'
'$is_empty': '$isEmpty'
'$is_string': '$isString'
'$is_number': '$isNumber'
'$is_boolean': '$isBoolean'
'$is_date': '$isDate'
methods:
set: (object) ->
delete this[k] for k, v of this
this[k] = v for k, v of object
this
pick: ->
result = {}
for k,v of this
result[k] = v if k in arguments
result
keys: ->
Object.keys(this)
values: ->
result = []
for k, v of this
result.push(v)
result
isFunction: ->
typeof this is 'function'
isArray: ->
this instanceof Array
invert: ->
object = {}
for k, v of this
object[v] = k
object
each: (fn)->
for k, v of this
fn(k, v)
this
pairs: ->
result = []
this.$each (k, v) -> result.push([k, v])
result
functions: ->
result = []
this.$each (k, v) -> result.push(k) if v.$is_function()
result
merge: (object) ->
result = this.$clone()
object.$each (k, v) -> result[k] = v
result
omit: (list) ->
list = arguments.$values() unless list.$is_array()
object = {}
this.$each (k, v) -> object[k] = v unless list.$contains(k)
object
defaults: (object) ->
result = this.$clone()
object.$each (k, v) -> result[k] = v unless result[k]?
result
clone: (object) ->
result = {}
this.$each (k, v) -> result[k] = v
result
tap: (fn) ->
fn()
this
isEmpty: ->
Object.keys(this).length is 0
isString: ->
toString.call(this) == '[object String]'
isNumber: ->
toString.call(this) == '[object Number]'
isBoolean: ->
toString.call(this) == '[object Boolean]'
isDate: ->
toString.call(this) == '[object Date]'
json: ->
JSON.stringify(this)
###########
# STRINGS #
###########
DRESS.set
name: 'String'
methods:
starts: (string) ->
this.indexOf(string) == 0
ends: (string) ->
this.slice(-string.length) == string
capitalize: ->
this.charAt(0).toUpperCase() + this.substring(1).toLowerCase()
titleize: ->
(this.split(' ').map (word) -> word.$capitalize()).join(' ')
integer: ->
parseInt(this)
number: ->
parseFloat(this)
date: ->
new Date(Date.parse(this))
parse: ->
JSON.parse(this)
###########
# NUMBERS #
###########
DRESS.set
name: 'Number'
methods:
times: (fn) ->
for i in [0..this - 1]
fn(i)
this
date: ->
new Date(this)