【问题标题】:Stop x-tags from capturing focus/blur events阻止 x-tags 捕获焦点/模糊事件
【发布时间】:2016-10-09 01:58:38
【问题描述】:

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

我有以下几点:-

(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 时触发这些事件。

我正在使用 xtags 1.5.11 和 tinymce 4.4.3。

更新 1

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

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

这导致编辑器失去焦点并转到包含元素(x-tinymce)。为了解决这个问题,我将 editorSetup 修改为如下所示:-

   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, '    ');
            }
        });
    }

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

这感觉像是一个 tinyMCE 问题,只是不确定是什么。

【问题讨论】:

  • @Supersharp 感谢您提及格式问题。我希望 tinyMCE 像任何其他输入元素一样工作。所以我希望模糊和焦点能够像处理文本区域和输入一样。
  • 我看不出问题出在哪里。默认情况下,它的作用类似于普通控件。无需触发任何模糊或焦点事件。
  • @Supersharp 如果我用 x-tinymce 元素注册了一个模糊事件并且我离开了富文本区域,我永远不会调用模糊函数。使用我上面的代码,它工作正常。
  • 好的,我明白你想要什么!
  • @Supersharp 是的,抱歉,我应该包含捕获焦点和模糊的代码,并明确说明我看到/没有看到的内容。

标签: web-component tinymce-4 x-tag


【解决方案1】:

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

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

此外,它使用 2 个隐藏的 <input>#FI#FO)控件,以便在按下 tab 键时捕捉焦点。

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">

【讨论】:

    猜你喜欢
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    • 2014-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多