javascriptinnerhtmlevent-listenerrobohelp

How can I overwrite a portion of an element's text without affecting the rest of the element and any event listeners


I have this code that gets created automatically by Adoboe's RoboHelp 2017 into my HTML5 generated help file:

<object id="MapCtrl" classid="CLSID:A8ECFBF5-08CC-4065-BD74-0FAD1EA61317" data-rhtags="1" class="" width="1" height="1">
</object>
<p style="font-family:Arial;font-size:12pt;font-weight: normal;font-style: normal;text-decoration: none;" data-rhtags="1" class="" align="left">In&nbsp;this&nbsp;Topic&nbsp;<a class="dropspot" href="javascript:TextPopup(this)" id="MTHotSpot46267"><span class="MTText" style="display: none;">Show</span><span class="MTText">Hide</span></a></p>

I'm trying to use javascript to dynamically modify instances of the In&nbsp;this&nbsp;Topic&nbsp; text with a localized string without affecting the Show / Hide links in the anchor tags.

Here's my current attempt:

function localizeMiniTOC(){
    const minitoc = document.querySelector('#MapCtrl + p');
    const text = minitoc.textContent;
    console.log (typeof text);
    console.log(text.includes('In\xa0this\xa0Topic'));
    if (text.includes('In\xa0this\xa0Topic') === true){
        let html = minitoc.innerHTML;
        linkStart = html.indexOf('<a');
        remaining = html.substring(linkStart,html.length);
        minitoc.innerHTML = 'En Este Tema ' + remaining;
    }
}

This does change the text, but the problem I'm having, is that this also destroys the event listener that RoboHelp creates. For example, here's what the original Firefox Inspector looks like before my above code.

Notice there's this event listener: enter image description here

Here's what it looks like after my above code above.

There's now no event listener: enter image description here

I did some research today, and I understand from this link that using .innerHTML "removes internal data, like event listeners": Element innerHTML getting rid of event listeners

But I can't seem to figure out a different way to overwrite the text before the anchor tag, yet leave the Show / Hide links and event listener unscathed.

Other things I've tried:

minitoc.insertAdjacentHTML('beforebegin','<p>En\xa0Este\xa0Tema\xa0' + remaining + '</p>');

(The example in the linked page shows how to do this by appending to an existing element, but I need to overwrite the text leading up to the anchor tag, not append to the element.)

All the examples online seem to deal with appending or prepending, not overwriting text.

How can I dynamically overwrite the In&nbsp;this&nbsp;Topic&nbsp; text with a localized string without affecting the Show / Hide links and the event listener on those links?


Solution

  • Perhaps there's not a way to overwrite the text without nuking the event handler, but I did manage to fix my code so that it now at least adds the event handler back on after the minitoc.innerHTML = 'En Este Tema ' + remaining; line rewrites my paragraph.

    Here's my updated function:

    function localizeMiniTOC(){
        const minitoc = document.querySelector('#MapCtrl + p');
        const anchor = document.querySelector('#MapCtrl + p > a');
        const text = minitoc.textContent;
        if (text.includes('In\xa0this\xa0Topic') === true){
            let html = minitoc.innerHTML;
            linkStart = html.indexOf('<a');
            remaining = html.substring(linkStart,html.length);
            if (anchor.id.includes('MTHotSpot') === true){
                minitoc.innerHTML = 'En Este Tema ' + remaining;
                minitoc.addEventListener('click', function(e){
                    if (e.target.tagName === 'SPAN' && e.target.className==="MTText"){
                        TextPopup(anchor.id);
                    }
                });
            }
        }
    }
    

    Notice that I had an error in my original attempted workaround to add the event listener back in. In this incorrect code, I had neglected to call the function properly in the second parameter:

    minitoc.addEventListener('click', TextPopup('MTHotSpot46267'));
    

    Here's the fixed code for that (taken from my updated function):

    minitoc.addEventListener('click', function(e){
      if (e.target.tagName === 'SPAN' && e.target.className==="MTText"){
      TextPopup(anchor.id);
    }
    

    This results in the event listener getting added to the paragraph and then it was just a matter of making sure I was clicking on the span tag before running the TextPopup function.

    In this pic, you can see the added event: Inspector showing the added event