chr 0.2.5 → 0.2.7

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: bc38de2cb0b82aa71968cd48127d83146daa2bfd
4
- data.tar.gz: 9a373db5e5f9d4e1ce08ef020b8691b4b3c5d473
3
+ metadata.gz: 5a86d147a723188f151bcacca8c35a403bd6fcf3
4
+ data.tar.gz: f1be1f7997afb7976ecfbda0f1641b69e12e3ac2
5
5
  SHA512:
6
- metadata.gz: b13c5bdb285b264cd540f236b6c55aa8c5671c66122798a5c1f840b8055d18c1a775d60c7fb9305c10cb3e8e06d20c616ae1fe6d296739c198418929bf1f06ca
7
- data.tar.gz: 8223dd3c23d34d4da1cfbba9d22f7089e5ebe201a26ad6e58f6d08d482803c0613e794607f348a1e0ba7ef8dd587ce9e680bb6ce16ab1db72992f4920ea2dce3
6
+ metadata.gz: 2aec7e0a14af19ce53844ab6b58e615a26db8338a9bfbf7382869ce6f796383128b409625bd2fcc091e02b42a92a93f035902f7dfa8857d0c65eeb0e6aefc8be
7
+ data.tar.gz: 918c153a9f11d8e7add0fcd26fedf80cf701bc398c3f1c7c0367dbf7f0374b61a140ef24516cd73692ed117eaec20cfca4dd944ad8f5f8210fb9a4d3dfd16905
data/README.md CHANGED
@@ -14,20 +14,19 @@ Application setup:
14
14
  postsConfig = (data) ->
15
15
  itemTitleField: 'title'
16
16
  arrayStore: new RestArrayStore({
17
- resource: 'post'
18
17
  path: '/admin/posts'
19
18
  sortBy: 'title'
20
19
  })
21
20
  formSchema:
22
- title { type: 'string' }
23
- body: { type: 'text' }
21
+ title: { type: 'string' }
22
+ body: { type: 'text' }
24
23
 
25
24
  $ ->
26
25
  config =
27
26
  modules:
28
27
  posts: postsConfig()
29
28
 
30
- chr.start(config)
29
+ chr.start(config)
31
30
  ```
32
31
 
33
32
  Styles setup:
@@ -80,14 +80,6 @@ class @List
80
80
  @$newBtn.on 'click', (e) => @_new(e)
81
81
  @$header.append @$newBtn
82
82
 
83
- # search
84
- @$search =$ """<div class='search' style='display: none;'>
85
- <a href='#' class='icon'></a>
86
- <input type='text' placeholder='Search...' />
87
- <a href='#' class='cancel'>Cancel</a>
88
- </div>"""
89
- @$header.append @$search
90
-
91
83
  if @config.items then @_process_config_items()
92
84
  if @config.arrayStore then @_bind_config_array_store()
93
85
  if @config.objectStore then @_bind_config_object_store()
@@ -52,10 +52,10 @@
52
52
  @_bind_pagination()
53
53
 
54
54
  if @config.arrayStore.searchable
55
- @_bind_search(this)
55
+ @_bind_search()
56
56
 
57
57
  if @config.arrayStore.reorderable
58
- @_bind_reorder(this)
58
+ @_bind_reorder()
59
59
 
60
60
 
61
61
  _bind_config_object_store: ->
@@ -1,26 +1,34 @@
1
1
  # -----------------------------------------------------------------------------
2
2
  # LIST PAGINATION
3
- # todo:
4
- # - trigger onScroll event only when scrolling down
5
3
  # -----------------------------------------------------------------------------
6
4
 
7
5
  @listPagination =
6
+
8
7
  # PRIVATE ===============================================
9
8
 
10
9
  _bind_pagination: ->
11
- arrayStore = @config.arrayStore
10
+ @lastScrollTop = 0
11
+
12
12
  @$items.scroll (e) =>
13
- if ! arrayStore.dataFetchLock
14
- # TODO: update this logic as it's not reliable when items has different height
15
- $listChildren = @$items.children()
16
- listChildrenCount = $listChildren.length
17
- listFirstChildHeight = $listChildren.first().outerHeight()
18
- listHeight = listChildrenCount * listFirstChildHeight
19
- viewHeight = @$el.height()
20
-
21
- if listHeight < (viewHeight + e.target.scrollTop + 100)
22
- @_show_spinner()
23
- arrayStore.load()
13
+ # trigger next page loading only when scrolling to bottom
14
+ if @lastScrollTop < e.target.scrollTop
15
+ @lastScrollTop = e.target.scrollTop
16
+
17
+ if ! @config.arrayStore.dataFetchLock
18
+
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.")
24
+
25
+ @_update_height_params()
26
+
27
+
28
+ _update_height_params: ->
29
+ @listViewHeight = @$el.height()
30
+ @listItemsHeight = 0
31
+ @$items.children().each (i, el) => @listItemsHeight += $(el).height()
24
32
 
25
33
 
26
34
 
@@ -8,12 +8,13 @@
8
8
  # -----------------------------------------------------------------------------
9
9
 
10
10
  @listReorder =
11
+
11
12
  # PRIVATE ===============================================
12
13
 
13
- _bind_reorder: (listEl) ->
14
- items = listEl.items
15
- list = listEl.$items.get(0)
16
- arrayStore = listEl.config.arrayStore
14
+ _bind_reorder: ->
15
+ items = @items
16
+ list = @$items.get(0)
17
+ arrayStore = @config.arrayStore
17
18
 
18
19
  config = arrayStore.reorderable
19
20
 
@@ -3,38 +3,51 @@
3
3
  # -----------------------------------------------------------------------------
4
4
 
5
5
  @listSearch =
6
+
6
7
  # PRIVATE ===============================================
7
8
 
8
- _bind_search: (listEl) ->
9
- $input = listEl.$search
10
- arrayStore = listEl.config.arrayStore
9
+ _bind_search: ->
10
+ @$search =$ "<div class='search'></div>"
11
+ @$searchIcon =$ "<a href='#' class='icon'></a>"
12
+ @$searchInput =$ "<input type='text' placeholder='Search...' />"
13
+ @$searchCancel =$ "<a href='#' class='cancel'>Cancel</a>"
11
14
 
12
- search = (input) ->
13
- query = $(input).val()
14
- listEl._show_spinner()
15
- arrayStore.search(query)
15
+ @$header.append(@$search)
16
+ @$search.append(@$searchIcon)
17
+ @$search.append(@$searchInput)
18
+ @$search.append(@$searchCancel)
16
19
 
17
- show = ->
18
- listEl.$el.addClass 'list-search'
19
- $input.find('input').focus()
20
+ @$searchInput.on 'keyup', (e) =>
21
+ if e.keyCode == 27 # esc
22
+ return @_on_search_cancel()
20
23
 
21
- cancel = ->
22
- listEl.$el.removeClass 'list-search'
23
- $input.find('input').val('')
24
- listEl._show_spinner()
25
- arrayStore.reset()
24
+ if e.keyCode == 13 # enter
25
+ return @_on_search()
26
26
 
27
- $input.show()
27
+ @$searchIcon.on 'click', (e) => e.preventDefault() ; @_on_search_show()
28
+ @$searchCancel.on 'click', (e) => e.preventDefault() ; @_on_search_cancel()
28
29
 
29
- $input.on 'keyup', 'input', (e) =>
30
- if e.keyCode == 27 # esc
31
- return cancel()
32
30
 
33
- if e.keyCode == 13 # enter
34
- return search(e.target)
31
+ # EVENTS ================================================
32
+
33
+ _on_search: ->
34
+ query = @$searchInput.val()
35
+ @_show_spinner()
36
+ @config.arrayStore.search(query)
37
+
38
+
39
+ _on_search_show: ->
40
+ @$el.addClass('list-search')
41
+ @$searchInput.focus()
42
+ @$search.show()
43
+
35
44
 
36
- $input.on 'click', '.icon', (e) => e.preventDefault() ; show()
37
- $input.on 'click', '.cancel', (e) => e.preventDefault() ; cancel()
45
+ _on_search_cancel: ->
46
+ @$el.removeClass('list-search')
47
+ @$searchInput.val('')
48
+ @_show_spinner()
49
+ # use reset(false) to do not sync with the existing list items
50
+ @config.arrayStore.reset(false)
38
51
 
39
52
 
40
53
 
@@ -45,6 +45,8 @@ class @ArrayStore
45
45
  @_initialize_database()
46
46
 
47
47
 
48
+ # PRIVATE ===============================================
49
+
48
50
  # when store is reorderable update sorting configuration
49
51
  _initialize_reorderable: ->
50
52
  if @reorderable
@@ -163,6 +165,8 @@ class @ArrayStore
163
165
  return object
164
166
 
165
167
 
168
+ # PUBLIC ================================================
169
+
166
170
  # subsribe to store event
167
171
  on: (eventType, callback) ->
168
172
  $(this).on eventType, (e, data) -> callback(e, data)
@@ -13,12 +13,18 @@ class @ObjectStore
13
13
  constructor: (@config={}) ->
14
14
  @_initialize_database()
15
15
 
16
+ # PRIVATE ===============================================
17
+
16
18
  _initialize_database: ->
17
19
  @_data = @config.data
18
20
 
21
+
22
+ # PUBLIC ================================================
23
+
19
24
  loadObject: ->
20
25
  @_data
21
26
 
27
+
22
28
  update: (id, value, callback) ->
23
29
  $.extend(@_data, value)
24
30
  callback?(@_data)
@@ -26,7 +26,9 @@
26
26
  #
27
27
  # -----------------------------------------------------------------------------
28
28
  class @MongosteenArrayStore extends RestArrayStore
29
- # initial store configuration
29
+
30
+ # PRIVATE ===============================================
31
+
30
32
  _initialize_database: ->
31
33
  @dataFetchLock = false
32
34
  @ajaxConfig =
@@ -41,6 +43,7 @@ class @MongosteenArrayStore extends RestArrayStore
41
43
  @objectsPerPage = chr.itemsPerPageRequest ? 20
42
44
 
43
45
  if @pagination
46
+ @lastPageLoaded = false
44
47
  @_bind_pagination_sync()
45
48
 
46
49
 
@@ -49,8 +52,6 @@ class @MongosteenArrayStore extends RestArrayStore
49
52
  # database while loading next page
50
53
  # ---------------------------------------------------------
51
54
  _bind_pagination_sync: ->
52
- @lastPageLoaded = false
53
-
54
55
  # when object's added to the end of the list & not on the last page,
55
56
  # we don't know it's position on the backend, so remove it from store
56
57
  $(this).on 'object_added', (e, data) =>
@@ -87,7 +88,7 @@ class @MongosteenArrayStore extends RestArrayStore
87
88
  @nextPage -= 1 ; @load()
88
89
 
89
90
 
90
- _udpate_next_page: (data) ->
91
+ _update_next_page: (data) ->
91
92
  if @pagination
92
93
  if data.length > 0
93
94
  @lastPageLoaded = true
@@ -140,9 +141,13 @@ class @MongosteenArrayStore extends RestArrayStore
140
141
  return formDataObject
141
142
 
142
143
 
143
- # load results for search query
144
+ # PUBLIC ================================================
145
+
146
+ # load first page of results for search query, skip store 'object_removed'
147
+ # event handler on @_reset_data()
144
148
  search: (@searchQuery) ->
145
- @nextPage = 1
149
+ @nextPage = 1
150
+ @lastPageLoaded = true
146
151
  @_reset_data()
147
152
  @load()
148
153
 
@@ -165,7 +170,7 @@ class @MongosteenArrayStore extends RestArrayStore
165
170
  params = $.param(params)
166
171
 
167
172
  @_ajax 'GET', null, params, ((data) =>
168
- @_udpate_next_page(data)
173
+ @_update_next_page(data)
169
174
  @_add_data_object(o) for o in data
170
175
 
171
176
  callbacks.onSuccess(data)
@@ -174,12 +179,18 @@ class @MongosteenArrayStore extends RestArrayStore
174
179
  ), callbacks.onError
175
180
 
176
181
 
177
- # reset data and load first page
178
- reset: ->
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)->
179
186
  @searchQuery = ''
180
187
  @nextPage = 1
181
188
  params = {}
182
189
 
190
+ if ! sync_with_existing_objects
191
+ @lastPageLoaded = true
192
+ @_reset_data()
193
+
183
194
  if @pagination
184
195
  @lastPageLoaded = false
185
196
  params.page = @nextPage
@@ -188,7 +199,7 @@ class @MongosteenArrayStore extends RestArrayStore
188
199
  params = $.param(params)
189
200
 
190
201
  @_ajax 'GET', null, params, ((data) =>
191
- @_udpate_next_page(data)
202
+ @_update_next_page(data)
192
203
  @_sync_with_data_objects(data)
193
204
 
194
205
  $(this).trigger('objects_added', { objects: data })
@@ -10,7 +10,9 @@
10
10
  # MONGOSTEEN (RAILS) OBJECT STORE IMPLEMENTATION
11
11
  # -----------------------------------------------------------------------------
12
12
  class @MongosteenObjectStore extends RestObjectStore
13
- # initial store configuration
13
+
14
+ # PRIVATE ===============================================
15
+
14
16
  _initialize_database: ->
15
17
  @dataFetchLock = false
16
18
  @ajaxConfig =
@@ -10,7 +10,9 @@
10
10
  # REST ARRAY STORE
11
11
  # -----------------------------------------------------------------------------
12
12
  class @RestArrayStore extends ArrayStore
13
- # initial store configuration
13
+
14
+ # PRIVATE ===============================================
15
+
14
16
  _initialize_database: ->
15
17
  @dataFetchLock = false
16
18
  @ajaxConfig = {}
@@ -65,6 +67,8 @@ class @RestArrayStore extends ArrayStore
65
67
  @_update_data_object(id, objectsMap[id])
66
68
 
67
69
 
70
+ # PUBLIC ================================================
71
+
68
72
  # load a single object, this is used in view when
69
73
  # store has not required item
70
74
  loadObject: (id, callbacks={}) ->
@@ -10,6 +10,9 @@
10
10
  # REST OBJECT STORE
11
11
  # -----------------------------------------------------------------------------
12
12
  class @RestObjectStore extends ObjectStore
13
+
14
+ # PRIVATE ===============================================
15
+
13
16
  _initialize_database: ->
14
17
  @dataFetchLock = false
15
18
  @ajaxConfig = {}
@@ -51,6 +54,8 @@ class @RestObjectStore extends ObjectStore
51
54
  $.ajax options
52
55
 
53
56
 
57
+ # PUBLIC ================================================
58
+
54
59
  # load a single object, this is used in view when
55
60
  # store has not required item
56
61
  loadObject: (callbacks={}) ->
@@ -30,7 +30,7 @@ class @InputRedactor extends InputString
30
30
 
31
31
  initialize: ->
32
32
  plugins = [ 'fixedtoolbar' ]
33
- if Loft then plugins.push('loft')
33
+ if Loft? then plugins.push('loft')
34
34
 
35
35
  redactor_options =
36
36
  focus: false
data/bower.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chr",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "homepage": "https://github.com/slate-studio/chr",
5
5
  "authors": [
6
6
  "Slate Studio (http://www.slatestudio.com)"
@@ -3085,10 +3085,10 @@ this.listConfig = {
3085
3085
  this._bind_pagination();
3086
3086
  }
3087
3087
  if (this.config.arrayStore.searchable) {
3088
- this._bind_search(this);
3088
+ this._bind_search();
3089
3089
  }
3090
3090
  if (this.config.arrayStore.reorderable) {
3091
- return this._bind_reorder(this);
3091
+ return this._bind_reorder();
3092
3092
  }
3093
3093
  },
3094
3094
  _bind_config_object_store: function() {}
@@ -3096,33 +3096,46 @@ this.listConfig = {
3096
3096
 
3097
3097
  this.listPagination = {
3098
3098
  _bind_pagination: function() {
3099
- var arrayStore;
3100
- arrayStore = this.config.arrayStore;
3101
- return this.$items.scroll((function(_this) {
3099
+ this.lastScrollTop = 0;
3100
+ this.$items.scroll((function(_this) {
3102
3101
  return function(e) {
3103
- var $listChildren, listChildrenCount, listFirstChildHeight, listHeight, viewHeight;
3104
- if (!arrayStore.dataFetchLock) {
3105
- $listChildren = _this.$items.children();
3106
- listChildrenCount = $listChildren.length;
3107
- listFirstChildHeight = $listChildren.first().outerHeight();
3108
- listHeight = listChildrenCount * listFirstChildHeight;
3109
- viewHeight = _this.$el.height();
3110
- if (listHeight < (viewHeight + e.target.scrollTop + 100)) {
3111
- _this._show_spinner();
3112
- return arrayStore.load();
3102
+ if (_this.lastScrollTop < e.target.scrollTop) {
3103
+ _this.lastScrollTop = e.target.scrollTop;
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
+ });
3115
+ }
3113
3116
  }
3114
3117
  }
3115
3118
  };
3116
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();
3128
+ };
3129
+ })(this));
3117
3130
  }
3118
3131
  };
3119
3132
 
3120
3133
  this.listReorder = {
3121
- _bind_reorder: function(listEl) {
3134
+ _bind_reorder: function() {
3122
3135
  var _getObjectNewPosition, arrayStore, config, items, list;
3123
- items = listEl.items;
3124
- list = listEl.$items.get(0);
3125
- arrayStore = listEl.config.arrayStore;
3136
+ items = this.items;
3137
+ list = this.$items.get(0);
3138
+ arrayStore = this.config.arrayStore;
3126
3139
  config = arrayStore.reorderable;
3127
3140
  _getObjectNewPosition = function(el) {
3128
3141
  var $el, newPosition, nextObjectId, nextObjectPosition, prevObjectId, prevObjectPosition;
@@ -3178,49 +3191,54 @@ this.listReorder = {
3178
3191
  };
3179
3192
 
3180
3193
  this.listSearch = {
3181
- _bind_search: function(listEl) {
3182
- var $input, arrayStore, cancel, search, show;
3183
- $input = listEl.$search;
3184
- arrayStore = listEl.config.arrayStore;
3185
- search = function(input) {
3186
- var query;
3187
- query = $(input).val();
3188
- listEl._show_spinner();
3189
- return arrayStore.search(query);
3190
- };
3191
- show = function() {
3192
- listEl.$el.addClass('list-search');
3193
- return $input.find('input').focus();
3194
- };
3195
- cancel = function() {
3196
- listEl.$el.removeClass('list-search');
3197
- $input.find('input').val('');
3198
- listEl._show_spinner();
3199
- return arrayStore.reset();
3200
- };
3201
- $input.show();
3202
- $input.on('keyup', 'input', (function(_this) {
3194
+ _bind_search: function() {
3195
+ this.$search = $("<div class='search'></div>");
3196
+ this.$searchIcon = $("<a href='#' class='icon'></a>");
3197
+ this.$searchInput = $("<input type='text' placeholder='Search...' />");
3198
+ this.$searchCancel = $("<a href='#' class='cancel'>Cancel</a>");
3199
+ this.$header.append(this.$search);
3200
+ this.$search.append(this.$searchIcon);
3201
+ this.$search.append(this.$searchInput);
3202
+ this.$search.append(this.$searchCancel);
3203
+ this.$searchInput.on('keyup', (function(_this) {
3203
3204
  return function(e) {
3204
3205
  if (e.keyCode === 27) {
3205
- return cancel();
3206
+ return _this._on_search_cancel();
3206
3207
  }
3207
3208
  if (e.keyCode === 13) {
3208
- return search(e.target);
3209
+ return _this._on_search();
3209
3210
  }
3210
3211
  };
3211
3212
  })(this));
3212
- $input.on('click', '.icon', (function(_this) {
3213
+ this.$searchIcon.on('click', (function(_this) {
3213
3214
  return function(e) {
3214
3215
  e.preventDefault();
3215
- return show();
3216
+ return _this._on_search_show();
3216
3217
  };
3217
3218
  })(this));
3218
- return $input.on('click', '.cancel', (function(_this) {
3219
+ return this.$searchCancel.on('click', (function(_this) {
3219
3220
  return function(e) {
3220
3221
  e.preventDefault();
3221
- return cancel();
3222
+ return _this._on_search_cancel();
3222
3223
  };
3223
3224
  })(this));
3225
+ },
3226
+ _on_search: function() {
3227
+ var query;
3228
+ query = this.$searchInput.val();
3229
+ this._show_spinner();
3230
+ return this.config.arrayStore.search(query);
3231
+ },
3232
+ _on_search_show: function() {
3233
+ this.$el.addClass('list-search');
3234
+ this.$searchInput.focus();
3235
+ return this.$search.show();
3236
+ },
3237
+ _on_search_cancel: function() {
3238
+ this.$el.removeClass('list-search');
3239
+ this.$searchInput.val('');
3240
+ this._show_spinner();
3241
+ return this.config.arrayStore.reset(false);
3224
3242
  }
3225
3243
  };
3226
3244
 
@@ -3276,8 +3294,6 @@ this.List = (function() {
3276
3294
  })(this));
3277
3295
  this.$header.append(this.$newBtn);
3278
3296
  }
3279
- this.$search = $("<div class='search' style='display: none;'>\n <a href='#' class='icon'></a>\n <input type='text' placeholder='Search...' />\n <a href='#' class='cancel'>Cancel</a>\n</div>");
3280
- this.$header.append(this.$search);
3281
3297
  if (this.config.items) {
3282
3298
  this._process_config_items();
3283
3299
  }
@@ -5505,12 +5521,12 @@ this.MongosteenArrayStore = (function(superClass) {
5505
5521
  this.nextPage = 1;
5506
5522
  this.objectsPerPage = (ref2 = chr.itemsPerPageRequest) != null ? ref2 : 20;
5507
5523
  if (this.pagination) {
5524
+ this.lastPageLoaded = false;
5508
5525
  return this._bind_pagination_sync();
5509
5526
  }
5510
5527
  };
5511
5528
 
5512
5529
  MongosteenArrayStore.prototype._bind_pagination_sync = function() {
5513
- this.lastPageLoaded = false;
5514
5530
  $(this).on('object_added', (function(_this) {
5515
5531
  return function(e, data) {
5516
5532
  var new_object, new_object_position;
@@ -5551,7 +5567,7 @@ this.MongosteenArrayStore = (function(superClass) {
5551
5567
  return this.load();
5552
5568
  };
5553
5569
 
5554
- MongosteenArrayStore.prototype._udpate_next_page = function(data) {
5570
+ MongosteenArrayStore.prototype._update_next_page = function(data) {
5555
5571
  if (this.pagination) {
5556
5572
  if (data.length > 0) {
5557
5573
  this.lastPageLoaded = true;
@@ -5602,6 +5618,7 @@ this.MongosteenArrayStore = (function(superClass) {
5602
5618
  MongosteenArrayStore.prototype.search = function(searchQuery) {
5603
5619
  this.searchQuery = searchQuery;
5604
5620
  this.nextPage = 1;
5621
+ this.lastPageLoaded = true;
5605
5622
  this._reset_data();
5606
5623
  return this.load();
5607
5624
  };
@@ -5629,7 +5646,7 @@ this.MongosteenArrayStore = (function(superClass) {
5629
5646
  return this._ajax('GET', null, params, ((function(_this) {
5630
5647
  return function(data) {
5631
5648
  var i, len, o;
5632
- _this._udpate_next_page(data);
5649
+ _this._update_next_page(data);
5633
5650
  for (i = 0, len = data.length; i < len; i++) {
5634
5651
  o = data[i];
5635
5652
  _this._add_data_object(o);
@@ -5642,11 +5659,18 @@ this.MongosteenArrayStore = (function(superClass) {
5642
5659
  })(this)), callbacks.onError);
5643
5660
  };
5644
5661
 
5645
- MongosteenArrayStore.prototype.reset = function() {
5662
+ MongosteenArrayStore.prototype.reset = function(sync_with_existing_objects) {
5646
5663
  var params;
5664
+ if (sync_with_existing_objects == null) {
5665
+ sync_with_existing_objects = true;
5666
+ }
5647
5667
  this.searchQuery = '';
5648
5668
  this.nextPage = 1;
5649
5669
  params = {};
5670
+ if (!sync_with_existing_objects) {
5671
+ this.lastPageLoaded = true;
5672
+ this._reset_data();
5673
+ }
5650
5674
  if (this.pagination) {
5651
5675
  this.lastPageLoaded = false;
5652
5676
  params.page = this.nextPage;
@@ -5655,7 +5679,7 @@ this.MongosteenArrayStore = (function(superClass) {
5655
5679
  params = $.param(params);
5656
5680
  return this._ajax('GET', null, params, ((function(_this) {
5657
5681
  return function(data) {
5658
- _this._udpate_next_page(data);
5682
+ _this._update_next_page(data);
5659
5683
  _this._sync_with_data_objects(data);
5660
5684
  return $(_this).trigger('objects_added', {
5661
5685
  objects: data
@@ -125,7 +125,7 @@ this.InputRedactor = (function(superClass) {
125
125
  InputRedactor.prototype.initialize = function() {
126
126
  var base, base1, plugins, redactor_options;
127
127
  plugins = ['fixedtoolbar'];
128
- if (Loft) {
128
+ if (typeof Loft !== "undefined" && Loft !== null) {
129
129
  plugins.push('loft');
130
130
  }
131
131
  redactor_options = {
@@ -102,8 +102,7 @@ Admin app layout ```app/views/layouts/admin.html.erb```:
102
102
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
103
103
  <title>Admin</title>
104
104
  <%= csrf_meta_tags %>
105
- <%= stylesheet_link_tag :admin, media: "all" %>
106
- <%= javascript_include_tag :admin %>
105
+ <%= stylesheet_link_tag :admin, media: "all" %>
107
106
  </head>
108
107
 
109
108
  <%= yield %>
@@ -116,6 +115,7 @@ Admin index view ```app/views/admin/index.html.erb```:
116
115
  <body class='loading'>
117
116
  <%= link_to 'Sign Out', destroy_admin_session_path, method: :delete, style: 'display:none;' %>
118
117
  </body>
118
+ <%= javascript_include_tag :admin %>
119
119
  ```
120
120
 
121
121
  New session view for devise ```app/views/admin/devise_overrides/sessions/new.html.erb```:
@@ -191,50 +191,28 @@ Last import in the code above is optional. But here is a default source for it a
191
191
 
192
192
  ```scss
193
193
  .sign-in {
194
- font-size: 14px;
195
- color: #555;
196
- margin: 3em 0 0 3em;
197
-
198
- h2 {
199
- text-transform: uppercase;
200
- font-size: 1em;
201
- font-size: 16px;
202
- color: $black;
203
- margin-bottom: 1.5em;
204
- }
194
+ margin: 2em; max-width: 18em;
205
195
 
206
- p {
207
- margin: -1.5em 0 2em;
208
- color: $positiveColor;
209
- }
196
+ h2 { text-transform: uppercase; color: $black; }
197
+ input { @include noFocus(); }
198
+ label { color: $black; }
199
+ .input { margin-bottom: .75em; }
210
200
 
211
- .form-actions, .form-inputs {
212
- max-width: 280px;
213
- }
201
+ .input input[type=checkbox] { margin-right: .5em; }
214
202
 
215
- .input {
216
- margin-bottom: 1.5em;
203
+ .input input.email, .input input.password {
204
+ float: right; margin: -2px 0 0; width: 12em;
205
+ border: 0; border-bottom: 1px solid $contrastColor;
217
206
  }
218
207
 
219
- input.string, input.password {
220
- float: right;
221
- margin-top: -.45em;
222
- padding: .25em .5em;
223
- width: 13.5em;
224
- }
225
-
226
- label.boolean input {
227
- margin-right: .25em;
228
- }
208
+ .input.boolean { margin-top: 1.25em; }
229
209
 
230
210
  .form-actions input {
231
- width: 100%;
232
- padding: 1em 2em;
233
- background-color: $positiveColor;
234
- border: 0;
235
- color: $white;
211
+ width: 100%; padding: 1em 2em; margin-top: .75em;
212
+ color: $white; background-color: $positiveColor; border: 0;
236
213
  }
237
214
  }
215
+
238
216
  ```
239
217
 
240
218
  **Third**: make sure admin assets are precompiled on production, include ```admin.js``` and ```admin.css``` in ```config/initializers/assets.rb```:
@@ -1,3 +1,3 @@
1
1
  module Chr
2
- VERSION = "0.2.5"
2
+ VERSION = "0.2.7"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chr",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
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.5
4
+ version: 0.2.7
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-05 00:00:00.000000000 Z
11
+ date: 2015-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bourbon