user9755712
user9755712

Reputation:

Replace HTML with innerHTML - Javascript

I need to write a JS functionality that reads an entire HTML document and replace a text with some other text.

HTML -

<ul>
  <li>
    <a id="aId" href="https://www.w3schools.com" target="_blank"> Link1 </a>
  </li>
  <li>
    <a id="bId" href="https://www.w3schools.com" target="_blank"> Link2 </a>
  </li>
  <li>
    <a href="https://www.w3schools.com" target="_blank"> Link3 </a>
  </li>
</ul>

Javascript code -

var strMessage1 = document.getElementById("aId") ;
var first = 'target="_blank"';
var second = 'target="_blank" rel="noopener noreferrer" onClick="alert(\'Hello World!\')"';

strMessage1.innerHTML = strMessage1.innerHTML.replace(first, second) ; 

The javascript should be able to run through entire HTML and replace the first var with the second var (defined in the script), wherever found. This is an example of just the first id - 'aId'.

Question - How would the script cover and replace contents in

as well.

DEMO - http://jsfiddle.net/nikhil_gupta/rzy3ajhx/.

Note - No use of jQuery.

Upvotes: 0

Views: 10593

Answers (5)

Scott Marcus
Scott Marcus

Reputation: 65806

.innerHTML alters the content of an element (what's between the opening and closing tags). Your code attempts to alter the value of an element's attribute. These are not the same thing.

Also, it's important to understand the implications of using innerHTML (and outerHTML).

  • They both cause the DOM to have to be re-built and then re-painted and re-flowed which is very expensive in terms of resources.
  • Their use will also remove any previously set up event handlers.
  • They open security holes in your application.
  • They are usually accompanied by gobs and gobs of string concatenations and nested quotes.

To change the value of an element's attribute, just access the HTML attribute you want to modify as a property of the JavaScript object or use the element.setAttribute(attributeName, value) DOM method.

Question - How would the script cover and replace contents in

  • bId id?
  • Link3, which has no id?

as well.

When you want to alter more than one element, you need to get them into a collection or array and then you can loop over them. Getting them into a group can be done in many different ways that doesn't have to do with ids at all (by tag name, by CSS class, by position in the document, by attribute values, etc.). In your example, if we wanted to modify all the links that were inside of bullets that have target=_blank as their href value, we could target them by position and attribute value with a CSS selector and the .querySelectorAll() method. You'll notice in my example below, I've removed the id attributes completely from the HTML and the code still works.

Lastly, you should not be using inline HTML event attributes (onclick, etc.) to configure event handling callback functions. That is a 25+ year old technique that gets copied and pasted by every new web developer without an understanding of why it shouldn't be used. Instead, use modern, standards-based code and the .addEventListener() DOM API.

// Get the elements you wish to work on into an Array
// Here, we're selecting <a> elements that have an href attribute with a value of _blank 
// that are direct children of <li> elements:
var elementsToChange = Array.prototype.slice.call(document.querySelectorAll("li > a[target='_blank']"));

// We only need to worry about what's going to change
var newRel = 'noopener noreferrer'

// This will be the click event callback function
function doAlert(){
  alert('Hello World!');
}

// Loop over the array
elementsToChange.forEach(function(element){
  // Just access the HTML attribute you want to modify as a property of the JavaScript object
  element.rel = newRel;
    
  // Or, use the DOM API
  element.setAttribute("rel", newRel); 
  
  // Either way the DOM API should always be used to set up event handlers
  element.addEventListener("click", doAlert);
});
<ul>
  <li><a href="https://www.w3schools.com" target="_blank">I will be modified by the code</a></li>
  <li><a href="https://www.w3schools.com">I WON'T be modified by the code!</a></li>
  <li><a href="https://www.w3schools.com" target="_blank">I will be modified by the code</a></li>
</ul>

Upvotes: 1

31piy
31piy

Reputation: 23859

You can use outerHTML to replace the occurrence of the contents of first with the contents of second. You may select the second a using the same document.getElementById call.

For third one, you can use document.querySelectorAll and get the last item of the returned collection.

var strMessage1 = document.getElementById("aId");
var strMessage2 = document.getElementById("bId");
var anchors = document.querySelectorAll("a");
var strMessage3 = anchors[anchors.length - 1];

var first = 'target="_blank"';
var second = 'target="_blank" rel="noopener noreferrer" onClick="alert(\'Hello World!\')"';

strMessage1.outerHTML = strMessage1.outerHTML.replace(first, second);
strMessage2.outerHTML = strMessage2.outerHTML.replace(first, second);
strMessage3.outerHTML = strMessage3.outerHTML.replace(first, second);
<ul>
  <li>
    <a id="aId" href="https://www.w3schools.com" target="_blank"> Link1 </a>
  </li>
  <li>
    <a id="bId" href="https://www.w3schools.com" target="_blank"> Link2 </a>
  </li>
  <li>
    <a href="https://www.w3schools.com" target="_blank"> Link3 </a>
  </li>
</ul>

Better coding practices:

  • Use setAttribute() to set individual attributes of an element instead of doing a replace. This will prevent unwanted bugs.
  • Instead of selecting individual elements by using document.getElementById and document.querySelectorAll, you may use one document.querySelectorAll and loop on the collection to replace the contents.

Upvotes: 0

rosethorn
rosethorn

Reputation: 91

  • Q1:bId id?

Ans1: I don't know which kind of element is you need. So, I catch all of the tags. There is a simple way to get elements: document.querySelectorAll("query")

  • Q2:Link3, which has no id?

Ans2: as Q1. Element that don't has id is fine.

  • Q3:edited tag not work.

Ans 3: .innerHTML is for <a>*here*</a>, you need to edit attribute so you need to call .outerHTML

Refs:

var all_a_tag = document.querySelectorAll("a");
for (var i = 0; i < all_a_tag.length; i++) {
  var elem = all_a_tag[i];
  var first = 'target="_blank"';
  var second = 'target="_blank" rel="noopener noreferrer" onClick="alert(\'Hello World!\')"';

  elem.outerHTML = elem.outerHTML.replace(first, second);
}
<ul>
  <li>
    <a id="aId" href="https://www.w3schools.com" target="_blank"> Link1 </a>
  </li>
  <li>
    <a id="bId" href="https://www.w3schools.com" target="_blank"> Link2 </a>
  </li>
  <li>
    <a href="https://www.w3schools.com" target="_blank"> Link3 </a>
  </li>
</ul>

Upvotes: 0

Do Trung Duc
Do Trung Duc

Reputation: 406

As far as I understand, you are trying to change the attributes in the html tag. You can't use .innerHTML or .replace to do that, it just changes the content inside the html tag. To solve for your question, you can use .getAttribute(), .setAttribute(), or .createAttribute() method. Something similar with your code, and it works:

var strMessage1 = document.getElementById("aId");
strMessage1.setAttribute("rel", "noopener noreferrer");
strMessage1.setAttribute("onClick", "alert(\'Hello World!\')")

Upvotes: 0

Bui Dinh Ngoc
Bui Dinh Ngoc

Reputation: 447

I think you mean outerHTML

http://jsfiddle.net/rzy3ajhx/1/

strMessage1.outerHTML = strMessage1.outerHTML.replace(first, second);

Upvotes: 0

Related Questions