Permalink
Browse files

commit updates from pull request 31 from asudoh, thanks asudoh.

  • Loading branch information...
2 parents 78285b3 + 4023425 commit 94119680e3b63fa43445dac15c66edcd62d782cc @edchat committed Mar 30, 2012
Showing with 241 additions and 12 deletions.
  1. +11 −0 Element.js
  2. +23 −0 FormElement.js
  3. +73 −0 ParserExtension.js
  4. +3 −1 _atBindingExtension.js
  5. +27 −2 _atBindingMixin.js
  6. +5 −0 at.js
  7. +4 −9 tests/test_async-mvc_group-simple.html
  8. +95 −0 tests/test_mvc_Element.html
View
@@ -0,0 +1,11 @@
+define([
+ "dojo/_base/declare",
+ "dijit/_WidgetBase"
+], function(declare, _WidgetBase){
+ return declare("dojox.mvc.Element", _WidgetBase, {
+ // summary:
+ // A simple widget that maps "value" attribute to DOM text (working as a lightweight version of dojox.mvc.Output in this case), and other attributes to DOM attributes.
+
+ _setValueAttr: {node: "domNode", type: "innerText"}
+ });
+});
View
@@ -0,0 +1,23 @@
+define([
+ "dojo/_base/declare",
+ "dijit/_WidgetBase"
+], function(declare, _WidgetBase){
+ return declare("dojox.mvc.FormElement", _WidgetBase, {
+ // summary:
+ // A widget implicitly created by dojox.mvc.ParserExtension for <input> elements.
+ // description:
+ // Updates value (or checked for check box) as user edits the <input>.
+
+ buildRendering: function(){
+ this.inherited(arguments);
+ var _self = this, node = this.focusNode = this.domNode;
+ this.on("change", function(e){
+ var attr = /^checkbox$/i.test(node.getAttribute("type")) ? "checked" : "value";
+ _self._set(attr, _self.get(attr));
+ });
+ },
+
+ _getCheckedAttr: function(){ return this.domNode.checked; },
+ _getValueAttr: function(){ return this.domNode.value; }
+ });
+});
View
@@ -0,0 +1,73 @@
+define([
+ "require",
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "dojo/has!dojo-parser?:dojo/_base/window",
+ "dojo/has",
+ "dojo/has!dojo-mobile-parser?:dojo/parser",
+ "dojo/has!dojo-parser?:dojox/mobile/parser",
+ "dojox/mvc/_atBindingMixin",
+ "dojox/mvc/Element",
+ "dojox/mvc/FormElement"
+], function(require, kernel, lang, win, has, parser, mobileParser, _atBindingMixin){
+
+ // module:
+ // dojox/mvc/ParserExtension
+ // summary:
+ // A extension of Dojo parser that allows data binding without specifying data-dojo-type.
+
+ has.add("dom-qsa", !!document.createElement("div").querySelectorAll);
+ try{ has.add("dojo-parser", !!require("dojo/parser")); }catch(e){}
+ try{ has.add("dojo-mobile-parser", !!require("dojox/mobile/parser")); }catch(e){}
+
+ if(has("dojo-parser")){
+ var oldScan = parser.scan;
+
+ parser.scan = /*====== dojo.parser.scan = ======*/ function(/*DOMNode?*/ root, /*Object*/ options){
+ // summary:
+ // 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"
+
+ for(var nodes = has("dom-qsa") ? root.querySelectorAll("[" + _atBindingMixin.prototype.dataBindAttr + "]") : root.getElementsByTagName("*"), i = 0, l = nodes.length; i < l; i++){
+ var node = nodes[i], foundBindingInAttribs = false;
+ if(!node.getAttribute(dataDojoType) && !node.getAttribute(dojoType) && node.getAttribute(_atBindingMixin.prototype.dataBindAttr)){
+ list.push({
+ "type": /^select|input|textarea$/i.test(node.tagName) ? "dojox/mvc/FormElement" : "dojox/mvc/Element",
+ node: node
+ });
+ }
+ }
+
+ return list;
+ };
+ }
+
+ if(has("dojo-mobile-parser")){
+ var oldParse = mobileParser.parse;
+
+ 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"
+ nodes = has("dom-qsa") ? (root || win.body()).querySelectorAll("[" + _atBindingMixin.prototype.dataBindAttr + "]") : (root || win.body()).getElementsByTagName("*");
+
+ for(var i = 0, l = nodes.length; i < l; i++){
+ var node = nodes[i], foundBindingInAttribs = false, bindingsInAttribs = [];
+ if(!node.getAttribute(dataDojoType) && !node.getAttribute(dojoType) && node.getAttribute(_atBindingMixin.prototype.dataBindAttr)){
+ node.setAttribute(dataDojoType, /^select|input|textarea$/i.test(node.tagName) ? "dojox/mvc/FormElement" : "dojox/mvc/Element");
+ }
+ }
+
+ return oldParse.apply(this, lang._toArray(arguments));
+ };
+ }
+
+ return parser || mobileParser;
+});
View
@@ -31,7 +31,9 @@ define([
// Monkey patch dijit._WidgetBase.set to establish data binding if a dojox.mvc.at() handle comes
var oldWidgetBaseSet = _WidgetBase.prototype.set;
_WidgetBase.prototype.set = function(/*String*/ name, /*Anything*/ value){
- if((value || {}).atsignature == "dojox.mvc.at"){
+ if(name == _atBindingMixin.prototype.dataBindAttr){
+ return this._setBind(value);
+ }else if((value || {}).atsignature == "dojox.mvc.at"){
return this._setAtWatchHandle(name, value);
}
return oldWidgetBaseSet.apply(this, lang._toArray(arguments));
View
@@ -104,13 +104,20 @@ define([
};
}
- return declare("dojox.mvc._atBindingMixin", null, {
+ var _atBindingMixin = declare("dojox.mvc._atBindingMixin", null, {
+ // summary:
+ // The mixin for dijit._WidgetBase to support data binding.
+
+ // dataBindAttr: String
+ // The attribute name for data binding.
+ dataBindAttr: "data-mvc-bindings",
+
_dbpostscript: function(/*Object?*/ params, /*DomNode|String*/ srcNodeRef){
// summary:
// 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];
@@ -186,6 +193,21 @@ define([
}
},
+ _setBind: function(/*Object*/ value){
+ // summary:
+ // Sets data binding described in data-dojo-bind.
+
+ var list = eval("({" + value + "})");
+ for(var prop in list){
+ var h = list[prop];
+ if((h || {}).atsignature != "dojox.mvc.at"){
+ console.warn(prop + " in " + dataBindAttr + " is not a data binding handle.");
+ }else{
+ this._setAtWatchHandle(prop, h);
+ }
+ }
+ },
+
_getExcludesAttr: function(){
// summary:
// Returns list of all properties that data binding is established with.
@@ -213,4 +235,7 @@ define([
return this.constructor._attribs = list; // String[]
}
});
+
+ _atBindingMixin.prototype[_atBindingMixin.prototype.dataBindAttr] = ""; // Let parser treat the attribute as string
+ return _atBindingMixin;
});
View
5 at.js
@@ -89,6 +89,11 @@ define([
}; // dojox.mvc.at.handle
};
+ // Data binding directions
+ at.from = sync.from;
+ at.to = sync.to;
+ at.both = sync.both;
+
// lang.setObject() thing is for back-compat, remove it in 2.0
return lang.setObject("dojox.mvc.at", at);
});
@@ -24,6 +24,7 @@
"dijit/form/TextBox",
"dojox/mvc/at",
"dojox/mvc/Group",
+ "dojox/mvc/ParserExtension",
"dojo/domReady!"
], function(parser, Stateful, EditModelRefController){
ctrl = new EditModelRefController({sourceModel: new Stateful({First: "John", Last: "Doe", Email: "jdoe@example.com"})});
@@ -48,25 +49,19 @@
<input class="cell" id="firstnameInput" data-dojo-type="dijit.form.TextBox"
data-dojo-props="value: dojox.mvc.at('rel:', 'First')">
<!-- Content in output below will always be in sync with value of textbox above -->
- (first name is: <span data-dojo-type="dijit._WidgetBase"
- data-dojo-props="_setValueAttr: {node: 'domNode', type: 'innerText'},
- value: dojox.mvc.at('rel:', 'First')"></span>)
+ (first name is: <span data-dojo-props="value: dojox.mvc.at('rel:', 'First')"></span>)
</div>
<div class="row">
<label class="cell" for="lastnameInput">Last:</label>
<input class="cell" id="lastnameInput" data-dojo-type="dijit.form.TextBox"
data-dojo-props="value: dojox.mvc.at('rel:', 'Last')">
- (last name is: <span data-dojo-type="dijit._WidgetBase"
- data-dojo-props="_setValueAttr: {node: 'domNode', type: 'innerText'},
- value: dojox.mvc.at('rel:', 'Last')"></span>)
+ (last name is: <span data-dojo-props="value: dojox.mvc.at('rel:', 'Last')"></span>)
</div>
<div class="row">
<label class="cell" for="emailInput">Email:</label>
<input class="cell" id="emailInput" data-dojo-type="dijit.form.TextBox"
data-dojo-props="value: dojox.mvc.at('rel:', 'Email')">
- (email is: <span data-dojo-type="dijit._WidgetBase"
- data-dojo-props="_setValueAttr: {node: 'domNode', type: 'innerText'},
- value: dojox.mvc.at('rel:', 'Email')"></span>)
+ (email is: <span data-dojo-props="value: dojox.mvc.at('rel:', 'Email')"></span>)
</div>
<br/>Model:
<button id="reset" type="button" data-dojo-type="dijit.form.Button"
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+ <title>Dojo MVC Node Widget Test</title>
+
+ <style type="text/css">
+ @import "../../../dijit/themes/claro/document.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+
+ .bgRed {
+ background-color: red;
+ }
+
+ .bgGreen {
+ background-color: green;
+ }
+
+ .bgBlue {
+ background-color: blue;
+ }
+
+ .boldText {
+ font-weight: Bold;
+ }
+ </style>
+
+ <!-- required: a default dijit theme: -->
+ <link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css"/>
+
+ <script type="text/javascript">
+ require = {
+ isDebug: 1,
+ async: 1,
+ has: {
+ "dojox-mvc-binding-in-props-only": 0
+ }
+ };
+ </script>
+
+ <!-- required: dojo.js -->
+ <script type="text/javascript" src="../../../dojo/dojo.js"></script>
+
+ <script type="text/javascript">
+ require([
+ "dojox",
+ "dojo/Stateful",
+ "dojo/parser",
+ "dojox/mvc/at",
+ "dojox/mvc/ParserExtension"
+ ], function(dojox, Stateful, parser, at){
+ window.at = at;
+ dojox.debugDataBinding = true;
+
+ titleModel = new Stateful({value: "Foo"});
+ colorModel = new Stateful({value: "bgRed"});
+ boldTextModel = new Stateful({checked: false});
+ parser.parse();
+ });
+ </script>
+</head>
+<body class="claro">
+ <div>
+ <div>
+ Text:
+ <span data-mvc-bindings="class: at(boldTextModel, 'checked').direct(at.from).attach({format: function(value){ return value ? 'boldText' : ''; }}),
+ value: at(titleModel, 'value')"></span>
+ </div>
+ <div>
+ Choose text from:
+ <select type="combo" data-mvc-bindings="value: 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;" data-mvc-bindings="class: at(colorModel, 'value')"></div>
+ <div>
+ Choose color from:
+ <select type="combo" data-mvc-bindings="value: at(colorModel, 'value')">
+ <option value="bgRed">Red</option>
+ <option value="bgGreen">Green</option>
+ <option value="bgBlue">Blue</option>
+ </select>
+ </div>
+ </div>
+
+ <div style="margin-top:8px;">
+ The text should be bold:
+ <input type="checkbox" data-mvc-bindings="checked: at(boldTextModel, 'checked')">
+ </div>
+ </body>
+</html>

0 comments on commit 9411968

Please sign in to comment.