Commit cec4a975 authored by Sindre Sorhus's avatar Sindre Sorhus

Merge pull request #1170 from samccone/sjs/reskin-canjs

update canjs UI
parents 666c2195 c2c66c11
node_modules/.bin/*
node_modules/canjs-localstorage/*
!node_modules/canjs-localstorage/can.localstorage.js
node_modules/napa/*
node_modules/canjs/*
!node_modules/canjs/can.jquery.js
node_modules/jquery/.bowerrc
node_modules/jquery/.npmignore
node_modules/jquery/AUTHORS.txt
node_modules/jquery/CONTRIBUTING.md
node_modules/jquery/MIT-LICENSE.txt
node_modules/jquery/README.md
node_modules/jquery/bower.json
node_modules/jquery/package.json
node_modules/jquery/.jscsrc
node_modules/jquery/src/*
node_modules/jquery/dist/*
!node_modules/jquery/dist/jquery.js
node_modules/todomvc-common/*
!node_modules/todomvc-common/base.js
!node_modules/todomvc-common/base.css
node_modules/todomvc-app-css/*
!node_modules/todomvc-app-css/index.css
{
"name": "todomvc-canjs",
"version": "0.0.0",
"dependencies": {
"jquery": "~2.0.0",
"canjs": "~2.0.0",
"canjs-localstorage": "~0.2.0",
"todomvc-common": "~0.3.0"
}
}
......@@ -3,7 +3,8 @@
<head>
<meta charset="utf-8">
<title>CanJS • TodoMVC</title>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css">
<link rel="stylesheet" href="node_modules/todomvc-common/base.css">
<link rel="stylesheet" href="node_modules/todomvc-app-css/index.css">
</head>
<body>
<section id="todoapp">
......@@ -52,10 +53,10 @@
</footer>
</todo-app>
</script>
<script src="bower_components/todomvc-common/base.js"></script>
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/canjs/can.jquery.js"></script>
<script src="bower_components/canjs-localstorage/can.localstorage.js"></script>
<script src="node_modules/todomvc-common/base.js"></script>
<script src="node_modules/jquery/dist/jquery.js"></script>
<script src="node_modules/canjs/can.jquery.js"></script>
<script src="node_modules/canjs-localstorage/can.localstorage.js"></script>
<script src="js/models/todo.js"></script>
<script src="js/components/todo-app.js"></script>
<script src="js/app.js"></script>
......
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #c5c5c5;
border-bottom: 1px dashed #f7f7f7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
#issue-count {
display: none;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
.learn-bar {
width: auto;
padding-left: 300px;
}
.learn-bar > .learn {
left: 8px;
}
}
/* global _ */
(function () {
'use strict';
/* jshint ignore:start */
// Underscore's Template Module
// Courtesy of underscorejs.org
var _ = (function (_) {
......@@ -114,6 +116,7 @@
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'));
}
/* jshint ignore:end */
function redirect() {
if (location.hostname === 'tastejs.github.io') {
......@@ -175,13 +178,17 @@
if (learnJSON.backend) {
this.frameworkJSON = learnJSON.backend;
this.frameworkJSON.issueLabel = framework;
this.append({
backend: true
});
} else if (learnJSON[framework]) {
this.frameworkJSON = learnJSON[framework];
this.frameworkJSON.issueLabel = framework;
this.append();
}
this.fetchIssueCount();
}
Learn.prototype.append = function (opts) {
......@@ -212,6 +219,26 @@
document.body.insertAdjacentHTML('afterBegin', aside.outerHTML);
};
Learn.prototype.fetchIssueCount = function () {
var issueLink = document.getElementById('issue-count-link');
if (issueLink) {
var url = issueLink.href.replace('https://github.com', 'https://api.github.com/repos');
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function (e) {
var parsedResponse = JSON.parse(e.target.responseText);
if (parsedResponse instanceof Array) {
var count = parsedResponse.length
if (count !== 0) {
issueLink.innerHTML = 'This app has ' + count + ' open issues';
document.getElementById('issue-count').style.display = 'inline';
}
}
};
xhr.send();
}
};
redirect();
getFile('learn.json', Learn);
})();
{
"dependencies": {
"todomvc-common": "^1.0.0",
"jquery": "^2.1.3",
"todomvc-app-css": "^1.0.1"
},
"devDependencies": {
"napa": "^1.2.0"
},
"scripts": {
"postinstall": "napa https://github.com/bitovi/canjs.com/archive/v2.0.7.zip:canjs passy/canjs-localstorage#v0.2.0:canjs-localstorage"
}
}
node_modules/.bin/*
node_modules/canjs-localstorage/*
!node_modules/canjs-localstorage/can.localstorage.js
node_modules/napa/*
node_modules/canjs/steal/*
node_modules/canjs/amd-dev/*
node_modules/canjs/amd/can/view/*
node_modules/canjs/amd/can/route/*
node_modules/canjs/amd/can/construct/*
node_modules/canjs/amd/can/control/*
node_modules/canjs/amd/can/map/*
node_modules/canjs/amd/can/model/*
node_modules/canjs/amd/can/compute.js
node_modules/canjs/amd/can/construct.js
node_modules/canjs/amd/can/util/deferred.js
node_modules/canjs/amd/can/util/dojo.js
node_modules/canjs/amd/can/util/fixture.js
node_modules/canjs/amd/can/util/fragment.js
node_modules/canjs/amd/can/util/hashchange.js
node_modules/canjs/amd/can/util/mootools.js
node_modules/canjs/amd/can/util/object.js
node_modules/canjs/amd/can/util/object/isplain.js
node_modules/canjs/amd/can/util/yui.js
node_modules/canjs/amd/can/util/zepto.js
!node_modules/canjs/amd/can/view/node_lists.js
!node_modules/canjs/amd/can/view/elements.js
!node_modules/canjs/amd/can/view/live.js
!node_modules/canjs/amd/can/util/batch.js
!node_modules/canjs/amd/can/construct.js
!node_modules/canjs/amd/can/util/string.js
!node_modules/canjs/amd/can/util/can.js
!node_modules/canjs/amd/can/util/array/each.js
!node_modules/canjs/amd/can/util/inserted.js
!node_modules/canjs/amd/can/util/event.js
!node_modules/canjs/amd/can/compute.js
!node_modules/canjs/amd/can/view/scope.js
!node_modules/canjs/amd/can/view/scanner.js
!node_modules/canjs/amd/can/view/render.js
!node_modules/canjs/amd/can/util/bind.js
!node_modules/canjs/amd/can.js
!node_modules/canjs/amd/can/view.js
!node_modules/canjs/amd/can/view/mustache.js
!node_modules/canjs/amd/can/view/bindings.js
!node_modules/canjs/amd/can/route.js
!node_modules/canjs/amd/can/util/library.js
!node_modules/canjs/amd/can/util/jquery.js
!node_modules/canjs/amd/can/util/string/deparam.js
!node_modules/canjs/amd/can/component.js
!node_modules/canjs/amd/can/model.js
node_modules/canjs/bower.json
node_modules/canjs/can.construct.proxy.js
node_modules/canjs/can.construct.super.js
node_modules/canjs/can.control.plugin.js
node_modules/canjs/can.dojo.dev.js
node_modules/canjs/can.dojo.js
node_modules/canjs/can.dojo.min.js
node_modules/canjs/can.ejs.js
node_modules/canjs/can.fixture.js
node_modules/canjs/can.jquery.dev.js
node_modules/canjs/can.jquery.js
node_modules/canjs/can.jquery.min.js
node_modules/canjs/can.list.sort.js
node_modules/canjs/can.map.attributes.js
node_modules/canjs/can.map.backup.js
node_modules/canjs/can.map.delegate.js
node_modules/canjs/can.map.list.js
node_modules/canjs/can.map.setter.js
node_modules/canjs/can.map.validations.js
node_modules/canjs/can.model.queue.js
node_modules/canjs/can.mootools.dev.js
node_modules/canjs/can.mootools.js
node_modules/canjs/can.mootools.min.js
node_modules/canjs/can.object.js
node_modules/canjs/can.route.pushstate.js
node_modules/canjs/can.view.modifiers.js
node_modules/canjs/can.yui.dev.js
node_modules/canjs/can.yui.js
node_modules/canjs/can.yui.min.js
node_modules/canjs/can.zepto.dev.js
node_modules/canjs/can.zepto.js
node_modules/canjs/can.zepto.min.js
node_modules/canjs/package.json
node_modules/canjs/readme.md
node_modules/requirejs/*
!node_modules/requirejs/require.js
node_modules/requirejs/bin/*
node_modules/jquery/.bowerrc
node_modules/jquery/.npmignore
node_modules/jquery/AUTHORS.txt
node_modules/jquery/CONTRIBUTING.md
node_modules/jquery/MIT-LICENSE.txt
node_modules/jquery/README.md
node_modules/jquery/bower.json
node_modules/jquery/package.json
node_modules/jquery/.jscsrc
node_modules/jquery/src/*
node_modules/jquery/dist/*
!node_modules/jquery/dist/jquery.js
node_modules/todomvc-common/*
!node_modules/todomvc-common/base.js
!node_modules/todomvc-common/base.css
node_modules/todomvc-app-css/*
!node_modules/todomvc-app-css/index.css
{
"name": "todomvc-canjs-require",
"version": "0.0.0",
"dependencies": {
"todomvc-common": "~0.3.0",
"requirejs": "~2.1.6",
"canjs": "~2.0.0",
"canjs-localstorage": "~0.2.0",
"jquery": "~1.10.0"
}
}
/*!
* CanJS - 2.0.3
* http://canjs.us/
* Copyright (c) 2013 Bitovi
* Tue, 26 Nov 2013 18:21:22 GMT
* Licensed MIT
* Includes: CanJS default build
* Download from: http://canjs.us/
*/
define(["can/util/library", "can/control", "can/observe", "can/view/mustache", "can/view/bindings"], function(can){
var ignoreAttributesRegExp = /dataViewId|class|id/i
/**
* @add can.Component
*/
var Component = can.Component = can.Construct.extend(
/**
* @static
*/
{
setup: function(){
can.Construct.setup.apply( this, arguments );
if(can.Component){
var self = this;
this.Control = can.Control.extend({
_lookup: function(options){
return [options.scope, options, window]
}
},can.extend({
setup: function(el, options){
var res = can.Control.prototype.setup.call(this, el, options)
this.scope = options.scope;
// call on() whenever scope changes
var self = this;
this.on(this.scope,"change",function(){
self.on();
self.on(self.scope,"change",arguments.callee);
});
return res;
}
},this.prototype.events));
var attributeScopeMappings = {};
// go through scope and get attribute ones
can.each(this.prototype.scope, function(val, prop){
if(val === "@") {
attributeScopeMappings[prop] = prop;
}
})
this.attributeScopeMappings = attributeScopeMappings;
// If scope is an object,
if(! this.prototype.scope || typeof this.prototype.scope === "object" ){
// use that object as the prototype of an extened Map constructor function.
// A new instance of that Map constructor function will be created and
// set as this.scope.
this.Map = can.Map.extend( this.prototype.scope||{} );
}
// If scope is a can.Map constructor function,
else if(this.prototype.scope.prototype instanceof can.Map) {
// just use that.
this.Map = this.prototype.scope;
}
if(this.prototype.template){
if(typeof this.prototype.template == "function"){
var temp = this.prototype.template
this.renderer = function(){
return can.view.frag(temp.apply(null, arguments))
}
} else {
this.renderer =can.view.mustache( this.prototype.template );
}
}
can.view.Scanner.tag(this.prototype.tag,function(el, options){
new self(el, options)
});
}
}
},{
/**
* @prototype
*/
setup: function(el, hookupOptions){
// Setup values passed to component
var initalScopeData = {},
component = this,
twoWayBindings = {},
// what scope property is currently updating
scopePropertyUpdating,
// the object added to the scope
componentScope;
// scope prototype properties marked with an "@" are added here
can.each(this.constructor.attributeScopeMappings,function(val, prop){
initalScopeData[prop] = el.getAttribute(can.hyphenate(val));
})
// get the value in the scope for each attribute
// the hookup should probably happen after?
can.each(can.makeArray(el.attributes), function(node, index){
var name = can.camelize(node.nodeName.toLowerCase()),
value = node.value;
// ignore attributes already in ScopeMappings
if(component.constructor.attributeScopeMappings[name] || ignoreAttributesRegExp.test(name)){
return;
}
// Cross-bind the value in the scope to this
// component's scope
var computeData = hookupOptions.scope.computeData(value, {args: []}),
compute = computeData.compute;
// bind on this, check it's value, if it has dependencies
var handler = function(ev, newVal){
scopePropertyUpdating = name;
componentScope.attr(name, newVal);
scopePropertyUpdating = null;
}
// compute only returned if bindable
compute.bind("change", handler);
// set the value to be added to the scope
initalScopeData[name] = compute();
if(!compute.hasDependencies) {
compute.unbind("change", handler);
} else {
// make sure we unbind (there's faster ways of doing this)
can.bind.call(el,"removed",function(){
compute.unbind("change", handler);
})
// setup two-way binding
twoWayBindings[name] = computeData
}
})
if(this.constructor.Map){
componentScope = new this.constructor.Map(initalScopeData);
} else if(this.scope instanceof can.Map) {
componentScope = this.scope;
} else if(can.isFunction(this.scope)){
var scopeResult = this.scope(initalScopeData, hookupOptions.scope, el);
// if the function returns a can.Map, use that as the scope
if(scopeResult instanceof can.Map){
componentScope = scopeResult
} else if( scopeResult.prototype instanceof can.Map ){
componentScope = new scopeResult(initalScopeData);
} else {
componentScope = new ( can.Map.extend(scopeResult) )(initalScopeData);
}
}
var handlers = {};
// setup reverse bindings
can.each(twoWayBindings, function(computeData, prop){
handlers[prop] = function(ev, newVal){
// check that this property is not being changed because
// it's source value just changed
if(scopePropertyUpdating !== prop){
computeData.compute(newVal)
}
}
componentScope.bind(prop, handlers[prop])
});
// teardown reverse bindings when element is removed
can.bind.call(el,"removed",function(){
can.each(handlers, function(handler, prop){
componentScope.unbind(prop, handlers[prop])
})
})
this.scope = componentScope;
can.data(can.$(el),"scope", this.scope)
// create a real Scope object out of the scope property
var renderedScope = hookupOptions.scope.add( this.scope ),
// setup helpers to callback with `this` as the component
helpers = {};
can.each(this.helpers || {}, function(val, prop){
if(can.isFunction(val)) {
helpers[prop] = function(){
return val.apply(componentScope, arguments)
}
}
});
// create a control to listen to events
this._control = new this.constructor.Control(el, {scope: this.scope});
// if this component has a template (that we've already converted to a renderer)
if( this.constructor.renderer ) {
// add content to tags
if(!helpers._tags){
helpers._tags = {};
}
// we need be alerted to when a <content> element is rendered so we can put the original contents of the widget in its place
helpers._tags.content = function(el, rendererOptions){
// first check if there was content within the custom tag
// otherwise, render what was within <content>, the default code
var subtemplate = hookupOptions.subtemplate || rendererOptions.subtemplate
if(subtemplate) {
var frag = can.view.frag( subtemplate(rendererOptions.scope, rendererOptions.options.add(helpers) ) );
can.insertBefore(el.parentNode, frag, el);
can.remove( can.$(el) );
}
}
// render the component's template
var frag = this.constructor.renderer( renderedScope, helpers);
} else {
// otherwise render the contents between the
var frag = can.view.frag( hookupOptions.subtemplate ? hookupOptions.subtemplate(renderedScope, hookupOptions.options.add(helpers)) : "");
}
can.appendChild(el, frag);
}
})
if(window.$ && $.fn){
$.fn.scope = function(attr){
if( attr ) {
return this.data("scope").attr(attr)
} else {
return this.data("scope")
}
}
}
can.scope = function(el, attr){
var el = can.$(el);
if( attr ){
return can.data(el,"scope").attr(attr)
} else {
return can.data(el, "scope")
}
}
return Component;
});
\ No newline at end of file
/*!
* CanJS - 2.0.3
* http://canjs.us/
* Copyright (c) 2013 Bitovi
* Tue, 26 Nov 2013 18:21:22 GMT
* Licensed MIT
* Includes: CanJS default build
* Download from: http://canjs.us/
*/
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.Map, 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 - 2.0.3
* http://canjs.us/
* Copyright (c) 2013 Bitovi
* Tue, 26 Nov 2013 18:21:22 GMT
* Licensed MIT
* Includes: CanJS default build
* Download from: http://canjs.us/
*/
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 - 2.0.3
* http://canjs.us/
* Copyright (c) 2013 Bitovi
* Tue, 26 Nov 2013 18:21:22 GMT
* Licensed MIT
* Includes: CanJS default build
* Download from: http://canjs.us/
*/
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 ) {
var name = instance.constructor.pluginName || instance.constructor._shortName;
for ( i = 0; i < controllers.length; i++ ) {
if ( typeof controllers[i] == 'string' ? name == controllers[i] : instance instanceof controllers[i] ) {
return true;
}
}
return false;
},
makeArray = can.makeArray,
old = can.Control.setup;
/*
* static
*/
can.Control.setup = function() {
// if you didn't provide a name, or are control, don't do anything
if ( this !== can.Control ) {
/**
* @property {String} can.Control.plugin.static.pluginName pluginName
* @parent can.Control.plugin
*
* @description
*
* Allows you to define the name of the jQuery plugin.
*
* @body
*
* Setting the static `pluginName` property allows you to override the default name
* with your own.
*
* var Filler = can.Control({
* pluginName: 'fillWith'
* },{});
*
* $("#foo").fillWith();
*
* If you don't provide a `pluginName`, the control falls back to the
* [can.Construct.fullName fullName] attribute:
*
* can.Control('Ui.Layout.FillWith', {}, {});
* $("#foo").ui_layout_fill_with();
*
*/
var pluginName = this.pluginName || this._fullName;
// create jQuery plugin
if(pluginName !== 'can_control'){
this.plugin(pluginName);
}
old.apply(this, arguments);
}
};
/*
* prototype
*/
$.fn.extend({
/**
* @function jQuery.fn.controls jQuery.fn.controls
* @parent can.Control.plugin
* @description Get the Controls associated with elements.
* @signature `jQuery.fn.controls([type])`
* @param {String|can.Control} [control] The type of Controls to find.
* @return {can.Control} The controls associated with the given elements.
*
* @body
* When the widget is initialized, the plugin control creates an array
* of control instance(s) with the DOM element it was initialized on using
* [can.data] method.
*
* The `controls` method allows you to get the control instance(s) for any element
* either by their type or pluginName.
*
* var MyBox = can.Control({
* pluginName : 'myBox'
* }, {});
*
* var MyClock = can.Control({
* pluginName : 'myClock'
* }, {});
*
*
* //- Inits the widgets
* $('.widgets:eq(0)').myBox();
* $('.widgets:eq(1)').myClock();
*
* $('.widgets').controls() //-> [ MyBox, MyClock ]
* $('.widgets').controls('myBox') // -> [MyBox]
* $('.widgets').controls(MyClock) // -> MyClock
*
*/
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;
},
/**
* @function jQuery.fn.control jQuery.fn.control
* @parent can.Control.plugin
* @description Get the Control associated with elements.
* @signature `jQuery.fn.control([type])`
* @param {String|can.Control} [control] The type of Control to find.
* @return {can.Control} The first control found.
*
* @body
* This is the same as [jQuery.fn.controls $().controls] except that
* it only returns the first Control found.
*
* //- Init MyBox widget
* $('.widgets').my_box();
*
* <div class="widgets my_box" />
*
* $('.widgets').controls() //-> MyBox
*/
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;
};
}
}
/**
* @function can.Control.plugin.prototype.update update
* @parent can.Control.plugin
*
* @description Reconfigure a control.
* @signature `update(newOptions)`
* @param {Object} newOptions Options to merge into the current options.
*
* @body
* Update extends [can.Control.prototype.options options]
* with the `options` argument and rebinds all events. It
* re-configures the control.
*
* For example, the following control wraps a recipe form. When the form
* is submitted, it creates the recipe on the server. When the recipe
* is `created`, it resets the form with a new instance.
*
* var Creator = can.Control({
* "{recipe} created" : function(){
* this.update({recipe : new Recipe()});
* this.element[0].reset();
* this.element.find("[type=submit]").val("Create Recipe")
* },
* "submit" : function(el, ev){
* ev.preventDefault();
* var recipe = this.options.recipe;
* recipe.attrs( this.element.formParams() );
* this.element.find("[type=submit]").val("Saving...")
* recipe.save();
* }
* });
*
* $('#createRecipes').creator({ recipe : new Recipe() })
*
* *Update* is called if a control's plugin helper is called with the plugin options on an element
* that already has a control instance of the same type. If you want to implement your
* own update method make sure to call the old one either using the [can.Construct.super super] plugin or
* by calling `can.Control.prototype.update.apply(this, arguments);`.
* For example, you can change the content of the control element every time the options change:
*
* var Plugin = can.Control({
* pluginName: 'myPlugin'
* }, {
* init : function(el, options) {
* this.updateCount = 0;
* this.update({
* text : 'Initialized'
* });
* },
* update : function(options) {
* // Call the can.Control update first.
* // Use this._super when using can/construct/super
* can.Control.prototype.update.call(this, options);
* this.element.html(this.options.text + ' ' +
* (++this.updateCount) + ' times');
* }
* });
*
* $('#control').myPlugin();
* $('#control').html();
* // Initialized. Updated 1 times
*
* $('#control').myPlugin({ text : 'Calling update. Updated' });
* $('#control').html();
* // Calling update. Updated 2 times
*
* @demo can/control/plugin/demo-update.html
*
* @param {Object} options A list of options to merge with
* [can.Control.prototype.options this.options]. Often this method
* is called by the [can.Control.plugin jQuery helper function].
*/
can.Control.prototype.update = function( options ) {
can.extend(this.options, options);
this.on();
};
return can;
});
\ No newline at end of file
/*!
* CanJS - 2.0.3
* http://canjs.us/
* Copyright (c) 2013 Bitovi
* Tue, 26 Nov 2013 18:21:22 GMT
* Licensed MIT
* Includes: CanJS default build
* Download from: http://canjs.us/
*/
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 || "";
if ( !can.route.routes[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
/*!
* CanJS - 2.0.3
* http://canjs.us/
* Copyright (c) 2013 Bitovi
* Tue, 26 Nov 2013 18:21:22 GMT
* Licensed MIT
* Includes: CanJS default build
* Download from: http://canjs.us/
*/
define(["can/util/library", "can/map", "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.Map.prototype, {
/**
* @function can.Map.backup.prototype.backup backup
* @plugin can/map/backup
* @parent can.Map.backup
*
* @description Save the values of the properties of an Map.
*
* @signature `map.backup()`
*
* `backup` backs up the current state of the properties of an Observe and marks
* the Observe as clean. If any of the properties change value, the original
* values can be restored with [can.Map.backup.prototype.restore restore].
*
* @return {can.Map} The map, for chaining.
*
* @body
*
* ## Example
*
* @codestart
* var recipe = new can.Map({
* title: 'Pancake Mix',
* yields: '3 batches',
* ingredients: [{
* ingredient: 'flour',
* quantity: '6 cups'
* },{
* ingredient: 'baking soda',
* quantity: '1 1/2 teaspoons'
* },{
* ingredient: 'baking powder',
* quantity: '3 teaspoons'
* },{
* ingredient: 'salt',
* quantity: '1 tablespoon'
* },{
* ingredient: 'sugar',
* quantity: '2 tablespoons'
* }]
* });
* recipe.backup();
*
* recipe.attr('title', 'Flapjack Mix');
* recipe.title; // 'Flapjack Mix'
*
* recipe.restore();
* recipe.title; // 'Pancake Mix'
* @codeend
*/
backup : function () {
this._backupStore = this._attrs();
return this;
},
/**
* @function can.Map.backup.prototype.isDirty isDirty
* @plugin can/map/backup
* @parent can.Map.backup
*
* @description Check whether an Observe has changed since the last time it was backed up.
*
* @signature `map.isDirty([deep])`
*
* `isDirty` checks whether any properties have changed value or whether any properties have
* been added or removed since the last time the Observe was backed up. If _deep_ is `true`,
* If the Observe has never been backed up, `isDirty` returns `undefined`.
* `isDirty` will include nested Observes in its checks.
*
* @param {bool} [deep=false] whether to check nested Observes
* @return {bool} Whether the Observe has changed since the last time it was [can.Map.backup.prototype.backup backed up].
*
* @codestart
* var recipe = new can.Map({
* title: 'Pancake Mix',
* yields: '3 batches',
* ingredients: [{
* ingredient: 'flour',
* quantity: '6 cups'
* },{
* ingredient: 'baking soda',
* quantity: '1 1/2 teaspoons'
* },{
* ingredient: 'baking powder',
* quantity: '3 teaspoons'
* },{
* ingredient: 'salt',
* quantity: '1 tablespoon'
* },{
* ingredient: 'sugar',
* quantity: '2 tablespoons'
* }]
* });
*
* recipe.isDirty(); // false
* recipe.backup();
*
* recipe.attr('title', 'Flapjack Mix');
* recipe.isDirty(); // true
* recipe.restore();
* recipe.isDirty(); // false
*
* recipe.attr('ingredients.0.quantity', '7 cups');
* recipe.isDirty(); // false
* recipe.isDirty(true); // true
*
* recipe.backup();
* recipe.isDirty(); // false
* recipe.isDirty(true); // false
* @codeend
*/
isDirty : function (checkAssociations) {
return this._backupStore &&
!can.Object.same(this._attrs(),
this._backupStore,
undefined,
undefined,
undefined,
!!checkAssociations);
},
/**
* @function can.Map.backup.prototype.restore restore
* @plugin can/map/backup
* @parent can.Map.backup
*
* @description Restore saved values of an Observe's properties.
*
* @signature `map.restore( [deep] )`
*
* `restore` sets the properties of an Observe back to what they were the last time
* [can.Map.backup.prototype.backup backup] was called. If _deep_ is `true`,
* `restore` will also restore the properties of nested Observes.
*
* `restore` will not remove properties that were added since the last backup, but it
* will re-add properties that have been removed.
*
* @param {bool} [deep=false] whether to restore properties in nested Observes
* @return {can.Map} The Observe, for chaining.
*
*
*
* @codestart
* var recipe = new can.Map({
* title: 'Pancake Mix',
* yields: '3 batches',
* ingredients: [{
* ingredient: 'flour',
* quantity: '6 cups'
* },{
* ingredient: 'baking soda',
* quantity: '1 1/2 teaspoons'
* },{
* ingredient: 'baking powder',
* quantity: '3 teaspoons'
* },{
* ingredient: 'salt',
* quantity: '1 tablespoon'
* },{
* ingredient: 'sugar',
* quantity: '2 tablespoons'
* }]
* });
*
* recipe.backup();
*
* recipe.attr('title', 'Flapjack Mix');
* recipe.restore();
* recipe.attr('title'); // 'Pancake Mix'
*
* recipe.attr('ingredients.0.quantity', '7 cups');
* recipe.restore();
* recipe.attr('ingredients.0.quantity'); // '7 cups'
* recipe.restore(true);
* recipe.attr('ingredients.0.quantity'); // '6 cups'
* @codeend
*
* ## Events
* When `restore` sets values or re-adds properties, the same events will be fired (including
* _change_, _add_, and _set_) as if the values of the properties had been set using `[can.Map.prototype.attr attr]`.
*/
restore : function (restoreAssociations) {
var props = restoreAssociations ? this._backupStore : flatProps(this._backupStore)
if (this.isDirty(restoreAssociations)) {
this._attrs(props);
}
return this;
}
})
return can.Map;
});
\ No newline at end of file
/*!
* CanJS - 2.0.3
* http://canjs.us/
* Copyright (c) 2013 Bitovi
* Tue, 26 Nov 2013 18:21:22 GMT
* Licensed MIT
* Includes: CanJS default build
* Download from: http://canjs.us/
*/
define(["can/util/library", "can/map", "can/list", "can/compute"], function(can) {
can.extend(can.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.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.splice(index, 0, 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;
}
/** TODO
,
every : function() {
},
some : function(callback) {
},
reduce : function() {
},
reduceRight : function() {
},
max : function() {
},
min : function() {
}
*/
});
return can.List;
});
\ No newline at end of file
......@@ -3,7 +3,8 @@
<head>
<meta charset="utf-8">
<title>CanJS + RequireJS • TodoMVC</title>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css">
<link rel="stylesheet" href="node_modules/todomvc-common/base.css">
<link rel="stylesheet" href="node_modules/todomvc-app-css/index.css">
</head>
<body>
<section id="todoapp"></section>
......@@ -50,7 +51,7 @@
</footer>
</todo-app>
</script>
<script src="bower_components/todomvc-common/base.js"></script>
<script data-main="js/app" src="bower_components/requirejs/require.js"></script>
<script src="node_modules/todomvc-common/base.js"></script>
<script data-main="js/app" src="node_modules/requirejs/require.js"></script>
</body>
</html>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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