阻止 x-tags 捕获焦点/模糊事件 [英] Stop x-tags from capturing focus/blur events

查看:22
本文介绍了阻止 x-tags 捕获焦点/模糊事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个包含 tinyMCE 功能的自定义元素.

I am trying to create a custom element which wraps tinyMCE functionality.

我有以下内容:-

(function(xtag) {
    xtag.register('x-tinymce', {
        lifecycle:{
            created: tinymceCreate,
            removed: tinymceDestroy
        },
        accessors: {
            disabled: {
                attribute: {
                    boolean: true
                },
                get: getDisabledAttribute,
                set: setDisabledAttribute
            }
        }
    });    
    function tinymceCreate(){
        var textarea = document.createElement('textarea');
        var currentElement = this;
        currentElement.textAreaId = xtag.uid();
        textarea.id = currentElement.textAreaId;
        currentElement.appendChild(textarea);
        currentElement.currentMode = 'design';
        var complexConfig = {
             selector: '#' + currentElement.textAreaId,
             setup: editorSetup
        }
        tinymce.init(complexConfig)
               .then(function thenRetrieveEditor(editors) {
                    currentElement.currentEditor = editors[0];
                    currentElement.currentEditor.setMode(currentElement.currentMode ? currentElement.currentMode :  'design');
        });    
        function editorSetup(editor) {
            editor.on('blur', function blur(event) {
                editor.save();
                document.getElementById(editor.id).blur();
                xtag.fireEvent(currentElement, 'blur', { detail: event, bubbles: false, cancellable: true });
            });
            editor.on('focus', function focus(event) {
                xtag.fireEvent(currentElement, 'focus', { detail: event, bubbles: false, cancellable: true });
            });
            editor.on('BeforeSetContent', function beforeSetContent(ed) {
                if (ed.content) 
                    ed.content = ed.content.replace(/\t/ig, '    ');
            });
        }
    }

    function tinymceDestroy() {
        if (this.currentEditor)
            tinymce.remove(this.currentEditor);
    }

    function getDisabledAttribute() {
        return this.currentMode === 'readonly';
    }

    function setDisabledAttribute(value) {
        if (value) {
            this.currentMode = 'readonly';
        }
        else {
            this.currentMode = 'design';
        }
        if (this.currentEditor) {
            this.currentEditor.setMode(this.currentMode);
        }
    }
})(xtag);

现在,当我注册一个模糊事件时,它会被调用,但焦点事件也会被调用.我认为这是因为默认情况下 x-tag 捕获焦点/模糊事件.我不希望它这样做.相反,我希望在用户聚焦/模糊 tinymce 时触发这些事件.

Now, when I register a blur event, it does get called, but so does the focus event. I think that this is because focus/blur events are captured by x-tag by default. I don't want it to do that. Instead, I want these events fired when the user focusses/blurs tinymce.

我使用的是 xtags 1.5.11 和 tinymce 4.4.3.

I am using xtags 1.5.11 and tinymce 4.4.3.

更新 1

好的,问题是当我打电话时:-

OK, the problem is when I call:-

xtag.fireEvent(currentElement, 'focus', { detail: event, bubbles: false, cancellable: true });

这导致焦点在编辑器上丢失并转到包含元素(x-tinymce).为了解决这个问题,我修改了我的 editorSetup 看起来像这样:-

This caused the focus to be lost on the editor and go to the containing eleemnt (x-tinymce). To counter this, I modified my editorSetup to look like this:-

   function editorSetup(editor) {
        // // Backspace is not detected in keypress, so need to include keyup event as well.
        // editor.on('keypress change keyup focus', function(ed) {
        //     $j("#" + editor.id).trigger(ed.type);
        // });
        var isFocusFromEditor = false;
        var isBlurFromEditor = false;
        editor.on('blur', function blurEvent(event) {
            console.log("blurred editor");
            if (!isFocusFromEditor) {
                editor.save();
                xtag.fireEvent(currentElement, 'blur', { detail: event, bubbles: false, cancellable: false });
            }
            else {
                console.log('refocussing');
                isFocusFromEditor = false;
                editor.focus();
                isBlurFromEditor = true;
            }

        });
        editor.on('focus', function focusEvent(event) {
            console.log("Focus triggered");
            isFocusFromEditor = true;
            xtag.fireEvent(currentElement, 'focus', { detail: event, bubbles: false, cancellable: false });
        });
        editor.on('BeforeSetContent', function beforeSetContent(ed) {
            if (ed.content) {
                ed.content = ed.content.replace(/\t/ig, '    ');
            }
        });
    }

这会阻止触发模糊事件,不幸的是,现在,当您离开编辑区域时不会调用模糊事件.

This stops the blur event from triggering, unfortuantely, now, the blur event does not get called when you leave the editing area.

这感觉像是一个微小的MCE问题,只是不确定是什么.

This feels like a tinyMCE problem, just not sure what.

推荐答案

这是一个在自定义元素级别捕获 focusblur 事件的解决方案.

Here is a solution that catches focus and blur events at the custom element level.

它使用 event.stopImmediatePropagation() 方法在需要时停止将 blur 事件传输到其他(外部)事件侦听器.

It uses the event.stopImmediatePropagation() method to stop the transmission of the blur event to other (external) event listeners when needed.

此外,它使用 2 个隐藏的 (#FI#FO)控件来捕捉焦点tab 键被按下.

Also, it uses 2 hidden <input> (#FI and #FO) controls in order to catch the focus when the tab key is pressed.

document.registerElement('x-tinymce', {
  prototype: Object.create(HTMLElement.prototype, {
    createdCallback: {
      value: function() {
        var textarea = this.querySelector('textarea')
        var output = this.querySelector('output')
        output.textContent = "state"
        var self = this
        self.textAreaId = this.dataset.id // xtag.uid();
        textarea.id = self.textAreaId
        var complexConfig = {
          selector: '#' + self.textAreaId,
          setup: editorSetup,
        }

        var FI = this.querySelector('#FI')
        FI.addEventListener('focus', function(ev) {
          if (ev.relatedTarget) {
            var ev = new FocusEvent('focus')
            self.dispatchEvent(ev)
          } else {
            var ev = new FocusEvent('blur')
            self.dispatchEvent(ev)
            focusNextElement(-1)
          }
        })

        var FO = this.querySelector('#FO')
        FO.addEventListener('focus', function(ev) {
          if (!ev.relatedTarget) {
            var ev = new FocusEvent('blur')
            self.dispatchEvent(ev)
            focusNextElement(1)
          } else {
            var ev = new FocusEvent('focus')
            self.dispatchEvent(ev)
          }
        })


        var focused = false

        this.addEventListener('focus', function(ev) {
          console.log('{focus} in ', this.localName)
          if (!focused) {
            focused = true
            output.textContent = focused
            self.editor.focus()								
          } else {
            console.error('should not be here')
            ev.stopImmediatePropagation()
          }
        })

        this.addEventListener('blur', function(ev) {
          console.log('{blur} in %s', this.localName)
          if (focused) {
            focused = false
            output.textContent = focused
          } else {
            console.log('=> cancel blur')
            ev.stopImmediatePropagation()
          }
        })

        tinymce.init(complexConfig).then(function(editors) {
          //self.currentEditor = editors[0]
        })

        //private 

        function focusNextElement(diff) {
          //add all elements we want to include in our selection
          var focussableElements = 'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])'
          if (document.activeElement) {
            var focussable = Array.prototype.filter.call(document.querySelectorAll(focussableElements), function(element) {
              //check for visibility while always include the current activeElement 
              return element.offsetWidth > 0 || element.offsetHeight > 0 || element === document.activeElement
            })
            var index = focussable.indexOf(document.activeElement)
            focussable[index + diff].focus()
          }
        }

        function editorSetup(editor) {
          console.warn('editor setup')
          self.editor = editor

          editor.on('focus', function(event) {
            if (!focused) {
              var ev = new FocusEvent('focus')
              self.dispatchEvent(ev)
            }
          })

          editor.on('blur', function(event) {
              //if ( focused ) 
              {
                var ev = new FocusEvent('blur')
                self.dispatchEvent(ev)
              }
          })
        }
      }
    },
    detachedCallback: {
      value: function() {
        if (this.editor)
          tinymce.remove(this.editor)
      }
    }
  })
})

var xElem = document.querySelector('x-tinymce')
xElem.addEventListener('focus', function(ev) {
  console.info('focus!')
})
xElem.addEventListener('blur', function(ev) {
  console.info('blur!')
})

<script src="http://cdn.tinymce.com/4/tinymce.min.js"></script>
<input type="text">
<x-tinymce data-id="foo">
  <output id=output></output>
  <input type=text id=FI style='width:0;height:0;border:none'>
  <textarea>content</textarea>
  <input type=text id=FO style='width:0;height:0;border:none'>
</x-tinymce>
<input type="text">

这篇关于阻止 x-tags 捕获焦点/模糊事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆