addOverlay removeOverlay and opaque

I have the following situation, I create two overlays with addOVerlay:

typoOverlay - is a spellchecker, highlighting typos with a red line underneath
urlOverlay - is for hyperlinks, highlighting hyperlinks as blue, and set with opaque:true

all is well, in the sense that hyperlinks are in blue without red lines underneath - they are not recognized as typo because urlOverlay was added after typoOverlay and with opaque:true

Now for my problem, I allow the user to choose ‘ignore all’ for a particular typo, in this case I add the typo to a dictionary detected by typoOverlay as ‘not a typo’. I then need to re-run typoOverlay on the entire text to remove any red lines from any such now-not-typos. Another example where I need to do this is if I have a button to toggle spellchecking for the document.

I do this with: { cm.removeOverlay(typoOverlay ); cm.addOVerlay(typoOverlay ); }

however after doing this, urlOverlay (hyperlinks) loose it’s opaqueness and show also as typos.

So it seems that opaqueness also depends on the order of overlays (which is not documented).

I can at this point remove and re-add urlOverlay which will solve it but breaks my code structure as it doesn’t allow me to separate the code for the two overlays which have nothing to do with each other.

Is there a way to preserve opaqueness regardless of overlay adding order ? otherwise is there a way to re-run typoOverlay over the entire document without removing and re-adding it ?

thx!

looking at the code I realized I can achieve redrawing of the overlays without removing and adding them by doing:

cm.setOption('maxHighlightLength', (--cm.options.maxHighlightLength) +1);

Changing maxHighlightLength calls resetModeState which issues cm.state.modeGen++ and regChange(cm) that reruns the overlays.This also updated the document only once as opposed to removing and adding which does it twice.

But of course this is unclear and ugly … so a better solution is needed.

Thx!

This patch adds an option priority to addOverlay, which allows you to control the order in which the overlays are applied, without removing and re-adding them all.

Thx for the help marijn,

I think the problem with this kind of solution is that it moves to responsibility for priorities to the addons themselves which creates a coupling between them. For example consider the interaction of the above spellcheck, hyperlink and the search addon overlays. I need the hyperlink overlay to sit after the spellcheck overlay but before the search overlay for opaqueness to work correctly, but how can I know the priority of the search add-on inside the hyperlink add-on ?

It is the external code that adds the addons to CM that should determine their order, of course I can pass the priority as a parameter from the external code to the addon constructor but this seems overly complicated.

I still don’t understand why you are resistant to adding a better way to re-run the modes/overlays than removing and adding them which to me seems not efficient, counter-intuitive and messes with their order. All that is needed is a way to do { cm.state.modeGen++; regChange(cm); }. This allows adding the addons in the right order from the external code without having to decide on priorities before in their internal implementation, and then simply re-run them when needed which will not change their order.

Personally I still think refresh() is the best place as it is not called often and is straight forward - calling refresh I expect everything to be refreshed - including modes/overlays. But otherwise a separate method can work as well.

I hope this makes sense

CodeMirror’s view of modes is that they are stateless – I.e. given the same input and state value, they should always return the same highlighting. I’m not going to add elements to the interface that encourage people to violate this.

Thx marijn

If you have a minute can you explain why do you want overlays to be
stateless ?

Wouldn’t it be better for for example the search highlight overlay to have
a state (the query) and re-run when needed instead of adding and removing
it every time ? or also in the case of for example a spellchecker that
allows adding words to an ‘ignore all’ list ?

Because with unstable modes we’d also need a protocol for signalling when a mode changes, which seems more complicated than just re-adding it.