2012-01-01 30 views
22

kodeksu jak:wydarzenie onChange z contentEditable

...text <span contenteditable="true" onChange="someFunction()">blah blah</span> text... 

Impreza onChange nie działa. (przynajmniej w FireFox)
Nie chcę używać znaczników textarea/input, ponieważ musi istnieć możliwość zmiany tylko określonych słów w tekście i muszą być wyświetlane inline (nie blokować).

Czy jest jakikolwiek sposób to zrobić?

+1

Dlaczego nie używać 'input' element i styl dala granicy/wyściółka i zrobić w' wyświetlaczu: inline' lub 'display: inline-block' – Chad

Odpowiedz

6

Funkcja, którą napisałem:
Jedno wywołanie tej funkcji naprawia wszystkie elementy ContentEditable na stronie.

function fix_onChange_editable_elements() 
{ 
    var tags = document.querySelectorAll('[contenteditable=true][onChange]');//(requires FF 3.1+, Safari 3.1+, IE8+) 
    for (var i=tags.length-1; i>=0; i--) if (typeof(tags[i].onblur)!='function') 
    { 
    tags[i].onfocus = function() 
    { 
     this.data_orig=this.innerHTML; 
    }; 
    tags[i].onblur = function() 
    { 
     if (this.innerHTML != this.data_orig) 
     this.onchange(); 
     delete this.data_orig; 
    }; 
    } 
} 
+1

Jeśli chcesz wiedzieć o zmianach "na żywo", powyższa zasada może zostać dostosowana do działania w ramach 'setInterval' (z rozsądnymi ustawieniami interwałów i ewentualnym' clearInterval'). –

23

Niezupełnie. Najnowsze przeglądarki WebKit obsługują zdarzenia HTML5 input na elementach contenteditable, co jest idealne, ale nie jest obsługiwane w innych przeglądarkach. (AKTUALIZACJA 31 grudnia 2012: Firefox obsługuje to od wersji 14). W przeciwnym razie możesz być w stanie przetrwać dzięki DOM mutation eventsDOMNodeInserted, , DOMNodeRemoved i DOMCharacterDataModified, ale mają one dwie wady: po pierwsze, nie są one obsługiwane w IE < 9 ani żadnej wersji Opera dla elementów contenteditable, a po drugie, nowa specyfikacja z wymianami zdarzeń działa, co oznacza, że ​​prawdopodobnie zostaną zastąpione w przyszłych przeglądarkach.

żywo przykład: http://jsfiddle.net/MBags/

Albo można iść niższy poziom i uchwyt klucza, myszy i wydarzenia schowka (cut i paste), która będzie działać we wszystkich głównych przeglądarek, ale znaczy, że trzeba sprawdzić, czy Zawartość edytowalna zmieniła się za każdym razem, gdy takie zdarzenie jest uruchamiane, co opóźnia się i szkodzi użytkownikowi w przypadku dużych treści.

+0

Zdarzenie onInput jest bardzo słabym rozwiązaniem. Pierwszy powód - zdarza się za każdym razem, gdy użytkownik zmienia nawet jedną literę. drugi powód - nie działa nawet w FireFox 8.0 –

+4

@ Dani-Br: Co? Moja odpowiedź mówi, że zdarzenie 'input' jest obsługiwane tylko w WebKit, a więc nie w Firefoksie. Po drugie, twoje pytanie nie jest wcale jasne, * kiedy * musisz wykryć zmiany w edytowalnej treści; Zdarzenie 'input' jest najbardziej podobnym wydarzeniem do zdarzenia' change' wprowadzania danych, chociaż przyznaję, że są one zupełnie inne. –

+0

Niestety, event _input_ nie działa w elementach _contenteditable_ w IE, nawet w IE10! – AnAurelian

4

Ponieważ elementy inne niż wejściowe nie mają tradycyjnych zdarzeń wejściowych, trzeba samemu łączyć coś razem. W tym celu:

var editable = document.querySelectorAll('div[contentEditable]'); 

for (var i=0, len = editable.length; i<len; i++){ 
    editable[i].setAttribute('data-orig',editable[i].innerHTML); 

    editable[i].onblur = function(){ 
     if (this.innerHTML == this.getAttribute('data-orig')) { 
      // no change 
     } 
     else { 
      // change has happened, store new value 
      this.setAttribute('data-orig',this.innerHTML); 
     } 
    }; 
} 

JS Fiddle demo.

Chociaż nie jest to zalecane przez Tim Down, nie powinno to być konieczne zbyt długo, z oczywistym wyjątkiem wspierania starszych przeglądarek.

9

Zbudowałem wtyczkę jQuery, aby to zrobić.

(function ($) { 
    $.fn.wysiwygEvt = function() { 
     return this.each(function() { 
      var $this = $(this); 
      var htmlOld = $this.html(); 
      $this.bind('blur keyup paste copy cut mouseup', function() { 
       var htmlNew = $this.html(); 
       if (htmlOld !== htmlNew) { 
        $this.trigger('change'); 
        htmlOld = htmlNew; 
       } 
      }) 
     }) 
    } 
})(jQuery); 

Możesz po prostu zadzwonić $('.wysiwyg').wysiwygEvt();

Można również usunąć/dodać zdarzenia, jeśli chcesz

+0

Podobnie jak kod, ale "ten" wygląda na niezdefiniowany. – AnthonyVO

+0

dziękuję, naprawiono ... – Blowsie

+1

Trzymajcie się, to wszystko będzie działać tylko raz, lub przez cały czas, kiedy tylko się zamazujecie, jeśli raz dokonaliście pojedynczej zmiany, ponieważ 'htmlold' jest zdefiniowane tylko raz i nigdy zastąpiony do bieżącego stanu! – Val