Commit 8e470a3e authored by Arthur Verschaeve's avatar Arthur Verschaeve

Drop the `epitome` example

As the author doesn't respond anymore and the framework hasn't been
updated for really long.

Ref gh-1209
parent c3f5dc53
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
node_modules/epitome/**
!node_modules/Epitome/Epitome-min.js
<!doctype html>
<html lang="en" data-framework="epitome">
<head>
<meta charset="utf-8">
<title>Epitome • TodoMVC</title>
<link rel="stylesheet" href="node_modules/todomvc-common/base.css">
<link rel="stylesheet" href="node_modules/todomvc-app-css/index.css">
</head>
<body>
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<input id="new-todo" placeholder="What needs to be done?" autofocus>
</header>
<section id="main">
<input id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list"></ul>
</section>
<footer id="footer"></footer>
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Created by <a href="https://github.com/DimitarChristoff/">Dimitar Christoff</a></p>
<p>Powered by <a href="http://epitome-mvc.github.io/Epitome">Epitome for MooTools</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<script type="text/template" id="item-template">
<div class="view">
<input class="toggle" type="checkbox" <%=completedCheckbox%>>
<label><%-title%></label>
<button class="destroy"></button>
</div>
<input class="edit" value="<%=title%>">
</script>
<script type="text/template" id="stats-template">
<span id="todo-count">
<strong><%=remaining%></strong> item<% if (obj.remaining !== 1) { %>s<% } %> left
</span>
<ul id="filters">
<li>
<a class="selected" href="#!/">All</a>
</li>
<li>
<a href="#!/active">Active</a>
</li>
<li>
<a href="#!/completed">Completed</a>
</li>
</ul>
<% if (completed) { %>
<button id="clear-completed">Clear completed</button>
<% } %>
</script>
<script src="node_modules/todomvc-common/base.js"></script>
<!-- mootools -->
<script src="js/lib/mootools-yui-compressed.js"></script>
<!-- epitome pre-compiled -->
<script src="node_modules/Epitome/Epitome-min.js"></script>
<!-- todo app -->
<script src="js/models/todo-model.js"></script>
<script src="js/collections/todo-collection.js"></script>
<script src="js/views/todo-list.js"></script>
<script src="js/views/todo-main.js"></script>
<script src="js/controllers/todo-router.js"></script>
<script src="js/app.js"></script>
</body>
</html>
/*jshint mootools:true */
(function (window) {
'use strict';
var App = window.App;
var todos = new App.TodoCollection(null, {
// a consistent collection if is needed if you want to use storage for a collection
id: 'todos'
});
// populate from storage if available
todos.setUp(todos.retrieve());
// instantiate the todo list view
App.todoView = new App.TodoView({
// bind to the collection and its events and model events
collection: todos,
// encapsulating element to bind to
element: document.id('todo-list'),
// template to use
template: document.id('item-template').get('text')
});
// the main view is for the footer/stats/controls
App.mainView = new App.MainView({
// also bound to the same collection but with a different output logic.
collection: todos,
// encapsulating element to bind to
element: document.id('todoapp'),
// stats template from DOM
template: document.id('stats-template').get('text'),
onReady: function () {
// need to work with controller that sets the current state of filtering
var proxy = function () {
App.router.showActiveFilter();
};
this.on('add:collection change:collection', proxy);
}
});
// the pseudo controller via Epitome.Router
App.router = new App.Router({
routes: {
'': 'init',
'#!/': 'applyFilter',
'#!/:filter': 'applyFilter'
},
onInit: function () {
// we want to always have a state
this.navigate('#!/');
},
onApplyFilter: function (filter) {
// the filter is being used by the todo collection and view.
// when false, the whole collection is being passed.
todos.filterType = filter || false;
// render as per current filter
App.todoView.render();
this.showActiveFilter();
}
});
})(window);
/*global Epitome, App */
/*jshint mootools:true */
(function (window) {
'use strict';
window.App = window.App || {};
// a collection that holds the todos
App.TodoCollection = new Class({
// normal collection or Collection.Sync
Extends: Epitome.Collection,
// enable storage methods, namespaced as collection.
Implements: Epitome.Storage.localStorage('collection'),
// base model class prototype
model: App.Todo,
map: {
active: 0,
completed: 1
},
todoFilter: function (model) {
// references the filterType which the controller sets
return this.filterType === false ? true : this.map[this.filterType] === +model.get('completed');
}
});
})(window);
/*global Epitome, App */
/*jshint mootools:true */
(function (window) {
'use strict';
window.App = window.App || {};
App.Router = new Class({
Extends: Epitome.Router,
showActiveFilter: function () {
// fix up the links for current filter
var self = this;
document.getElements('#filters li a').each(function (link) {
link.set('class', link.get('href') === self.req ? 'selected' : '');
});
}
});
})(window);
This diff is collapsed.
/*global Epitome, App */
/*jshint mootools:true */
(function (window) {
'use strict';
window.App = window.App || {};
// base structure for the todos themselves
App.Todo = new Class({
Extends: Epitome.Model,
options: {
defaults: {
completed: false,
title: ''
}
}
});
// a collection that holds the todos
App.TodoCollection = new Class({
Extends: Epitome.Collection,
Implements: Epitome.Storage.sessionStorage('collection'),
model: App.Todo
});
})(window);
/*global Epitome, App */
/*jshint mootools:true */
(function (window) {
'use strict';
window.App = window.App || {};
App.TodoView = new Class({
// a view abstraction bound to collection that displays the current view list based upon known data.
// normal view
Extends: Epitome.View,
// not API, but a wrapper property
tagName: 'li',
options: {
// added to group when editing
editingClass: 'editing',
// mask to bind to
input: 'input.edit',
// eavesdrop on these events
events: {
'blur:relay(input.edit)': 'update',
'click:relay(input.toggle)': 'statusChange',
'keypress:relay(input.edit)': 'handleKeypress',
'click:relay(button.destroy)': 'removeItem',
'dblclick:relay(label)': 'editing'
},
// define actual event handlers
onReady: function () {
// initial view
this.render();
},
// when collection changes, save the data to storage and re-render
'onChange:collection': function () {
this.collection.store();
this.render();
},
// when models get removed, re-render
'onRemove:collection': function () {
this.collection.store();
this.render();
},
// when sort is applied, re-render
'onSort:collection': function () {
this.collection.store();
this.render();
},
// when a new model is added, re-render
'onAdd:collection': function () {
this.collection.store();
this.render();
},
// handler for the edit event
onEditing: function (e, el) {
if (e && e.stop) {
e.stop();
}
var container = el.getParent('li');
var input = container.getElement(this.options.input);
container.addClass(this.options.editingClass);
input.focus();
input.value = input.value;
},
// when enter pressed while editing
onHandleKeypress: function (e, el) {
// on enter, blur() and let it bubble to onUpdate.
if (e.key === 'enter') {
el.blur();
}
},
// fired when editing ends
onUpdate: function (e, el) {
var p = el.getParent('li').removeClass(this.options.editingClass);
var val = el.get('value').trim();
if (!val.length) {
// the render method stores the model into the element, get it and remove
this.collection.removeModel(p.retrieve('model'));
return;
}
p.retrieve('model').set('title', val);
},
// handler for clicks on the checkboxes
onStatusChange: function (e, el) {
var p = el.getParent('li');
var done = !!el.get('checked');
p.retrieve('model').set('completed', done);
},
// when the X is pressed, drop the model
onRemoveItem: function (e, el) {
if (e && e.stop) {
e.stop();
}
// the render method stores the model into the element, get it and remove
this.collection.removeModel(el.getParent('li').retrieve('model'));
}
},
render: function () {
// main render method, will also fire onRender
var todos = new Elements();
var self = this;
// empty the container.
this.empty();
// the route controller works with the todoFilter to help determine what we render.
this.collection.filter(this.collection.todoFilter.bind(this.collection)).each(function (model) {
var obj = model.toJSON();
var li = new Element(self.tagName).toggleClass('completed', obj.completed).store('model', model);
// help the template to avoid slower logic in the template layer
obj.completedCheckbox = obj.completed ? 'checked' : '';
// compile template and store resulting element in our Elements collection
todos.push(li.set('html', self.template(obj)));
});
// inject the elements collection into the container element
this.element.adopt(todos);
// propagate the render event.
this.parent();
return this;
}
});
})(window);
/*global Epitome, App */
/*jshint mootools:true */
(function (window) {
'use strict';
window.App = window.App || {};
App.MainView = new Class({
// main view (presenter) encapsulating the app itself.
Extends: Epitome.View,
options: {
// eavesdrop on these events
events: {
'change:relay(#new-todo)': 'addTodo',
'keypress:relay(#new-todo)': 'handleKeypress',
'click:relay(#toggle-all)': 'toggleAll',
'click:relay(#clear-completed)': 'clearCompleted',
'click:relay(#filters.a)': 'setFilters'
},
// pass on some options for later func
newTodo: 'new-todo',
footer: 'footer',
main: 'main',
filters: '#filters li a',
toggleAll: 'toggle-all',
onToggleAll: function (e, el) {
// all todos will change their models to the new completed value
var state = !!el.get('checked');
this.collection.each(function (model) {
model.set('completed', state);
});
},
onHandleKeypress: function (e) {
// on enter, submit.
if (e.key === 'enter') {
this.addTodo();
}
},
onClearCompleted: function () {
// because removing a model re-indexes so we don't get a sparse array, cannot apply that in a normal loop.
var toRemove = this.collection.filter(function (model) {
return model.get('completed');
});
// removeModel actually supports a single model or an array of models as arguments.
this.collection.removeModel(toRemove);
this.render();
},
onAddTodo: function () {
// go to method
this.addTodo();
},
'onChange:collection': function () {
// also, re-render on change of collection
this.render();
},
'onRemove:collection': function () {
this.render();
},
'onAdd:collection': function () {
// when adding, re-render.
this.render();
}
},
initialize: function (options) {
// call default view constructor.
this.parent(options);
// store some pointers to static elements
this.newTodo = document.id(this.options.newTodo);
this.footer = document.id(this.options.footer);
this.toggleAll = document.id(this.options.toggleAll);
this.main = document.id(this.options.main);
// draw it.
this.render();
},
addTodo: function () {
// adding a new model when data exists
var val = this.newTodo.get('value').trim();
if (val.length) {
this.collection.addModel({
title: val,
completed: false
});
}
// clear the input
this.newTodo.set('value', '');
},
render: function () {
// main method to output everything. well. the footer anyway.
// work out what we have remaining and what is complete
var remaining = 0;
var completed = this.collection.filter(function (model) {
var status = model.get('completed');
if (status === false) {
remaining++;
}
return status;
}).length;
var visibleClass = remaining || completed ? '' : 'hidden';
// output footer
this.footer.set('html', this.template({
completed: completed,
remaining: remaining
})).set('class', visibleClass);
this.main.set('class', visibleClass);
// auto-correct the toggle-all checkbox with the new stats.
this.toggleAll.set('checked', this.collection.length ? !remaining : false);
}
});
})(window);
This diff is collapsed.
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;
appearance: none;
-webkit-font-smoothing: antialiased;
-moz-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;
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;
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);
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-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;
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;
position: relative;
}
#clear-completed:hover {
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",
"epitome": "epitome-mvc/Epitome#520364829b4b2b4a04645f9f3714f008e4f37e21"
}
}
# Epitome TodoMVC Example
> Epitome is a new extensible and modular open-source MVC framework, built out of MooTools Classes and Events.
> _[Epitome - dimitarchristoff.github.io/Epitome](http://dimitarchristoff.github.io/Epitome)_
## Learning Epitome
The [Epitome website](http://dimitarchristoff.github.io/Epitome) is a great resource for getting started.
Here are some links you may find helpful:
* [API Reference](http://dimitarchristoff.github.io/Epitome)
* [Examples](http://dimitarchristoff.github.io/Epitome/#examples)
* [Download & Building](http://dimitarchristoff.github.io/Epitome/#download-building)
* [Epitome on GitHub](https://github.com/DimitarChristoff/Epitome)
Get help from other Epitome users:
* [Epitome on Twitter](http://twitter.com/D_mitar)
_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)._
......@@ -212,9 +212,6 @@
<li class="routing">
<a href="examples/sammyjs/" data-source="http://sammyjs.org" data-content="Sammy.js is a tiny JavaScript framework developed to ease the pain and provide a basic structure for developing JavaScript applications.">Sammy.js</a>
</li>
<li class="routing">
<a href="examples/epitome/" data-source="http://dimitarchristoff.github.com/Epitome" data-content="Epitome is a new extensible and modular open-source MVC framework, built out of MooTools Classes and Events.">Epitome</a>
</li>
<li>
<a href="examples/somajs/" data-source="http://somajs.github.com/somajs" data-content="soma.js is a framework created to build scalable and maintainable javascript applications.">soma.js</a>
</li>
......
......@@ -949,37 +949,6 @@
}]
}]
},
"epitome": {
"name": "Epitome",
"description": "Epitome is a new extensible and modular open-source MVC* framework, built out of MooTools Classes and Events.",
"homepage": "dimitarchristoff.github.io/Epitome",
"examples": [{
"name": "Example",
"url": "examples/epitome"
}],
"link_groups": [{
"heading": "Official Resources",
"links": [{
"name": "API Reference",
"url": "http://dimitarchristoff.github.io/Epitome"
}, {
"name": "Examples",
"url": "http://dimitarchristoff.github.io/Epitome/#examples"
}, {
"name": "Download & Building",
"url": "http://dimitarchristoff.github.io/Epitome/#download-building"
}, {
"name": "Epitome on GitHub",
"url": "https://github.com/DimitarChristoff/Epitome"
}]
}, {
"heading": "Community",
"links": [{
"name": "Epitome on Twitter",
"url": "http://twitter.com/D_mitar"
}]
}]
},
"exoskeleton": {
"name": "Exoskeleton",
"description": "A faster and leaner Backbone for your HTML5 apps.",
......
......@@ -55,7 +55,6 @@ module.exports = [
'TodoMVC - ariatemplates, Editing, should cancel edits on escape',
'TodoMVC - dermis, Editing, should cancel edits on escape',
'TodoMVC - duel, Editing, should cancel edits on escape',
'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 - rappidjs, Editing, should cancel edits on escape',
......
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