Search code examples
jquerydynamicreplacelive

How to alter dynamic/live element attributes - (replaceWith()) used


I am having a hard time wrapping my head around how to access and alter attributes of HTML content added in place of a placeholder element using replaceWith.

Here is the scenario:

Here is the HTML (kept in a php file) that replaces the '#null_item' element in the subsequent HTML table:

<tr id="sign_options">
	<td>
		<input class="finalSign" type="hidden" value="" name="item_name_1" />
		<figure class="sample">
			<a id="sign_preview_lightbox" href="" rel="lightbox" title="Sign preview">
				<img id="sign_preview" src="/signs/previews/basic_aluminium_spacer4_f.jpg" alt="Sign preview" title="Sign preview" />
			</a>
		</figure>
	</td>
</tr>

if(localStorage['cartItem']) {
  $.get("/cart.php", function(data) {
    $('#null_item').replaceWith($(data));//fix this 'replaceWith' kak!
  });
}

console.log(signPreview);
console.log(document.getElementById('sign_preview').src);
<table id="quote">
  <colgroup>
    <col id="sign_col" span="1"><col id="options_col" span="1"><col id="qty_col" span="1"><col id="price_col" span="1"><col id="total_col" span="1">
  </colgroup>
  <th>Sign</th><th>Options</th><th>Qty</th><th>Price</th><th>Total</th>

  <tr id="null_item"><td><span class="italic">Empty</span></td><td></td><td></td><td></td><td id="delivery" class="subtotal">S$0</td></tr>
  <tr id="totals"><td></td><td></td><td colspan="2"><span class="boxed">Total signs</span></td><td>S$0</td></tr>
  <tr id="totals"><td></td><td></td><td colspan="2"><span class="boxed">Delivery</span></td><td>S$0</td></tr>
  <tr id="totals"><td></td><td></td><td colspan="2"><span class="boxed">Installation</span></td><td>S$0</td></tr>
  <tr id="discount"><td colspan="2">Discount code <input maxlength="7" class="discountCode" value="" onchange="calculateTotals()" name="discount_code"></td><td colspan="2"><span class="boxed">Discount</span></td><td>-S$0</td></tr>
  <tr id="grand_total"><td></td><td></td><td colspan="2"><span class="boxed">Grand total</span></td><td>S$0</td></tr>
  <tr id="buy_row"><td colspan="4"><img id="secure" src="/img/payment.png" alt="Secure payment via Paypal" title="Secure payment via Paypal"></td><td><input id="buy_now" class="buy_button" type="submit" name="submit" value="BUY NOW" alt="PayPal . The safer, easier way to pay online." onclick="paypalPasser()" /></td></tr>
</table>

The first block of HTML successfully replaces the intended '#null_item' tr, but after that, I cannot replace the scr for the '#sign_preview" img, nor can I read any existing src link.

Can anyone shed light? I know that for events one has to use the .on function and target the new element, but I don't know how to use that method to alter attributes of dynamically loaded elements.


Solution

  • I think the only thing you're maybe not wrapping your head around is the idea of callbacks and asynchronous methods.

    You're currently running your console.log statements before the replaceWith occurs.

    The function() { } block (your "callback") passed as the second parameter to $.get doesn't execute until the AJAX call to the server completes; the rest of your code following the call to $.get continues to run immediately.

    Try this, to see the effect:

    console.log('About to $.get');
    if(localStorage['cartItem']) {
      console.log('$.get()ing...');
      $.get("/cart.php", function(data) {
        $('#null_item').replaceWith($(data));//fix this 'replaceWith' kak!
        console.log('$got!');
        console.log(document.getElementById('sign_preview').src);
      });
    }
    console.log('After $.get()');
    

    The output will be:

    About to $.get
    $.get()ing...
    After $.get()
    ...
    $got!
    <the value of .src>
    

    So basically, you were trying to access an element before it existed. If you want to run code as a result of the AJAX method, it should be in, or called from, the callback.

    Here's how I would rewrite it:

    $.get("/cart.php").done(function(data) { 
        $('#null_item').replaceWith(data);
        // further processing
    }).fail(function(xhr, status, message) { 
        // handle failures
        alert('Ouch, an error occurred! ' + message);
    });