Commit 266ea64a authored by Sam Saccone's avatar Sam Saccone

Merge pull request #1369 from tastejs/drop-yui

Drop the YUI app
parents b5cde6ca ae3f0774
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="yui">
<head>
<meta charset="utf-8">
<title>YUI • 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/clarle">Clarence Leung</a> and
<a href="https://twitter.com/ericf">Eric Ferraiuolo</a>
</p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<script src="node_modules/todomvc-common/base.js"></script>
<script type="text/x-handlebars-template" id="item-template">
<div class="view">
<input class="toggle" type="checkbox" {{#if completed}}checked{{/if}}>
<label>{{title}}</label>
<button class="destroy"></button>
</div>
<input class="edit" value="{{title}}">
</script>
<script type="text/x-handlebars-template" id="stats-template">
<span id="todo-count"><strong>{{remaining}}</strong> {{pluralize remaining "item"}} 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>
{{/if}}
</script>
<script src="node_modules/todomvc-common/base.js"></script>
<script src="js/lib/yui.js"></script>
<script>
YUI({
groups: {
'todo-mvc': {
base: './js/',
modules: {
'todo': {
path: 'models/todo.js'
},
'todo-list': {
path: 'models/todolist.js'
},
'todo-view': {
path: 'views/todoview.js'
},
'todo-app': {
path: 'app.js'
}
}
}
}
}).use('todo-app', function (Y) {
new Y.TodoMVC.TodoApp();
});
</script>
</body>
</html>
/*global YUI*/
YUI.add('todo-app', function (Y) {
'use strict';
// Dependencies from MVC namespace.
var TodoApp;
var TodoList = Y.TodoMVC.TodoList;
var TodoView = Y.TodoMVC.TodoView;
// -- Main Application --------------
TodoApp = Y.Base.create('todoApp', Y.App, [], {
// Set container to bind to the existing '#todoapp' element
containerTemplate: '#todoapp',
// Compile statistics template with Handlebars.
template: Y.Handlebars.compile(Y.one('#stats-template').getHTML()),
// DOM events for creating new Todos and clearing out old ones.
events: {
'#new-todo': {
keypress: 'enterCreate'
},
'#clear-completed': {
click: 'clearCompleted'
},
'#toggle-all': {
click: 'completeAll'
}
},
// Initialize our TodoList, and bind any events that occur
// when new Todos are added, changed, or removed within it.
// Also, fetch any Todos that are found within localStorage.
initializer: function () {
this.set('todoList', new TodoList());
var list = this.get('todoList');
Y.Handlebars.registerHelper('pluralize', function (context, word) {
return (context === 1) ? word : word + 's';
});
list.after(['add', 'remove', 'reset', 'todo:completedChange'],
this.render, this);
list.load();
// Keep our filters on refresh by immediately dispatching route.
this.once('ready', function () {
if (this.hasRoute(this.getPath())) {
this.dispatch();
}
});
},
// Render our application with the statistics from our TodoList,
// and various other stylistic elements.
render: function () {
var todoList = this.get('todoList');
var completed = todoList.completed().size();
var remaining = todoList.remaining().size();
var main = this.get('main');
var footer = this.get('footer');
// If we have Todos in our TodoList, show them with statistics.
if (todoList.size()) {
main.show();
footer.show();
footer.setHTML(this.template({
completed: completed,
remaining: remaining
}));
// Highlights for filters at the bottom of our Todo application.
footer.one('#filters li a').removeClass('selected');
footer.all('#filters li a')
.filter('[href="#/' + (this.get('filter') || '') + '"]')
.addClass('selected');
} else {
main.hide();
footer.hide();
}
// Set the checkbox only if all Todos have been completed.
this.get('allCheckbox').set('checked', !remaining);
this.addViews();
},
// Add Todo views to the DOM simultaneously, triggered when
// the application initially loads, or we switch filters.
addViews: function () {
var models;
var fragment = Y.one(Y.config.doc.createDocumentFragment());
var todoList = this.get('todoList');
// An Array of models is passed through when the 'reset'
// event is triggered through syncing through load().
switch (this.get('filter')) {
case 'active':
models = todoList.remaining();
break;
case 'completed':
models = todoList.completed();
break;
default:
models = todoList;
break;
}
// Iterate through the (filtered) ModelList.
models.each(function (model) {
var view = new TodoView({model: model});
fragment.append(view.render().get('container'));
});
// To delete previously attached views and fix the memory leak.
this.get('container').one('#todo-list').destroy({recursivePurge: true});
this.get('container').one('#todo-list').setContent(fragment);
},
// Create and save a new Todo from the inputted value when the
// Enter key is pressed down.
enterCreate: function (e) {
var ENTER_KEY = 13;
var todoList = this.get('todoList');
var inputNode = this.get('inputNode');
var value = inputNode.get('value');
if (e.keyCode !== ENTER_KEY || !value) {
return;
}
todoList.create({
title: value
});
inputNode.set('value', '');
},
// Clear all completed Todos from the TodoList. This removes the models
// from the list, as well as deletes them from localStorage.
clearCompleted: function () {
var todoList = this.get('todoList');
var completed = todoList.completed();
todoList.remove(completed);
completed.each(function (todo) {
todo.clear();
});
},
// Complete all non-complete Todos, or reset them all if they are
// all already complete.
completeAll: function () {
var todoList = this.get('todoList');
var allCheckbox = this.get('allCheckbox');
var completed = allCheckbox.get('checked');
todoList.each(function (todo) {
todo.save({completed: completed});
});
},
// Set the filter for our application from the route that is passed
// in (see below).
handleFilter: function (req) {
this.set('filter', req.params.filter);
this.get('todoList').load();
}
}, {
ATTRS: {
// Significant DOM elements that relate to our application that
// we would like to keep as attributes.
container: {
valueFn: function () {
return Y.one('#todoapp');
}
},
inputNode: {
valueFn: function () {
return Y.one('#new-todo');
}
},
allCheckbox: {
valueFn: function () {
return Y.one('#toggle-all');
}
},
main: {
valueFn: function () {
return Y.one('#main');
}
},
footer: {
valueFn: function () {
return Y.one('#footer');
}
},
// This can be set to fall back on server-side routing when
// HTML5 pushState is not available. For this application,
// we are only using hash-based URLs though.
serverRouting: {
value: false
},
// Our initial filter for the application.
filter: {
value: null
},
// Routing for the application, to determine the filter.
// The callback takes a request object, Express-style.
routes: {
value: [
{
path: '/:filter',
callback: 'handleFilter'
}
]
}
}
});
// Namespace this application under our custom Y.MVC namespace.
Y.namespace('TodoMVC').TodoApp = TodoApp;
}, '@VERSION@', {
requires: [
'app-base',
'todo-list',
'todo-view',
'node'
]
});
This diff is collapsed.
/*global YUI*/
YUI.add('todo', function (Y) {
'use strict';
// -- Todo Model -------------
var Todo = Y.Base.create('todo', Y.Model, [Y.ModelSync.Local], {
// Set up the root localStorage key we save our Model data in.
root: 'todos-yui',
// Toggle the completed state of the Todo.
toggle: function () {
this.save({completed: !this.get('completed')});
},
// Destroy this Todo and remove it from localStorage.
clear: function () {
this.destroy({remove: true});
}
}, {
// Default attributes.
ATTRS: {
title: {
value: ''
},
completed: {
value: false
}
}
});
// Set this Model under our custom Y.MVC namespace.
Y.namespace('TodoMVC').Todo = Todo;
}, '@VERSION@', {
requires: [
'gallery-model-sync-local',
'model'
]
});
/*global YUI*/
YUI.add('todo-list', function (Y) {
'use strict';
// Dependencies from Y.MVC.
var TodoList;
var Todo = Y.TodoMVC.Todo;
// -- TodoList Model list -----
TodoList = Y.Base.create('todoList', Y.ModelList, [Y.ModelSync.Local], {
// The related Model for our Model List.
model: Todo,
// The root used for our localStorage key.
root: 'todos-yui',
// Return a ModelList of our completed Models.
completed: function () {
return this.filter({asList: true}, function (todo) {
return todo.get('completed');
});
},
// Return an ModelList of our un-completed Models.
remaining: function () {
return this.filter({asList: true}, function (todo) {
return !todo.get('completed');
});
}
});
// Set this Model List under our custom Y.MVC namespace.
Y.namespace('TodoMVC').TodoList = TodoList;
}, '@VERSION@', {
requires: [
'gallery-model-sync-local',
'model-list',
'todo'
]
});
/*global YUI*/
YUI.add('todo-view', function (Y) {
'use strict';
// -- Todo View -------------------
var TodoView = Y.Base.create('todoView', Y.View, [], {
// The container element that the View is rendered under.
containerTemplate: '<li>',
// Compile our template using Handlebars.
template: Y.Handlebars.compile(Y.one('#item-template').getHTML()),
// Bind DOM events for handling changes to a specific Todo,
// for completion and editing.
events: {
'.toggle': {
click: 'toggleComplete'
},
'label': {
dblclick: 'edit'
},
'.edit': {
blur: 'close',
keypress: 'enterUpdate'
},
'.destroy': {
click: 'clear'
}
},
// Initialize this view by setting event handlers when the Model
// is updated or destroyed.
initializer: function () {
var model = this.get('model');
model.after('change', this.render, this);
},
// Render this view in our <li> container, and fill it with the
// data in our Model.
render: function () {
var container = this.get('container');
var model = this.get('model');
container.setHTML(this.template(model.toJSON()));
container.toggleClass('completed', model.get('completed'));
this.set('inputNode', container.one('.edit'));
return this;
},
// Toggle the linked Todo's completion status.
toggleComplete: function () {
this.get('model').toggle();
},
// Turn on editing mode for the Todo by exposing the input field.
edit: function () {
var input = this.get('inputNode');
this.get('container').addClass('editing');
// place cursor at the end of the line
input._node.value = input._node.value;
input.focus();
},
// Get the value from our input field while hiding it, and
// save it to our Todo when focus is lost from the field.
close: function () {
var editedValue = this.get('inputNode').get('value');
this.get('container').removeClass('editing');
if (editedValue) {
this.get('model').save({title: editedValue});
} else {
this.clear();
}
},
// Also allow updating the Todo's text through the enter key.
enterUpdate: function (e) {
var ENTER_KEY = 13;
if (e.keyCode === ENTER_KEY) {
this.close();
}
},
// Destroy the model when the delete button is clicked.
clear: function () {
this.get('model').clear();
}
});
// Set this View under our custom Y.TodoMVC namespace.
Y.namespace('TodoMVC').TodoView = TodoView;
}, '@VERSION@', {
requires: [
'view',
'handlebars',
'event-focus'
]
});
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"
}
}
# YUI TodoMVC Example
> YUI is a free, open source JavaScript and CSS library for building richly interactive web applications.
> _[YUI - yuilibrary.com](http://yuilibrary.com)_
## Learning YUI
The [YUI website](http://yuilibrary.com) is a great resource for getting started.
Here are some links you may find helpful:
* [Documentation](http://yuilibrary.com/yui/docs)
* [Quick Start](http://yuilibrary.com/yui/quick-start)
* [Tutorials](http://yuilibrary.com/yui/docs/tutorials)
* [Examples](http://yuilibrary.com/yui/docs/examples)
* [Blog](http://yuiblog.com)
Get help from other YUI users:
* [YUI on StackOverflow](http://stackoverflow.com/questions/tagged/yui)
* [Forms](http://yuilibrary.com/forum)
* [YUI on Twitter](http://twitter.com/yuilibrary)
_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)._
......@@ -96,9 +96,6 @@
<li class="routing">
<a href="examples/dojo/" data-source="http://dojotoolkit.org" data-content="Dojo saves you time and scales with your development process, using web standards as its platform. It’s the toolkit experienced developers turn to for building high quality desktop and mobile web applications.">Dojo</a>
</li>
<li class="routing">
<a href="examples/yui/" data-source="http://yuilibrary.com" data-content="YUI's lightweight core and modular architecture make it scalable, fast, and robust. Built by frontend engineers at Yahoo!, YUI powers the most popular websites in the world.">YUI</a>
</li>
<li class="routing">
<a href="examples/knockback/" data-source="http://kmalakoff.github.com/knockback/" data-content="Knockback.js provides Knockout.js magic for Backbone.js Models and Collections.">Knockback.js</a>
</li>
......
......@@ -2215,46 +2215,6 @@
}]
}]
},
"yui": {
"name": "YUI",
"description": "YUI is a free, open source JavaScript and CSS library for building richly interactive web applications.",
"homepage": "yuilibrary.com",
"examples": [{
"name": "Example",
"url": "examples/yui"
}],
"link_groups": [{
"heading": "Official Resources",
"links": [{
"name": "Documentation",
"url": "http://yuilibrary.com/yui/docs"
}, {
"name": "Quick Start",
"url": "http://yuilibrary.com/yui/quick-start"
}, {
"name": "Tutorials",
"url": "http://yuilibrary.com/yui/docs/tutorials"
}, {
"name": "Examples",
"url": "http://yuilibrary.com/yui/docs/examples"
}, {
"name": "Blog",
"url": "http://yuiblog.com"
}]
}, {
"heading": "Community",
"links": [{
"name": "YUI on Stack Overflow",
"url": "http://stackoverflow.com/questions/tagged/yui"
}, {
"name": "Forums",
"url": "http://yuilibrary.com/forum"
}, {
"name": "YUI on Twitter",
"url": "http://twitter.com/yuilibrary"
}]
}]
},
"webrx": {
"name": "WebRx",
"description": "WebRx is a browser-based MVVM-Framework written in Typescript that combines functional-reactive programming with declarative Data-Binding and Templating.",
......
......@@ -52,7 +52,6 @@ module.exports = [
// the following are covered by the following issue:
// https://github.com/tastejs/todomvc/issues/789
'TodoMVC - closure, Editing, should cancel edits on escape',
'TodoMVC - yui, Editing, should cancel edits on escape',
'TodoMVC - ariatemplates, Editing, should cancel edits on escape',
'TodoMVC - dermis, Editing, should cancel edits on escape',
'TodoMVC - duel, 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