neat-rails 0.2.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  module Neat
2
2
  module Rails
3
- VERSION = "0.2.0"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  end
@@ -15,13 +15,12 @@ KEYS = {
15
15
  # viewPath - by default this is set to resource
16
16
  #
17
17
  class window.Neat.CollectionEditor extends Backbone.View
18
- sortOrder: 'asc'
19
- sortAliases: {}
20
18
  templateOptions: {}
21
- pageSize: 30
22
19
  useKeyboardToChangeRows: true
23
20
  cancelOnEsc: true
24
21
  saveOnEnter: true
22
+ renderer: "Basic"
23
+ rendererOptions: {}
25
24
 
26
25
  initialize: ->
27
26
  @keyDownHandlers = {}
@@ -36,41 +35,15 @@ class window.Neat.CollectionEditor extends Backbone.View
36
35
  @debug "looking for template at #{"#{@viewPath}/index"}"
37
36
  @template = @template ? Neat.template["#{@viewPath}/index"]
38
37
 
39
- @paginator = new window.Lail.PaginatedList [],
40
- page_size: if window.Neat.forPrint then Infinity else @pageSize
41
- always_show: false
42
- @paginator.onPageChange _.bind(@renderPage, @)
43
-
44
- @collection.bind 'reset', @__reset, @
45
- @collection.bind 'add', @__add, @
46
- @collection.bind 'remove', @__remove, @
47
-
48
- # We need to rerender the page if a model's attributes
49
- # have changed just in case this would affect how the
50
- # models are sorted.
51
- #
52
- # !todo: perhaps we can be smarter here and only listen
53
- # for changes to the attribute the view is sorted on.
54
- #
55
- # We don't want to redraw the page every time a model
56
- # has changed. If an old transaction is deleted, a very
57
- # large number of more recent transactions' running
58
- # balances could be updated very rapidly. Redrawing the
59
- # page will slow things down dramatically.
60
- #
61
- # Instead, redraw the page 500ms after a model has changed.
62
- #
63
- # This allows us to wait for activity to die down
64
- # and to redraw the page when it's more likely the system
65
- # has settled into new state.
66
- #
67
- @delayedRerender = new Lail.DelayedAction(_.bind(@rerenderPage, @), delay: 500)
68
- @collection.bind 'change', =>
69
- @delayedRerender.trigger() if @sortedBy
70
-
71
- # If the view's headers are 'a' tags, this view will try
72
- # to sort the collection using the header tags.
73
- $(@el).delegate '.header a', 'click', _.bind(@sort, @)
38
+ # For backwards-compatibility
39
+ @rendererOptions.pageSize = @pageSize if @pageSize?
40
+
41
+ rendererKlass = @renderer
42
+ rendererKlass = Neat.Renderer[rendererKlass] if _.isString(rendererKlass)
43
+ @_renderer = new rendererKlass(@, @collection, @rendererOptions)
44
+
45
+ @_renderer.afterRender _.bind(@afterRender, @)
46
+
74
47
  $(@el).delegate '.editor', 'keydown', _.bind(@onKeyDown, @)
75
48
 
76
49
  if @cancelOnEsc
@@ -83,37 +56,19 @@ class window.Neat.CollectionEditor extends Backbone.View
83
56
  @keyDownHandlers['UP'] = -> @edit @prevView()
84
57
  @keyDownHandlers['DOWN'] = -> @edit @nextView()
85
58
 
86
- @views = []
87
59
  @viewInEdit = null
88
60
  @templateOptions = {}
89
61
 
90
- repaginate: ->
91
- @rerenderPage(1)
92
62
 
93
- rerenderPage: (page)->
94
- page = @paginator.getCurrentPage() unless _.isNumber(page)
95
- if @sortedBy
96
- sortField = @sortField(@sortedBy)
97
- items = @collection.sortBy (model)->
98
- val = model.get(sortField) || ''
99
- if _.isString(val) then val.toLowerCase() else val
100
- items.reverse() if @sortOrder == 'desc'
101
- else
102
- items = @collection.toArray()
103
- @paginator.init items, page
104
63
 
105
64
 
106
65
  render: ->
107
66
  $el = $(@el)
108
67
  $el.html @template(@context())
109
68
  $el.cssHover '.neat-row.neat-interactive'
69
+ @$ul = $(@el).find("##{@resource}")
110
70
 
111
- @afterRender()
112
-
113
- @updateSortStyle() if @sortedBy
114
-
115
- @paginator.renderPaginationIn($el.find('.pagination'))
116
- @repaginate()
71
+ @_renderer.renderTo @$ul
117
72
  @
118
73
 
119
74
  context: ->
@@ -122,32 +77,21 @@ class window.Neat.CollectionEditor extends Backbone.View
122
77
  afterRender: ->
123
78
  @
124
79
 
125
- renderPage: ->
126
- alt = false
127
- $ul = $(@el).find("##{@resource}").empty() # e.g. $('#calendars')
128
- @views = []
80
+ buildViewFor: (model) ->
129
81
  self = @
130
-
131
- $(@el).find('.extended-pagination').html(@paginator.renderExtendedPagination())
132
-
133
- for model in @paginator.getCurrentSet()
134
- view = @constructModelView # e.g. window.CalendarView
135
- resource: @resource
136
- viewPath: @viewPath
137
- model: model
138
- templateOptions: @templateOptions
139
- view.bind 'edit:begin', -> self.beforeEdit.call(self, @)
140
- view.bind 'edit:end', -> self.afterEdit.call(self, @)
141
-
142
- @views.push(view)
143
-
144
- $el = $(view.render().el)
145
- $el.toggleClass 'alt', !(alt = !alt)
146
- $ul.append $el
147
- @
82
+ view = @constructModelView
83
+ resource: @resource
84
+ viewPath: @viewPath
85
+ model: model
86
+ templateOptions: @templateOptions
87
+ view.bind 'edit:begin', -> self.beforeEdit.call(self, @)
88
+ view.bind 'edit:end', -> self.afterEdit.call(self, @)
89
+ view
148
90
 
149
91
  constructModelView: (options) ->
150
- new @modelView options
92
+ viewClass = @modelView
93
+ viewClass = viewClass(options.model) if _.isFunction(viewClass) and !(viewClass.prototype instanceof Neat.ModelEditor)
94
+ new viewClass(options)
151
95
 
152
96
 
153
97
  beforeEdit: (view)->
@@ -162,33 +106,6 @@ class window.Neat.CollectionEditor extends Backbone.View
162
106
 
163
107
 
164
108
 
165
- sort: (e)->
166
- e.preventDefault()
167
- e.stopImmediatePropagation()
168
- sortBy = $(e.target).closest('a').attr('class').substring(@singular.length + 1)
169
- @log "sort by #{sortBy} [#{@sortField(sortBy)}]"
170
- if @sortedBy == sortBy
171
- @sortOrder = if @sortOrder == 'asc' then 'desc' else 'asc'
172
- else
173
- @removeSortStyle @sortedBy
174
- @sortedBy = sortBy
175
- @repaginate()
176
- @updateSortStyle()
177
- false
178
-
179
- removeSortStyle: (field)->
180
-
181
- updateSortStyle: ()->
182
- @removeSortStyle @sortedBy
183
-
184
- getHeader: (field)->
185
- $(@el).find(".header > .#{@singular}-#{field}")
186
-
187
- sortField: (field)->
188
- @sortAliases[field] ? field
189
-
190
-
191
-
192
109
  onKeyDown: (e)->
193
110
  keyName = @identifyKey(e.keyCode)
194
111
  handler = @keyDownHandlers[keyName]
@@ -203,18 +120,21 @@ class window.Neat.CollectionEditor extends Backbone.View
203
120
  # i.e. return true if target is in a dropdown control like Chosen
204
121
  false
205
122
 
206
-
123
+ views: ->
124
+ @_renderer.views
207
125
 
208
126
  nextView: ->
209
- @views[@indexOfViewInEdit() + 1]
127
+ @views()[@indexOfViewInEdit() + 1]
210
128
 
211
129
  prevView: ->
212
- @views[@indexOfViewInEdit() - 1]
130
+ @views()[@indexOfViewInEdit() - 1]
213
131
 
214
132
  indexOfViewInEdit: ->
215
- _.indexOf @views, @viewInEdit
133
+ _.indexOf @views(), @viewInEdit
216
134
 
217
135
  edit: (view)->
136
+ if view instanceof Backbone.Model
137
+ view = @_renderer.findViewForModel(view)
218
138
  if view
219
139
  @viewInEdit?.save()
220
140
  view.edit()
@@ -224,18 +144,6 @@ class window.Neat.CollectionEditor extends Backbone.View
224
144
  @viewInEdit?.cancelEdit()
225
145
 
226
146
 
227
-
228
- __reset: ->
229
- @render()
230
-
231
- __add: ->
232
- @rerenderPage()
233
-
234
- __remove: ->
235
- @rerenderPage()
236
-
237
-
238
-
239
147
  debug: (o...)->
240
148
  @log(o...) if Neat.debug
241
149
 
@@ -1,5 +1,5 @@
1
1
  $.fn.extend
2
- cssHover: (selector)->
2
+ cssHover: (selector) ->
3
3
  if arguments.length == 0
4
4
  @hover(
5
5
  -> $(@).addClass('hovered'),
@@ -11,5 +11,13 @@ $.fn.extend
11
11
  else
12
12
  $(@).removeClass('hovered')
13
13
 
14
- isIn: (selector)->
14
+ isIn: (selector) ->
15
15
  @is(selector) or (@parents(selector).length > 0)
16
+
17
+ insertBeforeChildOrAppendTo: (parent, selector) ->
18
+ $parent = $ parent
19
+ $insertionPoint = $parent.children(selector)
20
+ if $insertionPoint.length > 0
21
+ $insertionPoint.before @
22
+ else
23
+ $parent.append @
@@ -0,0 +1,33 @@
1
+ class @Neat.ScrollHandler
2
+ _.extend @prototype, Backbone.Events
3
+
4
+ constructor: (options={})->
5
+ @$viewPort = $(options.viewPort ? window)
6
+ @$document = $(document)
7
+ @$viewPort.scroll _.bind(@_windowWasScrolled, @)
8
+
9
+ _viewportHeight: ->
10
+ @$viewPort.height()
11
+
12
+ _documentHeight: ->
13
+ if $.isWindow @$viewPort[0]
14
+ @$document.height()
15
+ else
16
+ @$viewPort[0].scrollHeight
17
+
18
+ _windowWasScrolled: ->
19
+ viewportHeight = @_viewportHeight()
20
+ documentHeight = @_documentHeight()
21
+
22
+ scrollTop = @$viewPort.scrollTop()
23
+ scrollMax = documentHeight - viewportHeight
24
+ progress = scrollTop / scrollMax
25
+ distanceFromBottom = scrollTop - scrollMax
26
+
27
+ return if scrollMax <= 0
28
+
29
+ @trigger "scroll",
30
+ scrollTop: scrollTop
31
+ scrollMax: scrollMax
32
+ progress: progress
33
+ distanceFromBottom: distanceFromBottom
@@ -1,6 +1,7 @@
1
1
  class window.Neat.ModelEditor extends Backbone.View
2
2
  tagName: 'li'
3
3
  className: 'neat-row neat-interactive neat-editable'
4
+ waitOnSave: true
4
5
 
5
6
  initialize: (options)->
6
7
  options = options ? {}
@@ -82,7 +83,7 @@ class window.Neat.ModelEditor extends Backbone.View
82
83
  previousAttributes = @model.toJSON()
83
84
 
84
85
  @model.save attributes,
85
- wait: true
86
+ wait: @waitOnSave
86
87
  success: =>
87
88
  for attribute, newValue of attributes
88
89
  @debug " . #{attribute} changed from ", previousAttributes[attribute], " to ", @model.get(attribute)
@@ -94,26 +95,42 @@ class window.Neat.ModelEditor extends Backbone.View
94
95
  okToSave: (attributes)->
95
96
  true
96
97
 
97
- attributesFromForm: ($el)->
98
+ attributesFromForm: ($el) ->
98
99
  attrs = {}
99
100
  $el.find('input, select, textarea').each ->
100
- elem = $(this)
101
+ elem = $(@)
101
102
  name = elem.attr('name')
102
- if name
103
- elemType = elem.attr('type')
104
- value = elem.val()
105
-
106
- if name.substr(-2) == '[]'
107
- name = name.substring(0, name.length - 2)
108
- attrs[name] = attrs[name] || []
109
- attrs[name].push elem.val()
110
-
111
- else if elemType == 'checkbox' || elemType == 'radio'
112
- attrs[name] = '' if typeof(attrs[name]) == 'undefined'
113
- attrs[name] = value if elem.prop('checked')
114
-
115
- else
116
- attrs[name] = value
103
+ elemType = elem.attr('type')
104
+ value = elem.val()
105
+ return true unless name
106
+
107
+ # Parse out nested objects as represented in names
108
+ # person[address][zip]=63303 should be serialized to:
109
+ # person:
110
+ # address:
111
+ # zip: 63303
112
+ parts = _.without(name.split(/\[([^\]]+)\]/), '')
113
+ name = parts.pop()
114
+ isArray = false
115
+ while name is '[]'
116
+ isArray = true
117
+ name = parts.pop()
118
+ context = attrs
119
+ for part in parts
120
+ context = context[part] or (context[part] = {})
121
+
122
+ if (elemType == 'checkbox' || elemType == 'radio') && !elem.prop('checked')
123
+ return true
124
+
125
+ if isArray
126
+ # select with multiple=true will return
127
+ # an array of selected values, so we don't
128
+ # need to nest that array in another array
129
+ value = [value] unless _.isArray(value)
130
+ value = (context[name] || []).concat(value)
131
+
132
+ context[name] = value
133
+ true # Don't break out of the loop
117
134
  attrs
118
135
 
119
136
  destroy: (e)->
@@ -123,8 +140,8 @@ class window.Neat.ModelEditor extends Backbone.View
123
140
 
124
141
  @model.destroy
125
142
  wait: true
126
- success: => @onDestroySuccess
127
- error: _.bind(@onSaveError, @)
143
+ success: _.bind(@onDestroySuccess, @)
144
+ error: _.bind(@onDestroyError, @)
128
145
  @endEdit()
129
146
 
130
147
  confirmDestroy: (resource, callback)->
@@ -0,0 +1,102 @@
1
+ class window.Neat.Renderer.Basic
2
+
3
+ constructor: (@view, @collection, @options) ->
4
+ @collection.bind 'reset', @_collectionHasBeenReset, @
5
+ @collection.bind 'sort', @_collectionHasBeenSorted, @
6
+ @collection.bind 'add', @_modelHasBeenAddedToCollection, @
7
+ @collection.bind 'remove', @_modelHasBeenRemovedFromCollection, @
8
+ @collection.bind 'change', @_modelHasBeenChanged, @
9
+ @views = []
10
+ @observer = new Observer()
11
+
12
+ renderTo: (@$ul) ->
13
+ @views = []
14
+ @_render()
15
+
16
+ findViewForModel: (model)->
17
+ @views[@_indexOfViewForModel(model)]
18
+
19
+ afterRender: (callback) ->
20
+ @observer.observe "after_render", callback
21
+
22
+ _render: ->
23
+ # Doesn't need to render anything else like pagination controls on the view
24
+ # Just needs the @$ul that it should render views to
25
+ @_renderVisibleModels()
26
+
27
+ _renderVisibleModels: ->
28
+ visibleModels = @_visibleModels()
29
+
30
+ # Remove views that no longer correspond to visible models.
31
+ viewIndex = 0
32
+ while viewIndex < @views.length
33
+ if _.contains(visibleModels, @views[viewIndex].model)
34
+ viewIndex += 1
35
+ else
36
+ @_removeView(viewIndex)
37
+
38
+ # Add views for newly-visible models; and coerce views
39
+ # (and their corresponding DOM elements) to show up in
40
+ # the same order as the visible models.
41
+ for model, index in visibleModels
42
+ viewIndex = @_indexOfViewForModel(model)
43
+ if viewIndex >= 0
44
+ @_moveView(viewIndex, index) unless viewIndex is index
45
+ else
46
+ @_insertView @view.buildViewFor(model), index
47
+
48
+ @observer.fire "after_render"
49
+ @
50
+
51
+ _insertView: (view, newIndex) ->
52
+ view.render()
53
+ $(view.el).insertBeforeChildOrAppendTo @$ul, ".neat-row:eq(#{newIndex})"
54
+ @views.splice(newIndex, 0, view)
55
+ @_viewAddedAt(view, newIndex)
56
+
57
+ _moveView: (oldIndex, newIndex) ->
58
+ $el = $ @views[oldIndex].el
59
+ $el.detach().insertBeforeChildOrAppendTo @$ul, ".neat-row:eq(#{newIndex})"
60
+
61
+ view = @views.splice(oldIndex, 1)[0]
62
+ @views.splice(newIndex, 0, view)
63
+ @_viewRemovedAt(view, oldIndex)
64
+ @_viewAddedAt(view, newIndex)
65
+
66
+ _removeView: (oldIndex) ->
67
+ @views[oldIndex].remove()
68
+ view = @views.splice(oldIndex, 1)[0]
69
+ @_viewRemovedAt(view, oldIndex)
70
+
71
+
72
+
73
+ _viewAddedAt: (view, index) ->
74
+ # do nothing
75
+
76
+ _viewRemovedAt: (view, index) ->
77
+ # do nothing
78
+
79
+
80
+
81
+ _visibleModels: ->
82
+ @collection.toArray()
83
+
84
+ _indexOfViewForModel: (model)->
85
+ _.findIndex @views, (view)-> view.model.cid is model.cid
86
+
87
+
88
+
89
+ _collectionHasBeenReset: ->
90
+ @_render()
91
+
92
+ _collectionHasBeenSorted: ->
93
+ @_render()
94
+
95
+ _modelHasBeenAddedToCollection: ->
96
+ @_render()
97
+
98
+ _modelHasBeenRemovedFromCollection: ->
99
+ @_render()
100
+
101
+ _modelHasBeenChanged: (model) ->
102
+ # do nothing
@@ -0,0 +1,37 @@
1
+ class window.Neat.Renderer.InfiniteReveal extends window.Neat.Renderer.Basic
2
+
3
+ constructor: (@view, @collection, @options) ->
4
+ super
5
+ @scrollHandler = new Neat.ScrollHandler()
6
+ @scrollHandler.on "scroll", _.bind(@_windowHasBeenScrolled, @)
7
+
8
+ @sensitivity = @options.sensitivity ? 5
9
+ @pageSize = @options.pageSize ? 50
10
+
11
+
12
+
13
+ _render: ->
14
+ @_setMaxItems @pageSize
15
+ super
16
+
17
+ _visibleModels: ->
18
+ @collection.models[0...@maxItems]
19
+
20
+ _loadMore: ->
21
+ Neat.logger.log "[Neat.Renderer.InfiniteReveal] loading..."
22
+ @_setMaxItems @maxItems + @pageSize
23
+ @_renderVisibleModels()
24
+
25
+ _thereIsMore: ->
26
+ @collection.length > @maxItems
27
+
28
+
29
+
30
+ _setMaxItems: (value) ->
31
+ @maxItems = Math.min value, @collection.length
32
+
33
+ _windowHasBeenScrolled: (e) ->
34
+ return unless @_thereIsMore()
35
+ return unless Math.abs(e.distanceFromBottom) <= @sensitivity
36
+ return unless @view.$el.is(':visible')
37
+ @_loadMore()
@@ -0,0 +1,41 @@
1
+ class window.Neat.Renderer.Paginated extends window.Neat.Renderer.Basic
2
+
3
+ constructor: (@view, @collection, @options) ->
4
+ super
5
+ @paginator = new window.Lail.PaginatedList [],
6
+ page_size: if window.Neat.forPrint then Infinity else @options.pageSize
7
+ always_show: false
8
+ @paginator.onPageChange _.bind(@_renderPage, @)
9
+
10
+
11
+
12
+ _render: ->
13
+ @paginator.renderPaginationIn(@view.$el.find('.pagination'))
14
+ @_repaginate()
15
+
16
+ _repaginate: ->
17
+ @_rerenderPage(1)
18
+
19
+ _rerenderPage: (page)->
20
+ page = @paginator.getCurrentPage() unless _.isNumber(page)
21
+ items = @collection.toArray()
22
+ @paginator.init items, page
23
+
24
+ _renderPage: ->
25
+ @view.$el.find('.extended-pagination').html(@paginator.renderExtendedPagination())
26
+ @_renderVisibleModels()
27
+
28
+ _visibleModels: ->
29
+ @paginator.getCurrentSet()
30
+
31
+ _collectionHasBeenSorted: ->
32
+ @_repaginate()
33
+
34
+ _modelHasBeenAddedToCollection: ->
35
+ @_rerenderPage()
36
+
37
+ _modelHasBeenRemovedFromCollection: ->
38
+ @_rerenderPage()
39
+
40
+ _modelHasBeenChanged: ->
41
+ @_rerenderPage()
@@ -8,12 +8,16 @@
8
8
  //= require ./neat/lib/inflect
9
9
  //= require ./neat/lib/observer
10
10
  //= require ./neat/lib/paginated_list
11
- //= require ./neat/lib/delayed_action
12
11
  //= require ./neat/lib/jquery_extensions
12
+ //= require ./neat/lib/scroll_handler
13
+ //= require ./neat/renderer/basic
14
+ //= require ./neat/renderer/paginated
15
+ //= require ./neat/renderer/infinite_reveal
13
16
  //= require ./neat/collection_editor
14
17
  //= require ./neat/model_editor
15
18
 
16
19
  window.Neat = window.Neat || {}
20
+ window.Neat.Renderer = window.Neat.Renderer || {}
17
21
  window.Neat.debug = true;
18
22
  window.Neat.logger = {
19
23
  log: function() {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neat-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-02-08 00:00:00.000000000 Z
13
+ date: 2016-04-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
@@ -47,12 +47,15 @@ files:
47
47
  - neat-rails.gemspec
48
48
  - vendor/assets/javascripts/neat.js
49
49
  - vendor/assets/javascripts/neat/collection_editor.coffee
50
- - vendor/assets/javascripts/neat/lib/delayed_action.js
51
50
  - vendor/assets/javascripts/neat/lib/inflect.js
52
51
  - vendor/assets/javascripts/neat/lib/jquery_extensions.coffee
53
52
  - vendor/assets/javascripts/neat/lib/observer.js
54
53
  - vendor/assets/javascripts/neat/lib/paginated_list.js
54
+ - vendor/assets/javascripts/neat/lib/scroll_handler.coffee
55
55
  - vendor/assets/javascripts/neat/model_editor.coffee
56
+ - vendor/assets/javascripts/neat/renderer/basic.coffee
57
+ - vendor/assets/javascripts/neat/renderer/infinite_reveal.coffee
58
+ - vendor/assets/javascripts/neat/renderer/paginated.coffee
56
59
  homepage: ''
57
60
  licenses: []
58
61
  post_install_message:
@@ -67,7 +70,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
67
70
  version: '0'
68
71
  segments:
69
72
  - 0
70
- hash: 2435929593431474536
73
+ hash: -2190152860109017268
71
74
  required_rubygems_version: !ruby/object:Gem::Requirement
72
75
  none: false
73
76
  requirements:
@@ -76,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
79
  version: '0'
77
80
  segments:
78
81
  - 0
79
- hash: 2435929593431474536
82
+ hash: -2190152860109017268
80
83
  requirements: []
81
84
  rubyforge_project:
82
85
  rubygems_version: 1.8.23.2
@@ -1,49 +0,0 @@
1
- var Lail; if(!Lail) Lail={};
2
- Lail.DelayedAction = function(callback, options) {
3
- // !todo: paste John Resig's code
4
-
5
- options = options || {};
6
- var self = this,
7
- delay = options.delay || 1000,
8
- steps = options.steps || 10,
9
- intervalPeriod = delay / steps,
10
- counter = 0,
11
- _params,
12
- _interval;
13
-
14
- this.trigger = function(params) {
15
- _params = params;
16
- restartCountdown();
17
- }
18
-
19
- function restartCountdown() {
20
- counter = steps;
21
- if(!_interval) {
22
- _interval = setInterval(countdown, intervalPeriod);
23
- }
24
- }
25
-
26
- function countdown() {
27
- if(counter > 0) {
28
- counter = counter - 1;
29
- } else {
30
- stopCountdown()
31
- fireCallback();
32
- }
33
- }
34
-
35
- function stopCountdown() {
36
- if(_interval) {
37
- clearInterval(_interval);
38
- _interval = null;
39
- }
40
- }
41
-
42
- function fireCallback() {
43
- try {
44
- callback(_params);
45
- } catch(e) {
46
- App.debug(e);
47
- }
48
- }
49
- }