Abstract textarea resizing to its own javascript library
authorMichael M Slusarz <slusarz@curecanti.org>
Fri, 19 Feb 2010 21:43:16 +0000 (14:43 -0700)
committerMichael M Slusarz <slusarz@curecanti.org>
Fri, 19 Feb 2010 21:50:22 +0000 (14:50 -0700)
horde/js/TextareaResize.js [new file with mode: 0644]
imp/compose-dimp.php
imp/js/compose-dimp.js
imp/message-dimp.php

diff --git a/horde/js/TextareaResize.js b/horde/js/TextareaResize.js
new file mode 100644 (file)
index 0000000..0946f7e
--- /dev/null
@@ -0,0 +1,76 @@
+/**
+ * TextareaResize: a library that automatically resizes a text area based on
+ * its contents.
+ *
+ * Requires prototypejs 1.6+.
+ *
+ * Usage:
+ * ------
+ * cs = new TextareaResize(id[, options]);
+ *
+ *   id = (string|Element) DOM ID/Element object of textarea.
+ *   options = (object) Additional options:
+ *      'max_rows' - (Number) The maximum number of rows to display.
+ *      'observe_time' - (Number) The interval between form field checks.
+ *
+ * Custom Events:
+ * --------------
+ * TexareaResize:resize
+ *   Fired when the textarea is resized.
+ *   params: NONE
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ */
+
+var TextareaResize = Class.create({
+    // Variables used: elt, max_rows, size
+
+    initialize: function(id, opts)
+    {
+        opts = opts || {};
+
+        this.elt = $(id);
+        this.max_rows = opts.max_rows || 5;
+        this.size = -1;
+
+        new Form.Element.Observer(this.elt, opts.observe_time || 1, this.resize.bind(this));
+
+        this.resize();
+    },
+
+    resize: function()
+    {
+        var old_rows, rows,
+            size = $F(this.elt).length;
+
+        if (size == this.size) {
+            return;
+        }
+
+        old_rows = rows = Number(this.elt.readAttribute('rows', 1));
+
+        if (size > this.size) {
+            while (rows < this.max_rows) {
+                if (this.elt.scrollHeight == this.elt.clientHeight) {
+                    break;
+                }
+                this.elt.writeAttribute('rows', ++rows);
+            }
+        } else if (rows > 1) {
+            do {
+                this.elt.writeAttribute('rows', --rows);
+                if (this.elt.scrollHeight != this.elt.clientHeight) {
+                    this.elt.writeAttribute('rows', ++rows);
+                    break;
+                }
+            } while (rows > 1);
+        }
+
+        this.size = size;
+
+        if (rows != old_rows) {
+            this.elt.fire('TextareaResize:resize');
+        }
+    }
+
+});
index 51d8ecb..fd5fe81 100644 (file)
@@ -198,7 +198,8 @@ Horde::addInlineScript($compose_result['js_onload'], 'load');
 
 $scripts = array(
     array('compose-dimp.js', 'imp'),
-    array('md5.js', 'horde')
+    array('md5.js', 'horde'),
+    array('TextareaResize.js', 'horde')
 );
 
 IMP::status();
index 497e328..1c69d34 100644 (file)
@@ -10,9 +10,8 @@
 var DimpCompose = {
     // Variables defaulting to empty/false:
     //   auto_save_interval, compose_cursor, disabled, drafts_mbox, editor_on,
-    //   is_popup, knl_p, knl_sm, last_msg, mp_padding, resizebcc, resizecc,
-    //   resizeto, row_height, rte, skip_spellcheck, spellcheck, sc_submit,
-    //   uploading
+    //   is_popup, knl_p, knl_sm, last_msg, loaded, mp_padding, row_height,
+    //   rte, skip_spellcheck, spellcheck, sc_submit, uploading
 
     confirmCancel: function()
     {
@@ -462,9 +461,8 @@ var DimpCompose = {
     // opts = auto, focus, fwd_list, noupdate
     fillForm: function(msg, header, opts)
     {
-        // On IE, this can get loaded before DOM:loaded. Check for an init
-        // value and don't load until it is available.
-        if (!this.resizeto) {
+        // On IE, this can get loaded before DOM:loaded.
+        if (!document.loaded) {
             this.fillForm.bind(this, msg, header, opts).defer();
             return;
         }
@@ -490,10 +488,8 @@ var DimpCompose = {
         this.setBodyText(msg, true);
 
         $('to').setValue(header.to);
-        this.resizeto.resizeNeeded();
         if (header.cc) {
             $('cc').setValue(header.cc);
-            this.resizecc.resizeNeeded();
         }
         if (DIMP.conf_compose.cc) {
             this.toggleCC('cc', true);
@@ -502,7 +498,6 @@ var DimpCompose = {
         this.setSaveSentMail(identity.id[4]);
         if (header.bcc) {
             $('bcc').setValue(header.bcc);
-            this.resizebcc.resizeNeeded();
         }
         if (identity.id[6]) {
             bcc_add = $F('bcc');
@@ -575,7 +570,6 @@ var DimpCompose = {
     {
         if (r.response.header) {
             $('to').setValue(r.response.header.to);
-            this.resizeto.resizeNeeded();
         }
         $('to_loading_img').hide();
     },
@@ -854,8 +848,6 @@ var DimpCompose = {
 
     onDomLoad: function()
     {
-        var boundResize = this.resizeMsgArea.bind(this);
-
         DimpCore.growler_log = false;
         DimpCore.init();
 
@@ -877,9 +869,9 @@ var DimpCompose = {
         }
 
         // Automatically resize address fields.
-        this.resizeto = new ResizeTextArea('to', boundResize);
-        this.resizecc = new ResizeTextArea('cc', boundResize);
-        this.resizebcc = new ResizeTextArea('bcc', boundResize);
+        new TextareaResize('to');
+        new TextareaResize('cc');
+        new TextareaResize('bcc');
 
         /* Add addressbook link formatting. */
         if (DIMP.conf_compose.URI_ABOOK) {
@@ -921,52 +913,11 @@ var DimpCompose = {
         }
     }
 
-},
-
-ResizeTextArea = Class.create({
-    // Variables defaulting to empty:
-    //   defaultRows, field, onResize
-    maxRows: 5,
-
-    initialize: function(field, onResize)
-    {
-        this.field = $(field);
-
-        this.defaultRows = Math.max(this.field.readAttribute('rows'), 1);
-        this.onResize = onResize;
-
-        var func = this.resizeNeeded.bindAsEventListener(this);
-        this.field.observe('mousedown', func).observe('keyup', func);
-
-        this.resizeNeeded();
-    },
-
-    resizeNeeded: function()
-    {
-        var lines = $F(this.field).split('\n'),
-            cols = this.field.readAttribute('cols'),
-            newRows = lines.size(),
-            oldRows = this.field.readAttribute('rows');
-
-        lines.each(function(line) {
-            if (line.length >= cols) {
-                newRows += Math.floor(line.length / cols);
-            }
-        });
-
-        if (newRows != oldRows) {
-            this.field.writeAttribute('rows', (newRows > oldRows) ? Math.min(newRows, this.maxRows) : Math.max(this.defaultRows, newRows));
-
-            if (this.onResize) {
-                this.onResize();
-            }
-        }
-    }
-
-});
+};
 
 /* Attach event handlers. */
 document.observe('dom:loaded', DimpCompose.onDomLoad.bind(DimpCompose));
+document.observe('TextareaResize:resize', DimpCompose.resizeMsgArea.bind(DimpCompose));
 
 /* Click handler. */
 DimpCore.clickHandler = DimpCore.clickHandler.wrap(DimpCompose.clickHandler.bind(DimpCompose));
index d1d4476..61deaed 100644 (file)
@@ -41,6 +41,7 @@ if (isset($show_msg_result['error'])) {
 
 $scripts = array(
     array('ContextSensitive.js', 'horde'),
+    array('TextareaResize.js', 'horde'),
     array('fullmessage-dimp.js', 'imp'),
     array('imp.js', 'imp'),
     array('md5.js', 'horde')