web-dev-qa-db-fra.com

Redimensionner l'événement pour la zone de texte?

Les versions actuelles de Firefox et Chrome incluent un gestionnaire de glisser pour redimensionner une boîte <textarea>. J'ai besoin de capturer l'événement de redimensionnement, je pensais que ce serait facile avec la fonction resize() événement, mais ça ne marche pas!

J'ai également essayé l'événement onResize normal, mais le résultat est le même. Vous pouvez l'essayer sur JSFiddle .

Existe-t-il un moyen de le capturer?

45
metrobalderas

Vous devez d'abord rendre la zone de texte redimensionnable avant d'émettre l'événement de redimensionnement. Vous pouvez le faire en utilisant jQuery UI resizable () et à l'intérieur, vous pouvez appeler l'événement resize.

$("textarea").resizable({
    resize: function() {
        $("body").append("<pre>resized!</pre>");
    }
});

Consultez l'exemple de travail à http://jsfiddle.net/HhSYG/1/

2
Hussein

C'est une vieille question, mais quelqu'un d'autre avait la même question dans IRC, j'ai donc décidé de la résoudre ici: http://jsfiddle.net/vol7ron/Z7HDn/

Chrome ne capture pas l'événement de redimensionnement et cela Chrome ne capture pas le mousedown, vous devez donc définir l'état d'initialisation, puis gérer les modifications via mouseup:

jQuery(document).ready(function(){
   var $textareas = jQuery('textarea');

   // store init (default) state   
   $textareas.data('x', $textareas.outerWidth());
   $textareas.data('y', $textareas.outerHeight()); 

   $textareas.mouseup(function(){

      var $this = jQuery(this);

      if (  $this.outerWidth()  != $this.data('x') 
         || $this.outerHeight() != $this.data('y') )
      {
          // Resize Action Here
          alert( $this.outerWidth()  + ' - ' + $this.data('x') + '\n' 
               + $this.outerHeight() + ' - ' + $this.data('y')
               );
      }

      // store new height/width
      $this.data('x', $this.outerWidth());
      $this.data('y', $this.outerHeight()); 
   });

});

HTML

<textarea></textarea>
<textarea></textarea>

Remarque:

  1. Vous pouvez attacher votre propre redimensionnable comme l'a fait Hussein, mais si vous voulez l'original, vous pouvez utiliser le code ci-dessus
  2. Comme le mentionne Bryan Downing, cela fonctionne lorsque vous souriez pendant que votre souris est au-dessus d'une zone de texte; cependant, il peut arriver que cela ne se produise pas, comme lorsqu'un navigateur n'est pas agrandi et que vous continuez à glisser au-delà de la portée du navigateur, ou utilisez resize:vertical pour verrouiller le mouvement.

    Pour quelque chose de plus avancé, vous devez ajouter d'autres écouteurs, éventuellement une file d'attente et des scanners d'intervalle; ou d'utiliser mousemove, comme je le pense, jQuery resizable - la question devient alors combien évaluez-vous les performances par rapport au polissage?


Mise à jour: Il y a eu depuis un changement dans l'interface utilisateur des navigateurs. Maintenant, double-cliquer sur le coin peut réduire la zone de texte à sa taille par défaut. Vous devrez donc peut-être également capturer les modifications avant/après cet événement.

41
vol7ron

Une nouvelle norme pour cela est l'API Resize Observer, disponible en Chrome Dev 54 derrière l'indicateur de fonctionnalités de la plateforme Web expérimentale.

function outputsize() {
 width.value = textbox.offsetWidth
 height.value = textbox.offsetHeight
}
outputsize()

new ResizeObserver(outputsize).observe(textbox)
Width: <output id="width">0</output><br>
Height: <output id="height">0</output><br>
<textarea id="textbox">Resize me.</textarea>

Alternativement, Mutation Observer peut être utilisé pour détecter le changement d'attribut de style dans Firefox et Chrome 54.

function outputsize() {
 width.value = textbox.offsetWidth
 height.value = textbox.offsetHeight
}
outputsize()

new MutationObserver(outputsize).observe(textbox, {
 attributes: true, attributeFilter: [ "style" ]
})
Width: <output id="width">0</output><br>
Height: <output id="height">0</output><br>
<textarea id="textbox">Resize me.</textarea>

Redimensionner l'observateur

Spec: https://wicg.github.io/ResizeObserver

Polyfill: https://github.com/pelotoncycle/resize-observer

Problème avec Chrome: https://crbug.com/612962

Drapeau Chrome: chrome: // flags/# enable-experimental-web-platform-features

Problème avec Firefox: https://bugzil.la/1272409

Problème Safari: http://wkb.ug/15774

15
Daniel Herr

J'ai mélangé un peu la réponse de vol7ron, et j'ai juste remplacé "Resize Action Here" par un simple déclencheur de l'événement normal "resize", afin que vous puissiez attacher ce que vous voulez à l'événement resize "comme d'habitude":

$(document).ready(function(){
    $('textarea').bind('mouseup mousemove',function(){
        if(this.oldwidth  === null){this.oldwidth  = this.style.width;}
        if(this.oldheight === null){this.oldheight = this.style.height;}
        if(this.style.width != this.oldwidth || this.style.height != this.oldheight){
            $(this).resize();
            this.oldwidth  = this.style.width;
            this.oldheight = this.style.height;
        }
    });
});

J'ai ajouté l'événement mousemove pour que le redimensionnement se déclenche également en faisant glisser la souris pendant le redimensionnement, mais gardez à l'esprit qu'il se déclenche très souvent lorsque vous déplacez la souris.

dans ce cas, vous souhaiterez peut-être mettre un peu de retard dans le déclenchement ou la gestion de l'événement de redimensionnement, par exemple remplacer ce qui précède:

$(this).resize();

avec:

if(this.resize_timeout){clearTimeout(this.resize_timeout);}
this.resize_timeout = setTimeout(function(){$(this).resize();},100);

exemple d'utilisation, faites grandir et rétrécir la deuxième zone de texte avec la première:

$('textarea').eq(0).resize(function(){
    var $ta2 = $('textarea').eq(1);
    $('textarea').eq(1).css('width',$ta2.css('width')).css('height',$ta2.css('height'));
});
7
MoonLite

une autre façon de le faire est de se lier à l'événement mouseup sur la zone de texte. alors vous pouvez vérifier si la taille a changé.

6
Guy

L'événement de redimensionnement n'existe pas pour la zone de texte.

Le jQueryPlugin redimensionnable ne semble pas natif, nous devons donc utiliser une alternative.

Une façon de l'émuler consiste à utiliser l'événement mousedown/click. Si vous souhaitez déclencher un événement en temps réel, vous pouvez le faire comme ceci:

Mis à jour le 11 novembre 2013:

// This fiddle shows how to simulate a resize event on a
// textarea
// Tested with Firefox 16-25 Linux / Windows
// Chrome 24-30 Linux / Windows

var textareaResize = function(source, dest) {
    var resizeInt = null;

    // the handler function
    var resizeEvent = function() {
        dest.outerWidth( source.outerWidth() );
        dest.outerHeight(source.outerHeight());
    };

    // This provides a "real-time" (actually 15 fps)
    // event, while resizing.
    // Unfortunately, mousedown is not fired on Chrome when
    // clicking on the resize area, so the real-time effect
    // does not work under Chrome.
    source.on("mousedown", function(e) {
        resizeInt = setInterval(resizeEvent, 1000/15);
    });

    // The mouseup event stops the interval,
    // then call the resize event one last time.
    // We listen for the whole window because in some cases,
    // the mouse pointer may be on the outside of the textarea.
    $(window).on("mouseup", function(e) {
        if (resizeInt !== null) {
            clearInterval(resizeInt);
        }
        resizeEvent();
    });
};

textareaResize($("#input"), $("#output"));

Démo: http://jsfiddle.net/gbouthenot/D2bZd/

2
megar

FireFox prend désormais en charge les événements MutationObserver sur les zones de texte et cela semble fonctionner assez bien. Chrome a malheureusement encore besoin d'une solution de contournement.

Sur la base des autres réponses de cette page, voici une version refactorisée et mise à jour, qui déclenche un événement de redimensionnement de fenêtre lorsqu'un textarea est redimensionné.

J'ai également ajouté un écouteur d'événements pour la souris quittant la fenêtre qui est nécessaire dans un iFrame pour détecter quand le textarea devient plus grand que le cadre.

(function(textAreaChanged){
    function store(){
        this.x = this.offsetWidth;
        this.y = this.offsetHeight;
    }

    function textAreaEvent(){
        if (this.offsetWidth !== this.x || this.offsetHeight !== this.y) {
            textAreaChanged();
            store.call(this);
        }
    }

    $('textarea').each(store).on('mouseup mouseout',textAreaEvent);

    $(window).on('mouseup',textAreaEvent);

})(function(){
    $(window).trigger('resize');
});

Dans IE9 et supérieur, nous pouvons faire de même sans jQuery.

(function(textAreaChanged){
    function store(){
        this.x = this.offsetWidth;
        this.y = this.offsetHeight;
    }

    function textAreaEvent(){
        if (this.offsetWidth !== this.x || this.offsetHeight !== this.y) {
            textAreaChanged();
            store.call(this);
        }
    }

    Array.prototype.forEach.call(
        document.querySelectorAll('textarea'),
        function (el){
            el.addEventListener('mouseup',   textAreaEvent);
            el.addEventListener('mouseout',  textAreaEvent);
        }
    );

    window.addEventListener('mouseup',textAreaEvent)

})(function(){
    //trigger window resize
    var event = document.createEvent('Events');
    event.initEvent('resize', true, false);
    window.dispatchEvent(event);
});
1
David Bradshaw