Commit df70c339 authored by Pascal Hartig's avatar Pascal Hartig

Merge pull request #516 from stephenplusplus/olives

Olives: Use bower components
parents 23d7c727 7d6dd975
{
"name": "todomvc-olives",
"version": "0.0.0",
"dependencies": {
"olives": "~1.4.0",
"emily": "~1.3.5",
"requirejs": "~2.1.5",
"todomvc-common": "~0.1.2"
}
}
/**
* Olives http://flams.github.com/olives
* The MIT License (MIT)
* Copyright (c) 2012-2013 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
*/
define(["Tools"], function (Tools) {
return {
/**
* Returns a NodeList including the given dom node,
* its childNodes and its siblingNodes
* @param {HTMLElement|SVGElement} dom the dom node to start with
* @param {String} query an optional CSS selector to narrow down the query
* @returns the list of nodes
*/
getNodes: function getNodes(dom, query) {
if (this.isAcceptedType(dom)) {
if (!dom.parentNode) {
document.createDocumentFragment().appendChild(dom);
}
return dom.parentNode.querySelectorAll(query || "*");
} else {
return false;
}
},
/**
* Get a domNode's dataset attribute. If dataset doesn't exist (IE)
* then the domNode is looped through to collect them.
* @param {HTMLElement|SVGElement} dom
* @returns {Object} dataset
*/
getDataset: function getDataset(dom) {
var i=0,
l,
dataset={},
split,
join;
if (this.isAcceptedType(dom)) {
if (dom.hasOwnProperty("dataset")) {
return dom.dataset;
} else {
for (l=dom.attributes.length;i<l;i++) {
split = dom.attributes[i].name.split("-");
if (split.shift() == "data") {
dataset[join = split.join("-")] = dom.getAttribute("data-"+join);
}
}
return dataset;
}
} else {
return false;
}
},
/**
* Olives can manipulate HTMLElement and SVGElements
* This function tells if an element is one of them
* @param {Element} type
* @returns true if HTMLElement or SVGElement
*/
isAcceptedType: function isAcceptedType(type) {
if (type instanceof HTMLElement ||
type instanceof SVGElement) {
return true;
} else {
return false;
}
},
/**
* Assign a new value to an Element's property. Works with HTMLElement and SVGElement.
* @param {HTMLElement|SVGElement} node the node which property should be changed
* @param {String} property the name of the property
* @param {any} value the value to set
* @returns true if assigned
*/
setAttribute: function setAttribute(node, property, value) {
if (node instanceof HTMLElement) {
node[property] = value;
return true;
} else if (node instanceof SVGElement){
node.setAttribute(property, value);
return true;
} else {
return false;
}
},
/**
* Determine if an element matches a certain CSS selector.
* @param {Element} the parent node
* @param {String} CSS selector
* @param {Element} the node to check out
* @param true if matches
*/
matches : function matches(parent, selector, node){
return Tools.toArray(this.getNodes(parent, selector)).indexOf(node) > -1;
}
};
});
/**
* Olives http://flams.github.com/olives
* The MIT License (MIT)
* Copyright (c) 2012-2013 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
*/
define(["DomUtils"],
/**
* @class
* Event plugin adds events listeners to DOM nodes.
* It can also delegate the event handling to a parent dom node
* @requires Utils
*/
function EventPlugin(Utils) {
/**
* The event plugin constructor.
* ex: new EventPlugin({method: function(){} ...}, false);
* @param {Object} the object that has the event handling methods
* @param {Boolean} $isMobile if the event handler has to map with touch events
*/
return function EventPluginConstructor($parent, $isMobile) {
/**
* The parent callback
* @private
*/
var _parent = null,
/**
* The mapping object.
* @private
*/
_map = {
"mousedown" : "touchstart",
"mouseup" : "touchend",
"mousemove" : "touchmove"
},
/**
* Is touch device.
* @private
*/
_isMobile = !!$isMobile;
/**
* Add mapped event listener (for testing purpose).
* @private
*/
this.addEventListener = function addEventListener(node, event, callback, useCapture) {
node.addEventListener(this.map(event), callback, !!useCapture);
};
/**
* Listen to DOM events.
* @param {Object} node DOM node
* @param {String} name event's name
* @param {String} listener callback's name
* @param {String} useCapture string
*/
this.listen = function listen(node, name, listener, useCapture) {
this.addEventListener(node, name, function(e){
_parent[listener].call(_parent, e, node);
}, !!useCapture);
};
/**
* Delegate the event handling to a parent DOM element
* @param {Object} node DOM node
* @param {String} selector CSS3 selector to the element that listens to the event
* @param {String} name event's name
* @param {String} listener callback's name
* @param {String} useCapture string
*/
this.delegate = function delegate(node, selector, name, listener, useCapture) {
this.addEventListener(node, name, function(event){
if (Utils.matches(node, selector, event.target)) {
_parent[listener].call(_parent, event, node);
}
}, !!useCapture);
};
/**
* Get the parent object.
* @return {Object} the parent object
*/
this.getParent = function getParent() {
return _parent;
};
/**
* Set the parent object.
* The parent object is an object which the functions are called by node listeners.
* @param {Object} the parent object
* @return true if object has been set
*/
this.setParent = function setParent(parent) {
if (parent instanceof Object){
_parent = parent;
return true;
}
return false;
};
/**
* Get event mapping.
* @param {String} event's name
* @return the mapped event's name
*/
this.map = function map(name) {
return _isMobile ? (_map[name] || name) : name;
};
/**
* Set event mapping.
* @param {String} event's name
* @param {String} event's value
* @return true if mapped
*/
this.setMap = function setMap(name, value) {
if (typeof name == "string" &&
typeof value == "string") {
_map[name] = value;
return true;
}
return false;
};
//init
this.setParent($parent);
};
});
/**
* Olives http://flams.github.com/olives
* The MIT License (MIT)
* Copyright (c) 2012-2013 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
*/
define(["Store", "Tools"],
/**
* @class
* LocalStore is an Emily's Store that can be synchronized with localStorage
* Synchronize the store, reload your page/browser and resynchronize it with the same value
* and it gets restored.
* Only valid JSON data will be stored
*/
function LocalStore(Store, Tools) {
function LocalStoreConstructor() {
/**
* The name of the property in which to store the data
* @private
*/
var _name = null,
/**
* The localStorage
* @private
*/
_localStorage = localStorage,
/**
* Saves the current values in localStorage
* @private
*/
setLocalStorage = function setLocalStorage() {
_localStorage.setItem(_name, this.toJSON());
};
/**
* Override default localStorage with a new one
* @param local$torage the new localStorage
* @returns {Boolean} true if success
* @private
*/
this.setLocalStorage = function setLocalStorage(local$torage) {
if (local$torage && local$torage.setItem instanceof Function) {
_localStorage = local$torage;
return true;
} else {
return false;
}
};
/**
* Get the current localStorage
* @returns localStorage
* @private
*/
this.getLocalStorage = function getLocalStorage() {
return _localStorage;
};
/**
* Synchronize the store with localStorage
* @param {String} name the name in which to save the data
* @returns {Boolean} true if the param is a string
*/
this.sync = function sync(name) {
var json;
if (typeof name == "string") {
_name = name;
json = JSON.parse(_localStorage.getItem(name));
Tools.loop(json, function (value, idx) {
if (!this.has(idx)) {
this.set(idx, value);
}
}, this);
setLocalStorage.call(this);
// Watch for modifications to update localStorage
this.watch("added", setLocalStorage, this);
this.watch("updated", setLocalStorage, this);
this.watch("deleted", setLocalStorage, this);
return true;
} else {
return false;
}
};
}
return function LocalStoreFactory(init) {
LocalStoreConstructor.prototype = new Store(init);
return new LocalStoreConstructor;
};
});
/**
* Olives http://flams.github.com/olives
* The MIT License (MIT)
* Copyright (c) 2012-2013 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
*/
define(["StateMachine", "Store", "Plugins", "DomUtils", "Tools"],
/**
* @class
* OObject is a container for dom elements. It will also bind
* the dom to additional plugins like Data binding
* @requires StateMachine
*/
function OObject(StateMachine, Store, Plugins, DomUtils, Tools) {
return function OObjectConstructor(otherStore) {
/**
* This function creates the dom of the UI from its template
* It then queries the dom for data- attributes
* It can't be executed if the template is not set
* @private
*/
var render = function render(UI) {
// The place where the template will be created
// is either the currentPlace where the node is placed
// or a temporary div
var baseNode = _currentPlace || document.createElement("div");
// If the template is set
if (UI.template) {
// In this function, the thisObject is the UI's prototype
// UI is the UI that has OObject as prototype
if (typeof UI.template == "string") {
// Let the browser do the parsing, can't be faster & easier.
baseNode.innerHTML = UI.template.trim();
} else if (DomUtils.isAcceptedType(UI.template)) {
// If it's already an HTML element
baseNode.appendChild(UI.template);
}
// The UI must be placed in a unique dom node
// If not, there can't be multiple UIs placed in the same parentNode
// as it wouldn't be possible to know which node would belong to which UI
// This is probably a DOM limitation.
if (baseNode.childNodes.length > 1) {
throw Error("UI.template should have only one parent node");
} else {
UI.dom = baseNode.childNodes[0];
}
UI.plugins.apply(UI.dom);
} else {
// An explicit message I hope
throw Error("UI.template must be set prior to render");
}
},
/**
* This function appends the dom tree to the given dom node.
* This dom node should be somewhere in the dom of the application
* @private
*/
place = function place(UI, place, beforeNode) {
if (place) {
// IE (until 9) apparently fails to appendChild when insertBefore's second argument is null, hence this.
beforeNode ? place.insertBefore(UI.dom, beforeNode) : place.appendChild(UI.dom);
// Also save the new place, so next renderings
// will be made inside it
_currentPlace = place;
}
},
/**
* Does rendering & placing in one function
* @private
*/
renderNPlace = function renderNPlace(UI, dom) {
render(UI);
place.apply(null, Tools.toArray(arguments));
},
/**
* This stores the current place
* If this is set, this is the place where new templates
* will be appended
* @private
*/
_currentPlace = null,
/**
* The UI's stateMachine.
* Much better than if(stuff) do(stuff) else if (!stuff and stuff but not stouff) do (otherstuff)
* Please open an issue if you want to propose a better one
* @private
*/
_stateMachine = new StateMachine("Init", {
"Init": [["render", render, this, "Rendered"],
["place", renderNPlace, this, "Rendered"]],
"Rendered": [["place", place, this],
["render", render, this]]
});
/**
* The UI's Store
* It has set/get/del/has/watch/unwatch methods
* @see Emily's doc for more info on how it works.
*/
this.model = otherStore instanceof Store ? otherStore : new Store;
/**
* The module that will manage the plugins for this UI
* @see Olives/Plugins' doc for more info on how it works.
*/
this.plugins = new Plugins();
/**
* Describes the template, can either be like "&lt;p&gt;&lt;/p&gt;" or HTMLElements
* @type string or HTMLElement|SVGElement
*/
this.template = null;
/**
* This will hold the dom nodes built from the template.
*/
this.dom = null;
/**
* Place the UI in a given dom node
* @param node the node on which to append the UI
* @param beforeNode the dom before which to append the UI
*/
this.place = function place(node, beforeNode) {
_stateMachine.event("place", this, node, beforeNode);
};
/**
* Renders the template to dom nodes and applies the plugins on it
* It requires the template to be set first
*/
this.render = function render() {
_stateMachine.event("render", this);
};
/**
* Set the UI's template from a DOM element
* @param {HTMLElement|SVGElement} dom the dom element that'll become the template of the UI
* @returns true if dom is an HTMLElement|SVGElement
*/
this.setTemplateFromDom = function setTemplateFromDom(dom) {
if (DomUtils.isAcceptedType(dom)) {
this.template = dom;
return true;
} else {
return false;
}
};
/**
* Transforms dom nodes into a UI.
* It basically does a setTemplateFromDOM, then a place
* It's a helper function
* @param {HTMLElement|SVGElement} node the dom to transform to a UI
* @returns true if dom is an HTMLElement|SVGElement
*/
this.alive = function alive(dom) {
if (DomUtils.isAcceptedType(dom)) {
this.setTemplateFromDom(dom);
this.place(dom.parentNode, dom.nextElementSibling);
return true;
} else {
return false;
}
};
/**
* Get the current dom node where the UI is placed.
* for debugging purpose
* @private
* @return {HTMLElement} node the dom where the UI is placed.
*/
this.getCurrentPlace = function(){
return _currentPlace;
};
};
});
/**
* Olives http://flams.github.com/olives
* The MIT License (MIT)
* Copyright (c) 2012-2013 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
*/
define(["OObject", "Tools"],
/**
* @class
* Place plugin places OObject in the DOM.
* @requires OObject, Tools
*/
function PlacePlugin(OObject, Tools) {
/**
* Intilialize a Place.plugin with a list of OObjects
* @param {Object} $uis a list of OObjects such as:
* {
* "header": new OObject(),
* "list": new OObject()
* }
* @Constructor
*/
return function PlacePluginConstructor($uis) {
/**
* The list of uis currently set in this place plugin
* @private
*/
var _uis = {};
/**
* Attach an OObject to this DOM element
* @param {HTML|SVGElement} node the dom node where to attach the OObject
* @param {String} the name of the OObject to attach
* @throws {NoSuchOObject} an error if there's no OObject for the given name
*/
this.place = function place(node, name) {
if (_uis[name] instanceof OObject) {
_uis[name].place(node);
} else {
throw new Error(name + " is not an OObject UI in place:"+name);
}
};
/**
* Add an OObject that can be attached to a dom element
* @param {String} the name of the OObject to add to the list
* @param {OObject} ui the OObject to add the list
* @returns {Boolean} true if the OObject was added
*/
this.set = function set(name, ui) {
if (typeof name == "string" && ui instanceof OObject) {
_uis[name] = ui;
return true;
} else {
return false;
}
};
/**
* Add multiple dom elements at once
* @param {Object} $uis a list of OObjects such as:
* {
* "header": new OObject(),
* "list": new OObject()
* }
*/
this.setAll = function setAll(uis) {
Tools.loop(uis, function (ui, name) {
this.set(name, ui);
}, this);
};
/**
* Returns an OObject from the list given its name
* @param {String} the name of the OObject to get
* @returns {OObject} OObject for the given name
*/
this.get = function get(name) {
return _uis[name];
};
this.setAll($uis);
};
});
/**
* Olives http://flams.github.com/olives
* The MIT License (MIT)
* Copyright (c) 2012-2013 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
*/
define(["Tools", "DomUtils"],
/**
* @class
* Plugins is the link between the UI and your plugins.
* You can design your own plugin, declare them in your UI, and call them
* from the template, like :
* <tag data-yourPlugin="method: param"></tag>
* @see Model-Plugin for instance
* @requires Tools
*/
function Plugins(Tools, DomUtils) {
return function PluginsConstructor($plugins) {
/**
* The list of plugins
* @private
*/
var _plugins = {},
/**
* Just a "functionalification" of trim
* for code readability
* @private
*/
trim = function trim(string) {
return string.trim();
},
/**
* Call the plugins methods, passing them the dom node
* A phrase can be :
* <tag data-plugin='method: param, param; method:param...'/>
* the function has to call every method of the plugin
* passing it the node, and the given params
* @private
*/
applyPlugin = function applyPlugin(node, phrase, plugin) {
// Split the methods
phrase.split(";")
.forEach(function (couple) {
// Split the result between method and params
var split = couple.split(":"),
// Trim the name
method = split[0].trim(),
// And the params, if any
params = split[1] ? split[1].split(",").map(trim) : [];
// The first param must be the dom node
params.unshift(node);
if (_plugins[plugin] && _plugins[plugin][method]) {
// Call the method with the following params for instance :
// [node, "param1", "param2" .. ]
_plugins[plugin][method].apply(_plugins[plugin], params);
}
});
};
/**
* Add a plugin
*
* Note that once added, the function adds a "plugins" property to the plugin.
* It's an object that holds a name property, with the registered name of the plugin
* and an apply function, to use on new nodes that the plugin would generate
*
* @param {String} name the name of the data that the plugin should look for
* @param {Object} plugin the plugin that has the functions to execute
* @returns true if plugin successfully added.
*/
this.add = function add(name, plugin) {
var that = this,
propertyName = "plugins";
if (typeof name == "string" && typeof plugin == "object" && plugin) {
_plugins[name] = plugin;
plugin[propertyName] = {
name: name,
apply: function apply() {
return that.apply.apply(that, arguments);
}
};
return true;
} else {
return false;
}
};
/**
* Add multiple plugins at once
* @param {Object} list key is the plugin name and value is the plugin
* @returns true if correct param
*/
this.addAll = function addAll(list) {
return Tools.loop(list, function (plugin, name) {
this.add(name, plugin);
}, this);
};
/**
* Get a previously added plugin
* @param {String} name the name of the plugin
* @returns {Object} the plugin
*/
this.get = function get(name) {
return _plugins[name];
};
/**
* Delete a plugin from the list
* @param {String} name the name of the plugin
* @returns {Boolean} true if success
*/
this.del = function del(name) {
return delete _plugins[name];
};
/**
* Apply the plugins to a NodeList
* @param {HTMLElement|SVGElement} dom the dom nodes on which to apply the plugins
* @returns {Boolean} true if the param is a dom node
*/
this.apply = function apply(dom) {
var nodes;
if (DomUtils.isAcceptedType(dom)) {
nodes = DomUtils.getNodes(dom);
Tools.loop(Tools.toArray(nodes), function (node) {
Tools.loop(DomUtils.getDataset(node), function (phrase, plugin) {
applyPlugin(node, phrase, plugin);
});
});
return dom;
} else {
return false;
}
};
this.addAll($plugins);
};
});
/**
* Olives http://flams.github.com/olives
* The MIT License (MIT)
* Copyright (c) 2012-2013 Olivier Scherrer <pode.fr@gmail.com> - Olivier Wietrich <olivier.wietrich@gmail.com>
*/
define(["Observable", "Tools"],
/**
* @class
* SocketIOTransport allows for client-server eventing.
* It's based on socket.io.
*/
function SocketIOTransport(Observable, Tools) {
/**
* Defines the SocketIOTransport
* @private
* @param {Object} $io socket.io's object
* @returns
*/
return function SocketIOTransportConstructor($socket) {
/**
* @private
* The socket.io's socket
*/
var _socket = null;
/**
* Set the socket created by SocketIO
* @param {Object} socket the socket.io socket
* @returns true if it seems to be a socket.io socket
*/
this.setSocket = function setSocket(socket) {
if (socket && typeof socket.emit == "function") {
_socket = socket;
return true;
} else {
return false;
}
};
/**
* Get the socket, for debugging purpose
* @private
* @returns {Object} the socket
*/
this.getSocket = function getSocket() {
return _socket;
},
/**
* Subscribe to a socket event
* @param {String} event the name of the event
* @param {Function} func the function to execute when the event fires
*/
this.on = function on(event, func) {
return _socket.on(event, func);
},
/**
* Subscribe to a socket event but disconnect as soon as it fires.
* @param {String} event the name of the event
* @param {Function} func the function to execute when the event fires
*/
this.once = function once(event, func) {
return _socket.once(event, func);
};
/**
* Publish an event on the socket
* @param {String} event the event to publish
* @param data
* @param {Function} callback is the function to be called for ack
*/
this.emit = function emit(event, data, callback) {
return _socket.emit(event, data, callback);
};
/**
* Stop listening to events on a channel
* @param {String} event the event to publish
* @param data
* @param {Function} callback is the function to be called for ack
*/
this.removeListener = function removeListener(event, data, callback) {
return _socket.removeListener(event, data, callback);
};
/**
* Make a request on the node server
* @param {String} channel watch the server's documentation to see available channels
* @param data the request data, it could be anything
* @param {Function} func the callback that will get the response.
* @param {Object} scope the scope in which to execute the callback
*/
this.request = function request(channel, data, func, scope) {
if (typeof channel == "string"
&& typeof data != "undefined") {
var reqData = {
eventId: Date.now() + Math.floor(Math.random()*1e6),
data: data
},
boundCallback = function () {
func && func.apply(scope || null, arguments);
};
this.once(reqData.eventId, boundCallback);
this.emit(channel, reqData);
return true;
} else {
return false;
}
};
/**
* Listen to an url and get notified on new data
* @param {String} channel watch the server's documentation to see available channels
* @param data the request data, it could be anything
* @param {Function} func the callback that will get the data
* @param {Object} scope the scope in which to execute the callback
* @returns
*/
this.listen = function listen(channel, data, func, scope) {
if (typeof channel == "string"
&& typeof data != "undefined"
&& typeof func == "function") {
var reqData = {
eventId: Date.now() + Math.floor(Math.random()*1e6),
data: data,
keepAlive: true
},
boundCallback = function () {
func && func.apply(scope || null, arguments);
},
that = this;
this.on(reqData.eventId, boundCallback);
this.emit(channel, reqData);
return function stop() {
that.emit("disconnect-" + reqData.eventId);
that.removeListener(reqData.eventId, boundCallback);
};
} else {
return false;
}
};
/**
* Sets the socket.io
*/
this.setSocket($socket);
};
});
html,
body {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
color: inherit;
-webkit-appearance: none;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea url('bg.png');
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#todoapp {
background: #fff;
background: rgba(255, 255, 255, 0.9);
margin: 130px 0 40px 0;
border: 1px solid #ccc;
position: relative;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
#todoapp:before {
content: '';
border-left: 1px solid #f5d6d6;
border-right: 1px solid #f5d6d6;
width: 2px;
position: absolute;
top: 0;
left: 40px;
height: 100%;
}
#todoapp input::-webkit-input-placeholder {
font-style: italic;
}
#todoapp input:-moz-placeholder {
font-style: italic;
color: #a9a9a9;
}
#todoapp h1 {
position: absolute;
top: -120px;
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
color: #b3b3b3;
color: rgba(255, 255, 255, 0.3);
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
-ms-text-rendering: optimizeLegibility;
-o-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
#header {
padding-top: 15px;
border-radius: inherit;
}
#header:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
z-index: 2;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));
background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -moz-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -o-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
border-top-left-radius: 1px;
border-top-right-radius: 1px;
}
#new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: 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);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
#new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.02);
z-index: 2;
box-shadow: none;
}
#main {
position: relative;
z-index: 2;
border-top: 1px dotted #adadad;
}
label[for='toggle-all'] {
display: none;
}
#toggle-all {
position: absolute;
top: -42px;
left: -4px;
width: 40px;
text-align: center;
border: none; /* Mobile Safari */
}
#toggle-all:before {
content: '»';
font-size: 28px;
color: #d9d9d9;
padding: 0 25px 7px;
}
#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 dotted #ccc;
}
#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;
/*-moz-appearance: none;*/
-ms-appearance: none;
-o-appearance: none;
appearance: none;
}
#todo-list li .toggle:after {
content: '✔';
line-height: 43px; /* 40 + a couple of pixels visual adjustment */
font-size: 20px;
color: #d9d9d9;
text-shadow: 0 -1px 0 #bfbfbf;
}
#todo-list li .toggle:checked:after {
color: #85ada7;
text-shadow: 0 1px 0 #669991;
bottom: 1px;
position: relative;
}
#todo-list li label {
word-break: break-word;
padding: 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
-webkit-transition: color 0.4s;
-moz-transition: color 0.4s;
-ms-transition: color 0.4s;
-o-transition: color 0.4s;
transition: color 0.4s;
}
#todo-list li.completed label {
color: #a9a9a9;
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: 22px;
color: #a88a8a;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-ms-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
}
#todo-list li .destroy:hover {
text-shadow: 0 0 1px #000,
0 0 10px rgba(199, 107, 107, 0.8);
-webkit-transform: scale(1.3);
-moz-transform: scale(1.3);
-ms-transform: scale(1.3);
-o-transform: scale(1.3);
transform: scale(1.3);
}
#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: 0 15px;
position: absolute;
right: 0;
bottom: -31px;
left: 0;
height: 20px;
z-index: 1;
text-align: center;
}
#footer:before {
content: '';
position: absolute;
right: 0;
bottom: 31px;
left: 0;
height: 50px;
z-index: -1;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
0 6px 0 -3px rgba(255, 255, 255, 0.8),
0 7px 1px -3px rgba(0, 0, 0, 0.3),
0 43px 0 -6px rgba(255, 255, 255, 0.8),
0 44px 2px -6px rgba(0, 0, 0, 0.2);
}
#todo-count {
float: left;
text-align: left;
}
#filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
#filters li {
display: inline;
}
#filters li a {
color: #83756f;
margin: 2px;
text-decoration: none;
}
#filters li a.selected {
font-weight: bold;
}
#clear-completed {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
background: rgba(0, 0, 0, 0.1);
font-size: 11px;
padding: 0 10px;
border-radius: 3px;
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
}
#clear-completed:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
#info {
margin: 65px auto 0;
color: #a6a6a6;
font-size: 12px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
text-align: center;
}
#info a {
color: inherit;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox and Opera
*/
@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 {
top: -56px;
left: -15px;
width: 65px;
height: 41px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
.hidden{
display:none;
}
(function () {
'use strict';
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'));
}
function getSourcePath() {
// If accessed via addyosmani.github.com/todomvc/, strip the project
// path.
if (location.hostname.indexOf('github.com') > 0) {
return location.pathname.replace(/todomvc\//, '');
}
return location.pathname;
}
function appendSourceLink() {
var sourceLink = document.createElement('a');
var paragraph = document.createElement('p');
var footer = document.getElementById('info');
var urlBase = 'https://github.com/addyosmani/todomvc/tree/gh-pages';
if (footer) {
sourceLink.href = urlBase + getSourcePath();
sourceLink.appendChild(document.createTextNode('Check out the source'));
paragraph.appendChild(sourceLink);
footer.appendChild(paragraph);
}
}
function redirect() {
if (location.hostname === 'addyosmani.github.com') {
location.href = location.href.replace('addyosmani.github.com/todomvc',
'todomvc.com');
}
}
appendSourceLink();
redirect();
})();
......@@ -4,11 +4,8 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Olives • TodoMVC</title>
<link rel="stylesheet" href="../../../assets/base.css">
<link rel="stylesheet" href="components/todomvc-common/base.css">
<link rel="stylesheet" href="css/app.css">
<!--[if IE]>
<script src="../../../assets/ie.js"></script>
<![endif]-->
</head>
<body>
<section id="todoapp">
......@@ -42,10 +39,10 @@
<p>Created by <a href="http://github.com/podefr">Olivier Scherrer</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<script src="../../../assets/base.js"></script>
<script src="js/lib/require.js"></script>
<script src="js/lib/Emily.js"></script>
<script src="js/lib/Olives.js"></script>
<script src="components/todomvc-common/base.js"></script>
<script src="components/requirejs/require.js"></script>
<script src="components/emily/build/Emily.js"></script>
<script src="components/olives/build/Olives.js"></script>
<script src="js/lib/Tools.js"></script>
<script src="js/uis/Input.js"></script>
<script src="js/uis/List.js"></script>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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