Bob
Bob

Reputation: 87

How can I remove a child element only if it exists under a parent?

I need to remove the child tarif if it exists in either social_header or menu element depending on the size of the screen. Right now I have console errors:

Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

let tarif = document.createElement("li");
tarif.className = "tarif";
let anchor = document.createElement("a");
anchor.setAttribute('href', "#");
let tarif_text = document.createTextNode("Tarifs");
anchor.appendChild(tarif_text);
tarif.appendChild(anchor);
const social_header = $("#social-header")[0];
const menu = $("#menu")[0];

$(window).resize(function() {
  if ($(this).width() > 800) {
    social_header.insertBefore(tarif, social_header.children[0]);
    menu.removeChild(tarif);
  } else {
    menu.appendChild(tarif);
    social_header.removeChild(tarif);
  }
});

Upvotes: 1

Views: 854

Answers (2)

DDomen
DDomen

Reputation: 1878

You can use directly the insertBefore/appendChild properties

if ($(this).width() > 800) {
  social_header.insertBefore(tarif, social_header.firstChild)
}else{
  menu.appendChild(tarif);
}

Since a node can't have multiple parents, it will be removed from the current parent.

By the way mixing too much vanilla JS and jQuery is not always a good idea.

Upvotes: 0

Rory McCrossan
Rory McCrossan

Reputation: 337570

As you're already including jQuery in the page you can simplify what you're doing by using it's pattern of not throwing any errors when dealing with undefined target elements.

In this case, use prependTo() to add the element where necessary, and then find() to retrieve it within the parent and remove() it. Note that jQuery's remove() method will not throw an error when called on an empty object.

const $tarif = $('<li class="tarif"><a href="#">Tarfis</a></li>');
const $social_header = $("#social-header");
const $menu = $("#menu");

$(window).resize(function() {
  if ($(this).width() > 800) {
    $tarif.prependTo($social_header);
    $menu.find('.tarif').remove();
  } else {
    $tarif.appendTo($menu);
    $social_header.find('.tarif').remove();
  }
});

That being said, I would strongly suggest you solve your goal using CSS instead of JS. Your current approach is brittle, as it can easily be broken by someone simply disabling JS in the browser, and also not a good separation of UI and JS code.

To do the same thing in CSS, place all HTML in the DOM when the page loads and organise your CSS in this manner:

#menu .tarif { display: none; }
#social-header .tarif  { display: block; }

@media screen and (min-width: 0px) and (max-width: 800px) {
  #menu .tarif { display: block; }
  #social-header .tarif  { display: none; }
}

Upvotes: 0

Related Questions