Question

I'm using Iris Colourpicker (http://automattic.github.io/Iris/) in my rich HTML editor to allow users to update the colour of text in a contenteditable paragraph.

The problem is that after the first "change" event is called, I lose the selection, and thus any subsequent colour changes aren't applied.

I tried to use Tim Down's awesome Rangy library to save the selection and restore it when the change event is fired. This works for the first time the event is called but fails each time after.

I have this function to save the selection before the colour picker is opened

// Saves current selection.  Colour picker widget is displayed after this is called.
jQuery(".tve_save_selection").on("mousedown", function(e) {
        window.textselection = rangy.saveSelection();
});

And this is how the Iris colour picker is initialised:

var text_colourpicker_options = {
    change: function (event, ui) {
        color = ui.color.toString();
        rangy.restoreSelection(window.textselection);
        var sel = rangy.getSelection();
        if (sel.toString().length) {
         document.execCommand('ForeColor', false, color);
        }
    },
    hide: true,
    palettes: window.tve_custom_colours,
};

There doesn't appear to be a "close" event for the colour picker so I can't apply the execCommand after the user has settled on a colour.

I think that I may need to generate a new range after the document.execCommand() function fires, but as the DOM has changed I don't know how to determine the new range of the selection.

Any help on this would be much appreciated!

Était-ce utile?

La solution

Judging by the description you give, I infer that the anonymous function assigned the the option change is called each time the user changes the color. If this is the case, then your code cannot work.

Why It Does Not Work

It cannot work because your code calls rangy.restoreSelection multiple times with the same saved selection whereas this function can be called only once with a saved selection. This can be ascertained from the documentation:

Restores the selection from an object previously returned by rangy.saveSelection(). It removes any hidden marker elements created by that method.

(Emphasis added.) The markers are what allows the save and restore methods to work so if they are removed, then subsequent calls cannot work. This can also be ascertained by looking at the code of restoreSelection, abbreviated here to what is relevant to this question:

function restoreSelection(savedSelection, preserveDirection) {
    if (!savedSelection.restored) {
        // ...
        // Actual work
        // ...
        savedSelection.restored = true;
    }
}

On first invocation savedSelection.restored will be false and the actual work of restoring the selection will be performed. On subsequent calls on the same selection, savedSelection.restored will be true and no work will be done.

Solution

Save the selection again after restoring it:

rangy.restoreSelection(window.textselection);
window.textselection = rangy.saveSelection();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top