Frage

ein Widget Schreiben der Lage sein, Dateien umbenennen, indem Sie auf den Textnamen klicken und den neuen Namen eingeben. Ich habe keine ready-to-use-Lösungen finden, vielleicht können Sie mich auf einen Punkt?

Hier ist, wo ich am Ende und es funktioniert nicht: aus irgendeinem Grund, nur das letzte Eingabefeld verändert sich, und die erste und die zweite nicht referenziert:

<span id="text_name_0">Hello, world. Click me please.</span>
<input type="hidden" id="name_changer_0" />
<input type="hidden" id="done_changing_0" value="Done"/>
<br/>
<span id="text_name_1">Hello, world. Click me please.</span>
<input type="hidden" id="name_changer_1" />
<input type="hidden" id="done_changing_1" value="Done"/>
<br/>
<span id="text_name_2">Hello, world. Click me please.</span>
<input type="hidden" id="name_changer_2" />
<input type="hidden" id="done_changing_2" value="Done"/>

<script type="text/javascript">

function TextChanger(id) {
    this.textNode = document.getElementById('text_name_' + id);
    this.textValue = this.textNode.firstChild.nodeValue;
    this.textboxNode = document.getElementById('name_changer_' + id);
    this.doneButton = document.getElementById('done_changing_' + id);
}   

TextChanger.prototype.change = function(node) {
          node.textboxNode.setAttribute('value', node.textValue);
          node.textNode.style.display = 'none';
          node.textboxNode.setAttribute('type','text');
          node.doneButton.setAttribute('type','button');
}   

TextChanger.prototype.changeBack = function(node) {
          node.textNode.firstChild.nodeValue = node.textboxNode.value;
          node.textNode.style.display = 'block';
          node.textboxNode.setAttribute('type', 'hidden');
          node.doneButton.setAttribute('type','hidden');
}

for (var i=0; i < 3; i++) {
        changer = new TextChanger(i);
        changer.textNode.addEventListener("click", function() {
            changer.change(changer);
        }, false);

        changer.doneButton.addEventListener("click", function() {
            changer.changeBack(changer);
        }, false);
}
</script>

Danke.

War es hilfreich?

Lösung

Dies ist ein klassisches Schleife variable Bindungsproblem. Siehe diese Frage für einige Diskussion.

Ihre Schließung ist unwirksam, weil sie über die Kopie changer im Gebrauch innerhalb der Schleife schließt, die die Schleife wird sich ändern. So binden Sie es, Sie brauchen eine andere Schließung eine Kopie der aktuellen Version von changer zu nehmen:

function changebind(c) {
    return function() {
        c.change(c);
    };
}

for (var i=0; i<3; i++) {
    var changer= new TextChanger(i);
    changer.textNode.addEventListener('click', changebind(changer), false);

(Sie bevorzugen das node Argument zu Graben und nur this verwenden.)

In der Zukunft (ECMAScript Fifth Edition), wird es eine schnellere und effizientere Art und Weise, dies zu sagen:

for (var i=0; i<3; i++) {
    var changer= new TextChanger(i);
    changer.textNode.addEventListener('click', changer.change.bind(changer), false);
    changer.doneButton.addEventListener('click', changer.changeBack.bind(changer), false);
}

aber in der Zwischenzeit, da die meisten Browser function.bind noch nicht unterstützen, können Sie, dass in so hacken:

if (!Object.bind) {
    Function.prototype.bind= function(owner) {
        var that= this;
        var args= Array.prototype.slice.call(arguments, 1);
        return function() {
            return that.apply(owner,
                args.length===0? arguments : arguments.length===0? args :
                args.concat(Array.prototype.slice.call(arguments, 0))
            );
        };
    };
}

Andere Tipps

Wenn Sie nicht die jQuery Abhängigkeit dagegen habe ich verwendet jquery-in-place-Editor bevor Felder bearbeiten.

Das Problem ist, dass, wenn die Zuhörer Funktionen hier Feuer hinzugefügt, sie Verweise auf die globale Variable „Wechsler“ enthalten. Zu der Zeit, sie feuern die Schleife bereits abgeschlossen, und so „Wechsler“ zeigt auf das letzte Element in der Schleife.

Zusätzlich kann das Hinzufügen Zuhörer chaotisch Cross-Browser sein, es ist sicherer, eine Bibliothek wie jQuery oder YUI zu verwenden, dies zu tun. Dies ermöglicht es Ihnen auch um ein Objekt zu jedem Ereignis-Listener übergeben (in einem Cross-Browser-Art und Weise), so zum Beispiel die Sie tun können:

for (var i=0; i < 3; i++) {
                var changer = new TextChanger(i);
                YAHOO.util.Event.addListener(changer.textNode, "click", changer.change, changer); 
                ...
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top