admin管理员组

文章数量:1334826

I have a division that I need to change its outer HTML upon an event. The problem is that upon setting the outerHTML I am not able to reference the new selected DOM object unless I explicitly catch it again.

Is there a way to directly update the variable reference upon calling outerHTML (in my case the reference of the div variable below) ?

$("#changeDiv").click(function(){

  var div = $(this).prev();
  div[0].outerHTML = `<div id="imSecondtDiv"> <p> World </p> </div>`;
  console.log(div); // logs [div#imFirstDiv, prevObject: n.fn.init[1], context: button#changeDiv]
  
  // the following line does not affect the newly added division 
  // since the var `div` references the old DOM object
  // unless I add div = $(this).prev(); before setting the html of 
  // the paragraph it will not set it
  div.find('p').html('Override'); 

});
<script src=".1.1/jquery.min.js"></script>
<div id="imFirstDiv"> <p> Hello </p> </div>
<button id="changeDiv" >Change Div 1</button>

I have a division that I need to change its outer HTML upon an event. The problem is that upon setting the outerHTML I am not able to reference the new selected DOM object unless I explicitly catch it again.

Is there a way to directly update the variable reference upon calling outerHTML (in my case the reference of the div variable below) ?

$("#changeDiv").click(function(){

  var div = $(this).prev();
  div[0].outerHTML = `<div id="imSecondtDiv"> <p> World </p> </div>`;
  console.log(div); // logs [div#imFirstDiv, prevObject: n.fn.init[1], context: button#changeDiv]
  
  // the following line does not affect the newly added division 
  // since the var `div` references the old DOM object
  // unless I add div = $(this).prev(); before setting the html of 
  // the paragraph it will not set it
  div.find('p').html('Override'); 

});
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="imFirstDiv"> <p> Hello </p> </div>
<button id="changeDiv" >Change Div 1</button>

Share Improve this question asked Feb 24, 2016 at 21:55 KADKAD 11.1k4 gold badges33 silver badges74 bronze badges 3
  • Do you specifically need to change outerHTML (which isn't really standard anyway)? You wouldn't generally use this with jQuery. Instead, could you remove the first div and add the second? – Rhumborl Commented Feb 24, 2016 at 22:00
  • set id to p tag then add this $("#p_id").text("override"); instead of div.find('p').html('Override'); – Bilal Usean Commented Feb 24, 2016 at 22:01
  • Well my real case is much more plex than the example, I have a list of items that are indexed relative to each items occurrence in the list, upon deleting on of the items list am updating the index of all the previous items to keep proper indexing so I am updating all the HTML elements names and ids of the current item with the new ones and replacing the divisions in a loop with outerHTML – KAD Commented Feb 24, 2016 at 22:03
Add a ment  | 

3 Answers 3

Reset to default 4

I have solved this by getting a reference element (sibling or parent) of tag that's going to be replaced.

Here is a function which is not dependent on which element are you going to change:

function replaceElement(ele, outerHTML)
{
  var parent = false, refEle;
  //if element that's going to be changed has previousElementSibling, take it as reference. If not, the parentElement will be the reference.
  if (ele.previousElementSibling !== null)
    refEle = ele.previousElementSibling;
  else
  {
    refEle = ele.parentElement;
    //indicate that parentElement has been taken as reference
    parent = true;
  }
  //change the outerHTML
  ele.outerHTML = outerHTML;
  //return the correct reference
  if (parent)
    return refEle.firstElementChild;
  else return refEle.nextElementSibling;
}

So in your case, you would invoke it this way:

div[0] = replaceElement(div[0], '<div id="imSecondtDiv"> <p> World </p> </div>');

I hope it will work with jQuery as well, as I am writing all my scripts only in native javascript.

As you are seeing changing the outerHTML makes things behave a bit strangely, as you are pletely replacing the original element but still referencing the old one.

It would be better to create a new div, add it after() the old one then remove() the old one. This maintains the position of the div in the correct place.

$("#changeDiv").click(function(){

  // get the oldDiv
  var oldDiv = $(this).prev();

  // Create a newDiv
  var newDiv = $('<div id="imSecondtDiv"> <p> World </p> </div>');

  // add newDiv after oldDiv one, then remove oldDiv from the DOM.
  oldDiv.after(newDiv).remove();
  
  // now you still have the reference to newDiv, so do what you want with it
  newDiv.find('p').html('Override'); 

});
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="imFirstDiv"> <p> Hello </p> </div>
<button id="changeDiv" >Change Div 1</button>

Using outerHTML

If you really really do need to use outerHTML, you can simply grab $(this).prev() again:

$("#changeDiv").click(function(){

  var div = $(this).prev();
  div[0].outerHTML = `<div id="imSecondtDiv"> <p> World </p> </div>`;

  // the "new" div is now before the button, so grab the reference of THAt one
  div = $(this).prev();

  // the following line does not affect the newly added division 
  // since the var `div` references the old DOM object
  // unless I add div = $(this).prev(); before setting the html of 
  // the paragraph it will not set it
  div.find('p').html('Override'); 

});
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="imFirstDiv"> <p> Hello </p> </div>
<button id="changeDiv" >Change Div 1</button>

Is there a way to directly update the variable reference upon calling outerHTML?

No. According to MDN Web Docs:

While the element will be replaced in the document, the variable whose outerHTML property was set will still hold a reference to the original element.

const p = document.querySelector('p');
p.outerHTML = '<p>Goodbye, world!</p>';
console.log(p.textContent);
<p>Hello, world!</p>

As a workaround, however, you can create a live HTMLCollection from which to get the element both before and after the update:

const Ps = document.getElementsByTagName('p');
Ps[0].outerHTML = '<p>Goodbye, world!</p>';
console.log(Ps[0].textContent);
<p>Hello, world!</p>

本文标签: javascriptHow to get reference to the new DOM object after changing content with outerHTMLStack Overflow