I am using Google Apps Script to create a web app that contains several hyperlinks. When a hyperlink is clicked, it is supposed to trigger an alert box (just filler code to see if JS function is being called). My hyperlinks are being generated using this javascript function:
function updateAlertList(results) {
var div = document.getElementById('output');
div.innerHTML = '';
for (var i=0;i<results.length;i++)
{
div.innerHTML += '<p><a class="ra-button" href="javascript:void(0)" onclick="myJsFunc()">' + results[i].alertName + '</a></p>';
}
}
and the JS function that generates the alert is:
function myJsFunc(){
alert('this function was called');
}
For some reason, only the LAST hyperlink in the list of hyperlinks will trigger the JS function called myJsFunc. Whenever I click on any of the other hyperlinks that are earlier in the list, the JS function is not called. When I look in the console in Chrome Developer tools, I see the error "Cannot read property 'plugin_dispatchEvent___' of undefined"
Anybody know why the very last hyperlink in my list of hyperlinks works.. but the earlier ones don't?
I would change your code to this:
function updateAlertList(results) {
var div = document.getElementById('output');
div.innerHTML = '';
var alrtInnrHTML = '';
for (var i=0;i<results.length;i++) {
alrtInnrHTML += '<p><a class="ra-button" href="javascript:void(0)" onclick="myJsFunc()">' + results[i].alertName + '</a></p>';
console.log('alrtInnrHTML: ' + alrtInnrHTML);
}
}
div.innerHTML = alrtInnrHTML;
Please note that I created a variable alrtInnrHTML, and using += on the variable, not the innerHTML.
You are trying to use += on DOM manipulation instead of a variable. Set the HTML text string first, then inject the entire string just one time. Right now you are injecting HTML into the same DIV over and over and over again. Do all the links show up? In any case, even if your logic is working, I would change the logic to what I am suggesting, check that the final HTML content is correct with a console.log() output, and then inject the HTML all at once.
You would actually be better off adding individual <p> and <a> tags in each loop, and adding HTML in each loop rather than trying to construct a string of HTML.
You might want to do some reading about:
insertRow
insertCell
setAttribute
textContent
createTextNode
appendChild
createElement
With those methods you could avoid writing long HTML strings for the most part.
For example, you could create a table, with a new row for every result.
for (var i=0;i<results.length;i++) {
window.row1 = tblAlertList.insertRow(-1);
window.cell1 = row1.insertCell(0);
row1.setAttribute("class", "ra-button");
row1.innerHTML = <p><a class="ra-button" href="javascript:void(0)" onclick="myJsFunc()">' + results[i].alertName + '</a></p>';
}
That above code is just to give you an idea of what you might do, it's not working code.
Instead of creating a table, you could create an unordered list: <ul>
div.innerHTML = "<ul><a></a></ul>";
Then append a child to the last node in the list:
var node=document.createElement("LI");
var textnode=document.createTextNode("New Alert");
node.appendChild(textnode);
document.getElementById("myList").appendChild(node);
Related
I'm new in php programming. I'm in a very interesting moment.
let str = 'anytext';
line = document.createElement('p');
line.textContent = str;
alert('line = ' + line.textContent);
I tried to use and .textContent and .innerHTML and .innerText. Nothing. It refuses to display anything.
The alert shows that the value successfully assigned. No errors, but there is nothing displayed on
the screen of the browser. I mean, no paragraph element created visually.
I use javascript not in html document. I use it in php file.
The page has a table, which I created programmatically with php.
I thought I can solve this problem by sending the
$html = new DOMDocument('1.0','iso-8859-1');
with json_encode() and JSON.parse(); to javascript. But it didn't help too.
I don't know what else can I do. Can you help me?
You've created an element, but you haven't inserted it anywhere into the document. You need to figure out the appropriate place to put it into the DOM and then do so.
For example, if you have existing HTML of
<div class="main">
</div>
you can create a <p> and insert it to the bottom of the .main with
const main = document.querySelector('.main');
const line = document.createElement('p');
line.textContent = 'anytext';
main.appendChild(line);
Few days ago I had to write code quickly and added the bad code below.
<td class="note_box_con" onclick="getElementsByTagName('a')[0].click();">
After then, when I tried to use Text editor plugin written by Javascript, I found
Text editor plugin and the function of DOM collide into each other
Now I know what was the problem and solve it. But I cannot understand what kind of risk getElementsByTagName('a')[0].click(); has.
In my incomplete view, that code is just addEventlistener function().....
what kind of risk onclick="getElementsByTagName('a')[0].click();" has?
In my understanding, its a bad practice to do it this way. I would rather suggest you to use to fetch using classname or id.
If you are using some resource that adds anchor tags to your page, this will break your logic.
Following is a simulation:
var count = 0;
function addAnchor(){
var div = document.getElementById("content");
var str = "<a href='#'>" + count++ + "</a>";
div.innerHTML = str + div.innerHTML;
}
document.getElementsByTagName("a")[0].addEventListener("click", function(){
console.log(this.innerHTML);
return false;
})
<div id="content">
Test
</div>
<button onclick="addAnchor()">Add Link</button>
<a onclick="document.getElementsByTagName('a')[0].click()"> test </a>
Also, if there is a change in DOM structure, your code will not work properly. Best use a proper selector that uniquely identifies the element.
I am using an application where on change in the select box value my javascript function would be called. In the function I have an if/else statement. If the condition validates, it displays me a graph in my div, else it displays text in the same div.
var arrayDataSource = [];
//for example this array has the following [[1,0.2],[2,0],[3,1]
$.each(test, function(index, value)
{
//code to load data to that array
});
)
if(arrayDataSource.length > 0) {
//draw graph
} else {
document.getElementById('mydiv').innerHTML = "some text";
}
When I try to run the else condition my content gets overwritten as I am using an innerHTML to display text.
Do I have any other options to display text with javascript without using innerHTML? I have also seen some DOM functions and other relevant posts but nothing worked for me. My div properties should remain as they are even after the else condition.
Changing content in a div with JS without destroying its content you can simply use +=; instead of = only.
The code will be document.getElementById('overAllContainer').innerHTML += "some text";
Use insertAdjacentHTML instead of innerHTML as it does not reparse the element it is being used on and thus it does not corrupt the existing elements inside the element.
document.getElementById('overAllContainer').insertAdjacentHTML('beforeend', 'some text');
A better way to do it would be to append a new element with an attribute such as a class or an id to your overAllContainer in order to easily remove it when your selection changes.
You can do it via
document.getElementById('overAllContainer').insertAdjacentHTML('beforeend', '<p class="message">some text</p>');
Or via
var message = document.createElement('p');
message.setAttribute('class', 'message');
message.innerText = 'some text';
document.getElementById('overAllContainer').appendChild(message);
And then when you want to remove the message based on the selection changing,
document.querySelector('#overAllContainer .message').remove();
Use document.createTextNode:
var text = document.createTextNode("some text");
document.getElementById('mydiv').appendChild(text);
Please forgive me and let me know if my post is not right since I am brand new to this forum.
I have found most of the answer here (Create a <ul> and fill it based on a passed array), but my problem comes with .createTextNode. My users are using multiple editor boxes to build an outline. Within these boxes they can format the text (underline, color, bold, etc.). So the array items that I am passing to .createTextNode actually have HTML tags in them to format the line items. However .createTextNode makes it just plain text which in turn just spits out the tag instead of applying it when displayed via document.getElementById('foo').appendChild...
I know that I should stay away from HTML concatenation but it is looking very tempting.
Is there any way to retain the formatting of the list items when appended and displayed?
Thank you in advance for your assistance.
Try innerHTML, which will try to parse the content string as HTML structure. For example you have a P tag
<p id="asdf"></p>
<script>
document.getElementById('asdf').innerHTML = 'qwerty';
</script>
Will give you a clickable anchor
<p id="asdf">
qwerty
</p>
But be careful!!! (Notice I use three bang sign here) You must be sure there's no harmful code before you insert it. Check this example:
document.getElementById('asdf').innerHTML = '<img src="image.png" onload="alert(1)">'
You will see an alert dialog. This example is simple though, in practice it can be much more dangerous, e.g. dynamically append a cross site script into you page, aka XSS.
EDIT: here is a demo.
var options = ['Option 1','Option 2'];
function makeUL(){
var LIs = '';
for (i = 0; i < options.length; i += 1){
LIs += '<li>' + options[i] + '</li>';
}
return '<ul>' + LIs + '</ul>';
}
document.getElementById('foo').innerHTML = makeUL();
<div id="foo"></div>
The problem I'm having is that when I try to create a table via javascript, it is closing the table before I actually give the closing tag.
I'm using this solution to record/read cookies
https://stackoverflow.com/a/1960049
What I needed was to make a wishlist from this "array" of cookies, by looping through them all and putting them into a table. (inside the #catalog div)
function loopArray() {
var cookie = $.cookie("testCookie");
var items = cookie ? cookie.split(/,/) : new Array();
$('#catalog').empty();
$('#catalog').append("<table><tr><th>Part #</th><th>Delete</th></tr>");
for(var i=0;i<items.length;i++){
$('#catalog').append("<tr><td width='150'>"+items[i]+"</td><td><a href='javascript:;' onclick='remNum("+i+")'><img src='searchAssets/img/delete.png' /></a></td></tr>");
}
$('#catalog').append("</table>");
}
Not sure why this won't work. Tried cheating with innerHTML but that gave me problems, and I tried using document.write but when using the remNum function to remove the cookie value and refresh the list it completely wipes my whole page out.
This is what my table ends up looking like when I take out the code
<table><tbody><tr><th>Part #</th><th>Delete</th></tr></tbody></table><tr><td width="150">three</td><td><img src="searchAssets/img/delete.png"></td></tr>
You can't add partial mal-formed pieces of HTML with .append(). You have to add fully formed pieces of HTML. This line line $('#catalog').append("<table><tr><th>Part #</th><th>Delete</th></tr>"); is a real problem as it's only a piece of valid HTML and is invalid by itself.
What you can do is accumulate the string of partial HTML in your loop and just append the finished string once to the DOM at the end.
Or, you can add the fully formed HTML for the table, but with no rows and then insert a complete row at a time in your loop.
What you cannot do is append <table>, then some rows and then append </table> at the end. append creates WHOLE HTML objects so append <table> challenges the browser to make an entire object out of it or reject the whole thing.
For example, you can do it like this:
function loopArray() {
var cookie = $.cookie("testCookie");
var items = cookie ? cookie.split(/,/) : new Array();
var html = "<table><tr><th>Part #</th><th>Delete</th></tr>";
for(var i=0;i<items.length;i++){
html += "<tr><td width='150'>"+items[i]+"</td><td><a href='javascript:;' onclick='remNum("+i+")'><img src='searchAssets/img/delete.png' /></a></td></tr>";
}
html += "</table>";
$('#catalog').html(html);
}
What you are doing is wrong. .append doesn't work that way. You need to have the complete tag inside append, not partial content.
In your case I would suggest you put them as a string and append it at the end. See below,
$('#catalog').empty();
var tableContent = [];
tableContent.push("<table><tr><th>Part #</th><th>Delete</th></tr>");
for(var i=0;i<items.length;i++){
tableContent.push("<tr><td width='150'>"+items[i]+"</td><td><a href='javascript:;' onclick='remNum("+i+")'><img src='searchAssets/img/delete.png' /></a></td></tr>");
}
tableContent.push("</table>");
$('#catalog').html(tableContent.join('')); //using .html as you had it emptied earlier.