Peter
Peter

Reputation: 501

Replace RegExp - negative pattern

I have div with 'contenteditable'. I would like filter char in this div, and when is [^ą-źa-z0-9\s] AND NOT ( ), I must change color char, don't match the pattern. For example, when I get $(this).html(): dfgtąść45%$#tg ss&k; - I would like change to red color bold char.

JS:

var t = $(this).html().replace(/<\/?[^>]+>/gi, '').replace(/\s$/, '&nbsp;');
t = t.replace(/(&nbsp;)[^ą-źa-z0-9\s]/ig,function(match){return '<span style="color: red;">' + match + "</span>";});
$(this).html(t);

Upvotes: 1

Views: 1084

Answers (2)

MikeM
MikeM

Reputation: 13641

Here is one way

t = t.replace( /(&nbsp;)|(?:(?!&nbsp;)[^ą-źa-z0-9\s])+/ig,
    function ( match, nbsp ) {
        return nbsp ? nbsp : '<span style="color: red;">' + match + "</span>";
});

Note though that manipulating html in this way is not recommended: for example, any characters within element attributes which match the negated character class would be mistakenly enclosed in span tags.

Upvotes: 1

nhahtdh
nhahtdh

Reputation: 56829

If you want to highlight whatever that doesn't match a certain pattern, you can use this code. This is much more extensible than trying to modify the regex to negate the matches.

function unmatches(regex, str, callback) {

    var result = "";
    var lastAppend = 0;

    var arr;
    var nonMatching;

    while ((arr = regex.exec(str)) != null) {
        nonMatching = str.substring(lastAppend, arr.index);

        if (typeof callback === "function") {
            nonMatching = callback(nonMatching);
        }
        // If a function is not supplied, currently, it output back
        // the input string. It can be extended, though.

        result += nonMatching + arr[0];
        lastAppend = arr.index + arr[0].length;

        // In case the global flag is not set
        // There is at most one match without global flag
        if (!regex.global) {
            break;
        }
    }

    nonMatching = str.substring(lastAppend);

    if (typeof callback === "function") {
        nonMatching = callback(nonMatching);
    }

    result += nonMatching;

    return result;
}

Using your case as an example (note that I added the g flag):

var result = unmatches(/(&nbsp;)*[ą-źa-z0-9\s]+/g, "dfgtąść45%$#tg&nbsp;ss&k;", function (m) {
    if (m === "") {
        // Non matching part can be empty string
        return m; // Ignore
    } else {
        // The non-empty string case
        return '<span style="color: red;">' + m + '</span>';
    }
});

Upvotes: 1

Related Questions