Skip to content

Commit

Permalink
Don't bind to templates with undefined values
Browse files Browse the repository at this point in the history
  • Loading branch information
daffl committed Nov 27, 2012
1 parent 32b5af9 commit e90bc56
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 42 deletions.
7 changes: 4 additions & 3 deletions build/build.js
Expand Up @@ -80,22 +80,23 @@ function (testConfig, pluginify, amdify, EJS, libs) {
* Build the AMD module distributable
*/
var buildAmd = function() {
var excludes = [ "can/build/make/amd.js" ];
var excludes = [ "can/build/make/amd.js", "can/util/util.js" ];
_.each(_.values(libs), function(val) {
excludes = excludes.concat(val.exclude);
});
steal.build.amdify('can/build/make/amd.js', {
out: outFolder + '/amd',
exclude: excludes,
map : {
'can/util' : 'can/util.js'
'can/util' : 'can/util/library',
'can/util/jquery' : 'can/util/library'
}
});
};

steal.File(outFolder).mkdirs();

_.each(libraries, buildLibrary);
buildAmd();
buildjQueryAll();
buildAmd();
});
2 changes: 1 addition & 1 deletion build/make/amd.js
Expand Up @@ -2,7 +2,7 @@ steal('can/can.js', 'can/construct/proxy', 'can/construct/super', 'can/control',
'can/control/view', 'can/view/modifiers', 'can/model', 'can/view/ejs', 'can/view/mustache',
'can/observe/attributes', 'can/observe/delegate', 'can/observe/setter',
'can/observe/validations', 'can/route', 'can/view/modifiers', 'can/observe/backup',
'can/util/fixture', 'can/util/util.js', 'can/util/mootools', 'can/util/dojo', 'can/util/yui',
'can/util/fixture', 'can/util/library.js', 'can/util/mootools', 'can/util/dojo', 'can/util/yui',
'can/util/zepto', 'can/util/jquery',
function(can) {
return can;
Expand Down
25 changes: 12 additions & 13 deletions control/control.js
Expand Up @@ -138,11 +138,13 @@ steal('can/util','can/construct', function( can ) {
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 a `{}` template resolves to an object, `convertedName` will be
// an array
arr = can.isArray(convertedName),
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,
Expand Down Expand Up @@ -550,14 +552,11 @@ steal('can/util','can/construct', function( can ) {
funcName, ready;

for ( funcName in actions ) {
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));
// 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));
}
}

Expand Down
18 changes: 17 additions & 1 deletion control/control_test.js
Expand Up @@ -325,6 +325,22 @@

can.trigger(item1, "foo");
can.trigger(item2, "bar");
})
});

test("Don't bind if there are undefined values in templates", function() {
can.Control.processors.proc = function() {
ok(false, 'This processor should never be called');
}

var Control = can.Control({
}, {
'{noExistStuff} proc' : function() {

}
});

var c = new Control(document.createElement('div'));
equal(c._bindings.length, 1, 'There is only one binding');
});

})();
19 changes: 9 additions & 10 deletions control/modifier/modifier_test.js
Expand Up @@ -25,19 +25,14 @@ steal('can/util', 'can/control/modifier', function (can) {
});


asyncTest("pluginName", function () {

test("pluginName", function () {
stop();
var controllerClass = can.Control({
defaults : {
binder : undefined
}
}, {

init : function () {
this.options.binder = $(document.body);
this.on();
},

" click:debounce(30)" : function () {
ok(this instanceof can.Control, "Debounced function has the correct context.");
fooToTheBar = true;
Expand All @@ -57,8 +52,12 @@ steal('can/util', 'can/control/modifier', function (can) {
$('#test-content').html('<div id="foo"></div><div id="bar"></div>');

/**/
var controller1 = new controllerClass("#foo"),
controller2 = new controllerClass("#bar"),
var controller1 = new controllerClass("#foo", {
binder : $(document.body)
}),
controller2 = new controllerClass("#bar", {
binder : $(document.body)
}),
run = 0,
run2 = 0,
fooToTheBar;
Expand Down Expand Up @@ -97,7 +96,7 @@ steal('can/util', 'can/control/modifier', function (can) {
$(document.body).trigger('click');

setTimeout(function () {
ok(run === 5, "`run` is 5");
equal(run, 4, "`run` is 4");
start();
}, 40);
}, 40);
Expand Down
2 changes: 1 addition & 1 deletion grunt.js
Expand Up @@ -78,7 +78,7 @@ module.exports = function (grunt) {
},
downloads : '<json:build/downloads.json>',
docco : _.extend({_options : {
exclude : [/\.min\./, /\/amd/, /qunit\.js/]
exclude : [/\.min\./, /amd\//, /qunit\.js/]
}
}, outFiles),
strip : outFiles,
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,7 +1,7 @@
{
"name" : "CanJS",
"description" : "MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.",
"version" : "1.1.1",
"version" : "1.1.2",
"author" : {
"name" : "Bitovi",
"email" : "contact@bitovi.com",
Expand Down
2 changes: 1 addition & 1 deletion util/event.js
@@ -1,4 +1,4 @@
steal('./can.js',function(can){
steal('can/util/can.js',function(can){

// event.js
// ---------
Expand Down
2 changes: 1 addition & 1 deletion util/fragment.js
@@ -1,4 +1,4 @@
steal('./can.js',function(can){
steal('can/util/can.js',function(can){

// fragment.js
// ---------
Expand Down
4 changes: 4 additions & 0 deletions util/library.js
@@ -0,0 +1,4 @@
// This is the same as can/util/util.js but used for the AMD build
steal('can/util/jquery', function(can) {
return can;
});
17 changes: 11 additions & 6 deletions util/string/string.js
Expand Up @@ -162,26 +162,31 @@ steal('can/util',function(can) {
* @param {Object} data The data to be used to look for properties. If it's an array, multiple
* objects can be used.
* @param {Boolean} [remove] if a match is found, remove the property from the object
* @return The converted string or `null` if any data to render are `undefined`
*/
sub: function( str, data, remove ) {

var obs = [];

obs.push( str.replace( replacer, function( whole, inside ) {

// Convert inside to type.
var ob = can.getObject( inside, data, remove === undefined? remove : !remove );


if(ob === undefined) {
obs = null;
return "";
}

// If a container, push into objs (which will return objects found).
if ( isContainer( ob ) ) {
if ( isContainer( ob ) && obs ) {
obs.push( ob );
return "";
} else {
return "" + ob;
}

return "" + ob;
}));

return obs.length <= 1 ? obs[0] : obs;
return obs === null ? obs : (obs.length <= 1 ? obs[0] : obs);
},

// These regex's are used throughout the rest of can, so let's make
Expand Down
13 changes: 9 additions & 4 deletions util/string/string_test.js
Expand Up @@ -3,21 +3,26 @@ steal('funcunit/qunit', './string', function(qunit, can){
module("can/util/string")

test("can.sub", function(){
equals(can.sub("a{b}",{b: "c"}),"ac")
equals(can.sub("a{b}",{b: "c"}),"ac");

var foo = {b: "c"};

equals(can.sub("a{b}",foo,true),"ac");
ok(!foo.b,"b's value was removed")
ok(!foo.b,"b's value was removed");
});

test("can.sub with undefined values", function() {
var subbed = can.sub('test{exists} plus{noexists}', { exists : 'test' });
ok(subbed === null, 'Rendering with undefined values should return undefined');
});

test("can.sub double", function(){
equals(can.sub("{b} {d}",[{b: "c", d: "e"}]),"c e");
})
});

test("String.underscore", function(){
equals(can.underscore("Foo.Bar.ZarDar"),"foo.bar.zar_dar")
})
});


test("can.getObject", function(){
Expand Down

0 comments on commit e90bc56

Please sign in to comment.