javascript create tooltip for part of the string that's not already under a tooltip

javascript, regex

Solution

I think a single str.replace will do the work if got the right regexp pattern.

function replaceTooltips(str, tooltips) {

    //copy from https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions
    function escapeRegExp(string) {

        return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
    }

    var keys = [];
    for ( var k in tooltips) {
        keys.push(escapeRegExp(k));
    }

    //create a regexp like (Size)|(Color)|(Time and Size)
    var ptn = new RegExp('(' + keys.join(')|(') + ')', 'g');

    str = str.replace(ptn, function(mat) {

        if (!tooltips[mat]) {
            return mat;
        }

        return '<span class="tooltip" data-tooltip="' + tooltips[mat].replace(/"/g, '&quot;') + '">' + mat + '</span>';
    });

    return str;

}

http://jsfiddle.net/rooseve/6wRUF/

Problem

I have a string like this: ``` "Size: 40; Color: 30" ``` I want to create tooltips for them such that it looks like this: ``` <span class='tooltip' data-tooltip='The Size of a Unit is controlled by the Color of the Unit.'>Size</span>: 40; <span class='tooltip' data-tooltip='The Color of a Unit is a standard Setting.'>Color</span>: 30 ``` Using a naive replacement however I end up with this: ``` <span class='tooltip' data-tooltip='The Size of a Unit is controlled by the <span class='tooltip' data-tooltip='The Color of a Unit is a standard Setting.'>Color</span> of the Unit.'>Size</span>: 40; <span class='tooltip' data-tooltip='The Color of a Unit is a standard Setting.'>Color</span>: 30 ``` Which is not what I want. How do I write a regex or do a replacement in such a way that it doesn't replace text that's already part of the tooltip? Edit: I didn't make it clear that the replacements are not Size and Color, they're just examples. I'm adding an arbitrary amount, usually 20+ tooltips to any string. Here are some testables: ``` var tooltips = { "Size":"The Size of a Unit is controlled by the Color", "Color": "bar", "Time and Size": "foo" } "Here we have something of <b>Size</b> 20 and Color red. it's very important that the Time and Size of the work and kept in sync." ``` Should result in: ``` "Here we have something of <b><span class='tooltip' data-tooltip='The Size of a Unit is controlled by the Color'>Size<span></b> 20 and <span class='tooltip' data-tooltip='bar'>Color<span> red. it's very important that the <span class='tooltip' data-tooltip='foo'>Time and Size<span> of the work and kept in sync." ``` The longer match should take precedence over shorter matches. It should match on only whole words and not parts of words. Edit: Forgot to state yet another requirement. It should still match strings that are wrapped with tags that are not tooltips.

Original source

Related problems