chr 0.1.4 → 0.1.5

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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/Gruntfile.coffee +22 -21
  3. data/app/assets/javascripts/chr-dist.js +307 -262
  4. data/app/assets/javascripts/chr.coffee +22 -21
  5. data/app/assets/javascripts/chr/core/{_chr.coffee → chr.coffee} +0 -0
  6. data/app/assets/javascripts/chr/core/{_item.coffee → item.coffee} +2 -2
  7. data/app/assets/javascripts/chr/core/{_listReorder.coffee → list-reorder.coffee} +1 -1
  8. data/app/assets/javascripts/chr/core/{_listScroll.coffee → list-scroll.coffee} +1 -1
  9. data/app/assets/javascripts/chr/core/{_listSearch.coffee → list-search.coffee} +0 -0
  10. data/app/assets/javascripts/chr/core/{_list.coffee → list.coffee} +2 -0
  11. data/app/assets/javascripts/chr/core/{_module.coffee → module.coffee} +0 -0
  12. data/app/assets/javascripts/chr/core/{_utils.coffee → utils.coffee} +0 -0
  13. data/app/assets/javascripts/chr/core/{_view.coffee → view.coffee} +2 -2
  14. data/app/assets/javascripts/chr/form/{_form.coffee → form.coffee} +0 -0
  15. data/app/assets/javascripts/chr/form/{_inputCheckbox.coffee → input-checkbox.coffee} +0 -0
  16. data/app/assets/javascripts/chr/form/{_inputColor.coffee → input-color.coffee} +0 -0
  17. data/app/assets/javascripts/chr/form/{_inputFile.coffee → input-file.coffee} +0 -0
  18. data/app/assets/javascripts/chr/form/{_inputHidden.coffee → input-hidden.coffee} +0 -0
  19. data/app/assets/javascripts/chr/form/{_inputList.coffee → input-list.coffee} +0 -0
  20. data/app/assets/javascripts/chr/form/{_inputSelect.coffee → input-select.coffee} +0 -0
  21. data/app/assets/javascripts/chr/form/{_inputString.coffee → input-string.coffee} +0 -0
  22. data/app/assets/javascripts/chr/form/{_inputText.coffee → input-text.coffee} +0 -0
  23. data/app/assets/javascripts/chr/form/{_nestedForm.coffee → nested-form.coffee} +0 -0
  24. data/app/assets/javascripts/chr/store/store-mongosteen.coffee +111 -0
  25. data/app/assets/javascripts/chr/store/store-rest.coffee +90 -0
  26. data/app/assets/javascripts/chr/store/store.coffee +274 -0
  27. data/chr.gemspec +2 -2
  28. data/lib/chr/version.rb +1 -1
  29. data/package.json +1 -1
  30. metadata +26 -25
  31. data/app/assets/javascripts/chr/store/_store.coffee +0 -104
  32. data/app/assets/javascripts/chr/store/_storeRails.coffee +0 -167
@@ -3,27 +3,28 @@
3
3
  #= require ./chr/vendor/jquery.typeahead
4
4
  #= require ./chr/vendor/slip
5
5
 
6
- #= require ./chr/core/_item
7
- #= require ./chr/core/_list
8
- #= require ./chr/core/_listSearch
9
- #= require ./chr/core/_listScroll
10
- #= require ./chr/core/_listReorder
11
- #= require ./chr/core/_view
12
- #= require ./chr/core/_module
6
+ #= require ./chr/core/item
7
+ #= require ./chr/core/list
8
+ #= require ./chr/core/list-search
9
+ #= require ./chr/core/list-scroll
10
+ #= require ./chr/core/list-reorder
11
+ #= require ./chr/core/view
12
+ #= require ./chr/core/module
13
13
 
14
- #= require ./chr/form/_form
15
- #= require ./chr/form/_inputString
16
- #= require ./chr/form/_inputCheckbox
17
- #= require ./chr/form/_inputColor
18
- #= require ./chr/form/_inputFile
19
- #= require ./chr/form/_inputHidden
20
- #= require ./chr/form/_inputList
21
- #= require ./chr/form/_inputSelect
22
- #= require ./chr/form/_inputText
23
- #= require ./chr/form/_nestedForm
14
+ #= require ./chr/form/form
15
+ #= require ./chr/form/input-string
16
+ #= require ./chr/form/input-checkbox
17
+ #= require ./chr/form/input-color
18
+ #= require ./chr/form/input-file
19
+ #= require ./chr/form/input-hidden
20
+ #= require ./chr/form/input-list
21
+ #= require ./chr/form/input-select
22
+ #= require ./chr/form/input-text
23
+ #= require ./chr/form/nested-form
24
24
 
25
- #= require ./chr/store/_store
26
- #= require ./chr/store/_storeRails
25
+ #= require ./chr/store/store
26
+ #= require ./chr/store/store-rest
27
+ #= require ./chr/store/store-mongosteen
27
28
 
28
- #= require ./chr/core/_utils
29
- #= require ./chr/core/_chr
29
+ #= require ./chr/core/utils
30
+ #= require ./chr/core/chr
@@ -76,8 +76,8 @@ class @Item
76
76
  @$el.remove()
77
77
 
78
78
  position: ->
79
- fieldName = @config.arrayStore.sortBy
80
- @object[fieldName]
79
+ positionFieldName = @config.arrayStore.sortBy
80
+ parseFloat(@object[positionFieldName])
81
81
 
82
82
 
83
83
 
@@ -53,7 +53,7 @@
53
53
  objectPositionValue = _getObjectNewPosition(e.target)
54
54
  objectId = $(e.target).attr('data-id')
55
55
  value = {}
56
- value["[#{arrayStore.sortBy}"] = objectPositionValue
56
+ value["[#{arrayStore.sortBy}"] = "#{ objectPositionValue }"
57
57
 
58
58
  arrayStore.update objectId, value,
59
59
  # NOTE: error handling
@@ -15,7 +15,7 @@
15
15
  viewHeight = $container.height()
16
16
 
17
17
  if listHeight < (viewHeight + e.target.scrollTop + 100)
18
- listEl._loading -> arrayStore.fetchNextPage()
18
+ listEl._loading -> arrayStore.load()
19
19
 
20
20
 
21
21
 
@@ -116,6 +116,8 @@ class @List
116
116
  if @config.arrayStore then @_bindConfigArrayStore()
117
117
  if @config.objectStore then @_bindConfigObjectStore()
118
118
 
119
+ @config.onListInit?(@)
120
+
119
121
  selectItem: (href) ->
120
122
  @$items.children("a[href='#{ href }']").addClass 'active'
121
123
 
@@ -100,8 +100,8 @@ class @View
100
100
 
101
101
  onSave: (e) ->
102
102
  e.preventDefault()
103
- serializedObj = @form.serialize()
104
- if @object then @_updateObject(serializedObj) else @_createObject(serializedObj)
103
+ serializedFormObj = @form.serialize()
104
+ if @object then @_updateObject(serializedFormObj) else @_createObject(serializedFormObj)
105
105
 
106
106
  onDelete: (e) ->
107
107
  e.preventDefault()
@@ -0,0 +1,111 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Author: Alexander Kravets <alex@slatestudio.com>,
3
+ # Slate Studio (http://www.slatestudio.com)
4
+ #
5
+ # Coding Guide:
6
+ # https://github.com/thoughtbot/guides/tree/master/style/coffeescript
7
+ # -----------------------------------------------------------------------------
8
+
9
+ # -----------------------------------------------------------------------------
10
+ # MONGOSTEEN (RAILS) ARRAY/COLLECTION STORE IMPLEMENTATION
11
+ # -----------------------------------------------------------------------------
12
+ class @MongosteenArrayStore extends RestArrayStore
13
+ # initial store configuration
14
+ _initialize_database: ->
15
+ @dataFetchLock = false
16
+ @ajaxConfig =
17
+ processData: false
18
+ contentType: false
19
+
20
+ @searchable = @config.searchable ? false
21
+ @searchQuery = ''
22
+
23
+ @pagination = @config.pagination ? true
24
+ @pagesCounter = 0
25
+
26
+ # disable pagination when bootstraped data provided
27
+ if @config.data
28
+ @pagination = false
29
+
30
+
31
+ # generate resource api url
32
+ _resource_url: (type, id) ->
33
+ objectPath = if id then "/#{ id }" else ''
34
+ url = "#{ @config.path }#{ objectPath }.json"
35
+
36
+ if @config.urlParams
37
+ extraParamsString = $.param(@config.urlParams)
38
+ url = "#{ url }?#{ extraParamsString }"
39
+
40
+ return url
41
+
42
+
43
+ # get form data object from serialized form object,
44
+ # it uses special format for object names for support of:
45
+ # files, lists, nested objects
46
+ _parse_form_object: (serializedFormObject) ->
47
+ formDataObject = new FormData()
48
+
49
+ for attr_name, attr_value of serializedFormObject
50
+
51
+ # special case for LIST inputs, values separated with comma
52
+ if attr_name.indexOf('[__LIST__') > -1
53
+ attr_name = attr_name.replace('__LIST__', '')
54
+ values = attr_value.split(',')
55
+
56
+ for value in values
57
+ formDataObject.append("#{ @config.resource }#{ attr_name }[]", value)
58
+
59
+ else
60
+ # special case for FILE inputs
61
+ if attr_name.startsWith('__FILE__')
62
+ attr_name = attr_name.replace('__FILE__', '')
63
+
64
+ formDataObject.append("#{ @config.resource }#{ attr_name }", attr_value)
65
+
66
+ return formDataObject
67
+
68
+
69
+ # load next page objects from database, when finished
70
+ # trigger 'objects_added' event
71
+ load: (success) ->
72
+ params = {}
73
+
74
+ if @pagination
75
+ params.page = @pagesCounter + 1
76
+ params.perPage = _itemsPerPageRequest ? 20
77
+
78
+ if @searchable && @searchQuery.length > 0
79
+ params.search = @searchQuery
80
+
81
+ params = $.param(params)
82
+
83
+ @_ajax 'GET', null, params, ((dataObject) =>
84
+ if dataObject.length > 0
85
+ @pagesCounter = @pagesCounter + 1
86
+
87
+ for o in dataObject
88
+ @_add_data_object(o)
89
+
90
+ success?()
91
+ $(this).trigger('objects_added')
92
+ ) #, callbacks.onError
93
+
94
+
95
+ # load results for search query
96
+ search: (@searchQuery, callback) ->
97
+ @pagesCounter = 0
98
+ @_reset_data()
99
+ @load(callback)
100
+
101
+
102
+ # reset data and load first page
103
+ reset: (callback) ->
104
+ @searchQuery = ''
105
+ @pagesCounter = 0
106
+ @_reset_data()
107
+ @load(callback)
108
+
109
+
110
+
111
+
@@ -0,0 +1,90 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Author: Alexander Kravets <alex@slatestudio.com>,
3
+ # Slate Studio (http://www.slatestudio.com)
4
+ #
5
+ # Coding Guide:
6
+ # https://github.com/thoughtbot/guides/tree/master/style/coffeescript
7
+ # -----------------------------------------------------------------------------
8
+
9
+ # -----------------------------------------------------------------------------
10
+ # REST ARRAY STORE
11
+ # -----------------------------------------------------------------------------
12
+ class @RestArrayStore extends ArrayStore
13
+ # initial store configuration
14
+ _initialize_database: ->
15
+ @dataFetchLock = false
16
+ @ajaxConfig = {}
17
+
18
+
19
+ # generate rest url for resource
20
+ _resource_url: (type, id) ->
21
+ objectPath = if id then "/#{ id }" else ''
22
+ "#{ @config.path }#{ objectPath }"
23
+
24
+
25
+ # do requests to database api
26
+ _ajax: (type, id, data, success, error) ->
27
+ options = $.extend @ajaxConfig,
28
+ url: @_resource_url(type, id)
29
+ type: type
30
+ data: data
31
+ success: (data, textStatus, jqXHR) =>
32
+ @dataFetchLock = false
33
+ success?(data)
34
+ error: (jqXHR, textStatus, errorThrown ) =>
35
+ @dataFetchLock = false
36
+ error?(jqXHR.responseJSON)
37
+
38
+ @dataFetchLock = true
39
+ $.ajax options
40
+
41
+
42
+ # load objects from database, when finished
43
+ # trigger 'objects_added' event
44
+ load: (success) ->
45
+ @_ajax 'GET', null, {}, ((dataObject) =>
46
+ if dataObject.length > 0
47
+ for o in dataObject
48
+ @_add_data_object(o)
49
+
50
+ success?()
51
+ $(this).trigger('objects_added')
52
+ ) #, callbacks.onError
53
+
54
+
55
+ # add new object
56
+ push: (serializedFormObject, callbacks) ->
57
+ obj = @_parse_form_object(serializedFormObject)
58
+
59
+ @_ajax 'POST', null, obj, ((dataObject) =>
60
+ if @newItemOnTop
61
+ @_add_data_object_on_top(dataObject, callbacks.onSuccess)
62
+ else
63
+ @_add_data_object(dataObject, callbacks.onSuccess)
64
+ ), callbacks.onError
65
+
66
+
67
+ # update objects attributes
68
+ update: (id, serializedFormObject, callbacks) ->
69
+ obj = @_parse_form_object(serializedFormObject)
70
+
71
+ @_ajax 'PUT', id, obj, ((dataObject) =>
72
+ @_update_data_object(id, dataObject, callbacks.onSuccess)
73
+ ), callbacks.onError
74
+
75
+
76
+ # delete object
77
+ remove: (id) ->
78
+ @_ajax 'DELETE', id, {}, ( =>
79
+ @_remove_data_object(id)
80
+ ), # callbacks.onError
81
+
82
+
83
+ # reset all data and load it again
84
+ reset: (callback) ->
85
+ @_reset_data()
86
+ @load(callback)
87
+
88
+
89
+
90
+
@@ -0,0 +1,274 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Author: Alexander Kravets <alex@slatestudio.com>,
3
+ # Slate Studio (http://www.slatestudio.com)
4
+ #
5
+ # Coding Guide:
6
+ # https://github.com/thoughtbot/guides/tree/master/style/coffeescript
7
+ # -----------------------------------------------------------------------------
8
+
9
+ # -----------------------------------------------------------------------------
10
+ # OBJECT STORE
11
+ # -----------------------------------------------------------------------------
12
+ class @ObjectStore
13
+ constructor: (@config={}) ->
14
+ @_initialize_database()
15
+
16
+ _update_data_object: (value, callback) ->
17
+ callback?($.extend(@_data, value))
18
+
19
+ _fetch_data: ->
20
+ @_data = @config.data
21
+
22
+ _initialize_database: ->
23
+ @_fetch_data()
24
+
25
+ get: ->
26
+ @_data
27
+
28
+ update: (id, value, callback) ->
29
+ @_update_data_object(value, callback)
30
+
31
+
32
+ # -----------------------------------------------------------------------------
33
+ # ARRAY STORE
34
+ # javascript object storage implementation that stores/loads objects in memory,
35
+ # no backend database support here, supported features are:
36
+ # - new / update / remove
37
+ # - sorting
38
+ # - reordering
39
+ #
40
+ # configuration options:
41
+ # @config.data — initial array of objects, default: []
42
+ # @config.sortBy — objects field name which is used for sorting, does
43
+ # not sort when parameter is not provided, default: nil
44
+ # @config.sortReverse — reverse objects sorting (descending order),
45
+ # default: false
46
+ # @config.newItemOnTop — add new item to the top of the list, default: true,
47
+ # if @config.sortBy is not set, otherwise: false
48
+ # @config.reorderable — list items reordering configuration hash, should
49
+ # have two fields:
50
+ # { positionFieldName: '',
51
+ # sortReverse: false }
52
+ #
53
+ # public methods:
54
+ # - on(eventType, callback)
55
+ # - off(eventType)
56
+ # - get(id)
57
+ # - push(serializedFormObject, callbacks)
58
+ # - update(serializedFormObject, callbacks)
59
+ # - remove(id)
60
+ # - reset(callback)
61
+ #
62
+ # todo:
63
+ # - support for lists, files, nested objects
64
+ # -----------------------------------------------------------------------------
65
+ class @ArrayStore
66
+ constructor: (@config={}) ->
67
+ @_map = {} # objecs map for fast access by id
68
+ @_data = [] # stores objects in order
69
+
70
+ @sortBy = @config.sortBy ? false
71
+ @sortReverse = @config.sortReverse ? false
72
+ @reorderable = @config.reorderable ? false
73
+
74
+ if @sortBy == false
75
+ @newItemOnTop = @config.newItemOnTop ? true
76
+ else
77
+ @newItemOnTop = @config.newItemOnTop ? false
78
+
79
+ @_initialize_reorderable()
80
+ @_initialize_database()
81
+
82
+
83
+ # when store is reorderable update sorting configuration
84
+ _initialize_reorderable: ->
85
+ if @reorderable
86
+ if @reorderable.positionFieldName
87
+ @sortBy = @reorderable.positionFieldName
88
+ @sortReverse = @reorderable.sortReverse ? false
89
+ else
90
+ console.log 'Wrong reordering configuration, missing positionFieldName parameter.'
91
+ @reorderable = false
92
+
93
+
94
+ # this method should be overriden for database initialization
95
+ # and config processing when implementing custom store
96
+ _initialize_database: ->
97
+ ;
98
+
99
+
100
+ # add objects from @config.data,
101
+ # trigger 'objects_added' event
102
+ _fetch_data: ->
103
+ if @config.data
104
+ @_add_data_object(o) for o in @config.data
105
+
106
+ $(this).trigger('objects_added')
107
+
108
+
109
+ # sort object in _data array based on sortBy and sortReverse parameters
110
+ # implementatin details:
111
+ # http://stackoverflow.com/questions/9796764/how-do-i-sort-an-array-with-coffeescript
112
+ _sort_data: ->
113
+ if @sortBy
114
+ fieldName = @sortBy
115
+ direction = if @sortReverse then 1 else -1
116
+
117
+ sortByMethod = (key, a, b, dir) ->
118
+ if a[key] > b[key] then return -1*dir
119
+ if a[key] < b[key] then return +1*dir
120
+ return 0
121
+
122
+ @_data = @_data.sort (a, b) -> sortByMethod(fieldName, a, b, direction)
123
+
124
+
125
+ # gets objects position in _data array by objects id
126
+ _get_data_object_position: (id) ->
127
+ ids = []
128
+ for o in @_data
129
+ if o then ids.push(o._id)
130
+ $.inArray id, ids
131
+
132
+
133
+ # if objects id stored in id field, map it to _id as this is one
134
+ # which is used internally, this method might be more sophisticated
135
+ _normalize_object_id: (object) ->
136
+ if object.id
137
+ object._id = object.id
138
+ delete object.id
139
+ return object
140
+
141
+
142
+ # normalize objects id, add object to _data and _map, sort objects,
143
+ # trigger 'object_added' event
144
+ _add_data_object: (object, callback)->
145
+ object = @_normalize_object_id(object)
146
+
147
+ @_map[object._id] = object
148
+ @_data.push(object)
149
+
150
+ @_sort_data()
151
+ position = @_get_data_object_position(object._id)
152
+
153
+ $(this).trigger('object_added', { object: object, position: position, callback: callback })
154
+
155
+
156
+ # add object to the top of the _data neglecting ordering,
157
+ # trigger 'object_added' event
158
+ _add_data_object_on_top: (object, callback) ->
159
+ object = @_normalize_object_id(object)
160
+
161
+ @_map[object._id] = object
162
+ @_data.unshift(object)
163
+
164
+ position = 0
165
+
166
+ $(this).trigger('object_added', { object: object, position: position, callback: callback })
167
+
168
+
169
+ # get object by id, update it's attributes, sort objects,
170
+ # trigger 'object_changed' event
171
+ _update_data_object: (id, value, callback) ->
172
+ object = $.extend(@get(id), value)
173
+
174
+ @_sort_data()
175
+ position = @_get_data_object_position(id)
176
+
177
+ $(this).trigger('object_changed', { object: object, position: position, callback: callback })
178
+
179
+
180
+ # delete object by id from _data and _map,
181
+ # trigger 'object_removed' event
182
+ _remove_data_object: (id) ->
183
+ position = @_get_data_object_position(id)
184
+ if position >= 0
185
+ delete @_data[position]
186
+
187
+ delete @_map[id]
188
+
189
+ $(this).trigger('object_removed', { object_id: id })
190
+
191
+
192
+ # remove all objects from _data and _map,
193
+ # trigger 'object_removed' event for each
194
+ _reset_data: ->
195
+ for id, o of @_map
196
+ $(this).trigger('object_removed', { object_id: id })
197
+
198
+ @_map = {}
199
+ @_data = []
200
+
201
+
202
+ # get regular javascript object from serialized form object,
203
+ # which uses special format for object names for support of:
204
+ # - files
205
+ # - lists
206
+ # - nested objects
207
+ _parse_form_object: (serializedFormObject) ->
208
+ # this is very basic and have to be expanded to support all form inputs:
209
+ # - lists, files, nested objects
210
+ object = {}
211
+ for key, value of serializedFormObject
212
+ fieldName = key.replace('[', '').replace(']', '')
213
+ object[fieldName] = value
214
+ return object
215
+
216
+
217
+ # unsubscribe from store event, simple jQuery wrapper
218
+ off: (eventType) ->
219
+ if eventType then $(this).off(eventType) else $(this).off()
220
+
221
+
222
+ # subsribe to store event, subscribing to 'object_added' fetches data,
223
+ # available event types:
224
+ # - object_added
225
+ # - object_changed
226
+ # - object_removed
227
+ # - objects_added
228
+ on: (eventType, callback) ->
229
+ $(this).on eventType, (e, data) -> callback(e, data)
230
+
231
+ #! make sure this run only for first subscribe
232
+ if eventType == 'object_added'
233
+ @_fetch_data()
234
+
235
+
236
+ # get object by id
237
+ get: (id) ->
238
+ @_map[id]
239
+
240
+
241
+ # add new object
242
+ push: (serializedFormObject, callbacks) ->
243
+ object = @_parse_form_object(serializedFormObject)
244
+ if ! object._id then object._id = Date.now()
245
+
246
+ if @newItemOnTop
247
+ @_add_data_object_on_top(object, callbacks.onSuccess)
248
+ else
249
+ @_add_data_object(object, callbacks.onSuccess)
250
+
251
+
252
+ # update objects attributes
253
+ update: (id, serializedFormObject, callbacks) ->
254
+ object = @_parse_form_object(serializedFormObject)
255
+ @_update_data_object(id, object, callbacks.onSuccess)
256
+
257
+
258
+ # delete object
259
+ remove: (id) ->
260
+ @_remove_data_object(id)
261
+
262
+
263
+ # reset all data and load it again
264
+ reset: (callback) ->
265
+ # do nothing here as data is stored in memory, this method
266
+ # resets database data, syncing latest changes
267
+ @_sort_data()
268
+
269
+ $(this).trigger('objects_added')
270
+ callback?()
271
+
272
+
273
+
274
+