Resize Preview pane .. With the diff

David Glick dglick at gmail.com
Sat Dec 16 23:46:06 CET 2006


Thanks for throwing this up here Ryan.  Here's an updated patch (for
svn 410) that also works in IE and Opera in addition to Firefox.  (Can
someone test Safari?)  This one also resizes the splitter bar when the
window is resized.  The setting still isn't saved in user_prefs but
I'm sure Ryan will have that working soon...
peace,
David Glick

> I really am batting 1000 today. Here's the diff. Going to bed.
>

Index: program/include/main.inc
===================================================================
--- program/include/main.inc	(revision 410)
+++ program/include/main.inc	(working copy)
@@ -1277,6 +1277,7 @@
         // GENERAL
         'loginform' => 'rcmail_login_form',
         'username'  => 'rcmail_current_username',
+        'splitter' => 'rcube_splitter',

         // MAIL
         'mailboxlist' => 'rcmail_mailbox_list',
@@ -1912,7 +1913,19 @@
   return $select->show($set);
   }

+function rcube_splitter($attrib)
+  {
+  global $OUTPUT, $JS_OBJECT_NAME;
+
+  // register splitter in the system
+  $OUTPUT->add_script(sprintf("%s.register_splitter('%s', '%s', '%s');",
+                              $JS_OBJECT_NAME,
+                              $attrib['first'],
+                              $attrib['second'],
+                              $attrib['orientation']));

+  }
+
 /****** debugging functions ********/


Index: program/js/common.js
===================================================================
--- program/js/common.js	(revision 410)
+++ program/js/common.js	(working copy)
@@ -380,6 +380,187 @@
   }


+/**
+ * RoundCube splitter GUI class
+ *
+ * @constructor
+ */
+function rcube_splitter(attrib)
+  {
+  this.p1id = attrib.p1;
+  this.p2id = attrib.p2;
+  this.id = this.p1id + '_' + this.p2id + '_splitter';
+  this.orientation = attrib.orientation;
+  this.horizontal = (this.orientation == 'horizontal');
+
+  this.init = function()
+    {
+    this.p1 = document.getElementById(this.p1id);
+    this.p2 = document.getElementById(this.p2id);
+
+    // create and position the handle for this splitter
+    this.p1pos = rcube_get_object_pos(this.p1);
+    this.p2pos = rcube_get_object_pos(this.p2);
+    var top = this.p1pos.y + this.p1.offsetHeight;
+    var height = this.p2pos.y - this.p1pos.y - this.p1.offsetHeight;
+    var left = this.p1pos.x + this.p1.offsetWidth;
+    var width = this.p2pos.x - this.p1pos.x - this.p1.offsetWidth;
+    if (this.horizontal)
+      this.layer = new rcube_layer(this.id, {x: this.p1pos.x, y: top,
height: height, zindex: 1, vis: 1});
+    else
+      this.layer = new rcube_layer(this.id, {x: left, y:
this.p1pos.y, width: width, zindex: 1, vis: 1});
+    this.elm = this.layer.elm;
+    this.elm.className = 'splitter';
+    if (this.horizontal)
+      this.elm.style.paddingTop = Math.floor(height / 2) + 'px';
+    else
+      this.elm.style.paddingLeft = Math.floor(width / 2) + 'px';
+
+    this.line = document.createElement('DIV');
+    this.line.className = 'splitterLine';
+    if (this.horizontal)
+      {
+      this.line.style.borderTopWidth = '1px';
+      this.line.style.width = '100%';
+      this.line.style.height = '1px';
+      }
+    else
+      {
+      this.line.style.borderLeftWidth = '1px';
+      this.line.style.width = '1px';
+      this.line.style.height = '100%';
+      }
+
+    this.elm.appendChild(this.line);
+    rcube_event.add_listener({element: this.elm, event:'mouseover',
object:this, method:'onMouseOver'});
+    rcube_event.add_listener({element: this.elm, event:'mouseout',
object:this, method:'onMouseOut'});
+
+    // add the event to start dragging when the handle is pressed
+    var s = this;
+    this.elm.onmousedown = function(e){ return s.onDragStart(e); };
+    }
+
+  this.onDragStart = function(e)
+    {
+    this.p1pos = rcube_get_object_pos(this.p1);
+    this.p2pos = rcube_get_object_pos(this.p2);
+
+    // start listening to mousemove events
+    rcube_event.add_listener({element:document, event:'mousemove',
object:this, method:'onDrag'});
+    rcube_event.add_listener({element:document, event:'mouseup',
object:this, method:'onDragStop'});
+
+    // need to listen in any iframe documents too, b/c otherwise the
splitter stops moving when we move over an iframe
+    var iframes = document.getElementsByTagName('IFRAME');
+    this.iframe_events = Object();
+    for (var n in iframes)
+      {
+      var iframedoc = null;
+      if (iframes[n].contentDocument)
+        iframedoc = iframes[n].contentDocument;
+      else if (iframes[n].contentWindow)
+        iframedoc = iframes[n].contentWindow.document;
+      else if (iframes[n].document)
+        iframedoc = iframes[n].document;
+      if (iframedoc)
+        {
+        // I don't use the add_listener function for this one because
I need to create closures to fetch
+        // the position of each iframe when the event is received
+        var s = this;
+        var id = iframes[n].id;
+        this.iframe_events[n] = function(e){ e._rc_pos_offset =
rcube_get_object_pos(document.getElementById(id)); return s.onDrag(e);
}
+        if (iframedoc.addEventListener)
+          iframedoc.addEventListener('mousemove',
this.iframe_events[n], false);
+        else if (iframes[n].attachEvent)
+          iframedoc.attachEvent('onmousemove', this.iframe_events[n]);
+        else
+          iframedoc['onmousemove'] = this.iframe_events[n];
+
+        rcube_event.add_listener({element:iframedoc, event:'mouseup',
object:this, method:'onDragStop'});
+        }
+      }
+    }
+
+  this.onDrag = function(e)
+    {
+    var pos = rcube_event.get_mouse_pos(e);
+    if (e._rc_pos_offset)
+      {
+      pos.x += e._rc_pos_offset.x;
+      pos.y += e._rc_pos_offset.y;
+      }
+
+    if (this.horizontal)
+      {
+      if (((pos.y - this.layer.height * 1.5) > this.p1pos.y) &&
((pos.y + this.layer.height * 1.5) < (this.p2pos.y +
this.p2.offsetHeight)))
+        {
+        // resize the panels
+        this.p2.style.top = Math.round(pos.y + this.layer.height / 2
+ 1 - (bw.ie ? 10 : 0)) + 'px';
+        this.p1.style.height = Math.round(pos.y - this.p1pos.y -
this.layer.height / 2 - 1) + 'px';
+
+        // move the splitter handle
+        this.layer.move(this.layer.x, Math.round(pos.y -
this.layer.height / 2 + 1));
+        }
+      }
+    else
+      {
+      if (((pos.x - this.layer.width * 1.5) > this.p1pos.x) &&
((pos.x + this.layer.width * 1.5) < (this.p2pos.x +
this.p2.offsetWidth)))
+        {
+        this.p1.style.width = Math.round(pos.x - this.p1pos.x -
this.layer.width / 2 - 1) + 'px';
+        this.p2.style.left = Math.round(pos.x + this.layer.width / 2
+ 1) + 'px';
+
+        this.layer.move(Math.round(pos.x - this.layer.width / 2 + 1),
this.layer.y);
+        }
+      }
+
+    this.p1pos = rcube_get_object_pos(this.p1);
+    this.p2pos = rcube_get_object_pos(this.p2);
+    return false;
+    }
+
+  this.onDragStop = function(e)
+    {
+    // cancel the listening for drag events
+    rcube_event.remove_listener({element:document, event:'mousemove',
object:this, method:'onDrag'});
+    rcube_event.remove_listener({element:document, event:'mouseup',
object:this, method:'onDragStop'});
+    var iframes = document.getElementsByTagName('IFRAME');
+    for (var n in iframes)
+      {
+      var iframedoc;
+      if (iframes[n].contentDocument)
+        iframedoc = iframes[n].contentDocument;
+      else if (iframes[n].contentWindow)
+        iframedoc = iframes[n].contentWindow.document;
+      else if (iframes[n].document)
+        iframedoc = iframes[n].document;
+      if (iframedoc)
+        {
+        if (this.iframe_events[n]) {
+          if (iframedoc.removeEventListener)
+            iframedoc.removeEventListener('mousemove',
this.iframe_events[n], false);
+          else if (iframedoc.detachEvent)
+            iframedoc.detachEvent('onmousemove', this.iframe_events[n]);
+          else
+            iframedoc['onmousemove'] = null;
+        }
+
+        rcube_event.remove_listener({element:iframedoc,
event:'mouseup', object:this, method:'onDragStop'});
+        }
+      }
+    return rcube_event.cancel(e);
+    }
+
+  // events to make the handle appear when the mouse hovers over it
+  // (pure CSS doesn't work b/c IE only applies :hover classes to links)
+  this.onMouseOver = function(e)
+    {
+    this.line.style.visibility = 'visible';
+    }
+  this.onMouseOut = function(e)
+    {
+    this.line.style.visibility = 'hidden';
+    }
+  }
+
 // check if input is a valid email address
 // By Cal Henderson <cal at iamcal.com>
 // http://code.iamcal.com/php/rfc822/
Index: program/js/app.js
===================================================================
--- program/js/app.js	(revision 410)
+++ program/js/app.js	(working copy)
@@ -24,6 +24,7 @@
   this.env = new Object();
   this.labels = new Object();
   this.buttons = new Object();
+  this.splitters = new Object();
   this.gui_objects = new Object();
   this.commands = new Object();

@@ -78,6 +79,13 @@
     };


+  // add a splitter to the splitter list
+  this.register_splitter = function(p1, p2, orientation)
+    {
+    this.splitters[p1 + '_' + p2] = new rcube_splitter({p1: p1, p2:
p2, orientation: orientation});
+    }
+
+
   // register a specific gui object
   this.gui_object = function(name, id)
     {
@@ -108,6 +116,10 @@

     // enable general commands
     this.enable_command('logout', 'mail', 'addressbook', 'settings', true);
+
+    // initialize splitters
+    for (var n in this.splitters)
+      this.splitters[n].init();

     switch (this.task)
       {
Index: skins/default/common.css
===================================================================
--- skins/default/common.css	(revision 410)
+++ skins/default/common.css	(working copy)
@@ -213,7 +213,21 @@
   border: 1px solid #CCCCCC;
 }

+.splitter
+{
+  position: absolute;
+  cursor: move;
+  background: url(images/cleardot.png);
+}

+.splitterLine
+{
+  visibility: hidden;
+  border-color: #ff0000;
+  border-style: solid;
+  border-width: 0;
+}
+
 /***** common table settings ******/

 table.records-table thead tr td
Index: skins/default/templates/mail.html
===================================================================
--- skins/default/templates/mail.html	(revision 410)
+++ skins/default/templates/mail.html	(working copy)
@@ -55,6 +55,7 @@
 </div>

 <roundcube:if condition="config:preview_pane == true" />
+<roundcube:object name="splitter" first="mailcontframe"
second="mailpreviewframe" orientation="horizontal" />
 <div id="mailpreviewframe">
 <roundcube:object name="messagecontentframe" id="messagecontframe"
width="100%" height="100%" frameborder="0" src="/watermark.html" />
 </div>
Index: skins/default/templates/addressbook.html
===================================================================
--- skins/default/templates/addressbook.html	(revision 410)
+++ skins/default/templates/addressbook.html	(working copy)
@@ -31,6 +31,8 @@
 <roundcube:object name="addresslist" id="contacts-table"
class="records-table" cellspacing="0" summary="Contacts list" />
 </div>

+<roundcube:object name="splitter" first="addresslist"
second="contacts-box" orientation="vertical" />
+
 <div id="contacts-box">
 <roundcube:object name="addressframe" id="contact-frame" width="100%"
height="100%" frameborder="0" src="/watermark.html" />
 </div>
Index: skins/default/addresses.css
===================================================================
--- skins/default/addresses.css	(revision 410)
+++ skins/default/addresses.css	(working copy)
@@ -70,10 +70,19 @@
   border: 1px solid #999999;
   overflow: hidden;
   /* css hack for IE */
-  width: expression((parseInt(document.documentElement.clientWidth)-530)+'px');
+  width: expression((parseInt(document.documentElement.clientWidth)-80-document.getElementById('addresslist').offsetWidth)+'px');
   height: expression((parseInt(document.documentElement.clientHeight)-135)+'px');
 }

+
+#addresslist_contacts-box_splitter
+{
+  bottom: 40px;
+  /* css hack for IE */
+  height: expression((parseInt(document.documentElement.clientHeight)-135)+'px');
+}
+
+
 body.iframe,
 #contact-frame
 {
Index: skins/default/mail.css
===================================================================
--- skins/default/mail.css	(revision 410)
+++ skins/default/mail.css	(working copy)
@@ -131,9 +131,16 @@
   background-color: #F9F9F9;
   /* css hack for IE */
   width: expression((parseInt(document.documentElement.clientWidth)-240)+'px');
-  height: expression((parseInt(document.documentElement.clientHeight)-340)+'px');
+  height: expression((parseInt(document.documentElement.clientHeight)-130-document.getElementById('mailcontframe').offsetHeight)+'px');
 }

+#mailcontframe_mailpreviewframe_splitter
+{
+  right: 40px;
+  /* css hack for IE */
+  width: expression((parseInt(document.documentElement.clientWidth)-240)+'px');
+}
+
 #messagecontframe
 {
   width: 100%;




More information about the Dev mailing list