Genéricos roteiro click-to-renomeação em JavaScript (texto para entrada / caixa de texto)
-
06-07-2019 - |
Pergunta
Escrevendo um widget para ser capaz de renomear arquivos, clicando sobre o nome do texto e digitar o novo nome. I não encontrou quaisquer soluções ready-to-use, talvez você possa me apontar para um?
Aqui é onde eu acabei e ele não funciona: por alguma razão, apenas a última caixa de entrada está mudando, e o primeiro eo segundo não são referenciados:
<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>
Graças.
Solução
Este é um problema de ligação ciclo-variável clássico. Consulte esta questão para alguma discussão.
Seu fechamento é ineficaz porque se fecha sobre a cópia do changer
em uso dentro do loop, que o loop vai mudar. Para ligá-la, você precisa de outro encerramento, que terá uma cópia da versão atual do changer
:
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);
(Você pode preferir abandonar o argumento node
e apenas this
uso.)
No futuro (ECMAScript Fifth Edition), haverá uma maneira mais rápida e mais eficiente para dizer o seguinte:
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);
}
mas, entretanto, uma vez que a maioria dos navegadores não suportam function.bind
ainda, você pode cortar que em assim:
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))
);
};
};
}
Outras dicas
Se você não se importa a dependência jQuery, eu usei jquery-in-place-editor para editar campos antes.
O problema é que, quando as funções de ouvinte adicionado aqui fogo, eles contêm referências à variável "trocador" global. No momento em que disparar o circuito já foi concluída, e assim "trocador" aponta para o último item do loop.
Além disso, a adição de ouvintes pode ser confuso cross-browser, é mais seguro usar uma biblioteca como jQuery ou YUI a fazê-lo. Isso também irá permitir que você passe um objeto para cada ouvinte de evento (de uma forma cross-browser), por isso, por exemplo, você poderia fazer:
for (var i=0; i < 3; i++) {
var changer = new TextChanger(i);
YAHOO.util.Event.addListener(changer.textNode, "click", changer.change, changer);
...