【发布时间】:2014-12-07 22:21:14
【问题描述】:
我正在开发一个用于注释文本和添加边距 cmets 的 CKEditor 插件,但我希望我的一些自定义工具栏按钮仅在用户已经选择了一定范围的文本时才启用。每当用户正在键入或光标位于单点(而不是范围)时,应禁用按钮(及其相关命令)。
我是一位非常有经验的插件作者,我花了相当多的时间在core API docs 中寻找,但我还没有找到任何看起来有帮助的东西。
【问题讨论】:
标签: ckeditor
我正在开发一个用于注释文本和添加边距 cmets 的 CKEditor 插件,但我希望我的一些自定义工具栏按钮仅在用户已经选择了一定范围的文本时才启用。每当用户正在键入或光标位于单点(而不是范围)时,应禁用按钮(及其相关命令)。
我是一位非常有经验的插件作者,我花了相当多的时间在core API docs 中寻找,但我还没有找到任何看起来有帮助的东西。
【问题讨论】:
标签: ckeditor
您的情况有点棘手,因为选择更改事件在浏览器中没有很好地实现,FF 是主要问题。
在您的情况下,您将需要非常频繁地检查选择更改,因为您对所有选择更改感兴趣,因此 CKEditor selectionChange 不适合它。
幸运的是,编辑器中有一个selectionCheck 事件,它的触发频率更高,并且是为 FF 实现的。
解决方案:
这里你有一个插件的init 方法,我已经模拟了它来解决你的问题。它将按照您解释的方式禁用/启用 Source 按钮。
我已经为这个功能添加了节流功能,让机器不太大的客户可以欣赏你的功能:)
init: function( editor ) {
// Funciton depending on editor selection (taken from the scope) will set the state of our command.
function RefreshState() {
var editable = editor.editable(),
// Command that we want to control.
command = editor.getCommand( 'source' ),
range,
commandState;
if ( !editable ) {
// It might be a case that editable is not yet ready.
return;
}
// We assume only one range.
range = editable.getDocument().getSelection().getRanges()[ 0 ];
// The state we're about to set for the command.
commandState = ( range && !range.collapsed ) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;
command.setState( commandState );
}
// We'll use throttled function calls, because this event can be fired very, very frequently.
var throttledFunction = CKEDITOR.tools.eventsBuffer( 250, RefreshState );
// Now this is the event that detects all the selection changes.
editor.on( 'selectionCheck', throttledFunction.input );
// You'll most likely also want to execute this function as soon as editor is ready.
editor.on( 'instanceReady', function( evt ) {
// Also do state refresh on instanceReady.
RefreshState();
} );
}
【讨论】:
如果您正在开发一个插件,我猜您正在向 ckeditor 注册 commands。
在这种情况下,您应该提供一个refresh 方法,CKEditor 会在需要时调用该方法来更新按钮的状态:
由命令定义,确定命令的函数 状态。当编辑器有状态或选择时将调用它 改变了。
您可以在 CKEditor 团队开发的几个插件中看到实现示例。这是来自the source code of the Link plugin的一张:
refresh: function( editor, path ) {
var element = path.lastElement && path.lastElement.getAscendant( 'a', true );
if ( element && element.getName() == 'a' && element.getAttribute( 'href' ) && element.getChildCount() )
this.setState( CKEDITOR.TRISTATE_OFF );
else
this.setState( CKEDITOR.TRISTATE_DISABLED );
}
【讨论】:
这是使用 Gyum Fox 建议的 refresh 方法准确回答问题所需的代码。
我提到要让它工作,contextSensitive 必须设置为 1。
editor.addCommand( 'myCommand', {
exec: function( editor ) {
// Custom logic of the command
},
refresh: function( editor ) {
var editable = editor.editable();
range = editable.getDocument().getSelection().getRanges()[ 0 ]; // We assume only one range.
commandState = ( range && !range.collapsed ) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;
this.setState( commandState );
},
contextSensitive: 1
});
编辑:我注意到我这边有一些刷新问题。所以,正因为如此,我会选择 Marek Lewandowski 的答案。
【讨论】: