chr 0.1.5 → 0.2.0
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.
- checksums.yaml +4 -4
- data/Gruntfile.coffee +6 -3
- data/LICENSE.md +1 -1
- data/README.md +286 -7
- data/app/assets/javascripts/chr-dist.js +1031 -580
- data/app/assets/javascripts/chr.coffee +7 -4
- data/app/assets/javascripts/chr/core/chr.coffee +88 -37
- data/app/assets/javascripts/chr/core/item.coffee +57 -35
- data/app/assets/javascripts/chr/core/{list-scroll.coffee → list-pagination.coffee} +6 -3
- data/app/assets/javascripts/chr/core/list-reorder.coffee +3 -3
- data/app/assets/javascripts/chr/core/list-search.coffee +20 -11
- data/app/assets/javascripts/chr/core/list.coffee +163 -89
- data/app/assets/javascripts/chr/core/module.coffee +75 -35
- data/app/assets/javascripts/chr/core/view.coffee +117 -61
- data/app/assets/javascripts/chr/store/{store.coffee → _array-store.coffee} +53 -106
- data/app/assets/javascripts/chr/store/_object-store.coffee +28 -0
- data/app/assets/javascripts/chr/store/mongosteen-array-store.coffee +199 -0
- data/app/assets/javascripts/chr/store/mongosteen-object-store.coffee +52 -0
- data/app/assets/javascripts/chr/store/rest-array-store.coffee +142 -0
- data/app/assets/javascripts/chr/store/rest-object-store.coffee +79 -0
- data/app/assets/stylesheets/core/_list.scss +20 -25
- data/app/assets/stylesheets/core/_main.scss +3 -4
- data/app/assets/stylesheets/core/_mixins.scss +33 -2
- data/app/assets/stylesheets/core/_responsive.scss +30 -9
- data/app/assets/stylesheets/form/_input_checkbox.scss +18 -14
- data/bower.json +3 -2
- data/chr.gemspec +1 -1
- data/docs/assets.md +0 -0
- data/docs/basics.md +0 -0
- data/docs/bootstrap-data.md +0 -0
- data/docs/custom-inputs.md +0 -0
- data/docs/form.md +0 -0
- data/docs/internals.md +0 -0
- data/docs/nested-forms.md +0 -0
- data/docs/redactor-js.md +0 -0
- data/docs/scopes.md +0 -0
- data/lib/chr/version.rb +1 -1
- data/package.json +1 -1
- metadata +19 -7
- data/app/assets/javascripts/chr/store/store-mongosteen.coffee +0 -111
- data/app/assets/javascripts/chr/store/store-rest.coffee +0 -90
|
@@ -1,5 +1,18 @@
|
|
|
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
|
+
|
|
1
9
|
# -----------------------------------------------------------------------------
|
|
2
10
|
# MODULE
|
|
11
|
+
#
|
|
12
|
+
# configuration options:
|
|
13
|
+
# title - title used for menu and root list header
|
|
14
|
+
# showNestedListsAside - show module root list on the left and all nested
|
|
15
|
+
# lists on the right side for desktop
|
|
3
16
|
# -----------------------------------------------------------------------------
|
|
4
17
|
class @Module
|
|
5
18
|
constructor: (@chr, @name, @config) ->
|
|
@@ -8,57 +21,79 @@ class @Module
|
|
|
8
21
|
@$el = $("<section class='module #{ @name }' style='display: none;'>")
|
|
9
22
|
@chr.$el.append @$el
|
|
10
23
|
|
|
24
|
+
# root list
|
|
25
|
+
@activeList = @rootList = new List(this, @name, @config)
|
|
26
|
+
|
|
27
|
+
# menu item + layout
|
|
11
28
|
menuTitle = @config.menuTitle ? @config.title
|
|
12
29
|
menuTitle ?= @name.titleize()
|
|
13
|
-
@
|
|
30
|
+
menuPath = @name
|
|
14
31
|
|
|
15
|
-
|
|
32
|
+
# do not hide root list layout, nested lists are shown on aside
|
|
33
|
+
if @config.showNestedListsAside
|
|
34
|
+
@$el.addClass 'first-list-aside'
|
|
35
|
+
# jump to first nested list on menu click
|
|
36
|
+
firstNestedList = _firstNonEmptyValue(@nestedLists)
|
|
37
|
+
if ! _isMobile() && firstNestedList
|
|
38
|
+
menuPath += "/#{ firstNestedList.name }"
|
|
39
|
+
|
|
40
|
+
@chr.addMenuItem(menuPath, menuTitle)
|
|
16
41
|
|
|
42
|
+
@config.onModuleInit?(this)
|
|
17
43
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
44
|
+
|
|
45
|
+
# update list data if it's not visible, e.g. for update action we do not
|
|
46
|
+
# update whole list, this method is called before active list is shown.
|
|
47
|
+
_update_active_list_items: ->
|
|
21
48
|
if not @activeList.isVisible()
|
|
22
49
|
@activeList.updateItems()
|
|
23
50
|
|
|
51
|
+
|
|
52
|
+
# returns path for the current list
|
|
53
|
+
_view_path: ->
|
|
54
|
+
currentList = @visibleNestedListShownWithParent() ? @activeList
|
|
55
|
+
currentList.path
|
|
56
|
+
|
|
57
|
+
|
|
24
58
|
addNestedList: (listName, config, parentList) ->
|
|
25
59
|
@nestedLists[listName] = new List(this, listName, config, parentList)
|
|
26
60
|
|
|
27
|
-
selectActiveListItem: (href) ->
|
|
28
|
-
@unselectActiveListItem()
|
|
29
|
-
@activeList.selectItem(href)
|
|
30
|
-
|
|
31
|
-
unselectActiveListItem: ->
|
|
32
|
-
@activeList?.unselectItems()
|
|
33
61
|
|
|
34
62
|
hideActiveList: (animate=false)->
|
|
35
63
|
if animate then @activeList.$el.fadeOut() else @activeList.$el.hide()
|
|
36
64
|
@activeList = @activeList.parentList
|
|
37
|
-
|
|
65
|
+
|
|
38
66
|
|
|
39
67
|
showView: (object, config, title, animate=false) ->
|
|
40
|
-
newView = new View(this, config, @
|
|
68
|
+
newView = new View(this, config, @_view_path(), object, title)
|
|
41
69
|
@chr.$el.append(newView.$el)
|
|
42
70
|
|
|
43
|
-
@selectActiveListItem(location.hash)
|
|
44
|
-
|
|
45
71
|
newView.show animate, =>
|
|
46
72
|
@destroyView()
|
|
47
73
|
@view = newView
|
|
48
74
|
|
|
75
|
+
|
|
76
|
+
showViewByObjectId: (objectId, config, title, animate=false) ->
|
|
77
|
+
onSuccess = (object) => @showView(object, config, title, animate)
|
|
78
|
+
onError = -> chr.showError("can\'t show view for requested object")
|
|
79
|
+
|
|
80
|
+
if objectId == ''
|
|
81
|
+
config.objectStore.loadObject({ onSuccess: onSuccess, onError: onError })
|
|
82
|
+
else
|
|
83
|
+
config.arrayStore.loadObject(objectId, { onSuccess: onSuccess, onError: onError })
|
|
84
|
+
|
|
85
|
+
|
|
49
86
|
destroyView: ->
|
|
50
87
|
@view?.destroy()
|
|
51
88
|
|
|
52
|
-
show: ->
|
|
53
|
-
@chr.selectMenuItem(@name)
|
|
54
|
-
@unselectActiveListItem()
|
|
55
89
|
|
|
56
|
-
|
|
90
|
+
show: ->
|
|
91
|
+
@_update_active_list_items()
|
|
57
92
|
@$el.show()
|
|
58
93
|
@activeList.show(false)
|
|
59
94
|
|
|
95
|
+
|
|
60
96
|
hide: (animate=false) ->
|
|
61
|
-
@unselectActiveListItem()
|
|
62
97
|
@hideNestedLists()
|
|
63
98
|
|
|
64
99
|
if animate
|
|
@@ -69,29 +104,34 @@ class @Module
|
|
|
69
104
|
@destroyView()
|
|
70
105
|
@$el.hide()
|
|
71
106
|
|
|
107
|
+
|
|
108
|
+
# shows one of nested lists, with or without animation
|
|
72
109
|
showNestedList: (listName, animate=false) ->
|
|
73
|
-
@
|
|
74
|
-
@activeList = @nestedLists[listName]
|
|
110
|
+
listToShow = @nestedLists[listName]
|
|
75
111
|
|
|
76
|
-
|
|
112
|
+
if listToShow.showWithParent
|
|
113
|
+
# list works as view, never becomes active
|
|
114
|
+
listToShow.updateItems()
|
|
115
|
+
listToShow.show animate, => @hideNestedLists(exceptList=listName)
|
|
77
116
|
|
|
78
|
-
|
|
79
|
-
|
|
117
|
+
else
|
|
118
|
+
@activeList = listToShow
|
|
119
|
+
@_update_active_list_items()
|
|
120
|
+
@activeList.show(animate)
|
|
80
121
|
|
|
81
|
-
|
|
82
|
-
@
|
|
83
|
-
list.hide() for key, list of @nestedLists
|
|
122
|
+
# hide view
|
|
123
|
+
if animate and @view then @view.$el.fadeOut $.fx.speeds._default, => @destroyView()
|
|
84
124
|
|
|
85
|
-
showViewWhenObjectsAreReady: (objectId, config) ->
|
|
86
|
-
object = config.arrayStore.get(objectId)
|
|
87
|
-
if object then return @showView(object, config)
|
|
88
125
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
126
|
+
hideNestedLists: (exceptList) ->
|
|
127
|
+
@activeList = @rootList
|
|
128
|
+
list.hide() for key, list of @nestedLists when key isnt exceptList
|
|
92
129
|
|
|
93
|
-
console.log "object #{objectId} is not in the list"
|
|
94
130
|
|
|
131
|
+
# returns visible nested list that acts as view
|
|
132
|
+
visibleNestedListShownWithParent: ->
|
|
133
|
+
for key, list of @nestedLists
|
|
134
|
+
if list.isVisible() && list.showWithParent then return list
|
|
95
135
|
|
|
96
136
|
|
|
97
137
|
|
|
@@ -1,109 +1,154 @@
|
|
|
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
|
+
|
|
1
9
|
# -----------------------------------------------------------------------------
|
|
2
10
|
# VIEW
|
|
11
|
+
#
|
|
12
|
+
# configuration options:
|
|
13
|
+
# formSchema - form schema for object, autogenerated if missing
|
|
14
|
+
# disableDelete - do not add delete button below the form
|
|
15
|
+
# disableSave - do not add save button in header
|
|
16
|
+
# fullsizeView — use fullsize layout in desktop mode
|
|
17
|
+
#
|
|
18
|
+
# public methods:
|
|
19
|
+
# show(animate, callback)
|
|
20
|
+
# destroy()
|
|
21
|
+
#
|
|
3
22
|
# -----------------------------------------------------------------------------
|
|
4
23
|
class @View
|
|
5
|
-
|
|
6
|
-
@
|
|
7
|
-
@form = new Form(@object, @config)
|
|
24
|
+
constructor: (@module, @config, @closePath, @object, @title) ->
|
|
25
|
+
@store = @config.arrayStore ? @config.objectStore
|
|
8
26
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
27
|
+
@$el =$ "<section class='view #{ @module.name }'>"
|
|
28
|
+
@$el.hide()
|
|
29
|
+
|
|
30
|
+
if @config.fullsizeView
|
|
31
|
+
@$el.addClass 'fullsize'
|
|
32
|
+
|
|
33
|
+
# header
|
|
34
|
+
@$header =$ "<header></header>"
|
|
35
|
+
@$el.append @$header
|
|
36
|
+
|
|
37
|
+
@$title =$ "<div class='title'></div>"
|
|
38
|
+
@$header.append @$title
|
|
39
|
+
|
|
40
|
+
# close button
|
|
41
|
+
@$closeBtn =$ "<a href='#/#{ @closePath }' class='close silent'>Close</a>"
|
|
42
|
+
@$closeBtn.on 'click', (e) => @_on_close(e)
|
|
43
|
+
@$header.append @$closeBtn
|
|
44
|
+
|
|
45
|
+
# save button
|
|
46
|
+
unless @config.disableSave
|
|
47
|
+
@$saveBtn =$ "<a href='#' class='save'>Save</a>"
|
|
48
|
+
@$saveBtn.on 'click', (e) => @_on_save(e)
|
|
49
|
+
@$header.append @$saveBtn
|
|
50
|
+
|
|
51
|
+
@_render()
|
|
13
52
|
|
|
14
|
-
@$el.append @form.$el
|
|
15
53
|
|
|
16
54
|
_render: ->
|
|
55
|
+
@_update_title()
|
|
56
|
+
@_render_form()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
_update_title: ->
|
|
17
60
|
title = @title
|
|
18
61
|
title ?= @object[@config.itemTitleField] if @config.itemTitleField
|
|
19
62
|
title ?= _firstNonEmptyValue(@object)
|
|
63
|
+
|
|
20
64
|
if title == "" then title = "No Title"
|
|
21
65
|
|
|
22
|
-
#
|
|
66
|
+
# remove html tags from title to do not break layout
|
|
23
67
|
titleText = $("<div>#{ title }</div>").text()
|
|
24
68
|
@$title.html(titleText)
|
|
25
69
|
|
|
26
|
-
@_renderForm()
|
|
27
70
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
@form.initializePlugins()
|
|
32
|
-
@config.onViewShow?(@)
|
|
71
|
+
_render_form: ->
|
|
72
|
+
@form?.destroy()
|
|
73
|
+
@form = new Form(@object, @config)
|
|
33
74
|
|
|
34
|
-
|
|
35
|
-
|
|
75
|
+
# delete button
|
|
76
|
+
unless @config.disableDelete or @config.objectStore or @_is_new()
|
|
77
|
+
@$deleteBtn =$ "<a href='#' class='delete'>Delete</a>"
|
|
78
|
+
@$deleteBtn.on 'click', (e) => @_on_delete(e)
|
|
79
|
+
@form.$el.append @$deleteBtn
|
|
80
|
+
|
|
81
|
+
@$el.append @form.$el
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
_update_object: (value) ->
|
|
85
|
+
@_start_saving()
|
|
36
86
|
@store.update @object._id, value,
|
|
37
|
-
onSuccess: (object) =>
|
|
38
|
-
#
|
|
39
|
-
#
|
|
87
|
+
onSuccess: (@object) =>
|
|
88
|
+
# add a note here for this line, it's not obvious why it's here,
|
|
89
|
+
# looks like some logic related to title update
|
|
40
90
|
if @config.arrayStore then @title = null
|
|
41
91
|
|
|
42
92
|
formScrollPosition = @form.$el.scrollTop()
|
|
43
93
|
@_render()
|
|
44
|
-
@
|
|
94
|
+
@_initialize_form_plugins()
|
|
45
95
|
@form.$el.scrollTop(formScrollPosition)
|
|
46
96
|
|
|
47
|
-
|
|
97
|
+
@_stop_saving()
|
|
98
|
+
|
|
48
99
|
onError: (errors) =>
|
|
49
|
-
@
|
|
50
|
-
|
|
100
|
+
@_validation_errors('Changes were not saved.', errors)
|
|
101
|
+
@_stop_saving()
|
|
51
102
|
|
|
52
|
-
|
|
53
|
-
|
|
103
|
+
|
|
104
|
+
_create_object: (value) ->
|
|
105
|
+
@_start_saving()
|
|
106
|
+
# refactor this to subscribe to list event: item_added
|
|
54
107
|
@store.push value,
|
|
55
108
|
onSuccess: (object) =>
|
|
56
|
-
#
|
|
109
|
+
# we need to know when list item is added
|
|
57
110
|
location.hash = "#/#{ @closePath }/view/#{ object._id }"
|
|
58
111
|
onError: (errors) =>
|
|
59
|
-
@
|
|
60
|
-
|
|
112
|
+
@_validation_errors('Item were not created.', errors)
|
|
113
|
+
@_stop_saving()
|
|
61
114
|
|
|
62
|
-
|
|
115
|
+
_start_saving: ->
|
|
116
|
+
@$el.addClass('view-saving')
|
|
63
117
|
|
|
64
|
-
constructor: (@module, @config, @closePath, @object, @title) ->
|
|
65
|
-
@store = @config.arrayStore ? @config.objectStore
|
|
66
118
|
|
|
67
|
-
|
|
68
|
-
@$el.
|
|
119
|
+
_stop_saving: ->
|
|
120
|
+
setTimeout ( => @$el.removeClass('view-saving') ), 250
|
|
69
121
|
|
|
70
|
-
@$header =$ "<header></header>"
|
|
71
|
-
@$title =$ "<div class='title'></div>"
|
|
72
|
-
@$header.append @$title
|
|
73
122
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
123
|
+
_initialize_form_plugins: ->
|
|
124
|
+
@form.initializePlugins()
|
|
125
|
+
@config.onViewShow?(@)
|
|
77
126
|
|
|
78
|
-
unless @config.disableSave
|
|
79
|
-
@$saveBtn =$ "<a href='#' class='save'>Save</a>"
|
|
80
|
-
@$saveBtn.on 'click', (e) => @onSave(e)
|
|
81
|
-
@$header.append @$saveBtn
|
|
82
127
|
|
|
83
|
-
|
|
128
|
+
_validation_errors: (message, errors) ->
|
|
129
|
+
chr.showError(message)
|
|
130
|
+
@form.showValidationErrors(errors)
|
|
84
131
|
|
|
85
|
-
@_render()
|
|
86
132
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
@$el.fadeIn($.fx.speeds._default, => @_initializeFormPlugins() ; callback?())
|
|
90
|
-
else
|
|
91
|
-
@$el.show 0, => @_initializeFormPlugins() ; callback?()
|
|
133
|
+
_is_new: ->
|
|
134
|
+
! @object
|
|
92
135
|
|
|
93
|
-
destroy: ->
|
|
94
|
-
@form?.destroy()
|
|
95
|
-
@$el.remove()
|
|
96
136
|
|
|
97
|
-
|
|
98
|
-
@module.unselectActiveListItem()
|
|
137
|
+
_on_close: (e) ->
|
|
99
138
|
@$el.fadeOut $.fx.speeds._default, => @destroy()
|
|
100
139
|
|
|
101
|
-
|
|
140
|
+
|
|
141
|
+
_on_save: (e) ->
|
|
102
142
|
e.preventDefault()
|
|
103
143
|
serializedFormObj = @form.serialize()
|
|
104
|
-
if @object then @_updateObject(serializedFormObj) else @_createObject(serializedFormObj)
|
|
105
144
|
|
|
106
|
-
|
|
145
|
+
if @object
|
|
146
|
+
@_update_object(serializedFormObj)
|
|
147
|
+
else
|
|
148
|
+
@_create_object(serializedFormObj)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
_on_delete: (e) ->
|
|
107
152
|
e.preventDefault()
|
|
108
153
|
if confirm("Are you sure?")
|
|
109
154
|
@store.remove(@object._id)
|
|
@@ -112,8 +157,19 @@ class @View
|
|
|
112
157
|
location.hash = "#/#{ @closePath }"
|
|
113
158
|
@destroy()
|
|
114
159
|
|
|
115
|
-
|
|
116
|
-
|
|
160
|
+
|
|
161
|
+
show: (animate, callback) ->
|
|
162
|
+
if animate
|
|
163
|
+
@$el.fadeIn($.fx.speeds._default, =>
|
|
164
|
+
@_initialize_form_plugins()
|
|
165
|
+
callback?())
|
|
166
|
+
else
|
|
167
|
+
@$el.show 0, => @_initialize_form_plugins() ; callback?()
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
destroy: ->
|
|
171
|
+
@form?.destroy()
|
|
172
|
+
@$el.remove()
|
|
117
173
|
|
|
118
174
|
|
|
119
175
|
|
|
@@ -1,34 +1,3 @@
|
|
|
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
1
|
# -----------------------------------------------------------------------------
|
|
33
2
|
# ARRAY STORE
|
|
34
3
|
# javascript object storage implementation that stores/loads objects in memory,
|
|
@@ -38,26 +7,27 @@ class @ObjectStore
|
|
|
38
7
|
# - reordering
|
|
39
8
|
#
|
|
40
9
|
# configuration options:
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
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 }
|
|
10
|
+
# data — initial array of objects, default: []
|
|
11
|
+
# sortBy — objects field name which is used for sorting, does not sort
|
|
12
|
+
# when parameter is not provided, default: nil
|
|
13
|
+
# sortReverse — reverse objects sorting (descending order), default: false
|
|
14
|
+
# reorderable — list items reordering configuration hash, should have two
|
|
15
|
+
# fields: { positionFieldName: '', sortReverse: false }
|
|
52
16
|
#
|
|
53
17
|
# public methods:
|
|
54
18
|
# - on(eventType, callback)
|
|
19
|
+
# object_added
|
|
20
|
+
# object_changed
|
|
21
|
+
# object_removed
|
|
22
|
+
# objects_added
|
|
55
23
|
# - off(eventType)
|
|
56
24
|
# - get(id)
|
|
57
25
|
# - push(serializedFormObject, callbacks)
|
|
58
26
|
# - update(serializedFormObject, callbacks)
|
|
59
27
|
# - remove(id)
|
|
60
28
|
# - reset(callback)
|
|
29
|
+
# - addObjects(objects)
|
|
30
|
+
# - data()
|
|
61
31
|
#
|
|
62
32
|
# todo:
|
|
63
33
|
# - support for lists, files, nested objects
|
|
@@ -71,11 +41,6 @@ class @ArrayStore
|
|
|
71
41
|
@sortReverse = @config.sortReverse ? false
|
|
72
42
|
@reorderable = @config.reorderable ? false
|
|
73
43
|
|
|
74
|
-
if @sortBy == false
|
|
75
|
-
@newItemOnTop = @config.newItemOnTop ? true
|
|
76
|
-
else
|
|
77
|
-
@newItemOnTop = @config.newItemOnTop ? false
|
|
78
|
-
|
|
79
44
|
@_initialize_reorderable()
|
|
80
45
|
@_initialize_database()
|
|
81
46
|
|
|
@@ -97,15 +62,6 @@ class @ArrayStore
|
|
|
97
62
|
;
|
|
98
63
|
|
|
99
64
|
|
|
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
65
|
# sort object in _data array based on sortBy and sortReverse parameters
|
|
110
66
|
# implementatin details:
|
|
111
67
|
# http://stackoverflow.com/questions/9796764/how-do-i-sort-an-array-with-coffeescript
|
|
@@ -141,40 +97,33 @@ class @ArrayStore
|
|
|
141
97
|
|
|
142
98
|
# normalize objects id, add object to _data and _map, sort objects,
|
|
143
99
|
# trigger 'object_added' event
|
|
144
|
-
_add_data_object: (object
|
|
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) ->
|
|
100
|
+
_add_data_object: (object) ->
|
|
159
101
|
object = @_normalize_object_id(object)
|
|
160
102
|
|
|
161
|
-
|
|
162
|
-
|
|
103
|
+
# if object with same id already in the store, update it's parameters,
|
|
104
|
+
# otherwise add new object (this is used while pagination sync)
|
|
105
|
+
if ! @_map[object._id]
|
|
106
|
+
@_map[object._id] = object
|
|
107
|
+
@_data.push(object)
|
|
108
|
+
@_sort_data()
|
|
163
109
|
|
|
164
|
-
|
|
110
|
+
position = @_get_data_object_position(object._id)
|
|
165
111
|
|
|
166
|
-
|
|
112
|
+
$(this).trigger('object_added', { object: object, position: position })
|
|
113
|
+
else
|
|
114
|
+
@_update_data_object(object.id, object)
|
|
167
115
|
|
|
168
116
|
|
|
169
117
|
# get object by id, update it's attributes, sort objects,
|
|
170
118
|
# trigger 'object_changed' event
|
|
171
|
-
_update_data_object: (id, value
|
|
119
|
+
_update_data_object: (id, value) ->
|
|
172
120
|
object = $.extend(@get(id), value)
|
|
173
121
|
|
|
174
122
|
@_sort_data()
|
|
123
|
+
|
|
175
124
|
position = @_get_data_object_position(id)
|
|
176
125
|
|
|
177
|
-
$(this).trigger('object_changed', { object: object, position: position
|
|
126
|
+
$(this).trigger('object_changed', { object: object, position: position })
|
|
178
127
|
|
|
179
128
|
|
|
180
129
|
# delete object by id from _data and _map,
|
|
@@ -182,7 +131,7 @@ class @ArrayStore
|
|
|
182
131
|
_remove_data_object: (id) ->
|
|
183
132
|
position = @_get_data_object_position(id)
|
|
184
133
|
if position >= 0
|
|
185
|
-
|
|
134
|
+
@_data.splice(position, 1)
|
|
186
135
|
|
|
187
136
|
delete @_map[id]
|
|
188
137
|
|
|
@@ -214,23 +163,14 @@ class @ArrayStore
|
|
|
214
163
|
return object
|
|
215
164
|
|
|
216
165
|
|
|
217
|
-
#
|
|
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
|
|
166
|
+
# subsribe to store event
|
|
228
167
|
on: (eventType, callback) ->
|
|
229
168
|
$(this).on eventType, (e, data) -> callback(e, data)
|
|
230
169
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
170
|
+
|
|
171
|
+
# unsubscribe from store event, simple jQuery wrapper
|
|
172
|
+
off: (eventType) ->
|
|
173
|
+
if eventType then $(this).off(eventType) else $(this).off()
|
|
234
174
|
|
|
235
175
|
|
|
236
176
|
# get object by id
|
|
@@ -239,36 +179,43 @@ class @ArrayStore
|
|
|
239
179
|
|
|
240
180
|
|
|
241
181
|
# add new object
|
|
242
|
-
push: (serializedFormObject, callbacks) ->
|
|
182
|
+
push: (serializedFormObject, callbacks={}) ->
|
|
243
183
|
object = @_parse_form_object(serializedFormObject)
|
|
184
|
+
|
|
185
|
+
# generate id for new object
|
|
244
186
|
if ! object._id then object._id = Date.now()
|
|
245
187
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
else
|
|
249
|
-
@_add_data_object(object, callbacks.onSuccess)
|
|
188
|
+
@_add_data_object(object)
|
|
189
|
+
callbacks.onSuccess?()
|
|
250
190
|
|
|
251
191
|
|
|
252
192
|
# update objects attributes
|
|
253
|
-
update: (id, serializedFormObject, callbacks) ->
|
|
193
|
+
update: (id, serializedFormObject, callbacks={}) ->
|
|
254
194
|
object = @_parse_form_object(serializedFormObject)
|
|
255
|
-
@_update_data_object(id, object
|
|
195
|
+
@_update_data_object(id, object)
|
|
196
|
+
callbacks.onSuccess?()
|
|
256
197
|
|
|
257
198
|
|
|
258
199
|
# delete object
|
|
259
|
-
remove: (id) ->
|
|
200
|
+
remove: (id, callbacks={}) ->
|
|
260
201
|
@_remove_data_object(id)
|
|
202
|
+
callbacks.onSuccess?()
|
|
261
203
|
|
|
262
204
|
|
|
263
|
-
#
|
|
264
|
-
reset:
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
@_sort_data()
|
|
205
|
+
# do nothing for in memory data store
|
|
206
|
+
reset: ->
|
|
207
|
+
$(this).trigger('objects_added')
|
|
208
|
+
|
|
268
209
|
|
|
210
|
+
# add objects, this is a kind of workaround that helps to initialize
|
|
211
|
+
# store data without request
|
|
212
|
+
addObjects: (objects) ->
|
|
213
|
+
@_add_data_object(o) for o in objects
|
|
269
214
|
$(this).trigger('objects_added')
|
|
270
|
-
callback?()
|
|
271
215
|
|
|
272
216
|
|
|
217
|
+
# returns stored objects array
|
|
218
|
+
data: ->
|
|
219
|
+
return @_data
|
|
273
220
|
|
|
274
221
|
|