2
votes

I have a CKEDITOR plugin that I'm having trouble disabling when there is no selected copy in the editor. Right now, the user can click the button without any highlighted text in the editor. I would like to modify it so that the plugin button is only active when there is copy highlighted in the editor. I've followed the suggestion here, but it isn't working.

Main Plugin Code:

CKEDITOR.plugins.add('cta', {
    icons: 'cta',
    init: function (editor) {

        // Funciton depending on editor selection (taken from the scope) will set the state of our command.
        function RefreshState() {
            console.log('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.
                console.log("editable not ready yet");
                return;
            }

            // We assume only one range.
            range = editable.getDocument().getSelection().getRanges()[0];
            console.log(`range: `);
            console.log(range);

            // The state we're about to set for the command.
            commandState = (range && !range.collapsed) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;

            console.log('commandState');
            console.log(commandState);
            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();
        });



        editor.addCommand('ctabtn', new CKEDITOR.dialogCommand('ctaDialog'));
        editor.ui.addButton('cta', {
            label: 'Insert Call to Action button',
            command: 'ctabtn',
            toolbar: 'insert'
        });

        CKEDITOR.dialog.add('ctaDialog', this.path + 'dialogs/cta.js');
    }
});

My dialog code is here:

CKEDITOR.dialog.add('ctaDialog', function (editor) {
	return {

		// Basic properties of the dialog window: title, minimum size.
		title: 'Call to Action',
		minWidth: 400,
		minHeight: 200,

		// Dialog window content definition.
		contents: [{
			// Definition of the Basic Settings dialog tab (page).
			id: 'tab-basic',
			label: 'Basic Settings',

			// The tab content.
			elements: [{
					// Text input field for the Call to Action text.
					type: 'text',
					id: 'cta',
					label: 'Call to Action',
					// Validation checking whether the field is not empty.
					validate: CKEDITOR.dialog.validate.notEmpty("Call to Action field cannot be empty.")
				},
				{
					// Text input field for the link text.
					type: 'text',
					id: 'url',
					label: 'URL',
					// Validation checking whether the field is not empty.
					validate: CKEDITOR.dialog.validate.notEmpty("URL field cannot be empty.")
				}
			]
		}],

		// method invoked when the dialog button is clicked
		onShow: function () {
			var element = editor.getSelection();

			var link = CKEDITOR.plugins.link;			
			var _this = this.getParentEditor();
			var CTAhref = link.getSelectedLink(_this);

			this.setValueOf('tab-basic', 'cta', element.getSelectedText().toString());
			
			if (CTAhref != '' && CTAhref !== null) {
				this.setValueOf('tab-basic', 'url', CTAhref.$.href);
			}
		},

		// This method is invoked once a user clicks the OK button, confirming the dialog.
		onOk: function () {
			var dialog = this;
			var CTA = editor.document.createElement('a');
			CTA.setAttribute('href', dialog.getValueOf('tab-basic', 'url'));
			CTA.setAttribute('class', 'btn btn-special--lg');
			CTA.setText(dialog.getValueOf('tab-basic', 'cta'));
			editor.insertElement(CTA);
		}
	};
});

Any ideas on why the plugin icon button on the toolbar doesn't become inactive when there is no copy highlighted in the editor? I can see in the console that CKEDITOR.dom.range.collapsed is toggling between TRUE/FALSE depending upon whether text is highlighted or not. It's just not disabling the button.

1

1 Answers

1
votes

As stated, the suggested way of handling this was not working for me. What was working was using range.collapsed in returning a true value if a selection was made in the editor. With that, I turned to using Jquery to handle the rest.

// Hacky. But it gets the job done.
// a.cke_button.cke_button__cta.cke_button_off is the selector for my toolbar button.
// The onclick function listed was pulled from looking at the CKeditor functions
// to initiate my plugins modal.
// The setting of the "onclick" prop to null is needed to override the modal onclick
// binding when there is no selection.

range = editable.getDocument().getSelection().getRanges()[0];

if (range.collapsed === false) {
  $('a.cke_button.cke_button__cta.cke_button_off').attr("onclick", 'CKEDITOR.tools.callFunction(83,this);return false;');
  $('a.cke_button__cta').toggleClass('cta_button_disabled');
} else {
  $('a.cke_button.cke_button__cta.cke_button_off').prop("onclick", null);
}