Delimiting four nested items in Javascript/Html - javascript

Okay this is frustrating me to no end. I recently coded a page in JS for a buddy of mine who wants to display wedding pictures to a family to see which ones they'd like to purchase.
I used a for loop to count 1-904:
for (beginnum=1;beginnum<=904;beginnum++) { yada yada...
Then, I used adobe bridge to rename the camera files to be 1-904 and their thumbnails (1-904 + _thumb) and used the loop number to display 904 image spaces, and the correctly numbered picture:
[note:using <) in place of the usual open tag since the site wont display it]
IE...
document.write(beginnum + ":" + "<img src='pictures" + beginnum + "_thumb.jpg' />");
Opera...
document.write("<div>" + beginnum + ":" + "<img src='pictures" + beginnum + "_thumb.jpg' /></div>")
This all works perfectly in IE and Opera (with external CSS modifying the div to not line break).
I then created a function to call up the large version of the picture when clicked on.
The problem is, when I try and nest this function into the JavaScript generated HTML I would need four delimiters. I've heard ''' or """ or the &+numeric; work in some cases as a third and fourth but I can't seem to get them to work... where I run into a problem is here...
[note:again using <) for open tag]
document.write("<a href='javascript:void(0); onClick=
Since I've already used up " and ' I now have nothing left to use to call the function when a picture is clicked.
I usually don't ask for any help, but this time I can't think of anything else that should work... I assume maybe using JS to generate the HTML leaves me with ONLY 2 delimiters that will be recognized by the browser but I am not sure, anyone know for sure? Any fixes anyone can think of?
Thanks,
~Z~

Maybe this will work
for (i=0; i<904;i++)
{
document.write("<div class=\"DivClassName\"><img src=\"pictures_" + i + "thumb.jpg\" onclick=\"OpenAWindowAndDisplayTheBigPhoto(" + i + ")\"></div>");
}
Another approach: Suppose you put everything inside a <DIV id="mainDIV">
var mainDIV = document.getElementByID("mainDIV");
var div, img, a;
for (i=0; i<904; i++)
{
div = document.createElement("DIV");
div.className = "DivClassName";
a = document.createElement("A");
a.href = "javascript:void(0)";
a.onclick = function() {OpenAWindowAndDisplayTheBigPhoto(i);};
img = document.createElement("IMG");
img.src = "pictures_" + i + "thumb.jpg";
mainDIV.appendChild(div);
div.appendChild(a);
a.appendChild(img);
};

Try building the string one piece at a time instead of trying to build the whole literal for the document.write.
Whenever things get too convoluted to follow, just do one part at a time.
var s;
s = "'Hello.' ";
s += '"I must be going."';

Without seeing code it is hard to say for a fact, but you may want to take more advantage of the fact that javascript is a first-class language, so you can create functions and pass them as arguments to other functions, or have functions return functions.
By doing this, you can decompose your page into something that sounds a bit more manageable.
Also, take advantage of the onclick event.
You should be able to simplify the javascript and so avoid this problem, IMO.

Related

How can I use innerText instead of innerHTML in dynamically created HTML elements?

I use Javascript to dynamically create a lot of elements. Divs, images, spans, etc.
Here is an example piece of code that my JS would run:
infoCell.innerHTML = "Submitted by " + "<a href='/user/" + this.poster + "'><img src='" + this.poster_avatar_src + "' class='avatarimg'> <span style='color:blue'>" + this.poster + "</span> </a>in " + "<span style='color:blue; font-weight: 900;'><a href='/h/" + href + "'>" + this.topic + "</a></span>"
This was written early in my JS development, but now I realize that it can very quickly become very insecure, as almost all of the javascript variables being inserted into the HTML are written by the user with no limitations to character usage, etc.
How can I go through my javascript and change all of these so they still function, but without worrying about users inserting script into my site?
I am fine rewriting a lot but I would like to not do this again. I have about 90 innerHTML DOM modifications in my main JS file (typescript).
you could try to use a combination of document.createElement and HTMLElement.append
an example for the first <a> tag:
function makeElem (tagname, properties) {
let elem = document.createElement(tagname);
for (const key in properties) {
elem[key] = properties[key];
}
return elem;
}
infoCell.append("Submitted by ");
let a = makeElem("a", {href:'/user/"' + this.poster + '"'});
a.replaceChildren(makeElem("img", {'src':this.poster_avatar_src, 'className':'avatarimg'}), makeElem("span", {'textContent':this.poster,'style':'color:blue;'}));
infoCell.append(a);
this might not be the easiest but it should work, the reason for the "makeElem" function is purely convenience and you don't necessarily need it
There are a few approaches.
One is to use a sanitizer to translate all of the dynamic values into properly escaped strings before interpolation - but you'd have to be sure you get it right, otherwise there could still be problems.
Another way is to construct the element structure, then insert the dynamic strings at the appropriate points, eg:
const cell = document.createElement('div');
cell.innerHTML = `
Person info
<div class="name"></div>
<div class="age"></div>
`;
cell.querySelector('.name').textContent = name; // where name is dynamic
cell.querySelector('.age').textContent = age; // where age is dynamic
But this can be tedious if you have a lot of dynamic values to insert.
A third way (and one that I'd recommend for serious applications) is to use a framework to handle it for you. For example, in React, the above "cell" could be made like:
const Cell = ({ name, age }) => (
<div>
Person info
<div class="name">{name}</div>
<div class="age">{age}</div>
</div>
);
It takes some learning and getting used to, but once you get going it's a lot easier to read and write than other approaches.

Correct way to convert your JavaScript function into a string so it can be inserted into innerHTML

This is what I am doing: I am building a fun in house API Voting System. I am using a client side snippet insert onto page
Like this:
<script src="domain.com/api/scripts/main.js"></script>
<div id="content-wrap" id="ac1e435e-c564-48f8-9f45-338616e7a789"></div>
Now in my main .JS I do all ajax request and modify the #content-wrap with creating new elements and inserting additional JS required to run Voting System.
However big issue I am experiencing is when I write JavaScript that I need to insert into #content-wrap I am currently writing it like this:
script.innerHTML = "$(someting).on('click', funciton(){"
+ "$.ajax({type: 'post',"
+ " url: '" + base + "/api/request', data: $('form').serialize(), "
+ "success: function(response){";
As you can see that can cause lot of issues as I build on it.
What is better way to accomplish this or is there a way i can just write my script / code and do something like this.
script.innerHTML = ConvertToString(script.js) OR ConvertToString(function X);
ConvertToString is just an expression I am using to explain what I would like to do instead of what I am doing.
Thank you, I am open to any suggestions.
I also must do this in plain JavaScript or with jQuery library so any suggestions to use VueJs, AngularJS or React will be considered as future references.
Thank you again
Additional explanation:
I would like to insert into my script element JavaScript snippet. But my snippet is about 30 lines long currently and might get bigger with time so it is very difficult to code with all the + " code " on every line that I write so that it can be inserted with innerHTML into element and executed on Client end.
So I would instead like to do something like this
element.innerHTML = mysnippetcode // but with out using + "" on each line like shown above
OR
element.append(snippet)
I hope this makes it little more clear
Solution that worked for me was using back ticks to wrap my sinppet and insert it into innerHTML of the element..
Just use the function's name without the () to convert it to a string:
function foo() {
var a = 10;
var b = 20;
var c = a + b;
return c;
}
document.write(foo);
The document.write will result in this string:
function foo() { var a = 10; var b = 20; var c = a + b; return c; }
If you only want the function's body, then you could just normally remove the first and last characters of the string.
I am not entirely sure this is what you wanted, if not, please make yourself more clear.
Alternatively, you could do an eval([insert function code here]) and there would be no need to add the code to the innterHTML of the script, read up on that function if you haven't heard of it.
Or if you want to create a function from a string, you can use new Function([name] ,[function body string]) if you need arguments you have to sandwich them between the 2 parameters.
But my snippet is about 30 lines long currently and might get bigger with time > so it is very difficult to code with all the + " code " on every line that I
write
You can use template literals if you want multi-line strings in Javascript, you simply have to replace your quotes with backticks.
See this MDN page if you are interested, or even this StackOverflow answer.

Adding and Displaying Array Issue

var reset = function ()
{
var p = parseFloat($("#IA").val());
var q = parseFloat($("#IB").val());
var m = parseFloat($("#CGCD").val());
var aR = [];
aR += ["GCD(" + p + "," + q + ")=" + m];
document.getElementById("PGCD").innerHTML = aR + "\n";
document.getElementById("IA-error").innerHTML="";
document.getElementById("IB-error").innerHTML="";
$("#IA").focus();
};
The code above is only for a 'reset' function, a part of additional code (not present), the purpose which is to find the Greatest Common Denominator, GCD.
My 'reset' function is connected to a button, #reset, the purpose of which is to do four things:
add and store the string GCD(p,q)=m to the array 'aR'; p/q/m are variable stand-ins for the values of the input text areas #IA, #IB, and #CGCD (the GCD of #IA and #IB);
display the array 'aR' in a text-area #PGCD each time the reset button is clicked; this is why I used an array;
clear the two input text areas #IA and #IB;
clear the one output text area;
As it stands, all four objectives are completed successfully, with one exception: for the second objective, only the most recent GCD calculation is outputted; none of the previous calculations output.
I cannot get the array to list the different saved calculations within it. I think (?) the new calculations are being added to the array, but I am not sure.
I've tried a 'for' statement, and an 'if' statement, neither of which worked. I don't know whether I coded it wrong, or if it wasn't the right solution for my issue.
I tried to search the forums (here) for a solution, but was unable to find one.
Thank you.
If I'm understanding what you are describing, I believe your problem is that you are attempting to use += to add elements to an array. You should use
aR.push("GCD(" + p + "," + q + ")=" + m);
The += operator is used for addition of a value to itself as well as string concatenation.
Edit: per comments below, the main issue was declaration of aR as a local variable. It needs to be either global or declared within the same scope.

Splitting a long phrase into an array

I need to take the phrase
It’s that time of year when you clean out your closets, dust off shelves, and spruce up your floors. Once you’ve taken care of the dust and dirt, what about some digital cleaning? Going through all your files and computers may seem like a daunting task, but we found ways to make the process fairly painless.
and upon pressing a button
split it into an array
iterate over that array at each step
Build SPAN elements as you go, along with the attributes
Add the SPAN elements to the original DIV
Add a click handler to the SPAN elements, or to the DIV, which causes the style on the SPAN to change on mouseover.
So far I had
function splitString(stringToSplit, separator) {
var arrayOfStrings = stringToSplit.split(separator);
print('The original string is: "' + stringToSplit + '"');
print('The separator is: "' + separator + '"');
print("The array has " + arrayOfStrings.length + " elements: ");
for (var i=0; i < arrayOfStrings.length; i++)
print(arrayOfStrings[i] + " / ");
}
var space = " ";
var comma = ",";
splitString(tempestString, space);
splitString(tempestString);
splitString(monthString, comma);
for (var i=0; i < myArray.length; i++)
{
}
var yourSpan = document.createElement('span');
yourSpan.innerHTML = "Hello";
var yourDiv = document.getElementById('divId');
yourDiv.appendChild(yourSpan);
yourSpan.onmouseover = function () {
alert("On MouseOver");
}
and for html I have
The DIV that will serve as your input (and output) is here, with
id="transcriptText":</p>
<div id="transcriptText"> It’s that time of year when you clean out your
closets, dust off shelves, and spruce up your floors. Once you’ve taken
care of the dust and dirt, what about some digital cleaning? Going
through all your files and computers may seem like a daunting task, but
we found ways to make the process fairly painless.</div>
<br>
<div id="divideTranscript" class="button"> Transform the
Transcript! </div>
Any help on how to move one? I have been stuck for quite some time
Well, first off this looks like homework.
That said, I'll try to help without giving you the actual code, since we're not supposed to give actual working solutions to homework. You're splitting the string too many times (once is all that's needed based on the instructions you gave) and you have to actually store the result of the split call somewhere that your other code can use it.
Your instructions say to add attributes to the span, but not which attributes nor what their contents should be.
Your function should follow the instructions:
1) Split the string. Since it doesn't specify on what, I'd assume words. So split it on spaces only and leave the punctuation where it is.
2) with the array of words returned from the split() function, iterate over it like you attempt to, but inside the braces that scope the loop is where you want to concatenate the <span> starting and ending tags around the original word.
3) use the document.createElement() to make that current span into a DOM element. Attach the mouseover and click handlers to it, then appendChild() it to the div.
add the handler to your button to call the above function.
Note that it's possibly more efficient to use the innerHTML() function to insert all the spans at once, but then you have to loop again to add the hover/click handlers.

Append to a webpage in javascript

What I want to do is that: a webpage with continuously updating content. (In my case is updating every 2s) New content is appended to the old one instead of overwriting.
Here is the code I have:
var msg_list = new Array(
"<message>Hello, Clare</message>", "<message>Hello,Lily</message>",
"<message>Hello, Kevin</message>", "<message>Hello, Bill</message>"
);
var number = 0;
function send_msg()
{
document.write(number + " " + msg_list[number%4]+'<br/>');
number = number + 1;
}
var my_interval = setInterval('send_msg()', 2000);
However, in both IE and Firefox, only one line is printed out, and the page will not be updated anymore. Interestingly in Chrome, the lines are being printed out continuously, which is what I am looking for.
I know that document.write() is called when the page is loaded according to this link. So it's definitely not the way to update the webpage continuously. What will be the best way to achieve what I want to do?
Totally newbie in Javascript. Thank you.
Lily
I would have a div or some other container, like this:
<div id="msgDiv"></div>
Then write to it like using .innerHTML, like this:
var msg_list = new Array(
"<message>Hello, Clare</message>", "<message>Hello,Lily</message>",
"<message>Hello, Kevin</message>", "<message>Hello, Bill</message>"
);
var number = 0;
function send_msg()
{
document.getElementById("msgDiv").innerHTML += number + " " + msg_list[number%4]+'<br/>';
number++;
}
var my_interval = setInterval(send_msg, 2000);
You can see a working example of this here
You can append to the innerHTML property:
var number = 0;
function send_msg()
{
document.getElementById('console').innerHTML += (number + " " + msg_list[number%4]+'<br/>');
number = number + 1;
}
This code will append the message to an element with an id of console, such as
<div id="console"></div>
By the way, it is bad practice to call setInterval with a string.
Instead, pass the function itself, like this:
var my_interval = setInterval(send_msg, 2000);
I would start by looking at the jQuery library. This will save you a lot of pain.
What you want to do is keep inserted lines into a table, using eg:
$('table tbody').append('<tr><td>some value</td></tr>');
This would be an excellent opportunity for you to learn a little DOM programming.
Using the DOM to update the page should result in less overhead than simply concatenating more HTML into it. Find the node you want to put the updates into, and do an appendChild on each subsequent addition.
The answers to this question may be helpful: What's a simple way to web-ify my command-line daemon?

Categories