Fork this to experiment with Ember.js
by Kerrick
HTML
<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.1.2/handlebars.min.js"></script>
<script src="http://builds.emberjs.com/tags/v1.2.2/ember.js"></script>
<script src="http://builds.emberjs.com/beta/ember-data.js"></script>
<script type="text/x-handlebars" data-template-name="application">
<h1>Ember Data + jQueryUI Sortable</h1>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
{{#each model}}
{{render 'formField' this}}
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="formField">
<div class="form-field" {{bind-attr data-id=id}}>
<span class="delete" {{action 'delete'}}>X</span>
{{name}} ({{displayOrder}})
<span class="handle">#</span>
</div>
</script>
CSS
body { padding: 2em; }
.form-field {
border:1px solid #ccc;
margin:2px;
padding:2px;
background:white;
overflow: hidden;
}
.ui-sortable-helper {
-webkit-transform: scale(1.03);
-moz-transform: scale(1.03);
transform: scale(1.03);
box-shadow: 1px 3px 5px rgba(0, 0, 0, 0.4);
}
.handle {
cursor: move;
font-size: 2em;
float: right;
margin-right: 0.5em;
}
.delete {
cursor: pointer;
color: red;
}
}
JavaScript
App = Ember.Application.create({});
App.ApplicationAdapter = DS.FixtureAdapter.extend();
App.IndexRoute = Ember.Route.extend({
model: function(){
return this.store.find('formField');
}
});
App.IndexController = Ember.ArrayController.extend({
sortProperties: ['displayOrder'], // Force sort by displayOrder, not ID
updatePositions : function(positionData){
/* Position Data
{
//'The Model ID': 'Its Display Order, zero-indexed',
48: 0,
52: 1,
39: 2
}
*/
this.propertyWillChange('content'); // Manually notify Ember
this.get('content').forEach(function(formField) {
var key = formField.get('id');
formField.set('displayOrder', positionData[key] + 1);
});
this.propertyDidChange('content'); // Manually notify Ember
}
});
App.IndexView = Ember.View.extend({
handleSort: function(event,ui){
var positionData = {};
this.$(".form-field").each(function(index, element){
// Get model ID from bind-attr in template
var key = $(element).data('id');
positionData[key] = index;
});
this.get('controller').updatePositions(positionData);
// Delay recreating the sortable
Ember.run.next(function(){ this.makeSortable(); }.bind(this));
},
makeSortable: Ember.on('didInsertElement', function(){
try {
this.$().sortable("destroy");
} catch(err){
window.console.warn('No sortable to destroy', err);
}
finally {
this.$().sortable({
handle: '.handle',
axis: 'y',
update: this.handleSort.bind(this)
});
}
})
});
App.FormFieldController = Ember.ObjectController.extend({
actions: {
'delete': function() {
window.console.log('deleting record', this.get('name'));
...