chrome app click event on class not working in appendChild elements

1,143 views
Skip to first unread message

Kelly

unread,
Mar 2, 2015, 12:47:31 PM3/2/15
to chromi...@chromium.org
This is my first chrome app.  I did work through the chrome app 'hello world' and 'todo' tutorial apps.

The code i'm trying to implement has been working as a standard web app, so the js/jquery/html is valid in a web context tested with firefox/chrome/opera/safari.

I have 2 issues I don't understand.
1. js document.querySelector('.class').addEventListener("click", function)  on a class only works when the first instance of the class is clicked,
   yet the jquery $('.class').click(function(){});  does work.   Why???  Is the jquery call crawling through the DOM and setting the event listener on each instance of the class, but the querySelector is not?  I tried querySelectorAll, but that does not seem to be recognized in Chrome App API.

2. When I use the appendChild to add some html links to reference selected pics, i also add buttons to allow removal of the selection.
   Since the elements are not there at window.onload, setting the eventListener("click", function) does not work.  At the end of the addPic function where the appendChild code is working i put document.querySelector('.rmvbtn').addEventListener("click", rmvPic);
This shows up as a valid event when I 'inspect element' in the debugger, but it gives an error:
Refused to execute inline event handler because it violates the following Content Security Policy directive: "default-src 'self' chrome-extension-resource:

It is acting as though i used an inline 'onclick' js call.

Should I put this back in the window.onload js function and somehow re-load the page with the new appended html elements?  This re-load is not required in the normal web app.

PhistucK

unread,
Mar 2, 2015, 1:24:48 PM3/2/15
to Kelly, Chromium Apps
Regarding 1 - querySelector gives you the first element in the document with such class, $(".class") gives you all of the elements in the document with such class, so that may explain it.
querySelectorAll gives you all of the elements with such class, but you need to do something like Array.prototype.forEach.call(document.querySelectorAll(".class"), function (e) { e.addEventlistener("click", handler) }); in order to add event listeners to all of them.

Regarding 2 - it sounds like a bug. If you can provide a reduced test case (a small application that only does that and fails due to an error), I can inspect it.


PhistucK

--
You received this message because you are subscribed to the Google Groups "Chromium Apps" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-app...@chromium.org.
To post to this group, send email to chromi...@chromium.org.
Visit this group at http://groups.google.com/a/chromium.org/group/chromium-apps/.
For more options, visit https://groups.google.com/a/chromium.org/d/optout.

Kelly

unread,
Mar 2, 2015, 1:33:08 PM3/2/15
to chromi...@chromium.org, k...@kayceesoftware.com
Thanks, I'll try your suggestion on #1, I presumed that jquery must be doing the code to set the event on all items it found.
On #2, I will work up a reduced test case to submit here. 

Today i started reading on IndexedDB for my next step to store the pic links that are selected.  The tutorials referenced in HTML5ROCKS seem to be dead links, do you have any suggestions, documentation and examples seem to be VERY hard to find related to ChromeApps.  I just started writing js and jquery about a month ago and there are lots of examples and questions related to general web apps.

PhistucK

unread,
Mar 2, 2015, 1:36:05 PM3/2/15
to Kelly, Chromium Apps
IndexedDB should be the same for regular web pages and Chrome applications, so any documentation you find regarding regular web pages should be relevant to Chrome applications.


PhistucK

Kelly

unread,
Mar 2, 2015, 3:44:34 PM3/2/15
to chromi...@chromium.org, k...@kayceesoftware.com
I tried your suggestion on #1 and it did not work. so I just did a var x = querySelectorAll('.class');
then a loop for x.length addEventListener('click', function);   AND it works.  I'n not sure why the Array.prototype.forEach.call did not work.


On Monday, March 2, 2015 at 11:24:48 AM UTC-7, PhistucK wrote:

Kelly

unread,
Mar 2, 2015, 3:46:49 PM3/2/15
to chromi...@chromium.org, k...@kayceesoftware.com
On #2.  i tried it without the jquery and got the same type error:  Uncaught TypeError: Cannot read property 'previousElementSibling' of undefined

<html>
<head>
  <title>kcTst</title>
  <script src="main.js"></script>
  <script src="jquery-2.1.3.min.js"></script>
</head>

<body>
        <div id='inputTst' >Code
          <input type='text' id='BarCode' autofocus value="" />
         </div>
           <div class="imgbox" id="imgbox1">
             <a href=# id='122' name='122' class="itmLink">
              pic122</a><br>
             </div>
           <div class="imgbox" id="imgbox1">
             <a href=# id='777' name='777' class="itmLink">
              pic777</a><br>
             </div>

          <div id="itemList" class="lineItems">
         <TABLE ID=CSHTBL>
          <tbody id=ItmBody>
         </TABLE>
          </div>
</body>
</html>

js file:
window.onload = function() {

 var x = document.querySelectorAll('.itmLink');
 var i;
 for (i = 0; i < x.length; i++){
   x[i].addEventListener("click", linkClick);
 }
 
};
  // FINISHED ONLOAD FUNCTION ----------------------------

var Qty = 1;

function linkClick(){
  document.querySelector('#BarCode').value = this.id;
        addItmDiv();
      };

function addItmDiv() {
     var x = document.getElementById("BarCode");
     x.style.backgroundColor = 'red';
     var ITM = x.value;
   var namItm = "Itm" + ITM;
   var namQ   = "Nam" + Qty;
     var pNode = document.getElementById("ItmBody");
     var trNode = document.createElement('tr');
     trNode.setAttribute("id", namItm);
     trNode.setAttribute("class", "rmv");
     trNode.innerHTML = "<td id='cbtn'><a href=#><img src='/trash.png' alt='X'></a></td>";
   pNode.insertBefore(trNode, pNode.childNodes[0]);
     var nmNode = document.createElement('td');
     nmNode.setAttribute("id", namQ);
     nmNode.setAttribute("class", "TiTl");
     var txt = "<a href=#>" + namItm + "</a>";
     nmNode.innerHTML = txt;
   trNode.appendChild(nmNode);
     var qtyNode = document.createElement('input');
     qtyNode.setAttribute("id", "IQty");
     qtyNode.setAttribute("value", "1");
   trNode.appendChild(qtyNode);
     var upNode = document.createElement('a');
     upNode.setAttribute("id", "upQ");
     upNode.setAttribute("class", "upbtn");
     upNode.innerHTML = "+";
   trNode.appendChild(upNode);
   Qty += 1;
   document.querySelector('.upbtn').addEventListener("click", upQTY);
  }

function upQTY() {
 var qty = parseInt($(this.activeElement.previousElementSibling).val());
     qty += 1;
     $(this.document.activeElement.previousElementSibling).val(qty);

}

On Monday, March 2, 2015 at 11:24:48 AM UTC-7, PhistucK wrote:

PhistucK

unread,
Mar 2, 2015, 4:00:39 PM3/2/15
to Kelly, Chromium Apps
I accidentally typed addEventlistener instead of addEventListener, that might be the issue. Sorry.


PhistucK

Kelly

unread,
Mar 2, 2015, 8:26:14 PM3/2/15
to chromi...@chromium.org, k...@kayceesoftware.com
I changed the upQTY function to:
function upQTY() {
 var qty = parseInt(this.previousElementSibling.value);
     qty += 1;
     this.previousElementSibling.value = qty;
}

this.document.activeElement.previousElementSibling  was valid in the web based version,
but .document.activeElement  is not?  this.previousElementSibling is working.
I'll accept this, but at some point I would like to understand WHY.
Thanks MUCHO PhistucK.

PhistucK

unread,
Mar 3, 2015, 2:29:20 AM3/3/15
to Kelly, Chromium Apps
I do not recommend using this in a non object bound function (meaning, in a function that is not a method of some object instance). In that context, this may implicitly be global scope (window, in browsers), unless you call it differently (using .call, .apply, .bind or by adding it as an event listener, which gives the scope of the element to which you add that event listener).
Also, document is also defined in the global scope, so just start with document instead of window.document or this.document. They are redundant.

In this case, this.document.activeElement was not working because this was the element to which you added the event listener and not window.


PhistucK
Reply all
Reply to author
Forward
0 new messages