Cjoerg
Cjoerg

Reputation: 1325

How to autoresize a wysihtml5 textarea correctly

I am using bootstrap-wysihtml5 so receive input from a textarea input field. To improve the user experience I want to autoresize the textarea to fit the input text.

With help from the code in this Gist I am able to resize the textarea when clicked, but not on load.

Here is my current implementation:

var container = $("#container");
var textarea = $("<textarea />");
textarea.attr("style", "width: 90%;");

container.append(textarea);

textarea.wysihtml5({
  "font-styles": false,
  "emphasis": false,
  "lists": false,
  "html": false,
  "link": false,
  "image": false,
  "color": false
});

textarea.val("<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div<div><br></div><div>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur..</div");

textarea.observe("load", function () {     
  var $iframe = $(this.composer.iframe);
  var $body = $(this.composer.element);    // <body marginwidth="0" marginheight="0" contenteditable="true" class="wysihtml5-editor" spellcheck="true" style="color: rgb(85, 85, 85); cursor: auto; font-family: HelveticaNeue-Light, 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; line-height: 20px; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-rendering: auto; word-break: normal; word-wrap: break-word; word-spacing: 0px; min-height: 0px; overflow: hidden; background-color: rgb(255, 255, 255);"><div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.<br></div><div>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur..</div></body>

  $body.css({
    'min-height': 0,
    'line-height': '20px',
    'overflow': 'hidden',
  })

  var scrollHeightInit = $body[0].scrollHeight;                // 3860
  var bodyHeightInit = $body.height();                         // 3860
  var heightInit = Math.min(scrollHeightInit, bodyHeightInit); // 3860
  $iframe.height(heightInit);

  $body.bind('keypress keyup keydown paste change focus blur', function(e) {
    var scrollHeight = $body[0].scrollHeight;        // 150
    var bodyHeight = $body.height();                 // 60
    var height = Math.min(scrollHeight, bodyHeight); // 60
    $iframe.height(height);
  });
});

As you can see height is evaluated to 60, which is correct. But heightInit is evaluated to 3860, which is not correct. How do I fix this?

Upvotes: 1

Views: 5600

Answers (2)

Vincent Li
Vincent Li

Reputation: 11

Manube's answer doesn't work for me. I don't know why. I got the console log from $body and $iframe. But failed to set $body.css and $iframe.height(). I adopted document.getElementsByClassName('wysihtml5-sandbox')[0].setAttribute() instead. Then it worked. The change event's UX to auto resize iframe is not good though. Manube's answer helped me a lot and it is very simple. Thank you! Here is the code I used:

$('#edit').wysihtml5({
    toolbar:{ "fa": true, "image": false, "html": false },
    locale: 'zh-TW',
    name: 't-iframe',
    events: {
        load: function(){
            var $body = $(this.composer.element);
            var $iframe = $(this.composer.iframe);
            iframeh = Math.max($body[0].scrollHeight, $body.height()) + 100;
            document.getElementsByClassName('wysihtml5-sandbox')[0].setAttribute('style','height: ' + iframeh +'px !important');
},change: function(){
            var $abody = $(this.composer.element);
            var $aiframe = $(this.composer.iframe);
            aiframeh = Math.max($abody[0].scrollHeight, $abody.height()) + 100;
            document.getElementsByClassName('wysihtml5-sandbox')[0].setAttribute('style','height: ' + aiframeh +'px !important');
        }
    }
});

Upvotes: 1

Manube
Manube

Reputation: 5242

bootstrap-wysihtml5 has an events property; one of these events is the load event.

To resize the textarea on load, all you need to do is declare a load event within the textarea.wysihtml5 configuration function;

See code below:

Code

textarea.wysihtml5({
  ...other properties....,
  "events": {
    "load": function() {
      console.log("Loaded!");
      var $iframe = $(this.composer.iframe);
      var $body = $(this.composer.element);
      $body.css({
        'min-height': 0,
        'line-height': '20px',
        'overflow': 'hidden',
      });
      var scrollHeightInit = $body[0].scrollHeight;
      console.log("scrollHeightInit", scrollHeightInit);
      var bodyHeightInit = $body.height();
      console.log("bodyHeightInit", bodyHeightInit);
      var heightInit = Math.min(scrollHeightInit, bodyHeightInit);
      $iframe.height(heightInit);
    }
  }
});

Here is Working Plunker

Upvotes: 5

Related Questions