marionette-modal 1.0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/Gemfile +4 -0
  4. data/Gruntfile.coffee +111 -0
  5. data/LICENSE +22 -0
  6. data/README.md +42 -0
  7. data/Rakefile +1 -0
  8. data/dist/backbone.marionette.modals-min.js +1 -0
  9. data/dist/backbone.marionette.modals.js +104 -0
  10. data/dist/backbone.modal-min.js +1 -0
  11. data/dist/backbone.modal.js +382 -0
  12. data/dist/marionette.modal-bundled-min.js +1 -0
  13. data/dist/marionette.modal-bundled.js +858 -0
  14. data/dist/marionette.modal-min.js +1 -0
  15. data/dist/marionette.modal.css +24 -0
  16. data/dist/marionette.modal.js +370 -0
  17. data/dist/marionette.modal.theme.css +324 -0
  18. data/examples/1_single_view.html +71 -0
  19. data/examples/2_tab_based.html +104 -0
  20. data/examples/3_stacked_modal_with_marionette.html +105 -0
  21. data/examples/4_wizard.html +132 -0
  22. data/examples/css/style.css +45 -0
  23. data/examples/img/tab-icons.png +0 -0
  24. data/examples/style.css +35 -0
  25. data/examples/vendor/backbone.js +1591 -0
  26. data/examples/vendor/backbone.marionette.modals.js +104 -0
  27. data/examples/vendor/backbone.modal.css +24 -0
  28. data/examples/vendor/backbone.modal.js +382 -0
  29. data/examples/vendor/backbone.modal.theme.css +324 -0
  30. data/examples/vendor/jquery-1.9.1.js +9597 -0
  31. data/examples/vendor/marionette.js +2466 -0
  32. data/examples/vendor/marionette.modal.css +24 -0
  33. data/examples/vendor/marionette.modal.js +370 -0
  34. data/examples/vendor/marionette.modal.theme.css +324 -0
  35. data/examples/vendor/underscore.js +1314 -0
  36. data/lib/marionette-modal/version.rb +3 -0
  37. data/lib/marionette-modal.rb +22 -0
  38. data/marionette-modal.gemspec +23 -0
  39. data/package.json +19 -0
  40. data/src/backbone.marionette.modals.coffee +67 -0
  41. data/src/backbone.modal.coffee +253 -0
  42. data/src/marionette.modal.coffee +248 -0
  43. data/src/marionette.modal.sass +26 -0
  44. data/src/marionette.modal.theme.sass +486 -0
  45. data/src/style.sass +48 -0
  46. data/test/spec/backbone.marionette.modals.spec.js +120 -0
  47. data/test/spec/backbone.modal.spec.js +224 -0
  48. data/test/spec.html +41 -0
  49. data/test/src/backbone.marionette.modals.spec.coffee +56 -0
  50. data/test/src/backbone.modal.spec.coffee +139 -0
  51. metadata +128 -0
@@ -0,0 +1,3 @@
1
+ module MarionetteModal
2
+ VERSION = "1.0.0.8"
3
+ end
@@ -0,0 +1,22 @@
1
+ require "marionette-modal/version"
2
+
3
+ module MarionetteModal
4
+ module Assets
5
+ module Javascripts
6
+ module Marionette
7
+ FILE = File.open( File.expand_path('../dist/marionette.modal.js', File.dirname(__FILE__) ), 'r').read
8
+ REGION_FILE = File.open( File.expand_path('../dist/backbone.marionette.modals.js', File.dirname(__FILE__) ), 'r').read
9
+ end
10
+ module Backbone
11
+ FILE = File.open( File.expand_path('../dist/backbone.modal.js', File.dirname(__FILE__) ), 'r').read
12
+ end
13
+ module Bundle
14
+ FILE = File.open( File.expand_path('../dist/marionette.modal-bundled.js', File.dirname(__FILE__) ), 'r').read
15
+ end
16
+ end
17
+ module Stylesheets
18
+ CSS = File.open( File.expand_path('../dist/marionette.modal.css', File.dirname(__FILE__) ), 'r').read
19
+ THEME_CSS = File.open( File.expand_path('../dist/marionette.modal.theme.css', File.dirname(__FILE__) ), 'r').read
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'marionette-modal/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "marionette-modal"
8
+ spec.version = MarionetteModal::VERSION
9
+ spec.authors = ["Jared Smith"]
10
+ spec.email = ["jcsmith1859@gmail.com"]
11
+ spec.description = "Fork of Backbone.Modal Backbone.js plugin"
12
+ spec.summary = "Fork of the Backbone.Modal Backbone.js plugin that is more tightly integrated with Marionette.js"
13
+ spec.homepage = "https://github.com/Outcome-Engenuity/marionette-modal"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
data/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "Marionette.Modal",
3
+ "version": "1.0.0",
4
+ "description": "A plugin for Backbone.js that simplifies creating modals for your application.",
5
+ "devDependencies": {
6
+ "grunt": "~0.4.1",
7
+ "grunt-contrib-coffee": "~0.6.4",
8
+ "grunt-contrib-clean": "~0.5.0",
9
+ "grunt-regarde": "0.1.x",
10
+ "grunt-contrib-livereload": "0.1.x",
11
+ "grunt-contrib-jasmine": "~0.4.1",
12
+ "grunt-contrib-connect": "~0.2.0",
13
+ "grunt-open": "~0.2.0",
14
+ "grunt-contrib-uglify": "~0.2.0",
15
+ "grunt-contrib-sass": "~0.3.0",
16
+ "grunt-concurrent": "~0.2.0"
17
+ },
18
+ "author": "jcsmith1859"
19
+ }
@@ -0,0 +1,67 @@
1
+ unless Backbone?
2
+ throw new Error("Backbone is not defined. Please include the latest version from http://documentcloud.github.com/backbone/backbone.js")
3
+
4
+ class Backbone.Marionette.Modals extends Backbone.Marionette.Region
5
+ modals: []
6
+ zIndex: 0
7
+
8
+ show: (modal, options = {}) ->
9
+ @ensureEl()
10
+
11
+ if @modals.length > 0
12
+ lastModal = _.last(@modals)
13
+ lastModal.modalEl.addClass("#{lastModal.prefix}-modal--stacked")
14
+ secondLastModal = @modals[@modals.length-1]
15
+ secondLastModal?.modalEl.removeClass("#{secondLastModal.prefix}-modal--stacked-reverse")
16
+
17
+ modal.render()
18
+ modal.regionEnabled = true
19
+
20
+ @$el.show()
21
+ @$el.append modal.el
22
+
23
+ modal.$el.css(background: 'none') if @modals.length > 0
24
+
25
+ Marionette.triggerMethod.call(modal, "show")
26
+ Marionette.triggerMethod.call(this, "show", modal)
27
+
28
+ @currentView = modal
29
+
30
+ m.undelegateModalEvents() for m in @modals
31
+
32
+ modal.on('modal:close', @close)
33
+
34
+ @modals.push(modal)
35
+ @zIndex++
36
+
37
+ close: =>
38
+ modal = @currentView
39
+ return if !modal or modal.isClosed
40
+
41
+ if modal.close
42
+ modal.close()
43
+ else if modal.remove
44
+ modal.remove()
45
+
46
+ modal.off('modal:close', @close)
47
+
48
+ @modals.splice(_.indexOf(@modals, modal), 1)
49
+
50
+ @zIndex--
51
+
52
+ @currentView = @modals[@zIndex-1]
53
+
54
+ lastModal = _.last(@modals)
55
+
56
+ if lastModal
57
+ lastModal.modalEl.addClass("#{lastModal.prefix}-modal--stacked-reverse")
58
+ _.delay =>
59
+ lastModal.modalEl.removeClass("#{lastModal.prefix}-modal--stacked")
60
+ , 300
61
+
62
+ lastModal.delegateModalEvents() if @zIndex isnt 0
63
+
64
+ Marionette.triggerMethod.call(this, "close")
65
+
66
+ closeAll: ->
67
+ @close() for modal in @modals
@@ -0,0 +1,253 @@
1
+ unless Backbone?
2
+ throw new Error("Backbone is not defined. Please include the latest version from http://documentcloud.github.com/backbone/backbone.js")
3
+
4
+ class Backbone.Modal extends Backbone.View
5
+ prefix: 'bbm'
6
+ constructor: ->
7
+ @args = Array::slice.apply(arguments)
8
+ Backbone.View::constructor.apply(this, @args)
9
+
10
+ @setUIElements()
11
+ @delegateModalEvents()
12
+
13
+ render: (options = {}) ->
14
+ # use openAt or overwrite this with your own functionality
15
+ data = @serializeData()
16
+
17
+ @$el.addClass("#{@prefix}-wrapper")
18
+ @modalEl = Backbone.$('<div />').addClass("#{@prefix}-modal")
19
+ @modalEl.html @template(data) if @template
20
+ @$el.html @modalEl
21
+
22
+ # global events for key and click outside the modal
23
+ Backbone.$('body').on 'keyup', @checkKey
24
+ Backbone.$('body').on 'click', @clickOutside
25
+
26
+ if @viewContainer
27
+ @viewContainerEl = @modalEl.find(@viewContainer)
28
+ @viewContainerEl.addClass("#{@prefix}-modal__views")
29
+ else
30
+ @viewContainerEl = @modalEl
31
+
32
+ @$el.show()
33
+ @openAt(0) if @views?.length > 0
34
+ @onRender?()
35
+
36
+ @modalEl.css(opacity: 0)
37
+ @$el.fadeIn
38
+ duration: 100
39
+ complete: =>
40
+ @modalEl.css(opacity: 1).addClass("#{@prefix}-modal--open")
41
+
42
+ return this
43
+
44
+ setUIElements: ->
45
+ # get modal options
46
+ @template = @getOption('template')
47
+ @views = @getOption('views')
48
+ @views?.length = _.size(@views)
49
+ @viewContainer = @getOption('viewContainer')
50
+
51
+ # hide modal
52
+ @$el.hide()
53
+
54
+ throw new Error('No template or views defined for Backbone.Modal') if _.isUndefined(@template) and _.isUndefined(@views)
55
+ throw new Error('No viewContainer defined for Backbone.Modal') if @template and @views and _.isUndefined(@viewContainer)
56
+
57
+ getOption: (option) ->
58
+ # get class instance property
59
+ return unless option
60
+ if @options and option in @options and @options[option]?
61
+ return @options[option]
62
+ else
63
+ return @[option]
64
+
65
+ serializeData: ->
66
+ # return the appropriate data for this view
67
+ data = {}
68
+
69
+ data = _.extend(data, @model.toJSON()) if @model
70
+ data = _.extend(data, {items: @collection.toJSON()}) if @collection
71
+
72
+ return data
73
+
74
+ delegateModalEvents: ->
75
+ @active = true
76
+
77
+ # get elements
78
+ cancelEl = @getOption('cancelEl')
79
+ submitEl = @getOption('submitEl')
80
+
81
+ # set event handlers for submit and cancel
82
+ @$el.on('click', submitEl, @triggerSubmit) if submitEl
83
+ @$el.on('click', cancelEl, @triggerCancel) if cancelEl
84
+
85
+ # set event handlers for views
86
+ for key of @views
87
+ unless key is 'length'
88
+ match = key.match(/^(\S+)\s*(.*)$/)
89
+ trigger = match[1]
90
+ selector = match[2]
91
+
92
+ @$el.on trigger, selector, @views[key], @triggerView
93
+
94
+ undelegateModalEvents: ->
95
+ @active = false
96
+
97
+ # get elements
98
+ cancelEl = @getOption('cancelEl')
99
+ submitEl = @getOption('submitEl')
100
+
101
+ # remove event handlers for submit and cancel
102
+ @$el.off('click', submitEl, @triggerSubmit) if submitEl
103
+ @$el.off('click', cancelEl, @triggerCancel) if cancelEl
104
+
105
+ # remove event handlers for views
106
+ for key of @views
107
+ unless key is 'length'
108
+ match = key.match(/^(\S+)\s*(.*)$/)
109
+ trigger = match[1]
110
+ selector = match[2]
111
+
112
+ @$el.off trigger, selector, @views[key], @triggerView
113
+
114
+ checkKey: (e) =>
115
+ if @active
116
+ switch e.keyCode
117
+ when 27 then @triggerCancel()
118
+ when 13 then @triggerSubmit()
119
+
120
+ clickOutside: (e) =>
121
+ @triggerCancel(null, true) if Backbone.$(e.target).hasClass("#{@prefix}-wrapper") and @active
122
+
123
+ buildView: (viewType) ->
124
+ # returns a Backbone.View instance, a function or an object
125
+ return unless viewType
126
+ if _.isFunction(viewType)
127
+ view = new viewType(@args[0])
128
+
129
+ if view instanceof Backbone.View
130
+ return {el: view.render().$el, view: view}
131
+ else
132
+ return {el: viewType(@args[0])}
133
+
134
+ return {view: viewType, el: viewType.$el}
135
+
136
+ triggerView: (e) =>
137
+ # trigger what view should be rendered
138
+ e?.preventDefault?()
139
+ options = e.data
140
+ instance = @buildView(options.view)
141
+
142
+ @previousView = @currentView if @currentView
143
+ @currentView = instance.view || instance.el
144
+
145
+ index = 0
146
+ for key of @views
147
+ @currentIndex = index if options.view is @views[key].view
148
+ index++
149
+
150
+ if options.onActive
151
+ if _.isFunction(options.onActive)
152
+ options.onActive(this)
153
+ else if _.isString(options.onActive)
154
+ this[options.onActive].call(this, options)
155
+
156
+ if @shouldAnimate
157
+ @animateToView(instance.el)
158
+ else
159
+ @shouldAnimate = true
160
+ @$(@viewContainerEl).html instance.el
161
+
162
+ animateToView: (view) ->
163
+ style = position: 'relative', top: -9999, left: -9999
164
+ tester = Backbone.$('<tester/>').css(style)
165
+ tester.html @$el.clone().css(style)
166
+ if Backbone.$('tester').length isnt 0 then Backbone.$('tester').replaceWith tester else Backbone.$('body').append tester
167
+
168
+ if @viewContainer
169
+ container = tester.find(@viewContainer)
170
+ else
171
+ container = tester.find(".#{@prefix}-modal")
172
+
173
+ container.removeAttr('style')
174
+
175
+ previousHeight = container.outerHeight()
176
+ container.html(view)
177
+ newHeight = container.outerHeight()
178
+
179
+ if previousHeight is newHeight
180
+ @$(@viewContainerEl).html view
181
+ @previousView?.close?()
182
+ else
183
+ @$(@viewContainerEl).css(opacity: 0)
184
+
185
+ @$(@viewContainerEl).animate {height: newHeight}, 100, =>
186
+ @$(@viewContainerEl).css(opacity: 1).removeAttr('style')
187
+ @$(@viewContainerEl).html view
188
+ @previousView?.close?()
189
+
190
+ triggerSubmit: (e) =>
191
+ return unless e
192
+ # triggers submit
193
+ e?.preventDefault()
194
+
195
+ if @beforeSubmit
196
+ return if @beforeSubmit() is false
197
+
198
+ @submit?()
199
+
200
+ if @regionEnabled
201
+ @trigger('modal:close')
202
+ else
203
+ @close()
204
+
205
+ triggerCancel: (e) =>
206
+ # triggers cancel
207
+ e?.preventDefault()
208
+
209
+ if @beforeCancel
210
+ return if @beforeCancel() is false
211
+
212
+ @cancel?()
213
+
214
+ if @regionEnabled
215
+ @trigger('modal:close')
216
+ else
217
+ @close()
218
+
219
+ close: ->
220
+ # closes view
221
+ Backbone.$('body').off 'keyup', @checkKey
222
+ Backbone.$('body').off 'click', @clickOutside
223
+
224
+ @onClose?()
225
+
226
+ @shouldAnimate = false
227
+ @modalEl.addClass("#{@prefix}-modal--close")
228
+ @$el.fadeOut(duration: 200)
229
+
230
+ _.delay =>
231
+ @currentView?.remove?()
232
+ @remove()
233
+ , 200
234
+
235
+ openAt: (index) ->
236
+ # loop through views and trigger the index
237
+ i = 0
238
+ for key of @views
239
+ unless key is 'length'
240
+ view = @views[key] if i is index
241
+ i++
242
+
243
+ if view
244
+ @currentIndex = index
245
+ @triggerView(data: view)
246
+
247
+ return this
248
+
249
+ next: ->
250
+ @openAt(@currentIndex+1) if @currentIndex+1 < @views.length
251
+
252
+ previous: ->
253
+ @openAt(@currentIndex-1) if @currentIndex-1 < @views.length-1
@@ -0,0 +1,248 @@
1
+ unless Marionette?
2
+ throw new Error("Marionette is not defined. Please include the latest version from https://github.com/marionettejs/backbone.marionette")
3
+
4
+ class Marionette.Modal extends Marionette.View
5
+ prefix: 'bbm'
6
+
7
+ constructor: ->
8
+ @args = Array::slice.apply(arguments)
9
+ Marionette.View::constructor.apply(this, @args)
10
+
11
+ @setUIElements()
12
+ @delegateModalEvents()
13
+
14
+ render: (options = {}) ->
15
+ # use openAt or overwrite this with your own functionality
16
+ data = @serializeData()
17
+
18
+ @$el.addClass("#{@prefix}-wrapper")
19
+ @modalEl = Marionette.$('<div />').addClass("#{@prefix}-modal")
20
+ @modalEl.html @template(data) if @template
21
+ @$el.html @modalEl
22
+
23
+ # global events for key and click outside the modal
24
+ Marionette.$('body').on 'keyup', @checkKey
25
+ Marionette.$('body').on 'click', @clickOutside
26
+
27
+ if @viewContainer
28
+ @viewContainerEl = @modalEl.find(@viewContainer)
29
+ @viewContainerEl.addClass("#{@prefix}-modal__views")
30
+ else
31
+ @viewContainerEl = @modalEl
32
+
33
+ @$el.show()
34
+ @openAt(0) if @views?.length > 0
35
+ @onRender?()
36
+
37
+ @modalEl.css(opacity: 0)
38
+ @$el.fadeIn
39
+ duration: 100
40
+ complete: =>
41
+ @modalEl.css(opacity: 1).addClass("#{@prefix}-modal--open")
42
+
43
+ return this
44
+
45
+ setUIElements: ->
46
+ # get modal options
47
+ @template = Marionette.getOption(this, 'template')
48
+ @views = Marionette.getOption(this, 'views')
49
+ @views?.length = _.size(@views)
50
+ @viewContainer = Marionette.getOption(this, 'viewContainer')
51
+
52
+ # hide modal
53
+ @$el.hide()
54
+
55
+ throw new Error('No template or views defined for Backbone.Modal') if _.isUndefined(@template) and _.isUndefined(@views)
56
+ throw new Error('No viewContainer defined for Backbone.Modal') if @template and @views and _.isUndefined(@viewContainer)
57
+
58
+ serializeData: ->
59
+ # return the appropriate data for this view
60
+ data = {}
61
+
62
+ data = _.extend(data, @model.toJSON()) if @model
63
+ data = _.extend(data, {items: @collection.toJSON()}) if @collection
64
+
65
+ return data
66
+
67
+ delegateModalEvents: ->
68
+ @active = true
69
+
70
+ # get elements
71
+ cancelEl = Marionette.getOption(this, 'cancelEl')
72
+ submitEl = Marionette.getOption(this, 'submitEl')
73
+
74
+ # set event handlers for submit and cancel
75
+ @$el.on('click', submitEl, @triggerSubmit) if submitEl
76
+ @$el.on('click', cancelEl, @triggerCancel) if cancelEl
77
+
78
+ # set event handlers for views
79
+ for key of @views
80
+ unless key is 'length'
81
+ match = key.match(/^(\S+)\s*(.*)$/)
82
+ trigger = match[1]
83
+ selector = match[2]
84
+
85
+ @$el.on trigger, selector, @views[key], @triggerView
86
+
87
+ undelegateModalEvents: ->
88
+ @active = false
89
+
90
+ # get elements
91
+ cancelEl = @getOption('cancelEl')
92
+ submitEl = @getOption('submitEl')
93
+
94
+ # remove event handlers for submit and cancel
95
+ @$el.off('click', submitEl, @triggerSubmit) if submitEl
96
+ @$el.off('click', cancelEl, @triggerCancel) if cancelEl
97
+
98
+ # remove event handlers for views
99
+ for key of @views
100
+ unless key is 'length'
101
+ match = key.match(/^(\S+)\s*(.*)$/)
102
+ trigger = match[1]
103
+ selector = match[2]
104
+
105
+ @$el.off trigger, selector, @views[key], @triggerView
106
+
107
+ checkKey: (e) =>
108
+ if @active
109
+ switch e.keyCode
110
+ when 27 then @triggerCancel()
111
+ when 13 then @triggerSubmit()
112
+
113
+ clickOutside: (e) =>
114
+ @triggerCancel(null, true) if Marionette.$(e.target).hasClass("#{@prefix}-wrapper") and @active
115
+
116
+ buildView: (viewType) ->
117
+ # returns a Backbone.View instance, a function or an object
118
+ return unless viewType
119
+ if _.isFunction(viewType)
120
+ view = new viewType(@args[0])
121
+
122
+ if view instanceof Backbone.View
123
+ return {el: view.render().$el, view: view}
124
+ else
125
+ return {el: viewType(@args[0])}
126
+
127
+ return {view: viewType, el: viewType.$el}
128
+
129
+ triggerView: (e) =>
130
+ # trigger what view should be rendered
131
+ e?.preventDefault?()
132
+ options = e.data
133
+ instance = @buildView(options.view)
134
+
135
+ @previousView = @currentView if @currentView
136
+ @currentView = instance.view || instance.el
137
+
138
+ index = 0
139
+ for key of @views
140
+ @currentIndex = index if options.view is @views[key].view
141
+ index++
142
+
143
+ if options.onActive
144
+ if _.isFunction(options.onActive)
145
+ options.onActive(this)
146
+ else if _.isString(options.onActive)
147
+ this[options.onActive].call(this, options)
148
+
149
+ if @shouldAnimate
150
+ @animateToView(instance.el)
151
+ else
152
+ @shouldAnimate = true
153
+ @$(@viewContainerEl).html instance.el
154
+
155
+ animateToView: (view) ->
156
+ style = position: 'relative', top: -9999, left: -9999
157
+ tester = Marionette.$('<tester/>').css(style)
158
+ tester.html @$el.clone().css(style)
159
+ if Marionette.$('tester').length isnt 0 then Marionette.$('tester').replaceWith tester else Marionette.$('body').append tester
160
+
161
+ if @viewContainer
162
+ container = tester.find(@viewContainer)
163
+ else
164
+ container = tester.find(".#{@prefix}-modal")
165
+
166
+ container.removeAttr('style')
167
+
168
+ previousHeight = container.outerHeight()
169
+ container.html(view)
170
+ newHeight = container.outerHeight()
171
+
172
+ if previousHeight is newHeight
173
+ @$(@viewContainerEl).html view
174
+ @previousView?.close?()
175
+ else
176
+ @$(@viewContainerEl).css(opacity: 0)
177
+
178
+ @$(@viewContainerEl).animate {height: newHeight}, 100, =>
179
+ @$(@viewContainerEl).css(opacity: 1).removeAttr('style')
180
+ @$(@viewContainerEl).html view
181
+ @previousView?.close?()
182
+
183
+ # jQuery style event handler
184
+ triggerSubmit: (e) =>
185
+ return unless e
186
+ # triggers submit
187
+ e?.preventDefault()
188
+
189
+ if @beforeSubmit
190
+ return if @beforeSubmit() is false
191
+
192
+ @submit?()
193
+
194
+ if @regionEnabled
195
+ @trigger('modal:close')
196
+ else
197
+ @close()
198
+
199
+ # jQuery style event handler
200
+ triggerCancel: (e) =>
201
+ # triggers cancel
202
+ e?.preventDefault()
203
+
204
+ if @beforeCancel
205
+ return if @beforeCancel() is false
206
+
207
+ @cancel?()
208
+
209
+ if @regionEnabled
210
+ @triggerMethod 'modal:close'
211
+ else
212
+ @close()
213
+
214
+ close: ->
215
+ # closes view
216
+ Marionette.$('body').off 'keyup', @checkKey
217
+ Marionette.$('body').off 'click', @clickOutside
218
+
219
+ @onClose?()
220
+
221
+ @shouldAnimate = false
222
+ @modalEl.addClass("#{@prefix}-modal--close")
223
+ @$el.fadeOut(duration: 200)
224
+
225
+ _.delay =>
226
+ @currentView?.remove?()
227
+ @remove()
228
+ , 200
229
+
230
+ openAt: (index) ->
231
+ # loop through views and trigger the index
232
+ i = 0
233
+ for key of @views
234
+ unless key is 'length'
235
+ view = @views[key] if i is index
236
+ i++
237
+
238
+ if view
239
+ @currentIndex = index
240
+ @triggerView(data: view)
241
+
242
+ return this
243
+
244
+ next: ->
245
+ @openAt(@currentIndex + 1) if @currentIndex + 1 < @views.length
246
+
247
+ previous: ->
248
+ @openAt(@currentIndex - 1) if @currentIndex - 1 < @views.length - 1
@@ -0,0 +1,26 @@
1
+ /* Modal positioning */
2
+ .bbm-wrapper
3
+ box-sizing: border-box
4
+ position: absolute
5
+ left: 0
6
+ top: 0
7
+ width: 100%
8
+ height: 100%
9
+ z-index: 100
10
+ padding: 50px 10px
11
+
12
+ *
13
+ box-sizing: border-box
14
+
15
+ overflow-x: auto
16
+ overflow-y: scroll
17
+
18
+ .bbm-modal
19
+ border-radius: 3px
20
+ margin: auto
21
+ width: auto
22
+ max-width: 550px
23
+
24
+ .bbm-views
25
+ width: 100%
26
+ box-sizing: border-box