简体   繁体   中英

Iterate through an array in javascript to produce buttons on a form

Thanks for taking the time to read this question.

I have been working on a greasemonkey script (just loads an additional javascript on to a page to alter the content) to add buttons to a web form for a site I use a lot.

var gt_all_the_stocks = [
    [   // Greetings
        ["Getting in touch", "Thank you for getting in touch,\n\n", "", "", "Added thank you", "",],
        ["Time on phone", "Thank you for your time on the phone today,\n\n", "", "", "Added thank you", "",],
        ["Getting back", "Thank you for getting back to us,\n\n", "", "", "Added thank you", "",],
    ],
    [   // Faults Stocks
        ["SFI Required", "An engineer is needed", "", "", "", "", ],    
    ]
];

The array is formatted with each row of buttons being a separate array and each button being an element on that row. So given the array above I should have two rows of buttons created, the first should contain 3 buttons and the second 1 button.

I have written the following:

//Create a button function
function addButton(container, text, onclickFunc) {
    // Create a new button
    var buttonnode= document.createElement('input');

    // Set some generic attributes
    buttonnode.setAttribute('type','button');
    buttonnode.setAttribute('name',text);
    buttonnode.setAttribute('value',text);
    buttonnode.setAttribute('class', 'gt_buttons');

    // Attach the event
    container.appendChild(buttonnode)
    buttonnode.addEventListener("click", onclickFunc, true);

    // Return it
    return buttonnode;
}

// Iterate through the array and make the buttons
for (var i1 = 0; i1 < gt_all_the_stocks.length; i1++) {

    console.log("Setting up row #" + i1 + " " + typeof i1);
    row = i1;

    for (var i2 = 0; i2 < gt_all_the_stocks[i1].length; i2++) {

        button = i2;

        addButton(make_div_above, gt_all_the_stocks[row][button][0], function(){
            if ( gt_all_the_stocks[row][button][1].length != 0 ){
                surround("", gt_all_the_stocks[row][button][1]);
            }
            if ( gt_all_the_stocks[row][button][2].length != 0 ){
                setSMS(gt_all_the_stocks[row][button][2]);
            }
            if ( gt_all_the_stocks[row][button][3].length != 0 ){
                setSignoff(gt_all_the_stocks[row][button][3]);
            }
            if ( gt_all_the_stocks[row][button][4].length != 0 ){
                console.log("Stock Tickets: " + gt_all_the_stocks[row][button][4]);
            }
            if ( gt_all_the_stocks[row][button][5].length != 0 ){
                setCause(gt_all_the_stocks[row][button][5]);
            }
        });
    }
    addHr(make_div_above);

}

The problem arises with the buttons that are created. The name on the buttons changes with each button, so the first button created in this instance has "Getting in touch" on it, while the second has "Time on phone" on it. However when the button is clicked the text that is generated is the text from the last button in the array.

Basically if you click the button that says "Getting in touch" the text that comes out is "An engineer is needed", the text that relates to the button "SFI Required".

This might be a little bit of a rambling question but I am finding it difficult to say exactly what the problem is. My guess is that the variables row and button are being replaced on each iteration and the addButton function does not store the text and each iteration is replacing the text that is created.

Potentially this would mean that generating a different variable name on each iteration, maybe something like title_button_row so for the title of the second button on row 3 would be title_1_2 but not sure how to do that. PHP supports variable variable names like $title_$button_$row but I have no idea how to implement this is Javascript or even if this is a solution to this problem.

I have put up a gist of the whole script here for reference https://gist.github.com/lgoldstien/5890269

Again, thanks for reading and I look forward to your responses.

Calling functions which deals with DOM from loops results in issues like you are experiencing. To overcome this, peoples use various approaches like Array.forEach , Closures

Wrap addButton call inside a self executing anonymous function & pass the variables to it. Your problem will be solved. I am not sure you are a fan for Array.forEach . So I proposed Closure approach here.

Like this:(Just the for loop part)

for (var i1 = 0; i1 < gt_all_the_stocks.length; i1++) {

console.log("Setting up row #" + i1 + " " + typeof i1);
row = i1;

for (var i2 = 0; i2 < gt_all_the_stocks[i1].length; i2++) {

    button = i2;

    (function(r, btn) {
      addButton(make_div_above, gt_all_the_stocks[r][btn][0], function(){
        if ( gt_all_the_stocks[r][btn][1].length != 0 ){
          surround("", gt_all_the_stocks[r][btn][1]);
        }
        if ( gt_all_the_stocks[r][btn][2].length != 0 ){
          setSMS(gt_all_the_stocks[r][btn][2]);
        }
        if ( gt_all_the_stocks[r][btn][3].length != 0 ){
          setSignoff(gt_all_the_stocks[r][btn][3]);
        }
        if ( gt_all_the_stocks[r][btn][4].length != 0 ){
          console.log("Stock Tickets: " + gt_all_the_stocks[r][btn][4]);
        }
        if ( gt_all_the_stocks[r][btn][5].length != 0 ){
          setCause(gt_all_the_stocks[r][btn][5]);
        }
      });
    })(row, button);
}
addHr(make_div_above);

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM