Skip to content

Commit

Permalink
partial rewrite. More modular. Added o_O.object. Better testing
Browse files Browse the repository at this point in the history
  • Loading branch information
weepy committed Feb 14, 2012
1 parent 26fdc34 commit b84bfbd
Show file tree
Hide file tree
Showing 31 changed files with 1,493 additions and 9,903 deletions.
22 changes: 22 additions & 0 deletions Makefile
@@ -0,0 +1,22 @@
TESTS = test/*.js
UGLIFY = $(shell find node_modules -name "uglifyjs" -type f)

all: o_O.min.js

test:
@./node_modules/.bin/mocha \
$(TESTS)

o_O.js:
@node bin/build.js $^

o_O.min.js: o_O.js
@$(UGLIFY) $< > $@ \
&& du o_O.min.js \
&& du o_O.js

clean:
rm -f o_O.js
rm -f o_O.min.js

.PHONY: test clean
File renamed without changes.
8 changes: 8 additions & 0 deletions bin/build.js
@@ -0,0 +1,8 @@
var files = ["header", "o_O", "eventize", "property", "binding", "helpers", "bindings", "klass", "collection"]
var fs = require("fs")

var js = files.map(function(file) {
return fs.readFileSync("./lib/" + file + ".js")
})

fs.writeFileSync("o_O.js", "!function() {\n\n" + js.join("\n\n") + "\n\n}();")
78 changes: 0 additions & 78 deletions examples/_random.html

This file was deleted.

1 change: 0 additions & 1 deletion examples/todos/README.md

This file was deleted.

12 changes: 6 additions & 6 deletions examples/todos/index.html
Expand Up @@ -11,24 +11,24 @@ <h1>Todos</h1>
</div>
<div class="content">
<div id="create-todo">
<input id="new-todo" bind="val: current(); keyup: o_O.val(current); enterKey: add" placeholder="What needs to be done?" />
<input id="new-todo" bind="val: current(); keyup: o_O.value(current); enterKey: add" placeholder="What needs to be done?" />
<span class="ui-tooltip-top" bind="visible: showTooltip()" style="display: none;">Press Enter to save this task</span>
</div>
<div id="todos">
<div bind="visible: todos.count()">
<input id="check-all" class="check" type="checkbox" bind="val: allCompleted" />
<input id="check-all" class="check" type="checkbox" bind="value: allCompleted" />
<label for="check-all">Mark all as complete</label>
</div>
<ul id="todo-list" bind="foreach: todos">
<li bind="class: editing() && 'editing' " >
<div bind="class: 'todo ' + (done() && 'done') " >
<div bind="class: 'todo' + (done() ? ' done' : '')" >
<div class="display">
<input class="check" type="checkbox" id="checkbox" bind="value: done" />
<div class="todo-content" bind="text: content(); dblclick: edit" style="cursor: pointer;"></div>
<span class="todo-destroy" bind="click: (remove)"></span>
<div class="todo-content" bind="text: content();" style="cursor: pointer;"></div>
<span class="todo-destroy" bind="click: remove"></span>
</div>
<div class="edit">
<input class="todo-input" bind="val: content(); keyup: o_O.val(content); enterKey: stopEditing; blur: stopEditing"/>
<input class="todo-input" bind="val: content(); keyup: o_O.value(content); enterKey: stopEditing; blur: stopEditing"/>
</div>
</div>
</li>
Expand Down
47 changes: 25 additions & 22 deletions examples/todos/js/todos.js
@@ -1,9 +1,9 @@
(function() {
//a custom binding to handle the enter key (could go in a separate library)
o_O.bindings.enterKey = function(func) {
this.$.keyup(function(e) {
o_O.bindings.enterKey = function(func, $el) {
$el.keyup(function(e) {
if(e.keyCode === 13)
func()
func.call(this)
})
}

Expand All @@ -14,12 +14,16 @@
this.editing = o_O.property(false);

var self = this
this.edit = o_O.property(function() {
this.edit = function() {
self.editing(true);
})
}
};
window.Todo = Todo

Todo.prototype.stopEditing = function() { this.editing(false); }

Todo.prototype.stopEditing = function() {
this.editing(false);
}

Todo.prototype.remove = function() {
this.parent.remove(this)
Expand All @@ -32,8 +36,11 @@
self.todos = o_O.collection(todos)

//store the new todo value being entered
self.current = o_O.property();
self.current = o_O.property("");

// self.current.change(function(x) {
// console.log(this, x)
// })
//add a new todo, when enter key is pressed
self.add = function () {
var newTodo = new Todo(self.current());
Expand All @@ -60,7 +67,9 @@
}).length
})

self.todos.on('change:done', function(object, val) {
self.todos.on('change', function(object, propery, val, old) {
if(propery != 'done') return

self.completedCount.change()
self.remainingCount.change()
})
Expand All @@ -71,19 +80,12 @@
})

//writeable computed observable to handle marking all complete/incomplete
self.allCompleted = o_O.property({
//always return true/false based on the done flag of all todos
read: function() {
return !self.remainingCount();
},
//set all todos to the written value (true/false)
write: function(newValue) {
ko.utils.arrayForEach(self.todos, function(todo) {
//set even if value is the same, as subscribers are not notified in that case
todo.done(newValue);
});
}
});
self.allCompleted = o_O.property(function(v) {
if(v === undefined) return !self.remainingCount()
self.todos.each(function(todo) {
todo.done(v);
})
})

//track whether the tooltip should be shown
self.showTooltip = o_O.property(false);
Expand Down Expand Up @@ -113,5 +115,6 @@
// TODO: Storage
};

o_O.bind(new ViewModel([]), '#todoapp')
window.view = new ViewModel([])
o_O.bind(view, '#todoapp')
})();
98 changes: 98 additions & 0 deletions lib/binding.js
@@ -0,0 +1,98 @@
o_O.expression = function(text) {
o_O.expression.last = text // useful for catching syntax errors if this breaks
return new Function('o_O', 'with(this) { { return (' + text + ')} } ')
}


/*
* calculates the dependencies
* calls the callback with the result
* if running fn returns a function - nothing more happens
* otherwise the callback is called with the function result everytime a dependency changes
*/

o_O.bindFunction = function(fn, callback) {
var deps = o_O.dependencies(fn)
var result = o_O.dependencies.lastResult
var isEvent = typeof result == 'function'
callback(result)

// if this is an event watch for changes and reapply
if(!isEvent) {
forEach(deps, function(dep) {
dep.on('set', function(value) {
callback(fn())
})
})
}
}


o_O.bindElementToRule = function(el, attr, expr, context) {
var expression = o_O.expression(expr)

var trigger = function() {
return expression.call(context, o_O.helpers)
}

o_O.bindFunction(trigger, function(x) {
var y = typeof x == 'function' && !o_O.property.is(x)
? function(e) { return x.call(context, e) }
: x
return o_O.bindings[attr].call(context, y, $(el))
})

}



function extractRules (str) {
var rules = trim(str).split(";")
var ret = []
for(var i=0; i <rules.length; i++) {
var rule = rules[i]
rule = trim(rule)
if(!rule) continue // for trailing ;
var bits = trim(rule).split(":").map(trim)
var attr = trim(bits.shift())
var param = trim(bits.join(":"))

ret.push([attr, param])
}
return ret
}

o_O.bind = function(context, dom) {
var $el = $(dom)
context.el = $el[0]

function bind(el, k, v) {
var $$ = $(el)

var rules = extractRules($$.attr("bind"))

for(var i=0; i <rules.length; i++) {
var rule = rules[i]
o_O.bindElementToRule($$, rule[0], rule[1], context)
}
$$.attr("bind",null)
}

// lets do foreach first
$(dom).filter("[bind^=foreach]").each(function(k, v) {
bind(this, k, v)
})

$(dom).find("[bind^=foreach]").each(function(k, v) {
bind(this, k, v)
})

$(dom).filter("[bind]").each(function(k, v) {
bind(this, k, v)
})

$(dom).find("[bind]").each(function(k, v) {
bind(this, k, v)
})

}

0 comments on commit b84bfbd

Please sign in to comment.