Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$.clone doesn't clone delegated events #73

Open
AVGP opened this issue Dec 10, 2015 · 22 comments
Open

$.clone doesn't clone delegated events #73

AVGP opened this issue Dec 10, 2015 · 22 comments
Labels

Comments

@AVGP
Copy link

AVGP commented Dec 10, 2015

This test fails but should not:

    var element = $.create("div", { class: "parent",  contents: "This is the parent" });
    element._.delegate("click", "p", function() {
      done();
    });

    var child = $.create("p");
    element.appendChild(child);

    var clone = $.clone(element);

    var ev = document.createEvent("MouseEvent");
        ev.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    clone.childNodes[1].dispatchEvent(ev);
@guoguo12
Copy link
Collaborator

I believe it works if you do $.create("p", {}). $.create("p") creates a text node, so it won't match the selector "p" in the delegate call.

@guoguo12
Copy link
Collaborator

Oh, I see there was more discussion about this in #70. @LeaVerou, can you verify what I just wrote?

@AVGP
Copy link
Author

AVGP commented Dec 10, 2015

@guoguo12 You're right about the glitch with the text node, but the event still doesn't fire.

        var element = $.create("div", { class: "parent",  contents: "This is the parent" });
    element._.delegate("click", "p", function() {
      done();
    });

    var child = $.create("p", {});
    element.appendChild(child);

    var clone = $.clone(element);

    var ev = document.createEvent("MouseEvent");
        ev.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    clone.childNodes[1].dispatchEvent(ev);

And either I'm really blind today, or it won't even work using addEventListener on the clone when bliss is used:

var parent = document.createElement("div");
var child = document.createElement("span");

parent.appendChild(child);

var clone = parent.cloneNode(true);

clone.addEventListener("click", function() {
  done();
});

var ev = document.createEvent("MouseEvent");
ev.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
clone.querySelector("span").dispatchEvent(ev);

Nota bene: This JSFiddle demonstrates that this code should be okay.

@guoguo12
Copy link
Collaborator

@AVGP: Hmm, interesting. Are you saying it only fails during the Karma test?

@AVGP
Copy link
Author

AVGP commented Dec 10, 2015

Yes. It's weird, isn't it?

Here's yet another sample of what works:

<!doctype html>
<html>
  <body>
    <div id="test">
      <p>Click me</p>
    </div>
    <script src="bliss.min.js"></script>
    <script>
      var original = document.getElementById("test");

      original._.delegate("click", "p", function() {
        alert("OK");
      })

      var clone = $.clone(original);

      var ev = document.createEvent("MouseEvent");
      ev.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
      clone.querySelector("p").dispatchEvent(ev);

    </script>
  </body>
</html>

@zdfs
Copy link
Collaborator

zdfs commented Dec 10, 2015

Are you sure that's the only <p> tag on the page when you run that code?

@AVGP
Copy link
Author

AVGP commented Dec 10, 2015

@zdfs I don't see how that matters here?
The only <p> elements are the one in the original element and in the clone.
clone.querySelector only matches on the descendants of clone anyway... do I misunderstand how delegate works?

@zdfs
Copy link
Collaborator

zdfs commented Dec 10, 2015

I see it now. Sorry. I was worried for a second that maybe the delegated event wasn't actually being called. I need more coffee.

@AVGP
Copy link
Author

AVGP commented Dec 10, 2015

No worries, I just wanted to make sure I'm not missing the elephant in the room ;-)

@zdfs
Copy link
Collaborator

zdfs commented Dec 10, 2015

What about adding actual contents to the p tag. In my local testing, this seems to work.

@zdfs
Copy link
Collaborator

zdfs commented Dec 10, 2015

This:

var element = $.create("div", { class: "parent",  contents: "This is the parent" });
element._.delegate("click", "p", function() {
  done();
});

var child = $.create("p", { contents: 'test' });
element.appendChild(child);

var clone = $.clone(element);

var ev = document.createEvent("MouseEvent");
    ev.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
clone.childNodes[1].dispatchEvent(ev);

@AVGP
Copy link
Author

AVGP commented Dec 10, 2015

@zdfs Yes, that, too, works in a normal page but not in Karma... what the heck?

@zdfs
Copy link
Collaborator

zdfs commented Dec 10, 2015

Weird. It's working in Karma for me.

@zdfs
Copy link
Collaborator

zdfs commented Dec 10, 2015

You're passing the done parameter, right?

@dperrymorrow
Copy link
Collaborator

Probably unrelated, but might make your life easier when dealing with DOM items.
Have you tried out using HTML fixtures? That way you can just load up whatever HTML you want and not have to create it all manually with JS for each test.

https://github.com/LeaVerou/bliss/blob/gh-pages/tests/CoreSpec.js#L4-L14
https://github.com/LeaVerou/bliss/blob/gh-pages/tests/fixtures/core.html

@zdfs
Copy link
Collaborator

zdfs commented Dec 10, 2015

@AVGP - Is this still relevant? I just merged your PR.

@AVGP
Copy link
Author

AVGP commented Dec 10, 2015

@zdfs unfortunately yes.

I'll try later if HTML fixtures work or if it's just my local Karma + Chrome Beta combination that behaves weird...

@zdfs zdfs added the tests label Dec 11, 2015
@LeaVerou
Copy link
Owner

Regarding the $.create() issue:

  1. This is exactly why we shouldn't be using Bliss methods in tests, apart from the one being currently tested.
  2. I wonder if the mistake hints that the API is confusing. Especially since, I didn't even notice it when I first read the code! Treating plain strings as text nodes is certainly useful inside $.contents(), but not sure about $.create(). Think about it: If there's a second parameter, it creates an element. If there's only one, but it's an object, it creates an element. If there's NO parameter, it still creates an element. And if there's one, which is a string, it creates a text node?! I think it's internally inconsistent and we need to change it and move the text node logic to $.contents() instead. Thoughts?

@guoguo12
Copy link
Collaborator

Agreed. It's currently way too confusing.
On Dec 11, 2015 12:30 PM, "Lea Verou" [email protected] wrote:

Regarding the $.create() issue:

  1. This is exactly why we shouldn't be using Bliss methods in tests,
    apart from the one being currently tested.
  2. I wonder if the mistake hints that the API is confusing. Especially
    since, I didn't even notice it when I first read the code! Treating plain
    strings as text nodes is certainly useful inside $.contents(), but not
    sure about $.create(). Think about it: If there's a second parameter,
    it creates an element. If there's only one, but it's an object, it creates
    an element. If there's NO parameter, it still creates an element. And if
    there's one, which is a string, it creates a text node?! I think it's
    internally inconsistent and we need to change it and move the text node
    logic to $.contents() instead. Thoughts?


Reply to this email directly or view it on GitHub
#73 (comment).

@zdfs
Copy link
Collaborator

zdfs commented Dec 11, 2015

Agreed.

@LeaVerou
Copy link
Owner

Done. :)

@LeaVerou
Copy link
Owner

Apart from the $.create() issue, is the actual bug reported here still valid? If not, we should close this.

@LeaVerou LeaVerou reopened this Dec 24, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants