javascript - 穆工具 |打开/关闭弹出菜单和外部单击事件

标签 javascript events mootools

我正在使用 mootools 并处理弹出菜单:

document.getElement('.cart a').toggle(
  function() {
   this.getParent('div').removeClass('open');
   this.getNext('.cart_contents').hide();               
  },
  function() {
    this.getParent('div').addClass('open');
    this.getNext('.cart_contents').show();
  })
);

切换功能实现:

Element.implement({
    toggle: function(fn1,fn2){
        this.store('toggled',false);
        return this.addEvent('click',function(event){
            event.stop();
             if(this.retrieve('toggled')){
                 fn1.call(this);
             }else{
                 fn2.call(this);
             }
            this.store('toggled',!(this.retrieve('toggled')));
        });
    }
});

外部点击函数:

Element.Events.outerClick = {
    base : 'click',    
    condition : function(event){
        event.stopPropagation();
        return false;
    },
    onAdd : function(fn){
        this.getDocument().addEvent('click', fn);
    },
    onRemove : function(fn){
        this.getDocument().removeEvent('click', fn);
    }
};

我想添加outerclick事件来关闭我的弹出菜单:

document.getElement('.cart a').toggle(
      function() {
       this.getParent('div').removeClass('open');
       this.getNext('.cart_contents').hide();               
      },
      function() {
        this.getParent('div').addClass('open');
        this.getNext('.cart_contents').show();
      }).addEvent('outerClick',function() {
        // Error: Wrong code below 
        // Uncaught TypeError: Object #<HTMLDocument> has no method 'getParent' 
        this.getParent('div').removeClass('open');
        this.getNext('.cart_contents').hide();  
});

错误:未捕获类型错误:对象#没有方法“getParent” 谢谢。

最佳答案

这是一个与 Darren 的 outerClick 实现有关的问题(或缺陷)。这不是一个错误——它是为了尽可能快地工作而构建的。您只需要了解它将实际事件绑定(bind)到 document 时它会做什么。

Element.Events.outerClick = {
    base : 'click',    
    condition : function(event){
        event.stopPropagation();
        return false;
    },
    onAdd : function(fn){
        // the event actually gets added to document!
        // hence scope in fn will be document as delegator.
        this.getDocument().addEvent('click', fn);
    },
    onRemove : function(fn){
        this.getDocument().removeEvent('click', fn);
    }
};

因此函数将在上下文 this === document 下运行。

解决此问题的一种方法是将回调专门绑定(bind)到元素。问题是,删除它不起作用,因为 .bind 将返回一个独特的新函数,该函数不会再次与同一函数匹配。

(function(){
    var Element = this.Element,
        Elements = this.Elements;

    [Element, Elements].invoke('implement', {
        toggle: function(){
            var args = Array.prototype.slice.call(arguments), 
                count = args.length-1,
                // start at 0
                index = 0;

            return this.addEvent('click', function(){
                var fn = args[index];
                typeof fn === 'function' && fn.apply(this, arguments);
                // loop args.
                index = count > index ? index+1 : 0;
            });
        }
    });

    Element.Events.outerClick = {
        base : 'click',    
        condition : function(event){
            event.stopPropagation();
            return false;
        },
        onAdd : function(fn){
            this.getDocument().addEvent('click', fn.bind(this));
        },
        onRemove : function(fn){
            // WARNING: fn.bind(this) !== fn.bind(this) so the following
            // will not work. you need to keep track of bound fns or 
            // do it upstream before you add the event.
            this.getDocument().removeEvent('click', fn.bind(this));
        }
    };
}());

document.id('myp').toggle(
    function(e){
        console.log(e); // event.
        this.set('html', 'new text');
    },
    function(){
        console.log(this); // element
        this.set('html', 'old text');
    },
    function(){
        this.set("html", "function 3!");
    }
).addEvent('outerClick', function(e){
     console.log(this, e); 
});

http://jsfiddle.net/dimitar/UZRx5/ - 这现在可以工作 - 取决于你是否有一个析构函数来删除它。

另一种方法是添加事件来执行此操作:

var el = document.getElement('.cart a');
el.addEvent('outerClick', function(){ el.getParent(); // etc });
// or bind it 
el.addEvent('outerClick', function(){ this.getParent(); }.bind(el));

如果您保存引用,则可以将其删除

var el = document.getElement('.cart a'),
    bound = function(){
        this.getParent('div');
    }.bind(el);

el.addEvent('outerClick', bound);

// later
el.removeEvent('outerClick', bound);

就是这样。另一种 outerClick 在这里:https://github.com/yearofmoo/MooTools-Event.outerClick/blob/master/Source/Event.outerClick.js - 没有尝试过,但看起来它试图通过更改元素的范围并保留内存函数的引用来做正确的事情 - 尽管多个事件可能会导致问题,但需要事件 ID 来识别要删除的精确函数。另外,它看起来相当沉重 - 考虑到该事件是在文档中的,您不想在每次点击时执行太多逻辑。

关于javascript - 穆工具 |打开/关闭弹出菜单和外部单击事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22449501/

相关文章:

javascript - 与条件 promise 链使用react并在发送调度之前等待它们全部

由 <a> 引起的 javascript:history.back(-1) 问题

javascript - 通过在弹出窗口外单击来隐藏弹出窗口

powershell - 任务计划未执行可通过任务计划程序(Windows10)手动运行的Powershell脚本

javascript - mootools javascript 递归返回 Array.each()

Javascript 未捕获引用错误 : Class is not defined

javascript - 在 jQuery 中单击自身内的元素时删除动态生成的元素?

javascript - 在 Javascript 中获取放置事件的坐标?

php - magento 2 Catalog_product_save_before 无法保存产品但不断加载

mootools - HTML - MOOTOOLS - 在 ie6 中添加选择框选项