0

フラッシュカードのセット (スタック) を配列に格納する JavaScript Web アプリに取り組んでいます。

現在、ループ内のクロージャーに問題があります。この例 ( https://stackoverflow.com/a/15466863/1822824 ) を確認し、同様のものを実装しようとしましたが、「TypeError: 'null' はオブジェクトではありません ('document.getElementById(temp を評価しています) )')」。

Web アプリは、フラッシュカードのすべてのセット (スタック) をリンクとしてリストする必要があります。リンクをクリックすると、クリックしたフラッシュカード スタックの名前が表示されます。警告するリンク部分を追加しようとするまで、すべてがうまくいきました。

フィドル: http://jsfiddle.net/xmYug/

以下は私のコードです:

<p>
<strong>Flashcard Stack Name:</strong>
<input type="text" id="textStackName">
</p>
<p>
<strong>Enter one flashcard per line, seperate the front and back of each flashcard with a comma:</strong><br>
<textarea name="textarea" id="textareaFlashcards" cols="45" rows="15"></textarea> 
</p>
<p>
<input type="submit" id="buttonSubmit" value="Submit">
</p>
<div id="allStacks">
</div>

<script>
var funcs = [];

function createfunc(i) {
    var temp = "link" + i;

    return document.getElementById(temp).onclick = function() {
        // Alert the user of the stack name they just clicked on
        alert("Stack name: " + allStacks[i].stackName);
    };
}

/* Constructors */
// Constructs a new stack of flashcards - a stack of flashcards is usually about a single topic such as States & Capitals
function newStackConstructor(stackName) {
    this.stackName = stackName;
    this.stack = new Array();
}

// Constructs a new flashcard - a stack can have an unlimited number of flashcards
function newFlashcardConstructor(flashcardFront, flashcardBack) {
    this.flashcardFront = flashcardFront;
    this.flashcardBack = flashcardBack;
}

// Contains all of the flashcard stacks
var allStacks = new Array();

// SAMPLE DATA //////////////////////////////////////////////////////////////////////
// Make a test stack
allStacks.push(new newStackConstructor("States & Capitals"));

// Test data
allStacks[0].stack.push(new newFlashcardConstructor("Alabama", "Montgomery"));
allStacks[0].stack.push(new newFlashcardConstructor("Alaska", "Juneau"));
allStacks[0].stack.push(new newFlashcardConstructor("Arizona", "Phoenix"));
////////////////////////////////////////////////////////////////////////

buttonSubmit.onclick = function () { 
    newFlashcardStack();
};

// Make a new flashcard stack
function newFlashcardStack() {
    allStacks.push(new newStackConstructor(textStackName.value));

    var textareaFlashcardsTemp = textareaFlashcards.value;

    // Split flashcards by line break
    var flashcards = textareaFlashcardsTemp.split("\n");

    for (var i = 0; i < flashcards.length; i++) {

        // Split front & back of flashcards by comma
        flashcard = flashcards[i].split(",");

        allStacks[(allStacks.length - 1)].stack.push(new newFlashcardConstructor(flashcard[0], flashcard[1]));
    }

    // Update stack display to display all of the stacks and the new stack
    displayAllStacks();
}

// Display all flashcard stacks
function displayAllStacks() {
    // Clear stack display
    document.getElementById("allStacks").innerHTML = "";

    for (var i = 0; i < allStacks.length; i++) {
        funcs[i] = createfunc(i);

        document.getElementById("allStacks").innerHTML += '<p><a href="#" id="link' + i + '">' + allStacks[i].stackName + '</a></p>';
    }
}

displayAllStacks();
</script>
4

1 に答える 1

2

クリックハンドラーを割り当てるクロージャーがそのハンドラーを返し、それらすべてをそのfuncs配列に格納する理由がわかりません。

しかし、

funcs[i] = createfunc(i);
document.getElementById("allStacks").innerHTML += '<p><a href="#" id="link' + i + '">' + allStacks[i].stackName + '</a></p>';

その要素を作成する前であっても、ハンドラー関数を作成して割り当てようとします。まだ、

document.getElementById("allStacks").innerHTML += '<p><a href="#" id="link' + i + '">' + allStacks[i].stackName + '</a></p>';
funcs[i] = createfunc(i);

innerHTML現在のDOMを上書きし、イベントハンドラーが割り当てられていない新しいリンクを作成するように割り当てると、同様に機能しなくなります。代わりに、

var display = document.getElementById("allStacks");
display.innerHTML = "";
for (var i=0; i<allStacks.length; i++) {
    var p = document.createElement("p");
    var a = document.createElement("a");
    p.appendChild(a);
    a.appendChild(document.createTextNode(allStacks[i].stackName));
    a.href="#";
    // a.id = "link"+i; is not necessary
    var func = (function(i) {
        return function() {
            // Alert the user of the stack name they just clicked on
            alert("Stack name: " + allStacks[i].stackName);
        };
    })(i);
    // funcs[i] = func; if you want that
    a.onclick = func;

    display.appendChild(p);
}
于 2013-03-23T20:37:07.843 に答える