【问题标题】:Resize event for textarea?调整文本区域的大小事件?
【发布时间】:2011-07-31 00:49:57
【问题描述】:

当前版本的 Firefox 和 Chrome 包含一个拖动处理程序,用于调整 <textarea> 框的大小。我需要捕获调整大小事件,我认为使用 jQuery 的 resize() 事件会很容易,但它不起作用!

我也试过正常的onResize事件,但结果是一样的。 You can try it on JSFiddle.

有没有办法捕捉它?

【问题讨论】:

    标签: javascript jquery html events


    【解决方案1】:

    没有那么漂亮和动态,但它可以按预期工作。

    $('.classname').mouseup(function(){
        $('.classname').css('height', $(this).height());
    });
    

    【讨论】:

      【解决方案2】:

      Chrome没有捕获resize事件,Chrome没有捕获mousedown,所以需要设置init状态,然后通过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>
      

      你可以在JSFiddle上测试

      注意:

      1. 您可以像 Hussein 那样附加您自己的可调整大小,但如果您想要原始的,您可以使用上面的代码
      2. 正如 Bryan Downing 所提到的,当您将鼠标放在 textarea 顶部时,这适用于 mouseup;但是,在某些情况下可能不会发生这种情况,例如浏览器未最大化并且您继续拖动超出浏览器范围,或使用resize:vertical 锁定移动。

      对于更高级的东西,您需要添加其他侦听器,可能是队列和间隔扫描器;或者使用 mousemove,就像我相信 jQuery resizable 所做的那样——那么问题就变成了你对性能和抛光的重视程度如何?


      更新:此后浏览器的 UI 发生了变化。现在双击角可以将文本框收缩到默认大小。因此,您可能还需要在此事件之前/之后捕获更改。

      【讨论】:

      • 在我的快速测试中,这似乎只有在鼠标位于textarea 顶部时才可以使用。
      • @BryanDowning 这是正确的。大多数情况下,用户在释放之前不会开始更改文本区域的大小并拖动超出窗口/文档的范围;但这并不是说它不会/不会发生。对于更高级的东西,您需要其他侦听器,可能还需要队列和间隔扫描器;或使用 mousemove,因为我相信 jQuery resizable 确实如此
      • 对,只是觉得值得一提:) 这个问题在使用resize: vertical 时最为普遍,它只允许textarea 增加高度。鼠标很容易落到右边的textarea之外。
      • @BryanDowning 我忘了给你的评论投票,因为这是一个特别值得注意的用例,我也会在答案中提到它
      • 它仍然不完美,但如果你在 "mouseup" 中包含 "mouseleave" 效果会更好。我实际上最终使用了“mousemove”并限制了事件。
      【解决方案3】:

      我发现 mousemove 事件和 setTimeout 结合起来可以很好地解决这个问题。

      let el = document.querySelector('textarea')
      let resizeFn = ()=>{}
      let timeout = null
      
      el.addEventListener('mousemove',()=>{
          timeout && clearTimeout(timeout)
          timeout = setTimeout(resizeFn,250)
       })
      

      【讨论】:

        【解决方案4】:

        处理元素大小调整的标准方法是 Resize Observer api,在所有现代网络浏览器版本中都可用。

        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>

        如果需要处理旧版本的 Chrome 和 Firefox(其他未测试),可以使用 Mutation Observer 来检测 style 属性的变化。

        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>

        调整观察者大小

        文档:https://developer.mozilla.org/en-US/docs/Web/API/Resize_Observer_API

        规格:https://wicg.github.io/ResizeObserver

        当前支持:http://caniuse.com/#feat=resizeobserver

        Polyfills:https://github.com/pelotoncycle/resize-observer https://github.com/que-etc/resize-observer-polyfill https://github.com/juggle/resize-observer

        【讨论】:

        • 今天,我认为这将是最好的解决方案,因为大多数浏览器都支持它。 MutationObserver 就是这么强大的工具!这个答案是如何使用它的一个很好的例子。
        • 这个解决方案实际上应该固定在顶部。简单,精湛的方法。我讨厌其他答案中提到的其他 hacky 方式,我绝对认为使用 jQuery UI 是不必要的开销。
        • Resize Observer 是不错的选择,因为它适用于 Chrome、FF 和 Safari。 Mutation Observer 在 Safari 中不起作用。
        • MutationObserver 似乎有更多的浏览器支持,包括 Safari:caniuse.com/mutationobserver
        • @RaineRevere 调整观察者大小自 3 月起已在 Safari 中得到支持:caniuse.com/?search=resize%20observer
        【解决方案5】:

        我为同一问题的另一个版本写了这个答案。看来这里是旧闻了。无论出于何种原因,我都喜欢坚持使用 vanilla js,所以这里有一个整洁的 vanilla 小解决方案:

        <textarea
          onmousedown="storeDimensions(this)"
          onmouseup="onresizeMaybe(this)"
        ></textarea>
        
        <script>
          function storeDimensions(element){
            element.textWidth = element.offsetWidth;
            element.textHeight = element.offsetHeight;
            element.value = "is it gonna change? we don't know yet...";
          }
          
          function onresizeMaybe(element){
            if (element.textWidth===element.offsetWidth
             && element.textHeight===element.offsetHeight) 
              element.value = "no change.\n";
            else element.value ="RESIZED!\n";
            
            element.value +=
               `width: ${element.textWidth}\n`
              +`height: ${element.textHeight}`;
          }
        </script>

        对于家庭作业,请使用 onmousemove 而不是 onmouseup 来触发调整大小事件(在我的特定情况下我不需要它)。

        如果您想将此添加到 DOM 中的每个 textarea(未经过真正测试):

        let elementArray = document.getElementsByTagName("textarea");
        for(var i=0; i<elementArray.length; i++){
          elementArray[i].setAttribute("onmousedown", "storeDimensions(this)");
          elementArray[i].setAttribute("onmouseup", "onresizeMaybe(this)");
        }
        

        :) 希望有一天它对某人有所帮助...看看这个问题现在已经 9 岁了。

        注意:如果您想在 mousemove 上触发它,那么新奇的 ResizeObserver(callback).observe(element) 方法非常棒!

        【讨论】:

          【解决方案6】:

          FireFox 现在支持 textareas 上的 MutationObserver 事件,这似乎工作得很好。遗憾的是,Chrome 仍然需要解决方法。

          根据此页面上的其他答案,这里有一个重构和更新的版本,它会在调整 textarea 的大小时触发一个窗口调整大小事件。

          我还为鼠标离开窗口添加了一个事件侦听器,在 iFrame 中需要它来检测 textarea 何时变得大于框架。

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

          在 IE9 及更高版本中,我们可以在没有 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);
          });
          

          【讨论】:

            【解决方案7】:

            textarea 不存在调整大小事件。

            可调整大小的 jQueryPlugin 看起来不是原生的,所以我们必须使用替代。

            模拟它的一种方法是使用 mousedown/click 事件。 如果你想要实时事件触发,你可以这样做:

            2013 年 11 月 11 日更新:

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

            演示:http://jsfiddle.net/gbouthenot/D2bZd/

            【讨论】:

            • 出于某种原因,您的 jsfiddle 示例不会将右侧的文本区域与左侧的文本区域一起调整大小。
            • 我刚刚测试过了。你使用的是什么浏览器 ?我在网站上使用它,但没有收到任何投诉。
            • 我在最新的 Chrome 上,调整大小时没有 mousedown 事件...只有 mouseup 火灾。太奇怪了。
            • 我编辑了我的答案以支持 Chrome 最新的“错误”。我在 Linux/Windows 7 下使用 Firefox/Chrome 进行了测试。
            【解决方案8】:

            感谢 MoonLite - 您的脚本工作正常,但有时,如果您快速增加调整大小,鼠标指针在 mouseup 时位于文本区域之外,并且不会触发所需的功能。所以我在包含元素上添加了一个 mouseup 事件以使其工作可靠。

            .

             
                    $('textarea_container').bind('mouseup', function()
                    { YourCode ; } ) ;
            '

            【讨论】:

              【解决方案9】:

              我稍微混合了 vol7ron 的答案,只是用普通“resize”事件的简单触发器替换了“Resize Action Here”,因此您可以“像往常一样”将任何想要发生的事情附加到 resize 事件:

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

              我添加了 mousemove 事件,因此在调整大小时拖动鼠标时也会触发调整大小,但请记住,当您四处移动鼠标时它会经常触发。

              在这种情况下,您可能希望在实际触发或处理调整大小事件时稍作延迟,例如 替换上面的:

              $(this).resize();
              

              与:

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

              示例用法,使第二个文本区域与第一个文本区域一起增长和缩小:

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

              【讨论】:

                【解决方案10】:

                另一种方法是绑定到 textarea 上的 mouseup 事件。然后你可以检查大小是否改变。

                【讨论】:

                  【解决方案11】:

                  在发出 resize 事件之前,您需要先使 textarea 可调整大小。您可以通过使用 jQuery UI resizable() 来做到这一点,并在其中调用 resize 事件。

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

                  http://jsfiddle.net/HhSYG/1/查看工作示例

                  【讨论】:

                  • 看起来不错,在我的浏览器中看起来不像原生文本区域(chrome、mac)
                  • 没关系。你仍然需要使用 resizable() 来获得跨浏览器的支持。
                  • 我认为这不再有效(目前在 JQuery 1.8 中测试它
                  • 这对我在 Firefox 或 Chrome 中都不起作用。文本区域看起来很糟糕,并且根本没有出现调整大小的句柄。我正在使用 jQuery 1.9.1 和 jQuery UI 1.10.0。
                  • 即使小提琴显示了样式表,您也应该提到这个样式表是必要的。如果没有样式表,它就无法工作......
                  猜你喜欢
                  • 2011-01-06
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-03-29
                  相关资源
                  最近更新 更多