JS - remove DOM element

 Removing all but the last item(above)

document.querySelector(".grid").addEventListener("click", function(e){
    var removeTarget = e.target.parentNode;
    removeTarget.parentNode.removeChild(removeTarget);
}, false);
document.querySelector('.grid').addEventListener('click', function(e) {
  console.dir(e);
  if(e.target.tagName == "IMG"){
    var howmany = document.querySelectorAll("li").length;
    if(howmany > 1) {
      var removeTarget = e.target.parentNode;
      removeTarget.parentNode.removeChild(removeTarget);
    }  else {
      var photoTitle = e.target.alt;
      document.querySelector("#art p").innerHTML = "you have selected: " + photoTitle;
    }
  }
}, false);

 

Mouse Over

document.querySelector('.grid').addEventListener('mouseover', function(e) {
  if (e.target.tagName === 'IMG') {
    var divElem = document.createElement("div");
    divElem.className = "preview";
    e.target.parentNode.appendChild(divElem);

    var bigImg = document.createElement("img");
    var smallSrc = e.target.src;
    bigImg.src = smallSrc.substr(0, smallSrc.length - 7) + '.jpg';
    divElem.appendChild(bigImg);
  } // check to see that I clicked on IMG only
}, false); // click event

Mouse Out

Multiple identical event listeners - from Mozilla  

If multiple identical EventListeners are registered on the same EventTarget with the same parameters, the duplicate instances are discarded. They do not cause the EventListener to be called twice, and they do not need to be removed manually with the removeEventListener() method. Note however that when using an anonymous function as the handler, such listeners will NOT be identical since anonymous functions are not identical even if defined using the SAME unchanging source-code simply called repeatedly, even if in a loop. However, repeatedly defining the same named function in such cases can be more problematic. (see Memory issues below.) 

JS - Scope W3school

In JavaScript, objects and functions are also variables. 

1. My own solution: 

Define handler outside of the Mouseover event handler function. That way I don't need to use removeEventListener. The handler function (which is defined ONCE globally and attached to mouseout event listener once) will be called when mouse moves out.

document.querySelector('.grid').addEventListener('mouseover', function(e) {
  if (e.target.tagName === 'IMG') {

    var myElement = document.createElement('div');
    myElement.className = 'preview';
    e.target.parentNode.appendChild(myElement);

    var myImg = document.createElement('img');
    var imgLoc = e.target.src;
    myImg.src = imgLoc.substr(0, imgLoc.length - 7) + '.jpg';
    myElement.appendChild(myImg);

    e.target.addEventListener("mouseout", handler, false);

  } // check to see that I clicked on IMG only
}, false); // click event

function handler(d){
  var node = d.target.parentNode.querySelector("div.preview");
  node.parentNode.removeChild(node);
}

2. Given solution:

Define handler function inside of mourseover event handler function. IMO: this function is defined 'locally', and it only exists when mourseover event handler function is called. So it is created and registered to mouseout event everytime mourseover event handler function is called (i.e. one specific mouseout event handler 'dedicates to' one mouseover event and it should only correspond to ONE mouseover-mouseout event; mourseover event handler function should execute ONCE for ONE mourseover event). In other words, multiple locally defined 'handler functions' are attached to mouseout event listener.  When mouseout event is fired, all the functions are triggered and will attempt to remove the 'div.preview' DOM multiple times and this results in error (var myNode = d.target.parentNode.querySelector('div.preview') is null). 

To solve this issue, we need to remove the locally defined 'handler function' everytime at the end of mouseout event by e.target.removeEventListener('mouseout', handler, false);

document.querySelector('.grid').addEventListener('mouseover', function(e) {  // mouseover handler
  if (e.target.tagName === 'IMG') {

    var myElement = document.createElement('div');
    myElement.className = 'preview';
    e.target.parentNode.appendChild(myElement);

    var myImg = document.createElement('img');
    var imgLoc = e.target.src;
    myImg.src = imgLoc.substr(0, imgLoc.length-7) + '.jpg';
    myElement.appendChild(myImg);

    e.target.addEventListener('mouseout', function handler(d) {  // mouseout handler
      var myNode = d.target.parentNode.querySelector('div.preview');
      myNode.parentNode.removeChild(myNode);
      e.target.removeEventListener('mouseout', handler, false);
    }, false);

  } // check to see that I clicked on IMG only
}, false); // click event

HTML for try it out:

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>JavaScript Events</title>
  <link href='http://fonts.googleapis.com/css?family=Bree+Serif|Merriweather' rel='stylesheet' type='text/css'>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div id="art">
  <h2>Art Preview</h2>
  <p>Mouse over the following pieces of art to preview a large version</p>
    <ul class="grid">
      <li><img src="images/Hassum_Harrod_03_tn.jpg" alt="Hassum Harod's Summer Trees"></li>
      <li><img src="images/LaVonne_LaRue_02_tn.jpg" alt="LaVonne_LaRue's Mighty Duck"></li>
      <li><img src="images/Lorenzo_Garcia_01_tn.jpg" alt="Lorenzo Garcia's The Dancer"></li>
      <li><img src="images/Jennifer_Jerome_01_tn.jpg" alt="Jennifer Jerome's A day of Rest'"></li>
      <li><img src="images/Constance_Smith_03_tn.jpg" alt="Constance Smith's Letterforms"></li>
      <li><img src="images/LaVonne_LaRue_04_tn.jpg" alt="LaVonne LaRue's Flow"></li>
      <li><img src="images/Lorenzo_Garcia_03_tn.jpg" alt="Lorenzo Garcia's Mother'"></li>
      <li><img src="images/Jennifer_Jerome_02_tn.jpg" alt="Jennifer Jerome's Farm Life"></li>
      <li><img src="images/Hillary_Goldwynn_03_tn.jpg" alt="Hillary Goldwynn's Blue Sky"></li>
    </ul>
    </div>
  <script src="script.js"></script>
</body>
</html>

 

Contextmenu event

document.querySelector('.grid').addEventListener('contextmenu', function(e) {
  e.preventDefault();
  if (e.target.tagName === 'IMG') {

    var myElement = document.createElement('div');
    myElement.className = 'preview';
    e.target.parentNode.appendChild(myElement);

    var myImg = document.createElement('img');
    var imgLoc = e.target.src;
    myImg.src = imgLoc.substr(0, imgLoc.length-7) + '.jpg';

    myElement.style.left = e.offsetX + 15 + 'px';
    myElement.style.top = e.offsetY + 15 + 'px';

    myElement.appendChild(myImg);

    e.target.addEventListener('mouseout', function handler(d) {
      var myNode = d.target.parentNode.querySelector('div.preview');
      myNode.parentNode.removeChild(myNode);
      e.target.removeEventListener('mouseout', handler, false);
    }, false);

    e.target.addEventListener('mousemove', function (f) {
      myElement.style.left = (f.offsetX + 15) + 'px';
      myElement.style.top = (f.offsetY + 15) + 'px';
    }, false);    

  } // check to see that I clicked on IMG only
}, false); // click event

HTML:


<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>JavaScript Events</title>
  <link href='http://fonts.googleapis.com/css?family=Bree+Serif|Merriweather' rel='stylesheet' type='text/css'>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div id="art">
  <h2>Art Preview</h2>
  <p>Right click on the image to see a larger version. The preview will follow the mouse.</p>
    <ul class="grid">
      <li><img src="images/Hassum_Harrod_03_tn.jpg" alt="Hassum Harod's Summer Trees"></li>
      <li><img src="images/LaVonne_LaRue_02_tn.jpg" alt="LaVonne_LaRue's Mighty Duck"></li>
      <li><img src="images/Lorenzo_Garcia_01_tn.jpg" alt="Lorenzo Garcia's The Dancer"></li>
      <li><img src="images/Jennifer_Jerome_01_tn.jpg" alt="Jennifer Jerome's A day of Rest'"></li>
      <li><img src="images/Constance_Smith_03_tn.jpg" alt="Constance Smith's Letterforms"></li>
      <li><img src="images/LaVonne_LaRue_04_tn.jpg" alt="LaVonne LaRue's Flow"></li>
      <li><img src="images/Lorenzo_Garcia_03_tn.jpg" alt="Lorenzo Garcia's Mother'"></li>
      <li><img src="images/Jennifer_Jerome_02_tn.jpg" alt="Jennifer Jerome's Farm Life"></li>
      <li><img src="images/Hillary_Goldwynn_03_tn.jpg" alt="Hillary Goldwynn's Blue Sky"></li>
    </ul>
    </div>
  <script src="script.js"></script>
</body>
</html>

But adding removeEventListener will not work ...:

added removeEventListener and commented out the initial position setting for myelement.

document.querySelector('.grid').addEventListener('dblclick', function(e) {
  // e.preventDefault();
  if (e.target.tagName === 'IMG') {

    var myElement = document.createElement('div');
    myElement.className = 'preview';
    e.target.parentNode.appendChild(myElement);

    var myImg = document.createElement('img');
    var imgLoc = e.target.src;
    myImg.src = imgLoc.substr(0, imgLoc.length-7) + '.jpg';

    myElement.appendChild(myImg);
    // myElement.style.left = (e.offsetX + 10) + "px";
    // myElement.style.top = (e.offsetX + 10) + "px";

    e.target.addEventListener('mouseout', function handler(d) {
      var myNode = d.target.parentNode.querySelector('div.preview');
      myNode.parentNode.removeChild(myNode);
      e.target.removeEventListener('mouseout', handler, false);
    }, false);

    e.target.addEventListener('mousemove', function move(f) {
      console.log("moved!");
      myElement.style.left = (f.offsetX + 15) + 'px';
      myElement.style.top = (f.offsetY + 15) + 'px';
      f.target.removeEventListener('mousemove', move, false);
    }, false);    

  } // check to see that I clicked on IMG only
}, false); // click event

 So function move is locally defined (hover over move in VS code shows 'local function'), and everytime dblclick event handler gets called (everytime you double click), a new local move func will be defined and register for mousemove event. When mousemove is tigger, move executes for once and remove 'move' from event listener of mousemove. So mousemove only trigger move function ONCE for ONE double click. But we expect move to be executed for every mousemove after the first double click (i.e. move should be executed MANY TIMES after one mouse double click, and this is different from ONE-TO-ONE relationship between mouseout and mouseover), so it should NOT be removed from event listener after one execution.

If we want to remove move from mousemove event listener, maybe we should do that when mouseout event is triggered:

document.querySelector('.grid').addEventListener('dblclick', function(e) {
  // e.preventDefault();
  if (e.target.tagName === 'IMG') {

    var myElement = document.createElement('div');
    myElement.className = 'preview';
    e.target.parentNode.appendChild(myElement);

    var myImg = document.createElement('img');
    var imgLoc = e.target.src;
    myImg.src = imgLoc.substr(0, imgLoc.length-7) + '.jpg';

    myElement.appendChild(myImg);
    // myElement.style.left = (e.offsetX + 10) + "px";
    // myElement.style.top = (e.offsetX + 10) + "px";

    e.target.addEventListener('mouseout', handler, false);

    e.target.addEventListener('mousemove', move, false);    

    function move(f) {
      console.log("moved!");
      myElement.style.left = (f.offsetX + 15) + 'px';
      myElement.style.top = (f.offsetY + 15) + 'px';
      // e.target.removeEventListener('mousemove', move, false);
    }

    function handler(d) {
      var myNode = d.target.parentNode.querySelector('div.preview');
      myNode.parentNode.removeChild(myNode);
      e.target.removeEventListener('mouseout', handler, false);
      e.target.removeEventListener('mousemove', move, false);
    }

  } // check to see that I clicked on IMG only
}, false); // click event

IMO it makes sense to define handler (for mouseout) and move (for mousemove) inside of dblclick event handler in this case, because executing these two functions only makes sense after dblclick event triggers its handler. 

Moveover, defining INSIDE dblclick event handler gives access the event object e.target, which allows you to remove event listener from it.

 

Caption

Last movie we learned how to deal with a new event, the mouse over. And it was pretty similar to the click event. But there's always something unique about the individual events. So if you notice, towards the end of the movie when you roll over some of these things, you've got multiple high-resolution versions showing up. And sometimes when you rolled over thesebig images, you would get these other errors. Like sometimes it would give you these empty images. And you would see these errors piling up, so we need to deal with the mouse out event, and we were going to learn how to do that in this movie, with a lot of event especially an event like mouse over you going to have to worry not just about the event itself, but any related events that might come up when you work with the JavaScript file, so lets go ahead and fix this.

I am going to add the event listener, now this time I am going to add the event listener inside this event listener. So this new event is only going to happen when a mouse over happens, so let's go ahead and do that and we'll put it right here and we will say, e.target.add event listener, and this time we're going to look for a mouse out event. And then we want to do a function right here. Now this time we're going to name this function. We're going to call it handler. And that'll be important in a minute, when we want to get rid of this new mouseout event.

I'll show you how that works in a minute. So I'm going to open up curly brackets here, and make sure I put a semicolon. Make sure I pass a false so this bubble properly. And here's what I want to do when I mouseout out of one of those thumbnails. First I need to get the element that I want to delete. So I'm going to say var the node that I want, so I'm going to say myNode. And this is going to be equal to the target parent node. And I named this event d so I want to make sure that I pass it along, d target parentNode.

And then I'm going to do a query selector to select the element that I want. What I want to get rid of is the div with the class of preview that I create. Okay and then what I want to do is remove that node so I'm going to say my node and again when I remove something I have to look for the period of that element so I just say my node.parentNode and then remove child mynode, so this is what I want removed. So let me go and save this and let's see if it that works.

Refresh this page, and when I roll over this images, only the image shows and everything looks pretty good. But there's actually a problem with this. You're not going to be able to tell, there's 19 errors happening. Let's click on those and see what they are, let's go ahead and close this. Actually, let me just go to the console itself because it'll show you something happening here. It says cannot read property of parentNode of null, let's see, let's take a look at the Elements panel, and take a look at our art on ordered list, list item and let's roll over this list item and see what's happening.

So, when is this error happening? When I roll over one of these images and I roll out. Notice that there's a lot of Errors happening. And there's actually, you can see that, the errors seem to be increasing exponentially. Let me refresh the page and I'll show this to you. So if I roll over here one time and I roll out, it won't have an error. If I roll out over it again, I get an error.And then if I do it again, roll over roll out, now I get three errors. So, what's going on? They seem to be increasing. Exponentially. What's happening here is that some of the events are still being called so what's happening is I get a mouseout event, and then the second time I roll over and I roll out, I'm getting two mouse out events.

So there's a bunch of events that are staying in the event queue. That are not being processed and that's what's causing this error. So we need to fix that by removing the events that we have in the queue. Events in JavaScript work by inserting themselves into a queue and they will remain there until they're needed. So if you don't remove some events, it's going to cause a problem like this. And it's sort of hard to figure out because it's not doing anything visually that shouldn't be working, so this all looks good. It's just that you're getting a bunch of errors and you don't even know it.

So here's how we're going to fix that, back into our code, so what we want to do here is remove the element, now I can use e.target or the word this if I want to, and say remove. The event listener, and I have to tell it what I want to remove, in this case it's going to be mouseout, and then I'm going to call the function that I created, remember I gave it a name earlier, and I didn't give this one a name, this one doesn't need one because the mouse over event doesn't need to be removed in this case.

So, we're just going to say mouseout and then call the function we created, handler. Then give it a false Boolean here, which is just going to match the same Boolean we specified down here to make sure that the event bubble properly. So all the things about the event have to match. The first part lets the function know which event you want to target so this has to match perfectly. We want to target the event that's created by this mouse over, and that's what we did to create the function right here.

And then we want to tell it what we want it to remove. So this mouseout calls this function called handler here. And that's what I need to use as the second parameter. And then the last parameter just has to match whatever we put down here. So, let's go ahead and save this, and we'll switch over. Refresh, and it's working just like before, but if we inspect element, we're not going to get any JavaScript errors whenever we roll over these elements, and that's really what we want. So, even though sometimes you don't see any errors visually with events, you've gotta be careful and always check your console.

If you didn't get rid of that element it would eventually generate some problems with memory that you may have not known but your users might definitely feel whenever a browser crashes because there's too many events in the queue.

document.querySelector('.grid').addEventListener('mouseover', function(e) {  // mouseover handler
  if (e.target.tagName === 'IMG') {

    var myElement = document.createElement('div');
    myElement.className = 'preview';
    e.target.parentNode.appendChild(myElement);

    var myImg = document.createElement('img');
    var imgLoc = e.target.src;
    myImg.src = imgLoc.substr(0, imgLoc.length-7) + '.jpg';
    myElement.appendChild(myImg);

    e.target.addEventListener('mouseout', function handler(d) {  // mouseout handler
      var myNode = d.target.parentNode.querySelector('div.preview');
      myNode.parentNode.removeChild(myNode);
      // e.target.removeEventListener('mouseout', handler, false);
    }, false);

  } // check to see that I clicked on IMG only
}, false); // click event

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值