2

Because I'm generating my content dynamically, and it doesn't exists in the document until the scripts execute, normal element selectors don't apply.

<div class="list">
    //generated elements within here
    <p data-key="0" >List Item 1</p>
    <p data-key="1">List Item 2</p>
    //generated elements within here
</div>

So this does not work(note this is the same idea as above just with different names):

Category = 0;

$(".list > p").click(function(){
    var thisKey = $(this).data("key");
    for (var i = 0; i < ServiceArray[Category][thisKey][2][1][1].length; i++) {

        var listId = ServiceArray[Category][thisKey][2][1][i][2];
        var listTitle = ServiceArray[Category][thisKey][2][1][i][0];
        var List = "";

        for (var x = 0; x < ServiceArray[Category][thisKey][2][1][i][2].length; x++) {
            var Time = ServiceArray[Category][thisKey][2][1][i][2][x][3];
            var Content = ServiceArray[Category][thisKey][2][1][i][2][x][0];
            var Hours = ServiceArray[Category][thisKey][2][1][i][2][x][4];
            List += '<div class="li"><div class="selection"></div><p data-time="' + Time + '">' + Content + '<span class="orange"> ('+ Hours +'Hrs)</span></p></div>';
        }

        $(".layer4").append('<div id="' + listId + '" class="listContainer"><h2>' + listTitle + '</h2><div class="ListWrapper">' + List + '</div></div>');
    }
});

Instead, I have to use

$(".dropdown-service").on("click" ,"p",function () {
    //all the stuff up there, in here, except in here, I can't use $(this).data("key") to get my array keys.
});

So how can I select the elements to use their attached data in the function?

Remember, $(".list > p") won't successfully select the element, since it was not generated until after the document loaded. I don't fully understand this yet, but in a previous question, it was explained as being the issue; this is a secondary issue, that arose from that question's solution.

Here is that question.

Here is a JSFiddle.

Community
  • 1
  • 1
  • A variable to replace the `ServiceArray[Category][thisKey][2][1]` would really do wonders for your code readability. – Blue Skies Dec 09 '13 at 03:30
  • if `dropdown-service` is an ancestor of `.list > p` then `$(".dropdown-service").on("click" ,".list > p",function () {..});` should work – Arun P Johny Dec 09 '13 at 03:31
  • 2
    Did you try using `this` in the bottom event handler, as it should reference the `p` element and do exactly what you say it doesn't – adeneo Dec 09 '13 at 03:31
  • Sorry about the readability @BlueSkies - I'll be more careful with that. –  Dec 09 '13 at 03:32
  • also in the fiddle there are lot of code... can you place only the relevant code there – Arun P Johny Dec 09 '13 at 03:32
  • also I can see you are adding a click handler within another `$(".dropdown-service > p").click(function () {..})` within `$(".dropdown-category > p").click(function () {..});` it is a bad idea – Arun P Johny Dec 09 '13 at 03:33
  • @ArunPJohny Sorry, it's not a child, I just edited the question a bit, mentioning that the second example is the same idea as the first one, but with names from my actual script. The first one I made simple. –  Dec 09 '13 at 03:34
  • 1
    Maybe `$(this).data(...)` doesn't work because there is no data attached to the newly created elements? I really don't know want to go through all that code... – Felix Kling Dec 09 '13 at 03:35
  • 1
    can you atleast point us to the function that is creating the `p` elements and where the `data` is assigned to it – Arun P Johny Dec 09 '13 at 03:38
  • @FelixKling Of course, I don't expect you to, I just added it so no one would ask. The problem is basic, I can't use `$(parent > p).click(function(){ var dataKey = $(this).data("key"); });` on my list because the list was generated dynamically. So I have to use `$(".dropdown-service").on("click" ,"p",function () { var dataKey = $(this).data("key"); });` The only problem there is that I have no idea how to use that method to get the dataKey from the clicked element's attached data. –  Dec 09 '13 at 03:40
  • 2
    Again, you'd do it exactly as you have written, as the paragraph is the context of the handler, you'd do `$(this).data('key')`, as long as the element has any data to get. – adeneo Dec 09 '13 at 03:42
  • @ArunPJohny line 630 `ChangeService();` generates it –  Dec 09 '13 at 03:44
  • You don't have to change the body of the event handler to make it work with event delegation. You cannot bind the handler to the element because it doesn't exist yet. Event delegation solves this by attaching the event handler to an ancestor instead. However, when the handler is *executed*, i.e. one of the elements was clicked, then obviously the element must exist (otherwise it cannot be clicked). That's why `$(this).data('key')` should work and if it doesn't, the problem must be somewhere else. – Felix Kling Dec 09 '13 at 03:44
  • @adeneo I can't do that, because only the parent is selected in `$(".dropdown-service").on("click" ,"p",function () { var dataKey = $(this).data("key"); });` while the data is actually attached to the p elements within it. –  Dec 09 '13 at 03:45
  • No. `this` refers to the `p` element. jQuery makes sure of that: *"When jQuery calls a handler, the `this` keyword is a reference to the element where the event is being delivered; for directly bound events this is the element where the event was attached and for delegated events this is an element matching `selector`."* http://api.jquery.com/on/ – Felix Kling Dec 09 '13 at 03:47
  • You're not really getting how the delegated event handler works, it sets `this` to the element in the selector after the event, in this case `p`, and not `.dropdown-service`, so `this` will be the `p` element – adeneo Dec 09 '13 at 03:47
  • @FelixKling Right, but $(this) is talking about $(".dropdown-service") and no longer $(".dropdown-service > p") where the data is located. There's no data on $(".dropdown-service") itself. So, are you saying that I can use, inside, $(".dropdown-service > p") as the selector? Since I selected the parent element for event delegation, does the child element suddenly now work with it's usual selector? –  Dec 09 '13 at 03:48
  • Please read my previous comments. – Felix Kling Dec 09 '13 at 03:48
  • Ahh, ok. Yes, I'm misunderstanding then.. Hmm. Well, I don't know then. –  Dec 09 '13 at 03:48
  • That's why I'm saying the problem/error must be somewhere else, if `$(this).data(...)` doesn't work for you. – Felix Kling Dec 09 '13 at 03:50
  • Ok, I'll look more into it, and post a better question if I need to. –  Dec 09 '13 at 03:50
  • 2
    seems to be working fine http://jsfiddle.net/arunpjohny/PYAAf/1/ click on the dropdown and check the console – Arun P Johny Dec 09 '13 at 03:52
  • 1
    Just so I understand, have you actually tried the suggestions given above to use `$(this).data("key");`? – Blue Skies Dec 09 '13 at 03:54
  • Yes, it does appear to be elsewhere.. An unusual issue here. Sorry. –  Dec 09 '13 at 03:55
  • @BlueSkies Yes, that's what I'm doing, the issue seems to be something else in my script. –  Dec 09 '13 at 03:55
  • @jt0dd so can we assume the issue is resolved.... for further question create a fiddle which reproduces your exact issue... don't create one with all your code from the page – Arun P Johny Dec 09 '13 at 03:58
  • My apologies, I was told before that I should include everything, which didn't quite make sense, but anyway, will provide simplified examples from now on. I did pinpoint my problem, can you look at this? `$(".dropdown-service").on("click" ,"p",function () { $(".welcomeWrapper").hide(); });` line 700 JS Fiddle. That one line refuses to run, even alone like that. –  Dec 09 '13 at 04:16
  • `$(".welcomeWrapper").hide();` I mean, refuses to run. More clearly, It doesn't run when called by the function. If I call it manually, it works. –  Dec 09 '13 at 04:16

0 Answers0