Last active
August 29, 2015 13:59
-
-
Save andrewk/10867419 to your computer and use it in GitHub Desktop.
Response to request for modelling nested DOM as flight components - https://gist.github.com/djreimer/10687904
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
define( | |
[ | |
'flight/lib/component' | |
], | |
function(defineComponent) { | |
return defineComponent(ConditionSet); | |
function ConditionSet() { | |
this.defaultAttrs({ | |
'childTemplate' : 'Override this', | |
'conditionList' : '.conditions', | |
'addCondition' : '.js-add-condition', | |
'removeSelf' : '.js-remove-self' | |
}); | |
this.after('initialize', function() { | |
this.on('click', { 'addCondition' : this.appendNewCondition}); | |
this.on('click', { 'removeSelf' : this.removeSelf}); | |
}); | |
this.appendNewConditionSet(e, data) { | |
e.preventDefault(); | |
// probably pre-populate the template using Mustache, underscore, etc | |
this.select('conditionList').append(this.childTemplate); | |
this.trigger('uiAddCondition', { foo : bar}); | |
}; | |
this.removeSelf(e, data) { | |
e.preventDefault(); | |
this.$node.remove(); | |
this.trigger('uiRemoveConditionSet', { foo : bar}); | |
}; | |
} | |
} | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
define( | |
[ | |
'flight/lib/component' | |
], | |
function(defineComponent) { | |
return defineComponent(ConditionSet); | |
function ConditionSet() { | |
this.defaultAttrs({ | |
'childTemplate' : 'Override this', | |
'conditionList' : '.conditions', | |
'addCondition' : '.js-add-condition', | |
'removeSelf' : '.js-remove-self' | |
}); | |
this.after('initialize', function() { | |
this.on('click', { 'addCondition' : this.appendNewCondition}); | |
this.on('click', { 'removeSelf' : this.removeSelf}); | |
}); | |
this.appendNewConditionSet(e, data) { | |
e.preventDefault(); | |
// probably pre-populate the template using Mustache, underscore, etc | |
this.select('conditionList').append(this.childTemplate); | |
this.trigger('uiAddCondition', { foo : bar}); | |
}; | |
this.removeSelf(e, data) { | |
e.preventDefault(); | |
this.$node.remove(); | |
this.trigger('uiRemoveConditionSet', { foo : bar}); | |
}; | |
} | |
} | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- I wrote this on the train after a long day with a heavy head cold. I haven't run it, | |
but regardless of likely errors I think it expresses the design well enough. | |
- Segment and ConditionSet look close to identical, but that's likely due to the simplified | |
nature of the outline you provided | |
- I don't like attaching components to classes unless they're `js-`, as it's coupling | |
your styling and behaviour layers. We excelusively use data attributes for JS-DOM coupling | |
and I've quickly grown fond of the approach. | |
- The components could easily listen for add and remove events from their children, | |
their grandchildren etc. | |
- I don't know what JS background you're coming from, but in something like Backbone the | |
intention would be to model the data structure and then hang Views off that data structure. | |
It can be hard to get out of that at first, but if you strive to only model the | |
interaction/interface layer, you can keep your Model out of your javascript. | |
- I wrote an article on flight last week that goes into more details if you're interested: | |
http://www.sitepoint.com/taking-flight-twitter-flight/ | |
cheers, | |
Andrew |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script type="text/html" id="tpl-segment"> | |
<div class="segment" data-segment> | |
<ul class="condition-sets"></ul> | |
<a href="#" class="js-add-conditionset">Add condition set</a> | |
<a href="#" class="js-remove-self">Remove this segment</a> | |
</div> | |
</script> | |
<script type="text/html" id="tpl-conditionset"> | |
<li class="condition-set"> | |
<ul class="conditions"></ul> | |
<a href="#" class="js-add-condition">Add condition</a> | |
<a href="#" class="js-remove-self">Remove this condition set</a> | |
</li> | |
</script> | |
<script type="text/html" id="tpl-condition"> | |
<li class="condition"> | |
<input type="text" name="{{ name }}" value="{{ value }}" /> | |
<a href="#" class="js-remove-self">Remove this condition set</a> | |
</li> | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
require( | |
[ | |
'segment', | |
'condition-set', | |
'condition', | |
], | |
function ( | |
Segment, | |
ConditionSet, | |
Condition | |
) { | |
$(function() { | |
Segment.attachTo('.segment', { childTemplate : $('#tpl-conditionset').html() }); | |
ConditionSet.attachTo('.condition-set', { childTemplate : $('#tpl-condition').html() }); | |
ConditionSet.attachTo('.condition'); | |
}); | |
} | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
define( | |
[ | |
'flight/lib/component' | |
], | |
function(defineComponent) { | |
return defineComponent(Segment); | |
function Segment() { | |
this.defaultAttrs({ | |
'childTemplate' : 'Override this', | |
'conditionSetList' : '.condition-sets', | |
'addConditionSet' : '.js-add-conditionset', | |
'removeSelf' : '.js-remove-self' | |
}); | |
this.after('initialize', function() { | |
this.on('click', { 'addConditionSet' : this.appendNewConditionSet}); | |
}); | |
this.appendNewConditionSet(e, data) { | |
e.preventDefault(); | |
// probably pre-populate the template using Mustache, underscore, etc | |
this.select('conditionSetList').append(this.childTemplate); | |
this.trigger('uiAddConditionSet', { foo : bar}); | |
} | |
this.removeSelf(e, data) { | |
e.preventDefault(); | |
this.$node.remove(); | |
this.trigger('uiRemoveSegment', { foo : bar}); | |
}; | |
} | |
} | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Awesome, really appreciate you taking the time to write this.
When you call
.attachTo
, does it automatically bind to all future DOM nodes with that selector?e.g. if there are no
.condition-set
nodes on the DOM when this is called, does it do anything?