title: TinyMCE limit text on scrollerActived
body: <p>I have a textarea in my rails application to collect content from user in a database. The rails application is further feeding that text to an XML-driven flex application.</p>
  
  <p>The flex application has number of fixed sized containers which wraps the text inside (from the XML created by Rails app on-the-fly), but truncates the text if it exceeds the container's height. Problem is; there is no way to present the large text in XML, so it gets adjusted automatically in the compiled flex application. And the fact is; the web-based rails app and front-tier flex app are entirely disconnected in terms of having awareness of their internal events. (like in this case; rails app has no knowledge of the overflow event for flex internal containers and relying on font-size and character/line count doesn't work in this scenario!)</p>
  
  <p>Therefore, I wrote a JS function to watch and rescue the textarea's overflow situation and while setting its attributes (viz; line-height, font-size, font-family, width, height... yada yada) matching that of the flex control. The complex form in rails did the trick to have dynamic number of such textarea's control being observed by the JS function.</p>
  
  <p>Here is the Prototype code to handle the overflow event with the corresponding rescue code for cleanup:</p>
  
  <pre><code>var timeout;
  document.observe('dom:loaded', attach_obr);
  
  function attach_obr() {
      $$('.active_text').each (function(text_element){
          text_element.observe('keyup', function(e){
              check_limits(text_element.id);
          });
          text_element.observe('change', function(e){
              check_limits(text_element.id);
          });
      });
  }
  
  function check_limits(eyeD) {
      if($(eyeD).scrollHeight &gt; $(eyeD).offsetHeight){
  
          // overflow occured, now the rescue code here
          timeout = window.setTimeout(function() {
              $("error_notice").hide();
          }, 4000);
          $("error_notice").show().update('There is no space left in this box, please use a new box to continue adding content');
  
          // truncate text till the scrollbar disappears
          while($(eyeD).scrollHeight &gt; $(eyeD).offsetHeight){
              $(eyeD).value = $(eyeD).value.slice(0, -1);
          }
      }
      else {
          if($("error_notice").innerHTML!=""){
              $("error_notice").hide().update("");
              clearTime(timeout);
          }
      }
  }
  </code></pre>
  
  <p>[<strong>Note:</strong> It works with a minor flaw of truncating few more characters than expected in the last line. User can retype these letters till the end of that line. I guess this is because somehow the <em>change in width</em> of textarea due to the <em>appearance of scroll-bar</em> is effecting either the scrollHeight or offsetHeight during the process &amp; there should be something more to the loop's condition <code>($(eyeD).scrollHeight &gt; $(eyeD).offsetHeight)</code>]</p>
  
  <p>The while loop makes things bit slower, but at least it is serving the purpose. WYSIWYG is achieved. (I would love to hear any suggestion from the viewers to improve that inelegant code :O )</p>
  
  <p>WYSIWYG is not achieved, in terms of rich/formatted text..</p>
  
  <p><strong>Incorporating Rich Text:</strong></p>
  
  <p>Rather than expecting from user to place tags inside the area , in the next phase, I am planning to deploy tinyMCE in my app. Now, to make the above function work with tinyMCE, I have the following code:</p>
  
  <pre><code>tinyMCE.init({
      theme_advanced_buttons1 : "bold, italic, underline, strikethrough, separator, justifyleft, justifycenter, justifyright, justifyfull, separator, forecolor, backcolor",
      theme:"advanced",
      mode:"textareas",
      plugins : "safari",
      width: '360px',
      height: '198px',
      setup : function(ed) {
          ed.onChange.add(function(ed, i) {
              check_limits(ed.id);
          });
      }
  
  });
  </code></pre>
  
  <p>The binding and firing of events is working alright. Unfortunately, the aim to control the text overflow is not working. Reason being; </p>
  
  <p>a) <code>ed.id</code> is the id of my textarea not the interactive panel created by tinyMCE. So, the attributes like scrollHeight are offsetHeight are not getting changed for the hidden textarea control. </p>
  
  <p>b) The value of textarea in this case also contains HTML code rather than the actual text. So, it is very implicit to tell what is the actual text without markup (which in our case is required when truncating the overflowed text).</p>
  
  <p><strong>My questions:</strong></p>
  
  <ol>
  <li><p>Is there a way to get the scrollHeight and offsetHeight of the control created by tinyMCE?</p></li>
  <li><p>Is there a way to get the only-text version (without markup) of inner content of tinyMCE control?
  (So, when I truncate the text in check_limits function, it doesn't effect/breaks the markup/DOM created by tinyMCE for the formatted text. In other words, I would be simulating the user action of pressing backspace on tinyMCE control in the while loop.)</p></li>
  <li><p>Elegant way to do this whole exercise with &amp; without tinyMCE?</p></li>
  </ol>
  
  <p>Any suggestions are greatly appreciated!</p>