Skip to content

Instantly share code, notes, and snippets.

@briancavalier
Forked from unscriptable/ZZZ_MyView.js
Created November 23, 2011 12:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save briancavalier/1388575 to your computer and use it in GitHub Desktop.
Save briancavalier/1388575 to your computer and use it in GitHub Desktop.
cujo-ish view/widget
// It'd be great to get rid of this file entirely!
//MyView.js (filename above is just to sort this to top)
define([
'wire!./myView/spec',
'poly!poly/array' // for instance, not used in this example
],
function (spec) {
return spec;
});
define({
plugins: [
{ module: 'cujo' }
],
myView: {
// Create an instance of myView?
// Not sure yet how we'd create multiple instances, Object.create?
'cujo.view': 'path/to/myView'
}
});
// myView/controller.js
define({
// At this point, this is pretty much a "javascript-less" view!
// _onClick: function (e) {
// this.rootNode.classList.toggle(this.states.selected);
// }
});
define({
template: { module: 'text!./myView/template' },
strings: { module: 'i18n!./myView/strings' },
// Since, in this example the result of onClick is a state change,
// maybe we could shorten it via cola, or another facet that lets us
// define a state machine in the spec?
states: {
unselected: {
// When we're in the unselected state, and rootNode:click fires,
// transition to selected
// Here, selected could be a robo state, that may, in this
// case, simply cause an OOCSS state change. But you could
// imagine it doing other things, too!
'rootNode:click': 'selected'
},
selected: {
// Contrived example ... clicked while in the selected state
// causes a transition back to unselected
'rootNode:click': 'unselected'
}
}
});
// myView/strings.js
define({
greeting: 'Hello, cujo-er!'
});
<!- myView/template.html -->
<div class="myview" data-cujo-bind="rootNode"><!-- should rootNode be implicit? -->
<p>${strings.greeting}</p>
<p data-cujo-bind="foo"></p>
</div>
// MyView.js when concatenated together using cram.js
// cram.js needs two new features to make this work:
// 1. an option to NOT normalize module ids
// 2. an option to more easily exclude modules from the build (wire plugins, for instance)
define('./myView/controller', {
_onClick: function (e) {
this.rootNode.classList.toggle(this.states.selected);
}
});
define('text!.myView/template.html', function () {
return '<div class="myview" data-cujo-bind="rootNode"><!-- should rootNode be implicit? -->\n\t<p>${strings.greeting}</p>\n\t<p data-cujo-bind="foo"></p>\n</div>';
});
define('i18n!./myView/strings', {
greeting: 'Hello, cujo-er!'
});
define('wire!./myView/spec', {
plugins: [
{ module: 'wire/dom' },
{ module: 'wire/html5Event' } // adds `on` facet plus html5's node.classList!
],
oocssStates: {
selected: 'selected'
},
controller: {
module: './myView/controller',
on: {
rootNode: 'click:_onClick'
},
properties: {
states: { $ref: 'oocssStates' }
}
},
template: { module: 'text!./myView/template' },
strings: { module: 'i18n!./myView/strings' }
});
define(/* yes, this should stay anonymous! */ [
'wire!./myView/spec',
'poly!poly/array' // for instance, not used in this example
],
function (spec) {
return spec;
});
@unscriptable
Copy link

I'm not sure we should try to get rid of the top MyView.js file (_MyView.js in this gist) for a few reasons:

  1. It's a great place to put implicit dependencies, such as polyfills/shims or to put csrf proxies, for instance. (I just used this place to inject a csrf proxy, actually, but in a main.js file which is roughly equivalent.)
  2. If we wish, we could distribute the view/widget as a single file (MyView.js (ZZZ_MyView.js in this gist)) and as individual files (MyView.js + MyVIew/*). The two versions would be interchangeable and the dev could decide whether to use the exploded or concatenated version.
  3. If somebody wants to do something crazy with specs or doesn't want to use wire specs (jerk!), then this is the logical place to do it.

@briancavalier
Copy link
Author

Yeah, good points. I think there could be confusion about MyView.js vs. controller.js ... i.e. "Where does my code go?!?". I think we'd need to make sure there's a clear place for everything. That's what I was shooting for: having controller be the place where your code goes, since MyView.js is really just a boot file for the widget.

@unscriptable
Copy link

Is there any way to use the file that loads/wires the spec to also hold the event handlers?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment