Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Call `afterAttach` method on views if it is defined instead of trigge…

…ring 'attach' events. Always call this method on any attachment, passing true or false to indicate whether the view has been attached to the full DOM.
  • Loading branch information...
commit 4116e507fd3c8f44bad6d4ff167702d552637b0a 1 parent 00e093a
Nathan Sobo nathansobo authored
Showing with 50 additions and 35 deletions.
  1. +39 −29 space-pen-spec.coffee
  2. +11 −6 space-pen.coffee
68 space-pen-spec.coffee
View
@@ -128,21 +128,18 @@ describe "View", ->
expect(-> new BadView).toThrow("View markup must have a single root element")
describe "when a view is attached to another element via jQuery", ->
- [content, view2, view3, attachHandler, subviewAttachHandler, view2AttachHandler, view3AttachHandler] = []
+ [content, view2, view3, view4] = []
beforeEach ->
view2 = new TestView
view3 = new TestView
+ view4 = new TestView
- attachHandler = jasmine.createSpy 'attachHandler'
- subviewAttachHandler = jasmine.createSpy 'subviewAttachHandler'
- view2AttachHandler = jasmine.createSpy 'view2AttachHandler'
- view3AttachHandler = jasmine.createSpy 'view3AttachHandler'
-
- view.on 'attach', attachHandler
- view.subview.on 'attach', subviewAttachHandler
- view2.on 'attach', view2AttachHandler
- view3.on 'attach', view3AttachHandler
+ view.afterAttach = jasmine.createSpy 'view.afterAttach'
+ view.subview.afterAttach = jasmine.createSpy('view.subview.afterAttach')
+ view2.afterAttach = jasmine.createSpy('view2.afterAttach')
+ view3.afterAttach = jasmine.createSpy('view3.afterAttach')
+ expect(view4.afterAttach).toBeUndefined()
describe "when attached to an element that is on the DOM", ->
beforeEach ->
@@ -151,29 +148,42 @@ describe "View", ->
afterEach ->
content.empty()
- it "triggers an 'attach' event on all appended views and their subviews", ->
- content.append view, [view2, view3]
- expect(attachHandler).toHaveBeenCalled()
- expect(subviewAttachHandler).toHaveBeenCalled()
- expect(view2AttachHandler).toHaveBeenCalled()
- expect(view3AttachHandler).toHaveBeenCalled()
-
- view.detach()
- content.empty()
- attachHandler.reset()
- subviewAttachHandler.reset()
-
- otherElt = $('<div>')
- content.append(otherElt)
- view.insertBefore(otherElt)
- expect(attachHandler).toHaveBeenCalled()
- expect(subviewAttachHandler).toHaveBeenCalled()
+ describe "when $.fn.append is called with a single argument", ->
+ it "calls afterAttach (if it is present) on the appended view and its subviews, passing true to indicate they are on the DOM", ->
+ content.append view
+ expect(view.afterAttach).toHaveBeenCalledWith(true)
+ expect(view.subview.afterAttach).toHaveBeenCalledWith(true)
+
+ describe "when $.fn.append is called with multiple arguments", ->
+ it "calls afterAttach (if it is present) on all appended views and their subviews, passing true to indicate they are on the DOM", ->
+ content.append view, view2, [view3, view4]
+ expect(view.afterAttach).toHaveBeenCalledWith(true)
+ expect(view.subview.afterAttach).toHaveBeenCalledWith(true)
+ expect(view2.afterAttach).toHaveBeenCalledWith(true)
+ expect(view3.afterAttach).toHaveBeenCalledWith(true)
+
+ describe "when $.fn.insertBefore is called on the view", ->
+ it "calls afterAttach on the view and its subviews", ->
+ otherElt = $('<div>')
+ content.append(otherElt)
+ view.insertBefore(otherElt)
+ expect(view.afterAttach).toHaveBeenCalledWith(true)
+ expect(view.subview.afterAttach).toHaveBeenCalledWith(true)
+
+ describe "when a view is attached as part of a larger dom fragment", ->
+ it "calls afterAttach on the view and its subviews", ->
+ otherElt = $('<div>')
+ otherElt.append(view)
+ content.append(otherElt)
+ expect(view.afterAttach).toHaveBeenCalledWith(true)
+ expect(view.subview.afterAttach).toHaveBeenCalledWith(true)
describe "when attached to an element that is not on the DOM", ->
- it "does not trigger an attach event", ->
+ it "calls afterAttach (if it is present) on the appended view and its subviews, passing false to indicate they aren't on the DOM", ->
fragment = $('<div>')
fragment.append view
- expect(attachHandler).not.toHaveBeenCalled()
+ expect(view.afterAttach).toHaveBeenCalledWith(false)
+ expect(view.subview.afterAttach).toHaveBeenCalledWith(false)
it "allows $.fn.append to be called with undefined without raising an exception", ->
view.append undefined
17 space-pen.coffee
View
@@ -63,7 +63,7 @@ class View extends jQuery
@wireOutlets(this)
@bindEventHandlers(this)
@find('*').andSelf().data('view', this)
- @attr('triggerAttachEvents', true)
+ @attr('callAttachHooks', true)
step(this) for step in postProcessingSteps
@initialize?(args...)
@@ -163,9 +163,14 @@ class Builder
jQuery.fn.view = -> this.data('view')
# Trigger attach event when views are added to the DOM
-triggerAttachEvent = (element) ->
- if element?.attr?('triggerAttachEvents') and element.parents('html').length
- element.find('[triggerAttachEvents]').add(element).trigger('attach')
+callAttachHook = (element) ->
+ return unless element
+ elements = element.find?('[callAttachHooks]').toArray() ? []
+ elements.push(element[0]) if element.attr?('callAttachHooks')
+ for element in elements
+ return unless view = $(element).view()
+ onDom = view.parents('html').length > 0
+ view.afterAttach?(onDom)
for methodName in ['append', 'prepend', 'after', 'before']
do (methodName) ->
@@ -173,7 +178,7 @@ for methodName in ['append', 'prepend', 'after', 'before']
jQuery.fn[methodName] = (args...) ->
flatArgs = [].concat args...
result = originalMethod.apply(this, flatArgs)
- triggerAttachEvent arg for arg in flatArgs
+ callAttachHook arg for arg in flatArgs
result
for methodName in ['prependTo', 'appendTo', 'insertAfter', 'insertBefore']
@@ -181,7 +186,7 @@ for methodName in ['prependTo', 'appendTo', 'insertAfter', 'insertBefore']
originalMethod = $.fn[methodName]
jQuery.fn[methodName] = (args...) ->
result = originalMethod.apply(this, args)
- triggerAttachEvent(this)
+ callAttachHook(this)
result
(exports ? this).View = View
Please sign in to comment.
Something went wrong with that request. Please try again.