How to automatic resize tinyMCE?
Asked Answered
P

12

35

I have a TinyMCE that is set over a TextArea, and I want this editor area to ocuppy all the space of its parent div, all times.

I have a JS function that get the current space and set the textarea.style.height to it, but when I enables TinyMCE it seems to stop working.

Also, the textarea has width: 100%; it doesn't resize by HTML rendering when it's using TinyMCE too.

Any ideas?

Phaidra answered 25/11, 2009 at 18:45 Comment(0)
H
56

Nowadays, you should use the autoresize plugin that comes with tinyMCE. You will have to call tinyMCE like this (jQuery version):

$('.tinymce').tinymce({
  theme : 'advanced',
  plugins : 'autoresize',
  width: '100%',
  height: 400,
  autoresize_min_height: 400,
  autoresize_max_height: 800,
});

I made the experience, that it may be helpful to manually call the resizing in the init_instance_callback to provide the correct height on init. Add this parameter to the passed options, if you need this:

init_instance_callback: function (inst) { inst.execCommand('mceAutoResize'); }
Habitant answered 12/9, 2012 at 7:0 Comment(1)
autoresize_min_height and autoresize_max_height are now deprecated, simply use min_height and max_height instead.Mahdi
P
14

The point is that TinyMCE generates an iframe in the place of the textarea, with this ID: originalID+"_ifr", and a table originalID+"_tbl" for holding the controls and the editor area.

To make fluid width:

document.getElementById(id+'_tbl').style.width='100%'


To make fluid height:

Change dinamically document.getElementById(id+'_ifr').style.height to the height you want, through JS.
This is the script I'm using for this:

function toScreenHeight(id, minus) {
    var height;

    if (typeof(window.innerHeight) == "number") //non-IE
        height = window.innerHeight;
    else if (document.documentElement && document.documentElement.clientHeight) //IE 6+ strict mode
        height = document.documentElement.clientHeight;
    else if (document.body && document.body.clientHeight) //IE 4 compatible / IE quirks mode
        height = document.body.clientHeight;

    document.getElementById(id).style.height = (height - minus) + "px";
}

You can use the code and function calls inside onload and onresize body events.

Phaidra answered 25/11, 2009 at 19:49 Comment(2)
Thanks. This was helpful. You should change the style declaration on the first line under "To make fluid height" to "document.getElementById(id+'_tbl').style.height", which I'm sure is what you meant.Revell
I've run into the same prob, and I had a window resize listener which dynamically set the width of the TinyMCE editor, but that along with 100% stopped working. Auto width on this component seems a little brittle..?Doctrinal
A
10

in tinymce 3.4.6, set

width:'100%'

in init option will solve the problem.

Aloes answered 26/10, 2011 at 4:52 Comment(1)
that's kinda obvious, as you can see by the question's answer that was made by myself. the biggest problem is the height.Phaidra
V
4

If you're doing tiny MCE dynamically via JS, you can run into timing issues where the MCE editor is not yet available for style adjustments. To combat this, you can use an old school timeout.

In this example, I'm using a "j" namespace for JQuery. If your editor is in a fluid div that changes size, you may want include this in a $(window).resize(function() { }); listener.

setTimeout(function(){ 
  $j('.mceEditor').css('width','100%').css('minHeight','240px');
  $j('.mceLayout').css('width','100%').css('minHeight','240px');
  $j('.mceIframeContainer').css('width','100%').css('minHeight','240px');
  $j('#'+[INSERT TEXTAREA ID HERE]+'_ifr').css('width','100%').css('minHeight','240px');
},500) 
Vergeboard answered 29/9, 2011 at 16:17 Comment(4)
I have no clue why people would vote down this answer. It's the ONLY answer that made sense with jQuery. It's beautiful, short, intelligent and actually works. I'm sad that I can't vote +10 for this. Two year old answer and still super valid. Combined it with the init_instance_callback : "[function_name]" option that goes in the tinymce init part.Exorcise
Agreed, voted back up to zero (at time of writing). Nice people take the time to answer these questions and if it gets downvotes shouldn't someone explain why?Bork
I had to go one step further and add if(var==null){setTimeout...}, but still, simple and worksLatent
Thanks. This is rather old, but at the time TinyMCE didn't play nice with dynamic JS. I'm sure there are better answers for those using the latest & greatest MCE.Vergeboard
M
3

None of the above were working for me in TinyMCE v4, so my solution was to calculate the height based on the toolbars/menu bar/status bar, and then set the height of the editor, taking those heights into consideration.

function resizeEditor(myHeight) {
    window.console.log('resizeEditor');
    myEditor = getEditor();
    if (myEditor) {
        try {
            if (!myHeight) {            
                var targetHeight = window.innerHeight; // Change this to the height of your wrapper element
                var mce_bars_height = 0;
                $('.mce-toolbar, .mce-statusbar, .mce-menubar').each(function(){
                    mce_bars_height += $(this).height();
                });
                window.console.log('mce bars height total: '+mce_bars_height);                          
                myHeight = targetHeight - mce_bars_height - 8;  // the extra 8 is for margin added between the toolbars
            }
            window.console.log('resizeEditor: ', myHeight);
            myEditor.theme.resizeTo('100%', myHeight);  // sets the dimensions of the editable area
        }
        catch (err) {
        }
    }
}

In my case, I wanted the editor window to match the width and height of the actual window, since the editor would come up in a popup. To detect changes and resize, I set this to a callback:

window.onresize = function() {
    resizeEditor();
}
Maxentia answered 8/8, 2014 at 15:20 Comment(1)
I guess $('.mce-toolbar, .mce-statusbar, .mce-menubar') only works correctly if you have exactly one tinyMceEditor.Carbamate
F
2

With version 4 and the option to use flexbox layout in the browser I did the following to get a full width,height editing experience of the parent div.

It should be easy to put the css into a file if you prefer adding it to your existing styles.

var css = '.tinycme-full .mce-edit-area {display:flex;flex-flow:column;} .tinycme-full .mce-edit-area iframe {flex:1 1 auto;}  .tinycme-full {height:100%;} .tinycme-full .mce-tinymce.mce-container { width:100%;height:100%;border:0; } .tinycme-full .mce-panel{border:0} .tinycme-full .mce-container-body.mce-stack-layout {display: flex; flex-flow: column;height: 100%;} .tinycme-full .mce-stack-layout-item{  flex: 0 0 auto;} .tinycme-full .mce-edit-area{flex:1 1 auto;} ',
    head = document.head || document.getElementsByTagName('head')[0],
    style = document.createElement('style');

style.type = 'text/css';
if (style.styleSheet) {
    style.styleSheet["cssText"] = css;
} else {
    style.appendChild(document.createTextNode(css));
}

head.appendChild(style);

The idea is that it make all the needed divs take up as much column space as needed to fill the parent 100% and its done by putting a div around your textarea: <div class="tinycme-full"> <textarea ... /></div>

No jquery or other dependencies are needed andd it now fills the parent 100%. enter image description here

Flipper answered 24/6, 2015 at 22:28 Comment(2)
Works well but it chops off the statusbar down the bottom.Irresponsive
It works nice for me. Statusbar is displayed correctly.Fractocumulus
U
1

I had the same problem, after reading this thread I ended up with this code

init_instance_callback: function (inst) { 
  setTimeout(function () {
    document.getElementById(inst.id + '_ifr').style.height= (document.getElementById("theContainerDiv").offsetHeight-85) + 'px';
   },1000);
},

I resize the "_ifm" element instead of the "_tbl", since resizing the "_tbl" didn't resize the edit area for me. Then I leave some space for the toolbar and statusbar by making the "_ifr" 85 pixels shorter then the container div.

I had to use setTimeout to make it work, maybe because I have an animation that displays the container element.

Uniat answered 25/12, 2012 at 6:56 Comment(0)
H
1

I'm using pure css solution to achieve this (tinyMCE 4.0.20).

  1. Set iframe height to 100%:

    tinymce.init({ height: '100%' })

  2. Add styles to auto-resize iframe container:

    .mce-tinymce { height: auto; width: 100%; position: absolute; left: 0; top: 0; bottom: 0; }

    .bq-editor .mce-container-body { height: 100%; }

    .bq-editor .mce-edit-area { position: absolute; top: 57px; bottom: 0; width: 100%; height: auto; }

Note: I have one toolbar line, and top: 57px; in .bq-editor .mce-edit-area is toolbar padding.

Heckman answered 30/7, 2014 at 8:27 Comment(0)
L
1

SyCoDeR is right but I followed a slightly different path though probably with the same results.

/*Container, container body, iframe*/
.mce-tinymce, .mce-container-body, #code_ifr {
    min-height: 100% !important;
}
/*Container body*/
.mce-container-body {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
}
/*Editing area*/
.mce-container-body .mce-edit-area {
    position: absolute;
    top: 69px;
    bottom: 37px;
    left: 0;
    right: 0;
}
/*Footer*/
.mce-tinymce .mce-statusbar {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
}

Revised because TinyMCE changes the id's with menu/toolbar additions or deletions. This works no matter what you do with it.

Lavonnelaw answered 26/3, 2015 at 17:8 Comment(0)
G
1

This is an old question, but apparently it still drags a lot of attention nowadays (Second half of 2020).

Sadly, with the release of the TinyMCE v5, most of the workarounds I found simply do not work anymore. I am sure they worked once, but every TinyMCE release seems to bring new "constrainings" that cripple those workarounds...

Without making it a discussion, I believe it is the cost of evolution. For an old product like the TinyMCE, it is incredible to see it is still around and kicking, staying way above the competition. It is by far one of the most efficient and flexible solutions for all environments, including mobile and for those new languages and frameworks that born since (which seems to be a trend lately, with new ones coming out of the blue every day).

So, with that in my mind, and after so many (failed) attempts to make most of the proposed solutions work, I decided to dig into the source code (TinyMCE v5.4) to better understand it. What I found was a much superior product overall, and that the solution everyone has been looking for is much simpler to implement than I was anticipating.

With no further delay, here my solution that simply works. It implements an editor that takes the entire document area (or whatever area you want), which WILL resize with the browser, requiring NO script, NO hack, and NO trick that could cause cross-browsing issues. Here's how:

  1. Give to your <html> and <body> DOM objects the missing properties of size and adjust the spacing accordingly to your needs:
html, body {
   width    : 100%;
   height   : 100%;
   margin   : 0 !important;
   padding  : 0 !important;
   overflow : hidden;  /* Required if you want to have the editor taking the entire page. */
                       /* Otherwise, set as you need it. */
}
  1. TinyMCE suggests the <textarea> to be embedded inside a <form> object. Regardless if you use it as suggested or not, simply give to it and ID and the following CCS properties (in my case, it is set as <form method="post" id="editorBase">):
#editorBase {
   display : block !important;
   width   : 100%  !important;
   height  : 100%  !important;
}
  1. In the TinyMCE Init method, add or modify the following settings:
tinymce.init({
   // Required Settings:
   width  : '100%',  // Note value is set as "string".
   height : '100%',  // Note value is set as "string".
   resize : false,   // Suggestion: disable the statusbar resizing. :)
   
   // Suggested Settings:
   toolbar_sticky   : true,       // Keep the menu and tollbar in a fixed position .
   toolbar_location : 'top',      // You can try 'top', 'bottom' or 'auto'.
   toolbar_mode     : 'floating', // It is simply a button behavior settings. 
                                  // Options are: 'floating', 'sliding', 'scrolling', or 'wrap'.  
});
  1. Yet in the TinyMCE Init settings, find the plugins item and remove the autoresize option from it (it is the most important step of all!).

  2. Done! Try and test it! (YES! It is all done!)

With those simple adjustments you can set the editor to fit any design. Feel free to adjust it as needed. Just don't forget to set the width and the height properties in the TinyMCE Init settings as strings, and keep it consistent with the CSS settings for the <form>.

The reason to use strings in the width and height properties of the TinyMCE Init settings instead of numeric values is to allow you to use "%", "em", "pt", etc... Otherwise, the presented solution would never work.

Another trick to make it even more neat is to set the editor as borderless skin (a feature only present in the "professional" version of TinyMCE). No, it is not a hack, it is a siple adjustment to the CSS and totaly allowed by TinyMCE's EULA and Licensing. Simply add the following CSS to your page Stylesheet and it enjoy a borderless editor for free:

.tox-tinymce { border:none !important; }

Could not be easier than that.

Happy coding!

Gait answered 4/9, 2020 at 18:45 Comment(0)
W
0

The wrapper of iframe (its ID finish by _ifr) is the first parent of span that it has application as role . Thus, To get the wrapper :

$('span[role=application]').parents(':eq(0)')

So to Resize height:

$('[id$=_ifr]').css('height',$('span[role=application]').parents(':eq(0)').css('height'))

To resize width

$('[id$=_ifr]').css('width',$('span[role=application]').parents(':eq(0)').css('width'))
Wear answered 29/4, 2013 at 1:25 Comment(0)
P
0

None of these solutions worked 100% for me. I needed the height to adjust on initialization and during edits. What I did is grab the height of the HTML element in the iFrame, and then applied the height to the iFrame with an extra 100px.

Here's my solution: (added img max-width for responsive images)

on initialization

   setup: function(editor) { 
        editor.on('init', function (e) { 
            $("#editor_textarea_ifr").contents().find('img').css("max-width","100%");
            iframeHeight = $("#editor_textarea_ifr").contents().find("html").height();            
            $("#editor_textarea_ifr").css("height",iframeHeight + 100);                     
        });             
    },

on node change (edits)

  init_instance_callback: function (editor) {
    editor.on('NodeChange', function (e) {
      $("#editor_textarea_ifr").contents().find('img').css("max-width","100%");               
      iframeHeight = $("#editor_textarea_ifr").contents().find("html").height();              
      $("#editor_textarea_ifr").css("height",iframeHeight + 100);   
    });
}   
Poeticize answered 16/2, 2018 at 16:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.