可以dojo访问与HTML元素事件关联的功能吗?

时间:2009-10-26 20:08:20

标签: javascript dojo

当屏幕处于“编辑”模式时,我想过度使用与元素onclick事件相关的功能。然后在完成编辑后将原始功能恢复原状。

所以,最初我有以下内容:

<script type="text/javascript">
    var showAddNewForum = function(){
        dojo.byId("NewForum").className = dojo.byId("NewForum").className == 'hidden'?'':'hidden';
    }
</script>
<a  onclick="showAddNewForum()" class="editable" id="AddNewForum" name="AddNewForum" style="cursor:pointer;">New Forum</a>
        <div class="hidden" id="NewForum" name="NewForum">
            <form action="">
                <table>
                    <tr><td><label>Title</label></td><td><input type="text" id="newForumTitle"/></td></tr>
                    <tr><td><label>Description</label></td><td><input type="text" id="newForumDescription"/></td></tr>
                    <tr><td><label>Moderators</label></td><td><input type="text" id="newForumnModerators"/></td></tr>
                </table>
                <input type="button" value="submit"/>
            </form>
        </div>

在页面顶部有一个Admin按钮,可以将页面置于配置模式。具有可编辑类的所有元素将处于配置模式,因此可以通过一个小形式配置元素。这个想法是屏幕上的某些控件将根据用户角色具有不同的行为。示例:如果管理员另外显示,则不显示控件。

这是通过以下方式完成的:

    activateAdministration = function() {
        if (editOnClickHandle.length>0) {
            dojo.forEach(editOnClickHandle,function(item){dojo.disconnect(item)});
            editOnClickHandle = [];
        }else {
            dojo.query(".editable").forEach(function(node,idx,arr){
                var handler = dojo.connect(node,"onclick",function(e){
                    console.debug(node.onclick);
                    var adminWindow = document.getElementById("adminWindow");
                    adminWindow.className = "displayInline";
                    adminWindow.style.top = (e.layerY + 0) + "px";
                    adminWindow.style.left = (e.layerX + 0) + "px";
                    document.getElementById("adminElementId").value = node.id;
                    document.getElementById("adminCurrentUrl").value = location.href;
                    document.getElementById("adminClass").value = node.className;
                });
                editOnClickHandle.push(handler);
            });
        }
    }
<a class="tool" style="cursor:pointer;" onclick="activateAdministration();">Admin</a>

所以问题是原始的onclick函数仍然附加到事件中。如果它是一个提交函数或类似的东西,那么它也会触发不需要的东西。

我可以为原始函数设置处理程序,将其解除连接,添加新函数,然后在完成编辑后删除新函数并添加原始函数吗?

感谢您的任何提示,我希望问题很明确(可能不是)很乐意在需要时添加更多信息。

3 个答案:

答案 0 :(得分:2)

您是否控制showAddNewForum()函数的代码及其插入HTML?在这种情况下,我可能只使用一个处理程序,如:

dojo.connect(dojo.byId("AddNewForum"), "onclick", function(evt) {
    if (dojo.hasClass(evt.target, "editable") {
        //do the editing work here
        doConfiguration(evt.target);
    } else {
        //do regular work here.
        doRegularAction(evt.target);
    }
});

当您将页面更改为配置模式时,或者按住连接句柄并取消注册并注册正确的句柄。

答案 1 :(得分:1)

我实现这一点的方法是总是覆盖页面上每个可编辑对象的onclick处理程序,其处理程序可以简单地将调用委托给原始程序或称为管理程序版本。

你可以在dojo中轻松地连接它,如下所示:

  admin_mode = false;
  activateAdministration = function() {
    admin_mode = true;
  };

  editClick = function(e) {
    console.debug("..in admin edit function; this=%o; e=%o", this, e);
    // do your admin stuff here
    // var node = this;
  };

  dojo.query('.editable').forEach(function(node) {

    if (node.onclick) {
      var original_onclick = node.onclick;
      node.onclick = function() {
        if (admin_mode) {
          console.debug("calling admin onclick handler");
          editClick.apply(node, arguments);
        } else {
          // delegate
          console.debug("calling original onclick handler");
          original_onclick.apply(node, arguments);
        }
      }
    }

  });

我用这样的HTML测试了它:

<a onclick="console.debug('I am the original!; this=%o; args=%o', this, arguments);" 
   class="editable"> 
  EDITABLE 
</a>

<a onclick="console.debug('Me too!; this=%o; args=%o', this, arguments);" 
   class="editable"> 
  ALSO EDITABLE 
</a>

答案 2 :(得分:0)

首先让我说我恨IE,尤其是IE6。当我的公司最终离开IE6时,这将是一个美好的一天。所以我如何解决这个问题是我将一个名为oldclick的属性设置为node.onclick,然后在激活管理时设置node.onclick =“”。另一方面,我断开了hadlers并将oldclick添加回onclick。

var editOnClickHandle = []; 
activateAdministration = function() {
        if (editOnClickHandle.length>0) {//turn off administration
            dojo.forEach(editOnClickHandle,function(item){dojo.disconnect(item)});
            dojo.query(".editable").forEach(function(node,idx,arr){
                if(dojo.isIE){
                    node.onclick=node.getAttribute("oldclick");
                }else{
                    node.onclick=dojo.hitch(node.onclick,node.getAttribute("oldclick"));
                }               
            });
            editOnClickHandle = [];
        }else {//turn on administration
            dojo.query(".editable").forEach(function(node,idx,arr){
                var onClickName = new String(node.getAttribute("onclick"));
                var oldClickName = onClickName.substring(0,onClickName.indexOf("("));
                if(dojo.isIE){
                    node.setAttribute("oldclick",node.onclick);
                }else{
                    node.setAttribute("oldclick",oldClickName);
                }
                node.onclick="";
                editOnClickHandle.push(dojo.connect(node,"onclick",editClick));
            });
        }
    }

与此问题无关,但为了清楚起见,我将小管理窗口代码重构为一个名为editClick的分隔函数。它看起来像:

editClick = function(e){
    console.debug(e);
    var adminWindow = document.getElementById("adminWindow");
    adminWindow.className = "displayInline";
    adminWindow.style.top = (e.layerY + 0) + "px";
    adminWindow.style.left = (e.layerX + 0) + "px";
    document.getElementById("adminElementId").value = e.target.id;
    document.getElementById("adminCurrentUrl").value = location.href;
    document.getElementById("adminClass").value = e.target.className;
}

所以希望这将有助于将来的某些人,感谢您对jrburke的帮助。如果有人想挑选我的解决方案,我就是建设性的投入游戏。