neat-rails 0.2.0 → 0.5.0

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