【问题标题】:Create a dojo deferred to wait for user input创建一个延迟等待用户输入的道场
【发布时间】:2013-12-30 00:10:38
【问题描述】:

我正在考虑创建一个颜色选择器,以便从我的一个小部件中调用。用户单击一个按钮以调出颜色选择器并单击一种颜色,然后将其返回给调用小部件。

我想我需要创建一个延迟对象,它会以某种方式等到延迟解决。然后我可以将该颜色设置为调用小部件中的变量。不过,我很难把它包起来。

我的调用小部件有这样一个方法:

pickColor: function (e) {
    Event.stop(e);
    var colorPicker = new ColorWidget();
    colorPicker.getColor().then(function (value) {
        console.log(value);
    });
}

我的 ColorWidget 将是创建延迟对象的那个,对吗?

define([
    "dojo/_base/declare",
    "dijit/_WidgetBase",
    "dijit/_TemplatedMixin",
    "dojo/text!./templates/ColorWidget.html",
    "dojo/Deferred",
    "dojo/_base/Color",
    "dojo/dom-construct",
    "dojo/domReady!"],

function (declare, _WidgetBase, _TemplatedMixin, template, Deferred, Color, domConstruct) {

    return declare("ColorWidget", [_WidgetBase, _TemplatedMixin], {
        templateString: template,
        deferred: {},
        color: {},

        constructor: function () {
            this.deferred = new Deferred();
        },
        postCreate: function () {
            domConstruct.place(this.domNode, "color-picker-holder", "last");
        },
        pick: function (evt) {
            this.color = new Color(evt.srcElement.id);
            domConstruct.destroy(this.domNode);
            this.deferred.resolve(this.color);
        },
        getColor: function () {
            return this.deferred;
        }
    });
});

这只是我脑海中的一个想法,但这就是它的设计方式吗?我可能会在登录对话框中使用相同的想法,该对话框将停止初始化页​​面,直到成功验证。是这样吗?

编辑:我实际上走上了正轨。这行得通。

【问题讨论】:

  • 我无法想象您为什么要将“延迟”用于颜色选择器之类的东西。但这是一个有趣的问题。我猜你可能对这两个教程很熟悉:Getting started with DeferredsDojo deferreds and Promises
  • 是的,我看过那些。在用户选择一个小部件后,我很难想出一种更好的方法来调用小部件并从中获取值(到我的调用小部件中)。如果我立即调用 getColor() 并且它不是延迟的,它会立即返回 null。如果我离开了,一定要让我知道。感谢您的回复。
  • 为什么不让颜色选择器小部件发布一个“datePicked”事件?调用小部件可以订阅此事件(使用 dojo/on, on(colorpickerWidget, "datePicked", function(){}))并使用它的值(可以作为事件的参数传递)。
  • 这是一个更好的主意。我是 Dojo 的新手,所以我不熟悉它是如何发布/订阅的。在我走这条路之前,我做了谷歌“dojo observable”……没走多远。我去看看,谢谢。
  • 看起来他们的发布/订阅系统已被弃用,取而代之的是集中式“主题”中心。还是值得一看的。

标签: javascript dojo deferred


【解决方案1】:

虽然您说您已经回答了自己的问题,但我会用更好的解决方案来回答,因为我认为其他用户也可能会尝试使用 Deferred(这将是完全错误的)。

你想做的是……

1) 创建您的颜色选择器,使其成为表单元素。您只需要扩展一个有效的 dojo 表单元素。 (我选择为我的颜色选择器扩展 ValidationTextBox)。

2) 创建一个接受回调函数的自定义小部件。你可以重写 onChange 或者你可以有一个自定义的 _callback 方法。任何时候值改变(你可以使用观察者方法 .watch())你都会调用回调。

3) 您只需正常连接到 onChange 事件。


我创建了一个自定义 Dojo 小部件.. 看起来像这样:

颜色选择器

当您单击颜色选择器或文本框获得焦点时,会打开包含颜色选择器的下拉菜单。颜色选择器一旦更改,就会更新父小部件(即文本区域)。

您可以在下面看到相关的类。它分为几个文件...

ColorTextBox.js(扩展验证文本框)

_ColorPickerDropDown.js(只是一个创建颜色选择器的简单小部件)

代码

ColorTextBox.js

define([
    "dijit/form/ValidationTextBox",
    "dojo/_base/declare",
    "dojox/widget/ColorPicker",
    "dojo/text!./ColorTextBox.html",
    "dijit/_HasDropDown",
    "my/diskit/form/_ColorPickerDropDown",
    "dojo/_base/lang",
    "dojo/dom-style"

    ], function(ValidationTextBox, declare, ColorPicker, template,
        _HasDropDown, _ColorPickerDropDown, lang, domStyle ){
    return declare([ ValidationTextBox , _HasDropDown ], {
        templateString : template,
        regExp: "(?:[0-9a-fA-F]{3}){1,2}",

        baseClass: "diskitColorTextBox",
        postCreate : function(){

            this.connect(this.focusNode, "onclick", "openDropDown");
            this.watch( "value", lang.hitch( this, function(attr, oldVal, newVal){

                if(newVal === ""){
                    domStyle.set(this._buttonNode, "background", "transparent" );
                } else {
                    domStyle.set(this._buttonNode, "background", "#" + newVal );
                }
            }) );
            this.inherited( arguments );
        },
        openDropDown: function(/*Function*/ callback){

            if( this.dropDown ){
                this.dropDown.destroyRecursive();
            }
            var _changeMethod = function(){
                var hex = this.picker.get('value');
                if (hex.substring(0, 1) === '#') {
                    hex = hex.substring(1);
                    this.parent.set('value', hex);
                }
            };

            var lastHex = this.get('value');

            this.dropDown = new _ColorPickerDropDown({
                parent : this,
                value : "#" + lastHex,
                onCancel : lang.hitch( this.dropDown, function(){
                     this.parent.set('value', lastHex );
                }),
                onChange :lang.hitch( this.dropDown, _changeMethod ),
                onExecute : lang.hitch( this.dropDown, _changeMethod )
            });

            this.inherited(arguments);
        },
        closeDropDown: function() {
            this.inherited(arguments);
            if (this.dropDown) {
                this.dropDown.destroy();
                this.dropDown = null;
            }
        }



    });

});

Template String

<div class="itemCheckWrapper colorPicker">
    <fieldset>
        <div ><label>${label}</label></div>
        <div data-dojo-attach-point="_buttonNode" class="colorPreview"></div>
        <div class="dijitTextBox small dijit dijitReset dijitInline dijitLeft" id="widget_${id}" role="presentation">
            <div class="diskitInputPrefix" data-dojo-attach-point="verifiedNumberPrefixNode" >
                    #
            </div>
            <div class='dijitReset dijitValidationContainer'>
                <input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="&#935; " type="text" tabIndex="-1" readonly="readonly" role="presentation"        />
            </div>
            <div class="dijitReset dijitInputField dijitInputContainer">
                <input maxlength="6" class="dijitReset dijitInputInner" data-dojo-attach-point='_aroundNode,textbox,focusNode' autocomplete="off" ${!nameAttrSetting} type='${type}'/>
            </div>
        </div>
    </fieldset>

</div>

然后这就是扩展 dojox/widget/ColorPicker 的 ColorPicker...

ColorPickerDropDown.js

define([
    "dojo/_base/declare",
    "dojox/widget/ColorPicker",
    "dojo/text!./_ColorPickerDropDown.html",
    "my/diskit/_base/_DiskitMixin",
    "dojo/_base/lang"
    ], function( declare, ColorPicker, template, _DiskitMixin, lang ){
    return declare([ _DiskitMixin ], {
        templateString : template,
        baseClass: "diskitColorPickerDropDown",
        postCreate : function(){


            this.picker = new ColorPicker({
                animatePoint:false,
                showHsv: false,
                showRgb: false,
                webSafe:false,
                onChange :  lang.hitch( this, this.onChange )
            }, this._colorPickerNode);
            if(this.value.length === 7){
                this.picker.setColor( this.value.trim() );
            }
            this.inherited( arguments );
        },
        onCancel : function(){

        },
        onExecute : function(){

        }
    });

});

Template String

<div >
<div data-dojo-attach-point="_colorPickerNode"></div>
<div class='toolbar'>
    <a data-dojo-attach-event="onclick:onCancel" class='pull-right'>Cancel</a>
    <a data-dojo-attach-event="onclick:onExecute" class='btn btn-sm btn-default pull-right'>Select</a>
</div>
</div>

【讨论】:

  • 我已将答案更改为您的答案。虽然 observable 确实是公认的设计模式,但延迟对象并非完全错误。即使它没有等待异步调用,它仍然是一个等待解析的对象。无论如何,我喜欢你的小部件。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-25
相关资源
最近更新 更多