Answered by:
Dom manipulation problem

Question
-
One of my function creates some divS and buttons inside them. Then I want to gather those buttons when the app starts. My code is as follows but I cannot get references of those buttons in JavaScript, although I can see them on HTML page. What am I missing?
part of code in a navigation template project that creates buttons:
for (var i = 0; i < counter; i++) { str = dataArray[i].timerName; str1 = str.slice(1, str.length - 1); console.log(str1); message += str1 + "\n"; var newDiv = document.createElement("div"); var newBt = document.createElement("button"); newBt.id = str1 + "Bt"; var btValue = document.createTextNode(str1); newBt.appendChild(btValue); newDiv.appendChild(newBt); listDiv.appendChild(newDiv); }
In another function I want to get references of those buttons:
var buttons = document.querySelector("#timerList"); console.log("tier: " + buttons.id); var allButtons = buttons.querySelectorAll("div"); var bFound = (allButtons == null) ? "No matches found" : allButtons.length; console.log(bFound); for (var i = 0; i < bFound; i++) { console.log(allButtons[i].id); allButtons[i].addEventListener("click", function () { console.log(allButtons[i].value); }, false); }
Friday, April 19, 2013 8:10 PM
Answers
-
I've created a blank app to test this. my default html looks like this:
<body> <div id="timerList"></div> </body>
my default.js like this (I had to assume some values for dataArray, counter and message ...)
app.onactivated = function (args) { if (args.detail.kind === activation.ActivationKind.launch) { if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { // TODO: This application has been newly launched. Initialize // your application here. } else { // TODO: This application has been reactivated from suspension. // Restore application state here. } var dataArray = [{ timerName: "1abc2" }, { timerName: "2def3" }, { timerName: "3ghi4" }]; var counter = dataArray.length; var listDiv = document.getElementById("timerList"); var message = ""; for (var i = 0; i < counter; i++) { var str = dataArray[i].timerName; var str1 = str.slice(1, str.length - 1); console.log(str1); message += str1 + "\n"; var newDiv = document.createElement("div"); var newBt = document.createElement("button"); newBt.id = str1 + "Bt"; var btValue = document.createTextNode(str1); newBt.appendChild(btValue); newDiv.appendChild(newBt); listDiv.appendChild(newDiv); } var buttons = document.querySelector("#timerList"); console.log("tier: " + buttons.id); var allButtons = buttons.querySelectorAll("button"); var bFound = (allButtons == null) ? "No matches found" : allButtons.length; console.log(bFound); for (var i = 0; i < bFound; i++) { console.log(allButtons[i].id); allButtons[i].addEventListener("click", function (evt) {console.log(evt.target.textContent);}, false); } args.setPromise(WinJS.UI.processAll()); }
This code works for me.
- Marked as answer by Matt SmallMicrosoft employee, Moderator Monday, April 22, 2013 3:23 PM
Friday, April 19, 2013 10:10 PM
All replies
-
You are creating markup like this at runtime:
<div id="timerList"> <div> <button id="someTextBt">someText</button> </div> <div> <button id="someOtherTextBt">someOtherText</button> </div> </div>
Your first selector
document.querySelector("#timerList");
selects the outer div.
The second selector
var allButtons = buttons.querySelectorAll("div");
selects the div's that surround the buttons, not the buttons themself. In order to get the buttons, you have to change it to:
var allButtons = buttons.querySelectorAll("button");
This gives you an array of buttons. The next issue is that you're accessing your counter loop (i) in your event handler:
allButtons[i].addEventListener("click", function () { console.log(allButtons[i].value); }, false);
This doesn't work because at the time when your event handler (console.log(allButtons[i].value);) get's called i has a value of bFound. In order to get the element that caused the click, you have to write something like this:
allButtons[i].addEventListener("click", function (evt) {console.log(evt.target.textContent);}, false);
In addition, I changed your .value to .textContent because that's how you get the text of a button.
Hope that helps!
Friday, April 19, 2013 9:11 PM -
I have changed my code as your suggestions. But still I don't get reference to buttons inside that div.
var allButtons = buttons.querySelectorAll("buttons");
console.log(allButtons); // gives 0. Though there are two buttons inside that main timer div.
Friday, April 19, 2013 9:57 PM -
please remove the "s" in buttons:
var allButtons = buttons.querySelectorAll("buttons");
it should be
var allButtons = buttons.querySelectorAll("button");
Friday, April 19, 2013 10:00 PM -
Yes, ofcourse, that was a typo error. But still the problem is same.Friday, April 19, 2013 10:07 PM
-
I've created a blank app to test this. my default html looks like this:
<body> <div id="timerList"></div> </body>
my default.js like this (I had to assume some values for dataArray, counter and message ...)
app.onactivated = function (args) { if (args.detail.kind === activation.ActivationKind.launch) { if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { // TODO: This application has been newly launched. Initialize // your application here. } else { // TODO: This application has been reactivated from suspension. // Restore application state here. } var dataArray = [{ timerName: "1abc2" }, { timerName: "2def3" }, { timerName: "3ghi4" }]; var counter = dataArray.length; var listDiv = document.getElementById("timerList"); var message = ""; for (var i = 0; i < counter; i++) { var str = dataArray[i].timerName; var str1 = str.slice(1, str.length - 1); console.log(str1); message += str1 + "\n"; var newDiv = document.createElement("div"); var newBt = document.createElement("button"); newBt.id = str1 + "Bt"; var btValue = document.createTextNode(str1); newBt.appendChild(btValue); newDiv.appendChild(newBt); listDiv.appendChild(newDiv); } var buttons = document.querySelector("#timerList"); console.log("tier: " + buttons.id); var allButtons = buttons.querySelectorAll("button"); var bFound = (allButtons == null) ? "No matches found" : allButtons.length; console.log(bFound); for (var i = 0; i < bFound; i++) { console.log(allButtons[i].id); allButtons[i].addEventListener("click", function (evt) {console.log(evt.target.textContent);}, false); } args.setPromise(WinJS.UI.processAll()); }
This code works for me.
- Marked as answer by Matt SmallMicrosoft employee, Moderator Monday, April 22, 2013 3:23 PM
Friday, April 19, 2013 10:10 PM -
I'm fetching dataArray from a file read function. Inside that I've created those divs and buttons. May be it's something to look for. Thanks a lot for help though.
- Edited by SonalMac Friday, April 19, 2013 10:34 PM
Friday, April 19, 2013 10:33 PM