简体   繁体   中英

Javascript .indexOf matching HTML symbols

I solved a problem in a very sloppy manner, looking for a better solution.

Task

Check if a span contains an HTML symbol(an arrow), if present, replace the symbol with it's opposite.

First Attempt (not showing the second code snipet that does the reverse)

 first=headers[0].querySelector('span')
 if (first.innerHTML.indexOf('↘') !== -1)
                            first.innerHTML=first.innerHTML.substring(0, first.innerHTML.length - 13)
 first.innerHTML+=' ↖'

Why doesn't that work?

because while   ===   but for some reason ↘ === ↘

Seriously! Try this (tested in IE 11 and chrome)

<span>test</span>
<script>
    first=document.querySelector('span')
    first.innerHTML+='&nbsp&searr;'
    console.log(first.innerHTML)
</script>

In the console you get: test&nbsp;↘

My ugly solution

I copied the arrow into my JS code

if (first.innerHTML.indexOf('↘') !== -1)
                            first.innerHTML=first.innerHTML.substring(0, first.innerHTML.length - 7)
                    first.innerHTML+='&nbsp;&nwarr;'

So...what's the correct way of solving this issue?

If you're worried about having that literal arrow in your code, you shouldn't be. If your toolchain is correctly configured, it's just fine to have that literal arrow in your code.

But if you want to avoid it, you can use a unicode escape for it instead:

const nwarr = "\u2196";
if (first.innerHTML.indexOf(nwarr) !== -1) {
    first.innerHTML = first.innerHTML.substring(0, first.innerHTML.length - 7);
}
first.innerHTML += '&nbsp;&nwarr;'; // <== Did you mean &searr; here? The opposite of nwarr?

Live example (using &searr; in the replacement:

 const first = document.getElementById("first"); setTimeout(() => { const nwarr = "\↖"; if (first.innerHTML.indexOf(nwarr) !== -1) { first.innerHTML = first.innerHTML.substring(0, first.innerHTML.length - 7); } first.innerHTML += '&nbsp;&searr;'; }, 800); 
 <span id="first">Foo&nbsp;&nwarr;</span> 


Two side notes:

1. To replace things, I'd use replace rather than substring and += , not least so you don't have magic numbers (13, 7) in your code:

first.innerHTML = first.innerHTML.replace(/\&nbsp;\u2196/g, "&nbsp;&searr;");

you might even allow for some browsers to use an character entity rather than character for it:

first.innerHTML = first.innerHTML.replace(/\&nbsp;(?:\&nwarr;|\u2196)/g, "&nbsp;&searr;");

Live example (using &searr; in the replacement:

 const first = document.getElementById("first"); setTimeout(() => { first.innerHTML = first.innerHTML.replace(/\\&nbsp;(?:\\&nwarr;|\↖)/g, "&nbsp;&searr;"); }, 800); 
 <span id="first">Foo&nbsp;&nwarr;</span> 

2. I would avoid textual manipulation of innerHTML . If you assign to it, even when assigning back what it already had, it tears down all of the elements (and other nodes) within the element you're doing it on, and creates new, replacement elements and nodes.

For instance, you could spin through the text nodes:

 const first = document.getElementById("first"); setTimeout(() => { handleReplacement(first); }, 800); function handleReplacement(el) { for (let child = el.firstChild; child; child = child.nextSibling) { if (child.nodeType === 1) { // Element handleReplacement(child); } else if (child.nodeType === 3) { // Text child.nodeValue = child.nodeValue.replace(/\ \↖/g, "\ \↘"); } } } 
 <span id="first">Foo&nbsp;&nwarr;</span> 

Based on TJ Crowder's very good insights. I patched my test code into this:

<span>test&nbsp;&nwarr;</span>
<script>
const nw="\u2196";
const se="\u2198";
first=document.querySelector('span')
if (first.innerHTML.indexOf(nw) !== -1)
   {
    console.log("found arrow");
    first.innerHTML = first.innerHTML.replace(/\u2196/, se);
   }

</script>

It still feels like we've stumbled into a messy/buggy corner of the browser world.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM