Created
December 12, 2013 21:10
-
-
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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
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