Enable CKEditor toolbar button only with valid text selection?

江枫思渺然 提交于 2020-01-11 10:32:51

问题


I'm working on a CKEditor plugin for annotating text and adding margin comments, but I'd like some of my custom toolbar buttons to be enabled only when the user has already selected a range of text. Whenever the user is typing, or the cursor is at a single-point (instead of a range), the buttons (and their associated commands) should be disabled.

I'm a pretty experienced plugin author, and I've spent a fair amount of time hunting through the core API docs, but I haven't found anything yet that looks like it'll help.


回答1:


Your case is a little tricky, because selection change event is not well implemented across browsers, FF is the main problem.

In your case you'll going to need check selection changes very frequently, as you're interested in all selection changes therefore CKEditor selectionChange won't fit it.

Fortunately there's a selectionCheck event in editor that fires much more frequently and is implemented for FF.

Solution:

Here you have init method of a plugin that I've mocked to solve your problem. It will disable / enable Source button the way you explained.

I've already added throttling to this function, so that customers with less expansive machine can admire your feature :)

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();
    } );
}



回答2:


If you are working on a plugin, I guess that you are registering commands with the ckeditor.

In that case, you should provide a refresh method, which will be called by the CKEditor to update the state of the button when needed:

Defined by the command definition, a function to determine the command state. It will be invoked when the editor has its states or selection changed.

You can see examples of implementation in several of the plugins developed by the CKEditor team. Here is one taken from 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 );
}



回答3:


Here is the code required to answer exactly the question using the refresh method as suggested by Gyum Fox.
I mention that to make it work, contextSensitive has to be set to 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
});

EDIT: I noticed some refresh issues on my side. So, because of that, I'd go for the Marek Lewandowski answer.



来源:https://stackoverflow.com/questions/27348572/enable-ckeditor-toolbar-button-only-with-valid-text-selection

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!