我正在尝试创建一个包含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 });
这导致焦点在编辑器上丢失并转到包含eleemnt(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, ' ');
}
});
}
这会停止触发模糊事件,但不幸的是,当您离开编辑区域时,不会调用模糊事件。
这感觉就像一个小小的MCE问题,只是不确定是什么。
答案 0 :(得分:0)
这是一个在自定义元素级别捕获focus
和blur
事件的解决方案。
它使用event.stopImmediatePropagation()
方法在需要时停止向其他(外部)事件侦听器传输blur
事件。
此外,它还使用了2个隐藏的<input>
(#FI
和#FO
)控件,以便在按下标签键时捕捉焦点。
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">