Question

Can I apply a Code Mirror overlay outside the definition of a mode? The code below works but seems redundant and slow. I'm defining a mode for each editor/viewer on a page which could be zero to many. How can this be optimized?

Ideally, I would like to define the mode once and then apply the overlay as needed.

I have not been able to find an answer if I can. I want to define a mode (it highlights a search term (see this question)) and then I want to apply that mode to many editors/viewers on a page. Each editor/viewer has a different language and is set on the DOM element (e.g <pre class="sourcecode" language="javascript">code</pr>).

I think the solution would be something dealing with return CodeMirror.overlayMode(CodeMirror.getMode(config, mode),searchOverlay, true); but I've been unable to get it to work.

$('.sourcecode').each( function() {
        var value = $(this).text(),
            search = (typeof keyword === 'undefined') ? false : true,
            mode =  $(this).attr('language'),
            pre = $(this).get(0),
            line = ($(this).attr('firstLineNumber') == undefined) ? 1 : parseInt($(this).attr('firstLineNumber'), 10);

        // CodeMirror search highlighing

        // this seems redundent, slow, and messy
        if (search) {
            CodeMirror.defineMode("highlightSearch", function(config, parserConfig) {
              var searchOverlay = {
                token: function(stream, state) {
                    if (stream.match(keyword)) {
                        return "highlightSearch";
                    }

                    while (stream.next() != null && !stream.match(keyword, false)) {}
                    return null;
                }
              };
              return CodeMirror.overlayMode(CodeMirror.getMode(config, mode),searchOverlay, true);
            });
        }

        var viewer = CodeMirror(function(elt) {
            pre.parentNode.replaceChild(elt, pre);
        }, {
            value: value,
            lineNumbers: true,
            firstLineNumber: line,
            matchBrackets: true,
            lineWrapping: true,
            readOnly: true,
            mode: (search) ? 'highlightSearch' : mode,
        });
    });

Thank you for any help.

Was it helpful?

Solution

This is unlikely to be very costly (unless you are creating hundreds of editors per second), but a more elegant solution would be to define your wrapping mode once, and read the inner mode (mode variable in your code) from its parserConfig object, say parserConfig.inner. You'd then simply pass {name: "highlightSearch", inner: mode} as your mode option.

OTHER TIPS

For completeness I defined the mode outside the .each. Within the mode definition I replaced

return CodeMirror.overlayMode(CodeMirror.getMode(config, mode),searchOverlay, true);

with

return CodeMirror.overlayMode(CodeMirror.getMode(config, parserConfig.inner),searchOverlay, true);

and replaced

mode: (search) ? 'highlightSearch' : mode,

with

mode: (search) ? {name: 'highlightSearch', inner: mode} : mode,
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top