Using quotes within a javascript array and getting the result verbatim - javascript

So I have an array that looks like:
var typeArray = [
"'<span class="class">Text</span>'",
"test",
]
and im calling the array in code that looks like this:
<script>
var elem = document.getElementById("pHolderGen1");
var num = 151;
for(var i = 1; i <= num; i++) {
var d = document.createElement('div');
d.setAttribute('class', 'pfl');
d.innerHTML = '<p>'
+ typeArray[i-1] +
'</p>';
elem.appendChild(d);
}
</script>
Now I know there is an issue in the array with my use of quotes around class; however when I change it to:
var typeArray = [
"'<span class="/"grass"/">Grass</span>'",
"test",
]
as an attempt to get rid of the qoute issue I'm having all it displays is "NaN."
When I actually run the code I want it to produce (in html):
<p><span class="class">Text</span></p>
So in short I'm looking for a way to fix this and I also want to know why it does this.

Change "'<span class="class">Text</span>'" to "<span class='class'>Text</span>"

Related

page doesn't display anything

so I wrote a script to display 5 random arrays, but the page doesn't display anything.
here's the code:
<html>
<head>
<script>
function start(){
var arr(5),result;
result=document.getElementById("arraying");
result="<p>";
for(var i=0; i<5;i++){
arr[i]=Math.floor(Math.random()*10);
result+="arr["+i+"]= "+arr[i]+"</p><p>";
}
result+="</p>";
}
window.addEventListener("load",start,false);
</script>
</head>
<body>
<div id="arraying"></div>
</body>
</html>
I tried removing result=document.getElementById and write document.getElementById.innerHTML=result in the end of the function but didn't work. what's the error?
You cannot use the same variable for different purposes at the same time. First you assign a DOM element to result, and immediately on the next line you overwrite result with a string.
Build a string htmlStr inside your loop, and when that is done, assign this string to result.innerHTML property:
function start() {
let arr = [],
result, htmlStr = '';
result = document.getElementById("arraying");
htmlStr += "<p>";
for (let i = 0; i < 5; i++) {
arr[i] = Math.floor(Math.random() * 10);
htmlStr += "arr[" + i + "]= " + arr[i] + "</p><p>";
}
htmlStr += "</p>";
result.innerHTML = htmlStr;
}
window.addEventListener("load", start, false);
<div id="arraying"></div>
Looking at the code you seem to be missing some basic javascript concepts.
array size
This is probably your main issue:
var arr(5)
This does not make sense in javascript. Array length does not need to be predefined since all arrays are of dynamic length. Simply define an array like this:
var arr = []
Then later when you want to append new elements use push like this:
arr.push( Math.floor(Math.random()*10) )
adding html using innerHTML
There are different ways to dynamically inject html into your page. (It looks like) you tried to append the html as a string to the parent element. This is not possible.
You said you tried using innerHTML. That should work if used correctly.
A working implementation would work like this:
function start() {
var arr = []
var result = "<p>"
for(var i = 0; i < 5; i++) {
arr.push( Math.floor(Math.random()*10) ) // Btw this array isn't actually needed.
result += "arr[" + i + "] = " + arr[i] + "</p><p>"
}
document.getElementById("arraying").innerHTML = result
}
window.addEventListener("load", start, {passive: true});
adding html using createElement
A generally better way of dynamically adding html elements is via createElement.
This way you dont have to write html and are therefore less prone for making errors. It is also more performant and easier to integrate into javascript.
I think the best explaination is a commented implementation:
function start() {
var myDiv = document.getElementById("arraying") // get parent node
var arr = []
for(var i = 0; i < 5; i++) {
arr.push( Math.floor(Math.random()*10) )
var p = document.createElement("p") // create p element
p.innerText = "arr[" + i + "] = " + arr[i] // add text content to p element
myDiv.append(p) // append p element to parent element
}
}
window.addEventListener("load", start, {passive: true});
small tips
The let keyword works mostly the same as the var keyword, but is generally preferred because of some edge cases in which let is superior.
Fusing strings and variables using the plus operator is generally considered bad practice. A better way to do the string concatenation would have been
result += `arr[${i}] = ${arr[i]}</p><p>`

JSON to HTML using JSON.parse undefined error

When trying to parse the JSON
[{"title":"First Item","href":"first","children":[{"title":"Sub First Item","href":"sub"}]},{"title":"Second Item","href":"home"}]
into a list for navigation its just returning undefined.
I was using code from another answer which was working fine with hardcoded JSON but when using it from a textbox (as its going to be generated using jquery.nestable.js) it just gived undefined and i cant see why, ive tried escaping the quotation marks too but no luck there.
function convertNav(){
var data = document.getElementById('jsonNav').value;
var jsn = JSON.parse(document.getElementById('jsonNav').value);
var parseJsonAsHTMLTree = function(jsn){
var result = '';
if(jsn.title && jsn.children){
result += '<li>' + jsn.title + '<ul>';
for(var i in jsn.children) {
result += parseJsonAsHTMLTree(jsn.children[i]);
}
result += '</ul></li>';
}
else {
result += '<li>' + jsn.title + '</li>';
}
return result + '';
}
var result = '<ul>'+parseJsonAsHTMLTree(jsn)+'</ul>';
document.getElementById('convertedNav').value = result;
}
Ive put it in a jsfiddle
http://jsfiddle.net/nfdz1jnx/
Your code handles only a single Javascript object but, according to your code, all nodes and sub-nodes are wrapped inside Javascript arrays. You can use Array.prototype.forEach to handle the array objects.
Sample code follows.
function convertNav() {
var data = document.getElementById('seriaNav').value;
var jsn = JSON.parse(document.getElementById('seriaNav').value);
var parseJsonAsHTMLTree = function(jsn) {
var result = '';
jsn.forEach(function(item) {
if (item.title && item.children) {
result += '<li>' + item.title + '<ul>';
result += parseJsonAsHTMLTree(item.children);
result += '</ul></li>';
} else {
result += '<li>' + item.title + '</li>';
}
});
return result + '';
};
var result = '<ul>' + parseJsonAsHTMLTree(jsn) + '</ul>';
document.getElementById('convertedNav').value = result;
}
<textarea class="span7" style="width:400px;height:100px;" id="seriaNav">[{"title":"First Item","href":"first","children":[{"title":"Sub First Item","href":"sub"}]},{"title":"Second Item","href":"home"}]</textarea>
<hr />
<button class="btn btn-primary" onClick="convertNav();return false;">Convert</button>
<hr />
<textarea class="span5" style="width:400px;height:100px;" id="convertedNav"></textarea>
Your jsn variable is an array. You're getting a list of Objects back and you'll need to parse each one.
Add this after you get jsn back and you'll see an example of retrieving your data.
alert(jsn[0].title);
Your JSON is parsed into an array of objects. With this in mind, your paths to extract information are wrong. For example, you have:
if(jsn.title...
...whereas there is no jsn.title. There is, however, json[0].title.
Basically, you're missing a loop, over the objects. After
var result = '';
add
for (var i=0, len=jsn.length; i
...and in code subsequent to that change all references to jsn to jsn[i]
And of course close the loop further down.
(Finally, at the risk of being pedantic, jsn is not the best name for the var; it's not JSON anymore; it used to be, but now it's parsed, so it's an array. JSON is a string.)
[{"title":"First Item","href":"first","children":[{"title":"Sub First Item","href":"sub"}]},{"title":"Second Item","href":"home"}]
This is not JSON, this is an array of objects. You don't need to parse this. It's already parsed. It's a javascript object.
You should be able to just parse it like you would a regular object.
data[0].title
data[0].children[1].title
etc.

Iterating an array that is nested with an object key

var html = {
easyBB :
['easybbtutorials','www.easybbtutorials.com','http://i76.servimg.com/u/f76/17/83/35/07/easybb10.png'],
AvacWeb:
['AvacWeb','www.avacweb.com','http://i45.servimg.com/u/f45/16/35/08/55/new_lo12.png'],
easyBB2:
['easybbtutorials','www.easybbtutorials.com','http://i76.servimg.com/u/f76/17/83/35/07/easybb10.png'],
AvacWeb2 :
['AvacWeb','www.avacweb.com','http://i45.servimg.com/u/f45/16/35/08/55/new_lo12.png'],
easyBB3 :
['easybbtutorials','www.easybbtutorials.com','http://i76.servimg.com/u/f76/17/83/35/07/easybb10.png'],
AvacWeb3 :
['AvacWeb','www.avacweb.com','http://i45.servimg.com/u/f45/16/35/08/55/new_lo12.png']
};
var cont = document.getElementById('container');
for(var key in html){
for(var i =0;i<key.length;i++ ){
var name= '<span class="name">'+html[key][0] +'</span>',
link = '<span class="url">'+html[key][1] +'</span>',
image = '<img src="'+html[key][2]+'" title="'+html[key][0]+'" />';
cont.innerHTML= '<div class="wrapper">'+ name + '<br />'+image+'<br />'+link+'</div>';
i++;
}
}
I am trying to iterate over the arrays in each key of the HTML object I created problem is not sure how to do this I've tried multiple ways now and I believe (since I am posting) I am doing this all wrong. I've also tried doing: html[key[i]][0] though of course I get an error of i is not defined. Any suggestions what I am doing wrong, as of right now it is only posting one array to the html.
The problem is not the iteration, it's the line
cont.innerHTML = ...
which is replacing the content each time the loop iterates so that you only see the final item ("AvacWeb3").
Change that to
cont.innerHTML += ...
and get rid of the for (var i =0 ... loop which isn't needed. (jsfiddle)
for(var i = 0; i < html[key].length; i++){
...
You should do html[key][i][0].
And also you should do what Trevor said, html[key].length instead of key.length.
Make yourself easy by assigning html[key] to var currentkey for example, easier to keep track on.
Also, look into array.forEach, just for fun ;)

Optimize nested loop to create HTML elements using jQuery

I'm developing an onscreen keyboard using HTML / Javascript. The keyboard is generated at runtime.
I'm using a JSON datastructure to store the different keyboard layouts, language settings etc.
var initParams = {
keyboardLanguage: "de",
keyboardLayout: {
de: {
row1: ["Q","W","E","R","T","Z","U","I","O","P"],
row2: ["A","S","D","F","G","H","J","K","L"],
row3: ["Y","X","C","V","B","N","M"]
},
en: {
row1: ["Q","W","E","R","T","Y","U","I","O","P"],
row2: ["A","S","D","F","G","H","J","K","L"],
row3: ["Z","X","C","V","B","N","M"]
}
}
}
And here is the function that does the job:
function CreateKeyHtmlElements(){
var divElement = document.createElement("div");
for(var obj in initParams.keyboardLayout[initParams.keyboardLanguage]){
var keyRow = divElement.cloneNode(false);
keyRow.id = "key" + obj;
keyRow.className = "keyboard-key-row";
for(var i = 0, l = initParams.keyboardLayout[initParams.keyboardLanguage][obj].length; i < l; i +=1){
var key = divElement.cloneNode(false);
key.id = "key-" + initParams.keyboardLayout[initParams.keyboardLanguage][obj][i];
key.className = "keyboard-key";
key.textContent = initParams.keyboardLayout[initParams.keyboardLanguage][obj][i];
keyRow.appendChild(key);
$(key).appendTo(keyRow);
}
$(keyRow).appendTo($("#keyboard-key-box"));
}
}
Are there any effective ways to optimize this function, particularly the loops, using jQuery.
Thanks in advance.
Actually there is a special HTML element for aggregation of html, not to make actual dom manipulations
var fragment = document.createDocumentFragment();
But as long as the benchmarks don't show actual difference between the fragment approach and inserting sting via innerHTML (proof)
You can do something like this:
var result = '<div class="keyboard">';
$(initParams.keyboardLayout[initParams.keyboardLanguage]).each(function(i,obj){
result += '<div class="row">';
result += '<div class="key">'+obj.join('</div class="key"><div>')+'</div>';
result += '</div>';
})
$(".target").append(result);
This doesn't give you a chance to add ID's but that actually dosn't matter, just when binding use $(el).index() to get the column index and $(el).parent().index() to get row

How to extract values from a string in javascript?

I need some help with extracting values from a cookie using javascript.
The string in a cookie looks something like this:
string = 'id=1||price=500||name=Item name||shipping=0||quantity=2++id=2||price=1500||name=Some other name||shipping=10||quantity=2'
By using string.split() and string.replace() and a some ugly looking code I've somehow managed to get the values i need (price, name, shipping, quantity). But the problem is that sometimes not all of the strings in the cookie are the same. Sometimes the sting in a cookie will look something like this :
string = 'id=c1||color=red||size=XL||price=500||name=Item name||shipping=0||quantity=2++id=c1||price=500||name=Item name||shipping=0||quantity=2'
with some items having color and size as parameters and sometimes only one of those.
Is there some more efficient way to explain to my computer that i want the part of the string after 'price=' to be a variable named 'price' etc.
I hope I'm making sense I've tried to be as precise as I could.
Anyway, thank you for any help
EDIT: I just wanted to say thanks to all the great people of StackOverflow for such wonderfull ideas. Because of all of your great suggestions I'm going out to get drunk tonight. Thank you all :)
Let's write a parser!
function parse(input)
{
function parseSingle(input)
{
var parts = input.split('||'),
part,
record = {};
for (var i=0; i<parts.length; i++)
{
part = parts[i].split('=');
record[part[0]] = part[1];
}
return record;
}
var parts = input.split('++'),
records = [];
for (var i=0; i<parts.length; i++)
{
records.push(parseSingle(parts[i]));
}
return records;
}
Usage:
var string = 'id=1||price=500||name=Item name||shipping=0||quantity=2++id=2||price=1500||name=Some other name||shipping=10||quantity=2';
var parsed = parse(string);
/* parsed is:
[{id: "1", price: "500", name: "Item name", shipping: "0", quantity: "2"},
{id: "2", price: "1500", name: "Some other name", shipping: "10", quantity: "2"}]
*/
You can achieve this using regular expressions. For example, the regex /price=([0-9]+)/ will match price=XXX where XXX is one or more numbers. As this part of the regex is surrounded by parenthesis it explicitly captures the numeric part for you.
var string = 'id=1||price=500||name=Item name||shipping=0||quantity=2++id=2||price=1500||name=Some other name||shipping=10||quantity=2'
var priceRegex = /price=([0-9]+)/
var match = string.match(priceRegex);
console.log(match[1]); // writes 500 to the console log
Try that:
var string = 'id=1||price=500||name=Item name||shipping=0||quantity=2++id=2||price=1500||name=Some other name||shipping=10||quantity=2';
var obj = new Array();
var arr = string.split('||');
for(var x=0; x<arr.length;x++){
var temp = arr[x].split('=');
obj[temp[0]] = temp[1]
}
alert(obj['id']); // alert 1
First, split your string into two (or more) parts by ++ separator:
var strings = myString.split('++');
then for each of the strings you want an object, right? So you need to have an array and fill it like that:
var objects = [];
for (var i = 0; i < strings.length; ++i) {
var properties = strings[i].split('||');
var obj = {};
for (var j = 0; j < properties.length; ++j) {
var prop = properties[j].split('=');
obj[prop[0]] = prop[1]; //here you add property to your object, no matter what its name is
}
objects.push(obj);
}
thus you have an array of all objects constructed from your string. Naturally, in real life I'd add some checks that strings indeed satisfy the format etc. But the idea is clear, I hope.
If you can replace the || with &, you could try to parse it as if it were a query string.
A personal note - JSON-formatted data would've been easier to work with.
I would attach the data to a javascript object.
var settingsObj = {};
var components = thatString.split('||');
for(var j = 0; j < components.length; j++)
{
var keyValue = components[j].split('=');
settingsObj[keyValue[0]] = keyValue[1];
}
// Now the key value pairs have been set, you can simply request them
var id = settingsObj.id; // 1 or c1
var name = settingsObj.name; // Item Name, etc
You're already using .split() to break down the string by || just take that a step further and split each of those sections by = and assign everything on the left the field and the right the value
This should get the first match in the string:
string.match(/price=(\d{1,})/)[1]
Note this will only match the first price= in the string, not the second one.
If you can use jQuery, it wraps working with cookies and lets you access them like:
Reading a cookie:
var comments = $.cookie('comments');
Writing a cookie:
$.cookie('comments', 'expanded');
This post by someone else has a decent example:
http://www.vagrantradio.com/2009/10/getting-and-setting-cookies-with-jquery.html
If you can't use jQuery, you need to do standard string parsing like you currently are (perhaps regular expressions instead of the string splitting / replacing might trim down your code) or find some other javascript library that you can use.
If you like eye candies in your code you can use a regexp based "search and don't replace" trick by John Resig (cached here) :
var extract = function(string) {
var o = {};
string.replace(/(.*?)=(.*?)(?:\|\||$)/g, function(all, key, value) {
o[key] = value;
});
return o;
};
Then
var objects = string.split('++'),
i = objects.length;
for (;i--;) {
objects[i] = extract(objects[i]);
}
You could do something like this, where you eval the strings when you split them.
<html>
<head>
<script type="text/javascript">
var string = 'id=c1||color=red||size=XL||price=500||name=Item name||shipping=0||quantity=2++id=c1||price=500||name=Item name||shipping=0||quantity=2'
var mySplitResult = string.split("||");
for(i = 0; i < mySplitResult.length; i++){
document.write("<br /> Element " + i + " = " + mySplitResult[i]);
var assignment = mySplitResult[i].split("=");
eval(assignment[0] + "=" + "\""+assignment[1]+"\"");
}
document.write("Price : " + price);
</script>
</head>
<body>
</body>
</html>
var str = 'id=c1||color=red||size=XL||price=500||name=Item name||shipping=0||quantity=2++id=c1||price=500||name=Item name||shipping=0||quantity=2'
var items = str.split("++");
for (var i=0; i<items.length; i++) {
var data = items[i].split("||");
for (var j=0; j<data.length; j++) {
var stuff = data[j].split("=");
var n = stuff[0];
var v = stuff[1];
eval("var "+n+"='"+v+"'");
}
alert(id);
}
EDIT: As per JamieC's suggestion, you can eliminate eval("var "+n+"='"+v+"'"); and replace it with the (somewhat) safer window[n] = v; -- but you still have the simple problem that this will overwrite existing variables, not to mention you can't tell if the variable color was set on this iteration or if this one skipped it and the last one set it. Creating an empty object before the loop and populating it inside the loop (like every other answer suggests) is a better approach in almost every way.
JSON.parse('[{' + string.replace(/\+\+/g, '},{').replace(/(\w*)=([\w\s]*)/g, '"$1":"$2"').replace(/\|\|/g, ',') + '}]')
Convert the string for JSON format, then parse it.

Categories