chr 0.2.7 → 0.2.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a86d147a723188f151bcacca8c35a403bd6fcf3
4
- data.tar.gz: f1be1f7997afb7976ecfbda0f1641b69e12e3ac2
3
+ metadata.gz: 7fceeef7d448d2cdc5eb8b0d8b83b41f9e3286eb
4
+ data.tar.gz: e7ca6fddaae45df4c2d0e53ee1bd288975d8aa6c
5
5
  SHA512:
6
- metadata.gz: 2aec7e0a14af19ce53844ab6b58e615a26db8338a9bfbf7382869ce6f796383128b409625bd2fcc091e02b42a92a93f035902f7dfa8857d0c65eeb0e6aefc8be
7
- data.tar.gz: 918c153a9f11d8e7add0fcd26fedf80cf701bc398c3f1c7c0367dbf7f0374b61a140ef24516cd73692ed117eaec20cfca4dd944ad8f5f8210fb9a4d3dfd16905
6
+ metadata.gz: 6c18ab1dafebd9e6321c6d44734b11af06d2b2e42a46a0191c5b6c64b1043633e7621d8224dd75d6c6b543cb181ea456183c7940386a47baff602c93ab626e86
7
+ data.tar.gz: d568e55272035adadfa181cc463ba89399822a07b8969c1af63e482106a93b096993dd247cf7c59ca8ab5662e61b11ae3c732efa33c6958d6f62eee35d57167d
@@ -12,23 +12,23 @@
12
12
  @$items.scroll (e) =>
13
13
  # trigger next page loading only when scrolling to bottom
14
14
  if @lastScrollTop < e.target.scrollTop
15
- @lastScrollTop = e.target.scrollTop
16
-
17
15
  if ! @config.arrayStore.dataFetchLock
18
16
 
19
- if @listItemsHeight < (@listViewHeight + e.target.scrollTop + 100)
20
- @_show_spinner()
21
- @config.arrayStore.load
22
- onSuccess: => @_update_height_params()
23
- onError: => chr.showAlert("Can't load next page, server error 500.")
17
+ listViewHeight = @$el.height()
18
+ listItemsHeight = 0
19
+ @$items.children().each -> listItemsHeight += $(this).height()
20
+
21
+ if listItemsHeight < (listViewHeight + e.target.scrollTop + 100)
22
+
23
+ if ! @config.arrayStore.lastPageLoaded
24
24
 
25
- @_update_height_params()
25
+ @_show_spinner()
26
26
 
27
+ @config.arrayStore.load false,
28
+ onSuccess: => ;
29
+ onError: => chr.showAlert("Can't load next page, server error 500.")
27
30
 
28
- _update_height_params: ->
29
- @listViewHeight = @$el.height()
30
- @listItemsHeight = 0
31
- @$items.children().each (i, el) => @listItemsHeight += $(el).height()
31
+ @lastScrollTop = e.target.scrollTop
32
32
 
33
33
 
34
34
 
@@ -46,8 +46,7 @@
46
46
  @$el.removeClass('list-search')
47
47
  @$searchInput.val('')
48
48
  @_show_spinner()
49
- # use reset(false) to do not sync with the existing list items
50
- @config.arrayStore.reset(false)
49
+ @config.arrayStore.reset()
51
50
 
52
51
 
53
52
 
@@ -1,12 +1,22 @@
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
  # ARRAY STORE
3
- # javascript object storage implementation that stores/loads objects in memory,
11
+ # -----------------------------------------------------------------------------
12
+ #
13
+ # Javascript object storage implementation that stores/loads objects in memory,
4
14
  # no backend database support here, supported features are:
5
15
  # - new / update / remove
6
16
  # - sorting
7
17
  # - reordering
8
18
  #
9
- # configuration options:
19
+ # Config options:
10
20
  # data — initial array of objects, default: []
11
21
  # sortBy — objects field name which is used for sorting, does not sort
12
22
  # when parameter is not provided, default: nil
@@ -14,7 +24,7 @@
14
24
  # reorderable — list items reordering configuration hash, should have two
15
25
  # fields: { positionFieldName: '', sortReverse: false }
16
26
  #
17
- # public methods:
27
+ # Public methods:
18
28
  # - on(eventType, callback)
19
29
  # object_added
20
30
  # object_changed
@@ -29,8 +39,9 @@
29
39
  # - addObjects(objects)
30
40
  # - data()
31
41
  #
32
- # todo:
42
+ # TODO:
33
43
  # - support for lists, files, nested objects
44
+ #
34
45
  # -----------------------------------------------------------------------------
35
46
  class @ArrayStore
36
47
  constructor: (@config={}) ->
@@ -42,7 +53,7 @@ class @ArrayStore
42
53
  @reorderable = @config.reorderable ? false
43
54
 
44
55
  @_initialize_reorderable()
45
- @_initialize_database()
56
+ @_initialize_store()
46
57
 
47
58
 
48
59
  # PRIVATE ===============================================
@@ -60,7 +71,7 @@ class @ArrayStore
60
71
 
61
72
  # this method should be overriden for database initialization
62
73
  # and config processing when implementing custom store
63
- _initialize_database: ->
74
+ _initialize_store: ->
64
75
  ;
65
76
 
66
77
 
@@ -111,7 +122,9 @@ class @ArrayStore
111
122
 
112
123
  position = @_get_data_object_position(object._id)
113
124
 
114
- $(this).trigger('object_added', { object: object, position: position })
125
+ data = { object: object, position: position }
126
+ $(this).trigger('object_added', data)
127
+ return data
115
128
  else
116
129
  @_update_data_object(object.id, object)
117
130
 
@@ -121,11 +134,13 @@ class @ArrayStore
121
134
  _update_data_object: (id, value) ->
122
135
  object = $.extend(@get(id), value)
123
136
 
137
+ old_position = @_get_data_object_position(id)
124
138
  @_sort_data()
125
-
126
139
  position = @_get_data_object_position(id)
127
140
 
128
- $(this).trigger('object_changed', { object: object, position: position })
141
+ data = { object: object, position: position, positionHasChanged: (old_position != position) }
142
+ $(this).trigger('object_changed', data)
143
+ return data
129
144
 
130
145
 
131
146
  # delete object by id from _data and _map,
@@ -137,7 +152,9 @@ class @ArrayStore
137
152
 
138
153
  delete @_map[id]
139
154
 
140
- $(this).trigger('object_removed', { object_id: id })
155
+ data = { object_id: id }
156
+ $(this).trigger('object_removed', data)
157
+ return data
141
158
 
142
159
 
143
160
  # remove all objects from _data and _map,
@@ -11,11 +11,12 @@
11
11
  # -----------------------------------------------------------------------------
12
12
  class @ObjectStore
13
13
  constructor: (@config={}) ->
14
- @_initialize_database()
14
+ @_initialize_store()
15
+
15
16
 
16
17
  # PRIVATE ===============================================
17
18
 
18
- _initialize_database: ->
19
+ _initialize_store: ->
19
20
  @_data = @config.data
20
21
 
21
22
 
@@ -7,112 +7,22 @@
7
7
  # -----------------------------------------------------------------------------
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
- # MONGOSTEEN (RAILS) ARRAY/COLLECTION STORE IMPLEMENTATION
11
- # this store implementation talks to Mongosteen powered Rails api, supports
12
- # features:
13
- #
14
- # - pagination
15
- # `sortBy` & `sortReverse` options should be set same as on
16
- # backend model with `default_scope` method (default), e.g:
17
- # - frontend: `{ sortBy: 'created_at', sortReverse: true }`
18
- # - backend: `default_scope -> { desc(:created_at) }`
19
- #
20
- # - search
21
- # backend model configuration required, e.g: `search_in :title`
22
- #
23
- # configuration options:
24
- # @config.pagination - enable pagination, default `true`
25
- # @config.searchable - enable search, default `false`
26
- #
10
+ # RAILS ARRAY STORE
27
11
  # -----------------------------------------------------------------------------
28
12
  class @MongosteenArrayStore extends RestArrayStore
29
13
 
30
14
  # PRIVATE ===============================================
31
15
 
32
- _initialize_database: ->
33
- @dataFetchLock = false
16
+ _configure_store: ->
34
17
  @ajaxConfig =
35
18
  processData: false
36
19
  contentType: false
37
20
 
38
- @searchable = @config.searchable ? false
39
- @searchQuery = ''
40
-
41
- @pagination = @config.pagination ? true
42
- @nextPage = 1
43
- @objectsPerPage = chr.itemsPerPageRequest ? 20
44
-
45
- if @pagination
46
- @lastPageLoaded = false
47
- @_bind_pagination_sync()
48
-
49
-
50
- # ---------------------------------------------------------
51
- # workarounds to have consistency between arrayStore and
52
- # database while loading next page
53
- # ---------------------------------------------------------
54
- _bind_pagination_sync: ->
55
- # when object's added to the end of the list & not on the last page,
56
- # we don't know it's position on the backend, so remove it from store
57
- $(this).on 'object_added', (e, data) =>
58
- if ! @lastPageLoaded
59
- new_object = data.object
60
- new_object_position = data.position
61
-
62
- # check if object added to the end of the list
63
- if new_object_position >= @objectsNumberForLoadedPages
64
- e.stopImmediatePropagation()
65
-
66
- @_remove_data_object(new_object._id)
67
-
68
- # when object's added to the end of the list & not on the last page,
69
- # we don't know it's position on the backend, so remove it from store
70
- $(this).on 'object_changed', (e, data) =>
71
- if ! @lastPageLoaded
72
- new_object = data.object
73
- new_object_position = data.position
74
-
75
- # check if object added to the end of the list
76
- if new_object_position >= @objectsNumberForLoadedPages - 1
77
- e.stopImmediatePropagation()
78
-
79
- @_remove_data_object(new_object._id)
80
-
81
- # load current page again after item delete to sync, last item on the page
82
- $(this).on 'object_removed', (e, data) =>
83
- if ! @lastPageLoaded
84
- @_reload_current_page()
85
-
86
-
87
- _reload_current_page: ->
88
- @nextPage -= 1 ; @load()
89
-
90
-
91
- _update_next_page: (data) ->
92
- if @pagination
93
- if data.length > 0
94
- @lastPageLoaded = true
95
-
96
- if data.length == @objectsPerPage
97
- @nextPage += 1
98
- @lastPageLoaded = false
99
-
100
- else
101
- @lastPageLoaded = true
102
-
103
- @objectsNumberForLoadedPages = (@nextPage - 1) * @objectsPerPage
104
-
105
21
 
106
22
  # generate resource api url
107
23
  _resource_url: (type, id) ->
108
24
  objectPath = if id then "/#{ id }" else ''
109
- url = "#{ @config.path }#{ objectPath }.json"
110
-
111
- if @config.urlParams
112
- extraParamsString = $.param(@config.urlParams)
113
- url = "#{ url }?#{ extraParamsString }"
114
-
115
- return url
25
+ "#{ @config.path }#{ objectPath }.json"
116
26
 
117
27
 
118
28
  # get form data object from serialized form object,
@@ -141,70 +51,5 @@ class @MongosteenArrayStore extends RestArrayStore
141
51
  return formDataObject
142
52
 
143
53
 
144
- # PUBLIC ================================================
145
-
146
- # load first page of results for search query, skip store 'object_removed'
147
- # event handler on @_reset_data()
148
- search: (@searchQuery) ->
149
- @nextPage = 1
150
- @lastPageLoaded = true
151
- @_reset_data()
152
- @load()
153
-
154
-
155
- # load next page objects from database, when finished
156
- # trigger 'objects_added' event
157
- load: (callbacks={}) ->
158
- callbacks.onSuccess ?= $.noop
159
- callbacks.onError ?= $.noop
160
-
161
- params = {}
162
-
163
- if @pagination
164
- params.page = @nextPage
165
- params.perPage = @objectsPerPage
166
-
167
- if @searchable && @searchQuery.length > 0
168
- params.search = @searchQuery
169
-
170
- params = $.param(params)
171
-
172
- @_ajax 'GET', null, params, ((data) =>
173
- @_update_next_page(data)
174
- @_add_data_object(o) for o in data
175
-
176
- callbacks.onSuccess(data)
177
-
178
- $(this).trigger('objects_added', { objects: data })
179
- ), callbacks.onError
180
-
181
-
182
- # reset data and load first page, by default this sync with
183
- # objects that are currently in the _data, if you want to reset
184
- # these use `reset(false)`
185
- reset: (sync_with_existing_objects=true)->
186
- @searchQuery = ''
187
- @nextPage = 1
188
- params = {}
189
-
190
- if ! sync_with_existing_objects
191
- @lastPageLoaded = true
192
- @_reset_data()
193
-
194
- if @pagination
195
- @lastPageLoaded = false
196
- params.page = @nextPage
197
- params.perPage = @objectsPerPage
198
-
199
- params = $.param(params)
200
-
201
- @_ajax 'GET', null, params, ((data) =>
202
- @_update_next_page(data)
203
- @_sync_with_data_objects(data)
204
-
205
- $(this).trigger('objects_added', { objects: data })
206
- ), -> chr.showError('Error while loading data.')
207
-
208
-
209
54
 
210
55
 
@@ -7,14 +7,13 @@
7
7
  # -----------------------------------------------------------------------------
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
- # MONGOSTEEN (RAILS) OBJECT STORE IMPLEMENTATION
10
+ # RAILS OBJECT STORE
11
11
  # -----------------------------------------------------------------------------
12
12
  class @MongosteenObjectStore extends RestObjectStore
13
13
 
14
14
  # PRIVATE ===============================================
15
15
 
16
- _initialize_database: ->
17
- @dataFetchLock = false
16
+ _configure_store: ->
18
17
  @ajaxConfig =
19
18
  processData: false
20
19
  contentType: false
@@ -9,12 +9,48 @@
9
9
  # -----------------------------------------------------------------------------
10
10
  # REST ARRAY STORE
11
11
  # -----------------------------------------------------------------------------
12
+ #
13
+ # Config options:
14
+ # pagination - enable pagination for resource index, default `true`
15
+ # searchable - enable resource search, default `false`
16
+ # urlParams - additional parameter to be included into request
17
+ # sortBy - sort objects by field
18
+ # sortReverse - reverse sorted objects
19
+ #
20
+ # Public methods:
21
+ # loadObject
22
+ # load
23
+ # reset
24
+ # search
25
+ # push
26
+ # update
27
+ # remove
28
+ #
29
+ # -----------------------------------------------------------------------------
12
30
  class @RestArrayStore extends ArrayStore
13
31
 
14
32
  # PRIVATE ===============================================
15
33
 
16
- _initialize_database: ->
17
- @dataFetchLock = false
34
+ _initialize_store: ->
35
+ @dataFetchLock = false
36
+ @lastPageLoaded = false
37
+
38
+ @searchable = @config.searchable ? false
39
+ @searchQuery = ''
40
+
41
+ @pagination = @config.pagination ? true
42
+ @nextPage = 1
43
+ @objectsPerPage = chr.itemsPerPageRequest ? 20
44
+
45
+ @requestParams ?=
46
+ page: 'page'
47
+ perPage: 'perPage'
48
+ search: 'search'
49
+
50
+ @_configure_store()
51
+
52
+
53
+ _configure_store: ->
18
54
  @ajaxConfig = {}
19
55
 
20
56
 
@@ -24,16 +60,25 @@ class @RestArrayStore extends ArrayStore
24
60
  "#{ @config.path }#{ objectPath }"
25
61
 
26
62
 
63
+ _request_url: (type, id) ->
64
+ url = @_resource_url(type, id)
65
+
66
+ if @config.urlParams
67
+ extraParamsString = $.param(@config.urlParams)
68
+ url = "#{ url }?#{ extraParamsString }"
69
+
70
+ return url
71
+
72
+
27
73
  # do requests to database api
28
74
  _ajax: (type, id, data, success, error) ->
29
75
  options = $.extend @ajaxConfig,
30
- url: @_resource_url(type, id)
76
+ url: @_request_url(type, id)
31
77
  type: type
32
78
  data: data
33
79
  success: (data, textStatus, jqXHR) =>
34
80
  success?(data)
35
- setTimeout ( => @dataFetchLock = false ), 350
36
- #@dataFetchLock = false
81
+ setTimeout ( => @dataFetchLock = false ), 50
37
82
  error: (jqXHR, textStatus, errorThrown ) =>
38
83
  error?(jqXHR.responseJSON)
39
84
  @dataFetchLock = false
@@ -67,10 +112,32 @@ class @RestArrayStore extends ArrayStore
67
112
  @_update_data_object(id, objectsMap[id])
68
113
 
69
114
 
115
+ # update next page counter and check if the last page was loaded
116
+ _update_next_page: (data) ->
117
+ if @pagination
118
+ if data.length > 0
119
+ @lastPageLoaded = true
120
+
121
+ if data.length == @objectsPerPage
122
+ @nextPage += 1
123
+ @lastPageLoaded = false
124
+
125
+ else
126
+ @lastPageLoaded = true
127
+
128
+
129
+ _is_pagination_edge_case: ->
130
+ ( @pagination && @lastPageLoaded == false )
131
+
132
+
133
+ _reload_current_page: (callbacks) ->
134
+ @nextPage -= 1
135
+ @load(true, callbacks)
136
+
137
+
70
138
  # PUBLIC ================================================
71
139
 
72
- # load a single object, this is used in view when
73
- # store has not required item
140
+ # load a single object
74
141
  loadObject: (id, callbacks={}) ->
75
142
  callbacks.onSuccess ?= $.noop
76
143
  callbacks.onError ?= $.noop
@@ -80,21 +147,46 @@ class @RestArrayStore extends ArrayStore
80
147
  ), callbacks.onError
81
148
 
82
149
 
83
- # load objects from database, when finished
84
- # trigger 'objects_added' event
85
- load: (callbacks={}) ->
150
+ # load next page objects from database and trigger 'objects_added' event
151
+ load: (sync=false, callbacks={}) ->
86
152
  callbacks.onSuccess ?= $.noop
87
153
  callbacks.onError ?= $.noop
88
154
 
89
- @_ajax 'GET', null, {}, ((data) =>
90
- if data.length > 0
91
- for o in data
92
- @_add_data_object(o)
155
+ params = {}
156
+
157
+ if @pagination
158
+ params[@requestParams.page] = @nextPage
159
+ params[@requestParams.perPage] = @objectsPerPage
160
+
161
+ if @searchable && @searchQuery.length > 0
162
+ params[@requestParams.search] = @searchQuery
163
+
164
+ params = $.param(params)
165
+
166
+ @_ajax 'GET', null, params, ((data) =>
167
+ @_update_next_page(data)
168
+
169
+ if sync
170
+ @_sync_with_data_objects(data)
171
+ else
172
+ @_add_data_object(o) for o in data
93
173
 
94
174
  callbacks.onSuccess(data)
95
175
 
96
176
  $(this).trigger('objects_added', { objects: data })
97
- ) callbacks.onError
177
+ ), -> chr.showError('Error while loading data, application error 500.')
178
+
179
+
180
+ # reset data and load again first page
181
+ reset: (@searchQuery='') ->
182
+ @lastPageLoaded = false
183
+ @nextPage = 1
184
+ @load(true)
185
+
186
+
187
+ # load search results first page
188
+ search: (searchQuery) ->
189
+ @reset(searchQuery)
98
190
 
99
191
 
100
192
  # add new object
@@ -105,8 +197,15 @@ class @RestArrayStore extends ArrayStore
105
197
  obj = @_parse_form_object(serializedFormObject)
106
198
 
107
199
  @_ajax 'POST', null, obj, ((data) =>
108
- @_add_data_object(data)
200
+ d = @_add_data_object(data)
201
+
202
+ if @_is_pagination_edge_case()
203
+ if d.position >= (@nextPage - 1) * @objectsPerPage
204
+ # if object added to the end of the list remove it
205
+ @_remove_data_object(d.object._id)
206
+
109
207
  callbacks.onSuccess(data)
208
+
110
209
  ), callbacks.onError
111
210
 
112
211
 
@@ -118,8 +217,17 @@ class @RestArrayStore extends ArrayStore
118
217
  obj = @_parse_form_object(serializedFormObject)
119
218
 
120
219
  @_ajax 'PUT', id, obj, ((data) =>
121
- @_update_data_object(id, data)
122
- callbacks.onSuccess(data)
220
+ d = @_update_data_object(id, data)
221
+
222
+ if @_is_pagination_edge_case() && d.positionHasChanged
223
+ if d.position >= (@nextPage - 1) * @objectsPerPage - 1
224
+ # if object added to the end of the list reload page to
225
+ # sync last item on the page
226
+ @_reload_current_page(callbacks)
227
+
228
+ else
229
+ callbacks.onSuccess(data)
230
+
123
231
  ), callbacks.onError
124
232
 
125
233
 
@@ -130,16 +238,16 @@ class @RestArrayStore extends ArrayStore
130
238
 
131
239
  @_ajax 'DELETE', id, {}, ( =>
132
240
  @_remove_data_object(id)
133
- callbacks.onSuccess()
134
- ), callbacks.onError
135
241
 
242
+ if @_is_pagination_edge_case()
243
+ # after item delete reload page to sync last item on the page
244
+ @_reload_current_page(callbacks)
245
+
246
+ else
247
+ callbacks.onSuccess()
248
+
249
+ ), callbacks.onError
136
250
 
137
- # reset data and load it again
138
- reset: ->
139
- @_ajax 'GET', null, {}, ((data) =>
140
- @_sync_with_data_objects(data)
141
- $(this).trigger('objects_added', { objects: data })
142
- ), -> chr.showError('Error while loading data.')
143
251
 
144
252
 
145
253
 
@@ -13,8 +13,12 @@ class @RestObjectStore extends ObjectStore
13
13
 
14
14
  # PRIVATE ===============================================
15
15
 
16
- _initialize_database: ->
16
+ _initialize_store: ->
17
17
  @dataFetchLock = false
18
+ @_configure_store()
19
+
20
+
21
+ _configure_store: ->
18
22
  @ajaxConfig = {}
19
23
 
20
24
 
data/bower.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chr",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "homepage": "https://github.com/slate-studio/chr",
5
5
  "authors": [
6
6
  "Slate Studio (http://www.slatestudio.com)"
@@ -3097,34 +3097,30 @@ this.listConfig = {
3097
3097
  this.listPagination = {
3098
3098
  _bind_pagination: function() {
3099
3099
  this.lastScrollTop = 0;
3100
- this.$items.scroll((function(_this) {
3100
+ return this.$items.scroll((function(_this) {
3101
3101
  return function(e) {
3102
+ var listItemsHeight, listViewHeight;
3102
3103
  if (_this.lastScrollTop < e.target.scrollTop) {
3103
- _this.lastScrollTop = e.target.scrollTop;
3104
3104
  if (!_this.config.arrayStore.dataFetchLock) {
3105
- if (_this.listItemsHeight < (_this.listViewHeight + e.target.scrollTop + 100)) {
3106
- _this._show_spinner();
3107
- return _this.config.arrayStore.load({
3108
- onSuccess: function() {
3109
- return _this._update_height_params();
3110
- },
3111
- onError: function() {
3112
- return chr.showAlert("Can't load next page, server error 500.");
3113
- }
3114
- });
3105
+ listViewHeight = _this.$el.height();
3106
+ listItemsHeight = 0;
3107
+ _this.$items.children().each(function() {
3108
+ return listItemsHeight += $(this).height();
3109
+ });
3110
+ if (listItemsHeight < (listViewHeight + e.target.scrollTop + 100)) {
3111
+ if (!_this.config.arrayStore.lastPageLoaded) {
3112
+ _this._show_spinner();
3113
+ _this.config.arrayStore.load(false, {
3114
+ onSuccess: function() {},
3115
+ onError: function() {
3116
+ return chr.showAlert("Can't load next page, server error 500.");
3117
+ }
3118
+ });
3119
+ }
3115
3120
  }
3116
3121
  }
3117
3122
  }
3118
- };
3119
- })(this));
3120
- return this._update_height_params();
3121
- },
3122
- _update_height_params: function() {
3123
- this.listViewHeight = this.$el.height();
3124
- this.listItemsHeight = 0;
3125
- return this.$items.children().each((function(_this) {
3126
- return function(i, el) {
3127
- return _this.listItemsHeight += $(el).height();
3123
+ return _this.lastScrollTop = e.target.scrollTop;
3128
3124
  };
3129
3125
  })(this));
3130
3126
  }
@@ -3238,7 +3234,7 @@ this.listSearch = {
3238
3234
  this.$el.removeClass('list-search');
3239
3235
  this.$searchInput.val('');
3240
3236
  this._show_spinner();
3241
- return this.config.arrayStore.reset(false);
3237
+ return this.config.arrayStore.reset();
3242
3238
  }
3243
3239
  };
3244
3240
 
@@ -4968,7 +4964,7 @@ this.ArrayStore = (function() {
4968
4964
  this.sortReverse = (ref1 = this.config.sortReverse) != null ? ref1 : false;
4969
4965
  this.reorderable = (ref2 = this.config.reorderable) != null ? ref2 : false;
4970
4966
  this._initialize_reorderable();
4971
- this._initialize_database();
4967
+ this._initialize_store();
4972
4968
  }
4973
4969
 
4974
4970
  ArrayStore.prototype._initialize_reorderable = function() {
@@ -4984,7 +4980,7 @@ this.ArrayStore = (function() {
4984
4980
  }
4985
4981
  };
4986
4982
 
4987
- ArrayStore.prototype._initialize_database = function() {};
4983
+ ArrayStore.prototype._initialize_store = function() {};
4988
4984
 
4989
4985
  ArrayStore.prototype._sort_data = function() {
4990
4986
  var direction, fieldName, sortByMethod;
@@ -5028,43 +5024,51 @@ this.ArrayStore = (function() {
5028
5024
  };
5029
5025
 
5030
5026
  ArrayStore.prototype._add_data_object = function(object) {
5031
- var position;
5027
+ var data, position;
5032
5028
  object = this._normalize_object_id(object);
5033
5029
  if (!this._map[object._id]) {
5034
5030
  this._map[object._id] = object;
5035
5031
  this._data.push(object);
5036
5032
  this._sort_data();
5037
5033
  position = this._get_data_object_position(object._id);
5038
- return $(this).trigger('object_added', {
5034
+ data = {
5039
5035
  object: object,
5040
5036
  position: position
5041
- });
5037
+ };
5038
+ $(this).trigger('object_added', data);
5039
+ return data;
5042
5040
  } else {
5043
5041
  return this._update_data_object(object.id, object);
5044
5042
  }
5045
5043
  };
5046
5044
 
5047
5045
  ArrayStore.prototype._update_data_object = function(id, value) {
5048
- var object, position;
5046
+ var data, object, old_position, position;
5049
5047
  object = $.extend(this.get(id), value);
5048
+ old_position = this._get_data_object_position(id);
5050
5049
  this._sort_data();
5051
5050
  position = this._get_data_object_position(id);
5052
- return $(this).trigger('object_changed', {
5051
+ data = {
5053
5052
  object: object,
5054
- position: position
5055
- });
5053
+ position: position,
5054
+ positionHasChanged: old_position !== position
5055
+ };
5056
+ $(this).trigger('object_changed', data);
5057
+ return data;
5056
5058
  };
5057
5059
 
5058
5060
  ArrayStore.prototype._remove_data_object = function(id) {
5059
- var position;
5061
+ var data, position;
5060
5062
  position = this._get_data_object_position(id);
5061
5063
  if (position >= 0) {
5062
5064
  this._data.splice(position, 1);
5063
5065
  }
5064
5066
  delete this._map[id];
5065
- return $(this).trigger('object_removed', {
5067
+ data = {
5066
5068
  object_id: id
5067
- });
5069
+ };
5070
+ $(this).trigger('object_removed', data);
5071
+ return data;
5068
5072
  };
5069
5073
 
5070
5074
  ArrayStore.prototype._reset_data = function() {
@@ -5164,10 +5168,10 @@ this.ArrayStore = (function() {
5164
5168
  this.ObjectStore = (function() {
5165
5169
  function ObjectStore(config) {
5166
5170
  this.config = config != null ? config : {};
5167
- this._initialize_database();
5171
+ this._initialize_store();
5168
5172
  }
5169
5173
 
5170
- ObjectStore.prototype._initialize_database = function() {
5174
+ ObjectStore.prototype._initialize_store = function() {
5171
5175
  return this._data = this.config.data;
5172
5176
  };
5173
5177
 
@@ -5194,8 +5198,26 @@ this.RestArrayStore = (function(superClass) {
5194
5198
  return RestArrayStore.__super__.constructor.apply(this, arguments);
5195
5199
  }
5196
5200
 
5197
- RestArrayStore.prototype._initialize_database = function() {
5201
+ RestArrayStore.prototype._initialize_store = function() {
5202
+ var ref, ref1, ref2;
5198
5203
  this.dataFetchLock = false;
5204
+ this.lastPageLoaded = false;
5205
+ this.searchable = (ref = this.config.searchable) != null ? ref : false;
5206
+ this.searchQuery = '';
5207
+ this.pagination = (ref1 = this.config.pagination) != null ? ref1 : true;
5208
+ this.nextPage = 1;
5209
+ this.objectsPerPage = (ref2 = chr.itemsPerPageRequest) != null ? ref2 : 20;
5210
+ if (this.requestParams == null) {
5211
+ this.requestParams = {
5212
+ page: 'page',
5213
+ perPage: 'perPage',
5214
+ search: 'search'
5215
+ };
5216
+ }
5217
+ return this._configure_store();
5218
+ };
5219
+
5220
+ RestArrayStore.prototype._configure_store = function() {
5199
5221
  return this.ajaxConfig = {};
5200
5222
  };
5201
5223
 
@@ -5205,10 +5227,20 @@ this.RestArrayStore = (function(superClass) {
5205
5227
  return "" + this.config.path + objectPath;
5206
5228
  };
5207
5229
 
5230
+ RestArrayStore.prototype._request_url = function(type, id) {
5231
+ var extraParamsString, url;
5232
+ url = this._resource_url(type, id);
5233
+ if (this.config.urlParams) {
5234
+ extraParamsString = $.param(this.config.urlParams);
5235
+ url = url + "?" + extraParamsString;
5236
+ }
5237
+ return url;
5238
+ };
5239
+
5208
5240
  RestArrayStore.prototype._ajax = function(type, id, data, success, error) {
5209
5241
  var options;
5210
5242
  options = $.extend(this.ajaxConfig, {
5211
- url: this._resource_url(type, id),
5243
+ url: this._request_url(type, id),
5212
5244
  type: type,
5213
5245
  data: data,
5214
5246
  success: (function(_this) {
@@ -5218,7 +5250,7 @@ this.RestArrayStore = (function(superClass) {
5218
5250
  }
5219
5251
  return setTimeout((function() {
5220
5252
  return _this.dataFetchLock = false;
5221
- }), 350);
5253
+ }), 50);
5222
5254
  };
5223
5255
  })(this),
5224
5256
  error: (function(_this) {
@@ -5281,6 +5313,29 @@ this.RestArrayStore = (function(superClass) {
5281
5313
  return results;
5282
5314
  };
5283
5315
 
5316
+ RestArrayStore.prototype._update_next_page = function(data) {
5317
+ if (this.pagination) {
5318
+ if (data.length > 0) {
5319
+ this.lastPageLoaded = true;
5320
+ if (data.length === this.objectsPerPage) {
5321
+ this.nextPage += 1;
5322
+ return this.lastPageLoaded = false;
5323
+ }
5324
+ } else {
5325
+ return this.lastPageLoaded = true;
5326
+ }
5327
+ }
5328
+ };
5329
+
5330
+ RestArrayStore.prototype._is_pagination_edge_case = function() {
5331
+ return this.pagination && this.lastPageLoaded === false;
5332
+ };
5333
+
5334
+ RestArrayStore.prototype._reload_current_page = function(callbacks) {
5335
+ this.nextPage -= 1;
5336
+ return this.load(true, callbacks);
5337
+ };
5338
+
5284
5339
  RestArrayStore.prototype.loadObject = function(id, callbacks) {
5285
5340
  if (callbacks == null) {
5286
5341
  callbacks = {};
@@ -5298,7 +5353,11 @@ this.RestArrayStore = (function(superClass) {
5298
5353
  })(this)), callbacks.onError);
5299
5354
  };
5300
5355
 
5301
- RestArrayStore.prototype.load = function(callbacks) {
5356
+ RestArrayStore.prototype.load = function(sync, callbacks) {
5357
+ var params;
5358
+ if (sync == null) {
5359
+ sync = false;
5360
+ }
5302
5361
  if (callbacks == null) {
5303
5362
  callbacks = {};
5304
5363
  }
@@ -5308,10 +5367,22 @@ this.RestArrayStore = (function(superClass) {
5308
5367
  if (callbacks.onError == null) {
5309
5368
  callbacks.onError = $.noop;
5310
5369
  }
5311
- return this._ajax('GET', null, {}, ((function(_this) {
5370
+ params = {};
5371
+ if (this.pagination) {
5372
+ params[this.requestParams.page] = this.nextPage;
5373
+ params[this.requestParams.perPage] = this.objectsPerPage;
5374
+ }
5375
+ if (this.searchable && this.searchQuery.length > 0) {
5376
+ params[this.requestParams.search] = this.searchQuery;
5377
+ }
5378
+ params = $.param(params);
5379
+ return this._ajax('GET', null, params, ((function(_this) {
5312
5380
  return function(data) {
5313
5381
  var i, len, o;
5314
- if (data.length > 0) {
5382
+ _this._update_next_page(data);
5383
+ if (sync) {
5384
+ _this._sync_with_data_objects(data);
5385
+ } else {
5315
5386
  for (i = 0, len = data.length; i < len; i++) {
5316
5387
  o = data[i];
5317
5388
  _this._add_data_object(o);
@@ -5322,7 +5393,20 @@ this.RestArrayStore = (function(superClass) {
5322
5393
  objects: data
5323
5394
  });
5324
5395
  };
5325
- })(this))(callbacks.onError));
5396
+ })(this)), function() {
5397
+ return chr.showError('Error while loading data, application error 500.');
5398
+ });
5399
+ };
5400
+
5401
+ RestArrayStore.prototype.reset = function(searchQuery1) {
5402
+ this.searchQuery = searchQuery1 != null ? searchQuery1 : '';
5403
+ this.lastPageLoaded = false;
5404
+ this.nextPage = 1;
5405
+ return this.load(true);
5406
+ };
5407
+
5408
+ RestArrayStore.prototype.search = function(searchQuery) {
5409
+ return this.reset(searchQuery);
5326
5410
  };
5327
5411
 
5328
5412
  RestArrayStore.prototype.push = function(serializedFormObject, callbacks) {
@@ -5339,7 +5423,13 @@ this.RestArrayStore = (function(superClass) {
5339
5423
  obj = this._parse_form_object(serializedFormObject);
5340
5424
  return this._ajax('POST', null, obj, ((function(_this) {
5341
5425
  return function(data) {
5342
- _this._add_data_object(data);
5426
+ var d;
5427
+ d = _this._add_data_object(data);
5428
+ if (_this._is_pagination_edge_case()) {
5429
+ if (d.position >= (_this.nextPage - 1) * _this.objectsPerPage) {
5430
+ _this._remove_data_object(d.object._id);
5431
+ }
5432
+ }
5343
5433
  return callbacks.onSuccess(data);
5344
5434
  };
5345
5435
  })(this)), callbacks.onError);
@@ -5359,8 +5449,15 @@ this.RestArrayStore = (function(superClass) {
5359
5449
  obj = this._parse_form_object(serializedFormObject);
5360
5450
  return this._ajax('PUT', id, obj, ((function(_this) {
5361
5451
  return function(data) {
5362
- _this._update_data_object(id, data);
5363
- return callbacks.onSuccess(data);
5452
+ var d;
5453
+ d = _this._update_data_object(id, data);
5454
+ if (_this._is_pagination_edge_case() && d.positionHasChanged) {
5455
+ if (d.position >= (_this.nextPage - 1) * _this.objectsPerPage - 1) {
5456
+ return _this._reload_current_page(callbacks);
5457
+ }
5458
+ } else {
5459
+ return callbacks.onSuccess(data);
5460
+ }
5364
5461
  };
5365
5462
  })(this)), callbacks.onError);
5366
5463
  };
@@ -5378,24 +5475,15 @@ this.RestArrayStore = (function(superClass) {
5378
5475
  return this._ajax('DELETE', id, {}, ((function(_this) {
5379
5476
  return function() {
5380
5477
  _this._remove_data_object(id);
5381
- return callbacks.onSuccess();
5478
+ if (_this._is_pagination_edge_case()) {
5479
+ return _this._reload_current_page(callbacks);
5480
+ } else {
5481
+ return callbacks.onSuccess();
5482
+ }
5382
5483
  };
5383
5484
  })(this)), callbacks.onError);
5384
5485
  };
5385
5486
 
5386
- RestArrayStore.prototype.reset = function() {
5387
- return this._ajax('GET', null, {}, ((function(_this) {
5388
- return function(data) {
5389
- _this._sync_with_data_objects(data);
5390
- return $(_this).trigger('objects_added', {
5391
- objects: data
5392
- });
5393
- };
5394
- })(this)), function() {
5395
- return chr.showError('Error while loading data.');
5396
- });
5397
- };
5398
-
5399
5487
  return RestArrayStore;
5400
5488
 
5401
5489
  })(ArrayStore);
@@ -5410,8 +5498,12 @@ this.RestObjectStore = (function(superClass) {
5410
5498
  return RestObjectStore.__super__.constructor.apply(this, arguments);
5411
5499
  }
5412
5500
 
5413
- RestObjectStore.prototype._initialize_database = function() {
5501
+ RestObjectStore.prototype._initialize_store = function() {
5414
5502
  this.dataFetchLock = false;
5503
+ return this._configure_store();
5504
+ };
5505
+
5506
+ RestObjectStore.prototype._configure_store = function() {
5415
5507
  return this.ajaxConfig = {};
5416
5508
  };
5417
5509
 
@@ -5508,89 +5600,17 @@ this.MongosteenArrayStore = (function(superClass) {
5508
5600
  return MongosteenArrayStore.__super__.constructor.apply(this, arguments);
5509
5601
  }
5510
5602
 
5511
- MongosteenArrayStore.prototype._initialize_database = function() {
5512
- var ref, ref1, ref2;
5513
- this.dataFetchLock = false;
5514
- this.ajaxConfig = {
5603
+ MongosteenArrayStore.prototype._configure_store = function() {
5604
+ return this.ajaxConfig = {
5515
5605
  processData: false,
5516
5606
  contentType: false
5517
5607
  };
5518
- this.searchable = (ref = this.config.searchable) != null ? ref : false;
5519
- this.searchQuery = '';
5520
- this.pagination = (ref1 = this.config.pagination) != null ? ref1 : true;
5521
- this.nextPage = 1;
5522
- this.objectsPerPage = (ref2 = chr.itemsPerPageRequest) != null ? ref2 : 20;
5523
- if (this.pagination) {
5524
- this.lastPageLoaded = false;
5525
- return this._bind_pagination_sync();
5526
- }
5527
- };
5528
-
5529
- MongosteenArrayStore.prototype._bind_pagination_sync = function() {
5530
- $(this).on('object_added', (function(_this) {
5531
- return function(e, data) {
5532
- var new_object, new_object_position;
5533
- if (!_this.lastPageLoaded) {
5534
- new_object = data.object;
5535
- new_object_position = data.position;
5536
- if (new_object_position >= _this.objectsNumberForLoadedPages) {
5537
- e.stopImmediatePropagation();
5538
- return _this._remove_data_object(new_object._id);
5539
- }
5540
- }
5541
- };
5542
- })(this));
5543
- $(this).on('object_changed', (function(_this) {
5544
- return function(e, data) {
5545
- var new_object, new_object_position;
5546
- if (!_this.lastPageLoaded) {
5547
- new_object = data.object;
5548
- new_object_position = data.position;
5549
- if (new_object_position >= _this.objectsNumberForLoadedPages - 1) {
5550
- e.stopImmediatePropagation();
5551
- return _this._remove_data_object(new_object._id);
5552
- }
5553
- }
5554
- };
5555
- })(this));
5556
- return $(this).on('object_removed', (function(_this) {
5557
- return function(e, data) {
5558
- if (!_this.lastPageLoaded) {
5559
- return _this._reload_current_page();
5560
- }
5561
- };
5562
- })(this));
5563
- };
5564
-
5565
- MongosteenArrayStore.prototype._reload_current_page = function() {
5566
- this.nextPage -= 1;
5567
- return this.load();
5568
- };
5569
-
5570
- MongosteenArrayStore.prototype._update_next_page = function(data) {
5571
- if (this.pagination) {
5572
- if (data.length > 0) {
5573
- this.lastPageLoaded = true;
5574
- if (data.length === this.objectsPerPage) {
5575
- this.nextPage += 1;
5576
- this.lastPageLoaded = false;
5577
- }
5578
- } else {
5579
- this.lastPageLoaded = true;
5580
- }
5581
- }
5582
- return this.objectsNumberForLoadedPages = (this.nextPage - 1) * this.objectsPerPage;
5583
5608
  };
5584
5609
 
5585
5610
  MongosteenArrayStore.prototype._resource_url = function(type, id) {
5586
- var extraParamsString, objectPath, url;
5611
+ var objectPath;
5587
5612
  objectPath = id ? "/" + id : '';
5588
- url = "" + this.config.path + objectPath + ".json";
5589
- if (this.config.urlParams) {
5590
- extraParamsString = $.param(this.config.urlParams);
5591
- url = url + "?" + extraParamsString;
5592
- }
5593
- return url;
5613
+ return "" + this.config.path + objectPath + ".json";
5594
5614
  };
5595
5615
 
5596
5616
  MongosteenArrayStore.prototype._parse_form_object = function(serializedFormObject) {
@@ -5615,81 +5635,6 @@ this.MongosteenArrayStore = (function(superClass) {
5615
5635
  return formDataObject;
5616
5636
  };
5617
5637
 
5618
- MongosteenArrayStore.prototype.search = function(searchQuery) {
5619
- this.searchQuery = searchQuery;
5620
- this.nextPage = 1;
5621
- this.lastPageLoaded = true;
5622
- this._reset_data();
5623
- return this.load();
5624
- };
5625
-
5626
- MongosteenArrayStore.prototype.load = function(callbacks) {
5627
- var params;
5628
- if (callbacks == null) {
5629
- callbacks = {};
5630
- }
5631
- if (callbacks.onSuccess == null) {
5632
- callbacks.onSuccess = $.noop;
5633
- }
5634
- if (callbacks.onError == null) {
5635
- callbacks.onError = $.noop;
5636
- }
5637
- params = {};
5638
- if (this.pagination) {
5639
- params.page = this.nextPage;
5640
- params.perPage = this.objectsPerPage;
5641
- }
5642
- if (this.searchable && this.searchQuery.length > 0) {
5643
- params.search = this.searchQuery;
5644
- }
5645
- params = $.param(params);
5646
- return this._ajax('GET', null, params, ((function(_this) {
5647
- return function(data) {
5648
- var i, len, o;
5649
- _this._update_next_page(data);
5650
- for (i = 0, len = data.length; i < len; i++) {
5651
- o = data[i];
5652
- _this._add_data_object(o);
5653
- }
5654
- callbacks.onSuccess(data);
5655
- return $(_this).trigger('objects_added', {
5656
- objects: data
5657
- });
5658
- };
5659
- })(this)), callbacks.onError);
5660
- };
5661
-
5662
- MongosteenArrayStore.prototype.reset = function(sync_with_existing_objects) {
5663
- var params;
5664
- if (sync_with_existing_objects == null) {
5665
- sync_with_existing_objects = true;
5666
- }
5667
- this.searchQuery = '';
5668
- this.nextPage = 1;
5669
- params = {};
5670
- if (!sync_with_existing_objects) {
5671
- this.lastPageLoaded = true;
5672
- this._reset_data();
5673
- }
5674
- if (this.pagination) {
5675
- this.lastPageLoaded = false;
5676
- params.page = this.nextPage;
5677
- params.perPage = this.objectsPerPage;
5678
- }
5679
- params = $.param(params);
5680
- return this._ajax('GET', null, params, ((function(_this) {
5681
- return function(data) {
5682
- _this._update_next_page(data);
5683
- _this._sync_with_data_objects(data);
5684
- return $(_this).trigger('objects_added', {
5685
- objects: data
5686
- });
5687
- };
5688
- })(this)), function() {
5689
- return chr.showError('Error while loading data.');
5690
- });
5691
- };
5692
-
5693
5638
  return MongosteenArrayStore;
5694
5639
 
5695
5640
  })(RestArrayStore);
@@ -5704,8 +5649,7 @@ this.MongosteenObjectStore = (function(superClass) {
5704
5649
  return MongosteenObjectStore.__super__.constructor.apply(this, arguments);
5705
5650
  }
5706
5651
 
5707
- MongosteenObjectStore.prototype._initialize_database = function() {
5708
- this.dataFetchLock = false;
5652
+ MongosteenObjectStore.prototype._configure_store = function() {
5709
5653
  return this.ajaxConfig = {
5710
5654
  processData: false,
5711
5655
  contentType: false
@@ -1,3 +1,3 @@
1
1
  module Chr
2
- VERSION = "0.2.7"
2
+ VERSION = "0.2.8"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chr",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "devDependencies": {
5
5
  "grunt": "^0.4.5",
6
6
  "grunt-contrib-clean": "^0.6.0",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Kravets
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-07 00:00:00.000000000 Z
11
+ date: 2015-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bourbon