forked from Automattic/kue
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
386 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,386 @@ | ||
|
||
/*! | ||
* EventEmitter | ||
* Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> | ||
* MIT Licensed | ||
*/ | ||
|
||
/** | ||
* EventEmitter. | ||
*/ | ||
|
||
function EventEmitter() { | ||
this.callbacks = {}; | ||
} | ||
|
||
/** | ||
* Listen on the given `event` with `fn`. | ||
* | ||
* @param {String} event | ||
* @param {Function} fn | ||
*/ | ||
|
||
EventEmitter.prototype.on = function(event, fn){ | ||
(this.callbacks[event] = this.callbacks[event] || []) | ||
.push(fn); | ||
return this; | ||
}; | ||
|
||
/** | ||
* Emit `event` with the given args. | ||
* | ||
* @param {String} event | ||
* @param {Mixed} ... | ||
*/ | ||
|
||
EventEmitter.prototype.emit = function(event){ | ||
var args = Array.prototype.slice.call(arguments, 1) | ||
, callbacks = this.callbacks[event]; | ||
|
||
if (callbacks) { | ||
for (var i = 0, len = callbacks.length; i < len; ++i) { | ||
callbacks[i].apply(this, args) | ||
} | ||
} | ||
|
||
return this; | ||
}; | ||
|
||
/*! | ||
* caustic | ||
* Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca> | ||
* MIT Licensed | ||
*/ | ||
|
||
// TODO: `make caustic.js` should wrap in an anonymous function | ||
// TODO: `make caustic.min.js` | ||
|
||
// TODO: compile sub-views such as User etc based on the given | ||
// html, as there's no need to keep traversing each time. | ||
|
||
/** | ||
* Convert callback `fn` to a function when a string is given. | ||
* | ||
* @param {Type} name | ||
* @return {Type} | ||
* @api private | ||
*/ | ||
|
||
function callback(fn) { | ||
return 'string' == typeof fn | ||
? function(obj){ return obj[fn](); } | ||
: fn; | ||
} | ||
|
||
/** | ||
* Initialize a new view with the given `name` | ||
* or string of html. When a `name` is given an element | ||
* with the id `name + "-template"` will be used. | ||
* | ||
* Examples: | ||
* | ||
* var user = new View('user'); | ||
* var list = new View('<ul class="list"><li></li></ul>'); | ||
* | ||
* @param {String} name | ||
* @api public | ||
*/ | ||
|
||
function View(name) { | ||
if (!(this instanceof View)) return new View(name); | ||
EventEmitter.call(this); | ||
var html; | ||
if (~name.indexOf('<')) html = name; | ||
else html = $('#' + name + '-template').html(); | ||
this.el = $(html); | ||
this.visit(this.el); | ||
} | ||
|
||
/** | ||
* Inherit from `EventEmitter.prototype`. | ||
*/ | ||
|
||
View.prototype.__proto__ = EventEmitter.prototype; | ||
|
||
/** | ||
* Visit `el`. | ||
* | ||
* @param {jQuery} el | ||
* @param {Boolean} ignore | ||
* @api private | ||
*/ | ||
|
||
View.prototype.visit = function(el, ignore){ | ||
var self = this | ||
, type = el.get(0).nodeName | ||
, classes = el.attr('class').split(/ +/) | ||
, method = 'visit' + type; | ||
|
||
if (this[method] && !ignore) this[method](el, classes[0]); | ||
|
||
el.children().each(function(i, el){ | ||
self.visit($(el)); | ||
}); | ||
}; | ||
|
||
/** | ||
* Visit INPUT tag. | ||
* | ||
* @param {jQuery} el | ||
* @api public | ||
*/ | ||
|
||
View.prototype.visitINPUT = function(el){ | ||
var self = this | ||
, name = el.attr('name') | ||
, type = el.attr('type'); | ||
|
||
switch (type) { | ||
case 'text': | ||
this[name] = function(val){ | ||
if (0 == arguments.length) return el.val(); | ||
el.val(val); | ||
return this; | ||
} | ||
|
||
this[name].isEmpty = function(){ | ||
return '' == el.val(); | ||
}; | ||
|
||
this[name].clear = function(){ | ||
el.val(''); | ||
return self; | ||
}; | ||
break; | ||
case 'checkbox': | ||
this[name] = function(val){ | ||
if (0 == arguments.length) return el.attr('checked'); | ||
switch (typeof val) { | ||
case 'function': | ||
el.change(function(e){ | ||
val.call(self, el.attr('checked'), e); | ||
}); | ||
break; | ||
default: | ||
el.attr('checked', val | ||
? 'checked' | ||
: val); | ||
} | ||
return this; | ||
} | ||
break; | ||
} | ||
}; | ||
|
||
/** | ||
* Visit FORM. | ||
* | ||
* @param {jQuery} el | ||
* @api private | ||
*/ | ||
|
||
View.prototype.visitFORM = function(el, name){ | ||
var self = this; | ||
this.submit = function(val){ | ||
switch (typeof val) { | ||
case 'function': | ||
el.submit(function(e){ | ||
val.call(self, e, el); | ||
return false; | ||
}); | ||
break; | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Visit A tag. | ||
* | ||
* @param {jQuery} el | ||
* @api private | ||
*/ | ||
|
||
View.prototype.visitA = function(el, name){ | ||
var self = this; | ||
|
||
el.click(function(e){ | ||
self.emit(name, e, el); | ||
}); | ||
|
||
this[name] = function(fn){ | ||
el.click(function(e){ | ||
fn.call(self, e, el); | ||
return false; | ||
}); | ||
return this; | ||
} | ||
}; | ||
|
||
/** | ||
* Visit P, TD, SPAN, or DIV tag. | ||
* | ||
* @param {jQuery} el | ||
* @api private | ||
*/ | ||
|
||
View.prototype.visitP = | ||
View.prototype.visitTD = | ||
View.prototype.visitSPAN = | ||
View.prototype.visitDIV = function(el, name){ | ||
var self = this; | ||
this[name] = function(val){ | ||
if (0 == arguments.length) return el; | ||
el.empty().append(val.el || val); | ||
return this; | ||
}; | ||
}; | ||
|
||
/** | ||
* Visit UL tag. | ||
* | ||
* @param {jQuery} el | ||
* @api private | ||
*/ | ||
|
||
View.prototype.visitUL = function(el, name){ | ||
var self = this; | ||
this.children = []; | ||
|
||
this[name] = el; | ||
|
||
// TODO: move these out | ||
|
||
/** | ||
* Add `val` to this list. | ||
* | ||
* @param {String|jQuery|View} val | ||
* @return {View} for chaining | ||
* @api public | ||
*/ | ||
|
||
el.add = function(val){ | ||
var li = $('<li>'); | ||
self.children.push(val); | ||
el.append(li.append(val.el || val)); | ||
return this; | ||
}; | ||
|
||
/** | ||
* Return the list item `View`s as an array. | ||
* | ||
* @return {Array} | ||
* @api public | ||
*/ | ||
|
||
el.items = function(){ | ||
return self.children; | ||
}; | ||
|
||
/** | ||
* Iterate the list `View`s, calling `fn(item, i)`. | ||
* | ||
* @param {Function} fn | ||
* @return {View} for chaining | ||
* @api public | ||
*/ | ||
|
||
el.each = function(fn){ | ||
for (var i = 0, len = self.children.length; i < len; ++i) { | ||
fn(self.children[i], i); | ||
} | ||
return this; | ||
}; | ||
|
||
/** | ||
* Map the list `View`s, calling `fn(item, i)`. | ||
* | ||
* @param {String|function} fn | ||
* @return {Array} | ||
* @api public | ||
*/ | ||
|
||
el.map = function(fn){ | ||
var ret = [] | ||
, fn = callback(fn); | ||
|
||
for (var i = 0, len = self.children.length; i < len; ++i) { | ||
ret.push(fn(self.children[i], i)); | ||
} | ||
|
||
return ret; | ||
}; | ||
}; | ||
|
||
/** | ||
* Visit TABLE. | ||
* | ||
* @param {jQuery} el | ||
* @api private | ||
*/ | ||
|
||
View.prototype.visitTABLE = function(el, name){ | ||
this[name] = el; | ||
|
||
this[name].add = function(val){ | ||
this.append(val.el || val); | ||
}; | ||
}; | ||
|
||
/** | ||
* Visit CANVAS. | ||
* | ||
* @param {jQuery} el | ||
* @api private | ||
*/ | ||
|
||
View.prototype.visitCANVAS = function(el, name){ | ||
this[name] = el.get(0); | ||
}; | ||
|
||
/** | ||
* Visit H1-H5 tags. | ||
* | ||
* @param {jQuery} el | ||
* @api private | ||
*/ | ||
|
||
View.prototype.visitH1 = | ||
View.prototype.visitH2 = | ||
View.prototype.visitH3 = | ||
View.prototype.visitH4 = | ||
View.prototype.visitH5 = function(el, name){ | ||
var self = this; | ||
this[name] = function(val){ | ||
if (0 == arguments.length) return el.text(); | ||
el.text(val.el || val); | ||
return this; | ||
}; | ||
}; | ||
|
||
/** | ||
* Remove the view from the DOM. | ||
* | ||
* @return {View} | ||
* @api public | ||
*/ | ||
|
||
View.prototype.remove = function(){ | ||
var parent = this.el.parent() | ||
, type = parent.get(0).nodeName; | ||
if ('LI' == type) parent.remove(); | ||
else this.el.remove(); | ||
return this; | ||
}; | ||
|
||
/** | ||
* Append this view's element to `val`. | ||
* | ||
* @param {String|jQuery} val | ||
* @return {View} | ||
* @api public | ||
*/ | ||
|
||
View.prototype.appendTo = function(val){ | ||
this.el.appendTo(val.el || val); | ||
return this; | ||
}; |