<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<base href="http://polygit.org/polymer+v1.9.2/components/">
<link href="polymer/polymer.html" rel="import">
</head>
<body>
<!-- Latest Sortable -->
<script src="//rubaxa.github.io/Sortable/Sortable.js"></script>
<dom-module id="sortable-js">
<template>
<content></content>
</template>
</dom-module>
<script>
'use strict';
Polymer({
is: "sortable-js",
properties: {
group : { type: Object, value: () => {return {name: Math.random()};}, observer: "groupChanged" },
sort : { type: Boolean, value: true, observer: "sortChanged" },
disabled : { type: Boolean, value: false, observer: "disabledChanged" },
store : { type: Object, value: null, observer: "storeChanged" },
handle : { type: String, value: null, observer: "handleChanged" },
scrollSensitivity : { type: Number, value: 30, observer: "scrollSensitivityChanged" },
scrollSpeed : { type: Number, value: 10, observer: "scrollSpeedChanged" },
ghostClass : { type: String, value: "sortable-ghost", observer: "ghostClassChanged" },
chosenClass : { type: String, value: "sortable-chosen", observer: "chosenClassChanged" },
ignore : { type: String, value: "a, img", observer: "ignoreChanged" },
filter : { type: Object, value: null, observer: "filterChanged" },
animation : { type: Number, value: 0, observer: "animationChanged" },
dropBubble : { type: Boolean, value: false, observer: "dropBubbleChanged" },
dragoverBubble : { type: Boolean, value: false, observer: "dragoverBubbleChanged" },
dataIdAttr : { type: String, value: "data-id", observer: "dataIdAttrChanged" },
delay : { type: Number, value: 0, observer: "delayChanged" },
forceFallback : { type: Boolean, value: false, observer: "forceFallbackChanged" },
fallbackClass : { type: String, value: "sortable-fallback", observer: "fallbackClassChanged" },
fallbackOnBody : { type: Boolean, value: false, observer: "fallbackOnBodyChanged" },
draggable : {},
scroll : {}
},
created: function() {
// override default DOM property behavior
Object.defineProperties(this, {
draggable: { get: function() { return this._draggable || this.getAttribute("draggable") || ">*";}, set: function(value) { this._draggable = value; this.draggableChanged(value);} },
scroll: { get: function() { return this._scroll || JSON.parse(this.getAttribute("scroll") || "true"); }, set: function(value) { this._scroll = value; this.scrollChanged(value);} }
});
},
attached: function() {
// Given
// <sortable-js>
// <template is="dom-repeat" items={{data}}>
// <div>
// <template is="dom-if" if="true">
// <span>hello</span></template></div>
// After render, it becomes
// <sortable-js>
// <div>
// <span>hello</span>
// <template is="dom-if">
// <tempalte is="dom-repeat">
this.initialize();
},
detached: function() {
this.destroy();
},
initialize: function() {
var templates = this.querySelectorAll("template[is='dom-repeat']");
var template = templates[templates.length-1];
var options = {};
Object.keys(this.properties).forEach(function(key) {
options[key] = this[key];
}.bind(this));
var _this = this;
var eventCallbacks = {
onUpdate: function (e) {
if (template) {
template.splice("items", e.newIndex, 0, template.splice("items", e.oldIndex, 1)[0]);
/*
if (manuallyHandleUpdateEvents) {
template.items.splice(e.newIndex, 0, template.items.splice(e.oldIndex, 1)[0]);
} else {
template.splice("items", e.newIndex, 0, template.splice("items", e.oldIndex, 1)[0]);
}
*/
}
_this.fire("update", e);
},
onAdd: function(e) {
if (template) {
var froms = e.from.querySelectorAll("template[is='dom-repeat']");
var from = froms[froms.length-1];
var model = from.modelForElement(e.item);
template.splice("items", e.newIndex, 0, model.item);
e.model = model;
}
_this.fire("add", e);
},
onRemove: function(e) {
// Donot remove if group.pull is clone
if (e.target.group.pull === 'clone') {
return false;
}
if (template) {
var item = template.splice("items", e.oldIndex, 1)[0];
e.model = {item: item};
}
_this.fire("remove", e);
},
onChoose: function(e) {
_this.fire("choose", e);
},
onStart: function(e) {
_this.fire("start", e);
},
onEnd: function(e) {
_this.fire("end", e);
},
onSort: function(e) {
_this.fire("sort", e);
},
onFilter: function(e) {
_this.fire("filter", e);
},
onMove: function(e) {
_this.fire("move", e);
},
onClone: function(e) {
_this.fire("clone", e);
}
};
Object.keys(eventCallbacks).forEach(function(name){
options[name] = eventCallbacks[name];
});
this.sortable = Sortable.create(this, options);
},
destroy: function() {
if(this.sortable) {
this.sortable.destroy();
}
},
groupChanged : function(value) {
if(typeof(value) === 'string') {
return this.set('group', {name: value});
}
this.sortable && this.sortable.option("group", value );
},
sortChanged : function(value) { this.sortable && this.sortable.option("sort", value); },
disabledChanged : function(value) { this.sortable && this.sortable.option("disabled", value); },
storeChanged : function(value) { this.sortable && this.sortable.option("store", value); },
handleChanged : function(value) { this.sortable && this.sortable.option("handle", value); },
scrollChanged : function(value) { this.sortable && this.sortable.option("scroll", value); },
scrollSensitivityChanged : function(value) { this.sortable && this.sortable.option("scrollSensitivity", value); },
scrollSpeedChanged : function(value) { this.sortable && this.sortable.option("scrollSpeed", value); },
draggableChanged : function(value) { this.sortable && this.sortable.option("draggable", value); },
ghostClassChanged : function(value) { this.sortable && this.sortable.option("ghostClass", value); },
chosenClassChanged : function(value) { this.sortable && this.sortable.option("chosenClass", value); },
ignoreChanged : function(value) { this.sortable && this.sortable.option("ignore", value); },
filterChanged : function(value) { this.sortable && this.sortable.option("filter", value); },
animationChanged : function(value) { this.sortable && this.sortable.option("animation", value); },
dropBubbleChanged : function(value) { this.sortable && this.sortable.option("dropBubble", value); },
dragoverBubbleChanged : function(value) { this.sortable && this.sortable.option("dragoverBubble", value); },
dataIdAttrChanged : function(value) { this.sortable && this.sortable.option("dataIdAttr", value); },
delayChanged : function(value) { this.sortable && this.sortable.option("delay", value); },
forceFallbackChanged : function(value) { this.sortable && this.sortable.option("forceFallback", value); },
fallbackClassChanged : function(value) { this.sortable && this.sortable.option("fallbackClass", value); },
fallbackOnBodyChanged : function(value) { this.sortable && this.sortable.option("fallbackOnBody", value); }
});
</script>
<dom-module id="employee-list">
<template>
<sortable-js>
<template is="dom-repeat" items="{{employees}}">
<div>First name: <span>{{item.first}}</span></div>
</template>
</sortable-js>
</template>
<script>
Polymer({
is: 'employee-list',
ready: function() {
this.employees = [
{first: 'Bob', last: 'Smith'},
{first: 'Sally', last: 'Johnson'}
];
}
});
</script>
</dom-module>
<employee-list></employee-list>
</body>
</html>
Output
300px
This bin was created anonymously and its free preview time has expired (learn why). — Get a free unrestricted account
Dismiss xKeyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |