I'm writing a function for creating images from an array and I need to put some extensive HTML inside a javascript string. Unfortunately whenever I use parentheses, it throws off the whole thing.
Any help?
This:
listItem.innerHTML = "<img src='" + listData[i] + "'>"; */
This doesn't:
listItem.innerHTML = "<div class='item square' style='background-image: url(" + listData[i] + ")'></div>";
Your code depends on listData[i] being valid when tossed into three places:
CSS’s url()
CSS
HTML
It shouldn’t. Building HTML in JavaScript isn’t a very good idea in the first place. If you truly have enough markup that must be built dynamically that you can’t use the DOM, use a template engine that knows its target. In this and most cases, use the DOM!
var itemImage = document.createElement('div');
itemImage.className = 'item square';
itemImage.style.backgroundImage = 'url("' + encodeURI(listData[i]) + '")';
listItem.appendChild(itemImage);
This creates one element, assigns values to some of its properties, and appends it to listItem, and it will always do that; you don’t have to hope that your quotes matched up properly or that you remembered to escape absolutely everything.
Footnote: the combination of encodeURI and double quotes around the url() value will almost certainly fix any potential problem – quotes or parentheses – regardless of which method you use to add them, but that doesn’t mean you should keep using innerHTML.
Related
First post here, so please be gentle ;-)
I've been learning coding over the last couple of weeks by making a dummy page, and been implementing what i learn on it incrementaly as i progress, hence it's a mixed bag where the functionality/code is according to when i wrote it, based on pure html/CSS, inline javascript, external javascript, and finally jquery.
So i mostly wrapped it up and i'm now cleaning up the mess, and part of my mission is to cull functions and lines of codes, and in one of them i'm kind of stuck.
The before was 30 buttons calling to 30 different functions onclick like so:
function cell3() {
document.getElementById('base3').src='images/1/3/' + x + '.png';
document.getElementById('base3b').src='images/1/3/' + x + '.png';
document.getElementById('v2base3').src='images/2/3/' + x + '.png';
document.getElementById('v2base3b').src='images/2/3/' + x + '.png';
document.getElementById('cell3').style.backgroundColor= x ;
}
Where a global variable (x) defines the folder paths for images to replace the images within some divs when clicking the button (cell3). It also changes the bGroung color of it. Sorry if the naming is a bit confusing...
So i'm removing all 30 functions and the 30 onclick calls with this bit of jquery:
$('button').click(function(){
var eyeD = $(this).attr("id");
var newURLa = 'images/1/' + eyeD + '/' + x + '.png';
var newURLb = 'images/2/' + eyeD + '/' + x + '.png';
$('base' + eyeD).attr('src', newURLa);
$('base' + eyeD + 'b').attr('src', newURLa);
$('v2base' + eyeD).attr('src', newURLb);
$('v2base' + eyeD + 'b').attr('src', newURLb);
$(this).css( "background-color", x );
document.getElementsByid('check').innerhtml = eyeD;
});
For that to 'work' i changed the button's names from 'cell1', 'cell2, etc. to '1', '2', etc.
Now the thing is, when clicking on the buttons the var 'eyeD' takes the value from the button ok. ('1', '2', etc.). The elements ID's are formed correctly ('base1', 'base2'... 'base1b', base2b'...), and the URL's are formed correctly. (The last line in the code is a p element that displays values so i could try to troubleshoot it) The background color also changes as expected. But the images do not get replaced.
Tried adding commas to the resulting URL's in case it was a syntax issue, but nothing happens. i even went freestyle and tried it with the =url() on it, different commas in different places, etc. So basically scraping the barrel here. Also wrote a url without variables to see if that would work, but still nothing. Also getting no errors when looking at the console.
It's probably a basic 'DOH!' thing, but right now i have a mental block...
Also, is there a way to keep the original naming and just retrieve the numbering part of the ID's? Thought about using the [4] identifier to get the 5th digit, but that won't work when running double digit numbers. (10, 11, etc)
Thanks!
Your jQuery lines accessing the elements are missing the # sign.
Change these...
$('base' + eyeD).attr('src', newURLa);
To this...
$('#base' + eyeD).attr('src', newURLa);
Also, your last line where you use plain JS, can be done in jQuery as well with less code.
document.getElementsByid('check').innerhtml = eyeD;
To...
$("#check").html(eyeD);
However, you should always use distinct ID's for elements. If you need to use multiple elements at the same time, use a class instead.
$(".check").html(eyeD);
You're grabbing an element incorrectly.
Either Grab an element by it's class name like so:
$('.v2base' + eyeD + 'b').attr('src', newURLb);
Or by its ID:
$('#v2base' + eyeD + 'b').attr('src', newURLb);
Problem solved!! It was indeed calling the id with the hash, but also it has to be called with double quotation marks. Single inverted commas won't work.
So the working format is
$("#v2base" + eyeD + "b")
but it won't work like so
$('#v2base' + eyeD + 'b')
Thanks everyone, it's been emotional
I'm having a bit of trouble correctly displaying a message in a webpage I am trying to create. The code I have is:
content.innerHTML += "<button 'onclick=\"likeFunction(" + feed.messages[y]._id + ")\">" + "Like(" + feed.messages[y].likesCount + ")" + "</button>"
When I inspect the element on the page source, I get this output:
<button 'onclick="like(idOfObject)">Likes(likeNumber)</button>
What I need it to look like is:
<button 'onclick="like("idOfObject")">Likes(likeNumber)</button>
I'm a bit confused on how I would add more single or double quotes and where to escape them correctly to get this desired output.
I think I see a few typos. Most noticeably with the leading ' in front of onclick. I don't think this needs to be here.
As for formatting the string, consider looking into template literals introduced in ES6.
Might look something like this:
content.innerHTML += `<button onclick="likeFunction(${idOfObjectVariable})">Likes (${likeCountVariable})</button>`
Hope this helps
You're so close! First, you need to remove the ' before onclick. If you want to add double quotes around the idOfObject, then you just need escape one double quote after likeFunction( and one double quote before )\">".
"<button onclick=\"likeFunction(\"" + feed.messages[y]._id + "\")\">"
The only problem is that when the double quotes around your variable idOfObject render, they'll correspond to the opening and closing quotes you already have for onclick. So, your solution should have single quotes inside of double quotes:
"<button onclick=\"likeFunction(\'" + feed.messages[y]._id + "\')\">"
I would have guessed what you wanted in your HTML would be:
<button onclick="like('idOfObject')">7</button>
or
<button onclick='like("idOfObject")'>7</button>
You probably do not want to quote the entire on-click attribute, just the part on the right hand side of the = .
content.innerHTML += "<button onclick=\"like('" + feed.messages[y]._id + "')\">" + ...
I'm guessing you also probably don't want something that gets displayed to the user that looks like a function all, but the result of the function call, but that is not what you were asking about.
You SHOULD NOT concatenate html manually from untrusted input (suppose someone injected malicious html code to your feed.messages[y]._id or another field). Sanitization is one of your options but it's like patching a huge hole.
You can read more about preventing those security attacks named XSS here.
Consider creating your DOM manualy with createElement API and bind your event handlers manually.
function renderButton(content, feed, y) {
function likeFunction() {
alert("LIKE" + feed.messages[y]._id);
};
var button = document.createElement("button");
var text = document.createTextNode("Like(" + feed.messages[y].likesCount + ")");
button.appendChild(text);
button.addEventListener('click', likeFunction)
content.appendChild(button);
}
Then you can just render your button with a simple function call.
renderButton(content, feed, 0)
I have the following javascript:
tr.append("<a href='add_widget.html?id=" + data[i].id + "&pg=" + data[i].page_number + "&dest=" + data[i].dest + "&name=" + data[i].name.replace("'","\\'") + "'</a><button class='btn btn-xs btn-primary'>Edit</button> </td>");
The code in question has to do with the name field.
If I have a name like "John Doe" when I click on the hyperlink created by the above javascript, the new page's querystring has the full name.
However, if I try to pass a name like "John's stuff", the above logic creates a query string variable that looks like this:
&name=John\
How can I change the above code so that the entire string "John's stuff" is passed to the add_widget.html page?
Thanks.
replace("'","%27")
try http://meyerweb.com/eric/tools/dencoder/ it's an online URL encoder/decoder.
When you're trying to "protect" characters, you have to keep in mind what you're protecting them from. In this case, there are two interpreters you have to worry about:
You're building HTML, so you have to worry about the HTML parser;
You're building a URL, so you have to worry about how the browser and the server will parse the URL.
To deal with the first problem, you can replace the quotes with the HTML entity equivalent ('). To deal with the second, you can use encodeURIComponent().
I think you'd want to do the encodeURIComponent() call first, to avoid having the HTML entity notation get messed up. The entity notation will be gone after the HTML parser is finished with the string anyway:
function qEncode(str) {
return encodeURIComponent(str).replace(/'/g, "'");
}
To use that:
tr.append("<a href='add_widget.html?id=" +
qEncode(data[i].id) + "&pg=" +
qEncode(data[i].page_number) + "&dest=" +
qEncode(data[i].dest) + "&name=" +
qEncode(data[i].name) +
"'</a><button class='btn btn-xs btn-primary'>Edit</button> </td>"
);
Note that you could also encode double-quote characters too.
A totally different way of working around this problem would be to build the DOM content with DOM APIs. By doing that, you'd completely avoid the HTML parser, and you'd just need encodeURIComponent().
You need to think, what will be interpreting my code, so what do I need to escape for?
Your code will be interpreted by the HTML Interpreter in the browser
Your code will be interpreted as a URI
This means you need to escape/encode them in reverse order. Luckily JavaScript provides a URI encoder as encodeURIComponent, but it doesn't provide a HTML one (probably as we have DOM Methods) but it isn't too hard to implement for important characters, e.g.
function html_encode(str) {
var re_chars = /[<>'"]/g;
function replacer($0) {
return '&#' + $0.charCodeAt(0) + ';'
}
return str.replace(re_chars, replacer);
}
// example follows
html_encode('<foo bar="baz">'); // "<foo bar="baz">"
So for you,
attrib_value = html_encode(/* ... + */ encodeURIComponent(data[i].name) /* + ... */ );
For completeness,
function html_decode(str) {
var re = /&(?:#\d{1,3}|amp|quot|lt|gt|nbsp);/g, // notice extra entities
d = document.createElement('div');
function replacer($0) {
d.innerHTML = $0;
return d.textContent;
}
return str.replace(re, replacer);
}
// and an example
html_decode('<foo bar="baz">'); // "<foo bar="baz">"
Using escape(data[i].name) instead of data[i].name.replace("'","\\'"), will solve your problem.
This might sound silly but i'm having trouble printing a variable in this code -
var clsuffix = "something";
$("#box").wrap('<div class="boxy" />');
I want to print the clsuffix variable inside the class=" here "
so it could be like
<div class="boxysomething">
But when i use the variable inside class="", it comes up as it is (not being treated as variable)
Just concatenate it in. Ultimately, your goal is to build a string consisting of the literal "boxy" and the contents of the variable clsuffix. That is done with "boxy" + clsuffix in JavaScript:
$("#box").wrap('<div class="boxy' + clsuffix + '" />');
If you were just trying to insert the variable into the string (such as you might do in a PHP double-quoted string), it won't be interpreted by JavaScript:
// Doesn't work in JavaScript:
$("#box").wrap('<div class="boxyclsuffix" />');
I'd suggest:
$('#box').wrap('<div />', {'class' : 'boxy' + cslsuffix});
Which effectively creates the div element, and uses the map to assign values to the defined attributes.
I need to build a dynamic string as for each data. This string will set up an HTML button, when event click will call a function. I'm having problems with the 'e'. See the example below:
var stringButton = "";
var txtBtn = "My Button";
for(item in data){
stringButton= "<input id='btn-" + item.id + "' type='button' href='#'
class='fbbutton'" + "value=' " + txtBtn + "' onclick='actionBtn(" + item .id + ", '" +
item .name + "')'>";
}
function actionBtn(id, name) {
//process data.
}
In inspect element I see:
<input id="btn-1599" type="button" href="#" class="fbbutton" value=" My Button "
onclick="actionBtn(1599, " itemName"" jjjj')'="">
The problem is to create string which call methods passing parameters strings.
As we can see, " and ' are wrong. What is the correct way?
The correct way IMO is to use DOM creation methods and bind the event handler properly instead of using inline event handlers.
var button = document.createElement('input');
button.id = item.id;
button.type = "button";
button.className = "fbbutton";
button.value = txtBtn;
button.onclick = (function(item) {
return function() {
actionBtn(item.id, item.name);
};
}(item));
DOM Inspectors show you the DOM after it has been processed by the parser. It does NOT show you the raw source. Things like "what kind of quotes were used", "what order the attributes were in", "how many space characters were between attributes" are not preserved.
Here, you are seeing that all the attributes are wrapped in double-quotes, but that they also contain double-quotes. But you would also notice that the ones inside the value are colour-coded as part of the string (usually in blue).
That said, in your source, you are usin single quotes around the attribute value and single quotes inside it. Consider using double-quotes in place of one or the other (escaped as \" here), or an " entity.
Finally, welcome to Stack Overflow. Please ACCEPT answers to previous questions before asking new ones.
There is surely a ' or a " in your item.name, so it cut the string that you are building.
Try escaping them
Either do as in Felix Klings answer or, if you will be doing this alot, use javascript templates/micro templates.
https://developer.mozilla.org/en/JavaScript_templates