JSFiddle - React, Tailwind, and code Playground
by hoffmanc
HTML
<script src="http://documentcloud.github.com/underscore/underscore.js"></script>
<script src="https://github.com/downloads/wycats/handlebars.js/handlebars-1.0.0.beta.6.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone.js"></script>
<script src="https://raw.github.com/derickbailey/backbone.marionette/master/src/backbone.marionette.js"></script>
<h1>Survey Designer</h1>
<p>This page is a testing ground for building a new survey designer interface, using Backbone.js</p>
<div id='questions'></div>
<script type='text/template' id="question-template">
<span class='handle'>↕</span>
{{defaultText}}
<ul data-id='{{id}}'></ul>
</script>
CSS
ul {
list-style: none;
margin: 10px;
}
span.handle{
cursor: move;
margin-right: 10px;
}
h1 {
font-size: 18pt;
}
.ui-state-hover {
background-color: #990;
height: 1em;
}
JavaScript
SDApp = new Backbone.Marionette.Application();
// customizations
// http://derickbailey.github.com/backbone.marionette/#backbone-marionette-renderer/caching-pre-compiled-templates
Backbone.Marionette.TemplateCache.loadTemplate = function(template, callback) {
// pre-compile the template and store that in the cache.
var compiledTemplate = Handlebars.compile($(template).html());
callback.call(this, compiledTemplate);
};
Backbone.Marionette.Renderer.renderTemplate = function(template, data) {
// because `template` is the pre-compiled template object,
// we only need to execute the template with the data
return template(data);
};
// MODELS
var QuestionTreeNode = Backbone.Model.extend({
initialize: function() {
var questions = this.get("questions");
if (questions) {
n = this;
this.questions = new QuestionTreeNodeCollection(
_.map(questions, function(q) { return _.extend(q, {parent: n}); })
);
this.unset("questions");
}
}
});
// COLLECTIONS
var QuestionTreeNodeCollection = Backbone.Collection.extend({
model: QuestionTreeNode
});
// VIEWS
// The recursive tree view
var QuestionTreeView = Backbone.Marionette.CompositeView.extend({
template: "#question-template",
tagName: "li",
events: {
'question:move': 'moveQuestion'
},
moveQuestion: function(event, parentId, pos) {
this.$el.trigger('question:move:approved', [this.model, parentId, pos]);
},
initialize: function() {
// grab the child collection from the parent model
// so that we can render the collection as children
// of this parent node
this.collection = this.model.questions;
},
appendHtml: function(cv, iv) {
// ensure we nest the child list inside of
// the current list item
cv.$("ul:first").append(iv.el);
},
onRender: function() {
if (_.isUndefined(this.collection))...