Permalink
Browse files

Don't bind to templates with undefined values

  • Loading branch information...
daffl committed Nov 27, 2012
1 parent 32b5af9 commit e90bc56d9c1ec46ae01f084ccbcab43c9c611d0c
View
@@ -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();
});
View
@@ -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;
View
@@ -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,
@@ -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));
}
}
View
@@ -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');
+ });
})();
@@ -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;
@@ -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;
@@ -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);
View
@@ -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,
View
@@ -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",
View
@@ -1,4 +1,4 @@
-steal('./can.js',function(can){
+steal('can/util/can.js',function(can){
// event.js
// ---------
View
@@ -1,4 +1,4 @@
-steal('./can.js',function(can){
+steal('can/util/can.js',function(can){
// fragment.js
// ---------
View
@@ -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;
+});
View
@@ -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
View
@@ -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(){

0 comments on commit e90bc56

Please sign in to comment.