Dijit / form /在自定义小部件的Dijit / TitlePane部分内选择在错误的位置打开下拉列表

时间:2016-09-23 14:31:55

标签: javascript drop-down-menu dojo

我有以下小部件HTML。

<div class="expandableSearch">
    <div data-dojo-type="dijit/TitlePane" data-dojo-props="title:'${prefixTitle}', open:false" id="${containedWidgetId}titleNodePane">
        <div id="container"
        class="${baseClass}Container"
        data-dojo-attach-point="containerNode"></div>
    </div>
</div>

背后有以下Javascript:

/**
 * Javascript for ExpandableSearchComponent
 */
define([ "dojo/_base/declare", "dijit/_WidgetBase", "dijit/_TemplatedMixin",
        "dojo/text!./templates/ExpandableSearchComponent.html",
        "dijit/TitlePane", "dijit/_WidgetsInTemplateMixin", "dijit/registry",
        "dojo/on", "dojo/aspect", "dojo/_base/lang", "dojo/dom",
        "dojo/dom-attr", "js/utils/CommonUtils", "dijit/focus" ], function(declare,
        _WidgetBase, _TemplatedMixin, template, TitlePane,
        _WidgetsInTemplateMixin, registry, on, aspect, lang, dom, domAttr,
        CommonUtils, focusUtil) {

    return declare([ _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin ], {
        templateString : template,
        prefixTitle : "",
        containedWidgetId : "",
        defaultValue : "",

        startup : function() {
            this.inherited(arguments);
            var containedWidgetId = this.containedWidgetId;
            var containedWidget = registry.byId(this.containedWidgetId);
            if (typeof containedWidget === "undefined") {
                containedWidget = dom.byId(this.containedWidgetId);
            }

            var titlePane = registry.byId(this.containedWidgetId
                    + "titleNodePane");
            this.own(on(titlePane, "Show", function() {

                if (typeof containedWidget.loadAndOpenDropDown === "function") {
                    containedWidget._aroundNode = containedWidget.focusNode;
                    containedWidget.loadAndOpenDropDown();
                }
                focusUtil.focus(dom.byId(containedWidgetId));
            }));
            this.own(on(titlePane, "Hide", function() {
                if (typeof containedWidget.closeDropDown === "function") {
                    containedWidget.closeDropDown();
                }

            }));

            this.own(on(containedWidget, "change", function(event) {
                var newVal = "";
                if (typeof containedWidget.attr == "function"
                        && containedWidget.attr("displayedValue") !== null) {
                    newVal = containedWidget.attr("displayedValue");
                }
                if (typeof event === "object") {
                    newVal = containedWidget.value;
                }
                var newTitle = this.prefixTitle + newVal;
                if (newTitle.length > 35) {
                    newTitle = newTitle.substring(0, 32) + "...";
                }
                titlePane.set("title", newTitle);
                if (titlePane.open) {
                    titlePane.toggle();
                }
            }.bind(this)));

        },
        reset : function() {
            var containedWidget = registry.byId(this.containedWidgetId);
            if (typeof containedWidget === "undefined") {
                containedWidget = dom.byId(this.containedWidgetId);
            }
            if (typeof containedWidget.set === "function"
                    && containedWidget.attr("displayedValue") !== null) {
                containedWidget.set("value", this.defaultValue);
            }
            if (typeof containedWidget.set === "function"
                    && containedWidget.attr("displayedValue") === null) {
                containedWidget.set("value", this.defaultValue);
            }
            if (typeof containedWidget.onChange !== "function") {
                domAttr.set(containedWidget, "value", this.defaultValue);
                if ("createEvent" in document) {
                    var evt = document.createEvent("HTMLEvents");
                    evt.initEvent("change", false, true);
                    containedWidget.dispatchEvent(evt);
                } else {
                    containedWidget.fireEvent("onchange");
                }
            }
        }
    });

});

基本上,HTML和Javascript的这种组合只是一个dijit/TitlePane,还有一些额外的javascript

  1. 自动设置窗格标题;
  2. 如果底层元素有下拉列表,则自动打开和关闭它;
  3. 自动将焦点设置为包含的元素。
  4. 像这样使用:

    <div data-dojo-type="js/widgets/ExpandableSearchComponent" id="machineSearchView.operatingSystemExpandableSearch"
        data-dojo-props="prefixTitle: '<s:property value="%{getText('label.machine.operatingSystem')}"/>: ', containedWidgetId: 'machineSearchView.operatingSystem', defaultValue: '-1'">
        <div data-dojo-type="dojo/store/Memory"
            data-dojo-id="operatingSystemStore"
            data-dojo-props="<s:property value='%{getOperatingSystemTypeCodeJsonString()}'/>"></div>
        <s:set name="operatingSystem" value="machineSearchView.operatingSystem"
            scope="request"></s:set>
        <div data-dojo-type="dijit/form/Select" class="readOnlySelect"
            data-dojo-props="store:operatingSystemStore, labelAttr: 'label', sortByLabel: false, value:'${operatingSystem}'"
            name="machineSearchView.operatingSystem" id="machineSearchView.operatingSystem"></div>
    </div>
    

    当我打开它时,它看起来像这样:

    enter image description here

    如您所见,dijit/form/Select打开SelectMenu组件上的TitlePane而不是Select div本身。你可以只看到SelectMenu旁边的选择窥视。

    作为我喜欢看的例子:

    enter image description here

    containedWidget._aroundNode = containedWidget.focusNode;试图让它基于https://davidwalsh.name/dijit-dropdowns,但它没有帮助。我不确定我还能尝试什么。我已经尝试过深入调试Dojo组件内部的bin,但无济于事?

    我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

TitlePane在打开时播放动画。在&#34;显示&#34;打开选择下拉菜单事件太早,TitlePane容器还没有准备好。您需要等待动画完成。 TitlePane中的内部开放动画对象是_wipeIn,您可以在其onEnd()函数之后添加一个方面。

&#13;
&#13;
require([
  "dijit/TitlePane",
  "dijit/form/Select",
  "dojo/data/ObjectStore",
  "dojo/store/Memory",
  "dojo/on",
  "dojo/aspect",
  "dojo/domReady!"
], function(TitlePane, Select, ObjectStore, Memory, on, aspect) {

  var store = new Memory({
    data: [
      { id: "foo", label: "Foo" },
      { id: "bar", label: "Bar" }
    ]
  });

  var os = new ObjectStore({ objectStore: store });

  var s = new Select({store: os});
  s.startup();
  
  var tp = new TitlePane({title:"I'm a TitlePane", content: s, open: false});
  tp.placeAt("content");
  tp.startup();
  
  /*
  // This does not work:
  on(tp, "Show", function() {
    s.loadAndOpenDropDown();
  });
  */
  
  // This works:
  aspect.after(tp._wipeIn, "onEnd", function() {
      s.loadAndOpenDropDown();
  });
  
  on(tp, "Hide", function() {
      s.closeDropDown();
  });
});
&#13;
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/resources/dojo.css"> 
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dijit/themes/claro/claro.css">

<div class="claro">
  <div id="content"></div>
</div>
&#13;
&#13;
&#13;