Changeset 24185 in legacy


Ignore:
Timestamp:
Apr 1, 2011 9:14:41 AM (6 years ago)
Author:
bill
Message:

Refactor parser to allow attributes (for a single node) to be partly specified in data-dojo-props, and partly specified directly ex: value=123. Uses node.attributes to detect which attributes are specified on a node, or for older versions of IE calls cloneNode(false) followed by some regex's on clone.outerHTML.

Due to lowercase/uppercase issues (ex: tabIndex, onClick), and for type conversion, the code still introspects each widget to get it's attribute metadata. In the future, would like to defer/avoid that in the common case.

Fixes #10153, #12423, #12476, #10150, #9823, refs #11490 !strict.

Also fixes the problem on IE8 where a button without type=... defaults to type=submit rather than whatever the widget defines the default as, fixes #10163, refs #9334, #8946.

Future updates will be attached to ticket #12476.

Files:
7 edited

Legend:

Unmodified
Added
Removed
  • dijit/trunk/_WidgetBase.js

    r24125 r24185  
    244244                this._supportingWidgets = [];
    245245
     246                // this is here for back-compat, remove in 2.0 (but check NodeList-instantiate.html test)
     247                if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
     248
    246249                // mix in our passed parameters
    247                 if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
    248250                if(params){
    249251                        this.params = params;
  • dijit/trunk/form/Form.js

    r23988 r24185  
    7474                        dojo.attr(this.domNode, "encType", value);
    7575                        if(dojo.isIE){ this.domNode.encoding = value; }
    76                 },
    77 
    78                 postCreate: function(){
    79                         // IE tries to hide encType
    80                         // TODO: remove in 2.0, no longer necessary with data-dojo-params
    81                         if(dojo.isIE && this.srcNodeRef && this.srcNodeRef.attributes){
    82                                 var item = this.srcNodeRef.attributes.getNamedItem('encType');
    83                                 if(item && !item.specified && (typeof item.value == "string")){
    84                                         this.set('encType', item.value);
    85                                 }
    86                         }
    87                         this.inherited(arguments);
    8876                },
    8977
  • dijit/trunk/tests/form/robot/Button_mouse.html

    r24177 r24185  
    342342                                                        var d = new doh.Deferred();
    343343
    344                                                         doh.robot.mouseMoveAt('Plain', 500, 1);
     344                                                        doh.robot.mouseMoveAt('SubmitPlain', 500, 1);
    345345                                                        doh.robot.mouseClick({left:true}, 500);
    346346
     
    360360                                                        var d = new doh.Deferred();
    361361
    362                                                         doh.robot.mouseMoveAt('Combo', 500, 1);
     362                                                        doh.robot.mouseMoveAt('SubmitCombo', 500, 1);
    363363                                                        doh.robot.mouseClick({left:true}, 500);
    364364
     
    378378                                                        var d = new doh.Deferred();
    379379
    380                                                         var downArrowNode = dojo.query(".dijitDownArrowButton", dojo.byId("Combo"))[0];
     380                                                        var downArrowNode = dojo.query(".dijitDownArrowButton", dojo.byId("SubmitCombo"))[0];
    381381
    382382                                                        doh.robot.mouseMoveAt(downArrowNode, 500, 1);
     
    398398                                                        var d = new doh.Deferred();
    399399
    400                                                         doh.robot.mouseMoveAt("ComboMenuItem", 500, 1);
     400                                                        doh.robot.mouseMoveAt("SubmitComboMenuItem", 500, 1);
    401401                                                        doh.robot.mouseClick({left:true}, 500);
    402402
     
    416416                                                        var d = new doh.Deferred();
    417417
    418                                                         doh.robot.mouseMoveAt('DropDown', 500, 1);
     418                                                        doh.robot.mouseMoveAt('SubmitDropDown', 500, 1);
    419419                                                        doh.robot.mouseClick({left:true}, 500);
    420420
     
    434434                                                        var d = new doh.Deferred();
    435435
    436                                                         doh.robot.mouseMoveAt("DropDownMenuItem", 500, 1);
     436                                                        doh.robot.mouseMoveAt("SubmitDropDownMenuItem", 500, 1);
    437437                                                        doh.robot.mouseClick({left:true}, 500);
    438438
     
    452452                                                        var d = new doh.Deferred();
    453453
    454                                                         doh.robot.mouseMoveAt('Disabled', 500, 1);
     454                                                        doh.robot.mouseMoveAt('SubmitDisabled', 500, 1);
    455455                                                        doh.robot.mouseClick({left:true}, 500);
    456456
  • dijit/trunk/tests/form/test_Button.html

    r24176 r24185  
    7575                <button id="button" onclick="console.log('clicked native button');">&lt;button&gt;</button>
    7676                <input id="input" type="button" value="&lt;input type='button'&gt;" onclick="console.log('clicked native input button');"/>
    77                 <button data-dojo-type="dijit.form.Button" data-dojo-props='id:"T1465", onClick:function(){ console.log("clicked simple"); }, iconClass:"plusIcon", value:"Create"'>
     77                <button data-dojo-type="dijit.form.Button" id="T1465" data-dojo-props='onClick:function(){ console.log("clicked simple"); }, iconClass:"plusIcon", value:"Create"'>
    7878                        Create
    7979                </button>
    80                 <span data-dojo-type="dijit.Tooltip" data-dojo-props='connectId:["T1465"]'>tooltip on button</span>
    81                 <button data-dojo-type="dijit.form.Button" data-dojo-props='id:"T1466", title:"view title", onClick:function(){ console.log("clicked simple"); }'>
     80                <span data-dojo-type="dijit.Tooltip" data-dojo-props='connectId:["1465"]'>tooltip on button</span>
     81                <button data-dojo-type="dijit.form.Button" id="T1466" title="view title" data-dojo-props='onClick:function(){ console.log("clicked simple"); }'>
    8282                        View
    8383                </button>
    84                 <button id="comboCreate" data-dojo-type="dijit.form.ComboButton" data-dojo-props='optionsTitle:"save options", onClick:function(){ console.log("clicked combo save") },
    85                                 iconClass:"plusIcon", title:"creative title"'>
     84                <button id="comboCreate" title="creative title" data-dojo-type="dijit.form.ComboButton" data-dojo-props='optionsTitle:"save options", onClick:function(){ console.log("clicked combo save") },
     85                                iconClass:"plusIcon"'>
    8686                        <span>Create</span>
    87                         <span id="createMenu" data-dojo-type="dijit.Menu"'>
     87                        <span id="createMenu" data-dojo-type="dijit.Menu">
    8888                                <span data-dojo-type="dijit.MenuItem"  data-dojo-props='iconClass:"dijitEditorIcon dijitEditorIconSave",
    8989                                        onClick:function(){ console.log("not actually saving anything, just a test!"); }'>Create blank</span>
     
    9292                        </span>
    9393                </button>
    94                 <button id="edit" data-dojo-type="dijit.form.DropDownButton" data-dojo-props='iconClass:"noteIcon", title:"edit title", value:"Edit"'>
     94                <button id="edit" title="edit title" value="Edit" data-dojo-type="dijit.form.DropDownButton" data-dojo-props='iconClass:"noteIcon"'>
    9595                        <span>Edit<b>!</b></span>
    9696                        <span id="editMenu" data-dojo-type="dijit.Menu" >
     
    132132                        </span>
    133133                </button>
    134                 <button id="disabled" data-dojo-type="dijit.form.Button" data-dojo-props='onClick:function(){ console.log("clicked simple"); }, disabled:true, iconClass:"plusIcon"'>
     134                <button id="disabled" disabled data-dojo-type="dijit.form.Button" data-dojo-props='onClick:function(){ console.log("clicked simple"); }, iconClass:"plusIcon"'>
    135135                        Disabled
    136136                </button>
     
    138138        <br style="clear:both;"/>
    139139        <h2>DropDownButtons with different drop down positions</h2>
    140         <button id="dropdown_default" data-dojo-type="dijit.form.DropDownButton" data-dojo-props='iconClass:"noteIcon", value:"color"'>
     140        <button id="dropdown_default" value="color" data-dojo-type="dijit.form.DropDownButton" data-dojo-props='iconClass:"noteIcon"'>
    141141                <span>Default (below)</span>
    142142                <span data-dojo-type="dijit.ColorPalette"
    143143                        data-dojo-props='palette:"3x4", onChange:function(val){ console.log(val); }'></span>
    144144        </button>
    145         <button id="dropdown_up" data-dojo-type="dijit.form.DropDownButton" data-dojo-props='dropDownPosition:["above"], iconClass:"noteIcon", value:"color"'>
     145        <button id="dropdown_up" value="color" data-dojo-type="dijit.form.DropDownButton" data-dojo-props='dropDownPosition:["above"], iconClass:"noteIcon"'>
    146146                <span>Above</span>
    147147                <span data-dojo-type="dijit.ColorPalette"
    148148                        data-dojo-props='palette:"3x4", onChange:function(val){ console.log(val); }'></span>
    149149        </button>
    150         <button id="dropdown_before" data-dojo-type="dijit.form.DropDownButton" data-dojo-props='dropDownPosition:["before"], iconClass:"noteIcon", value:"color"'>
     150        <button id="dropdown_before" value="color" data-dojo-type="dijit.form.DropDownButton" data-dojo-props='dropDownPosition:["before"], iconClass:"noteIcon"'>
    151151                <span>Before</span>
    152152                <span data-dojo-type="dijit.ColorPalette"
    153153                        data-dojo-props='palette:"3x4", onChange:function(val){ console.log(val); }'></span>
    154154        </button>
    155         <button id="dropdown_after" data-dojo-type="dijit.form.DropDownButton" data-dojo-props='dropDownPosition:["after"], iconClass:"noteIcon", value:"color"'>
     155        <button id="dropdown_after" value="color" data-dojo-type="dijit.form.DropDownButton" data-dojo-props='dropDownPosition:["after"], iconClass:"noteIcon"'>
    156156                <span>After</span>
    157157                <span data-dojo-type="dijit.ColorPalette"
     
    202202        <p>Buttons have showLabel=false so text is not displayed.  If no title attribute supplied, Should have label as title attribute displayed on mouse over</p>
    203203        <div class="box">
    204                 <button data-dojo-type="dijit.form.Button" data-dojo-props='id:"T1467", title:"title attrib rather than label", onClick:function(){ console.log("clicked simple button with no text label"); },
     204                <button id="1467" title="title attrib rather than label" data-dojo-type="dijit.form.Button" data-dojo-props='onClick:function(){ console.log("clicked simple button with no text label"); },
    205205                iconClass:"plusIcon", showLabel:false'>
    206                 <span><b>Rich</b><i> Text</i> Test!</span>
    207                 </button>
    208                                 <div data-dojo-type="dijit.form.DropDownButton" data-dojo-props='iconClass:"noteIcon", showLabel:false, title:"color title"'>
     206                        <span><b>Rich</b><i> Text</i> Test!</span>
     207                </button>
     208                <div title="color title" data-dojo-type="dijit.form.DropDownButton" data-dojo-props='iconClass:"noteIcon", showLabel:false'>
    209209                        <span>Color</span>
    210210                        <div id="colorPalette2" data-dojo-type="dijit.ColorPalette"
    211211                                data-dojo-props='palette:"3x4", onChange:function(val){ console.log(val); }'>
    212212                        </div>
    213         </div>
    214         <div data-dojo-type="dijit.form.ComboButton" data-dojo-props='optionsTitle:"save options", title:"save title", onClick:function(){ console.log("clicked combo save"); },
     213                </div>
     214                <div title="save title" data-dojo-type="dijit.form.ComboButton" data-dojo-props='optionsTitle:"save options", onClick:function(){ console.log("clicked combo save"); },
    215215                                iconClass:"plusBlockIcon", showLabel:false'>
    216216                        <span>Save</span>
     
    227227        <p>The button CSS as well as the icon CSS can change on toggle </p>
    228228        <div class="box">
    229                 <button id="toggle1" data-dojo-type="dijit.form.ToggleButton" data-dojo-props='checked:true,
     229                <button id="toggle1" checked data-dojo-type="dijit.form.ToggleButton" data-dojo-props='
    230230                        onChange:function(val){
    231231                                console.log("toggled button checked="+val);
     
    308308                }
    309309                var labels=["<img src='../images/note.gif' width='20' height='20'/>All", "<i>work</i>", "and no", "<span style='font-size: 40pt;'>play</span>",
    310                                          "<span style='color: red'>makes</span>", "Jack", "<span style='font-size: 20pt;'>a</a>", "dull",
     310                                         "<span style='color: red'>makes</span>", "Jack", "<span style='font-size: 20pt;'>a</span>", "dull",
    311311                                         "<img src='../images/plus.gif' width='16' height='16'/>boy"];
    312312                var idx = 0;
     
    393393                for the form just output to the console.
    394394        </div>
    395         <form id="testForm" data-dojo-type="dijit.form.Form" data-dojo-props='name:"testForm",
    396                 encType:"multipart/form-data", action:"../formAction.html", method:"" '>
     395        <form id="testForm" encType="multipart/form-data" name="testForm" action="../formAction.html" method="" data-dojo-type="dijit.form.Form">
    397396                <script type="dojo/method" data-dojo-event="onReset">
    398397                        console.log("testForm onReset invoked");
     
    412411        <form>
    413412                <label for="onClickName">Value: </label><input id="onClickName" name="onClickName" value="RESET"/><br>
    414                 <button id="reset1" data-dojo-type="dijit.form.Button" data-dojo-props='type:"reset" '>Reset with no onClick handler should reset</button>
     413                <button id="reset1" type="reset" data-dojo-type="dijit.form.Button">Reset with no onClick handler should reset</button>
    415414                <button type="reset" id="reset1N">Native Reset with no onClick handler should reset</button><br>
    416                 <button id="reset2" data-dojo-type="dijit.form.Button" data-dojo-props='type:"reset", onClick:function(){ return false }'>Reset with "return false" onClick handler should not reset</button>
     415                <button id="reset2" type="reset" data-dojo-type="dijit.form.Button" data-dojo-props='onClick:function(){ return false }'>Reset with "return false" onClick handler should not reset</button>
    417416                <button type="reset" id="reset2N" onClick="return false;">Native Reset with "return false" onClick handler should not reset</button><br>
    418                 <button id="reset3" data-dojo-type="dijit.form.Button" data-dojo-props='type:"reset", onClick:function(){ return true }'>Reset with "return true" onClick handler should reset</button>
     417                <button id="reset3" type="reset" data-dojo-type="dijit.form.Button" data-dojo-props='onClick:function(){ return true }'>Reset with "return true" onClick handler should reset</button>
    419418                <button type="reset" id="reset3N" onClick="return true;">Native Reset with "return true" onClick handler should reset</button><br>
    420                 <button id="reset4" data-dojo-type="dijit.form.Button" data-dojo-props='type:"reset", onClick:function(){ return }'>Reset with "return" onClick handler should reset</button>
     419                <button id="reset4" type="reset" data-dojo-type="dijit.form.Button" data-dojo-props='onClick:function(){ return }'>Reset with "return" onClick handler should reset</button>
    421420                <button type="reset" id="reset4N" onClick="return;">Native Reset with "return" onClick handler should reset</button><br>
    422                 <button id="reset5" data-dojo-type="dijit.form.Button" data-dojo-props='type:"reset", onClick:function(){  }'>Reset with "" onClick handler should reset</button>
     421                <button id="reset5" type="reset" data-dojo-type="dijit.form.Button" data-dojo-props='onClick:function(){  }'>Reset with "" onClick handler should reset</button>
    423422                <button type="reset" id="reset5N" onClick="">Native Reset with "" onClick handler should reset</button><br>
    424423        </form>
     
    433432                };
    434433        </script>
    435         <form id="myForm" data-dojo-type="dijit.form.Form" data-dojo-props='encType:"multipart/form-data", action:"../formAction.html", method:"", target:"formSubmitIframe"'>
    436                 <button id="Plain" data-dojo-type="dijit.form.Button" data-dojo-props='name:"Plain", type:"submit", value:"Plain Submit", label:"Plain Submit"'></button>
    437                 <button id="Combo" data-dojo-type="dijit.form.ComboButton" data-dojo-props='name:"Combo", type:"submit", value:"Combo Submit", label:"Combo Submit"'>
     434        <form id="myForm" data-dojo-type="dijit.form.Form" encType="multipart/form-data" action="../formAction.html" method="" target="formSubmitIframe">
     435                <button id="SubmitPlain" data-dojo-type="dijit.form.Button" name="Plain" type="submit" value="Plain Submit">Plain Submit</button>
     436                <button id="SubmitCombo" data-dojo-type="dijit.form.ComboButton" name="Combo" type="submit" value="Combo Submit"
     437                                data-dojo-props="label: 'Combo Submit'">
     438                        Combo Submit
    438439                        <span data-dojo-type="dijit.Menu">
    439                                 <span id="ComboMenuItem" data-dojo-type="dijit.MenuItem" data-dojo-props='onClick:function(){ dijit.byId("myForm").submit(); }'>Combo MenuItem Submit</span>
     440                                <span id="SubmitComboMenuItem" data-dojo-type="dijit.MenuItem" data-dojo-props='onClick:function(){ dijit.byId("myForm").submit(); }'>Combo MenuItem Submit</span>
    440441                        </span>
    441442                </button>
    442                 <button id="DropDown" data-dojo-type="dijit.form.DropDownButton" data-dojo-props='name:"DropDown", type:"submit", value:"DropDown Submit", label:"DropDown Submit"'>
     443                <button id="SubmitDropDown" data-dojo-type="dijit.form.DropDownButton" name="DropDown" type="submit" value="DropDown Submit"
     444                                data-dojo-props="label: 'DropDown Submit'">
     445                        DropDown Submit
    443446                        <span data-dojo-type="dijit.Menu">
    444                                 <span id="DropDownMenuItem" data-dojo-type="dijit.MenuItem" data-dojo-props='onClick:function(){ dijit.byId("myForm").submit(); }'>DropDown MenuItem Submit</span>
     447                                <span id="SubmitDropDownMenuItem" data-dojo-type="dijit.MenuItem" data-dojo-props='onClick:function(){ dijit.byId("myForm").submit(); }'>DropDown MenuItem Submit</span>
    445448                        </span>
    446449                </button>
    447                 <button id="Disabled" data-dojo-type="dijit.form.Button" data-dojo-props='name:"Disabled", type:"submit", disabled:true, value:"Disabled Submit", label:"Disabled Submit"'></button>
     450                <button id="SubmitDisabled" data-dojo-type="dijit.form.Button" name="Disabled" type="submit" disabled value="Disabled Submit">Disabled Submit</button>
    448451        </form>
    449452        <br>
  • dijit/trunk/tests/form/test_validate.html

    r23808 r24185  
    140140                        <div class="testExample">
    141141                                <input id="q01" data-dojo-type="dijit.form.TextBox"
    142                                         data-dojo-props='name:"firstname", value:"testing testing", style:{width:"700px"}, tabIndex:"2",
     142                                        name="firstname" value="testing testing" style="width:700px" tabIndex="2"
     143                                        data-dojo-props='
    143144                                        trim:true,
    144145                                        selectOnClick:true,
     
    159160                        <div class="testExample">
    160161                                <input id="q02" data-dojo-type="dijit.form.TextBox"
    161                                         data-dojo-props='name:"lastname", value:"testing testing", "class":"verylong",
    162                                         trim:true,
    163                                         uppercase:true '/>
     162                                        name="lastname" value="testing testing" class="verylong"
     163                                        data-dojo-props='trim:true, uppercase:true '/>
    164164                        </div>
    165165
     
    170170                        <div class="testExample">
    171171                                <input id="q03" data-dojo-type="dijit.form.NumberTextBox"
    172                                         data-dojo-props='name:"age", tabIndex:"1",
     172                                        name="age" tabIndex="1" class="small"
     173                                        data-dojo-props='
    173174                                        promptMessage:"(optional) Enter an age between 0 and 120",
    174175                                        maxLength:"3",
    175                                         "class":"small",
    176176                                        constraints:{places:0,min:0,max:120},
    177177                                        onChange:function(val){ dojo.byId("oc3").value=""+val; },
     
    195195                        <div class="testExample">
    196196                                <input id="fav" data-dojo-type="dijit.form.NumberTextBox"
    197                                         data-dojo-props='name:"fav", "class":"small",
    198                                         maxLength:"3",
    199                                         constraints:{places:0,min:1,max:100},
    200                                         regExpGen:function(){ return "\\d+" },
    201                                         required:true'/>
     197                                        name="fav" class="small" required
     198                                        data-dojo-props='maxLength:"3",constraints:{places:0,min:1,max:100},regExpGen:function(){ return "\\d+" }'/>
    202199                                        <button onclick="dijit.byId('fav').set('required', true); return false;">attr(required, true)</button>
    203200                                        <button onclick="dijit.byId('fav').set('required', false); return false;">attr(required, false)</button>
     
    211208                        <div class="testExample">
    212209                                <input id="q04" data-dojo-type="dijit.form.ValidationTextBox"
    213                                         data-dojo-props='name:"occupation", "class":"verylong", style:{fontSize:"15pt"},
    214                                         lowercase:true,
    215                                         required:true,
    216                                         promptMessage:"Enter an occupation" '/>
     210                                        name="occupation" class="verylong" style="fontSize:15pt" required="true"
     211                                        data-dojo-props='lowercase:true, promptMessage:"Enter an occupation" '/>
    217212                        </div>
    218213
     
    307302                        <div class="testExample">
    308303                                <input id="q08" data-dojo-type="dijit.form.CurrencyTextBox"
    309                                         data-dojo-props='name:"income1", "class":"medium", value:54775.53,
    310                                         required:true,
    311                                         constraints:{fractional:true},
    312                                         currency:"USD",
    313                                         onChange:function(val){ dojo.byId("oc8").value = val; },
    314                                         invalidMessage:"Invalid amount.  Cents are MANDATORY." '/>USD
     304                                        name="income1" class="medium" value="54775.53" required
     305                                        data-dojo-props='constraints:{fractional:true},
     306                                                currency:"USD",
     307                                                onChange:function(val){ dojo.byId("oc8").value = val; },
     308                                                invalidMessage:"Invalid amount.  Cents are MANDATORY." '/>USD
    315309                                &nbsp;onChange:<input id="oc8" size="15" disabled value="not fired yet!" autocomplete="off"/>
    316310                        </div>
     
    319313                                euro currency (local format) fractional part is optional:
    320314                                <input id="q08eur" data-dojo-type="dijit.form.CurrencyTextBox"
    321                                         data-dojo-props='name:"income2",
    322                                         "class":"medium", value:54775.53,
    323                                         required:true,
    324                                         currency:"EUR",
    325                                         invalidMessage:"Invalid amount.  Include cents." '/>EUR
     315                                        name="income2" class="medium" value="54775.53" required
     316                                        data-dojo-props='currency:"EUR", invalidMessage:"Invalid amount.  Include cents." '/>EUR
    326317                                <button onclick="dijit.byId('q08eur').set('disabled',true); return false;">Disable</button>
    327318                                <button onclick="dijit.byId('q08eur').set('disabled',false); return false;">Enable</button>
     
    456447                        <div class="testExample">
    457448                                <input id="q22" data-dojo-type="dijit.form.ValidationTextBox"
    458                                         data-dojo-props='name:"phone", "class":"medium", value:"someTestString",
    459                                         regExp:"[\\w]+",
    460                                         required:true,
    461                                         invalidMessage:"Invalid Non-Space Text."'/>
     449                                        name="phone" class="medium" value="someTestString" required
     450                                        data-dojo-props='regExp:"[\\w]+", invalidMessage:"Invalid Non-Space Text."'/>
    462451                        </div>
    463452
     
    467456                        </div>
    468457                        <div class="testExample">
    469                                 <input id="q23" data-dojo-type="dijit.form.TextBox" data-dojo-props='type:"password", name:"password", "class":"medium"
    470                                         '/>
     458                                <input id="q23" data-dojo-type="dijit.form.TextBox" type="password" name="password" class="medium"/>
    471459                        </div>
    472460
     
    499487                        <div class="testExample">
    500488                                <input id="q24" data-dojo-type="dijit.form.TextBox"
    501                                         data-dojo-props='name: "readOnly", "class": "medium", readOnly: true, value: "cannot type here", title: "hint text" '/>
     489                                        name="readOnly" class="medium" readOnly value="cannot type here" title="hint text"/>
    502490                                <input type="button" id="removereadonly" onclick="dijit.byId('q24').set('readOnly',false);" value="Remove readOnly" tabIndex="-1"/>
    503491                                <input type="button" onclick="dijit.byId('q24').set('readOnly',true);" value="Set readOnly" tabIndex="-1"/>
     
    511499                        <div class="testExample">
    512500                                <input id="q25" data-dojo-type="dijit.form.ValidationTextBox"
    513                                         data-dojo-props='name: "disabled", "class": "medium", disabled: true, value: "cannot type here" '/>
     501                                        name="disabled" class="medium" disabled value="cannot type here"/>
    514502                                <input type="button" onclick="dijit.byId('q25').set('readOnly',false);" value="Remove readOnly" tabIndex="-1"/>
    515503                                <input type="button" onclick="dijit.byId('q25').set('readOnly',true);" value="Set readOnly" tabIndex="-1"/>
     
    543531                </div>
    544532                <div class="testExample">
    545                         <input id="q26" data-dojo-type="dijit.form.TextBox" data-dojo-props='placeHolder:"placeholder is here", name:"placeHolder", value:""
    546                                                 '/>
     533                        <input id="q26" data-dojo-type="dijit.form.TextBox" placeHolder="placeholder is here" name="placeHolder" value=""/>
    547534                </div>
    548535                <h2>Tooltip positioning</h2>
  • dojo/trunk/parser.js

    r24126 r24185  
    22
    33new Date("X"); // workaround for #11279, new Date("") == NaN
     4
     5var features = {
     6        // Feature detection for when node.attributes only lists the attributes specified in the markup
     7        // rather than old IE/quirks behavior where it lists every default value too
     8        "dom-attributes-explicit": document.createElement("div").attributes.length < 40
     9};
     10function has(feature){
     11        return features[feature];
     12}
     13
    414
    515dojo.parser = new function(){
     
    818
    919        var d = dojo;
    10 
    11         function val2type(/*Object*/ value){
    12                 // summary:
    13                 //              Returns name of type of given value.
    14 
    15                 if(d.isString(value)){ return "string"; }
    16                 if(typeof value == "number"){ return "number"; }
    17                 if(typeof value == "boolean"){ return "boolean"; }
    18                 if(d.isFunction(value)){ return "function"; }
    19                 if(d.isArray(value)){ return "array"; } // typeof [] == "object"
    20                 if(value instanceof Date) { return "date"; } // assume timestamp
    21                 if(value instanceof d._Url){ return "url"; }
    22                 return "object";
    23         }
    2420
    2521        function str2obj(/*String*/ value, /*String*/ type){
     
    6864
    6965        var dummyClass = {}, instanceClasses = {
    70                 // map from fully qualified name (like "dijit.Button") to structure like
    71                 // { cls: dijit.Button, params: {label: "string", disabled: "boolean"} }
     66                // Map from fully qualified name (like "dijit.Button") to structure like:
     67                // {
     68                //              cls: dijit.Button,
     69                //              params: {
     70                //                      label: {name: "label", type: "string"},
     71                //                      disabled: {name: "disabled", type: "boolean"},
     72                //                      onclick: {name: "onClick", type: "function"}
     73                //              }
     74                // }
     75                // Note that the params key is lowercased, onclick rather than onClick.
    7276        };
    7377
     
    7579        // If BorderContainer is loaded after _Widget's parameter list has been cached,
    7680        // we need to refresh that parameter list (for _Widget and all widgets that extend _Widget).
    77         // TODO: remove this in 2.0, when we stop caching parameters.
    7881        d.connect(d, "extend", function(){
    7982                instanceClasses = {};
    8083        });
     84
     85        // These are the data types where we can simply do "typeof value" to get the type of the value
     86        var _nativeTypes = {"string": "string", "number": "number", "boolean": "boolean", "function": "function"};
     87
     88        // TODO: defer getProtoInfo() code until needed.
     89        //   1. We can avoid using the lowerCase --> mixedCase
     90        //              mapping for obvious parameters (lowercase values like "name", or commmon mixed case like onChange
     91        //              onClick, tabIndex)
     92        //       2. Only need to compute types of parameters that the user specifies
    8193
    8294        function getProtoInfo(cls, params){
     
    88100                        if(name.charAt(0)=="_"){ continue; }    // skip internal properties
    89101                        if(name in dummyClass){ continue; }             // skip "constructor" and "toString"
    90                         params[name] = val2type(cls[name]);
     102
     103                        var value = cls[name];
     104                        params[name.toLowerCase()] = {
     105                                name: name,
     106                                type:
     107                                        _nativeTypes[typeof value] ||
     108                                        ((value && "length" in value) ? "array" :
     109                                        (value instanceof Date) ? "date" :
     110                                        (value instanceof d._Url) ? "url" :
     111                                        "object")
     112                        };
    91113                }
    92114                return params;
    93115        }
    94116
    95         function getClassInfo(/*String*/ className, /*Boolean*/ skipParamsLookup){
     117        function getClassInfo(/*String*/ className){
    96118                // summary:
    97119                //              Maps a widget name string like "dijit.form.Button" to the widget constructor itself,
     
    100122                //              fully qualified name (like "dijit.form.Button")
    101123                // returns:
    102                 //              structure like
    103                 //                      {
    104                 //                              cls: dijit.Button,
    105                 //                              params: { label: "string", disabled: "boolean"}
    106                 //                      }
     124                //              structure like instanceClasses, see above
    107125
    108126                var c = instanceClasses[className];
    109127                if(!c){
    110                         // get pointer to widget class
    111                         var cls = d.getObject(className), params = null;
     128                        var cls = d.getObject(className);
    112129                        if(!cls){ return null; }                // class not defined [yet]
    113                         if(!skipParamsLookup){ // from fastpath, we don't need to lookup the attrs on the proto because they are explicit
    114                                 params = getProtoInfo(cls.prototype, {})
    115                         }
    116                         c = { cls: cls, params: params };
    117                        
    118                 }else if(!skipParamsLookup && !c.params){
    119                         // if we're calling getClassInfo and have a cls proto, but no params info, scan that cls for params now
    120                         // and update the pointer in instanceClasses[className]. This happens when a widget appears in another
    121                         // widget's template which still uses dojoType, but an instance of the widget appears prior with a data-dojo-type,
    122                         // skipping this lookup the first time.
    123                         c.params = getProtoInfo(c.cls.prototype, {});
    124                 }
    125                
     130                        var params = getProtoInfo(cls.prototype, {})
     131                        c = (instanceClasses[className] = { cls: cls, params: params });
     132
     133                }
     134
    126135                return c;
    127136        }
     
    154163        };
    155164
    156         this.instantiate = function(/* Array */nodes, /* Object? */mixin, /* Object? */args){
     165        this.instantiate = function(nodes, mixin, args){
    157166                // summary:
    158167                //              Takes array of nodes, and turns them into class instances and
     
    179188                args = args||{};
    180189
     190                // Precompute names of special attributes we are looking for
    181191                // TODO: for 2.0 default to data-dojo- regardless of scopeName (or maybe scopeName won't exist in 2.0)
    182                 var attrName = (args.scope || d._scopeName) + "Type",   // typically "dojoType"
    183                         attrData = "data-" + (args.scope || d._scopeName) + "-";        // typically "data-dojo-"
     192                var dojoType = (args.scope || d._scopeName) + "Type",           // typically "dojoType"
     193                        dojotype = dojoType.toLowerCase(),                                              // typically "dojotype" (intentionally lowercase)
     194                        attrData = "data-" + (args.scope || d._scopeName) + "-",// typically "data-dojo-"
     195                        dataDojoType = attrData + "type",                                               // typically "data-dojo-type"
     196                        dataDojoProps = attrData + "props",                                             // typically "data-dojo-props"
     197                        dataDojoAttachPoint = attrData + "attach-point",
     198                        dataDojoAttachEvent = attrData + "attach-event",
     199                        dataDojoId = attrData + "id";
    184200
    185201                d.forEach(nodes, function(obj){
    186202                        if(!obj){ return; }
    187203
    188                         // Get pointers to DOMNode, dojoType string, and clsInfo (metadata about the dojoType), etc.
    189                         var node, type, clsInfo, clazz, scripts, fastpath;
    190                         if(obj.node){
    191                                 // new format of nodes[] array, object w/lots of properties pre-computed for me
    192                                 node = obj.node;
    193                                 type = obj.type;
    194                                 fastpath = obj.fastpath;
    195                                 clsInfo = obj.clsInfo || (type && getClassInfo(type, fastpath));
     204                        var node = obj.node || obj,
     205                                type = dojoType in mixin ? mixin[dojoType] : obj.node ? obj.type : (node.getAttribute(dataDojoType) || node.getAttribute(dojoType)),
     206                                clsInfo = obj.clsInfo || (type && getClassInfo(type)),
    196207                                clazz = clsInfo && clsInfo.cls;
    197                                 scripts = obj.scripts;
    198                         }else{
    199                                 // old (backwards compatible) format of nodes[] array, simple array of DOMNodes. no fastpath/data-dojo-type support here.
    200                                 node = obj;
    201                                 type = attrName in mixin ? mixin[attrName] : node.getAttribute(attrName);
    202                                 clsInfo = type && getClassInfo(type);
    203                                 clazz = clsInfo && clsInfo.cls;
    204                                 scripts = (clazz && (clazz._noScript || clazz.prototype._noScript) ? [] :
    205                                                         d.query("> script[type^='dojo/']", node));
    206                         }
    207208                        if(!clsInfo){
    208209                                throw new Error("Could not load class '" + type);
     
    222223                                d._mixin(params, obj.inherited);
    223224                        }
    224                        
    225                         // mix things found in data-dojo-props into the params
    226                         if(fastpath){
    227                                 var extra = node.getAttribute(attrData + "props");
    228                                 if(extra && extra.length){
    229                                         try{
    230                                                 extra = d.fromJson.call(args.propsThis, "{" + extra + "}");
    231                                                 d._mixin(params, extra);
    232                                         }catch(e){
    233                                                 // give the user a pointer to their invalid parameters. FIXME: can we kill this in production?
    234                                                 throw new Error(e.toString() + " in data-dojo-props='" + extra + "'");
    235                                         }
    236                                 }
    237 
    238                                 // For the benefit of _Templated, check if node has data-dojo-attach-point/data-dojo-attach-event
    239                                 // and mix those in as though they were parameters
    240                                 var attachPoint = node.getAttribute(attrData + "attach-point");
    241                                 if(attachPoint){
    242                                         params.dojoAttachPoint = attachPoint;
    243                                 }
    244                                 var attachEvent = node.getAttribute(attrData + "attach-event");
    245                                 if(attachEvent){
    246                                         params.dojoAttachEvent = attachEvent;
    247                                 }
    248                                 dojo.mixin(params, mixin);
     225
     226                        // Get list of attributes explicitly listed in the markup
     227                        var attributes;
     228                        if(has("dom-attributes-explicit")){
     229                                // Standard path to get list of user specified attributes
     230                                attributes = node.attributes;
    249231                        }else{
    250                                 // FIXME: we need something like "deprecateOnce()" to throw dojo.deprecation for something.
    251                                 // remove this logic in 2.0
    252                                 // read parameters (ie, attributes) specified on DOMNode
    253 
    254                                 var attributes = node.attributes;
    255 
    256                                 // clsInfo.params lists expected params like {"checked": "boolean", "n": "number"}
    257                                 for(var name in clsInfo.params){
    258                                         var item = name in mixin ? { value:mixin[name], specified:true } : attributes.getNamedItem(name);
    259                                         if(!item || (!item.specified && (!dojo.isIE || name.toLowerCase()!="value"))){ continue; }
    260                                         var value = item.value;
    261                                         // Deal with IE quirks for 'class' and 'style'
    262                                         switch(name){
    263                                         case "class":
    264                                                 value = "className" in mixin ? mixin.className : node.className;
    265                                                 break;
    266                                         case "style":
    267                                                 value = "style" in mixin ? mixin.style : (node.style && node.style.cssText); // FIXME: Opera?
    268                                         }
    269                                         var _type = clsInfo.params[name];
    270                                         if(typeof value == "string"){
    271                                                 params[name] = str2obj(value, _type);
     232                                // Special path for IE, avoid (sometimes >100) bogus entries in node.attributes
     233                                var clone = /^input$|^img$/i.test(node.nodeName) ? node : node.cloneNode(false),
     234                                        attrs = clone.outerHTML.replace(/=[^\s"']+|="[^"]*"|='[^']*'/g, "").replace(/^\s*<[a-zA-Z]*/, "").replace(/>.*$/, "");
     235
     236                                attributes = dojo.map(attrs.split(/\s+/), function(name){
     237                                        var lcName = name.toLowerCase();
     238                                        return {
     239                                                name: name,
     240                                                // getAttribute() doesn't work for button.value, returns innerHTML of button.
     241                                                // but getAttributeNode().value doesn't work for the form.encType or li.value
     242                                                value: node.nodeName.match(/^BUTTON$|^TEXTAREA$/) && name == "value" ?
     243                                                                node.getAttributeNode(lcName).value : node.getAttribute(lcName),
     244                                                specified: true
     245                                        };
     246                                });
     247                        }
     248
     249                        // Read in attributes and process them, including data-dojo-props, data-dojo-type,
     250                        // dojoAttachPoint, etc., as well as normal foo=bar attributes.
     251                        var i=0, item;
     252                        while(item = attributes[i++]){
     253                                if(!item || !item.specified){
     254                                        continue;
     255                                }
     256                                var lcName = item.name.toLowerCase(),
     257                                        paramMeta = clsInfo.params[lcName],
     258                                        name =  paramMeta ? paramMeta.name : item.name,
     259                                        value = item.value;
     260
     261                                switch(lcName){
     262
     263                                // Data-dojo-props.   Save for later to make sure it overrides direct foo=bar settings
     264                                case dataDojoProps:             // data-dojo-props
     265                                        var extra = value;
     266                                        break;
     267
     268                                // The data-dojo-type=... setting itself, already processed
     269                                case dataDojoType:
     270                                case dojotype:
     271                                        break;
     272
     273                                // data-dojo-id or jsId. TODO: drop jsId in 2.0
     274                                case dataDojoId:
     275                                case "jsid":
     276                                        var jsname = value;
     277                                        break;
     278
     279                                // For the benefit of _Templated
     280                                case dataDojoAttachPoint:
     281                                        params.dojoAttachPoint = value;
     282                                        break;
     283                                case dataDojoAttachEvent:
     284                                        params.dojoAttachEvent = value;
     285                                        break;
     286
     287                                // Special parameter handling needed for IE
     288                                case "class":
     289                                        params["class"] = node.className;
     290                                        break;
     291                                case "style":
     292                                        params["style"] = node.style && node.style.cssText;
     293                                        break;
     294
     295                                // Normal attribute, ex: value="123"
     296                                default:
     297                                        if(typeof value == "string" && paramMeta){
     298                                                params[name] = str2obj(value, paramMeta.type);
    272299                                        }else{
    273300                                                params[name] = value;
     
    275302                                }
    276303                        }
     304
     305                        // Mix things found in data-dojo-props into the params, overriding any direct settings
     306                        if(extra){
     307                                try{
     308                                        extra = d.fromJson.call(args.propsThis, "{" + extra + "}");
     309                                        d._mixin(params, extra);
     310                                }catch(e){
     311                                        // give the user a pointer to their invalid parameters. FIXME: can we kill this in production?
     312                                        throw new Error(e.toString() + " in data-dojo-props='" + extra + "'");
     313                                }
     314                        }
     315
     316                        // Any parameters specified in "mixin" override everything else.
     317                        d._mixin(params, mixin);
     318
     319                        var scripts = obj.node ? obj.scripts : (clazz && (clazz._noScript || clazz.prototype._noScript) ? [] :
     320                                                d.query("> script[type^='dojo/']", node));
     321
    277322
    278323                        // Process <script type="dojo/*"> script tags
     
    308353
    309354                        // map it to the JS namespace if that makes sense
    310                         // FIXME: in 2.0, drop jsId support. use data-dojo-id instead
    311                         var jsname = (node.getAttribute(attrData + "id") || node.getAttribute("jsId"));
    312355                        if(jsname){
    313356                                d.setObject(jsname, instance);
     
    426469                args = args || {};
    427470
    428                 var attrName = (args.scope || d._scopeName) + "Type",           // typically "dojoType"
     471                var dojoType = (args.scope || d._scopeName) + "Type",           // typically "dojoType"
    429472                        attrData = "data-" + (args.scope || d._scopeName) + "-",        // typically "data-dojo-"
    430473                        dataDojoType = attrData + "type",                                               // typically "data-dojo-type"
     
    505548                        }
    506549
    507                         // Check for data-dojo-type attributes
    508                         var type, html5 = node.getAttribute(dataDojoType);
    509                         if(html5){
    510                                 type = html5;
    511                         }else{
    512                                 // fallback to backward compatible mode, using dojoType. remove in 2.0
    513                                 type = node.getAttribute(attrName);
    514                         }
    515                         var fastpath = html5 == type;
     550                        // Check for data-dojo-type attribute, fallback to backward compatible dojoType
     551                        var type = node.getAttribute(dataDojoType) || node.getAttribute(dojoType);
    516552
    517553                        // Short circuit for leaf nodes containing nothing [but text]
     
    530566
    531567                        // If dojoType/data-dojo-type specified, add to output array of nodes to instantiate
    532                         var clsInfo = type && getClassInfo(type, fastpath), // note: won't find classes declared via dojo.Declaration
     568                        var clsInfo = type && getClassInfo(type), // note: won't find classes declared via dojo.Declaration
    533569                                childScripts = clsInfo && !clsInfo.cls.prototype._noScript ? [] : null; // <script> nodes that are parent's children
    534570                        if(type){
    535571                                list.push({
    536572                                        "type": type,
    537                                         fastpath: fastpath,
    538573                                        clsInfo: clsInfo,
    539574                                        node: node,
  • dojo/trunk/tests/parser.html

    r24073 r24185  
    1111                <script type="text/javascript">
    1212                define("dojo/tests/parser/script", ["dojo", "dojo/parser", "doh/runner"], function(dojo) {
     13
     14                        dojo.declare("tests.parser.Widget", null, {
     15                                constructor: function(args, node){
     16                                        this.params = args;
     17                                }
     18                        });
    1319
    1420                        dojo.declare("tests.parser.Class1", null, {
     
    6773                        });
    6874                       
    69                         dojo.declare("tests.parser.inputClass", null, {
    70                                 constructor: function(args, node){ dojo.mixin(this, args); },
     75                        dojo.declare("tests.parser.InputClass", null, {
     76                                constructor: function(args, node){
     77                                        this.params = args;
     78                                        dojo.mixin(this, args);
     79                                },
     80
    7181                                // these attributes are special in HTML, they don't have a value specified
    7282                                disabled: false,
    73                                 checked: false
     83                                readonly: false,
     84                                checked: false,
     85
     86                                // other attributes native to HTML
     87                                value: "",
     88                                title: "default title",
     89                                tabIndex: "0",          // special because mixed case
     90
     91                                // custom widget attributes that don't match a native HTML attributes
     92                                custom1: 123,
     93                                custom2: 456
    7494                        });
    7595
     
    117137                                        this._ran = true;
    118138                                }
    119                         })
     139                        });
    120140                       
    121141
     
    126146                        };
    127147
     148                        tests.parser.FormClass = dojo.declare(tests.parser.Widget, {
     149                                encType: ""
     150                        });
     151
    128152                        dojo.addOnLoad(function(){
    129                                 doh.register("t",
     153                                doh.register("basic tests",
    130154                                        [
    131155                                                function parse(){
    132156                                                        // Running the parser here so that failures appear in test log
    133                                                         dojo.parser.parse();
    134                                                 },
    135 
     157                                                        dojo.parser.parse(dojo.byId("main"));
     158                                                },
     159
     160                                                function testDataDojoId(t){
     161                                                        t.t(typeof obj == "object");
     162                                                },
    136163                                                function testJsId(t){
    137                                                         // console.debug(obj);
    138                                                         t.t(typeof obj == "object");
    139                                                 },
    140 
     164                                                        t.t(typeof obj3 == "object");
     165                                                },
    141166                                                // Attribute parsing tests
    142167                                                function testStrProp(t){
     
    210235                                                },
    211236                                                function testDisabledFlag(t){
    212                                                         t.is("boolean", (typeof disabledObj.disabled));
    213                                                         t.t(disabledObj.disabled);
    214                                                         t.f(disabledObj.checked);
     237                                                        t.is("boolean", typeof disabledObj.disabled, "typeof disabled");
     238                                                        t.t(disabledObj.disabled, "disabled");
     239                                                        t.f(disabledObj.checked, "checked");
    215240                                                },
    216241                                                function testCheckedFlag(t){
    217                                                         t.is("boolean", (typeof checkedObj.checked));
    218                                                         t.f(checkedObj.disabled);
    219                                                         t.t(checkedObj.checked);
     242                                                        t.is("boolean", typeof checkedObj.checked, "typeof checked");
     243                                                        t.f(checkedObj.disabled, "disabled");
     244                                                        t.t(checkedObj.checked, "checked");
    220245                                                },
    221246                                                function testFunctionProp(t){
     
    384409                                        ]
    385410                                );
     411
     412                                doh.register("IE attribute detection", [
     413                                        function input1(){
     414                                                var widgets = dojo.parser.instantiate([dojo.byId("ieInput1")]);
     415                                                var params = widgets[0].params;
     416
     417                                                doh.is("checkbox", params.type, "type");
     418                                                doh.t(params.disabled, "disabled");
     419                                                doh.t(params.checked, "checked");
     420                                                doh.t(params.readonly, "readonly");
     421                                                doh.is("bar", params.foo, "foo");
     422                                                doh.is("zaz", params.bar, "bar");
     423                                                doh.is("escaped\"dq", params.bob, "bob");
     424                                                doh.is("escaped\'sq", params.frank, "frank");
     425                                        },
     426                                        function input2(){
     427                                                var widgets = dojo.parser.instantiate([dojo.byId("ieInput2")]);
     428                                                var params = widgets[0].params;
     429
     430                                                doh.f("type" in params, "type");
     431                                                doh.f("name" in params, "name");
     432                                                doh.f("value" in params, "value");
     433                                                doh.f("data-dojo-type" in params, "data-dojo-type");
     434                                                doh.f("data-dojo-props" in params, "data-dojo-props");
     435                                                doh.is("hi", params.foo, "foo");
     436                                        },
     437                                        function input3(){
     438                                                var widgets = dojo.parser.instantiate([dojo.byId("ieInput3")]);
     439                                                var params = widgets[0].params;
     440
     441                                                doh.is("password", params.type, "type");
     442                                                doh.is("test", params.name, "name");
     443                                                doh.is("123", params.value, "value");
     444                                                doh.is("myClass", params["class"], "class");
     445                                                doh.is("display:block", params["style"].replace(/[ ;]/g, "").toLowerCase(), "style");
     446                                                doh.is("3", params.tabIndex, "tabIndex");
     447                                        },
     448                                        function textarea(){
     449                                                var widgets = dojo.parser.instantiate([dojo.byId("ieTextarea")]);
     450                                                var params = widgets[0].params;
     451
     452                                                doh.is("attrVal", params.value, "value");
     453                                        },
     454                                        function button1(){
     455                                                var widgets = dojo.parser.instantiate([dojo.byId("ieButton1")]);
     456                                                var params = widgets[0].params;
     457                                                doh.t(params.checked, "checked");
     458                                                doh.is("button1val", params.value, "value");
     459                                        },
     460                                        function button2(){
     461                                                var widgets = dojo.parser.instantiate([dojo.byId("ieButton2")]);
     462                                                var params = widgets[0].params;
     463                                                doh.f("checked" in params, "checked");
     464                                                doh.f("value" in params, "value");
     465                                        },
     466                                        function button3(){
     467                                                var widgets = dojo.parser.instantiate([dojo.byId("ieButton3")]);
     468                                                var params = widgets[0].params;
     469                                                doh.t(params.checked, "checked");
     470                                        },
     471                                        function button4(){
     472                                                var widgets = dojo.parser.instantiate([dojo.byId("ieButton4")]);
     473                                                var params = widgets[0].params;
     474                                                doh.f("checked" in params);
     475                                        },
     476                                        function form1(){
     477                                                var widgets = dojo.parser.instantiate([dojo.byId("ieForm1")]);
     478                                                var params = widgets[0].params;
     479
     480                                                doh.is("foo", params.encType, "encType is specified");
     481                                        },
     482                                        function form2(){
     483                                                var widgets = dojo.parser.instantiate([dojo.byId("ieForm2")]);
     484                                                var params = widgets[0].params;
     485
     486                                                doh.f("encType" in params, "encType not specified")
     487                                        },
     488                                        function li(){
     489                                                var widgets = dojo.parser.instantiate([dojo.byId("li")]);
     490                                                var params = widgets[0].params;
     491                                                doh.is("home", params.value);
     492
     493                                        }
     494                                ]);
     495
     496                                doh.register("mixed attribute specification", function mixed(){
     497                                        dojo.parser.parse(dojo.byId("mixedContainer"));
     498                                        doh.is("object", typeof mixedObj, "widget created");
     499                                        doh.is("mixedValue", mixedObj.value, "native attribute")
     500                                        doh.is(999, mixedObj.custom1, "data-dojo-props attribute");
     501                                        doh.is("custom title", mixedObj.title, "data-dojo-props overrides native");
     502                                });
     503
    386504                                doh.run();
    387505                        })
     
    391509        <body>
    392510                <h1>Parser Unit Test</h1>
    393                 <script>
    394                         function foo(){ this.fooCalled=true; }
    395                 </script>
    396                 <div dojoType="tests.parser.Class1" data-dojo-id="obj"
    397                         strProp1="text" strProp2=""
    398                         intProp="5"
    399                         arrProp="foo, bar, baz"
    400                         arrProp2=""
    401                         boolProp1="true" boolProp2="false"
    402                         dateProp1="2006-01-01" dateProp2="" dateProp3="now"
    403                         funcProp2="foo" funcProp3="this.func3Called=true;"
    404                 >
    405                         <script type="dojo/method" event="preamble">
    406                                 this.preambleTestProp = 3;
     511
     512                <div id=main>
     513                        <script>
     514                                function foo(){ this.fooCalled=true; }
    407515                        </script>
    408                         <script type="dojo/method">
    409                                 // this should be run immediately
    410                                 this.deepProp = deepTestProp;
    411                         </script>
    412                         <script type="dojo/connect" event="callInc">
    413                                 this.callCount++;
    414                         </script>
    415                         <script type="dojo/method" event="callInc2">
    416                                 this.callCount2++;
    417                         </script>
    418                 </div>
    419                 <div>
    420                         <div type="tests.parser.Class1" jsId="obj2" id="toParse">
    421                         </div>
    422                 </div>
    423                 <div dojoType="tests.parser.Class2" jsId="obj3">
    424                 </div>
    425                 <div dojoType="tests.parser.Class3" jsId="obj4">
    426                 </div>
    427                 <input dojoType="tests.parser.inputClass" jsId="checkedObj" checked type="checkbox">
    428                 <button dojoType="tests.parser.inputClass" jsId="disabledObj" disabled>hi</button>
    429                
    430                 <div id="parsertest"></div>
    431                 <div id="parsertest2"></div>
    432 
    433                 <!-- section for testing that dir attribute trickles down from ancestor -->
    434                 <div dojoType="tests.parser.DirClass" jsId="setRtl" dir="rtl" name="RTL setting"></div>
    435                 <div dir="rtl">
    436                         <div dojoType="tests.parser.DirClass" jsId="inheritRtl" name="inherited RTL from parent"></div>
    437                         <div dir="ltr">
    438                                 <div dojoType="tests.parser.DirClass" jsId="inheritLtr" name="inherited LTR from parent"></div>
    439                         </div>
    440                         <div>
    441                                 <div dojoType="tests.parser.DirClass" jsId="inheritRtl2" name="inherited RTL from grandparent"></div>
    442                         </div>
    443                         <div dojoType="tests.parser.DirClass" jsId="setLtr" dir="ltr" name="LTR setting overrides inherited RTL"></div>
    444                 </div>
    445                 <div dojoType="tests.parser.DirClass" jsId="noDir" name="dir not inherited or set"></div>
    446                
    447                 <!-- section for testing parser recursion -->
    448 
    449                 <div>
    450                         <div dojoType="tests.parser.NormalContainer" jsId="container1">
    451                                 <!-- this script tag should get passed as param to NormalContainer constructor -->
    452                                 <script type="dojo/method" event="incr" args="x">
    453                                         return x+1;
    454                                 </script>
    455                                
    456                                 <!-- and these contained widgets should get instantiated -->
    457                                 <div dojoType="tests.parser.Class1" jsId="contained1"></div>
    458                                 <div>
    459                                         <div dojoType="tests.parser.Class1" jsId="contained2"></div>                   
    460                                 </div>
    461                         </div>
    462                 </div>
    463 
    464                 <div>
    465                         <div dojoType="tests.parser.ShieldedContainer" jsId="container2">
    466                                 <!-- this script tag should get passed as param to NormalContainer constructor -->
    467                                 <script type="dojo/method" event="incr" args="x">
    468                                         return x+1;
    469                                 </script>
    470                                
    471                                 <!-- but these contained widgets should *not* get instantiated -->
    472                                 <div dojoType="tests.parser.Class1" jsId="contained3"></div>
    473                                 <div>
    474                                         <div dojoType="tests.parser.Class1" jsId="contained4"></div>                   
    475                                 </div>
    476                         </div>
    477                 </div>
    478 
    479                 <div>
    480                         <div data-dojo-id="html5simple" data-dojo-type="tests.parser.HTML5Props" data-dojo-props="simple:true"></div>
    481                         <div data-dojo-id="html5simple2" data-dojo-type="tests.parser.HTML5Props"
    482                                 data-dojo-props="simple:false, a:1, b:'two', c:[1,2,3], d:function(){ return this; }, e:{ f:'g' }"
    483                         ></div>
    484                         <!-- note needing to use a named inherited lookup because we're just mixing in -->
    485                         <div data-dojo-id="html5simple3" data-dojo-type="tests.parser.HTML5Props"
    486                                 data-dojo-props="afn: function(){ return this.inherited('afn', arguments); }"
    487                         ></div>
    488                        
    489                         <!-- not used for tests, but thinking out loud: what about a named-resource prop, via getObject -->
    490                         <div data-dojo-id="html5fromobjectns" data-dojo-type="tests.parser.HTML5Props"
    491                                 data-dojo-obj="tests.parser.HTML5Props._aDefaultObj"
    492                         ></div>
    493                         <div data-dojo-id="html5fromobjectns2" data-dojo-type="tests.parser.HTML5Props"
    494                                 data-dojo-obj="tests.parser.HTML5Props._aDefaultObj" data-dojo-props="simple:false"
    495                         ></div>
    496                        
    497                 </div>
    498                
    499                 <div>
    500                         <div data-dojo-id="htmldojomethod" data-dojo-type="tests.parser.HTML5withMethod">
    501                                 <p>Some random markup</p>
    502                                 <script type="dojo/method" data-dojo-event="someMethod" data-dojo-args="a, b">
    503                                         return this.baseValue + a + b;
    504                                 </script>
    505                                 <script type="dojo/connect" data-dojo-event="diffMethod" data-dojo-args="a">
    506                                         this._fromvalue = a;
     516                        <div dojoType="tests.parser.Class1" data-dojo-id="obj"
     517                                strProp1="text" strProp2=""
     518                                intProp="5"
     519                                arrProp="foo, bar, baz"
     520                                arrProp2=""
     521                                boolProp1="true" boolProp2="false"
     522                                dateProp1="2006-01-01" dateProp2="" dateProp3="now"
     523                                funcProp2="foo" funcProp3="this.func3Called=true;"
     524                        >
     525                                <script type="dojo/method" event="preamble">
     526                                        this.preambleTestProp = 3;
    507527                                </script>
    508528                                <script type="dojo/method">
    509                                         this._methodRan = true;
     529                                        // this should be run immediately
     530                                        this.deepProp = deepTestProp;
    510531                                </script>
    511                         </div>
     532                                <script type="dojo/connect" event="callInc">
     533                                        this.callCount++;
     534                                </script>
     535                                <script type="dojo/method" event="callInc2">
     536                                        this.callCount2++;
     537                                </script>
     538                        </div>
     539                        <div>
     540                                <div type="tests.parser.Class1" jsId="obj2" id="toParse">
     541                                </div>
     542                        </div>
     543                        <div dojoType="tests.parser.Class2" jsId="obj3">
     544                        </div>
     545                        <div dojoType="tests.parser.Class3" jsId="obj4">
     546                        </div>
     547                        <input dojoType="tests.parser.InputClass" jsId="checkedObj" checked type="checkbox">
     548                        <button dojoType="tests.parser.InputClass" jsId="disabledObj" disabled>hi</button>
     549
     550                        <div id="parsertest"></div>
     551                        <div id="parsertest2"></div>
     552
     553                        <!-- section for testing that dir attribute trickles down from ancestor -->
     554                        <div dojoType="tests.parser.DirClass" jsId="setRtl" dir="rtl" name="RTL setting"></div>
     555                        <div dir="rtl">
     556                                <div dojoType="tests.parser.DirClass" jsId="inheritRtl" name="inherited RTL from parent"></div>
     557                                <div dir="ltr">
     558                                        <div dojoType="tests.parser.DirClass" jsId="inheritLtr" name="inherited LTR from parent"></div>
     559                                </div>
     560                                <div>
     561                                        <div dojoType="tests.parser.DirClass" jsId="inheritRtl2" name="inherited RTL from grandparent"></div>
     562                                </div>
     563                                <div dojoType="tests.parser.DirClass" jsId="setLtr" dir="ltr" name="LTR setting overrides inherited RTL"></div>
     564                        </div>
     565                        <div dojoType="tests.parser.DirClass" jsId="noDir" name="dir not inherited or set"></div>
     566
     567                        <!-- section for testing parser recursion -->
     568
     569                        <div>
     570                                <div dojoType="tests.parser.NormalContainer" jsId="container1">
     571                                        <!-- this script tag should get passed as param to NormalContainer constructor -->
     572                                        <script type="dojo/method" event="incr" args="x">
     573                                                return x+1;
     574                                        </script>
     575
     576                                        <!-- and these contained widgets should get instantiated -->
     577                                        <div dojoType="tests.parser.Class1" jsId="contained1"></div>
     578                                        <div>
     579                                                <div dojoType="tests.parser.Class1" jsId="contained2"></div>
     580                                        </div>
     581                                </div>
     582                        </div>
     583
     584                        <div>
     585                                <div dojoType="tests.parser.ShieldedContainer" jsId="container2">
     586                                        <!-- this script tag should get passed as param to NormalContainer constructor -->
     587                                        <script type="dojo/method" event="incr" args="x">
     588                                                return x+1;
     589                                        </script>
     590
     591                                        <!-- but these contained widgets should *not* get instantiated -->
     592                                        <div dojoType="tests.parser.Class1" jsId="contained3"></div>
     593                                        <div>
     594                                                <div dojoType="tests.parser.Class1" jsId="contained4"></div>
     595                                        </div>
     596                                </div>
     597                        </div>
     598
     599                        <!-- tests for new data-dojo-type / data-dojo-props syntax -->
     600                        <div>
     601                                <div data-dojo-id="html5simple" data-dojo-type="tests.parser.HTML5Props" data-dojo-props="simple:true"></div>
     602                                <div data-dojo-id="html5simple2" data-dojo-type="tests.parser.HTML5Props"
     603                                        data-dojo-props="simple:false, a:1, b:'two', c:[1,2,3], d:function(){ return this; }, e:{ f:'g' }"
     604                                ></div>
     605                                <!-- note needing to use a named inherited lookup because we're just mixing in -->
     606                                <div data-dojo-id="html5simple3" data-dojo-type="tests.parser.HTML5Props"
     607                                        data-dojo-props="afn: function(){ return this.inherited('afn', arguments); }"
     608                                ></div>
     609
     610                                <!-- not used for tests, but thinking out loud: what about a named-resource prop, via getObject -->
     611                                <div data-dojo-id="html5fromobjectns" data-dojo-type="tests.parser.HTML5Props"
     612                                        data-dojo-obj="tests.parser.HTML5Props._aDefaultObj"
     613                                ></div>
     614                                <div data-dojo-id="html5fromobjectns2" data-dojo-type="tests.parser.HTML5Props"
     615                                        data-dojo-obj="tests.parser.HTML5Props._aDefaultObj" data-dojo-props="simple:false"
     616                                ></div>
     617
     618                        </div>
     619
     620                        <div>
     621                                <div data-dojo-id="htmldojomethod" data-dojo-type="tests.parser.HTML5withMethod">
     622                                        <p>Some random markup</p>
     623                                        <script type="dojo/method" data-dojo-event="someMethod" data-dojo-args="a, b">
     624                                                return this.baseValue + a + b;
     625                                        </script>
     626                                        <script type="dojo/connect" data-dojo-event="diffMethod" data-dojo-args="a">
     627                                                this._fromvalue = a;
     628                                        </script>
     629                                        <script type="dojo/method">
     630                                                this._methodRan = true;
     631                                        </script>
     632                                </div>
     633                        </div>
     634                </div> <!-- end of <div id=main> -->
     635
     636                <!-- tests that we can parse parameters correctly on IE6/7, not getting tripped up by escaped quotes etc. -->
     637                <div id=ie>
     638                        <input id="ieInput1" data-dojo-type="tests.parser.InputClass"
     639                                        type=checkbox disabled foo = 'bar' readonly bar=zaz bob='escaped"dq' frank="escaped'sq" checked />
     640                        <input id="ieInput2" data-dojo-type="tests.parser.InputClass"
     641                                        fakeout1="type=submit" fakeout2="name='test'" fakeout3="value='123'" data-dojo-props="foo: 'hi'"/>
     642                        <input id="ieInput3" data-dojo-type="tests.parser.InputClass"
     643                                        type=password name="test" value="123" class="myClass" style="display:block" tabindex="3"/>
     644                        <textarea id="ieTextarea" data-dojo-type="tests.parser.InputClass" value="attrVal">contentVal</textarea>
     645                        <button id="ieButton1" data-dojo-type="tests.parser.InputClass" checked value="button1val">
     646                                        checked ToggleButton as button
     647                        </button>
     648                        <button id="ieButton2" data-dojo-type="tests.parser.InputClass">
     649                                        unchecked ToggleButton as button
     650                        </button>
     651                        <div id="ieButton3" data-dojo-type="tests.parser.InputClass" checked>
     652                                        checked ToggleButton as div
     653                        </div>
     654                        <div id="ieButton4" data-dojo-type="tests.parser.InputClass">
     655                                        unchecked ToggleButton as div
     656                        </div>
     657                        <form id="ieForm1" data-dojo-type="tests.parser.FormClass" encType="foo"></form>
     658                        <form id="ieForm2" data-dojo-type="tests.parser.FormClass"></form>
     659                        <ul dojoType="tests.parser.Widget" class="nav">
     660                                <li id="li" dojoType="tests.parser.Widget" value="home">Home</li>
     661                                <li dojoType="tests.parser.Widget" value="contact">Contact</li>
     662                                <li dojoType="tests.parser.Widget" value="group">Group</li>
     663                                <li dojoType="tests.parser.Widget" value="campaign">Campaign</li>
     664                        </ul>
     665                </div>
     666
     667                <!-- tests for when parameters are specified both natively and in data-dojo-props. -->
     668                <div id="mixedContainer">
     669                        <input data-dojo-type="tests.parser.InputClass" data-dojo-id="mixedObj"
     670                                  value="mixedValue" title="native title" data-dojo-props="custom1: 999, title: 'custom title'">
    512671                </div>
    513672
Note: See TracChangeset for help on using the changeset viewer.