有没有办法停止dojo onBlur事件处理程序中的所有其他事件?

ndh0cuux  于 2022-12-16  发布在  Dojo
关注(0)|答案(2)|浏览(227)

也许我走错了路...

**设置:**我有一个相当复杂的完全文档化的Web应用程序,这个问题的重要部分是在dijit.layout.BorderContainer的中心区域有一个较长的表单,在其他区域有一个导航树和一些操作按钮。
**我想做的:**如果用户确实输入了数据并且没有保存,那么当他要离开表单时(如果他离开,点击“new Element”按钮,...),他们应该会收到一条警告消息。为了更好的用户体验,我想给予一个模态对话框,其中包含选项“save”、“leave anyway”、“cancel”。我的想法是使用表单的onBlur事件,停止所有其他事件(很可能是其他小部件上的onClick),检查更改,如果有更改,显示对话框,否则让其他事件继续。我不想为所有非表单活动元素添加checkChanges方法!

在第一次测试中,我只是试图阻止事件发生...

这很管用

<div id="formArea" dojoType="dijit.form.Form" encoding="multipart/form-data" action=""  class="ContentPane" region="center">
   <script type="dojo/connect" event="onBlur" >
      alert("I don't think so");
    </script>
 </div>

......但它很丑陋,我不能轻易地继续

这不

<div id="formArea" dojoType="dijit.form.Form" encoding="multipart/form-data" action=""  class="ContentPane" region="center">
   <script type="dojo/connect" event="onBlur" args="e">
      console.log("blur"); // ok
      e.preventDefault();//event.stopt(e)//return false //<--neither of these
    </script>
 </div>

问题是,如果我单击表单外的按钮,onBlur会触发,但我无法在按钮上停止onClick。我知道onBlur不提供事件对象-因此e.something实际上无法工作......是否有办法在其他元素上捕获onClick

wlsrxk51

wlsrxk511#

如果未保存数据,请暂停窗体onBlur中的按钮事件侦听器。
查看实际应用:http://jsfiddle.net/phusick/A5DHf/
您有一些按钮事件侦听器,请通过on.pausable(node, event, callback)而不是on()注册它们:

var b1Handler = on.pausable(button1Node, "click", function() {
    console.log("b1.onClick");        
});

var b2Handler = on.pausable(button2Node, "click", function() {
    console.log("b2.onClick");        
});

将处理程序聚集到数组中:

var handlersToPause = [b1Handler, b2Handler];

添加onBlur事件侦听器:

on(form, "blur", function(e) {

    if (this.isDirty()) {
        // if data are not saved, pause button event listeners
        handlersToPause.forEach(function(handler) {
            handler.pause();
        });
        // display modal dialog here     
    }            
});

例如,添加onFocus事件侦听器以恢复按钮事件侦听器:

on(form, "focus", function(e) {
    handlersToPause.forEach(function(handler) {
        handler.resume();            
    });
});

请注意,handler.pause()正在暂停onclick监听程序,而不是事件。onclick事件正在Event queue中等待,因此在onblur的执行时间内无法访问。
我会想出一些更健壮的解决方案,但这很快就回答了您的问题。无论如何,看看dojo/aspect和它的around建议调用您的 checkChanges,而不需要更改 * 所有非表单活动元素。

qxsslcnc

qxsslcnc2#

只有confirm('question?')会像那样“死锁”你页面的事件。
我做了一个类似的设置,但我来的方式(除非用户在地址栏中输入url并点击回车)是一个弹出的对话框,每当导航树被点击,发送用户到一个新的视图。

----------------------------------------
| Nav 1  |   Asset1 ( view controller )  |
| Nav 2  |   Asset2 ( hidden )           |
----------------------------------------

导航1是默认的加载视图,资产1已加载,包含“设置页面”表单或类似表单,并且可以更改。诀窍是,资产1和资产2是从AbstractAsset派生而来的,而AbstractAsset是一个简单的ContentPane扩展。
在AbstractAsset中有一个名为isDirty的“功能必须覆盖"函数

var Viewcontroller = declare("AbstractAsset", [dijit.ContentPane], {
       isDirty: function() { return false; }
});

declare("Asset1", [Viewcontroller], {

startup: function() {
  // sets up form
  ...
  // and references inputfields to 'this'
  this.inputfields = this.form.getChildren();

  // and saves (clones) the state of each field
  var self = this;
  this.inputfields.forEach(function(inputWidget) {
     self.states[inputWidget.id] = inputWidget.get("value");
  });
},
isDirty: function() {
  var self = this;
  var dirty = false;
  this.form.getChildren().some(input) {
     if(self.states[input.id] != input.get("value")) {
        dirty = true;
        return false; // breaks .some loop
     }
     return true;
  });
  return dirty;
}

})

接下来,每次导航点击都必须调用当前可见的视图控制器的isDirty函数才能继续。假设用户点击导航树(dijit.Tree)行节点 Nav 2

var navigation = dojo.declare("NavigationController", [dijit.Tree], {
 currentView : null,
 onLoad: function() {
   // start Asset1 in viewNode by default
   this.currentView = new Asset1({ }, this.viewNode); 
 },
 onClick : function() {
    if(this.currentView.isDirty()) alert("I Dont Think So");
    else {
       this.loadFunction(this.model.selection.getSelected());
    }
 }

});

这是实现on-unload-check的总体思路,您需要通过“主应用程序控制器”来挂钩任何onClick事件,以确定应该发生什么。Check this application(用作cms导航控制器)及其isDirty的page.js:587示例

相关问题