Skip to content

Instantly share code, notes, and snippets.

@jamesreggio
Created December 12, 2013 21:10
Show Gist options
  • Save jamesreggio/7935493 to your computer and use it in GitHub Desktop.
Save jamesreggio/7935493 to your computer and use it in GitHub Desktop.
This Gist demonstrates how to use an invasive jQuery plugin (UI Sortable) with the latest version of Ractive.js (0.3.7). It was built as an analogue to https://gist.github.com/petehunt/7882164, which illustrates how to pair jQuery UI Sortable with React.
<!--
This Gist demonstrates how to use an invasive jQuery plugin (UI Sortable) with
the latest version of Ractive.js (0.3.7).
It was built as an analogue to https://gist.github.com/petehunt/7882164, which
illustrates how to pair jQuery UI Sortable with React. I would contend that
Ractive.js plays more nicely with this plugin.
The key takeaway from this exercise is that you must not allow a third-party
plugin (e.g., jQuery) to change the DOM in a manner that its structure no
longer aligns with Ractive's parallel DOM.
The parallel DOM (accessible as `fragment` on your Ractive instance) maintains
references to actual DOM nodes *and* is unable to re-bind to an updated DOM or
register transformations on the DOM that it did not initiate itself.
!!! VERY IMPORTANT !!!
Don't use this code in a production app. Ractive.js provides a better way to
implement sortable lists, and it doesn't require jQuery. Check it out here:
http://ractivejs.github.io/Ractive-decorators-sortable/
-->
<!DOCTYPE html>
<html>
<head>
<title>Ractive.js + jQuery UI Sortable</title>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="https://rawgithub.com/RactiveJS/Ractive/master/Ractive.js">
</script>
</head>
<body>
<div id="app"></div>
<script id="item-template" type="text/ractive">
<span>
{{value}}: {{count}}
</span>
</script>
<script id="sortable-template" type="text/ractive">
<ul>
{{#items:i}}
<li data-index="{{i}}">
<rv-item value="{{.}}"></rv-item>
</li>
{{/items}}
</ul>
</script>
<script id="app-template" type="text/ractive">
<div>
<h1>Ractive.js + jQuery UI Sortable</h1>
<rv-sortable items="{{items}}"></rv-sortable>
<p>Current order: {{JSON.stringify(items)}}</p>
<p><button on-click="add">Add an item</button></p>
<p><button on-click="remove">Remove an item</button></p>
<p><button on-click="noop">Refresh list</button></p>
</div>
</script>
<script>
var Item, Sortable, app;
Item = Ractive.extend({
template: '#item-template',
data: {
count: 0
},
handleTick: function(){
this.set({
count: this.data.count + 1
});
},
complete: function(){
this.interval = setInterval(this.handleTick.bind(this), 1000);
},
teardown: function(){
clearInterval(this.interval);
}
});
Sortable = Ractive.extend({
template: '#sortable-template',
components: {
item: Item
},
handleDrop: function(){
// Map the `data-index` values to `data.items` entries.
var items = jQuery(this.find('ul'))
.sortable('toArray', { attribute: 'data-index' })
.map(function(i){ return this.data.items[i] }.bind(this));
// Restore the list to its original ordering, which is necessary to
// ensure that Ractive's parallel DOM remains in sync.
jQuery(this.findAll('ul li')).sort(function(a, b){
return (a.dataset.index > b.dataset.index ? 1 : -1);
}).appendTo(this.find('ul'));
// Update the `items` array.
// There is a subtle bug in this implementation that causes problems
// with 'add/remove an item' after this update. For more info:
// https://github.com/RactiveJS/Ractive/issues/317
this.set({ items: items });
},
enableSortable: function(){
jQuery(this.find('ul')).sortable({
beforeStop: this.handleDrop.bind(this)
});
},
complete: function(){
this.enableSortable();
}
});
app = new Ractive({
el: '#app',
template: '#app-template',
data: {
items: ['test 0', 'test 1', 'test 2'],
counter: 3
},
components: {
sortable: Sortable
}
});
app.on({
add: function(){
this.data.items.push('test ' + this.data.counter++);
},
remove: function(){
this.data.items.pop();
},
noop: function(){
this.set({ items: this.data.items.slice() });
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment