2

Aspiring developer and first time posting a question to StackOverflow. Researched the topic but couldn't find an exact answer to my question.

  1. Background:

    • Modifying this static shopping cart, to accept dynamically created list item. https://tutorialzine.com/2014/04/responsive-shopping-cart-layout-twitter-bootstrap-3

    • Trying to insert a new item to the shopping cart via span tag, span tag information will be dynamically provided by another function.

    • For testing purpose I'm using a button to insert the new item to the shopping list.

    • The shopping cart has popover event to "Modify / Delete" individual items lists

  2. Question: I can't figure out the exact JavaScript / jQuery command to attach the popover event. All static items in the list have the popover event automatically attached but the dynamically created items do not.

    • I tried using the addEventListener(); but the jQuery doesn't get attached properly.

    • My initial assumption was if the dynamically created list items had the same "class" as the static items that the popoever event would be automatically applied to them as well.

    • Tried these solutions but didn't work out for me, the popover event doesn't get attached properly.

    a. Event binding on dynamically created elements? Event binding on dynamically created elements?

    b. Attach event to dynamically created chosen select using jQuery Attach event to dynamically created chosen select using jQuery

    c. Attaching events after DOM manipulation using JQuery ajax Attaching events after DOM manipulation using JQuery ajax

  3. Here's the HTML and JavaScript:

var qrcodelist = document.getElementById('qrdemo_list');

function myFunction() {
// HTML for testing when device is not connected: comment out when device is connected
var x = document.getElementsByClassName("decode-value-offline")[0].innerHTML;

// Qty and Price text values
var qty_text = 1;
var price_text = '$150';

// Create li 
var entry_li = document.createElement('li');
entry_li.setAttribute("class", "row");

// Create quantity span     
var qty_span = document.createElement('span');
qty_span.setAttribute("class", "quantity");
qty_span.appendChild(document.createTextNode(qty_text));

// Create price span     
var price_span = document.createElement('span');
price_span.setAttribute("class", "price");
price_span.appendChild(document.createTextNode(price_text));

// Create pop btn span
var popbtn_span = document.createElement('span');
popbtn_span.setAttribute("class", "popbtn");
popbtn_span.setAttribute("data-original-title", "");
popbtn_span.setAttribute("title", "");
//popbtn_span.addEventListener( );

// Create a tag inside pop btn
var popbtn_a_span = document.createElement('a');
popbtn_a_span.setAttribute("class", "arrow");
popbtn_span.appendChild(popbtn_a_span);

// Create item span and text node     
var item_span = document.createElement('span');
item_span.setAttribute("class", "itemName");

// Append span to li
entry_li.appendChild(qty_span);
entry_li.appendChild(item_span);
entry_li.appendChild(popbtn_span);
entry_li.appendChild(price_span);

// Create text node and insert qr-code result to li span
item_span.appendChild(document.createTextNode(x));

// Get list node and insert 
var list_node = document.getElementById("qrdemo_list").lastChild;
// alert(list_node);
qrdemo_list.insertBefore(entry_li, qrdemo_list.childNodes[3]);

// Write x to console log
console.log(x);
}

// Popover JavaScript 
$(function() {
  var pop = $('.popbtn');
  var row = $('.row:not(:first):not(:last)');


  pop.popover({
    trigger: 'manual',
    html: true,
    container: 'body',
    placement: 'bottom',
    animation: false,
    content: function() {
      return $('#popover').html();
    }
  });


  pop.on('click', function(e) {
    pop.popover('toggle');
    pop.not(this).popover('hide');
  });

  $(window).on('resize', function() {
    pop.popover('hide');
  });

  row.on('touchend', function(e) {
    $(this).find('.popbtn').popover('toggle');
    row.not(this).find('.popbtn').popover('hide');
    return false;
  });

});
<!-- Shopping Cart List HTML -->

<div class="col-md-7 col-sm-12 text-left">
  <ul id="qrdemo_list">
    <li class="row list-inline columnCaptions">
      <span>QTY</span>
      <span>ITEM</span>
      <span>Price</span>
    </li>
    <li class="row">
      <span class="quantity">1</span>
      <span class="itemName">Birthday Cake</span>
      <span class="popbtn"><a class="arrow"></a></span>
      <span class="price">$49.95</span>
    </li>
    <li class="row">
      <span class="quantity">50</span>
      <span class="itemName">Party Cups</span>
      <span class="popbtn"><a class="arrow"></a></span>
      <span class="price">$5.00</span>
    </li>
    <li class="row">
      <span class="quantity">20</span>
      <span class="itemName">Beer kegs</span>
      <span class="popbtn"><a class="arrow"></a></span>
      <span class="price">$919.99</span>
    </li>
    <li class="row">
      <span class="quantity">18</span>
      <span class="itemName">Pound of beef</span>
      <span class="popbtn"><a class="arrow"></a></span>
      <span class="price">$269.45</span>
    </li>
    <li class="row">
      <span class="quantity">1</span>
      <span class="itemName">Bullet-proof vest</span>
      <span class="popbtn" data-parent="#asd" data-toggle="collapse" data-target="#demo"><a class="arrow"></a></span>
      <span class="price">$450.00</span>
    </li>
    <li class="row totals">
      <span class="itemName">Total:</span>
      <span class="price">$1694.43</span>
      <span class="order"> <a class="text-center">ORDER</a></span>
    </li>
    <li class="row">
      <!-- QR Code Images -->
      <span class="itemName"><img src="img/AppleQRCode.png" width="100" height="100"></span>
      <span class="price"><img src="img/OrangeQRCode.png" width="100" height="100"></span>
    </li>
    <li class="row">
      <!-- device offline testing span -->
      <span class="decode-value-offline">Unknown</span>
    </li>
    <li class="row totals">
      <!-- Button to insert qr-code result to list -->
      <span class="order"><a class="text-center" onclick="myFunction()">Insert</a></span>
      <span class="itemName">Insert QR Code Result</span>
    </li>
  </ul>
</div>

<!-- Popover HTML -->

<!-- The popover content -->

<div id="popover" style="display: none">
  <a href="#"><span class="glyphicon glyphicon-pencil"></span></a>
  <a href="#"><span class="glyphicon glyphicon-remove"></span></a>
</div>

<!-- JavaScript includes -->

<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/js/customjs.js"></script>

Appreciate the great support in advance and please contact me if additional information is needed for clarification.

2 Answers2

0

You need to delegate jquery function to the HTML elements created dynamically like this:

Change your following line

var pop = $('.popbtn');
var row = $('.row:not(:first):not(:last)');

like given here:

var pop = $(document).find('.popbtn');
var row = $(document).find('.row:not(:first):not(:last)');
Himanshu Upadhyay
  • 6,220
  • 1
  • 13
  • 32
  • Hi! Really appreciate the reply. Tried the above change but didn't work out for me. Here's the result I get when viewing from Firefox Developer Edition. Static content (Birthday Cake) has "EV" indicated but Dynamic content (Unknown) via "insert button" doesn't. http://oi68.tinypic.com/33kf820.jpg – Teddy Matayoshi Jul 13 '17 at 05:44
0

JSFiddle of Fix: https://jsfiddle.net/0phz61w7/

The issue is that you need to delegate the event. Please do the following:

Change:

pop.on('click', function(e) {
    pop.popover('toggle');
    pop.not(this).popover('hide');
});

To:

$(document).on('click', '.popbtn', function(e) {
    pop.popover('toggle');
    pop.not(this).popover('hide');
});

Also, you need to remove the } from line 54, just after console.log(x);. That is throwing an error.

The above modification works, but in the code provided, .popbtn is not visible because the node is empty. So in the jsfiddle provided, I added a CSS rule to include the text POPBTN. Click that and an alert I added to the click event fires.

Pegues
  • 1,543
  • 1
  • 17
  • 35
  • And inside the new delegated event, add a `console.log` to see if, when clicking `.popbtn`, that the click event is recognized. If the click event is then recognized, that means there is then something wrong with `pop.popover('toggle')` or `pop.not(this).popover('hide')` that needs to be looked at. – Pegues Jul 13 '17 at 10:49
  • Issue with your code: Line 54, you have a closing `}` without an opening curly bracket - this is just after `console.log(x);` That should be removed. – Pegues Jul 13 '17 at 10:54
  • Hi! Appreciate the reply. I messed up on the javascript and didn't include the button click function. Updated the above code. Do you think you can rework the jsFiddle code to accomodate this change? Tried myself but couldn't reproduce the desired results. Thank you very much. var qrcodelist = document.getElementById('qrdemo_list'); function myFunction() { – Teddy Matayoshi Jul 13 '17 at 12:23
  • Almost there I think, after modifying the code as suggested I see the event's attached via Firefox / Firebug. Here's a screen shot. http://oi63.tinypic.com/a4wsvq.jpg The "Clicked" alert fires but the popover will not appear for the "Unknown" list item added by the button. Will keep on working on this. Thank you very much. – Teddy Matayoshi Jul 13 '17 at 12:45