2009-10-25 7 views
1

텍스트 이름을 클릭하고 새 이름을 입력하여 파일 이름을 바꿀 수있는 위젯 작성. 바로 사용할 수있는 솔루션을 찾지 못했습니다. 나는 결국 그것이 작동하지 않는 경우 다음JavaScript의 일반적인 클릭하면 이름 바꾸기 스크립트 (텍스트 입력/텍스트 상자)

이다 : 어떤 이유로, 마지막 입력 상자는 변경 및 제 1 및 제 2 참조되지 않은된다

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

감사합니다.

+0

답변을 수락하는 것이 예의입니다. (수표를 클릭하십시오.) 도움이되었거나 뭔가 가르쳐 준 다른 답변에 투표 할 수도 있습니다. –

답변

1

이것은 고전적인 루프 변수 바인딩 문제입니다. 자세한 내용은 this question을 참조하십시오.

클로저는 루프 내에서 사용중인 changer 사본을 덮어 쓰므로 효과가 없습니다. 루프가 변경됩니다. 바인딩하려면 changer의 현재 버전의 복사본을 가지고 다른 폐쇄가 필요합니다. (당신은 node 인수를 도랑을 선호 그냥 this을 사용할 수있다)

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

을 앞으로

(ECMAScript를 대부분의 브라우저는 아직 function.bind을 지원하지 않기 때문에

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

하지만 그 동안

,이 같은 것을 해킹 할 수 있습니다 : 제 5 판)은이 말을 더 빠르고 효율적인 방법이있을 것

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

의미가 있습니다, 많이 고마워요! –

0

jQuery 의존성에 신경 쓰지 않는다면, 전에 필드를 편집하려면 jquery-in-place-editor을 사용했습니다.

+0

고마워요. 완벽하게 작동합니다. –

0

여기에 리스너 함수가 추가되면 전역 변수 "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

감사합니다. 지금은 이유가 있습니다. 자바 스크립트는 'by-ref'를 사용하고 'by-value'는 사용하지 않습니다. –

관련 문제