web-dev-qa-db-fra.com

déclencher un événement lorsque contenteditable est modifié

Quand une valeur div est modifiée, comment puis-je déclencher un événement?

<div class="changeable" contenteditable="true"> Click this div to edit it <div>

Alors, quand son contenu change, je veux créer une alerte et/ou faire autre chose:

$('.changeable').text().change(function() {
  alert('Handler for .change() called.');
});
39
johnmosly

Stockez simplement le contenu dans une variable et vérifiez si elle est différente après l'événement blur(). S'il est différent, stockez le nouveau contenu.

var contents = $('.changeable').html();
$('.changeable').blur(function() {
    if (contents!=$(this).html()){
        alert('Handler for .change() called.');
        contents = $(this).html();
    }
});

exemple: http://jsfiddle.net/niklasvh/a4QNB/

42
Niklas

Vous pouvez simplement utiliser un événement focus/blur avec la fonction data () de jQuery: 

// Find all editable content.
$('[contenteditable=true]')
    // When you click on item, record into data("initialText") content of this item.
    .focus(function() {
        $(this).data("initialText", $(this).html());
    });
    // When you leave an item...
    .blur(function() {
        // ...if content is different...
        if ($(this).data("initialText") !== $(this).html()) {
            // ... do something.
            console.log('New data when content change.');
            console.log($(this).html());
        }
    });
});

MISE À JOUR: Avec Vanilla JS

// Find all editable content.
var contents = document.querySelectorAll("[contenteditable=true]");
[].forEach.call(contents, function (content) {
    // When you click on item, record into `data-initial-text` content of this item.
    content.addEventListener("focus", function () {
        content.setAttribute("data-initial-text", content.innerHTML);
    });
    // When you leave an item...
    content.addEventListener("blur", function () {
        // ...if content is different...
        if (content.getAttribute("data-initial-text") !== content.innerHTML) {
            // ... do something.
            console.log("New data when content change.");
            console.log(content.innerHTML);
        }
    });
});
15
Bruno Lesieur

J'ai construit un plugin jQuery pour le faire.

(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')
                }
            })
        })
    }
})(jQuery);

Vous pouvez simplement appeler $('.wysiwyg').wysiwygEvt();

Vous pouvez également supprimer/ajouter des événements si vous le souhaitez

12
Blowsie

actuellement, la meilleure solution est le événement de saisie HTML5

<div contenteditable="true" id="content"></div>

dans votre jquery.

$('#content').on('input', (e) => {
    // your code here
    alert('changed')
});
6
Canaan Etai

C'est plus simple de le faire en utilisant EventListener (pas une méthode jQuery):

 document.getElementById ("éditeur"). addEventListener ("entrée", fonction () {
 alert ("événement d'entrée déclenché"); 
}, false);.

6
VasG

C'est mon approche ...

$('.changeable').focusout(function() {
  alert('Handler for .change() called.');
});
5
Marcel Barraza

Voici une version jquery:

function fix_contenteditableOnchange(obj)
{
     div=$(obj);
     var contents = div.html();
     var onchange = div.attr('onchange');
     div.blur(function() {
      if (contents!=$(this).html()){
        eval(onchange);
        fix_contenteditableOnchange(obj);
      }
     });
}

Essayez ceci.

1
Sven

Encore une autre version dans jQuery. Voir dans jsFiddle ici .

var $editableContent = $("#mycontent");

//  Implement on text change
$editableContent.on("focus", function(event) {$(this).data("currentText", $(this).text());});

$editableContent.on("blur", function (event) {
        if ($(this).text() != $(this).data("currentText")) {
                $(this).trigger('change');}});


//  Wire onchange event
$editableContent.on("change", function(){alert("Text changed to: " + $(this).text())});
1
dcapelo

En chrome et peut-être dans d'autres navigateurs, il y a un bogue, lorsque l'utilisateur appuie sur l'onglet, il crée un espace et ajoute Apple-be span ou quelque chose du genre. Pour supprimer cet utilisateur. 

var contents = $('.changeable').html();
$('.changeable').blur(function() {
   if (contents!=$(this).html()){
 alert('Handler for .change() called.');
      $(".Apple-tab-span").remove();
       contents = $(this).html();
       contentsTx = $(this).text();
       alert(contentsTx);

   }
});

Ceci enlèvera le span .. Le même que le code ci-dessus vient de le modifier un peu, ou vous pouvez ajouter 

.Apple-tab-span
{
  Display:None;
}

et cela résoudra également le problème ... http://jsfiddle.net/a4QNB/312/

@Nikals vient de modifier la réponse ... 

1
nikunjM

Vous devez faire une conjonction des événements blur et DOMSubtreeModified sur vos éléments contenteditable.

var contentEdited = false;

function fn($el) {
  if (contentEdited) {
    var text = $el[0].innerText.trim();
    console.log(text);
    contentEdited = false;
  }
}
$("div.editable").on("blur", function() {
  fn($(this));
}).on("DOMSubtreeModified", function() {
  contentEdited = true;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="editable" contenteditable="true">Click this div to edit it<div>

0
Dan Philip

Une autre solution qui est une version légèrement modifiée des précédentes mais peut être plus pratique à utiliser pour certains d’entre vous.

L'idée est de sauvegarder la valeur d'origine et de la comparer à la valeur actuelle dans l'événement 'flou'. J'enregistre la valeur d'origine en tant qu'attribut de balise div éditable (au lieu de créer une variable pour la valeur d'origine). Utiliser attribut comme conteneur pour la valeur Origine est plus confortable quand on a un grand nombre de divs modifiables dans la table (en tant que cellules). Il est donc facile d’obtenir la valeur Origin car il n’est pas nécessaire de créer beaucoup de variables.

Voir mon exemple complet de code:

div éditable

<td><div contenteditable="true" class="cell" Origin="originValue">originValue</div></td>

détecter les changements de flou

var cells = $("#table").find('td>div[contenteditable=true]');

cells.each(function () {    

        $(this).blur(function() {

                    if ($(this).text() != $(this).attr("Origin")) {
                        console.log('changed');
                    }
        });    
});
0
Bronek