<html>
<head>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://canjs.com/release/2.2.6/can.jquery.js"></script>
<script src="http://canjs.com/release/2.2.6/can.map.define.js"></script>
<script src="http://canjs.com/release/2.2.6/can.stache.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="test"></div>
<script id="template" type="text/stache">
{{#items}}
<p>Previous: {{_prevItem.name}}</p>
<p>Current: {{name}}</p>
{{/items}}
</script>
</body>
</html>
//Gets the define properties, extends them and returns result
var DefineExtend = function () {
var defines = [];
can.each(arguments, function (item) {
//if passing an object with define at the top
if (item.define) {
defines.push(item.define);
return;
}
// if passing something like a can.Map constructor
if (item.prototype && item.prototype.define) {
defines.push(item.prototype.define);
}
});
return {define: can.extend.apply(can, defines)};
};
//
var PenultimateList = can.List.extend({
init: function () {
var self = this;
this.each(function (item) {
// Can't do this because JSON.stringify don't like it.
item.attr('_parent', self);
// This works but feels hacky...
item._parent = function () {
return self;
};
});
// Still looking into why this causes issues with updating the list
this.bind('length', function (opts, child) {
child._parent = function () {
return self;
};
});
}
});
var PenultimateMap = can.Map.extend({
define: {
_parent: {
value: function () {
return can.noop;
},
serialize: false
},
_prevItem: {
get: function () {
var items = this._parent();
var index = items ? items.indexOf(this) - 1: -1;
if ( index > -1) {
return items[index];
}
return {};
},
serialize: false
}
}
});
// I thought that doing this:
//var ExtendedMap = PenultimateMap.extend({define:{}});
// would extend one define into the other, but it actually compeltely overwrites the define object
// DefineExtend properly extends the two.
var ExtendedMap = can.Map.extend(DefineExtend(PenultimateMap, {
define: {
name: {
type:'string'
}
}
}));
PenultimateList.Map = ExtendedMap;
var DemoMap = can.Map.extend({
define: {
items: {
value: [{name:"juan"},{name:"cheese"}],
Type: PenultimateList
}
}
});
var template = can.view.render('template');
$('#test').html(template(new DemoMap({})));
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard 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. |