chr 0.2.7 → 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
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