Skip to content

Commit

Permalink
Introduction of data-dojo-bind.
Browse files Browse the repository at this point in the history
  • Loading branch information
asudoh committed Mar 15, 2012
1 parent 15598c8 commit c022e39
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 93 deletions.
126 changes: 40 additions & 86 deletions ParserExtension.js
Expand Up @@ -19,85 +19,48 @@ define([
try{ has.add("dojo-parser", !!require("dojo/parser")); }catch(e){}
try{ has.add("dojo-mobile-parser", !!require("dojox/mobile/parser")); }catch(e){}

function _eval(/*String*/ s){
return eval("(" + s + ")");
}

if(has("dojo-parser")){
var oldConstruct = parser.construct, oldScan = parser.scan;

if(!has("dojox-mvc-binding-in-props-only")){
parser.construct = /*====== dojo.parser.construct = ======*/ function(/*Function*/ ctor, /*DOMNode*/ node, /*Object?*/ mixin, /*Object?*/ options, /*DOMNode[]?*/ scripts, /*Object?*/ inherited){
// summary:
// Calls new ctor(params, node), where params is the hash of parameters specified on the node,
// excluding data-dojo-type and data-dojo-mixins. Does not call startup(). Returns the widget.
// ctor: Function
// Widget constructor.
// node: DOMNode
// This node will be replaced/attached to by the widget. It also specifies the arguments to pass to ctor.
// mixin: Object?
// Attributes in this object will be passed as parameters to ctor,
// overriding attributes specified on the node.
// options: Object?
// An options object used to hold kwArgs for instantiation. See parse.options argument for details.
// scripts: DOMNode[]?
// Array of <script type="dojo/*"> DOMNodes. If not specified, will search for <script> tags inside node.
// inherited: Object?
// Settings from dir=rtl or lang=... on a node above this node. Overrides options.inherited.

var attrData = "data-" + (options.scope || kernel._scopeName) + "-", // typically "data-dojo-"
dataDojoProps = attrData + "props", // typically "data-dojo-props"
extra = node.getAttribute(dataDojoProps),
props = lang.mixin({}, mixin);

for(var attribs = node.attributes, i = attribs.length - 1; i >= 0; i--){
try{
var v = eval("(" + attribs[i].value + ")");
if((v || {}).atsignature == "dojox.mvc.at"){
props[attribs[i].name.replace(/^data\-dojo\-bind\-text$/i, "value")] = v;
attribs[i].value = "";
}
}catch(e){}
}

if(extra){
try{
lang.mixin(props, eval("({" + extra + "})"));
}catch(e){
// give the user a pointer to their invalid parameters. FIXME: can we kill this in production?
throw new Error(e.toString() + " in data-dojo-props='" + extra + "'");
}
parser.construct = /*====== dojo.parser.construct = ======*/ function(/*Function*/ ctor, /*DOMNode*/ node, /*Object?*/ mixin, /*Object?*/ options, /*DOMNode[]?*/ scripts, /*Object?*/ inherited){
// summary:
// TODOC

var attrData = "data-" + (options.scope || kernel._scopeName) + "-", // typically "data-dojo-"
dataDojoBind = attrData + "bind", // typically "data-dojo-bind"
bind = node.getAttribute(dataDojoBind),
props = lang.mixin({}, mixin);

// Mix things found in data-dojo-props into the params, overriding any direct settings
if(bind){
try{
props.refs = _eval.call(options.propsThis, "{" + bind + "}");
}catch(e){
// give the user a pointer to their invalid parameters. FIXME: can we kill this in production?
throw new Error(e.toString() + " in data-dojo-bind='" + bind + "'");
}
}

return oldConstruct.call(this, ctor, node, props, options, scripts, inherited);
};
}
return oldConstruct.call(this, ctor, node, props, options, scripts, inherited);
};

parser.scan = /*====== dojo.parser.scan = ======*/ function(/*DomNode?*/ root, /*Object*/ options){
parser.scan = /*====== dojo.parser.scan = ======*/ function(/*DOMNode?*/ root, /*Object*/ options){
// summary:
// root: DomNode?
// A default starting root node from which to start the parsing. See dojo.parser.scan() for more details.
// options: Object
// A kwArgs options object, see dojo.parser.parse() for details.
// TODOC

var list = oldScan.apply(this, lang._toArray(arguments)),
dojoType = (options.scope || kernel._scopeName) + "Type", // typically "dojoType"
attrData = "data-" + (options.scope || kernel._scopeName) + "-", // typically "data-dojo-"
dataDojoType = attrData + "type", // typically "data-dojo-type"
dataDojoProps = attrData + "props"; // typically "data-dojo-props"
dataDojoBind = attrData + "bind"; // typically "data-dojo-bind"

for(var nodes = has("dom-qsa") && has("dojox-mvc-binding-in-props-only") ? root.querySelectorAll("[" + dataDojoProps + "]") : root.getElementsByTagName("*"), i = 0, l = nodes.length; i < l; i++){
for(var nodes = has("dom-qsa") ? root.querySelectorAll("[" + dataDojoBind + "]") : root.getElementsByTagName("*"), i = 0, l = nodes.length; i < l; i++){
var node = nodes[i], foundBindingInAttribs = false;

if(!has("dojox-mvc-binding-in-props-only")){
for(var attribs = node.attributes, j = 0, m = attribs && attribs.length; j < m; j++){
try{
var v = eval("(" + attribs[j].value + ")");
if((v || {}).atsignature == "dojox.mvc.at"){
foundBindingInAttribs = true;
break;
}
}catch(e){}
}
}

if(!node.getAttribute(dataDojoType) && !node.getAttribute(dojoType) && (node.getAttribute(dataDojoProps) || foundBindingInAttribs)){
if(!node.getAttribute(dataDojoType) && !node.getAttribute(dojoType) && node.getAttribute(dataDojoBind)){
list.push({
"type": /^select|input|textarea$/i.test(node.tagName) ? "dojox/mvc/FormElement" : "dojox/mvc/Element",
node: node
Expand All @@ -112,35 +75,26 @@ define([
if(has("dojo-mobile-parser")){
var oldParse = mobileParser.parse;

mobileParser.parse = /*====== dojox.mobile.parser.parse = ======*/ function(/*DomNode?*/ root, /*Object*/ options){
mobileParser.parse = /*====== dojox.mobile.parser.parse = ======*/ function(/*DOMNode?*/ root, /*Object*/ options){
// summary:
// TODOC

var dojoType = ((options || {}).scope || kernel._scopeName) + "Type", // typically "dojoType"
attrData = "data-" + ((options || {}).scope || kernel._scopeName) + "-", // typically "data-dojo-"
dataDojoType = attrData + "type", // typically "data-dojo-type"
dataDojoBind = attrData + "bind", // typically "data-dojo-bind"
dataDojoProps = attrData + "props", // typically "data-dojo-props"
nodes = has("dom-qsa") && has("dojox-mvc-binding-in-props-only") ? (root || win.body()).querySelectorAll("[" + dataDojoProps + "]") : (root || win.body()).getElementsByTagName("*");
nodes = has("dom-qsa") ? (root || win.body()).querySelectorAll("[" + dataDojoBind + "]") : (root || win.body()).getElementsByTagName("*");

for(var i = 0, l = nodes.length; i < l; i++){
var node = nodes[i], foundBindingInAttribs = false, bindingsInAttribs = [];

if(!has("dojox-mvc-binding-in-props-only")){
for(var attribs = node.attributes, j = attribs && (attribs.length - 1); j >= 0; j--){
try{
var v = eval("(" + attribs[j].value + ")");
if((v || {}).atsignature == "dojox.mvc.at"){
bindingsInAttribs.push("'" + [attribs[j].name.replace(/^data\-dojo\-bind\-text$/i, "value")] + "':" + attribs[j].value);
attribs[j].value = "";
foundBindingInAttribs = true;
}
}catch(e){}
}
}

if(!node.getAttribute(dataDojoType) && !node.getAttribute(dojoType) && (node.getAttribute(dataDojoProps) || foundBindingInAttribs)){
if(!node.getAttribute(dataDojoType) && !node.getAttribute(dojoType) && node.getAttribute(dataDojoBind)){
node.setAttribute(dataDojoType, /^select|input|textarea$/i.test(node.tagName) ? "dojox/mvc/FormElement" : "dojox/mvc/Element");
if(!has("dojox-mvc-binding-in-props-only")){
var props = node.getAttribute(dataDojoProps);
node.setAttribute(dataDojoProps, bindingsInAttribs.concat(props ? [props] : []).join(","));
}
}
var bind = node.getAttribute(dataDojoBind);
if(bind){
var props = node.getAttribute(dataDojoProps);
node.setAttribute(dataDojoProps, (props ? [props] : []).concat(bind ? [bind] : []).join(","));
}
}

Expand Down
2 changes: 1 addition & 1 deletion _atBindingMixin.js
Expand Up @@ -110,7 +110,7 @@ define([
// See if any parameters for this widget are dojox.mvc.at handles.
// If so, move them under this._refs to prevent widget implementations from referring them.

var refs = this._refs = {};
var refs = this._refs = params.refs || {};
for(var prop in params){
if((params[prop] || {}).atsignature == "dojox.mvc.at"){
var h = params[prop];
Expand Down
12 changes: 6 additions & 6 deletions tests/test_mvc_Element.html
Expand Up @@ -61,23 +61,23 @@
<div>
<div>
Text:
<span class="dojox.mvc.at(boldTextModel, 'checked').direct(dojox.mvc.from).attach({format: function(value){ return value ? 'boldText' : ''; }})"
data-dojo-bind-text="dojox.mvc.at(titleModel, 'value')"></span>
<span data-dojo-bind="class: dojox.mvc.at(boldTextModel, 'checked').direct(dojox.mvc.from).attach({format: function(value){ return value ? 'boldText' : ''; }}),
value: dojox.mvc.at(titleModel, 'value')"></span>
</div>
<div>
Choose text from:
<select type="combo" value="dojox.mvc.at(titleModel, 'value')">
<select type="combo" data-dojo-bind="value: dojox.mvc.at(titleModel, 'value')">
<option value="Foo">Foo</option>
<option value="Bar">Bar</option>
</select>
</div>
</div>

<div style="margin-top:8px;">
<div style="width:200px;height:200px;" class="dojox.mvc.at(colorModel, 'value')"></div>
<div style="width:200px;height:200px;" data-dojo-bind="class: dojox.mvc.at(colorModel, 'value')"></div>
<div>
Choose color from:
<select type="combo" value="dojox.mvc.at(colorModel, 'value')">
<select type="combo" data-dojo-bind="value: dojox.mvc.at(colorModel, 'value')">
<option value="bgRed">Red</option>
<option value="bgGreen">Green</option>
<option value="bgBlue">Blue</option>
Expand All @@ -87,7 +87,7 @@

<div style="margin-top:8px;">
The text should be bold:
<input type="checkbox" checked="dojox.mvc.at(boldTextModel, 'checked')">
<input type="checkbox" data-dojo-bind="checked: dojox.mvc.at(boldTextModel, 'checked')">
</div>
</body>
</html>

0 comments on commit c022e39

Please sign in to comment.