Welcome Guest, Not a member yet? Register   Sign In
Applying jQuery to Dynamically Created Elements
#1

[eluser]Fielder[/eluser]
Can a jQuery and/or ajax expert help me out?
To summarize, my jQuery is loaded on pageload. However the <div id="store_body"> referenced in the jQuery has not yet been created. It is created dynamically when the grid is finally create through a means of AJAX, and displayed back to the user. But when displayed back to the browser, the <div id="store_body"> is not hidden as I've asked it to be in my initial jQuery load.

What you will see is in my view at the very end is I've created a couple of static <div>s just to test that the jQuery works correctly. The
<div><image id="button_showstore" src="../../../assets/images/icons/shape_square_edit.png" /></div>
that acts as the button and
<div id="store_body">Information here</div>
as what I want to hide. This is loaded as part of the initial pageload, so I have to think it has something to do with the dynamically created <div>.

If anyone can give me some more ideas, I've tried everything and have come up with nothing.
Oh, and no errors or problems reported in firebug.

When the page loads it loads my
jquery.js
Code:
$(document).ready(function() {
        
        $("#store_body").hide();
        
        $("#button_showstore").click(function() {
            $("#store_body").slideToggle("fast");
        });
});

For those of you familiar with xajax, I'm using xajax to dynamically create my output table.
store_form.php
Code:
$xajaxgrid = $this->xajaxgrid->createGrid($con_id);
                
                $objResponse->Assign("div_table", "innerHTML", $xajaxgrid);
                $objResponse->Assign('multistore_exclusive', 'checked', false);
                $objResponse->Assign("div_submit", "innerHTML", "");

My grid is created as such and sent back to the store_form.php and displayed to the user.
xajaxgrid.php library
Code:
function addRow($table, $data, $edit=TRUE, $delete=TRUE, $divName="grid", $fields=NULL)
    {
        
        $nameRow = $divName."Row".$data[0]; // <tr id="gridRow".multistore_id>
        $row = '<tr id="'.$nameRow.'" class="'.$this->rowStyle.'" >';
        
        $inc = 0;

        foreach ($data as $key => $value)
        {
            $nameCell = $nameRow."Col".$inc;
            if($key != 'id')
            {
                $row .= '<td id="'.$nameCell.'">'.$value.'</td>';
            }                  
               $inc++;
        }
        if ($edit)
        {
            $editStore = "editRow".$data[0];
            $row .= '<td align="center" width="5%"><a href="[removed]void(0);" id="button_showstore"><img id="button_showstore" src="../../../assets/images/icons/shape_square_edit.png" /></a></td>';
            
            $editRow = $this->editRow($data[0]);
        }
        
        $row .= '</tr>';
        
        if (isset($editRow))
        {
            $row .= $editRow;
        }
        
        $this->rows .= $row;
        
        if ($this->rowStyle == "row0")
        {
            $this->rowStyle = "row1";
        }
        else
        {
            $this->rowStyle = "row0";
        }
        
    }
    
    function editRow($multistore_id)
    {
        $editStore = "editRow".$multistore_id;
        
        $editRow = '<tr><td colspan="5">';
        
        $editRow .= '<div id="store_body">'.$this->editRow_contents($multistore_id).'</div>';
        
        
        $editRow .= '</td></tr>';
        
        return $editRow;
    }
    
    function editRow_contents($multistore_id)
    {
        $form = $multistore_id;
        
        return $form;
    }

    function render()
    {
        $grid = $this->top . $this->header . $this->rows . $this->footer;
        
        return $grid;
    }
my view
Code:
&lt;?=form_open('contractstore_form/postback', $form_attributes); ?&gt;
    <table class="selectBox">
        <tr>
            <td>&lt;?=$storename_name_dropdownlist?&gt;</td>
            <td><div id="div_store_number">&lt;?=$div_store_number?&gt;</div></td>
            <td><div id="div_store_upscode">&lt;?=$div_store_upscode?&gt;</div></td>
        </tr>
        <tr>
            <td class="table_footer">Store Name</td>
            <td class="table_footer">Store Number</td>
            <td class="table_footer">UPS Code</td>
        </tr>
        <tr>
            <td></td>
            <td>
                <li>&lt;input type="checkbox" name="multistore_exclusive" id="multistore_exclusive" value="1" /&gt;&lt;label for="multistore_exclusive">Check for Exclusivity</label></li>
            </td>
            <td class="button">
                <li><div id="div_submit"></div>
            </td>
        </tr>
        <tr class="empty">
            <td colspan="3"></td>
        </tr>
    </table>
    <div><img id="button_showstore" src="../../../assets/images/icons/shape_square_edit.png" /></div>
    <div id="store_body">Information here</div>
    <div id="div_table"></div>
&lt;/form&gt;
#2

[eluser]slowgary[/eluser]
Why use Javascript to hide it? That's what CSS is for:
Code:
#store_body {
     display: hidden;
}

If you have this declaration already in your CSS, the element will be added to the DOM but already hidden, so no additional JavaScript will be necessary. For that matter, why even append the 'store_body' div with javascript when it's hidden anyways? Couldn't it just be part of your page to begin with (just hidden)?

If for some reason you need to do it with JavaScript, you should be able to do it in the AJAX callback. I've never used xajax, so I'm not sure how that works. Why not use jQuery's ajax method? So easy...
Code:
$(document).ready(function(){
     $.post(
          'server-script.php',
          {param1 : value, param2 : value, param3 : value},
          function(data){
               var new_element = $("<div id='store_body'>" + data.property + "</div>");
               new_element.css('display', 'none');
               $(body).append(new_element);
          },
          'json'
     );
});

Something like that would work. You could probably also rely on jQuery's live() method. So instead of:
Code:
$("#store_body").hide();
You would do:
Code:
$("#store_body").live('load', function(){
     $(this).hide();
});

It really doesn't make sense to do this though as you could just as easily (and with less overhead) have already declared this in your CSS.

Hope this helps.
#3

[eluser]Thorpe Obazee[/eluser]
[quote author="slowgary" date="1245665234"]Why use Javascript to hide it? That's what CSS is for:
Code:
#store_body {
     display: hidden;
}
[/quote]

AFAIK, it's "display: none"
#4

[eluser]slowgary[/eluser]
!!! LOL. I've been writing CSS for YEARS!!! Yeah, that was pretty stupid of me. I need to get some sleep.
#5

[eluser]jdfwarrior[/eluser]
Long weekend and its still waaaayyyy too early in the morning, so.. looking through your code would only fry my brain right now, but would loading the js at the bottom of the page fix something like this?

slowgary's idea of using the live method would probably work too. I can't confirm that though, at the moment I'm doing good to know what jQuery is.. wow.
#6

[eluser]Wuushu[/eluser]
Use the .live method outlined below. jQuery doesn't automatically bind events to dynamically added elements, unless you specify them with the .live method, introduced in 1.3
#7

[eluser]slowgary[/eluser]
Right, but he's not binding an event listener, he's just trying to .hide() something that's not there.

Fielder, when you call a method in jQuery, it looks for the element(s) matched against the selector and does it's work on them. If there aren't any matching elements, it doesn't sit around waiting for one to be born. If you are binding an event listener however, jQuery has the .live() method which actually does sit around watching for any new DOM elements so that it can bind the event listener. In your case, you don't really want an event listener bound, you just want to hide it... so the idea is to just bind an event listener to the 'load' event, which triggers as soon as the element gets injected into the DOM.

I still think that it's a bad way of doing things, you're using JS to handle something that CSS does perfectly. Also, there's a high likelihood that in many browsers you will see the '#store_body' element pop into existence then disappear, especially in a slow browser like IE. Using native CSS would be much faster and less complicated, and I can't think of any good reason you couldn't already have that specified in your CSS, I'm sure you just hadn't thought of it yet (and you haven't even had the chance to reply to these posts).
#8

[eluser]Fielder[/eluser]
slowgary, your explanation of css vs. jquery makes sense to me. In fact, I did have <div id="store_body" style="display: none;"> in there initially and it did hide it when it was created - which is great and what I want. But how do I get it to unhide when the user clicks on the edit <img>? That's where I figured I'd use the jQuery slidetoggle to unhide and hide it as needed by the user (plus the smooth hide/unhide animation is kinda nice)?

Can I do a click action of some sort in css to unhide it?
#9

[eluser]slowgary[/eluser]
Sure. Same way you did the hide...
Code:
$("#button_showstore").bind('click', function(){
     $("#store_body").show();  //or use .show('slow') / .fade('slow') / .slideDown('slow') to see an effect
});
#10

[eluser]jdfwarrior[/eluser]
jQuery has built in methods for manipulatings css

Code:
$("object").click(function() {

  $("other-object").css({ "display", "block" });

});

Or slowgary's method works as well.. Smile




Theme © iAndrew 2016 - Forum software by © MyBB