Commit c5ddf214 authored by Arthur Verschaeve's avatar Arthur Verschaeve

Drop `plastronjs` app

Fix #1219
parent c83a47f3
......@@ -27,7 +27,6 @@ module.exports = [
// https://github.com/tastejs/todomvc/issues/828
// routing should default to all
'TodoMVC - batman, Routing, should highlight the currently applied filter',
'TodoMVC - plastronjs, Routing, should highlight the currently applied filter',
'TodoMVC - sammyjs, Routing, should highlight the currently applied filter',
// https://github.com/tastejs/todomvc/issues/824
......@@ -60,7 +59,6 @@ module.exports = [
'TodoMVC - epitome, Editing, should cancel edits on escape',
'TodoMVC - extjs_deftjs, Editing, should cancel edits on escape',
'TodoMVC - olives, Editing, should cancel edits on escape',
'TodoMVC - plastronjs, Editing, should cancel edits on escape',
'TodoMVC - rappidjs, Editing, should cancel edits on escape',
'TodoMVC - serenadejs, Editing, should cancel edits on escape',
'TodoMVC - thorax, Editing, should cancel edits on escape',
......
node_modules/todomvc-app-css
!node_modules/todomvc-app-css/index.css
node_modules/todomvc-common
!node_modules/todomvc-common/base.js
!node_modules/todomvc-common/base.css
<!doctype html>
<html lang="en" data-framework="plastronjs">
<head>
<meta charset="utf-8">
<title>PlastronJS • TodoMVC</title>
<link rel="stylesheet" href="node_modules/todomvc-common/base.css">
<link rel="stylesheet" href="node_modules/todomvc-app-css/index.css">
<style>
#filters.none li.none,
#filters.active li.active,
#filters.completed li.completed {
font-weight: bold;
}
</style>
</head>
<body>
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<input id="new-todo" class="todo-entry" placeholder="What needs to be done?" autofocus>
</header>
<section id="main">
<input id="toggle-all" class="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list"></ul>
</section>
<footer id="footer">
<span id="todo-count"><strong>0</strong> item left</span>
<ul id="filters" class="none">
<li class="none">
<a href="#/">All</a>
</li>
<li class="active">
<a href="#/active">Active</a>
</li>
<li class="completed">
<a href="#/completed">Completed</a>
</li>
</ul>
<button id="clear-completed" class="clear-completed">Clear completed</button>
</footer>
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Created by <a href="http://rhysbrettbowen.com">Rhys Brett-Bowen</a> (<a href="https://twitter.com/RhysBB">RhysBB</a>)</p>
<p>Using <a href="https://github.com/rhysbrettbowen/PlastronJS">PlastronJS</a> and <a href="https://developers.google.com/closure/">Closure Tools</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<script src="node_modules/todomvc-common/base.js"></script>
<!-- <script src="http://localhost:9810/compile?id=todomvc&mode=raw"></script> -->
<script src="js/compiled.js"></script>
</body>
</html>
goog.require('mvc.Router');
goog.require('todomvc.listcontrol');
goog.require('todomvc.listmodel');
var todolist = new todomvc.listmodel();
// Create the control for the collection.
var todolistControl = new todomvc.listcontrol( todolist );
// HTML already there so use decorate.
todolistControl.decorate( goog.dom.getElement('todoapp') );
// Setup router
var router = new mvc.Router();
router.route( '{/}', function() {
todolist.set( 'filter', 'none' );
});
router.route( '/active', function() {
todolist.set( 'filter', 'active' );
});
router.route( '/completed', function() {
todolist.set( 'filter', 'completed' );
});
This diff is collapsed.
/*global goog, mvc, todomvc */
goog.provide('todomvc.listcontrol');
goog.require('goog.events.KeyCodes');
goog.require('goog.string');
goog.require('mvc.Control');
goog.require('todomvc.templates');
goog.require('todomvc.todocontrol');
/**
* the control for the todo list, handles the page as well
*
* @constructor
* @param {mvc.Collection} list model for todo items.
* @extends {mvc.Control}
*/
todomvc.listcontrol = function( list ) {
goog.base( this, list );
};
goog.inherits( todomvc.listcontrol, mvc.Control );
/**
* setup for event listeners.
*
* @inheritDoc
*/
todomvc.listcontrol.prototype.enterDocument = function() {
goog.base( this, 'enterDocument' );
var list = /** @type {Object} */(this.getModel());
// handle new note entry
this.on( goog.events.EventType.KEYUP, this.handleNewInput, '.todo-entry' );
// update complete button based on completed
this.autobind('#clear-completed', {
template: 'Clear completed ({$completed})',
noClick: true, // click should not set completed
show: true // hide when completed == false
});
// Clear completed
this.click( function() {
goog.array.forEach( list.getModels( 'completed' ),
function( model ) {
model.dispose();
});
}, '.clear-completed' );
// when to check the check all
this.autobind('.toggle-all', {
reqs: 'allDone'
});
// change classes of ULs based on filter
this.autobind( 'ul', {
reqs: 'filter',
reqClass: ['active', 'completed', 'none']
} );
// update the count based on active
this.autobind('#todo-count', {
template: todomvc.templates.itemsLeft,
reqs: 'active'
});
// show or hide based on the totals
this.autobind(['#main', 'footer'], {
show: 'total',
noClick: true
});
// autolists on modelChange and return refresh function
var refresh = this.autolist( todomvc.todocontrol,
goog.dom.getElement('todo-list') ).fire;
// if filter changes refresh view
this.bind( 'filter', refresh );
// if anything changes save models and refresh view
this.anyModelChange( refresh );
};
/**
* adds the input as a new item
*/
todomvc.listcontrol.prototype.handleNewInput = function( e ) {
var input = e.target;
// On return get trimmed text
if ( e.keyCode !== goog.events.KeyCodes.ENTER ) {
return;
}
var text = goog.string.trim( input.value );
if ( !text ) {
return;
}
// Create new model
this.getModel().newModel({
'title': text
});
input.value = '';
};
/*global goog, mvc, soy, todomvc */
goog.provide('todomvc.todocontrol');
goog.require('goog.dom');
goog.require('goog.string');
goog.require('goog.events.KeyCodes');
goog.require('mvc.Control');
goog.require('todomvc.templates');
/**
* this is the control for a todo item.
*
* @constructor
* @param {mvc.Model} model for the control.
* @extends {mvc.Control}
*/
todomvc.todocontrol = function( model ) {
goog.base( this, model );
};
goog.inherits( todomvc.todocontrol, mvc.Control );
/**
* overrides goog.ui.Component#createDom with the todo template.
*
* @inheritDoc
*/
todomvc.todocontrol.prototype.createDom = function() {
var el = soy.renderAsElement( todomvc.templates.todoItem, null, null );
this.setElementInternal(/** @type {Element} */(el));
};
/**
* setup for event listeners.
*
* @inheritDoc
*/
todomvc.todocontrol.prototype.enterDocument = function() {
var model = this.getModel();
// Toggle complete
this.autobind('.toggle', '{$completed}');
// Change li class on completion
this.autobind('', {
reqs: ['completed'],
onClass: 'completed',
noClick: true
});
// Delete the model
this.click(function() {
model.dispose();
}, '.destroy');
// keep label inline with title
this.autobind( 'label', {
reqs: ['title'],
template: function (data) { return data.title; },
data: {
title: function (control) {
var value = control.getModel().get('title');
return goog.string.htmlEscape(value);
}
}
});
var inputEl = this.getEls('.edit')[0];
// Dblclick to edit
this.on( goog.events.EventType.DBLCLICK, function() {
goog.dom.classes.add( this.getElement(), 'editing' );
inputEl.focus();
}, '.view');
// blur on enter
this.on( goog.events.EventType.KEYUP, function( e ) {
if ( e.keyCode === goog.events.KeyCodes.ENTER ) {
e.target.blur();
}
});
// finish editing on blur
this.on( goog.events.EventType.BLUR, function() {
goog.dom.classes.remove( this.getElement(), 'editing' );
});
// bind the title and the edit input
this.autobind( '.edit', '{$title}' );
};
/*global goog, mvc, todomvc */
goog.provide('todomvc.listmodel');
goog.require('mvc.Collection');
goog.require('todomvc.listsync');
goog.require('todomvc.todomodel');
/**
* @constructor
* @extends {mvc.Collection}
*/
todomvc.listmodel = function () {
var todosSchema = {
// number of completed
'completed': {
get: function () {
return this.getModels('completed').length;
},
models: true
},
'allDone': {
get: function () {
return this.getLength() === this.getModels('completed').length;
},
set: function (done) {
goog.array.forEach(this.getModels('none'), function (model) {
model.set('completed', done);
});
},
models: true
},
// number of active models
'active': {
get: function () {
return this.getLength() - this.getModels('completed').length;
},
models: true
},
// the total
'total': {
get: function () {
return this.getLength();
},
models: true
}
};
goog.base(this, {
'id': 'todos-plastronjs',
'sync': new todomvc.listsync(),
'schema': todosSchema,
'modelType': todomvc.todomodel
});
// fetch from localstorage
this.fetch();
// save on any changes
this.anyModelChange(this.save);
};
goog.inherits(todomvc.listmodel, mvc.Collection);
todomvc.listmodel.Filter = {
'none': function () {
return true;
},
'active': function (model) {
return !model.get('completed');
},
'completed': function (model) {
return model.get('completed');
}
};
/**
* return models based on current filter or filter given
*
* @inheritDoc
*/
todomvc.listmodel.prototype.getModels = function (opt_filter) {
return goog.base(this, 'getModels',
todomvc.listmodel.Filter[opt_filter || this.get('filter')]);
};
/**
* @return {Object} todos as json.
*/
todomvc.listmodel.prototype.toJson = function () {
return goog.array.map(this.getModels('none'), function (mod) {
return mod.toJson();
});
};
goog.provide('todomvc.todomodel');
goog.require('goog.string');
goog.require('mvc.Model');
goog.require('mvc.Model.ValidateError');
/**
* @constructor
* @param {Object=} opt_options to be put on the model.
* @extends {mvc.Model}
*/
todomvc.todomodel = function (opt_options) {
goog.base(this, opt_options);
// title must have a length, also format to remove spaces
this.setter('title', function (title) {
var updated = goog.string.trim(title);
if (!updated.length) {
throw new mvc.Model.ValidateError('null string');
}
return updated;
});
// when a note title is no longer valid then remove it
this.errorHandler(function () {
this.dispose();
});
};
goog.inherits(todomvc.todomodel, mvc.Model);
This source diff could not be displayed because it is too large. You can view the blob instead.
/*global goog, mvc, todomvc */
goog.provide('todomvc.listsync');
goog.require('mvc.LocalSync');
/**
* @constructor
* @extends {mvc.LocalSync}
*/
todomvc.listsync = function() {
goog.base( this );
};
goog.inherits( todomvc.listsync, mvc.LocalSync );
/**
* @inheritDoc
*/
todomvc.listsync.prototype.read = function( model, opt_callback ) {
var id = /** @type {string} */(model.get('id'));
var todos = this.store_.get(id) || [];
goog.array.forEach(/** @type {Array} */(todos),
function( todo ) {
model.newModel( todo, true );
});
model.change();
};
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
font-weight: inherit;
color: inherit;
-webkit-appearance: none;
-ms-appearance: none;
appearance: none;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
font-smoothing: antialiased;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #f5f5f5;
color: #4d4d4d;
min-width: 230px;
max-width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
font-smoothing: antialiased;
font-weight: 300;
}
button,
input[type="checkbox"] {
outline: none;
}
.hidden {
display: none;
}
#todoapp {
background: #fff;
margin: 130px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
#todoapp input::-webkit-input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
#todoapp input::-moz-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
#todoapp input::input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
#todoapp h1 {
position: absolute;
top: -155px;
width: 100%;
font-size: 100px;
font-weight: 100;
text-align: center;
color: rgba(175, 47, 47, 0.15);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
-ms-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
#new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
font-weight: inherit;
line-height: 1.4em;
border: 0;
outline: none;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-ms-box-sizing: border-box;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
}
#main {
position: relative;
z-index: 2;
border-top: 1px solid #e6e6e6;
}
label[for='toggle-all'] {
display: none;
}
#toggle-all {
position: absolute;
top: -55px;
left: -12px;
width: 60px;
height: 34px;
text-align: center;
border: none; /* Mobile Safari */
}
#toggle-all:before {
content: '❯';
font-size: 22px;
color: #e6e6e6;
padding: 10px 27px 10px 27px;
}
#toggle-all:checked:before {
color: #737373;
}
#todo-list {
margin: 0;
padding: 0;
list-style: none;
}
#todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px solid #ededed;
}
#todo-list li:last-child {
border-bottom: none;
}
#todo-list li.editing {
border-bottom: none;
padding: 0;
}
#todo-list li.editing .edit {
display: block;
width: 506px;
padding: 13px 17px 12px 17px;
margin: 0 0 0 43px;
}
#todo-list li.editing .view {
display: none;
}
#todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
-ms-appearance: none;
appearance: none;
}
#todo-list li .toggle:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" stroke-width="3"/></svg>');
}
#todo-list li .toggle:checked:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>');
}
#todo-list li label {
white-space: pre;
word-break: break-word;
padding: 15px 60px 15px 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
transition: color 0.4s;
}
#todo-list li.completed label {
color: #d9d9d9;
text-decoration: line-through;
}
#todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 30px;
color: #cc9a9a;
margin-bottom: 11px;
transition: color 0.2s ease-out;
}
#todo-list li .destroy:hover {
color: #af5b5e;
}
#todo-list li .destroy:after {
content: '×';
}
#todo-list li:hover .destroy {
display: block;
}
#todo-list li .edit {
display: none;
}
#todo-list li.editing:last-child {
margin-bottom: -1px;
}
#footer {
color: #777;
padding: 10px 15px;
height: 20px;
text-align: center;
border-top: 1px solid #e6e6e6;
}
#footer:before {
content: '';
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 50px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
0 8px 0 -3px #f6f6f6,
0 9px 1px -3px rgba(0, 0, 0, 0.2),
0 16px 0 -6px #f6f6f6,
0 17px 2px -6px rgba(0, 0, 0, 0.2);
}
#todo-count {
float: left;
text-align: left;
}
#todo-count strong {
font-weight: 300;
}
#filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
#filters li {
display: inline;
}
#filters li a {
color: inherit;
margin: 3px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
#filters li a.selected,
#filters li a:hover {
border-color: rgba(175, 47, 47, 0.1);
}
#filters li a.selected {
border-color: rgba(175, 47, 47, 0.2);
}
#clear-completed,
html #clear-completed:active {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
cursor: pointer;
visibility: hidden;
position: relative;
}
#clear-completed::after {
visibility: visible;
content: 'Clear completed';
position: absolute;
right: 0;
white-space: nowrap;
}
#clear-completed:hover::after {
text-decoration: underline;
}
#info {
margin: 65px auto 0;
color: #bfbfbf;
font-size: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center;
}
#info p {
line-height: 1;
}
#info a {
color: inherit;
text-decoration: none;
font-weight: 400;
}
#info a:hover {
text-decoration: underline;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
#toggle-all,
#todo-list li .toggle {
background: none;
}
#todo-list li .toggle {
height: 40px;
}
#toggle-all {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
@media (max-width: 430px) {
#footer {
height: 50px;
}
#filters {
bottom: 10px;
}
}
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #c5c5c5;
border-bottom: 1px dashed #f7f7f7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
#issue-count {
display: none;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
.learn-bar {
width: auto;
padding-left: 300px;
}
.learn-bar > .learn {
left: 8px;
}
}
/* global _ */
(function () {
'use strict';
/* jshint ignore:start */
// Underscore's Template Module
// Courtesy of underscorejs.org
var _ = (function (_) {
_.defaults = function (object) {
if (!object) {
return object;
}
for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
var iterable = arguments[argsIndex];
if (iterable) {
for (var key in iterable) {
if (object[key] == null) {
object[key] = iterable[key];
}
}
}
}
return object;
}
// By default, Underscore uses ERB-style template delimiters, change the
// following template settings to use alternative delimiters.
_.templateSettings = {
evaluate : /<%([\s\S]+?)%>/g,
interpolate : /<%=([\s\S]+?)%>/g,
escape : /<%-([\s\S]+?)%>/g
};
// When customizing `templateSettings`, if you don't want to define an
// interpolation, evaluation or escaping regex, we need one that is
// guaranteed not to match.
var noMatch = /(.)^/;
// Certain characters need to be escaped so that they can be put into a
// string literal.
var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
_.template = function(text, data, settings) {
var render;
settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation.
var matcher = new RegExp([
(settings.escape || noMatch).source,
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join('|') + '|$', 'g');
// Compile the template source, escaping string literals appropriately.
var index = 0;
var source = "__p+='";
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset)
.replace(escaper, function(match) { return '\\' + escapes[match]; });
if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
}
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
}
if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
index = offset + match.length;
return match;
});
source += "';\n";
// If a variable is not specified, place data values in local scope.
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
source + "return __p;\n";
try {
render = new Function(settings.variable || 'obj', '_', source);
} catch (e) {
e.source = source;
throw e;
}
if (data) return render(data, _);
var template = function(data) {
return render.call(this, data, _);
};
// Provide the compiled function source as a convenience for precompilation.
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
return template;
};
return _;
})({});
if (location.hostname === 'todomvc.com') {
window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'));
}
/* jshint ignore:end */
function redirect() {
if (location.hostname === 'tastejs.github.io') {
location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com');
}
}
function findRoot() {
var base = location.href.indexOf('examples/');
return location.href.substr(0, base);
}
function getFile(file, callback) {
if (!location.host) {
return console.info('Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.');
}
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200 && callback) {
callback(xhr.responseText);
}
};
}
function Learn(learnJSON, config) {
if (!(this instanceof Learn)) {
return new Learn(learnJSON, config);
}
var template, framework;
if (typeof learnJSON !== 'object') {
try {
learnJSON = JSON.parse(learnJSON);
} catch (e) {
return;
}
}
if (config) {
template = config.template;
framework = config.framework;
}
if (!template && learnJSON.templates) {
template = learnJSON.templates.todomvc;
}
if (!framework && document.querySelector('[data-framework]')) {
framework = document.querySelector('[data-framework]').dataset.framework;
}
this.template = template;
if (learnJSON.backend) {
this.frameworkJSON = learnJSON.backend;
this.frameworkJSON.issueLabel = framework;
this.append({
backend: true
});
} else if (learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.frameworkJSON.issueLabel = framework;
this.append();
}
this.fetchIssueCount();
}
Learn.prototype.append = function (opts) {
var aside = document.createElement('aside');
aside.innerHTML = _.template(this.template, this.frameworkJSON);
aside.className = 'learn';
if (opts && opts.backend) {
// Remove demo link
var sourceLinks = aside.querySelector('.source-links');
var heading = sourceLinks.firstElementChild;
var sourceLink = sourceLinks.lastElementChild;
// Correct link path
var href = sourceLink.getAttribute('href');
sourceLink.setAttribute('href', href.substr(href.lastIndexOf('http')));
sourceLinks.innerHTML = heading.outerHTML + sourceLink.outerHTML;
} else {
// Localize demo links
var demoLinks = aside.querySelectorAll('.demo-link');
Array.prototype.forEach.call(demoLinks, function (demoLink) {
if (demoLink.getAttribute('href').substr(0, 4) !== 'http') {
demoLink.setAttribute('href', findRoot() + demoLink.getAttribute('href'));
}
});
}
document.body.className = (document.body.className + ' learn-bar').trim();
document.body.insertAdjacentHTML('afterBegin', aside.outerHTML);
};
Learn.prototype.fetchIssueCount = function () {
var issueLink = document.getElementById('issue-count-link');
if (issueLink) {
var url = issueLink.href.replace('https://github.com', 'https://api.github.com/repos');
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function (e) {
var parsedResponse = JSON.parse(e.target.responseText);
if (parsedResponse instanceof Array) {
var count = parsedResponse.length
if (count !== 0) {
issueLink.innerHTML = 'This app has ' + count + ' open issues';
document.getElementById('issue-count').style.display = 'inline';
}
}
};
xhr.send();
}
};
redirect();
getFile('learn.json', Learn);
})();
{
"private": true,
"dependencies": {
"todomvc-common": "^1.0.1",
"todomvc-app-css": "^1.0.1"
}
}
{
"id": "todomvc",
"inputs": "js/app.js",
"paths": ["js/", "template/"],
"output-wrapper": "(function(){%output%})();",
"mode": "ADVANCED",
"level": "VERBOSE",
"output-file": "js/compiled.js"
}
# PlastronJS TodoMVC Example
> PlastronJS is an MVC library which uses the Google Closure library for use with the Closure Compiler.
> _[PlastronJS - rhysbrettbowen.github.io/PlastronJS](http://rhysbrettbowen.github.io/PlastronJS)_
## Learning PlastronJS
The [PlastronJS website](http://rhysbrettbowen.github.io/PlastronJS) is a great resource for getting started.
Here are some links you may find helpful:
* [PlastronJS on GitHub](https://github.com/rhysbrettbowen/PlastronJS)
Articles and guides from the community:
* [The Future of PlastronJS](http://modernjavascript.blogspot.com/2012/11/the-future-of-plastronjs.html)
* [Krisztian Toth's JavaScript Games, XRegExp, PlastronJS](http://dailyjs.com/2012/04/06/toth-xregexp-plastron)
_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._
## Running
The app is built with [Plovr](http://plovr.com). To run the unminified version you need to:
1. [Download Plovr](http://plovr.com/download.html)
2. Create a directory called `build`
3. Put the jar file in the build folder
4. Create a folder, `js/lib`
5. Download and move the contents of [PlastronJS](https://github.com/rhysbrettbowen/PlastronJS) to `js/lib`
Then run the following command in your terminal:
java -jar build/plovr.jar serve plovr.json
Change the script src at the bottom of `index.html` from:
js/compiled.js
to
http://localhost:9810/compile?id=todomvc&mode=raw
You can now view the uncompiled example and play around with it!
## Compiling
Once you have done the steps above, you can compile any changes you make by running the below command:
java -jar build/plovr.jar build plovr.json
View the compiled version for the page by changing the bottom script `src` back to `js/compiled`.
## Credit
This TodoMVC application was created by [Rhys Brett-Bowen](http://rhysbrettbowen.com).
{namespace todomvc.templates}
/**
*/
{template .todoItem}
<li>
<div class="view">
<input class="toggle" type="checkbox">
<label></label>
<button class="destroy"></button>
</div>
<input class="edit" type="text">
</li>
{/template}
/**
* use template for the 's' logic.
* Used in autobind so gets data under model namespace.
*
* @param model
*/
{template .itemsLeft}
<strong>{$model['active']}</strong> item{if $model['active'] != 1}s{/if} left
{/template}
......@@ -233,9 +233,6 @@
<li>
<a href="examples/olives/" data-source="https://github.com/flams/olives" data-content="Olives is a JS MVC framework that helps you create realtime UIs. It includes a set of AMD/CommonJS modules that are easily extensive, a high level of abstraction to reduce boilerplate and is based on socket.io, to provide a powerful means to communicate with node.js.">Olives</a>
</li>
<li class="routing">
<a href="examples/plastronjs/" data-source="https://github.com/rhysbrettbowen/PlastronJS" data-content="PlastronJS is an mvc framework built on top of the Closure Library and built to compile with projects that use the Closure Compiler.">PlastronJS</a>
</li>
<li>
<a href="examples/dijon/" data-source="https://github.com/creynders/dijon-framework" data-content="Dijon is an IOC and DI micro-framework for Javascript. Originally it was meant to be a port of Robotlegs, but deviated to something quite different. It remains however heavily inspired by Robotlegs, and more specifically Swiftsuspenders.">Dijon</a>
</li>
......
......@@ -1631,31 +1631,6 @@
}]
}]
},
"plastronjs": {
"name": "PlastronJS",
"description": "PlastronJS is an MVC library which uses the Google Closure library for use with the Closure Compiler.",
"homepage": "rhysbrettbowen.github.io/PlastronJS",
"examples": [{
"name": "Example",
"url": "examples/plastronjs"
}],
"link_groups": [{
"heading": "Official Resources",
"links": [{
"name": "PlastronJS on GitHub",
"url": "https://github.com/rhysbrettbowen/PlastronJS"
}]
}, {
"heading": "Articles and Guides",
"links": [{
"name": "The Future of PlastronJS",
"url": "http://modernjavascript.blogspot.com/2012/11/the-future-of-plastronjs.html"
}, {
"name": "Krisztian Toth's JavaScript Games, XRegExp, PlastronJS",
"url": "http://dailyjs.com/2012/04/06/toth-xregexp-plastron"
}]
}]
},
"polymer": {
"name": "Polymer",
"description": "Polymer is a new type of library for the web, built on top of Web Components, and designed to leverage the evolving web platform on modern browsers. It is comprised of core platform features (e.g Shadow DOM, Custom Elements, MDV) enabled with polyfills and a next generation web application framework built on these technologies.",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment