2009-12-13 5 views
0

HTML 및 JavaScript로 리치 텍스트/wysiwyg 편집기 구성 요소를 구축하고 있습니다. 컬러 피커에 대한 이미지 입력 ​​요소가 포함 된 툴바 항목의 정렬되지 않은 목록이 있습니다. 색상 선택기는 입력 요소의 click 이벤트에 표시되는 오버레이입니다.JavaScript, DOM 흐림/포커스, 드롭 다운

문제 :

나는 초점이 도구 모음 항목 입력 요소에서 손실 된 경우 색상 선택기 오버레이 숨기려. 따라서 입력 요소의 blur 이벤트를 처리하고 색상 피커 오버레이에서 hide를 호출합니다. 입력 요소의 blur 이벤트가 색상 선택기 오버레이 내부의 click 이벤트 핸들러보다 먼저 발생하기 때문에 약간의 타임 아웃도 사용합니다. IE에서는이 모든 것이 잘 작동하지만 파이어 폭스에서는 타임 아웃이 내가 원하는 것보다 훨씬 더 중요합니다.

입력 요소를 앵커로 변경하고 오버레이를 배치하려고 시도했습니다. 툴바 항목에 오버레이를 클릭 할 때 여전히 포커스가 있다고 말하는 오히려 재미있었습니다.

사람들은 정상적인 드롭 다운으로이 상황을 어떻게 처리합니까?

감사합니다, 벤

무섭게 단순화, 비 OOP 예 :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml" > 
    <head> 
     <title>Test</title> 
     <style type="text/css"> 
      .richTextEditor 
      { 
      } 
      .richTextEditor .toolbar 
      { 
      } 
      .richTextEditor iframe 
      { 
       border: 1px solid #000; 
       background: #FFF; 
      } 
     </style> 
    </head> 
<body> 
    <div id="notes" class="richTextEditor"> 
     <ul class="toolbar"> 
      <li command="bold"><input type="button" value="Bold" /></li> 
      <li command="foreColor"><input type="button" value="Show Colour Picker" /></li> 
     </ul> 
     <iframe frameborder="0"></iframe> 
    </div> 
    <script type="text/javascript"> 
     var notes = document.getElementById("notes"); 
     var editorElement = notes.getElementsByTagName("IFRAME")[0]; 
     var colourPicker = null; 

     function showColourPicker(toolbarItemElement) { 
      if (!colourPicker) { 
       colourPicker = document.createElement("DIV"); 
       var red = document.createElement("A"); 
       red.href = "javascript:void(0);"; 
       red.style.backgroundColor = "red"; 
       red.innerHTML = "red"; 
       red.onclick = function() { 
        var toolbarItemCommand = toolbarItemElement.getAttribute("command"); 
        editorElement.contentWindow.focus(); 
        editorElement.contentWindow.document.execCommand(toolbarItemCommand, false, "rgb(255,0,0)"); 
        editorElement.contentWindow.focus(); 
        colourPicker.style.display = "none"; 
       }; 
       colourPicker.appendChild(red); 
       document.body.appendChild(colourPicker); 
      } else { 
       colourPicker.style.display = "block"; 
      } 
      toolbarItemElement.getElementsByTagName("INPUT")[0].onblur = function() { 
       window.setTimeout(function() { 
        colourPicker.style.display = "none"; 
       }, 100); 
      }; 
     } 

     function toolbarItemInputElement_click(e) { 
      var e = e || window.event; 
      var target = e.target || e.srcElement; 
      while (target.tagName != "LI") { 
       target = target.parentNode; 
      } 
      var toolbarItemCommand = target.getAttribute("command"); 
      if (toolbarItemCommand == "foreColor" || toolbarItemCommand == "backColor") { 
       showColourPicker(target); 
      } else { 
       editorElement.contentWindow.focus(); 
       editorElement.contentWindow.document.execCommand(toolbarItemCommand, false, null); 
       editorElement.contentWindow.focus(); 
      } 
      if (e.preventDefault) { 
       e.preventDefault(); 
      } else { 
       e.cancelBubble = true; 
      } 
      return false; 
     } 


     window.onload = function() { 
      // turn on design mode 
      editorElement.contentWindow.document.designMode = "on"; 

      // attach toolbar item event handlers 
      var toolbarItemElements = document.getElementsByTagName("LI"); 
      for (var i = 0; i < toolbarItemElements.length; i++) { 
       var toolbarItemInputElement = toolbarItemElements[i].getElementsByTagName("INPUT")[0]; 
       toolbarItemInputElement.onclick = toolbarItemInputElement_click; 
      } 
     }; 
    </script> 
</body> 
</html> 

그것은 상당히 무작위, 그래서 당신을 위해 일하지 않는 경우 페이지를 새로 고침 몇 번을 시도해보십시오. Firefox에서 다음을 수행합니다.

  1. 마우스를 사용하여 iFrame에 포커스를 설정하십시오.
  2. 유형 111space222space333space444 (여기서 space는 스페이스 바이며 word space가 아닙니다!).
  3. "222"를 두 번 클릭하면 강조 표시됩니다.
  4. "색상 선택기 표시"를 클릭하십시오.
  5. "빨간색"을 클릭하십시오.
  6. Firefox에서 아무 일도 일어나지 않습니다.

100ms가 충분하지 않습니까? 무엇이 될까요?

다시 한번 감사드립니다.

+0

Fx의 시간 초과 지연은 얼마나 더 큽니까?일반적으로 스레드가 유휴 상태 일 때 (모든 이벤트가 시작되고 전파되면) 0ms의 시간 만료로 충분합니다. 몇 가지 예제 소스 코드를 게시 할 수 있습니까? –

+0

내 생각은 정확하게 - 나는 다른 일이 벌어지고있는 것 같지만 확실히 식별 할 수는 없다. 나는 곧 버전을 줄이려고 노력할 것이다. 감사. –

+0

예제가 게시되었습니다. –

답변

0

입력 요소를 앵커로 변경하는 대신 입력 및 오버레이를 앵커 또는 blur 이벤트를 발생시키는 다른 요소로 래핑하고 거기에 이벤트 처리기를 첨부하십시오.

나는 도구 모음 및 기타 컨트롤 위에있는 요소에서 mousemove 이벤트 처리기를 사용할 수 있으며 오버레이 또는 입력에서 오버레이 및 입력으로 이동하는 것을 기준으로 상태를 변경할 수 있다고 생각합니다.

타임 아웃의 경우 이 아닌은 0ms를 사용하지만 1ms는 사용하는 이유가 있음을 상기합니다.

편집 : onblur를 대체하기 위해 mousemove/event 위임을 사용하는 것에 대한 링크 추가.

PPK: Delegating the focus and blur events

+0

내가 잘못 본 것이 아니라면 포커스 및 흐림 이벤트가 거품을 일으키지 않으므로 이벤트 핸들러를 입력 요소가 아닌 컨테이너 요소에 배치하면 이벤트가 실행되지 않습니다. mousemove 아이디어는 건전하지만 아직 필사적이지 않습니다. 5 분 더 줘! 타임 아웃은 실제로 0ms보다 커야하지만, 방금 게시 한 예에서는 약 90ms보다 커야합니다 (IE의 경우, Firefox의 경우 더 큼). 아이디어를 제공해 주셔서 감사합니다. –