can.view.modifiers.js | |
---|---|
/*!
* CanJS - 1.1.4 (2013-02-05)
* http://canjs.us/
* Copyright (c) 2013 Bitovi
* Licensed MIT
*/
(function (window, $, can, undefined) { | |
can/view/modifiers/modifiers.js---- ADD jQUERY HELPERS ----- converts jquery functions to use views | var convert, modify, isTemplate, isHTML, isDOM, getCallback, |
text and val cannot produce an element, so don't run hookups on them | noHookup = {
'val': true,
'text': true
};
convert = function (func_name) { |
save the old jQuery helper | var old = $.fn[func_name]; |
replace it with our new helper | $.fn[func_name] = function () {
var args = can.makeArray(arguments),
callbackNum, callback, self = this,
result; |
if the first arg is a deferred wait until it finishes, and call modify with the result | if (can.isDeferred(args[0])) {
args[0].done(function (res) {
modify.call(self, [res], old);
})
return this;
} |
check if a template | else if (isTemplate(args)) { |
if we should operate async | if ((callbackNum = getCallback(args))) {
callback = args[callbackNum];
args[callbackNum] = function (result) {
modify.call(self, [result], old);
callback.call(self, result);
};
can.view.apply(can.view, args);
return this;
} |
call view with args (there might be deferreds) | result = can.view.apply(can.view, args); |
if we got a string back | if (!can.isDeferred(result)) { |
we are going to call the old method with that string | args = [result];
} else { |
if there is a deferred, wait until it is done before calling modify | result.done(function (res) {
modify.call(self, [res], old);
})
return this;
}
}
return noHookup[func_name] ? old.apply(this, args) : modify.call(this, args, old);
};
}; |
modifies the content of the element but also will run any hookup | modify = function (args, old) {
var res, stub, hooks; |
check if there are new hookups | for (var hasHookups in can.view.hookups) {
break;
} |
if there are hookups, turn into a frag and insert that by using a frag, the element can be recursively hooked up before insterion | if (hasHookups && args[0] && isHTML(args[0])) {
args[0] = can.view.frag(args[0]).childNodes;
} |
then insert into DOM | res = old.apply(this, args);
return res;
}; |
returns true or false if the args indicate a template is being used $('#foo').html('/path/to/template.ejs',{data}) in general, we want to make sure the first arg is a string and the second arg is data | isTemplate = function (args) { |
save the second arg type | var secArgType = typeof args[1]; |
the first arg is a string | return typeof args[0] == "string" && |
the second arg is an object or function | (secArgType == 'object' || secArgType == 'function') && |
but it is not a dom element | !isDOM(args[1]);
}; |
returns true if the arg is a jQuery object or HTMLElement | isDOM = function (arg) {
return arg.nodeType || (arg[0] && arg[0].nodeType)
}; |
returns whether the argument is some sort of HTML data | isHTML = function (arg) {
if (isDOM(arg)) { |
if jQuery object or DOM node we're good | return true;
} else if (typeof arg === "string") { |
if string, do a quick sanity check that we're HTML | arg = can.trim(arg);
return arg.substr(0, 1) === "<" && arg.substr(arg.length - 1, 1) === ">" && arg.length >= 3;
} else { |
don't know what you are | return false;
}
}; |
returns the callback arg number if there is one (for async view use) | getCallback = function (args) {
return typeof args[3] === 'function' ? 3 : typeof args[2] === 'function' && 2;
};
$.fn.hookup = function () {
can.view.frag(this);
return this;
};
can.each([
"prepend",
"append",
"after",
"before",
"text",
"html",
"replaceWith", "val"], function (func) {
convert(func);
});
})(this, jQuery, can);
|