JSFiddle - React, Tailwind, and code Playground
by hoffmanc
HTML
<script src="http://documentcloud.github.com/underscore/underscore.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone.js"></script>
<script src="http://cloud.github.com/downloads/wycats/handlebars.js/handlebars-1.0.0.beta.6.js"></script>
<h1>Survey Designer</h1>
<p>This is a prototype version of the Survey Designer.</p>
<div id='items'></div>
<script id="surveyItems-template" type="text/x-handlebars-template">
{{#each Items}}
<li data-id='{{ID}}'>
<span class='handle'>↕</span>
<span>{{Name}}</span>
{{#if Items}}
<ul data-id='{{ID}}'>
{{#each Items}}
<li data-id='{{ID}}'>
<div style='float: right;'>{{QADomain}}</div>
<span class='handle'>↕</span>
<span>{{Name}}</span>
</li>
{{/each}}
</ul>
{{/if}}
</li>
{{/each}}
</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
SurveyDesigner = {};
var SurveyTree = SurveyDesigner.SurveyTree = Backbone.Model.extend({
idAttribute: "SurveyID",
initialize: function () {
this.Items = this.get("Items");
},
// find each item by it's ID and move it!
move: function (itemID, newParentID, pos) {
// rebuild and return dictionary for each move
// (this seems to be better than trying to maintain a client-only attribute)
var itemDictionary = this.getItemDictionary();
var item = itemDictionary[itemID];
var oldParent = itemDictionary[item.ParentID];
var newParent = itemDictionary[newParentID];
// check to see if either the newParent is root (ID=0), or
// the item being moved matches the new parent's QADomain
if (newParent.ID !== 0 && newParent.QADomain !== item.QADomain) {
throw new Error("item does not match the QADomain of the container.");
}
// check to see if the old parent will be made empty when this
// item is moved out of it
if (oldParent.ID !== 0 && oldParent.Items.length === 1) {
// remove the oldParent from the root
var root = itemDictionary[0];
root.Items.splice(root.Items.indexOf(oldParent), 1);
}
// check if we are nesting matrix headers
if (newParent.ID !== 0 && item.Type.indexOf('Header') !== -1) {
throw new Error("cannot nest containers.");
}
// remove the item at this position (can't use handy Collection helpers,
// since this is just an Array)
oldParent.Items.splice(oldParent.Items.indexOf(item), 1);
// add new item (again, no Collection niceties)
newParent.Items.splice(pos, 0, item);
// set the ParentID of the item to the new parent's ID
item.ParentID = newParent.ID;
},
// create a key-value dictionary for keeping references to
// relocation candidates
getItemDictionary: function ()...