Универсальный скрипт click-to-rename в JavaScript (текст для ввода / текстовое поле) - PullRequest
1 голос
/ 25 октября 2009

Написание виджета для возможности переименования файлов, нажав на текстовое имя и введя новое имя. Я не нашел готовых решений, может быть, вы можете указать мне одно?

Вот где я оказался, и он не работает: по какой-то причине меняется только последнее поле ввода, а на первое и второе не ссылаются:

<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>

Спасибо.

Ответы [ 3 ]

1 голос
/ 25 октября 2009

Это классическая проблема привязки петли-переменной. См. этот вопрос для обсуждения.

Ваше закрытие неэффективно, потому что оно закрывается поверх копии changer, используемой внутри цикла, который изменится цикл. Чтобы связать его, вам нужно другое закрытие, чтобы взять копию текущей версии 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);

(Вы можете отказаться от аргумента node и просто использовать this.)

В будущем (пятое издание ECMAScript) будет более быстрый и эффективный способ сказать это:

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);
}

но тем временем, поскольку большинство браузеров пока не поддерживают function.bind, вы можете взломать это следующим образом:

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))
            );
        };
    };
}
0 голосов
/ 25 октября 2009

Проблема в том, что, когда здесь добавляются функции слушателя, они содержат ссылки на глобальную переменную "changer". В тот момент, когда они запускают цикл, он уже завершен, поэтому «изменитель» указывает на последний элемент цикла.

Кроме того, добавление слушателей может привести к путанице между браузерами, для этого безопаснее использовать такие библиотеки, как jQuery и YUI Это также позволит вам передавать объект каждому слушателю событий (кросс-браузерным способом), например, вы можете сделать:

for (var i=0; i < 3; i++) {
                var changer = new TextChanger(i);
                YAHOO.util.Event.addListener(changer.textNode, "click", changer.change, changer); 
                ...
0 голосов
/ 25 октября 2009

Если вы не возражаете против зависимости jQuery, я использовал jquery-in-place-editor для редактирования полей раньше.

...