UNPKG

dijit

Version:

Dijit provides a complete collection of user interface controls based on Dojo, giving you the power to create web applications that are highly optimized for usability, performance, internationalization, accessibility, but above all deliver an incredible u

618 lines (561 loc) 23.1 kB
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <title>WidgetsInTemplateMixin.js</title> <style type="text/css"> /* Make our tests stand out as easily identifiable content */ .testcontainer { border: 10px yellow; border-style: dashed; padding: 1em; margin: 1em; } .testcontainer > p { padding: 0 1em; font-weight: bold; } </style> <script type="text/javascript" src="boilerplate.js"></script> <script type="text/javascript"> require([ "doh", "dojo/_base/array", "dojo/_base/declare", "dojo/_base/window", "dojo/dom", "dojo/dom-geometry", "dojo/html", "dojo/on", "dojo/query", "dojo/parser", "dijit/registry", "dijit/_WidgetBase", "dijit/_Widget", "dijit/_AttachMixin", "dijit/_TemplatedMixin", "dijit/_WidgetsInTemplateMixin", "dijit/form/Button", "dijit/form/CheckBox", "dijit/form/TextBox", "dijit/ProgressBar", "dijit/_Container", "dijit/_Contained", "dijit/layout/ContentPane", "dijit/layout/_LayoutWidget", "dijit/layout/LayoutContainer", "dijit/tests/resources/TestContextRequireWidget", "dojo/domReady!" ], function(doh, array, declare, win, dom, domGeom, html, on, query, parser, registry, _WidgetBase, _Widget, _AttachMixin, _TemplatedMixin, _WidgetsInTemplateMixin, Button, CheckBox, TextBox, ProgressBar, _Container, _Contained, _LayoutWidget, LayoutContainer){ declare('Test1Widget', [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], { templateString: dom.byId('Test1Template').value, onClick: function(e){ if(e.target){ alert('onClick widgetId='+e.target.id); }else{ if(e._counter == undefined){ e._counter = 1; }else{ e._counter++; } } } }); declare('Test3Widget', [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin], { templateString: dom.byId('Test3Template').value }); declare('TestLayoutWidget', _LayoutWidget, { startup: function(){ if(this._started){ this._doubleStarted = true; } this.inherited(arguments); }, destroy: function(){ if(this._destroyed){ this._doubleDestroyed = true; } this.inherited(arguments); this._destroyed = true; } }); declare('TestCtnrWidget', [_WidgetBase, _Container], { startup: function(){ if(this._started){ this._doubleStarted = true; } this.inherited(arguments); }, destroy: function(){ if(this._destroyed){ this._doubleDestroyed = true; } this.inherited(arguments); this._destroyed = true; } }); declare('TestCtndWidget', [_WidgetBase, _Contained], { startup: function(){ if(this._started){ this._doubleStarted = true; } this.inherited(arguments); }, destroy: function(){ if(this._destroyed){ this._doubleDestroyed = true; } this.inherited(arguments); this._destroyed = true; } }); declare('TestNonCtnrWidget', [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], { templateString: "<div data-dojo-attach-point=containerNode></div>", startup: function(){ if(this._started){ this._doubleStarted = true; } this.inherited(arguments); }, destroy: function(){ if(this._destroyed){ this._doubleDestroyed = true; } this.inherited(arguments); this._destroyed = true; } }); declare('TestStubWidget', _WidgetBase, { startup: function(){ if(this._started){ this._doubleStarted = true; } this.inherited(arguments); }, destroy: function(){ if(this._destroyed){ this._doubleDestroyed = true; } this.inherited(arguments); this._destroyed = true; } }); declare('Test5Widget', [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], { templateString: dom.byId('Test5Template').value, startup: function(){ if(this._started){ this._doubleStarted = true; } this.inherited(arguments); }, destroy: function(){ if(this._destroyed){ this._doubleDestroyed = true; } this.inherited(arguments); this._destroyed = true; } }); declare('Test6Widget', [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], { templateString: dom.byId('Test6Template').value, clickCount: 0, handleClick: function(){ this.clickCount++; } }); declare("Missing", [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], { templateString: '<div>' + '<div data-dojo-type="dijit/layout/ContentPane">' + '<div data-dojo-type="dijit/form/Button" data-dojo-props="id: \'missingButtonId\'" ' + 'data-dojo-attach-point="missingButton">Missing...</div>' + '</div>' + '</div>' }); function getTest5WidgetsInTemplate(testW){ // summary: // Returns all the widgets in the template for a Test5Widget return [ testW, testW.layout, testW.layChild1, testW.layChild2, testW.container, testW.contained1, testW.contained2, testW.nonContainer, testW.nonContained1, testW.nonContained2, testW.threeLevel, testW.secondLevel, testW.bottomLevel, testW.anotherThree, testW.anotherSecond, testW.anotherBottom, testW.stub1 ]; } function validateTest5Widget(/*Test5Widget*/ testW, /*Boolean*/ started){ // Check that testW widget, and all the widgets in it's template, got started, but not double-started array.forEach(getTest5WidgetsInTemplate(testW), function(w){ if(started){ doh.t(w._started, w + " should be started"); }else{ doh.f(w._started, w + " should not be started"); } doh.is(undefined, w._doubleStarted, "w._doubleStarted: " + w); }); } function validateTest5WidgetDestroy(t, testW){ var savedWidgets = getTest5WidgetsInTemplate(testW); testW.destroy(); array.forEach(savedWidgets, function(w, idx){ doh.t(w._destroyed, "w._destroyed: " + w); doh.is(undefined, w._doubleDestroyed, "w._doubleDestroyed: " + w); }); } doh.register("_AttachMixin-widgetInTemplate", [ function createAttachWidgetsCombo() { /*** TEST _AttachMixin combined with _WidgetsInTemplateMixin ***/ var AttachWidgetsCombo = declare([ _WidgetBase, _AttachMixin, _WidgetsInTemplateMixin ], { postCreate: function() { html.set(this.heading, "Amazing things will happen if you click this button!!!"); }, _buttonClicked: function(e) { html.set(this.heading, "Well that was boring. " + "My attach point button thinks it is a " + (this.mybutton.isInstanceOf(Button) ? 'dijit/form/Button':'Gruffalo')); } }); var myawc = new AttachWidgetsCombo({}, dom.byId('attachMeThree')); doh.t(myawc.heading, "heading"); doh.t(myawc.mybutton, "mybutton"); doh.is("Amazing things will happen if you click this button!!!", myawc.heading.innerHTML, "Initial value"); // Simulate clicking the button. Don't use click() because it's not supported on a <span> // in Android < 4.4. on.emit(myawc.mybutton.focusNode, "click", { bubbles: true, cancelable: true }); doh.is("Well that was boring. My attach point button thinks it is a dijit/form/Button", myawc.heading.innerHTML, "Post-op value"); }, function containerNode(){ // Test that widgets inside of containerNode aren't parsed by _WidgetsInTemplateMixin declare("OuterWidget", [ _WidgetBase, _AttachMixin, _WidgetsInTemplateMixin ], { // Prevent the main parser call from hitting my supporting widgets. // But this also stops the parser from hitting anything inside my containerNode, so I need // to do a recursive parse() like ContentPane does (or just extend ContentPane) stopParser: true, postCreate: function(){ doh.is(0, this.getChildren().length, "contained widget not created yet"); parser.parse(this.containerNode); } }); declare("SupportingWidget", _WidgetBase); declare("ContainedWidget", _WidgetBase); parser.parse(dom.byId("containerNode")); doh.t("outerWidget" in window, "outer widget created"); doh.t(outerWidget.supportingWidget, "supporting widget instantiated"); doh.f(outerWidget.containedWidget, "contained widget not instantiated by _WidgetsInTemplateMixin parse call"); doh.is(1, outerWidget.getChildren().length, "contained widget created too"); } ]); doh.register("_Templated-widgetsInTemplate", [ function parse(){ parser.parse("templateTests"); }, { name: "data-dojo-attach-point", runTest: function(t){ var testW = registry.byId("test1Widget"); doh.t(testW, "test1Widget was instantiated"); doh.t(testW.normalNode, "normalNode"); doh.f(isNaN(testW.normalNode.nodeType), "normalNode.nodeType"); doh.t(testW.buttonWidget instanceof Button, "buttonWidget is Button"); doh.t(testW.checkboxWidget instanceof CheckBox, "checkboxWidget is CheckBox"); doh.t(testW.progressBarWidget instanceof ProgressBar, "progressBarWidget is ProgressBar"); } }, { name: "data-dojo-attach-event", runTest: function(t){ var testW = registry.byId("test1Widget"); testW.buttonWidget._counter=0; testW.buttonWidget.onClick(testW.buttonWidget); testW.checkboxWidget._counter=0; testW.checkboxWidget.onClick(testW.checkboxWidget); testW.progressBarWidget._counter=0; testW.progressBarWidget.onChange(testW.progressBarWidget); doh.is(1,testW.buttonWidget._counter, "buttonWidget._counter"); doh.is(1,testW.checkboxWidget._counter, "checkboxWidget._counter"); doh.is(1,testW.progressBarWidget._counter, "progressBarWidget._counter"); } }, { name: "data-dojo-attach-event strange name", runTest: function(t){ // This is for testing data-dojo-attach-event to attach to a method in the widget, // rather than using _WidgetBase.on(...). Remove for 2.0. var SubWidget = declare("SubWidget", _WidgetBase, { f: function(){ // just for attaching to } }); var MainWidget = declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], { templateString: '<div>' + '<div data-dojo-type="SubWidget" data-dojo-attach-point="sw" ' + ' data-dojo-attach-event="f: g">' + '</div>', g: function(){ this.gWasCalled = true; } }); var mw = new MainWidget(); doh.t(mw.sw, "attach-point exists"); mw.sw.f(); doh.t(mw.gWasCalled, "attach-event worked"); } }, { // Test that getDescendants () // finds direct descendants but skips widgetsInTemplates // and also nested widgets (if direct==true) name: "getChildren", runTest: function(t){ var testW = registry.byId("test3Widget"); /*** performance tests var start = new Date(); for(var i=0; i<1000; i++) testW.getChildren(); console.log("*** time for getChildren(): " + (new Date()-start)); var start = new Date(); for(var i=0; i<1000; i++) testW.getDescendants(); console.log("*** time for getDescendants(false): " + (new Date()-start)); ***/ var chil = testW.getChildren(); doh.is(5, chil.length, "number of direct descendants"); doh.is(chil[0].id, "3.1"); doh.is(chil[1].id, "3.2"); doh.is(chil[2].id, "3.3"); doh.is(chil[3].id, "3.4"); doh.is(chil[4].id, "3.5"); // remove this test for 2.0 var desc = testW.getDescendants(); doh.is(7, desc.length, "number of descendants (including nested ones)"); doh.is(desc[0].id, "3.1"); doh.is(desc[1].id, "3.2"); doh.is(desc[2].id, "3.3"); doh.is(desc[3].id, "3.nested"); doh.is(desc[4].id, "3.nested2"); doh.is(desc[5].id, "3.4"); doh.is(desc[6].id, "3.5"); } }, { // Check that declarative widget with other widgets in template is correctly started name: "declarative widget with many child widgets", runTest: function(t){ validateTest5Widget(registry.byId("test5Widget"), true); } }, { // Check that programmatic widget with other widgets in template is correctly started name: "programmatic widget with many child widgets", runTest: function(t){ // Create widget. Widgets in template should not be started yet. test5WidgetProgrammatic = new Test5Widget(); validateTest5Widget(test5WidgetProgrammatic, false); // Place widget in DOM and startup. Widgets in template should now be started. test5WidgetProgrammatic.placeAt("test5Widget", "after"); test5WidgetProgrammatic.startup(); validateTest5Widget(test5WidgetProgrammatic, true); } }, { // Check that destroying our declarative widget works correctly name: "declarative widget destruction", runTest: function(t){ validateTest5WidgetDestroy(t, registry.byId("test5Widget")); } }, { // Check that destroying our programmatic widget works correctly name: "programmatic widget destruction", runTest: function(t){ validateTest5WidgetDestroy(t, test5WidgetProgrammatic); } }, { // Test that data-dojo-attach-point inside of a ContentPane (inside of a template) works name: "ContentPane", runTest: function(){ var testW = registry.byId("missing"); doh.t(testW, "widget was created"); doh.t(testW.missingButton, "data-dojo-attach-point created"); doh.is("dijit.form.Button", testW.missingButton.declaredClass, "and it's to a widget"); doh.t(registry.byId("missingButtonId"), "nested widget also registered by id"); } }, { // Test that data-dojo-attach-event bindings work with widgets in template, when // binding to dijit/_Widget methods name: "_Widget Deferred Connect methods", runTest: function(){ var test6Widget = registry.byId("test6Widget"); doh.t(test6Widget.clickCount === 0, "click count was initially zero"); // Issue a 'click' event directly on the interior input of the TextBox test6Widget.textbox.textbox.click(); doh.t(test6Widget.clickCount === 1, "click count incremented properly"); } }, function widgetsInTemplateLifecycle(t){ var result = [], expected = [1, 1, 0, 2, 2, 3]; // widgetsInTemplateLifecycle declare("SubThing", _WidgetBase, { postCreate: function(){ this.inherited(arguments); result.push(1); }, startup: function(){ this.inherited(arguments); result.push(2); } }); declare("ParentThing", [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], { templateString: "<div>" + "<span data-dojo-type='SubThing'>a</span>" + "<div data-dojo-type='dijit/layout/LayoutContainer'>" + "<span data-dojo-type='SubThing' data-dojo-props='region: \"center\"'>b</span>" + "</div>" + "</div>", postCreate: function(){ // children postcreate (x2) called before this postCreate this.inherited(arguments); result.push(0); }, startup: function(){ // then children startup (x2) then our startup // (we can call inherited after push(), and change the order) this.inherited(arguments); result.push(3); } }); new ParentThing().startup(); t.is(expected.length, result.length); array.forEach(expected, function(r){ t.is(r, result.shift()); }); } ]); // Test that "this" referenced from data-dojo-props can refer to the hosting widget doh.register("data-dojo-props this", function(){ var host = declare([dijit._WidgetBase, dijit._TemplatedMixin, dijit._WidgetsInTemplateMixin], { obj: {hello: "world"}, templateString: "<div>" + "<div data-dojo-type='dijit/_WidgetBase' data-dojo-props='hostObj: this.obj'" + " data-dojo-attach-point='subWidget'></div>" + "</div>" }); var hostWidget = new host(), subWidget = hostWidget && hostWidget.subWidget; doh.isNot(undefined, hostWidget, "created host widget"); doh.isNot(undefined, subWidget, "created sub widget"); doh.isNot(undefined, subWidget.hostObj, "sub widget got hostObj defined"); doh.is("world", subWidget.hostObj.hello, "object is correct") }); // Test that a context require can be passed to the parser doh.register("context require", function(){ var cw = registry.byId("testContextWidget"); doh.is(typeof cw.fooNode, "object", "button created"); doh.is(cw.fooNode.fooNode.innerHTML, "TestWidget", "sub widget contains right properties"); }); doh.run(); }); </script> </head> <body> <h1>WidgetsInTemplateMixin</h1> <!-- Tests for _WidgetsInTemplateMixin combined with _AttachMixin --> <div class="testcontainer"> <p>This test shows that a _AttachMixin dijit with _WidgetsInTemplate properly attaches widgets from the template.<br> <div id="attachMeThree"> <h2 data-dojo-attach-point='heading'></h2> <button data-dojo-type='dijit/form/Button' data-dojo-attach-point='mybutton' data-dojo-attach-event='click: _buttonClicked'>A button</button> </div> </div> <!-- Test that widgets inside containerNode aren't parsed by _WidgetsInTemplateMixin--> <div id="containerNode" class="testcontainer"> <p>This tests that nodes inside of data-dojo-attach-point="containerNode" are ignored<br> <div data-dojo-id="outerWidget" data-dojo-type="OuterWidget"> <h2 data-dojo-attach-point="heading">heading</h2> <div data-dojo-type="SupportingWidget" data-dojo-attach-point="supportingWidget">supporting widget</div> <div data-dojo-attach-point="containerNode"> <span data-dojo-type="ContainedWidget" data-dojo-attach-point="containedWidget">contained widget</span> </div> </div> </div> <!-- Tests for _WidgetsInTemplateMixin combined with _TemplatedMixin --> <div id="templateTests"> <textarea id="Test1Template" style="display:none;"> <div> <div data-dojo-attach-point="normalNode">normal node</div> <button data-dojo-attach-point="buttonWidget" data-dojo-attach-event="click:onClick" data-dojo-type="dijit/form/Button">button #1</button> <div data-dojo-attach-point="checkboxWidget" data-dojo-attach-event="click:onClick" data-dojo-type="dijit/form/CheckBox"></div> checkbox #1 <div data-dojo-attach-point="progressBarWidget" data-dojo-attach-event="change:onClick" data-dojo-type="dijit/ProgressBar" data-dojo-props='value: 20, maximum: 200, style: "width:400px;"'></div> </div> </textarea> <div data-dojo-type="Test1Widget" data-dojo-props="id: 'test1Widget'"></div> <textarea id="Test3Template" style="display:none;"> <div> <div data-dojo-attach-point="checkboxWidget" data-dojo-type="dijit/form/CheckBox"></div> checkbox #3 <div data-dojo-attach-point="containerNode"></div> </div> </textarea> <div data-dojo-type="Test3Widget" data-dojo-props="id: 'test3Widget'"> <span>hello world</span> <b style="border: 1px solid blue;">this is my <button data-dojo-type="dijit/form/Button" data-dojo-props="id: '3.1'">first button</button> </b> <button data-dojo-type="dijit/form/Button" data-dojo-props="id: '3.2'">another button</button> <i>and some more</i> <div style="border: 1px solid red;"> <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="style: {border: '1px solid gray'}, id: '3.3'"> <button data-dojo-type="dijit/form/Button" data-dojo-props="id: '3.nested'">a nested button</button> <button data-dojo-type="dijit/form/Button" data-dojo-props="id: '3.nested2'">another nested button</button> </div> <button data-dojo-type="dijit/form/Button" data-dojo-props="id: '3.4'">yet another button</button> <button data-dojo-type="dijit/form/Button" data-dojo-props="id: '3.5'">yet yet another button</button> </div> </div> <!-- Test templated widget containing container and nested widgets in template --> <textarea id="Test5Template" style="display:none;"> <div> <div data-dojo-type="TestLayoutWidget" data-dojo-attach-point="layout"> <div data-dojo-type="TestCtndWidget" data-dojo-attach-point="layChild1"></div> <div data-dojo-type="TestCtndWidget" data-dojo-attach-point="layChild2"></div> </div> <div data-dojo-type="TestCtnrWidget" data-dojo-attach-point="container"> <div data-dojo-type="TestCtndWidget" data-dojo-attach-point="contained1"></div> <div data-dojo-type="TestCtndWidget" data-dojo-attach-point="contained2"></div> </div> <div data-dojo-type="TestStubWidget" data-dojo-attach-point="stub1"></div> <div data-dojo-type="TestNonCtnrWidget" data-dojo-attach-point="nonContainer"> <div data-dojo-type="TestStubWidget" data-dojo-attach-point="nonContained1"></div> <div data-dojo-type="TestStubWidget" data-dojo-attach-point="nonContained2"></div> </div> <div data-dojo-type="TestCtnrWidget" data-dojo-attach-point="threeLevel"> <div data-dojo-type="TestNonCtnrWidget" data-dojo-attach-point="secondLevel"> <div data-dojo-type="TestStubWidget" data-dojo-attach-point="bottomLevel"></div> </div> </div> <div data-dojo-type="TestNonCtnrWidget" data-dojo-attach-point="anotherThree"> <div data-dojo-type="TestCtnrWidget" data-dojo-attach-point="anotherSecond"> <div data-dojo-type="TestCtndWidget" data-dojo-attach-point="anotherBottom"></div> </div> </div> </div> </textarea> <div data-dojo-type="Test5Widget" data-dojo-props="id: 'test5Widget'"></div> <div data-dojo-type="Missing" data-dojo-props="id: 'missing'"></div> <!-- Test templated widget containing relative MIDs for data-dojo-type --> <div data-dojo-type="dijit/tests/resources/TestContextRequireWidget" data-dojo-props="id: 'testContextWidget'"></div> <!-- Test templated widget for back-compat with inherited onClick etc events when using widgets in template --> <textarea id="Test6Template" style="display:none;"> <div> <div data-dojo-type="dijit/form/TextBox" data-dojo-attach-point="textbox" data-dojo-attach-event="onClick: handleClick"></div> </div> </textarea> <div data-dojo-type="Test6Widget" data-dojo-props="id: 'test6Widget'"></div> </div> </body> </html>