Commit b50e3e28 authored by Sven Franck's avatar Sven Franck

modifications to pass todomvc tests

parent 1af400dd
/*global window, RSVP, FileReader */
/*jslint indent: 2, maxerr: 3, unparam: true */
(function (window, RSVP, FileReader) {
"use strict";
window.loopEventListener = function (target, type, useCapture, callback,
allowDefault) {
//////////////////////////
// Infinite event listener (promise is never resolved)
// eventListener is removed when promise is cancelled/rejected
//////////////////////////
var handle_event_callback,
callback_promise;
function cancelResolver() {
if ((callback_promise !== undefined) &&
(typeof callback_promise.cancel === "function")) {
callback_promise.cancel();
}
}
function canceller() {
if (handle_event_callback !== undefined) {
target.removeEventListener(type, handle_event_callback, useCapture);
}
cancelResolver();
}
function itsANonResolvableTrap(resolve, reject) {
handle_event_callback = function (evt) {
evt.stopPropagation();
if (allowDefault !== true) {
evt.preventDefault();
}
cancelResolver();
callback_promise = new RSVP.Queue()
.push(function () {
return callback(evt);
})
.push(undefined, function (error) {
if (!(error instanceof RSVP.CancellationError)) {
canceller();
reject(error);
}
});
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(itsANonResolvableTrap, canceller);
};
window.promiseEventListener = function (target, type, useCapture) {
//////////////////////////
// Resolve the promise as soon as the event is triggered
// eventListener is removed when promise is cancelled/resolved/rejected
//////////////////////////
var handle_event_callback;
function canceller() {
target.removeEventListener(type, handle_event_callback, useCapture);
}
function resolver(resolve) {
handle_event_callback = function (evt) {
canceller();
evt.stopPropagation();
evt.preventDefault();
resolve(evt);
return false;
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(resolver, canceller);
};
window.promiseReadAsText = function (file) {
return new RSVP.Promise(function (resolve, reject) {
var reader = new FileReader();
reader.onload = function (evt) {
resolve(evt.target.result);
};
reader.onerror = function (evt) {
reject(evt);
};
reader.readAsText(file);
});
};
}(window, RSVP, FileReader));
\ No newline at end of file
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
<title>Router Gadget</title> <title>Router Gadget</title>
<script src="rsvp.js"></script> <script src="rsvp.js"></script>
<script src="renderjs.js"></script> <script src="renderjs.js"></script>
<script src="gadget_global.js"></script>
<script src="gadget_router.js"></script> <script src="gadget_router.js"></script>
</head> </head>
<body> <body>
......
/*global define, App, window, RSVP, rJS */ /*global define, App, window, RSVP, rJS, loopEventListener */
/*jshint unused:false */ /*jshint unused:false */
(function (window, RSVP, rJS) { (function (window, RSVP, rJS, loopEventListener) {
'use strict'; 'use strict';
...@@ -16,66 +16,6 @@ ...@@ -16,66 +16,6 @@
} }
} }
// Return an infinite promise for event listening purposes.
// Copied directly from RenderJS implementation; don't worry about it.
function loopEventListener(
target, type, useCapture, callback, prevent_default) {
var handle_event_callback;
var callback_promise;
if (prevent_default === undefined) {
prevent_default = true;
}
function cancelResolver() {
if ((callback_promise !== undefined) &&
(typeof callback_promise.cancel === 'function')) {
callback_promise.cancel();
}
}
function canceller() {
if (handle_event_callback !== undefined) {
target.removeEventListener(
type, handle_event_callback, useCapture);
}
cancelResolver();
}
function itsANonResolvableTrap(resolve, reject) {
var result;
handle_event_callback = function (evt) {
if (prevent_default) {
evt.stopPropagation();
evt.preventDefault();
}
cancelResolver();
try {
result = callback(evt);
} catch (e) {
result = RSVP.reject(e);
}
callback_promise = result;
new RSVP.Queue()
.push(function () {
return result;
})
.push(undefined, function (error) {
if (!(error instanceof RSVP.CancellationError)) {
canceller();
reject(error);
}
});
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(itsANonResolvableTrap, canceller);
}
rJS(window) rJS(window)
// Initialize the gadget as soon as it is loaded in memory, // Initialize the gadget as soon as it is loaded in memory,
...@@ -101,4 +41,4 @@ ...@@ -101,4 +41,4 @@
// Declare an acquired method from the parent gadget to use it. // Declare an acquired method from the parent gadget to use it.
.declareAcquiredMethod('setQuery', 'setQuery'); .declareAcquiredMethod('setQuery', 'setQuery');
}(window, RSVP, rJS)); }(window, RSVP, rJS, loopEventListener));
\ No newline at end of file
...@@ -17,7 +17,8 @@ button { ...@@ -17,7 +17,8 @@ button {
-webkit-appearance: none; -webkit-appearance: none;
appearance: none; appearance: none;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-font-smoothing: antialiased;
font-smoothing: antialiased;
} }
body { body {
...@@ -29,12 +30,14 @@ body { ...@@ -29,12 +30,14 @@ body {
max-width: 550px; max-width: 550px;
margin: 0 auto; margin: 0 auto;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-font-smoothing: antialiased;
font-smoothing: antialiased;
font-weight: 300; font-weight: 300;
} }
:focus { button,
outline: 0; input[type="checkbox"] {
outline: none;
} }
.hidden { .hidden {
...@@ -90,13 +93,15 @@ body { ...@@ -90,13 +93,15 @@ body {
font-weight: inherit; font-weight: inherit;
line-height: 1.4em; line-height: 1.4em;
border: 0; border: 0;
outline: none;
color: inherit; color: inherit;
padding: 6px; padding: 6px;
border: 1px solid #999; border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
box-sizing: border-box; box-sizing: border-box;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-font-smoothing: antialiased;
font-smoothing: antialiased;
} }
.new-todo { .new-todo {
...@@ -112,32 +117,28 @@ body { ...@@ -112,32 +117,28 @@ body {
border-top: 1px solid #e6e6e6; border-top: 1px solid #e6e6e6;
} }
.toggle-all { label[for='toggle-all'] {
text-align: center; display: none;
border: none; /* Mobile Safari */
opacity: 0;
position: absolute;
} }
.toggle-all + label { .toggle-all {
position: absolute;
top: -55px;
left: -12px;
width: 60px; width: 60px;
height: 34px; height: 34px;
font-size: 0; text-align: center;
position: absolute; border: none; /* Mobile Safari */
top: -52px;
left: -13px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
} }
.toggle-all + label:before { .toggle-all:before {
content: '❯'; content: '❯';
font-size: 22px; font-size: 22px;
color: #e6e6e6; color: #e6e6e6;
padding: 10px 27px 10px 27px; padding: 10px 27px 10px 27px;
} }
.toggle-all:checked + label:before { .toggle-all:checked:before {
color: #737373; color: #737373;
} }
...@@ -165,7 +166,7 @@ body { ...@@ -165,7 +166,7 @@ body {
.todo-list li.editing .edit { .todo-list li.editing .edit {
display: block; display: block;
width: 506px; width: 506px;
padding: 12px 16px; padding: 13px 17px 12px 17px;
margin: 0 0 0 43px; margin: 0 0 0 43px;
} }
...@@ -187,27 +188,19 @@ body { ...@@ -187,27 +188,19 @@ body {
appearance: none; appearance: none;
} }
.todo-list li .toggle { .todo-list li .toggle:after {
opacity: 0; 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 + label {
/*
Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
*/
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
background-repeat: no-repeat;
background-position: center left;
} }
.todo-list li .toggle:checked + label { .todo-list li .toggle:checked:after {
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E'); 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 { .todo-list li label {
white-space: pre-line;
word-break: break-all; word-break: break-all;
padding: 15px 15px 15px 60px; padding: 15px 60px 15px 15px;
margin-left: 45px;
display: block; display: block;
line-height: 1.2; line-height: 1.2;
transition: color 0.4s; transition: color 0.4s;
...@@ -307,6 +300,7 @@ body { ...@@ -307,6 +300,7 @@ body {
border-radius: 3px; border-radius: 3px;
} }
.filters li a.selected,
.filters li a:hover { .filters li a:hover {
border-color: rgba(175, 47, 47, 0.1); border-color: rgba(175, 47, 47, 0.1);
} }
...@@ -322,6 +316,7 @@ html .clear-completed:active { ...@@ -322,6 +316,7 @@ html .clear-completed:active {
line-height: 20px; line-height: 20px;
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;
position: relative;
} }
.clear-completed:hover { .clear-completed:hover {
...@@ -363,6 +358,13 @@ html .clear-completed:active { ...@@ -363,6 +358,13 @@ html .clear-completed:active {
.todo-list li .toggle { .todo-list li .toggle {
height: 40px; height: 40px;
} }
.toggle-all {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
} }
@media (max-width: 430px) { @media (max-width: 430px) {
......
...@@ -3,61 +3,65 @@ ...@@ -3,61 +3,65 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>OfficeJS App</title> <title>TodoMVC App</title>
<link href="base.css" rel="stylesheet">
<link href="index.css" rel="stylesheet">
<script src="rsvp.js"></script> <script src="rsvp.js"></script>
<script src="renderjs.js"></script> <script src="renderjs.js"></script>
<script src="jio.js"></script> <script src="jio.js"></script>
<script src="handlebars.js"></script> <script src="handlebars.js"></script>
<script src="gadget_global.js"></script>
<script src="index.js"></script> <script src="index.js"></script>
<link href="base.css" rel="stylesheet">
<link href="index.css" rel="stylesheet"> <script id="list_template" type="text/x-handlebars-template">
<link href="manifest.json" rel="manifest"> <section id="main" class="main {{#unless todo_exists}}hidden{{/unless}}">
<label for="toggle-all" class="toggle-label">Mark all as complete</label>
<input id="toggle-all" class="toggle-all" type="checkbox" {{#if all_checked}}checked="true"{{/if}}>
<ul id="todo-list" class="todo-list"></ul>
</section>
<footer id="footer" class="footer {{#unless todo_exists}}hidden{{/unless}}">
<span id="todo-count" class="todo-count">{{todo_count}}</span>
<ul id="filters" class="filters">
<li><a href="#/">All</a></li>
<li><a href="#/active">Active</a></li>
<li><a href="#/completed">Completed</a></li>
</ul>
<button id="clear-completed" class="clear-completed {{#if all_completed}}hidden{{/if}}">Clear completed</button>
</footer>
</script>
<script id="item_template" type="text/x-handlebars-template">
<li class="todo-item {{#if this.completed}}completed{{/if}} {{#if this.editing}}editing{{/if}}"
data-jio-id="{{this.id}}">
<div class="view {{#if this.edit}}hidden{{/if}}">
<input class="toggle" type="checkbox"{{#if this.completed}} checked="true"{{/if}}>
<label class="todo-label">{{this.title}}</label>
<button class="destroy"></button>
</div>
<input class="edit{{#unless this.editing}} hidden{{/unless}}">
</li>
</script>
</head> </head>
<body> <body>
<section id="todoapp" class="todoapp">
<header id="header" class="header">
<h1>todos</h1>
<form id="todo-form">
<input id="new-todo" class="new-todo" placeholder="What needs to be done?" autofocus>
</form>
</header>
<main class="handlebars">
</main>
</section>
<footer id="info" class="info">
<p>Double-click to edit a todo</p>
</footer>
<div data-gadget-url="gadget_model.html" <div data-gadget-url="gadget_model.html"
data-gadget-scope="model" data-gadget-scope="model"
data-gadget-sandbox="public"> data-gadget-sandbox="public">
</div> </div>
<main class="handlebars">
</main>
<script class="handlebars-template" type="text/x-handlebars-template">
<section class="todoapp">
<header class="header">
<h1>todos</h1>
<form>
<input class="new-todo" placeholder="What needs to be done?" autofocus>
</form>
</header>
<section class="main {{#unless todo_exists}}hidden{{/unless}}">
<input class="toggle-all" type="checkbox" {{#if all_completed}}checked="true"{{/if}}>
<label for="toggle-all" class="toggle-label">Mark all as complete</label>
<ul class="todo-list">
{{#each todo_list}}
<li class="todo-item {{#if this.completed}}completed{{/if}} {{#if this.editing}}editing{{/if}}"
data-jio-id="{{this.id}}">
<div class="view {{#if this.edit}}hidden{{/if}}">
<input class="toggle" type="checkbox"{{#if this.completed}} checked="true"{{/if}}>
<label class="todo-label">{{this.title}}</label>
<button class="destroy"></button>
</div>
<input class="edit{{#unless this.editing}} hidden{{/unless}}">
</li>
{{/each}}
</ul>
</section>
<footer class="footer {{#unless todo_exists}}hidden{{/unless}}">
<span class="todo-count">{{todo_count}}</span>
<div class="filters">
<a href="#/" class="selected">All</a>
<a href="#/active">Active</a>
<a href="#/completed">Completed</a>
</div>
<button class="clear-completed">Clear completed</button>
</footer>
</section>
<footer class="info">
<p>Double-click to edit a todo</p>
</footer>
</script>
</body> </body>
</html> </html>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -1023,4 +1023,4 @@ define("rsvp", ...@@ -1023,4 +1023,4 @@ define("rsvp",
__exports__.reject = reject; __exports__.reject = reject;
}); });
window.RSVP = requireModule("rsvp"); window.RSVP = requireModule("rsvp");
})(window); })(window);
\ No newline at end of file
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