Commit 410a831f authored by Sindre Sorhus's avatar Sindre Sorhus

Merge pull request #405 from bitovi/canjs-1.1.3-require

Canjs 1.1.3 + RequireJS
parents 6dd68ec0 c9a105e0
......@@ -70,7 +70,7 @@
<a href="architecture-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>
<li class="routing">
<a href="architecture-examples/canjs/" data-source="http://canjs.us" data-content="CanJS with jQuery (includes a jQuery UI widget binding example). CanJS is a client-side, JavaScript framework that makes building rich web applications easy. It provides can.Model (for connecting to RESTful JSON interfaces), can.View (for template loading and caching), can.Observe (for key-value binding), can.EJS (live binding templates), can.Control (declarative event bindings) and can.route (routing support).">CanJS</a>
<a href="architecture-examples/canjs/" data-source="http://canjs.us" data-content="CanJS with jQuery. CanJS is a client-side, JavaScript framework that makes building rich web applications easy. It provides can.Model (for connecting to RESTful JSON interfaces), can.View (for template loading and caching), can.Observe (for key-value binding), can.EJS (live binding templates), can.Control (declarative event bindings) and can.route (routing support).">CanJS</a>
</li>
<li class="labs">
<a href="labs/architecture-examples/maria/src/" data-source="https://github.com/petermichaux/maria" data-content="An MVC framework for JavaScript applications. The real MVC. The Smalltalk MVC. The Gang of Four MVC. The three core design patterns of MVC (observer, composite, and strategy) are embedded in Maria's Model, View, and Controller objects. Other patterns traditionally included in MVC implementations (e.g. factory method and template) make appearances too.">Maria</a>
......@@ -178,6 +178,9 @@
<li class="routing labs">
<a href="labs/dependency-examples/angularjs_require/" data-source="http://angularjs.org" data-content="What HTML would have been had it been designed for web apps. This is an example of using it with AMD modules.">AngularJS + RequireJS</a>
</li>
<li class="routing labs">
<a href="labs/dependency-examples/canjs_require/" data-source="http://canjs.us" data-content="CanJS is a client-side, JavaScript framework that makes building rich web applications easy. The AMD version lets you use the framework in a fully modular fashion and will only what you actually need.">CanJS + RequireJS</a>
</li>
<li class="routing labs">
<a href="labs/architecture-examples/troopjs/" data-source="https://github.com/troopjs/" data-content="TroopJS attempts to package popular front-end technologies and bind them with minimal effort for the developer. It includes jQuery for DOM manipulation, ComposeJS for object composition, RequireJS for modularity and Has.js for feature detection. On top, it includes Pub/Sub support, templating, weaving (widgets to DOM) and auto-wiring.">TroopJS</a>
</li>
......
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>CanJS + RequireJS • TodoMVC</title>
<link rel="stylesheet" href="../../../assets/base.css">
</head>
<body>
<section id="todoapp">
</section>
<div id="info">
<p>Double-click to edit a todo</p>
<p>Written by <a href="http://bitovi.com">Bitovi</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</div>
<script src="../../../assets/base.js"></script>
<!--[if IE]>
<script src="../../../assets/ie.js"></script>
<![endif]-->
<script data-main="js/app" src="../../../assets/require.min.js"></script>
</body>
</html>
/*global require*/
require.config({
paths: {
jquery: '../../../../assets/jquery.min',
can: 'lib/can'
}
});
require(['can/util/library', 'can/route', 'app/todos', 'app/models/todo', 'can/view/ejs', 'can/view/mustache'],
function (can, route, Todos, Model) {
'use strict';
// Set up a route that maps to the `filter` attribute
route(':filter');
// Delay routing until we initialized everything
route.ready(false);
// View helper for pluralizing strings
can.Mustache.registerHelper('plural', function (str, count) {
return str + (count !== 1 ? 's' : '');
});
// Find all Todos
Model.findAll({}, function (todos) {
// Wire it up. Instantiate a new Todos control
new Todos('#todoapp', {
// The (Todo) model that the control should use
Model: Model,
// The list of Todos retrieved from the model
todos: todos,
// The control state for filtering the view (in our case the router)
state: can.route,
// The view to render
view: 'views/todos.mustache'
});
});
// Now we can start routing
route.ready(true);
});
\ No newline at end of file
/*global define*/
define(['can/util/library', 'can/model'], function (can, Model) {
'use strict';
var LocalStorage = Model({
// Implement local storage handling
localStore: function (cb) {
var name = this.name,
data = JSON.parse(window.localStorage[name] || (window.localStorage[name] = '[]')),
res = cb.call(this, data);
if (res !== false) {
can.each(data, function (todo) {
delete todo.editing;
});
window.localStorage[name] = JSON.stringify(data);
}
},
findAll: function () {
var def = new can.Deferred();
this.localStore(function (todos) {
var instances = [],
self = this;
can.each(todos, function (todo) {
instances.push(new self(todo));
});
def.resolve({data: instances});
});
return def;
},
destroy: function (id) {
var def = new can.Deferred();
this.localStore(function (todos) {
for (var i = 0; i < todos.length; i++) {
if (todos[i].id === id) {
todos.splice(i, 1);
break;
}
}
def.resolve({});
});
return def;
},
create: function (attrs) {
var def = new can.Deferred();
this.localStore(function (todos) {
attrs.id = attrs.id || parseInt(100000 * Math.random(), 10);
todos.push(attrs);
});
def.resolve({id: attrs.id});
return def;
},
update: function (id, attrs) {
var def = new can.Deferred(), todo;
this.localStore(function (todos) {
for (var i = 0; i < todos.length; i++) {
if (todos[i].id === id) {
todo = todos[i];
break;
}
}
can.extend(todo, attrs);
});
def.resolve({});
return def;
}
}, {});
return LocalStorage;
});
\ No newline at end of file
/*global define*/
define(['can/util/library', 'can/observe', 'app/models/localstorage'], function (can, Observe, LocalStorage) {
'use strict';
// Basic Todo entry model
// { text: 'todo', complete: false }
var Todo = LocalStorage({
storageName: 'todos-canjs-requirejs'
}, {
// Returns if this instance matches a given filter
// (currently `active` and `complete`)
matches: function (state) {
return !state || (state === 'active' && !this.attr('complete')) ||
(state === 'completed' && this.attr('complete'));
}
});
// Extend the existing Todo.List to add some helper methods
Todo.List = Todo.List({
completed: function () {
var completed = 0;
this.each(function (todo) {
completed += todo.attr('complete') ? 1 : 0;
});
return completed;
},
remaining: function () {
return this.attr('length') - this.completed();
},
allComplete: function () {
return this.attr('length') === this.completed();
},
// Returns a new can.Observe.List that contains only the Todos
// matching the current filter
byFilter: function(filter) {
var filtered = new Observe.List();
can.each(this, function(todo) {
if(todo.matches(filter)) {
filtered.push(todo);
}
});
return filtered;
},
// Returns the list to display based on the currently set `filter`
displayList: function() {
return this.byFilter(this.attr('filter'));
}
});
return Todo;
});
/*global define*/
define(['can/util/library', 'can/control'], function (can, Control) {
'use strict';
var ENTER_KEY = 13;
var Todos = Control({
// Default options
defaults: {
view: 'views/todos.ejs'
}
}, {
// Initialize the Todos list
init: function () {
// Render the Todos we passed in the options
this.element.append(can.view(this.options.view, {
todos: this.options.todos
}));
},
// Listen for when a new Todo has been entered
'#new-todo keyup': function (el, e) {
var value = can.trim(el.val());
if (e.which === ENTER_KEY && value !== '') {
// Create a new Model which was passed as an option when initializing the control
new this.options.Model({
text: value,
complete: false
}).save(function () {
el.val('');
});
}
},
// Handle a newly created Todo (`Model` that was passed when initializing this Control)
'{Model} created': function (list, e, item) {
this.options.todos.push(item);
// Reset the filter so that you always see your new todo
this.options.state.attr('filter', '');
},
// Listener for when the filter observe
'{state} filter': function (state, event, filter) {
// Update the filter of our Todo list
this.options.todos.attr('filter', filter || '');
// Remove the `selected` class from the old link and add it to the link for the current location hash
this.element.find('#filters a').removeClass('selected').filter('[href="' + window.location.hash + '"]')
.addClass('selected');
},
// Listen for editing a Todo
'.todo dblclick': function (el) {
el.data('todo').attr('editing', true).save(function () {
el.children('.edit').focus();
});
},
// Update a todo
updateTodo: function (el) {
var value = can.trim(el.val());
var todo = el.closest('.todo').data('todo');
// If we don't have a todo we don't need to do anything
if (!todo) {
return;
}
if (value === '') {
todo.destroy();
} else {
todo.attr({
editing: false,
text: value
}).save();
}
},
// Listen for an edited Todo
'.todo .edit keyup': function (el, e) {
if (e.which === ENTER_KEY) {
this.updateTodo(el);
}
},
'.todo .edit focusout': 'updateTodo',
// Listen for the toggled completion of a Todo
'.todo .toggle click': function (el) {
el.closest('.todo').data('todo')
.attr('complete', el.is(':checked'))
.save();
},
// Listen for a removed Todo
'.todo .destroy click': function (el) {
el.closest('.todo').data('todo').destroy();
},
// Listen for toggle all completed Todos
'#toggle-all click': function (el) {
var toggle = el.prop('checked');
can.each(this.options.todos, function (todo) {
todo.attr('complete', toggle).save();
});
},
// Listen for removing all completed Todos
'#clear-completed click': function () {
can.each(this.options.todos.byFilter('completed'), function (todo) {
todo.destroy();
});
}
});
return Todos;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/library', 'can/control', 'can/model', 'can/view/ejs', 'can/route'], function (can) {
return can;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/string'], function (can) {
// ## construct.js
// `can.Construct`
// _This is a modified version of
// [John Resig's class](http://ejohn.org/blog/simple-javascript-inheritance/).
// It provides class level inheritance and callbacks._
// A private flag used to initialize a new class instance without
// initializing it's bindings.
var initializing = 0;
can.Construct = function () {
if (arguments.length) {
return can.Construct.extend.apply(can.Construct, arguments);
}
};
can.extend(can.Construct, {
newInstance: function () {
// Get a raw instance object (`init` is not called).
var inst = this.instance(),
arg = arguments,
args;
// Call `setup` if there is a `setup`
if (inst.setup) {
args = inst.setup.apply(inst, arguments);
}
// Call `init` if there is an `init`
// If `setup` returned `args`, use those as the arguments
if (inst.init) {
inst.init.apply(inst, args || arguments);
}
return inst;
},
// Overwrites an object with methods. Used in the `super` plugin.
// `newProps` - New properties to add.
// `oldProps` - Where the old properties might be (used with `super`).
// `addTo` - What we are adding to.
_inherit: function (newProps, oldProps, addTo) {
can.extend(addTo || newProps, newProps || {})
},
// used for overwriting a single property.
// this should be used for patching other objects
// the super plugin overwrites this
_overwrite: function (what, oldProps, propName, val) {
what[propName] = val;
},
// Set `defaults` as the merger of the parent `defaults` and this
// object's `defaults`. If you overwrite this method, make sure to
// include option merging logic.
setup: function (base, fullName) {
this.defaults = can.extend(true, {}, base.defaults, this.defaults);
},
// Create's a new `class` instance without initializing by setting the
// `initializing` flag.
instance: function () {
// Prevents running `init`.
initializing = 1;
var inst = new this();
// Allow running `init`.
initializing = 0;
return inst;
},
// Extends classes.
extend: function (fullName, klass, proto) {
// Figure out what was passed and normalize it.
if (typeof fullName != 'string') {
proto = klass;
klass = fullName;
fullName = null;
}
if (!proto) {
proto = klass;
klass = null;
}
proto = proto || {};
var _super_class = this,
_super = this.prototype,
name, shortName, namespace, prototype;
// Instantiate a base class (but only create the instance,
// don't run the init constructor).
prototype = this.instance();
// Copy the properties over onto the new prototype.
can.Construct._inherit(proto, _super, prototype);
// The dummy class constructor.
function Constructor() {
// All construction is actually done in the init method.
if (!initializing) {
return this.constructor !== Constructor && arguments.length ?
// We are being called without `new` or we are extending.
arguments.callee.extend.apply(arguments.callee, arguments) :
// We are being called with `new`.
this.constructor.newInstance.apply(this.constructor, arguments);
}
}
// Copy old stuff onto class (can probably be merged w/ inherit)
for (name in _super_class) {
if (_super_class.hasOwnProperty(name)) {
Constructor[name] = _super_class[name];
}
}
// Copy new static properties on class.
can.Construct._inherit(klass, _super_class, Constructor);
// Setup namespaces.
if (fullName) {
var parts = fullName.split('.'),
shortName = parts.pop(),
current = can.getObject(parts.join('.'), window, true),
namespace = current,
_fullName = can.underscore(fullName.replace(/\./g, "_")),
_shortName = can.underscore(shortName);
current[shortName] = Constructor;
}
// Set things that shouldn't be overwritten.
can.extend(Constructor, {
constructor: Constructor,
prototype: prototype,
namespace: namespace,
shortName: shortName,
_shortName: _shortName,
fullName: fullName,
_fullName: _fullName
});
// Make sure our prototype looks nice.
Constructor.prototype.constructor = Constructor;
// Call the class `setup` and `init`
var t = [_super_class].concat(can.makeArray(arguments)),
args = Constructor.setup.apply(Constructor, t);
if (Constructor.init) {
Constructor.init.apply(Constructor, args || t);
}
return Constructor;
}
});
return can.Construct;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/library', 'can/construct'], function (can, Construct) {
var isFunction = can.isFunction,
isArray = can.isArray,
makeArray = can.makeArray,
proxy = function (funcs) {
//args that should be curried
var args = makeArray(arguments),
self;
// get the functions to callback
funcs = args.shift();
// if there is only one function, make funcs into an array
if (!isArray(funcs)) {
funcs = [funcs];
}
// keep a reference to us in self
self = this;
return function class_cb() {
// add the arguments after the curried args
var cur = args.concat(makeArray(arguments)),
isString, length = funcs.length,
f = 0,
func;
// go through each function to call back
for (; f < length; f++) {
func = funcs[f];
if (!func) {
continue;
}
// set called with the name of the function on self (this is how this.view works)
isString = typeof func == "string";
// call the function
cur = (isString ? self[func] : func).apply(self, cur || []);
// pass the result to the next function (if there is a next function)
if (f < length - 1) {
cur = !isArray(cur) || cur._use_call ? [cur] : cur
}
}
return cur;
}
}
can.Construct.proxy = can.Construct.prototype.proxy = proxy;
// this corrects the case where can/control loads after can/construct/proxy, so static props don't have proxy
var correctedClasses = [can.Control, can.Model],
i = 0;
for (; i < correctedClasses.length; i++) {
if (correctedClasses[i]) {
correctedClasses[i].proxy = proxy;
}
}
return can;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/library', 'can/construct'], function (can, Construct) {
// tests if we can get super in .toString()
var isFunction = can.isFunction,
fnTest = /xyz/.test(function () {
xyz;
}) ? /\b_super\b/ : /.*/;
// overwrites a single property so it can still call super
can.Construct._overwrite = function (addTo, base, name, val) {
// Check if we're overwriting an existing function
addTo[name] = isFunction(val) && isFunction(base[name]) && fnTest.test(val) ? (function (name, fn) {
return function () {
var tmp = this._super,
ret;
// Add a new ._super() method that is the same method
// but on the super-class
this._super = base[name];
// The method only need to be bound temporarily, so we
// remove it when we're done executing
ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, val) : val;
}
// overwrites an object with methods, sets up _super
// newProps - new properties
// oldProps - where the old properties might be
// addTo - what we are adding to
can.Construct._inherit = function (newProps, oldProps, addTo) {
addTo = addTo || newProps
for (var name in newProps) {
can.Construct._overwrite(addTo, oldProps, name, newProps[name]);
}
}
return can;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/library', 'can/construct'], function (can) {
// ## control.js
// `can.Control`
// _Controller_
// Binds an element, returns a function that unbinds.
var bind = function (el, ev, callback) {
can.bind.call(el, ev, callback);
return function () {
can.unbind.call(el, ev, callback);
};
},
isFunction = can.isFunction,
extend = can.extend,
each = can.each,
slice = [].slice,
paramReplacer = /\{([^\}]+)\}/g,
special = can.getObject("$.event.special", [can]) || {},
// Binds an element, returns a function that unbinds.
delegate = function (el, selector, ev, callback) {
can.delegate.call(el, selector, ev, callback);
return function () {
can.undelegate.call(el, selector, ev, callback);
};
},
// Calls bind or unbind depending if there is a selector.
binder = function (el, ev, callback, selector) {
return selector ? delegate(el, can.trim(selector), ev, callback) : bind(el, ev, callback);
},
basicProcessor;
var Control = can.Control = can.Construct(
{
// Setup pre-processes which methods are event listeners.
setup: function () {
// Allow contollers to inherit "defaults" from super-classes as it
// done in `can.Construct`
can.Construct.setup.apply(this, arguments);
// If you didn't provide a name, or are `control`, don't do anything.
if (can.Control) {
// Cache the underscored names.
var control = this,
funcName;
// Calculate and cache actions.
control.actions = {};
for (funcName in control.prototype) {
if (control._isAction(funcName)) {
control.actions[funcName] = control._action(funcName);
}
}
}
},
// Moves `this` to the first argument, wraps it with `jQuery` if it's an element
_shifter: function (context, name) {
var method = typeof name == "string" ? context[name] : name;
if (!isFunction(method)) {
method = context[method];
}
return function () {
context.called = name;
return method.apply(context, [this.nodeName ? can.$(this) : this].concat(slice.call(arguments, 0)));
};
},
// Return `true` if is an action.
_isAction: function (methodName) {
var val = this.prototype[methodName],
type = typeof val;
// if not the constructor
return (methodName !== 'constructor') &&
// and is a function or links to a function
(type == "function" || (type == "string" && isFunction(this.prototype[val]))) &&
// and is in special, a processor, or has a funny character
!! (special[methodName] || processors[methodName] || /[^\w]/.test(methodName));
},
// Takes a method name and the options passed to a control
// and tries to return the data necessary to pass to a processor
// (something that binds things).
_action: function (methodName, options) {
// If we don't have options (a `control` instance), we'll run this
// later.
paramReplacer.lastIndex = 0;
if (options || !paramReplacer.test(methodName)) {
// If we have options, run sub to replace templates `{}` with a
// value from the options or the window
var convertedName = options ? can.sub(methodName, [options, window]) : methodName;
if (!convertedName) {
return null;
}
// If a `{}` template resolves to an object, `convertedName` will be
// an array
var arr = can.isArray(convertedName),
// Get the name
name = arr ? convertedName[1] : convertedName,
// Grab the event off the end
parts = name.split(/\s+/g),
event = parts.pop();
return {
processor: processors[event] || basicProcessor,
parts: [name, parts.join(" "), event],
delegate: arr ? convertedName[0] : undefined
};
}
},
// An object of `{eventName : function}` pairs that Control uses to
// hook up events auto-magically.
processors: {},
// A object of name-value pairs that act as default values for a
// control instance
defaults: {}
},
{
// Sets `this.element`, saves the control in `data, binds event
// handlers.
setup: function (element, options) {
var cls = this.constructor,
pluginname = cls.pluginName || cls._fullName,
arr;
// Want the raw element here.
this.element = can.$(element)
if (pluginname && pluginname !== 'can_control') {
// Set element and `className` on element.
this.element.addClass(pluginname);
}
(arr = can.data(this.element, "controls")) || can.data(this.element, "controls", arr = []);
arr.push(this);
// Option merging.
this.options = extend({}, cls.defaults, options);
// Bind all event handlers.
this.on();
// Get's passed into `init`.
return [this.element, this.options];
},
on: function (el, selector, eventName, func) {
if (!el) {
// Adds bindings.
this.off();
// Go through the cached list of actions and use the processor
// to bind
var cls = this.constructor,
bindings = this._bindings,
actions = cls.actions,
element = this.element,
destroyCB = can.Control._shifter(this, "destroy"),
funcName, ready;
for (funcName in actions) {
// Only push if we have the action and no option is `undefined`
if (actions.hasOwnProperty(funcName) && (ready = actions[funcName] || cls._action(funcName, this.options))) {
bindings.push(ready.processor(ready.delegate || element, ready.parts[2], ready.parts[1], funcName, this));
}
}
// Setup to be destroyed...
// don't bind because we don't want to remove it.
can.bind.call(element, "destroyed", destroyCB);
bindings.push(function (el) {
can.unbind.call(el, "destroyed", destroyCB);
});
return bindings.length;
}
if (typeof el == 'string') {
func = eventName;
eventName = selector;
selector = el;
el = this.element;
}
if (func === undefined) {
func = eventName;
eventName = selector;
selector = null;
}
if (typeof func == 'string') {
func = can.Control._shifter(this, func);
}
this._bindings.push(binder(el, eventName, func, selector));
return this._bindings.length;
},
// Unbinds all event handlers on the controller.
off: function () {
var el = this.element[0]
each(this._bindings || [], function (value) {
value(el);
});
// Adds bindings.
this._bindings = [];
},
// Prepares a `control` for garbage collection
destroy: function () {
var Class = this.constructor,
pluginName = Class.pluginName || Class._fullName,
controls;
// Unbind bindings.
this.off();
if (pluginName && pluginName !== 'can_control') {
// Remove the `className`.
this.element.removeClass(pluginName);
}
// Remove from `data`.
controls = can.data(this.element, "controls");
controls.splice(can.inArray(this, controls), 1);
can.trigger(this, "destroyed"); // In case we want to know if the `control` is removed.
this.element = null;
}
});
var processors = can.Control.processors,
// Processors do the binding.
// They return a function that unbinds when called.
// The basic processor that binds events.
basicProcessor = function (el, event, selector, methodName, control) {
return binder(el, event, can.Control._shifter(control, methodName), selector);
};
// Set common events to be processed as a `basicProcessor`
each(["change", "click", "contextmenu", "dblclick", "keydown", "keyup", "keypress", "mousedown", "mousemove", "mouseout", "mouseover", "mouseup", "reset", "resize", "scroll", "select", "submit", "focusin", "focusout", "mouseenter", "mouseleave",
// #104 - Add touch events as default processors
// TOOD feature detect?
"touchstart", "touchmove", "touchcancel", "touchend", "touchleave"], function (v) {
processors[v] = basicProcessor;
});
return Control;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['jquery', 'can/util/library', 'can/control'], function ($, can) {
//used to determine if a control instance is one of controllers
//controllers can be strings or classes
var i, isAControllerOf = function (instance, controllers) {
for (i = 0; i < controllers.length; i++) {
if (typeof controllers[i] == 'string' ? instance.constructor._shortName == controllers[i] : instance instanceof controllers[i]) {
return true;
}
}
return false;
},
makeArray = can.makeArray,
old = can.Control.setup;
can.Control.setup = function () {
// if you didn't provide a name, or are control, don't do anything
if (this !== can.Control) {
var pluginName = this.pluginName || this._fullName;
// create jQuery plugin
if (pluginName !== 'can_control') {
this.plugin(pluginName);
}
old.apply(this, arguments);
}
};
$.fn.extend({
controls: function () {
var controllerNames = makeArray(arguments),
instances = [],
controls, c, cname;
//check if arguments
this.each(function () {
controls = can.$(this).data("controls");
if (!controls) {
return;
}
for (var i = 0; i < controls.length; i++) {
c = controls[i];
if (!controllerNames.length || isAControllerOf(c, controllerNames)) {
instances.push(c);
}
}
});
return instances;
},
control: function (control) {
return this.controls.apply(this, arguments)[0];
}
});
can.Control.plugin = function (pluginname) {
var control = this;
if (!$.fn[pluginname]) {
$.fn[pluginname] = function (options) {
var args = makeArray(arguments),
//if the arg is a method on this control
isMethod = typeof options == "string" && $.isFunction(control.prototype[options]),
meth = args[0],
returns;
this.each(function () {
//check if created
var plugin = can.$(this).control(control);
if (plugin) {
if (isMethod) {
// call a method on the control with the remaining args
returns = plugin[meth].apply(plugin, args.slice(1));
}
else {
// call the plugin's update method
plugin.update.apply(plugin, args);
}
}
else {
//create a new control instance
control.newInstance.apply(control, [this].concat(args));
}
});
return returns !== undefined ? returns : this;
};
}
}
can.Control.prototype.update = function (options) {
can.extend(this.options, options);
this.on();
};
return can;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/library', 'can/route', 'can/control'], function (can) {
// ## control/route.js
// _Controller route integration._
can.Control.processors.route = function (el, event, selector, funcName, controller) {
selector = selector || "";
can.route(selector);
var batchNum, check = function (ev, attr, how) {
if (can.route.attr('route') === (selector) && (ev.batchNum === undefined || ev.batchNum !== batchNum)) {
batchNum = ev.batchNum;
var d = can.route.attr();
delete d.route;
if (can.isFunction(controller[funcName])) {
controller[funcName](d);
} else {
controller[controller[funcName]](d);
}
}
};
can.route.bind('change', check);
return function () {
can.route.unbind('change', check);
};
};
return can;
});
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/library', 'can/observe'], function (can, Observe) {
can.each([can.Observe, can.Model], function (clss) {
// in some cases model might not be defined quite yet.
if (clss === undefined) {
return;
}
can.extend(clss, {
attributes: {},
convert: {
"date": function (str) {
var type = typeof str;
if (type === "string") {
return isNaN(Date.parse(str)) ? null : Date.parse(str)
} else if (type === 'number') {
return new Date(str)
} else {
return str
}
},
"number": function (val) {
return parseFloat(val);
},
"boolean": function (val) {
return Boolean(val === "false" ? 0 : val);
},
"default": function (val, oldVal, error, type) {
var construct = can.getObject(type),
context = window,
realType;
// if type has a . we need to look it up
if (type.indexOf(".") >= 0) {
// get everything before the last .
realType = type.substring(0, type.lastIndexOf("."));
// get the object before the last .
context = can.getObject(realType);
}
return typeof construct == "function" ? construct.call(context, val, oldVal) : val;
}
},
serialize: {
"default": function (val, type) {
return isObject(val) && val.serialize ? val.serialize() : val;
},
"date": function (val) {
return val && val.getTime()
}
}
});
// overwrite setup to do this stuff
var oldSetup = clss.setup;
clss.setup = function (superClass, stat, proto) {
var self = this;
oldSetup.call(self, superClass, stat, proto);
can.each(["attributes"], function (name) {
if (!self[name] || superClass[name] === self[name]) {
self[name] = {};
}
});
can.each(["convert", "serialize"], function (name) {
if (superClass[name] != self[name]) {
self[name] = can.extend({}, superClass[name], self[name]);
}
});
};
});
var oldSetup = can.Observe.prototype.setup;
can.Observe.prototype.setup = function (obj) {
var diff = {};
oldSetup.call(this, obj);
can.each(this.constructor.defaults, function (value, key) {
if (!this.hasOwnProperty(key)) {
diff[key] = value;
}
}, this);
this._init = 1;
this.attr(diff);
delete this._init;
};
can.Observe.prototype.__convert = function (prop, value) {
// check if there is a
var Class = this.constructor,
oldVal = this.attr(prop),
type, converter;
if (Class.attributes) {
// the type of the attribute
type = Class.attributes[prop];
converter = Class.convert[type] || Class.convert['default'];
}
return value === null || !type ?
// just use the value
value :
// otherwise, pass to the converter
converter.call(Class, value, oldVal, function () {}, type);
};
can.Observe.prototype.serialize = function (attrName) {
var where = {},
Class = this.constructor,
attrs = {};
if (attrName != undefined) {
attrs[attrName] = this[attrName];
} else {
attrs = this.__get();
}
can.each(attrs, function (val, name) {
var type, converter;
type = Class.attributes ? Class.attributes[name] : 0;
converter = Class.serialize ? Class.serialize[type] : 0;
// if the value is an object, and has a attrs or serialize function
where[name] = val && typeof val.serialize == 'function' ?
// call attrs or serialize to get the original data back
val.serialize() :
// otherwise if we have a converter
converter ?
// use the converter
converter(val, type) :
// or return the val
val
});
return attrName != undefined ? where[attrName] : where;
};
return can.Observe;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/library', 'can/observe', 'can/util/object'], function (can) {
var flatProps = function (a) {
var obj = {};
for (var prop in a) {
if (typeof a[prop] !== 'object' || a[prop] === null || a[prop] instanceof Date) {
obj[prop] = a[prop]
}
}
return obj;
};
can.extend(can.Observe.prototype, {
backup: function () {
this._backupStore = this._attrs();
return this;
},
isDirty: function (checkAssociations) {
return this._backupStore && !can.Object.same(this._attrs(), this._backupStore, undefined, undefined, undefined, !! checkAssociations);
},
restore: function (restoreAssociations) {
var props = restoreAssociations ? this._backupStore : flatProps(this._backupStore)
if (this.isDirty(restoreAssociations)) {
this._attrs(props);
}
return this;
}
})
return can.Observe;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/library'], function (can) {
// returns the
// - observes and attr methods are called by func
// - the value returned by func
// ex: `{value: 100, observed: [{obs: o, attr: "completed"}]}`
var getValueAndObserved = function (func, self) {
var oldReading;
if (can.Observe) {
// Set a callback on can.Observe to know
// when an attr is read.
// Keep a reference to the old reader
// if there is one. This is used
// for nested live binding.
oldReading = can.Observe.__reading;
can.Observe.__reading = function (obj, attr) {
// Add the observe and attr that was read
// to `observed`
observed.push({
obj: obj,
attr: attr
});
};
}
var observed = [],
// Call the "wrapping" function to get the value. `observed`
// will have the observe/attribute pairs that were read.
value = func.call(self);
// Set back so we are no longer reading.
if (can.Observe) {
can.Observe.__reading = oldReading;
}
return {
value: value,
observed: observed
};
},
// Calls `callback(newVal, oldVal)` everytime an observed property
// called within `getterSetter` is changed and creates a new result of `getterSetter`.
// Also returns an object that can teardown all event handlers.
computeBinder = function (getterSetter, context, callback) {
// track what we are observing
var observing = {},
// a flag indicating if this observe/attr pair is already bound
matched = true,
// the data to return
data = {
// we will maintain the value while live-binding is taking place
value: undefined,
// a teardown method that stops listening
teardown: function () {
for (var name in observing) {
var ob = observing[name];
ob.observe.obj.unbind(ob.observe.attr, onchanged);
delete observing[name];
}
}
},
batchNum;
// when a property value is changed
var onchanged = function (ev) {
if (ev.batchNum === undefined || ev.batchNum !== batchNum) {
// store the old value
var oldValue = data.value,
// get the new value
newvalue = getValueAndBind();
// update the value reference (in case someone reads)
data.value = newvalue;
// if a change happened
if (newvalue !== oldValue) {
callback(newvalue, oldValue);
}
batchNum = batchNum = ev.batchNum;
}
};
// gets the value returned by `getterSetter` and also binds to any attributes
// read by the call
var getValueAndBind = function () {
var info = getValueAndObserved(getterSetter, context),
newObserveSet = info.observed;
var value = info.value;
matched = !matched;
// go through every attribute read by this observe
can.each(newObserveSet, function (ob) {
// if the observe/attribute pair is being observed
if (observing[ob.obj._cid + "|" + ob.attr]) {
// mark at as observed
observing[ob.obj._cid + "|" + ob.attr].matched = matched;
} else {
// otherwise, set the observe/attribute on oldObserved, marking it as being observed
observing[ob.obj._cid + "|" + ob.attr] = {
matched: matched,
observe: ob
};
ob.obj.bind(ob.attr, onchanged);
}
});
// Iterate through oldObserved, looking for observe/attributes
// that are no longer being bound and unbind them
for (var name in observing) {
var ob = observing[name];
if (ob.matched !== matched) {
ob.observe.obj.unbind(ob.observe.attr, onchanged);
delete observing[name];
}
}
return value;
};
// set the initial value
data.value = getValueAndBind();
data.isListening = !can.isEmptyObject(observing);
return data;
}
// if no one is listening ... we can not calculate every time
can.compute = function (getterSetter, context) {
if (getterSetter && getterSetter.isComputed) {
return getterSetter;
}
// get the value right away
// TODO: eventually we can defer this until a bind or a read
var computedData, bindings = 0,
computed, canbind = true;
if (typeof getterSetter === "function") {
computed = function (value) {
if (value === undefined) {
// we are reading
if (computedData) {
// If another compute is calling this compute for the value,
// it needs to bind to this compute's change so it will re-compute
// and re-bind when this compute changes.
if (bindings && can.Observe.__reading) {
can.Observe.__reading(computed, 'change');
}
return computedData.value;
} else {
return getterSetter.call(context || this)
}
} else {
return getterSetter.apply(context || this, arguments)
}
}
} else {
// we just gave it a value
computed = function (val) {
if (val === undefined) {
// If observing, record that the value is being read.
if (can.Observe.__reading) {
can.Observe.__reading(computed, 'change');
}
return getterSetter;
} else {
var old = getterSetter;
getterSetter = val;
if (old !== val) {
can.Observe.triggerBatch(computed, "change", [val, old]);
}
return val;
}
}
canbind = false;
}
computed.isComputed = true;
computed.bind = function (ev, handler) {
can.addEvent.apply(computed, arguments);
if (bindings === 0 && canbind) {
// setup live-binding
computedData = computeBinder(getterSetter, context || this, function (newValue, oldValue) {
can.Observe.triggerBatch(computed, "change", [newValue, oldValue])
});
}
bindings++;
}
computed.unbind = function (ev, handler) {
can.removeEvent.apply(computed, arguments);
bindings--;
if (bindings === 0 && canbind) {
computedData.teardown();
}
};
return computed;
};
can.compute.binder = computeBinder;
return can.compute;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/library', 'can/observe'], function (can) {
// ** - 'this' will be the deepest item changed
// * - 'this' will be any changes within *, but * will be the
// this returned
// tells if the parts part of a delegate matches the broken up props of the event
// gives the prop to use as 'this'
// - parts - the attribute name of the delegate split in parts ['foo','*']
// - props - the split props of the event that happened ['foo','bar','0']
// - returns - the attribute to delegate too ('foo.bar'), or null if not a match
var matches = function (parts, props) {
//check props parts are the same or
var len = parts.length,
i = 0,
// keeps the matched props we will use
matchedProps = [],
prop;
// if the event matches
for (i; i < len; i++) {
prop = props[i]
// if no more props (but we should be matching them)
// return null
if (typeof prop !== 'string') {
return null;
} else
// if we have a "**", match everything
if (parts[i] == "**") {
return props.join(".");
} else
// a match, but we want to delegate to "*"
if (parts[i] == "*") {
// only do this if there is nothing after ...
matchedProps.push(prop);
}
else if (prop === parts[i]) {
matchedProps.push(prop);
} else {
return null;
}
}
return matchedProps.join(".");
},
// gets a change event and tries to figure out which
// delegates to call
delegate = function (event, prop, how, newVal, oldVal) {
// pre-split properties to save some regexp time
var props = prop.split("."),
delegates = (this._observe_delegates || []).slice(0),
delegate, attr, matchedAttr, hasMatch, valuesEqual;
event.attr = prop;
event.lastAttr = props[props.length - 1];
// for each delegate
for (var i = 0; delegate = delegates[i++];) {
// if there is a batchNum, this means that this
// event is part of a series of events caused by a single
// attrs call. We don't want to issue the same event
// multiple times
// setting the batchNum happens later
if ((event.batchNum && delegate.batchNum === event.batchNum) || delegate.undelegated) {
continue;
}
// reset match and values tests
hasMatch = undefined;
valuesEqual = true;
// yeah, all this under here has to be redone v
// for each attr in a delegate
for (var a = 0; a < delegate.attrs.length; a++) {
attr = delegate.attrs[a];
// check if it is a match
if (matchedAttr = matches(attr.parts, props)) {
hasMatch = matchedAttr;
}
// if it has a value, make sure it's the right value
// if it's set, we should probably check that it has a
// value no matter what
if (attr.value && valuesEqual) {
valuesEqual = attr.value === "" + this.attr(attr.attr)
} else if (valuesEqual && delegate.attrs.length > 1) {
// if there are multiple attributes, each has to at
// least have some value
valuesEqual = this.attr(attr.attr) !== undefined
}
}
// if there is a match and valuesEqual ... call back
if (hasMatch && valuesEqual) {
// how to get to the changed property from the delegate
var from = prop.replace(hasMatch + ".", "");
// if this event is part of a batch, set it on the delegate
// to only send one event
if (event.batchNum) {
delegate.batchNum = event.batchNum
}
// if we listen to change, fire those with the same attrs
// TODO: the attrs should probably be using from
if (delegate.event === 'change') {
arguments[1] = from;
event.curAttr = hasMatch;
delegate.callback.apply(this.attr(hasMatch), can.makeArray(arguments));
} else if (delegate.event === how) {
// if it's a match, callback with the location of the match
delegate.callback.apply(this.attr(hasMatch), [event, newVal, oldVal, from]);
} else if (delegate.event === 'set' && how == 'add') {
// if we are listening to set, we should also listen to add
delegate.callback.apply(this.attr(hasMatch), [event, newVal, oldVal, from]);
}
}
}
};
can.extend(can.Observe.prototype, {
delegate: function (selector, event, handler) {
selector = can.trim(selector);
var delegates = this._observe_delegates || (this._observe_delegates = []),
attrs = [],
selectorRegex = /([^\s=,]+)(?:=("[^",]*"|'[^',]*'|[^\s"',]*))?(,?)\s*/g,
matches;
// parse each property in the selector
while (matches = selectorRegex.exec(selector)) {
// we need to do a little doctoring to make up for the quotes.
if (matches[2] && $.inArray(matches[2].substr(0, 1), ['"', "'"]) >= 0) {
matches[2] = matches[2].substr(1, -1);
}
attrs.push({
// the attribute name
attr: matches[1],
// the attribute name, pre-split for speed
parts: matches[1].split('.'),
// the value associated with this property (if there was one given)
value: matches[2],
// whether this selector combines with the one after it with AND or OR
or: matches[3] === ','
});
}
// delegates has pre-processed info about the event
delegates.push({
// the attrs name for unbinding
selector: selector,
// an object of attribute names and values {type: 'recipe',id: undefined}
// undefined means a value was not defined
attrs: attrs,
callback: handler,
event: event
});
if (delegates.length === 1) {
this.bind("change", delegate)
}
return this;
},
undelegate: function (selector, event, handler) {
selector = can.trim(selector);
var i = 0,
delegates = this._observe_delegates || [],
delegateOb;
if (selector) {
while (i < delegates.length) {
delegateOb = delegates[i];
if (delegateOb.callback === handler || (!handler && delegateOb.selector === selector)) {
delegateOb.undelegated = true;
delegates.splice(i, 1)
} else {
i++;
}
}
} else {
// remove all delegates
delegates = [];
}
if (!delegates.length) {
//can.removeData(this, "_observe_delegates");
this.unbind("change", delegate)
}
return this;
}
});
// add helpers for testing ..
can.Observe.prototype.delegate.matches = matches;
return can.Observe;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/library', 'can/observe', 'can/observe/compute'], function (can) {
can.extend(can.Observe.List.prototype, {
filter: function (callback) {
// The filtered list
var filtered = new this.constructor();
var self = this;
// Creates the binder for a single element at a given index
var generator = function (element, index) {
// The event handler that updates the filtered list
var binder = function (ev, val) {
var index = filtered.indexOf(element);
// Remove it from the list if it exists but the new value is false
if (!val && index !== -1) {
filtered.splice(index, 1);
}
// Add it to the list if it isn't in there and the new value is true
if (val && index === -1) {
filtered.push(element);
}
};
// a can.compute that executes the callback
var compute = can.compute(function () {
return callback(element, self.indexOf(element), self);
});
// Update the filtered list on any compute change
compute.bind('change', binder);
// Call binder explicitly for the initial list
binder(null, compute());
};
// We also want to know when something gets added to our original list
this.bind('add', function (ev, data, index) {
can.each(data, function (element, i) {
// Call the generator for each newly added element
// The index is the start index + the loop index
generator(element, index + i);
});
});
// Removed items should be removed from both lists
this.bind('remove', function (ev, data, index) {
can.each(data, function (element, i) {
var index = filtered.indexOf(element);
if (index !== -1) {
filtered.splice(index, 1);
}
});
});
// Run the generator for each list element
this.forEach(generator);
return filtered;
},
map: function (callback) {
var mapped = new can.Observe.List();
var self = this;
// Again, lets run a generator function
var generator = function (element, index) {
// The can.compute for the mapping
var compute = can.compute(function () {
return callback(element, index, self);
});
compute.bind('change', function (ev, val) {
// On change, replace the current value with the new one
mapped.splice(index, 1, val);
});
mapped.push(compute());
}
this.forEach(generator);
// We also want to know when something gets added to our original list
this.bind('add', function (ev, data, index) {
can.each(data, function (element, i) {
// Call the generator for each newly added element
// The index is the start index + the loop index
generator(element, index + i);
});
});
this.bind('remove', function (ev, data, index) {
// The indices in the mapped list are the same so lets just splice it out
mapped.splice(index, data.length);
})
return mapped;
}
});
return can.Observe.List;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/library', 'can/observe/attributes'], function (can) {
can.classize = function (s, join) {
// this can be moved out ..
// used for getter setter
var parts = s.split(can.undHash),
i = 0;
for (; i < parts.length; i++) {
parts[i] = can.capitalize(parts[i]);
}
return parts.join(join || '');
}
var classize = can.classize,
proto = can.Observe.prototype,
old = proto.__set;
proto.__set = function (prop, value, current, success, error) {
// check if there's a setter
var cap = classize(prop),
setName = "set" + cap,
errorCallback = function (errors) {
var stub = error && error.call(self, errors);
// if 'setter' is on the page it will trigger
// the error itself and we dont want to trigger
// the event twice. :)
if (stub !== false) {
can.trigger(self, "error", [prop, errors], true);
}
return false;
},
self = this;
// if we have a setter
if (this[setName] &&
// call the setter, if returned value is undefined,
// this means the setter is async so we
// do not call update property and return right away
(value = this[setName](value, function () {
old.call(self, prop, value, current, success, errorCallback)
}, errorCallback)) === undefined) {
return;
}
old.call(self, prop, value, current, success, errorCallback);
return this;
};
return can.Observe;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/library', 'can/observe/attributes'], function (can) {
//validations object is by property. You can have validations that
//span properties, but this way we know which ones to run.
// proc should return true if there's an error or the error message
var validate = function (attrNames, options, proc) {
// normalize argumetns
if (!proc) {
proc = options;
options = {};
}
options = options || {};
attrNames = can.makeArray(attrNames)
// run testIf if it exists
if (options.testIf && !options.testIf.call(this)) {
return;
}
var self = this;
can.each(attrNames, function (attrName) {
// Add a test function for each attribute
if (!self.validations[attrName]) {
self.validations[attrName] = [];
}
self.validations[attrName].push(function (newVal) {
// if options has a message return that, otherwise, return the error
var res = proc.call(this, newVal, attrName);
return res === undefined ? undefined : (options.message || res);
})
});
};
var old = can.Observe.prototype.__set;
can.Observe.prototype.__set = function (prop, value, current, success, error) {
var self = this,
validations = self.constructor.validations,
errorCallback = function (errors) {
var stub = error && error.call(self, errors);
// if 'setter' is on the page it will trigger
// the error itself and we dont want to trigger
// the event twice. :)
if (stub !== false) {
can.trigger(self, "error", [prop, errors], true);
}
return false;
};
old.call(self, prop, value, current, success, errorCallback);
if (validations && validations[prop]) {
var errors = self.errors(prop);
errors && errorCallback(errors)
}
return this;
}
can.each([can.Observe, can.Model], function (clss) {
// in some cases model might not be defined quite yet.
if (clss === undefined) {
return;
}
var oldSetup = clss.setup;
can.extend(clss, {
setup: function (superClass) {
oldSetup.apply(this, arguments);
if (!this.validations || superClass.validations === this.validations) {
this.validations = {};
}
},
validate: validate,
validationMessages: {
format: "is invalid",
inclusion: "is not a valid option (perhaps out of range)",
lengthShort: "is too short",
lengthLong: "is too long",
presence: "can't be empty",
range: "is out of range"
},
validateFormatOf: function (attrNames, regexp, options) {
validate.call(this, attrNames, options, function (value) {
if ((typeof value != 'undefined' && value != '') && String(value).match(regexp) == null) {
return this.constructor.validationMessages.format;
}
});
},
validateInclusionOf: function (attrNames, inArray, options) {
validate.call(this, attrNames, options, function (value) {
if (typeof value == 'undefined') {
return;
}
if (can.grep(inArray, function (elm) {
return (elm == value);
}).length == 0) {
return this.constructor.validationMessages.inclusion;
}
});
},
validateLengthOf: function (attrNames, min, max, options) {
validate.call(this, attrNames, options, function (value) {
if ((typeof value == 'undefined' && min > 0) || value.length < min) {
return this.constructor.validationMessages.lengthShort + " (min=" + min + ")";
} else if (typeof value != 'undefined' && value.length > max) {
return this.constructor.validationMessages.lengthLong + " (max=" + max + ")";
}
});
},
validatePresenceOf: function (attrNames, options) {
validate.call(this, attrNames, options, function (value) {
if (typeof value == 'undefined' || value === "" || value === null) {
return this.constructor.validationMessages.presence;
}
});
},
validateRangeOf: function (attrNames, low, hi, options) {
validate.call(this, attrNames, options, function (value) {
if (typeof value != 'undefined' && value < low || value > hi) {
return this.constructor.validationMessages.range + " [" + low + "," + hi + "]";
}
});
}
});
});
can.extend(can.Observe.prototype, {
errors: function (attrs, newVal) {
// convert attrs to an array
if (attrs) {
attrs = can.isArray(attrs) ? attrs : [attrs];
}
var errors = {},
self = this,
attr,
// helper function that adds error messages to errors object
// attr - the name of the attribute
// funcs - the validation functions
addErrors = function (attr, funcs) {
can.each(funcs, function (func) {
var res = func.call(self, isTest ? (self.__convert ? self.__convert(attr, newVal) : newVal) : self[attr]);
if (res) {
if (!errors[attr]) {
errors[attr] = [];
}
errors[attr].push(res);
}
});
},
validations = this.constructor.validations,
isTest = attrs && attrs.length === 1 && arguments.length === 2;
// go through each attribute or validation and
// add any errors
can.each(attrs || validations || {}, function (funcs, attr) {
// if we are iterating through an array, use funcs
// as the attr name
if (typeof attr == 'number') {
attr = funcs;
funcs = validations[attr];
}
// add errors to the
addErrors(attr, funcs || []);
});
// return errors as long as we have one
return can.isEmptyObject(errors) ? null : isTest ? errors[attrs[0]] : errors;
}
});
return can.Observe;
});
\ No newline at end of file
This diff is collapsed.
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/can'], function (can) {
can.each = function (elements, callback, context) {
var i = 0,
key;
if (elements) {
if (typeof elements.length === 'number' && elements.pop) {
if (elements.attr) {
elements.attr('length');
}
for (key = elements.length; i < key; i++) {
if (callback.call(context || elements[i], elements[i], i, elements) === false) {
break;
}
}
} else if (elements.hasOwnProperty) {
for (key in elements) {
if (elements.hasOwnProperty(key)) {
if (callback.call(context || elements[key], elements[key], key, elements) === false) {
break;
}
}
}
}
}
return elements;
};
return can;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(function () {
var can = window.can || {};
if (typeof GLOBALCAN === 'undefined' || GLOBALCAN !== false) {
window.can = can;
}
can.isDeferred = function (obj) {
var isFunction = this.isFunction;
// Returns `true` if something looks like a deferred.
return obj && isFunction(obj.then) && isFunction(obj.pipe);
};
return can;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/can'], function (can) {
// deferred.js
// ---------
// _Lightweight, jQuery style deferreds._
// extend is usually provided by the wrapper but to avoid steal.then calls
// we define a simple extend here as well
var extend = function (target, src) {
for (var key in src) {
if (src.hasOwnProperty(key)) {
target[key] = src[key];
}
}
},
Deferred = function (func) {
if (!(this instanceof Deferred)) return new Deferred();
this._doneFuncs = [];
this._failFuncs = [];
this._resultArgs = null;
this._status = "";
// Check for option `function` -- call it with this as context and as first
// parameter, as specified in jQuery API.
func && func.call(this, this);
};
can.Deferred = Deferred;
can.when = Deferred.when = function () {
var args = can.makeArray(arguments);
if (args.length < 2) {
var obj = args[0];
if (obj && (can.isFunction(obj.isResolved) && can.isFunction(obj.isRejected))) {
return obj;
} else {
return Deferred().resolve(obj);
}
} else {
var df = Deferred(),
done = 0,
// Resolve params -- params of each resolve, we need to track them down
// to be able to pass them in the correct order if the master
// needs to be resolved.
rp = [];
can.each(args, function (arg, j) {
arg.done(function () {
rp[j] = (arguments.length < 2) ? arguments[0] : arguments;
if (++done == args.length) {
df.resolve.apply(df, rp);
}
}).fail(function () {
df.reject(arguments);
});
});
return df;
}
}
var resolveFunc = function (type, _status) {
return function (context) {
var args = this._resultArgs = (arguments.length > 1) ? arguments[1] : [];
return this.exec(context, this[type], args, _status);
}
},
doneFunc = function (type, _status) {
return function () {
var self = this;
// In Safari, the properties of the `arguments` object are not enumerable,
// so we have to convert arguments to an `Array` that allows `can.each` to loop over them.
can.each(Array.prototype.slice.call(arguments), function (v, i, args) {
if (!v) return;
if (v.constructor === Array) {
args.callee.apply(self, v)
} else {
// Immediately call the `function` if the deferred has been resolved.
if (self._status === _status) v.apply(self, self._resultArgs || []);
self[type].push(v);
}
});
return this;
}
};
extend(Deferred.prototype, {
pipe: function (done, fail) {
var d = can.Deferred();
this.done(function () {
d.resolve(done.apply(this, arguments));
});
this.fail(function () {
if (fail) {
d.reject(fail.apply(this, arguments));
} else {
d.reject.apply(d, arguments);
}
});
return d;
},
resolveWith: resolveFunc("_doneFuncs", "rs"),
rejectWith: resolveFunc("_failFuncs", "rj"),
done: doneFunc("_doneFuncs", "rs"),
fail: doneFunc("_failFuncs", "rj"),
always: function () {
var args = can.makeArray(arguments);
if (args.length && args[0]) this.done(args[0]).fail(args[0]);
return this;
},
then: function () {
var args = can.makeArray(arguments);
// Fail `function`(s)
if (args.length > 1 && args[1]) this.fail(args[1]);
// Done `function`(s)
if (args.length && args[0]) this.done(args[0]);
return this;
},
state: function () {
switch (this._status) {
case 'rs':
return 'resolved';
case 'rj':
return 'rejected';
default:
return 'pending';
}
},
isResolved: function () {
return this._status === "rs";
},
isRejected: function () {
return this._status === "rj";
},
reject: function () {
return this.rejectWith(this, arguments);
},
resolve: function () {
return this.resolveWith(this, arguments);
},
exec: function (context, dst, args, st) {
if (this._status !== "") return this;
this._status = st;
can.each(dst, function (d) {
d.apply(context, args);
});
return this;
}
});
return can;
});
\ No newline at end of file
This diff is collapsed.
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/can'], function (can) {
// event.js
// ---------
// _Basic event wrapper._
can.addEvent = function (event, fn) {
if (!this.__bindEvents) {
this.__bindEvents = {};
}
var eventName = event.split(".")[0];
if (!this.__bindEvents[eventName]) {
this.__bindEvents[eventName] = [];
}
this.__bindEvents[eventName].push({
handler: fn,
name: event
});
return this;
};
can.removeEvent = function (event, fn) {
if (!this.__bindEvents) {
return;
}
var i = 0,
events = this.__bindEvents[event.split(".")[0]],
ev;
while (i < events.length) {
ev = events[i]
if ((fn && ev.handler === fn) || (!fn && ev.name === event)) {
events.splice(i, 1);
} else {
i++;
}
}
return this;
};
can.dispatch = function (event) {
if (!this.__bindEvents) {
return;
}
var eventName = event.type.split(".")[0],
handlers = (this.__bindEvents[eventName] || []).slice(0),
self = this,
args = [event].concat(event.data || []);
can.each(handlers, function (ev) {
event.data = args.slice(1);
ev.handler.apply(self, args);
});
}
return can;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/can'], function (can) {
// fragment.js
// ---------
// _DOM Fragment support._
var fragmentRE = /^\s*<(\w+)[^>]*>/,
fragment = function (html, name) {
if (name === undefined) {
name = fragmentRE.test(html) && RegExp.$1;
}
if (html && can.isFunction(html.replace)) {
// Fix "XHTML"-style tags in all browsers
html = html.replace(/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, "<$1></$2>");
}
var container = document.createElement('div'),
temp = document.createElement('div')
// IE's parser will strip any `<tr><td>` tags when `innerHTML`
// is called on a `tbody`. To get around this, we construct a
// valid table with a `tbody` that has the `innerHTML` we want.
// Then the container is the `firstChild` of the `tbody`.
// [source](http://www.ericvasilik.com/2006/07/code-karma.html).
if (name === "tbody" || name === "tfoot" || name === "thead") {
temp.innerHTML = "<table>" + html + "</table>";
container = temp.firstChild.nodeType === 3 ? temp.lastChild : temp.firstChild;
} else if (name === "tr") {
temp.innerHTML = "<table><tbody>" + html + "</tbody></table>";
container = temp.firstChild.nodeType === 3 ? temp.lastChild : temp.firstChild.firstChild;
} else if (name === "td" || name === "th") {
temp.innerHTML = "<table><tbody><tr>" + html + "</tr></tbody></table>";
container = temp.firstChild.nodeType === 3 ? temp.lastChild : temp.firstChild.firstChild.firstChild;
} else if (name === 'option') {
temp.innerHTML = "<select>" + html + "</select>";
container = temp.firstChild.nodeType === 3 ? temp.lastChild : temp.firstChild;
} else {
container.innerHTML = '' + html;
}
// IE8 barfs if you pass slice a `childNodes` object, so make a copy.
var tmp = {},
children = container.childNodes;
tmp.length = children.length;
for (var i = 0; i < children.length; i++) {
tmp[i] = children[i];
}
return [].slice.call(tmp);
}
can.buildFragment = function (html, nodes) {
var parts = fragment(html),
frag = document.createDocumentFragment();
can.each(parts, function (part) {
frag.appendChild(part);
})
return frag;
};
return can;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['jquery', 'can/util/can', 'can/util/array/each'], function ($, can) {
// _jQuery node list._
$.extend(can, $, {
trigger: function (obj, event, args) {
if (obj.trigger) {
obj.trigger(event, args);
} else {
$.event.trigger(event, args, obj, true);
}
},
addEvent: function (ev, cb) {
$([this]).bind(ev, cb);
return this;
},
removeEvent: function (ev, cb) {
$([this]).unbind(ev, cb);
return this;
},
// jquery caches fragments, we always needs a new one
buildFragment: function (result, element) {
var ret = $.buildFragment([result], $(element));
return ret.cacheable ? $.clone(ret.fragment) : ret.fragment;
},
$: $,
each: can.each
});
// Wrap binding functions.
$.each(['bind', 'unbind', 'undelegate', 'delegate'], function (i, func) {
can[func] = function () {
var t = this[func] ? this : $([this]);
t[func].apply(t, arguments);
return this;
};
});
// Wrap modifier functions.
$.each(["append", "filter", "addClass", "remove", "data", "get"], function (i, name) {
can[name] = function (wrapped) {
return wrapped[name].apply(wrapped, can.makeArray(arguments).slice(1));
};
});
// Memory safe destruction.
var oldClean = $.cleanData;
$.cleanData = function (elems) {
$.each(elems, function (i, elem) {
if (elem) {
can.trigger(elem, "destroyed", [], false);
}
});
oldClean(elems);
};
return can;
});
\ No newline at end of file
/*
* CanJS - 1.1.3 (2012-12-11)
* http://canjs.us/
* Copyright (c) 2012 Bitovi
* Licensed MIT
*/
define(['can/util/jquery'], function (can) {
return can;
});
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -63,6 +63,7 @@ We also have a number of in-progress applications in Labs:
- [KnockoutJS](http://knockoutjs.com) + [ClassBindingProvider](https://github.com/rniemeyer/knockout-classBindingProvider) (using Ryan Niemeyer's Class Binding Provider)
- [KnockoutJS](http://knockoutjs.com) + [RequireJS](http://requirejs.org) (using AMD)
- [AngularJS](http://angularjs.org) + [RequireJS](http://requirejs.org) (using AMD)
- [CanJS](http://canjs.us) + [RequireJS](http://requirejs.org) (using AMD)
- [AngularJS](http://angularjs.org) (optimized)
- [Backbone.xmpp](https://github.com/ggozad/Backbone.xmpp)
- [Dart](http://dartlang.org)
......
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