some reason Cannot read property addEventListener of null - addeventlistener

I got this error. I tried to dinamicly add some html tags by JS.. And there is a ID name is well what I need for addEventListener. But I dont know how to fix it.. If I change '#answer-' + i to .answers is working.. But this is not solution because I could click for any button without get the clicked ID..
Questions.prototype.displayQuestion = function() {
let answer = [];
questionDOM.innerHTML = this.question;
let correct = this.correct;
for(let i = 0; i < this.answer.length; i++){
answer.push(
`
<div id="answer-${i}" class="answer">
<h5>${this.answer[i]}</h6>
<div class="check"></div>
</div>
`
);
document.querySelector('#answer-' + i).addEventListener('click', function() {
if(i === correct) {
document.querySelector('#answer-' + correct).classList.add('animate__animated', 'animate__heartBeat');
} else if (i !== correct) {
document.querySelector('#answer-1').classList.add('animate__animated','animate__headShake')
}
})
}
answerDOM.innerHTML = answer.join('');
}
index.html
<body>
<div class="container">
<div class="question">
<div class="questionbox animate__animated animate__bounce">
<h2 id="question"></h2>
</div>
</div>
<div class="answers"></div>
</div>
<script src="app.js"></script>

You are pushing to your answers array but not actually adding the nodes to the dom. You want to do something like document.body.innerHTML += answer[i] before you try to get the element by id. I can also see that your loop won't execute because the length of answer is initially zero before you add to it within the loop. You need to add to answer before the loop or change the loop condition to <= this.answer.length <--- but that is an infinite loop

Related

GAS PropertiesService to Save and Return Sort Order

QUESTION
How can I use PropertiesService to store an array from index.html, send the array to code.gs, and return the array in index.html?
SPECIFIC CASE
In a Google Web App, I have a group of sortable lists (made using JQuery UI Sortable). I want to save the most recent order/position of each li. I'm attempting to have that order/position "persist" when the page is refreshed or closed.
EXAMPLE
If you see the default Sortable, you could change the order of the items. If you refreshed the page, or closed it and return, the items would be in their original order.
WHERE I'M HAVING TROUBLE
I am able to get the array to show up in the console, but I don't know how to get it back to code.gs. I think I am now, but I'm not sure. Beyond that, I don't know how to "read" that PropertiesService so that the array is returned to index.html. I'm not really sure what I'm doing so if someone could slow walk me it would be appreciated!
ALTERNATIVES
I also looked into writing directly to the spreadsheet where the values originate. I'm not really sure how to do that either. I made some attempts, and was able to get "undefined" as a value in a spreadsheet cell.
FULL CODE (note: the list items are formed using an array, so they will not show up here): https://jsfiddle.net/nateomardavis/Lmcjzho2/1/
PARTIAL CODE
code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('index');
}
function webAppTest() {
getTeamArray();
}
function getTeamArray() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName('TEST');
var range = sheet.getRange(2, 1, 1000, 1);
var values = range.getValues();
var teamsArray = [];
for (var i = 0; i < values.length; ++i) {
teamsArray.push(values[i][0]);
}
var uniqueArray = [];
uniqueArray.push(teamsArray[0]);
for (var i in teamsArray) {
if ((uniqueArray[uniqueArray.length - 1] != teamsArray[i]) && (teamsArray[i] !== "")) {
uniqueArray.push(teamsArray[i]);
}
}
return uniqueArray;
}
function savePositions(myProperty, positions) {
PropertiesService.getScriptProperties().setProperty("myProperty", JSON.stringify(positions));
};
function getPositions() {
var returnedObj = PropertiesService.getScriptProperties()
};
index.html
<body>
<div id="myList" class="connectedSortable">MY LIST</div>
<table id=table1>
<div id="team1">
<p>TEAM 1</p>
<br>
<div id="group" v>SELECTED</div>
<ul id="team1s" name='team1s' class="connectedSortable"></ul>
<div id="group">ALTERNATE</div>
<ul id="team1a" name='team1a' class="connectedSortable"></ul>
</div>
</table>
<table id=table2>
<div id="team2">
<p>TEAM 2</p>
<br>
<div id="group" v>SELECTED</div>
<ul id="team2s" name='team2s' class="connectedSortable"></ul>
<div id="group">ALTERNATE</div>
<ul id="team2a" name='team2a' class="connectedSortable"></ul>
</div>
</table>
<table id=table3>
<div id="team3">
<p>TEAM 3</p>
<br>
<div id="group" v>SELECTED</div>
<ul id="team3s" name='team3s' class="connectedSortable"></ul>
<div id="group">ALTERNATE</div>
<ul id="team3a" name='team3a' class="connectedSortable"></ul>
</div>
</table>
<table id=table4>
<div id="team4">
<p>TEAM 4</p>
<br>
<div id="group" v>SELECTED</div>
<ul id="team4s" name='team4s' class="connectedSortable"></ul>
<div id="group">ALTERNATE</div>
<ul id="team4a" name='team4a' class="connectedSortable"></ul>
</div>
</table>
<script>
$(function() {
google.script.run.withSuccessHandler(buildOptionsList)
.getTeamArray();
});
function buildOptionsList(uniqueArray) {
var div = document.getElementById('myList');
for (var i = 0; i < uniqueArray.length; i++) {
var ul = document.createElement('ul');
var li = document.createElement('li');
var cLass = li.setAttribute('class', 'ui-state-default');
var iD = li.setAttribute('id', uniqueArray[i]);
li.appendChild(document.createTextNode(uniqueArray[i]));
div.appendChild(ul);
div.appendChild(li);
}
}
$(function() {
$("#myList, #team1s, #team1a, #team2s, #team2a, #team2s, #team3s, #team3a, #team4s, #team4a").sortable({
connectWith: ".connectedSortable",
update: function(event, ui) {
var changedList = this.id;
var order = $(this).sortable('toArray');
var positions = order.join(';');
console.log({
id: changedList,
positions: positions
});
//Instead of using JSON to save, can I use the spreadsheet itself to save the positions and then pull it from there as I did with "buildOptionsList" above?
function saveList() {
google.script.run.savePositions("myProperty", JSON.stringify(positions));
JSON.parse("myProperty");
}
}
})
});
$(function getPositions(event, ui) {
var changedList = this.id;
var order = $(this).sortable('toArray');
var positions = order.join(';');
console.log({
id: changedList,
positions: positions
});
});
</script>
</body>
</html>
It's also possible to just use the browser's localStorage client side.
localStorage.setItem('id', positions); //Store positions in users browser
localStorage.getItem('id'); //Retrieve the stored positions later
Notes:
For this to work, the url(document.domain of the iframe="*.googleusercontent.com") from which your script is deployed must remain constant. During my brief testing, it was constant even when changing from /dev to /exec of the parent(script.google.com) and even during version update. But there's no official reference.
This solution is better than properties service, if you have multiple users, as each one will have their own data stored in their own browsers and there are no server calls during each change.
Using google.script.run simple example:
<script>
function sendStringToServer() {
var string=$('#text1').val();
google.script.run
.withSuccessHandler(function(s){
alert(s);
})
.saveString(string);
}
</script>
Google Script:
function myFunction() {
PropertiesService.getScriptProperties().setProperty('MyString', string);
return "String was saved in Service";
}
Client to Server Communication

Asp.net Div tags in a for loop

Is it possible to include div tags within a for loop in an asp.net page and assign its id dynamically so that I can refer a particular div tag with the assigned id in a jquery script.
I want to do something like below.
#for(var i = 0; i < projectCountGlobal; i++)
{
<div id="i" > // id should be assigned dynamically
<div id="ProjectImage">
</div>
<div id="ProjectName">
</div>
<div id="Experts">
<div id="ExpertImage">
</div>
<div id="ExpertName">
</div>
</div>
</div>
}
From the snippet it seems like you are doing razor view so you can simply do like this,
<div id="#i" >
that shall do the trick.
i you can do this using following code snippet:
$('.topopup').hover(function () {
for (var i = 0; i < 5; i++) {
$('body').append('<div id=' + i + '>a</div>');
}
})
// HTML code on page
<body>
Click Here
<div id="toPopup" style="display:none;">
<div id="popup_content">Rahul Deshmukh</div>
<div id="backgroundPopup"></div>
<div id="containerDiv"></div>
</div>
</body>
here i am appending div inside body tag for this you need to add min.js also in your peoject folder
here "topopup" is a anchor tag and on the mouse over of this anchor tag, i am adding div inside body tag.

How to get the value of the element selected in ListView JQUERYMOBILE

Hi i'm developping a simple listView that lists the column "firstname" of my table : i want to get the selected value (name) , i found this link but it shows he how to get the index and not the value of the selected item http://jsfiddle.net/w2JZU/
here's my code :
HTML:
<div id="popup-bg">
</div>
<div id="popup-box">
<div data-role="page" id="home">
<div data-role="header">
<h1>Players</h1>
</div>
<div data-role="content">
<ul data-role="listview" id="artiste" >
</ul>
</div>
</div>
</div>
</section>
js :
function successCB()
{
db.transaction(queryDB, errorCB);
}
function queryDB(tx)
{
tx.executeSql('SELECT * FROM Players ', [], querySuccess, errorCB);
}
function querySuccess(tx, results)
{
var len = results.rows.length;
var dataset= results.rows;
$("#artiste").empty();
for (var i = 0; i < len; i++)
{ item = dataset.item(i);
$("#artiste").append( "<li data-theme='c'><a href='game.html'>
<img src='images/avatar.jpg'><h3>"+item['firstName']+"</h3></a></li>" );
}
There isn't a "value" for an item in a list using the li tag. However, you can get the text of what's in that list element using the jQuery .text() method. I've modified the jsfiddle you referenced to do exactly that: http://jsfiddle.net/Cht2e/
You might want to consider adding another attribute to the li tag, such as data-name (you can make up the attribute) and then you can get that via the jQuery .attr() method. For example, you might change you append code to do:
$("#artiste").append( "<li data-theme='c' data-name='"+item['firstName']+"'><a href='game.html'>
<img src='images/avatar.jpg'><h3>"+item['firstName']+"</h3></a></li>" );
And then attach your click handler like this:
$('#artiste').children('li').on('click', function () {
alert('Selected Name=' + $(this).attr('data-name'));
});
I don't think this is necessarily the best structure or approach to take, but it will accomplish what you're asking.

Trying to use an index in a razor for loop

I have the following code:
#{
var index=0;
}
#foreach (AdminSummary adminSummary in #Model.AdminSummaries) {
index++;
<div class="rep_tr0">
<div class="rep_td0">#adminSummary.RowKey</div>
<div class="rep_td0">Edit</div>
<div class="rep_td0">Delete</div>
<div class="rep_td0">#Html.TextBox("position_" index, #adminSummary.Position, new { size = 5 })</div>
<div class="rep_td0">#adminSummary.Title</div>
<div class="rep_td0">#adminSummary.DetailCount</div>
<div class="rep_td0">#adminSummary.Modified</div>
<div class="rep_td0">#adminSummary.ModifiedBy</div>
</div>
}
I am trying to find a good way to add an index value to the position name.
But this keeps giving me the error: CS1026: ) expected for the line with position_ on
Does anyone have any idea what I might be doing wrong?
Update:
I tried the following:
<div class="rep_td0">#Html.TextBox("position_"#(index), #adminSummary.Position, new { size = 5 })</div>
This gave the error: CS1646: Keyword, identifier, or string expected after verbatim specifier: #
Try
<div class="rep_td0">#Html.TextBox(string.Format("position_{0}", index), #adminSummary.Position, new { size = 5 })</div>
<div class="rep_td0">#Html.TextBox("position_"+ index.ToString(), #adminSummary.Position, new { size = 5 })</div>
just replace this line with above.
Try wrapping your inserted razor in ()
Example
Also, sometimes if you are in a razor block, the compiler requires you to wrap html if it is the only thing on the line,like div tags, in
<text><div class="rep_tr0"></text>
EDIT: Sorry, misread the question a little, after index++
string textBoxId = "position_" + index;
THEN:
<div class="rep_td0">#Html.TextBox(#textBoxId, #adminSummary.Position, new { size = 5 })</div>
Nice, but instead #foreach(), try use #for(), then your loop has its own index.

Dynamically create divs with incremented id using jquery

I have a text
I want to append multiple divs but the id should be changed dynamically.
e.g:
<div id=first>text</div>
<div id=first0>text</div>
<div id=first1>text</div>
<div id=first2>text</div>
<div id=first3>text</div>
<div id=first4>text</div>
<div id=first5>text</div>
Any help? thanks..
Your title and question content seem to disagree with each other. I am assuming you are wanting to create div's where each id sequentially increments each time one is created?
$(function(){
var count = 0;
$('#append').click(function(){
$('#parent').append('<div id="first'+count+'">text</div>');
count++;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="append">Add DIV</a>
<div id="parent"></div>
You can change it with .attr():
$('#first').attr('id', 'first6')
try to change the code to :
<div id="first">text</div>
<div id="first0">text</div>
<div id="first1">text</div>
<div id="first2">text</div>
<div id="first3">text</div>
<div id="first4">text</div>
<div id="first5">text</div>
dont forget the id inside " " (id="first" not id=first)
now you can simply use jquery : $("#first").attr('id','first6');
If you were interested in how styling works.`
$(function(){
for (let i = 0 ;i < 10; i ++){
$('#foo').append('<div id="first'+i+'">text</div>');
}
});
#first4 {
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo"></div>
Create a div with id=Container and the create 5 divs dynamically using following code
//using JavaScript
for(var i=0;i<5;i++){
var obj = document.getElementById("container");
obj.innerHTML += '<div id="first'+i+'"></div>';
}

Resources