Javascript: function and its argument - javascript

I've a problem with my function and its arguments... this is the code:
function elab(){
var up = arguments[0];
var id = arguments[1];
len = arguments.length - 3;
for(var a = 1; a <= 10; a++){
arg = (arguments[2] + a); // id tag html : [nome][num]
document.getElementById(arg).style.display = "block";
}
for (var i = 3; i < len; i++) {
alert('test1');
document.getElementById(arguments[i]).style.display = "none";
alert('test2');
}
change_price(up, id);
}
The script hangs at the second cycle: it prints 'test1' but not 'test2'.
Where is the error?
thx all ;)

Note that this advice should be used for all things unsure:
for (var i = 3; i < len; i++) {
var node = document.getElementById(arguments[i]);
if (node) {
node.style.display = "none"; // block
}
}
In other words, always test if an element can be found if you're not 100% sure. To be even more pedantic:
for (var i = 3; i < len; i++) {
var node = document.getElementById(arguments[i]);
if (!node) {
throw "Element " + arguments[i] + " not found.";
}
node.style.display = "none"; // block
}

Related

problem using .split() method in a function but it works on console.log

the problem is only in the bottom function objectPutter
specifically the line with wowza.split(' '); labelled with the comment
let eq
let x = null
let bracketNum = 0
let k = 0
let pre = 0
class subEqCreator { //subEq object
constructor() {
this.precede = 0;
this.text = '';
}
parser() {
this.text += eq[k]
}
ma() {
this.text.split(' ')
}
};
function trigger() { //used for HTML onClick method
show();
brackets();
subEqDynamic()
parseEquation();
objectPutter()
};
function show() {
const recent = document.querySelector("ol");
const txt = document.getElementById('input');
eq = txt.value;
li = document.createElement('li');
li.innerText = eq;
recent.appendChild(li);
txt.value = '';
};
function brackets() { //counts how many brackets appear
for (let i = 0; i < eq.length; i++) {
if (eq[i] == "(") {
bracketNum++;
};
};
};
let subEqDynamic = function() { // creates a new object for each bracket
for (let count = 0; count <= bracketNum; count++) {
this['subEq' + count] = x = new subEqCreator()
};
};
function parseEquation() { // assign characters to SubEq object
let nextIndex = 0;
let currentIndex = 0;
let lastIndex = [0];
let eqLen = eq.length;
let nex = this['subEq' + nextIndex]
for (k; k < eqLen; k++) {
if (eq[k] == "(") {
nextIndex++;
pre++
this['subEq' + currentIndex].text += '( )';
this['subEq' + nextIndex].precede = pre;
lastIndex.push(currentIndex);
currentIndex = nextIndex;
} else if (eq[k] == ")") {
pre--
currentIndex = lastIndex.pop();
} else {
this['subEq' + currentIndex].parser()
}
}
}
function objectPutter() {
for (let i = 0; i < bracketNum; i++) {
let wowza = this['subEq' + i].text
wowza.split(' '); // 🚩 why isnt it working here
console.log(subEq0);
for (let j = 1; j <= wowza.length; j += 2) { // for loop generates only odds
let ni = i++
wowza.splice(j, 0, this['subEq' + ni])
console.log(i)
}
}
}
to fix this i tried;
making a method for it ma() in the constructor.
putting in the function parseEquation above in case it was a scope issue.
also, i noticed subEq0.split(' ') worked in browser console even replicating it to the way i done it using this['subEq' + i].text.split(' ') where i = 0.
After it runs the it says .splice is not a function and console.log(subEq0) shows subEq0.text is still a string
.split() does not change the variable it returns the splitted variable

How to avoid "maximum call stack size exceeded" exception?

I have the next code for generating sitemap tree by urls list.
C# model:
public class Node
{
public Node(string child, string parent)
{
Child = child;
Parent = parent;
}
public string Parent { get; set; }
public string Child { get; set; }
public bool IsRoot { get; set; }
}
C# method that generates list of nodes.
private static List<Node> ExtractNode(List<string> Urls)
{
List<Node> nodeList = new List<Node>();
foreach (string itm in Urls)
{
string[] arr = itm.Split('/');
int index = -1;
foreach (string node in arr)
{
index += 1;
if (index == 0)
{
Node rootNode = new Node(node, "");
if (!nodeList.Exists(x => x.Child == rootNode.Child & x.Parent == rootNode.Parent))
{
rootNode.IsRoot = true;
nodeList.Add(rootNode);
}
}
else
{
Node childNode = new Node(node, arr[index - 1].ToString());
{
if (!nodeList.Exists(x => x.Child == childNode.Child & x.Parent == childNode.Parent))
{
nodeList.Add(childNode);
}
}
}
}
}
return nodeList;
}
Javascript code. Next function takes list of nodes:
function makeTree(nodes) {
var roots = [];
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].IsRoot) {
roots.push(nodes[i].Child);
}
}
var trees = "";
for (var j = 0; j < roots.length; j++) {
trees += "<div class='sitemapRoot'><ul><li>" + getChildren(roots[j], nodes) + "</li></ul></div>";
}
return trees;
}
And next one called recursively:
function getChildren(root, nodes) {
var result = "";
var index = 0;
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].Parent == root) {
index += 1;
}
}
if (index > 0) {
var RootHeader = "";
for (var j = 0; j < nodes.length; j++) {
if (nodes[j].IsRoot & root == nodes[j].Child) {
RootHeader = nodes[j].Child;
}
}
result += RootHeader + "<ul>\n";
for (var k = 0; k < nodes.length; k++) {
if (nodes[k].IsRoot & root == nodes[k].Child) {
RootHeader = nodes[k].Child;
}
if (nodes[k].Parent == root) {
result += "<ul><li>" + nodes[k].Child + getChildren(nodes[k].Child, nodes) + "</li></ul>\n";
}
}
result += "</ul>\n";
return result;
}
return "";
}
This code works good for a small set of data. But when I try to pass list of 500 nodes I get next error:
Uncaught RangeError: Maximum call stack size exceeded
at getChildren (treeGenerator.js:371)
So, the question is how I can optimize code to avoid this error?
There are two ways that you can fix this issue. You always have to worry about the call stack size when you use recursive functions. If you believe it is an issue, then you need to go asynchronous or refactor to not be recursive. These aren't necessarily the most optimized answers but hopefully they'll get you started.
Non-Recursive function
function makeTree(nodes) {
var roots = [],
limbs = [],
i, j;
//go through all of the nodes and link the parent/children.
for (i = 0; i < nodes.length; i++) {
for (j = i + 1; j < nodes.length; j++) {//only look at the rest of the elements to increase performance
if (nodes[i].Child == nodes[j].Parent) {
nodes[i].children = (nodes[i].children || []);
nodes[i].children.push(nodes[j]);
nodes[j].parentNode = nodes[i];
}
}
for (j = 0; j < limbs.length; j++) {//look through the limbs to see if one of them is my child.
if (nodes[i].Child == limbs[j].Parent) {
nodes[i].children = (nodes[i].children || []);
nodes[i].children.push(limbs[j]);
limbs[j].parentNode = nodes[i];
limbs.splice(j--, 1);//remove from the list since I can only have 1 parent.
}
}
//I have all of my children.
if (nodes[i].IsRoot) {
roots.push(nodes[i]);
}else if(!nodes[i].parentNode){
//I don't know my parent so I'm a limb.
limbs.push(node);
}
}
//now that everyone knows their parent and their children, we'll assemble the html by looking at all of the leafs first and working way up the tree.
i = 0;
while(nodes.length > 0){
if(!nodes[i].children || nodes[i].childHtml){
//I'm either a leaf or I have my child's html.
var node = nodes[i];
node.html = node.Child + (node.childHtml? "<ul>" + node.childHtml + "</ul>" : "");
node.childHtml = null;//don't need this anymore.
if(node.parentNode){
//let's check to see if my siblings are complete
var ready = true,
childHtml = "";
for(var j = 0; j < node.parentNode.children.length; j++){
if(node.parentNode.children[j].html == null){
ready = false;//I don't know this html yet so skip it for now.
break;
}else{
childHtml += "<li>" + node.parentNode.children[j].html + "</li>";//go ahead and try to create the list of children.
}
}
if(ready){
//all of siblings are complete, so update parent.
node.parentNode.childHtml = childHtml;
node.parentNode.children = null;//remove reference for cleanup.
}
}
nodes.splice(i, 1);//remove from the list since I have my html.
}else{
i++;//look at the next node in the list.
}
if(i >= nodes.length){
i = 0;//since we are splicing and going through the list multiple times (possibly), we'll set the index back to 0.
}
}
//every node knows it's html, so build the full tree.
var trees = "";
for (var j = 0; j < roots.length; j++) {
trees += "<div class='sitemapRoot'><ul><li>" + roots[j].html + "</li></ul></div>";
}
return trees;
}
Asynchronous Recursive function
function makeTreeAsync(nodes, callback) {
var roots = [],
numRoots = 0;
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].IsRoot) {
numRoots++;
getChildrenAsync(nodes[i], nodes, create);
}
}
function create(child){
roots.push(child);
if(roots.length === numRoots){
var trees = "";
for (var j = 0; j < roots.length; j++) {
trees += "<div class='sitemapRoot'><ul><li>" + roots[j].html + "</li></ul></div>";
}
callback(trees);
}
}
}
function getChildrenAsync(root, nodes, callback) {
var result = "";
var index = 0;
var children = [];
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].Parent == root.Child) {
index += 1;
getChild(i);
}
}
if (index == 0) {
root.html = root.Child;
callback(root);
}
function getChild(x){
setTimeout(function(){
getChildrenAsync(nodes[x], nodes, createHtml);
});
}
function createHtml(node){
children.push(node);
if(children.length === index){
var result = root.Child;
if(children.length){
result += "<ul>"
for (var j = 0; j < children.length; j++) {
result += "<li>" + children[j].html + "</li>";
}
result += "</ul>";
}
root.html = result;
callback(root);
}
}
}
I used the following to create trees for testing the code:
function makeTestNodes(numRoots, numChildrenPerRoot){
var nodes= [];
for(var i = 0;i < numRoots;i++){
nodes.push({
Parent: "",
Child: i.toString(),
IsRoot: 1
});
var parent = i.toString();
for(var j = 0;j < numChildrenPerRoot;j++){
var child = parent + "." + j.toString();
nodes.push({
Parent: parent,
Child: child,
IsRoot: 0
});
nodes.push({
Parent: parent,
Child: parent + "." + j.toString() + "a",
IsRoot: 0
});
parent = child;
}
}
return nodes;
}
Use the following snippet to call the two functions with the test nodes:
Note: the following uses jquery to get the body node. I called the following snippet when the page was ready.
var body = $("body");
body.append(makeTree(makeTestNodes(20, 50)));
makeTreeAsync(makeTestNodes(20, 50), function(html){
body.append(html);
});

Passing loop counter as argument in Node.js

I was trying this as a tutorial from nodeschool, and I'm new to Node.js. The code is below, and I know the problem in it, but I am not able to resolve it. The problem is that j has a value of 3 for every iteration of the loop inside the bl function, but Why is that happening?
var bl = require('bl');
var http = require('http');
var urls = process.argv.slice(2);
var result = [];
for (var i = 0; i < urls.length; i++) {
result.push(null);
}
for(j = 0 ; j < urls.length; ++j){
http.get(urls[j],function(response){
response.pipe(bl(function(err,data){
//console.log(result[i]);
//console.log(data.toString());
result[j] = data.toString();
console.log('J : ' + j);
console.log(data.toString());
var flag = 0;
for (var i = 0; i < result.length; i++) {
console.log('here1');
console.log(result[i]);
if(result[i] == null){
flag = 1;
console.log('here');
break;
}
}
if(flag == 0){
for (var i = 0; i < result.length; i++) {
console.log(result[i]);
}
}
}));
});
}
http.get is an async request but the for is sync so for is "most fast" and when http.get finish to download the url data then variable "j" takes last value.
You have another mistake I think, on your for loop you increase variable "j" as "++j" and it will be "j++".
To fix the first issue (variable "j" value) you can use an anonymous function and pass the value "j" like:
for(j = 0 ; j < urls.length; j++) {
(function(j) {
http.get(urls[j],function(response){
response.pipe(bl(function(err,data){
//console.log(result[i]);
//console.log(data.toString());
result[j] = data.toString();
console.log('J : ' + j);
console.log(data.toString());
var flag = 0;
for (var i = 0; i < result.length; i++) {
console.log('here1');
console.log(result[i]);
if(result[i] == null){
flag = 1;
console.log('here');
break;
}
}
if(flag == 0){
for (var i = 0; i < result.length; i++) {
console.log(result[i]);
}
}
}));
});
}(j));
}
There are a lot of code but in resume i did this:
for(j = 0 ; j < urls.length; j++) {
(function(j) {
/* your code inside this function will have the correct
value to variable "j" if you use async methods */
} (j));
}

remove null value in javascript

am having script with working condition but many for loop is there so any way to do this...to simplify this ...am new to script kindly help on this....
function change()
{
//document.getElementById("Geography").options[7]=new Option("", "newval", true, false);
var geo = document.getElementById("Geography").options;
var zon = document.getElementById("zone").options;
var coun = document.getElementById("country").options;
for (var i = 0; i < geo.length; i++)
{
if (geo[i].innerHTML == "Null Value" || geo[i].innerHTML == "")
{
document.getElementById("Geography").options[i] = null;
}
}
for (var i = 0; i < coun.length; i++)
{
alert("Loop1" + i);
if (coun[i].innerHTML == "Null Value")
{
document.getElementById("country").options[i] = null;
}
}
for (var i = 0; i < zon.length; i++)
{
//alert("Loop1" + i);
if (zon[i].innerHTML == "Null Value")
{
document.getElementById("zone").options[i] = null;
}
}
}
To remove an option, call removeChild() on the parent element.
var geoSel = document.getElementById("Geography");
var geo = geoSel.options;
for (var i = geoSel.options.length-1; i >= 0; i--) {
if (geo[i].innerHTML == "Null Value" || geo[i].innerHTML == "") {
geo.removeChild(geo[i]);
}
}
I count down instead of up because removing a child will cause the indexes of all the following children to be shifted down. In a count-up loop, that will cause elements to be skipped.
use this UPDATED DEMO
function change(){
var optionsArr = [];
optionsArr.push(document.getElementById("Geography").options);
optionsArr.push(document.getElementById("zone").options);
optionsArr.push(document.getElementById("country").options);
var optArrlenght = optionsArr.length;
for ( var j = 0; j < optArrlenght; j++){
var options = optionsArr[j];
var optionslength = options.length;
for (var i = 0; i < optionslength; i++)
{
if (options[i].innerHTML == "Null Value" || options[i].innerHTML == "")
{
options[i].remove();
i--;
optionslength--;
}
}
}
}
change();

Validation is not used while my conditions are met.

Here is my code:
function getTable(strExp){
this.strExp = strExp;
console.log(strExp);
var strTBL = "";
if (strExp === "Res"){
for (var it = 0; it > 3; it++){
strTBL = strTBL + jsonData.Table.ResTBL[it];
console.log("Im in");
}
}
else if (valeur === "Dice"){
}
return strTBL;
}
In my script I do this call : document.getElementById("ResTBL").innerHTML = getTable("Res")
When I see my console log I don't see the I'm in log, but it gives me the value of strExp.
Just place it < 3 in a cycle
for (var it = 0; it < 3; it++) {
strTBL = strTBL + jsonData.Table.ResTBL[it];
console.log("Im in");
}

Categories

Resources