Warnings and Upfront Disclaimers

This is an exploration of a problem that would be considered extremely basic by someone experienced with JavaScript. However, I wanted to write something showing the trial and error that goes into solving a development problem, especially when inexperienced with the language and jargon. There aren’t many of those articles around the internet (that I’m aware of), so hopefully this can help other learning developers that not always having a quick and easy fix is normal!

(To that end, there’s a bunch of footnotes to help people understand my research process and other general.)

The Problem

The website used a plugin that would allow you to create forms, and then generate posts based on those forms. Unfortunately, it’s extremely inflexible plugin and there was too much time already sunk into it. The generated posts wouldn’t let you control how the fields displayed. This meant the form field titles were added in, and also didn’t have the colons inside the <label> tag (so that even if the label was hidden with CSS, the colon would still show).

See the Pen Colon JS Problem, Before by Emily Serven (@emilyeserven) on CodePen.

Possible Solutions without JavaScript?

Some very hacky CSS was attempted to fix this problem, but in the end, nothing worked out.

1
2
3
4
.wpuf-customs {
margin-left: -2px;
overflow: hidden;
}

Another option was to edit the PHP file in the actual plugin. However, I couldn’t find where to make the edit, and this solution would require re-editing the hack in every time the plugin was updated.

Finally, the last option was to try using a different plugin on top of the currently existing one. The WP Toolset content template system is used insert information into a post, and usually it will override the rest of the content, regardless of any other settings. However, the problem plugin overrode the content template to the point that it stripped all the HTML out.

With all those options exhausted, it was time to resort to JavaScript.

The Plan

I needed to write a function1 that would iterate2 through a list3 and replace the colons with empty spaces, either through a replace()4 method5 or a regular expression6. I checked out regular expressions first (and did find a tool7 to make sure I wrote a valid expression), but decided that just using replace() would be easier.

Trial and Error 1: I Used a String Method on an Object

The original code I figured out for the problem was as follows:

1
2
3
4
5
6
7
8
function memberList() {
    var memberListItems = document.querySelectorAll('ul.wpuf_customs li');
    for (var i = 0; i < memberListItems.length; i++) {
        console.log(memberListItems[i]); //for debugging, ensuring loop is iterating correctly.
        memberListItems[i].replace(":", "");
    }
}
memberList();

A function called memberList() that had a local8 variable memberListItems. This variable kept the DOM query9 and allowed me to use it in a for loop10. However, I kept getting an error that I wasn’t working with a string.

After further investigation, I found out that I was trying to use a string method on an object. Which leads us into the next part…

Trial and Error 2: I Removed the Colon, but Added Everything Else Back in

1
2
3
4
5
6
7
8
function memberList() {
    var memberListItems = document.querySelectorAll('ul.wpuf_customs li');
    for (var i = 0; i < memberListItems.length; i++) {
        console.log(memberListItems[i]);
        memberListItems[i].textContent.replace(":", "");
    }
}
memberList();

By using the textContent property, I was able to convert the objects to a string11, but I also stripped out all the HTML. Because of this, links, images, and labels came back and I ended off worse than when I started.

Trial and Error 3: I Tried Removing Labels While Keeping the Image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function memberList() {
    var memberListItems = document.querySelectorAll('ul.wpuf_customs li');
    var memberListLabel = document.querySelectorAll('ul.wpuf_customs li label');
    for (var i = 0; i < memberListItems.length; i++) {
        memberListItems[i].removeChild(memberListLabel[i]);
        console.log(memberListItems[i]);
        if (memberListItems[i].textContent.includes(":")) {
            console.log(memberListItems[i].innerHTML);
            memberListItems[i].textContent = memberListItems[i].textContent.replace(":", "");
            console.log(": Replaced");
        }
        else {
            console.log("Image.");
        }
    }
}
memberList();

Before removing the colon (and stripping the HTML), I used the includes()12 method to remove the <label> tag and all of its content13. To protect the area with the image (which had a colon inside its <label> tag, for some reason…) I added an if statement checking to see if a selected object included a : character.

(I had experimented with testing14 if an element contains a class15 and removing nodes16, but neither of those solutions worked.)

At the end of this, however, there was still a problem because the <a> tag was being stripped out. So instead of using textContent, I decided to switch over to a different solution.

Trial and Error 4: I Decided to Use innerHTML Instead of textContent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function memberList() {
    var memberListItems = document.querySelectorAll('ul.wpuf_customs li');
    var memberListLabel = document.querySelectorAll('ul.wpuf_customs li label');
    for (var i = 0; i < memberListItems.length; i++) {
        memberListItems[i].removeChild(memberListLabel[i]);
        console.log(memberListItems[i]);
        if (memberListItems[i].textContent.includes(":")) {
            console.log(memberListItems[i].innerHTML);
            memberListItems[i].innerHTML = memberListItems[i].innerHTML.replace(":", "");
            console.log(": Replaced");
        }
        else {
            console.log("Image.");
        }
    }
}
memberList();

There’s a definite17 difference18 between the textContent and innerHTML methods. Most importantly, innerHTML will make changes to the DOM while also keeping the HTML intact. Because of this, I was able to keep all the links and images.

At the End… I Made Further Simplifications

1
2
3
4
5
6
7
function memberList() {
    var memberListItems = document.querySelectorAll('ul.wpuf_customs li');
    for (var i = 0; i < memberListItems.length; i++) {
        memberListItems[i].innerHTML = memberListItems[i].innerHTML.replace(":", "");
    }
}
memberList();

innerHTML solved a lot of problems, thereby creating unneeded code (although it should be noted that its use is a last resort, as interacting with DOM elements in that was is bad practice). I removed the label query selector, the item in the for loop that removed the actual <label>, and all the console.logs that were used for debugging.

Finally, I wanted to optimize loading times. Since this script was only needed on a specific category of pages, I inserted the JavaScript into a Toolset content template, which only loaded on the needed pages.

Final Product

See the Pen Colon JS Problem, After by Emily Serven (@emilyeserven) on CodePen.

Some Notes on Research and Asking for Help

Knowing how to efficiently Google and being familiar with StackOverflow are essential for this job/hobby. However, I can’t emphasize enough how nice it is to have other people to ask for help, especially if you don’t have as much experience in the language you’re working on. On that front, I had some support via some Slack channels since this was a time-sensitive problem. The people here did not outright solve the problem for me, but definitely pointed out places for me to investigate. This would have taken another hour or so if I did not have that help! (I was using frontenddevelopers and CodeNewbie for this project specifically, since more people were online at the time.)

Footnotes / References

Refs&Docs is my own personal documentation site, and is included in these footnotes to try and explain fundamentals. Other links are part of the research process. They were Googled unless noted.