Begin reworking Event handling model.
authorMichael M Slusarz <slusarz@curecanti.org>
Fri, 16 Jan 2009 07:46:43 +0000 (00:46 -0700)
committerMichael M Slusarz <slusarz@curecanti.org>
Fri, 16 Jan 2009 19:37:15 +0000 (12:37 -0700)
Instead of attaching event handlers to every DOM element, set a single
event handler on the document and sniff the Event object to determine
what DOM element it hit.

This is not fully complete yet, and there still are some issues (i.e
dealing with context menu actions).

imp/js/src/DimpBase.js
imp/js/src/DimpCore.js
imp/js/src/compose-dimp.js
imp/js/src/fullmessage-dimp.js
imp/templates/chunks/message.php
imp/templates/index/index.inc
imp/themes/screen-dimp.css

index a877d07..eff17af 100644 (file)
@@ -9,9 +9,9 @@
 
 var DimpBase = {
     // Vars used and defaulting to null/false:
-    //   filter_on, filtertoggle, fl_visible, folder, folderswitch, fspecial,
-    //   isvisible, message_list_template, offset, pollPE, pp, searchobserve,
-    //   uid, viewport
+    //   cfolderaction, filter_on, filtertoggle, fl_visible, folder,
+    //   folderswitch, fspecial, isvisible, message_list_template, offset,
+    //   pollPE, pp, searchobserve, uid, viewport
     bcache: $H(),
     cacheids: {},
     lastrow: -1,
@@ -520,7 +520,6 @@ var DimpBase = {
             }.bind(this),
             onFirstContent: function() {
                 this.clearPreviewPane();
-                $('msgList').observe('dblclick', this._handleMsgListDblclick.bindAsEventListener(this));
             }.bind(this),
             onClearRows: function(r) {
                 r.each(function(row) {
@@ -574,7 +573,6 @@ var DimpBase = {
 
         // Set up viewport filter events.
         this.viewport.addFilter('ListMessages', this._addSearchfilterParams.bind(this));
-        mf.observe('keyup', this._searchfilterOnKeyup.bind(this));
         mf.observe('focus', this._searchfilterOnFocus.bind(this));
         mf.observe('blur', this._searchfilterOnBlur.bind(this));
         mf.addClassName('msgFilterDefault');
@@ -686,7 +684,6 @@ var DimpBase = {
         }
         row = this.viewport.createSelection('domid', elt.id).get('dataob').first();
         row.draft ? DimpCore.compose('resume', { folder: row.view, uid: row.imapuid }) : this.msgWindow(row);
-        e.stop();
     },
 
     _handleMsgListCheckbox: function(e)
@@ -1115,27 +1112,9 @@ var DimpBase = {
             });
         }
         $('dimpmain_portal').update(r.response.portal);
-
-        /* Link portal block headers to the application. */
-        $('dimpmain_portal').select('h1.header a').each(this.bcache.get('portalClkLink') || this.bcache.set('portalClkLink', function(d) {
-            d.observe('click', function(e, d) {
-                this.go('app:' + d.readAttribute('app'));
-                e.stop();
-            }.bindAsEventListener(this, d));
-        }.bind(this)));
     },
 
     /* Search filter functions. */
-    _searchfilterOnKeyup: function()
-    {
-        if (this.searchobserve) {
-            clearTimeout(this.searchobserve);
-        }
-        if (this.filter_on) {
-            this.searchobserve = (this.bcache.get('searchfilterR') || this.bcache.set('searchfilterR', this.searchfilterRun.bind(this))).delay(0.5);
-        }
-    },
-
     searchfilterRun: function()
     {
         if (!this.viewport.isFiltering()) {
@@ -1292,33 +1271,42 @@ var DimpBase = {
     /* Keydown event handler */
     _keydownHandler: function(e)
     {
-        // Only catch keyboard shortcuts in message list view. Disable
-        // catching when the RedBox overlay is visible.
-        if (!$('dimpmain_folder').visible() ||
-            RedBox.overlayVisible()) {
-            return;
-        }
-
-        var co, ps, r, row, rowoff,
-            kc = e.keyCode || e.charCode,
-            sel = this.viewport.getSelected();
+        var co, form, ps, r, row, rowoff, sel,
+            kc = e.keyCode || e.charCode;
 
         // Form catching - normally we will ignore, but certain cases we want
         // to catch.
-        if (e.findElement('FORM')) {
+        form = e.findElement('FORM');
+        if (form) {
             switch (kc) {
             case Event.KEY_ESC:
+                // Catch escapes in search box
                 if (e.element().readAttribute('id') == 'msgList_filter') {
                     e.element().blur();
                     this.searchfilterClear(false);
                     e.stop();
                 }
                 break;
+
+            case Event.KEY_RETURN:
+                // Catch returns in RedBox
+                if (form.readAttribute('id') == 'RB_folder') {
+                    this.cfolderaction();
+                    e.stop();
+                }
+                break;
             }
 
             return;
         }
 
+        // Only catch keyboard shortcuts in message list view.
+        if (!$('dimpmain_folder').visible()) {
+            return;
+        }
+
+        sel = this.viewport.getSelected();
+
         switch (kc) {
         case Event.KEY_DELETE:
         case Event.KEY_BACKSPACE:
@@ -1398,6 +1386,287 @@ var DimpBase = {
         }
     },
 
+    _keyupHandler: function(e)
+    {
+        if (e.element().readAttribute('id') == 'msgList_filter') {
+            if (this.searchobserve) {
+                clearTimeout(this.searchobserve);
+            }
+            if (this.filter_on) {
+                this.searchobserve = (this.bcache.get('searchfilterR') || this.bcache.set('searchfilterR', this.searchfilterRun.bind(this))).delay(0.5);
+            }
+        }
+    },
+
+    _clickHandler: function(e, dblclick)
+    {
+        if (e.isRightClick()) {
+            return;
+        }
+
+        var elt = e.element(), f, id, mbox, tmp;
+
+        while (Object.isElement(elt)) {
+            id = elt.readAttribute('id');
+
+            switch (id) {
+            case 'msgList':
+                if (dblclick) {
+                    this._handleMsgListDblclick(e);
+                    e.stop();
+                    return;
+                }
+                break;
+
+            case 'RB_Folder_ok':
+                this.cfolderaction();
+                e.stop();
+                return;
+
+            case 'RB_Folder_cancel':
+                this._closeRedBox();
+                e.stop();
+                return;
+
+            case 'normalfolders':
+            case 'specialfolders':
+                this._handleFolderMouseEvent(e, 'click');
+                break;
+
+            case 'hometab':
+            case 'logolink':
+                this.go('portal');
+                e.stop();
+                return;
+
+            case 'button_compose':
+            case 'composelink':
+                DimpCore.compose('new');
+                e.stop();
+                return;
+
+            case 'checkmaillink':
+                this.pollFolders();
+                e.stop();
+                return;
+
+            case 'fetchmaillink':
+                IMPDialog.display({ dialog_load: DIMP.conf.URI_IMP + '/FetchmailDialog' });
+                e.stop();
+                return;
+
+            case 'appportal':
+            case 'appoptions':
+                this.go(id.substring(3));
+                e.stop();
+                return;
+
+            case 'applogout':
+                elt.down('A').update('[' + DIMP.text.onlogout + ']');
+                DimpCore.logout();
+                e.stop();
+                return;
+
+            case 'newfolder':
+                this.createBaseFolder();
+                e.stop();
+                return;
+
+            case 'button_forward':
+            case 'button_reply':
+                this.composeMailbox(id == 'button_reply' ? 'reply' : DIMP.conf.forward_default);
+                break;
+
+            case 'button_deleted':
+            case 'button_ham':
+            case 'button_spam':
+                this.flag(id.substring(7));
+                e.stop();
+                return;
+
+            case 'button_other':
+                DimpCore.DMenu.trigger(e.findElement('A').next(), true);
+                e.stop();
+                return;
+
+            case 'sf_all':
+            case 'sf_current':
+                this.updateSearchfilter(id.substring(3), 'folder');
+                e.stop();
+                return;
+
+            case 'sf_msgall':
+            case 'sf_from':
+            case 'sf_to':
+            case 'sf_subject':
+                this.updateSearchfilter(id.substring(3), 'msg');
+                e.stop();
+                return;
+
+            case 'msglistHeader':
+                this.sort(e);
+                e.stop();
+                return;
+
+            case 'ctx_folder_create':
+                this.createSubFolder(DimpCore.DMenu.element());
+                break;
+
+            case 'ctx_folder_rename':
+                this.renameFolder(DimpCore.DMenu.element());
+                break;
+
+            case 'ctx_folder_empty':
+                mbox = DimpCore.DMenu.element().readAttribute('mbox');
+                DimpCore.DMenu.close(true);
+                if (window.confirm(DIMP.text.empty_folder)) {
+                    DimpCore.doAction('EmptyFolder', { view: mbox }, null, this._emptyFolderCallback.bind(this));
+                }
+                break;
+
+            case 'ctx_folder_delete':
+                mbox = DimpCore.DMenu.element().readAttribute('mbox');
+                DimpCore.DMenu.close(true);
+                if (window.confirm(DIMP.text.delete_folder)) {
+                    DimpCore.doAction('DeleteFolder', { view: mbox }, null, this.bcache.get('folderC') || this.bcache.set('folderC', this._folderCallback.bind(this)));
+                }
+                break;
+
+            case 'ctx_folder_seen':
+            case 'ctx_folder_unseen':
+                this.flag(id == 'ctx_folder_seen' ? 'allSeen' : 'allUnseen', null, DimpCore.DMenu.element().readAttribute('mbox'));
+                break;
+
+            case 'ctx_folder_poll':
+            case 'ctx_folder_nopoll':
+                this.modifyPollFolder(DimpCore.DMenu.element().readAttribute('mbox'), id == 'ctx_folder_poll');
+                break;
+
+            case 'ctx_container_create':
+                this.createSubFolder(DimpCore.DMenu.element());
+                break;
+
+            case 'ctx_container_rename':
+                this.renameFolder(DimpCore.DMenu.element());
+                break;
+
+            case 'ctx_message_reply':
+            case 'ctx_message_reply_all':
+            case 'ctx_message_reply_list':
+            case 'ctx_message_forward_all':
+            case 'ctx_message_forward_body':
+            case 'ctx_message_forward_attachments':
+                this.composeMailbox(id.substring(12));
+                break;
+
+            case 'ctx_message_seen':
+            case 'ctx_message_unseen':
+            case 'ctx_message_flagged':
+            case 'ctx_message_clear':
+            case 'ctx_message_spam':
+            case 'ctx_message_ham':
+            case 'ctx_message_blacklist':
+            case 'ctx_message_whitelist':
+            case 'ctx_message_deleted':
+            case 'ctx_message_undeleted':
+                this.flag(id.substring(12));
+                break;
+
+            case 'ctx_draft_resume':
+                this.composeMailbox('resume');
+                e.stop();
+                return;
+
+            case 'ctx_draft_flagged':
+            case 'ctx_draft_clear':
+            case 'ctx_draft_deleted':
+            case 'ctx_draft_undeleted':
+                this.flag(id.substring(10));
+                break;
+
+            case 'ctx_reply_reply':
+            case 'ctx_reply_reply_all':
+            case 'ctx_reply_reply_list':
+                this.composeMailbox(id.substring(10));
+                break;
+
+            case 'ctx_forward_forward_all':
+            case 'ctx_forward_forward_body':
+            case 'ctx_forward_forward_attachments':
+                this.composeMailbox(id.substring(12));
+                break;
+
+            case 'previewtoggle':
+                this.togglePreviewPane();
+                break;
+
+            case 'oa_seen':
+            case 'oa_unseen':
+            case 'oa_flagged':
+            case 'oa_clear':
+            case 'oa_blacklist':
+            case 'oa_whitelist':
+            case 'oa_undeleted':
+                this.flag(id.substring(3));
+                break;
+
+            case 'oa_selectall':
+                this.selectAll();
+                break;
+
+            case 'oa_purge_deleted':
+                this.purgeDeleted();
+                break;
+
+            case 'th_expand':
+            case 'th_collapse':
+                this._toggleHeaders(id, true);
+                break;
+
+            case 'msg_newwin':
+            case 'msg_newwin_options':
+                this.msgWindow(this.viewport.getViewportSelection().search({ imapuid: { equal: [ DIMP.conf.msg_index ] } , view: { equal: [ DIMP.conf.msg_folder ] } }).get('dataob').first());
+                e.stop();
+                return;
+
+            case 'qclose':
+                this.searchfilterClear(false);
+                e.stop();
+                return;
+
+            case 'applicationfolders':
+                tmp = e.element();
+                if (!tmp.hasClassName('custom')) {
+                    tmp.up('LI.custom');
+                }
+                if (tmp) {
+                    this.go('app:' + tmp.down('A').readAttribute('id').substring(3));
+                    e.stop();
+                    return;
+                }
+                break;
+
+            case 'tabbar':
+                if (e.element().hasClassName('applicationtab')) {
+                    this.go('app:' + e.element().readAttribute('id').substring(6));
+                    e.stop();
+                    return;
+                }
+                break;
+
+            case 'dimpmain_portal':
+                if (e.element().match('H1.header a')) {
+                    this.go('app:' + e.element().readAttribute('app'));
+                    e.stop();
+                    return;
+                }
+                break;
+            }
+
+            elt = elt.up();
+        }
+    },
+
     /* Handle rename folder actions. */
     renameFolder: function(folder)
     {
@@ -1428,14 +1697,16 @@ var DimpBase = {
     _createFolderForm: function(action, text)
     {
         var n = new Element('FORM', { action: '#', id: 'RB_folder' }).insert(
-                    new Element('P').insert(text)
-                ).insert(
-                    new Element('INPUT', { type: 'text', size: 15 })
-                ).insert(
-                    new Element('INPUT', { type: 'button', className: 'button', value: DIMP.text.ok }).observe('click', action)
-                ).insert(
-                    new Element('INPUT', { type: 'button', className: 'button', value: DIMP.text.cancel }).observe('click', this.bcache.get('closeRB') || this.bcache.set('closeRB', this._closeRedBox.bind(this)))
-                ).observe('keydown', function(e) { if ((e.keyCode || e.charCode) == Event.KEY_RETURN) { e.stop(); action(e); } });
+                new Element('P').insert(text)
+            ).insert(
+                new Element('INPUT', { type: 'text', size: 15 })
+            ).insert(
+                new Element('INPUT', { type: 'button', id: 'RB_Folder_ok', className: 'button', value: DIMP.text.ok })
+            ).insert(
+                new Element('INPUT', { type: 'button', id: 'RB_Folder_cancel', className: 'button', value: DIMP.text.cancel })
+            );
+
+        this.cfolderaction = action;
 
         RedBox.overlay = true;
         RedBox.onDisplay = Form.focusFirstElement.curry(n);
@@ -1445,9 +1716,8 @@ var DimpBase = {
 
     _closeRedBox: function()
     {
-        var c = RedBox.getWindowContents();
-        DimpCore.addGC([ c, c.descendants() ].flatten());
         RedBox.close();
+        this.cfolderaction = null;
     },
 
     _folderAction: function(folder, e, mode)
@@ -1568,7 +1838,6 @@ var DimpBase = {
             nf = $('normalfolders'),
             nfheight = nf.getStyle('max-height');
 
-        elts.invoke('observe', 'click', this._handleFolderMouseEvent.bindAsEventListener(this, 'click'));
         elts.invoke('observe', 'mouseover', this._handleFolderMouseEvent.bindAsEventListener(this, 'over'));
         if (DIMP.conf.is_ie6) {
             elts.invoke('observe', 'mouseout', this._handleFolderMouseEvent.bindAsEventListener(this, 'out'));
@@ -1985,10 +2254,6 @@ var DimpBase = {
 
     /* Onload function. */
     _onLoad: function() {
-        var tmp,
-             C = DimpCore.clickObserveHandler,
-             dmenu = DimpCore.DMenu;
-
         if (Horde.dhtmlHistory.initialize()) {
             Horde.dhtmlHistory.addListener(this.go.bind(this));
         }
@@ -2011,133 +2276,17 @@ var DimpBase = {
 
         /* Add popdown menus. */
         DimpCore.addPopdown('button_reply', 'reply');
-        dmenu.disable('button_reply_img', true, true);
+        DimpCore.DMenu.disable('button_reply_img', true, true);
         DimpCore.addPopdown('button_forward', 'forward');
-        dmenu.disable('button_forward_img', true, true);
+        DimpCore.DMenu.disable('button_forward_img', true, true);
         DimpCore.addPopdown('button_other', 'otheractions');
 
-        /* Set up click event observers for elements on main page. */
-        tmp = $('logo');
-        if (tmp.visible()) {
-            C({ d: tmp.down('a'), f: this.go.bind(this, 'portal') });
-        }
-
-        C({ d: $('composelink'), f: DimpCore.compose.bind(DimpCore, 'new') });
-        C({ d: $('checkmaillink'), f: this.pollFolders.bind(this) });
-
-        tmp = $('fetchmaillink');
-        if (tmp) {
-            C({ d: tmp, f: IMPDialog.display.bind(IMPDialog, { dialog_load: DIMP.conf.URI_IMP + '/FetchmailDialog' }) });
-        }
-
-        [ 'portal', 'options' ].each(function(a) {
-            var d = $('app' + a);
-            if (d) {
-                C({ d: d, f: this.go.bind(this, a) });
-            }
-        }, this);
-        tmp = $('applogout');
-        if (tmp) {
-            C({ d: tmp, f: function() { $('applogout').down('A').update('[' + DIMP.text.onlogout + ']'); DimpCore.logout(); } });
-        }
-
-        tmp = $('applicationfolders');
-        if (tmp) {
-            tmp.select('li.custom a').each(function(s) {
-                C({ d: s, f: this.go.bind(this, 'app:' + s.readAttribute('app')) });
-            }, this);
-        }
-
-        C({ d: $('newfolder'), f: this.createBaseFolder.bind(this) });
         new Drop('dropbase', this._folderDropConfig);
-        tmp = $('hometab');
-        if (tmp) {
-            C({ d: tmp, f: this.go.bind(this, 'portal') });
-        }
-        $('tabbar').select('a.applicationtab').each(function(a) {
-            C({ d: a, f: this.go.bind(this, 'app:' + a.readAttribute('app')) });
-        }, this);
-        C({ d: $('button_reply'), f: this.composeMailbox.bind(this, 'reply'), ns: true });
-        C({ d: $('button_forward'), f: this.composeMailbox.bind(this, DIMP.conf.forward_default), ns: true });
-        [ 'spam', 'ham', 'deleted' ].each(function(a) {
-            var d = $('button_' + a);
-            if (d) {
-                C({ d: d, f: this.flag.bind(this, a) });
-            }
-        }, this);
-        C({ d: $('button_compose').down('A'), f: DimpCore.compose.bind(DimpCore, 'new') });
-        C({ d: $('button_other'), f: function(e) { dmenu.trigger(e.findElement('A').next(), true); }, p: true });
-        C({ d: $('qoptions').down('.qclose a'), f: this.searchfilterClear.bind(this, false) });
-        [ 'all', 'current' ].each(function(a) {
-            var d = $('sf_' + a);
-            if (d) {
-                C({ d: d, f: this.updateSearchfilter.bind(this, a, 'folder') });
-            }
-        }, this);
-        [ 'msgall', 'from', 'to', 'subject' ].each(function(a) {
-            C({ d: $('sf_' + a), f: this.updateSearchfilter.bind(this, a, 'msg') });
-        }, this);
-        C({ d: $('msglistHeader'), f: this.sort.bind(this), p: true });
-        C({ d: $('ctx_folder_create'), f: function() { this.createSubFolder(dmenu.element()); }.bind(this), ns: true });
-        C({ d: $('ctx_folder_rename'), f: function() { this.renameFolder(dmenu.element()); }.bind(this), ns: true });
-        C({ d: $('ctx_folder_empty'), f: function() { var mbox = dmenu.element().readAttribute('mbox'); dmenu.close(true); if (window.confirm(DIMP.text.empty_folder)) { DimpCore.doAction('EmptyFolder', { view: mbox }, null, this._emptyFolderCallback.bind(this)); } }.bind(this), ns: true });
-        C({ d: $('ctx_folder_delete'), f: function() { var mbox = dmenu.element().readAttribute('mbox'); dmenu.close(true); if (window.confirm(DIMP.text.delete_folder)) { DimpCore.doAction('DeleteFolder', { view: mbox }, null, this.bcache.get('folderC') || this.bcache.set('folderC', this._folderCallback.bind(this))); } }.bind(this), ns: true });
-        [ 'ctx_folder_seen', 'ctx_folder_unseen' ].each(function(a) {
-            C({ d: $(a), f: function(type) { this.flag(type, null, dmenu.element().readAttribute('mbox')); }.bind(this, a == 'ctx_folder_seen' ? 'allSeen' : 'allUnseen'), ns: true });
-        }, this);
-        [ 'ctx_folder_poll', 'ctx_folder_nopoll' ].each(function(a) {
-            C({ d: $(a), f: function(modify) { this.modifyPollFolder(dmenu.element().readAttribute('mbox'), modify); }.bind(this, a == 'ctx_folder_poll'), ns: true });
-        }, this);
-        C({ d: $('ctx_container_create'), f: function() { this.createSubFolder(dmenu.element()); }.bind(this), ns: true });
-        C({ d: $('ctx_container_rename'), f: function() { this.renameFolder(dmenu.element()); }.bind(this), ns: true });
-        [ 'reply', 'reply_all', 'reply_list', 'forward_all', 'forward_body', 'forward_attachments' ].each(function(a) {
-            C({ d: $('ctx_message_' + a), f: this.composeMailbox.bind(this, a), ns: true });
-        }, this);
-        [ 'seen', 'unseen', 'flagged', 'clear', 'spam', 'ham', 'blacklist', 'whitelist', 'deleted', 'undeleted' ].each(function(a) {
-            var d = $('ctx_message_' + a);
-            if (d) {
-                C({ d: d, f: this.flag.bind(this, a), ns: true });
-            }
-        }, this);
-        C({ d: $('ctx_draft_resume'), f: this.composeMailbox.bind(this, 'resume') });
-        [ 'flagged', 'clear', 'deleted', 'undeleted' ].each(function(a) {
-            var d = $('ctx_draft_' + a);
-            if (d) {
-                C({ d: d, f: this.flag.bind(this, a), ns: true });
-            }
-        }, this);
-        [ 'reply', 'reply_all', 'reply_list' ].each(function(a) {
-            C({ d: $('ctx_reply_' + a), f: this.composeMailbox.bind(this, a), ns: true });
-        }, this);
-        [ 'forward_all', 'forward_body', 'forward_attachments' ].each(function(a) {
-            C({ d: $('ctx_forward_' + a), f: this.composeMailbox.bind(this, a), ns: true });
-        }, this);
-        C({ d: $('previewtoggle'), f: this.togglePreviewPane.bind(this), ns: true });
-        [ 'seen', 'unseen', 'flagged', 'clear', 'blacklist', 'whitelist', 'undeleted' ].each(function(a) {
-            var d = $('oa_' + a);
-            if (d) {
-                C({ d: d, f: this.flag.bind(this, a), ns: true });
-            }
-        }, this);
-        C({ d: $('oa_selectall'), f: this.selectAll.bind(this), ns: true });
 
-        tmp = $('oa_purge_deleted');
-        if (tmp) {
-            C({ d: tmp, f: this.purgeDeleted.bind(this), ns: true });
-        }
-
-        $('th_expand', 'th_collapse').each(function(a) {
-            C({ d: a, f: this._toggleHeaders.bind(this, a, true), ns: true });
-        }.bind(this));
         if (DIMP.conf.toggle_pref) {
             this._toggleHeaders($('th_expand'));
         }
 
-        $('msg_newwin', 'msg_newwin_options').compact().each(function(a) {
-            C({ d: a, f: function() { this.msgWindow(this.viewport.getViewportSelection().search({ imapuid: { equal: [ DIMP.conf.msg_index ] } , view: { equal: [ DIMP.conf.msg_folder ] } }).get('dataob').first()); }.bind(this) });
-        }, this);
-
-        DimpCore.messageOnLoad();
         this._resizeIE6();
     },
 
@@ -2260,7 +2409,12 @@ document.observe('dom:loaded', function() {
     DimpBase.setPollFolders();
 
     /* Bind key shortcuts. */
-    document.observe('keydown', DimpBase._keydownHandler.bind(DimpBase));
+    document.observe('keydown', DimpBase._keydownHandler.bindAsEventListener(DimpBase));
+    document.observe('keyup', DimpBase._keyupHandler.bindAsEventListener(DimpBase));
+
+    /* Bind mouse clicks. */
+    document.observe('click', DimpBase._clickHandler.bindAsEventListener(DimpBase));
+    document.observe('dblclick', DimpBase._clickHandler.bindAsEventListener(DimpBase, true));
 
     /* Resize elements on window size change. */
     Event.observe(window, 'resize', DimpBase._onResize.bind(DimpBase));
index 61f4a42..60ec52b 100644 (file)
@@ -138,7 +138,7 @@ DimpCore = {
                 }
                 uids = tmp;
             }
-            params.set('uid', DimpCore.toRangeString(uids));
+            params.set('uid', this.toRangeString(uids));
         }
         if (DIMP.conf.SESSION_ID) {
             params.update(DIMP.conf.SESSION_ID.toQueryParams());
@@ -451,53 +451,12 @@ DimpCore = {
         [ id.select('.address'), id.select('.largeaddrtoggle') ].flatten().compact().each(this.removeMouseEvents.bind(this));
     },
 
-    /* Add event observers to message output.  Adds observers used in both
-     * the base page and the popup message window. */
-    messageOnLoad: function()
-    {
-        var C = this.clickObserveHandler, tmp;
-
-        if ($('partlist')) {
-            C({ d: $('partlist_col').up(), f: function() { $('partlist', 'partlist_col', 'partlist_exp').invoke('toggle'); } });
-        }
-        if (tmp = $('msg_print')) {
-            C({ d: tmp, f: function() { window.print(); } });
-        }
-        if (tmp = $('msg_view_source')) {
-            C({ d: tmp, f: function() { view(DimpCore.addURLParam(DIMP.conf.URI_VIEW, { index: DIMP.conf.msg_index, mailbox: DIMP.conf.msg_folder, actionID: 'view_source', id: 0 }, true), DIMP.conf.msg_index + '|' + DIMP.conf.msg_folder) } });
-        }
-        C({ d: $('ctx_contacts_new'), f: function() { this.compose('new', { to: this.DMenu.element().readAttribute('address') }); }.bind(this), ns: true });
-        C({ d: $('ctx_contacts_add'), f: function() { this.doAction('AddContact', { name: this.DMenu.element().readAttribute('personal'), email: this.DMenu.element().readAttribute('email') }, null, true); }.bind(this), ns: true });
-        if ($('alertslog')) {
-            C({ d: $('alertsloglink'), f: this.toggleAlertsLog.bind(this) });
-        }
-    },
-
     /* Utility functions. */
     addGC: function(elt)
     {
         this.remove_gc = this.remove_gc.concat(elt);
     },
 
-    // o: (object) Contains the following items:
-    //    'd'  - (required) The DOM element
-    //    'f'  - (required) The function to bind to the click event
-    //    'ns' - (optional) If set, don't stop the event's propogation
-    //    'p'  - (optional) If set, passes in the event object to the called
-    //                      function
-    clickObserveHandler: function(o)
-    {
-        return o.d.observe('click', DimpCore._clickFunc.curry(o));
-    },
-
-    _clickFunc: function(o, e)
-    {
-        o.p ? o.f(e) : o.f();
-        if (!o.ns) {
-            e.stop();
-        }
-    },
-
     addURLParam: function(url, params)
     {
         var q = url.indexOf('?');
@@ -522,6 +481,56 @@ DimpCore = {
         } else {
             DimpBase.loadPreview(null, params);
         }
+    },
+
+    /* Mouse click handler. */
+    _clickHandler: function(e)
+    {
+        if (e.isRightClick()) {
+            return;
+        }
+
+        var elt = e.element(), id, tmp;
+
+        while (Object.isElement(elt)) {
+            id = elt.readAttribute('id');
+
+            switch (id) {
+            case 'partlist_toggle':
+                tmp = $('partlist');
+                $('partlist_col', 'partlist_exp').invoke('toggle');
+                if (tmp.visible()) {
+                    Effect.BlindUp(tmp, { duration: 0.2 });
+                } else {
+                    Effect.BlindDown(tmp, { duration: 0.2 });
+                }
+                e.stop();
+                return;
+
+            case 'msg_print':
+                window.print();
+                e.stop();
+                return;
+
+            case 'msg_view_source':
+                this.popupWindow(this.addURLParam(DIMP.conf.URI_VIEW, { index: DIMP.conf.msg_index, mailbox: DIMP.conf.msg_folder, actionID: 'view_source', id: 0 }, true), DIMP.conf.msg_index + '|' + DIMP.conf.msg_folder);
+                break;
+
+            case 'ctx_contacts_new':
+                this.compose('new', { to: this.DMenu.element().readAttribute('address') });
+                break;
+
+            case 'ctx_contacts_add':
+                this.doAction('AddContact', { name: this.DMenu.element().readAttribute('personal'), email: this.DMenu.element().readAttribute('email') }, null, true);
+                break;
+
+            case 'alertsloglink':
+                this.toggleAlertsLog();
+                break;
+            }
+
+            elt = elt.up();
+        }
     }
 };
 
@@ -561,6 +570,9 @@ document.observe('dom:loaded', function() {
             }
         }
     }, 10);
+
+    /* Add click handler. */
+    document.observe('click', DimpCore._clickHandler.bindAsEventListener(DimpCore));
 });
 
 Event.observe(window, 'load', function() {
@@ -634,12 +646,3 @@ Object.extend(String.prototype, {
         });
     }
 });
-
-/** Functions overriding IMP/prototypejs JS functions. **/
-
-/* We need to replace the IMP javascript for this function with code that
- * calls the correct DIMP functions. */
-function popup_imp(url, w, h, args)
-{
-    DimpCore.compose('new', args.toQueryParams().toObject());
-}
index 8961cc9..9b643dc 100644 (file)
@@ -495,14 +495,10 @@ var DimpCompose = {
     {
         var span = new Element('SPAN').insert(name),
             div = new Element('DIV').insert(span).insert(' [' + type + '] (' + size + ' KB) '),
-            input = new Element('INPUT', { type: 'button', atc_id: atc_num, value: DIMP.text_compose.remove }),
-            C = DimpCore.clickObserveHandler;
+            input = new Element('INPUT', { type: 'button', atc_id: atc_num, value: DIMP.text_compose.remove });
         div.insert(input);
         $('attach_list').insert(div);
-        C({ d: input, f: this.removeAttach.bind(this, [ input.up() ]) });
-        if (type != 'application/octet-stream') {
-            C({ d: span.addClassName('attachName'), f: function() { view(DimpCore.addURLParam(DIMP.conf.URI_VIEW, { composeCache: $F('composeCache'), actionID: 'compose_attach_preview', id: atc_num }), $F('composeCache') + '|' + atc_num) } });
-        }
+
         this.resizeMsgArea();
     },
 
@@ -629,6 +625,57 @@ var DimpCompose = {
     openAddressbook: function()
     {
         window.open(DIMP.conf_compose.abook_url, 'contacts', 'toolbar=no,location=no,status=no,scrollbars=yes,resizable=yes,width=550,height=300,left=100,top=100');
+    },
+
+    /* Click observe handler. */
+
+    _clickHandler: function(e)
+    {
+        if (e.isRightClick()) {
+            return;
+        }
+
+        var elt = e.element(), id, tmp;
+
+        while (Object.isElement(elt)) {
+            id = elt.readAttribute('id');
+
+            switch (id) {
+            case 'togglebcc':
+            case 'togglecc':
+                this.toggleCC(id.substring(6));
+                this.resizeMsgArea();
+                break;
+
+            case 'compose_close':
+                this.confirmCancel();
+                break;
+
+            case 'draft_button':
+            case 'send_button':
+                this.uniqueSubmit(id == 'send_button' ? 'send_message' : 'save_draft');
+                break;
+
+            case 'htmlcheckbox':
+                this.toggleHtmlCheckbox();
+                break;
+            }
+
+            /*
+            if (DIMP.conf_compose.abook_url) {
+                $('sendto', 'sendcc', 'sendbcc').each(function(a) {
+                    C({ d: a.down('TD.label SPAN').addClassName('composeAddrbook'), f: DC.openAddressbook.bind(DC) });
+                });
+            }
+
+        C({ d: input, f: this.removeAttach.bind(this, [ input.up() ]) });
+        if (type != 'application/octet-stream') {
+            C({ d: span.addClassName('attachName'), f: function() { view(DimpCore.addURLParam(DIMP.conf.URI_VIEW, { composeCache: $F('composeCache'), actionID: 'compose_attach_preview', id: atc_num }), $F('composeCache') + '|' + atc_num) } });
+        }
+            */
+
+            elt = elt.up();
+        }
     }
 },
 
@@ -676,8 +723,7 @@ ResizeTextArea = Class.create({
 document.observe('dom:loaded', function() {
     var tmp,
         DC = DimpCompose,
-        boundResize = DC.resizeMsgArea.bind(DC),
-        C = DimpCore.clickObserveHandler;
+        boundResize = DC.resizeMsgArea.bind(DC);
 
     DC.resizeMsgArea();
     DC.initializeSpellChecker();
@@ -695,24 +741,8 @@ document.observe('dom:loaded', function() {
         $('submit_frame').writeAttribute({ position: 'absolute', width: '1px', height: '1px' }).setStyle({ left: '-999px' }).show();
     }
 
-    /* Attach click handlers. */
-    if (tmp = $('compose_close')) {
-        C({ d: tmp, f: DC.confirmCancel.bind(DC) });
-    }
-    C({ d: $('send_button'), f: DC.uniqueSubmit.bind(DC, 'send_message') });
-    C({ d: $('draft_button'), f: DC.uniqueSubmit.bind(DC, 'save_draft') });
-    [ 'cc', 'bcc' ].each(function(a) {
-        C({ d: $('toggle' + a), f: DC.toggleCC.bind(DC, a) });
-    });
-    if (tmp = $('htmlcheckbox')) {
-        C({ d: tmp, f: DC.toggleHtmlCheckbox.bind(DC), ns: true });
-    }
-
-    if (DIMP.conf_compose.abook_url) {
-        $('sendto', 'sendcc', 'sendbcc').each(function(a) {
-            C({ d: a.down('TD.label SPAN').addClassName('composeAddrbook'), f: DC.openAddressbook.bind(DC) });
-        });
-    }
+    /* Mouse click handler. */
+    document.observe('click', DC._clickHandler.bindAsEventListener(DC));
 
     /* Only allow submit through send button. */
     $('compose').observe('submit', Event.stop);
@@ -720,9 +750,5 @@ document.observe('dom:loaded', function() {
     /* Attach other handlers. */
     $('identity').observe('change', DC.change_identity.bind(DC));
 
-    // Various events that may cause the textarea to grow larger than the
-    // window size.
-    $('togglecc').observe('click', boundResize);
-    $('togglebcc').observe('click', boundResize);
     Event.observe(window, 'resize', boundResize);
 });
index 9442a8b..058ea73 100644 (file)
@@ -64,13 +64,62 @@ var DimpFullmessage = {
         if (r.imp_compose) {
             $('composeCache').setValue(r.imp_compose);
         }
+    },
+
+    /* Mouse click handler. */
+    _clickHandler: function(e)
+    {
+        if (e.isRightClick()) {
+            return;
+        }
+
+        var elt = e.element(), id;
+
+        while (Object.isElement(elt)) {
+            id = elt.readAttribute('id');
+
+            switch (id) {
+            case 'windowclose':
+                window.close();
+                e.stop();
+                exit;
+
+            case 'forward_link':
+            case 'reply_link':
+                this.quickreply(id == 'reply_link' ? 'reply' : DIMP.conf.forward_default);
+                e.stop();
+                exit;
+
+            case 'button_deleted':
+            case 'button_ham':
+            case 'button_spam':
+                DIMP.baseWindow.DimpBase.flag(id.substring(7), DIMP.conf.msg_index, DIMP.conf.msg_folder);
+                window.close();
+                e.stop();
+                exit;
+
+            case 'ctx_replypopdown_reply':
+            case 'ctx_replypopdown_reply_all':
+            case 'ctx_replypopdown_reply_list':
+                this.quickreply(id.substring(17));
+                break;
+
+            case 'ctx_fwdpopdown_forward_all':
+            case 'ctx_fwdpopdown_forward_body':
+            case 'ctx_fwdpopdown_forward_attachments':
+                this.quickreply(id.substring(15));
+                break;
+            }
+
+            // C({ d: $('qreply').select('div.headercloseimg img').first(), f: DimpCompose.confirmCancel.bind(DimpCompose) });
+            elt = elt.up();
+        }
     }
 
 };
 
 document.observe('dom:loaded', function() {
     window.focus();
-    DimpCore.messageOnLoad();
     DimpCore.addPopdown('reply_link', 'replypopdown');
     DimpCore.addPopdown('forward_link', 'fwdpopdown');
 
@@ -83,24 +132,5 @@ document.observe('dom:loaded', function() {
     });
 
     /* Set up click handlers. */
-    var C = DimpCore.clickObserveHandler;
-    C({ d: $('windowclose'), f: function() { window.close(); } });
-    C({ d: $('reply_link'), f: DimpFullmessage.quickreply.bind(DimpFullmessage, 'reply') });
-    C({ d: $('forward_link'), f: DimpFullmessage.quickreply.bind(DimpFullmessage, DIMP.conf.forward_default) });
-    [ 'spam', 'ham', 'deleted' ].each(function(a) {
-        var d = $('button_' + a);
-        if (d) {
-            C({ d: d, f: function(a) { DIMP.baseWindow.DimpBase.flag(a, DIMP.conf.msg_index, DIMP.conf.msg_folder); window.close(); }.curry(a) });
-        }
-    });
-    C({ d: $('qreply').select('div.headercloseimg img').first(), f: DimpCompose.confirmCancel.bind(DimpCompose) });
-    [ 'reply', 'reply_all', 'reply_list' ].each(function(a) {
-        var d = $('ctx_replypopdown_' + a);
-        if (d) {
-            C({ d: d, f: DimpFullmessage.quickreply.bind(DimpFullmessage, a), ns: true });
-        }
-    });
-    [ 'forward_all', 'forward_body', 'forward_attachments' ].each(function(a) {
-        C({ d: $('ctx_fwdpopdown_' + a), f: DimpFullmessage.quickreply.bind(DimpFullmessage, a), ns: true });
-    });
+    document.observe('click', DimpFullmessage.clickHandler.bindAsEventListener(DimpFullmessage));
 });
index d1940dd..f1607a5 100644 (file)
@@ -69,7 +69,7 @@ function _createDAfmsg($text, $image, $id, $class = '', $show_text = true)
 <?php endforeach; ?>
 <?php if (isset($show_msg_result['atc_label'])): ?>
         <tr id="msgAtc">
-         <td class="label"><?php if ($show_msg_result['atc_list']): ?><?php echo Horde::link('') ?><span id="partlist_col" class="iconImg arrowcollapsedImg"></span><span id="partlist_exp" class="iconImg arrowexpandedImg" style="display:none"></span> <span class="iconImg attachmentImg attachmentImage"></span></a><?php else: ?><span class="iconImg attachmentImg attachmentImage"></span><?php endif; ?></td>
+         <td class="label"><?php if ($show_msg_result['atc_list']): ?><a id="partlist_toggle"><span id="partlist_col" class="iconImg arrowcollapsedImg"></span><span id="partlist_exp" class="iconImg arrowexpandedImg" style="display:none"></span> <span class="iconImg attachmentImg attachmentImage"></span></a><?php else: ?><span class="iconImg attachmentImg attachmentImage"></span><?php endif; ?></td>
          <td>
           <span class="atcLabel"><?php echo $show_msg_result['atc_label'] ?></span><?php echo $show_msg_result['atc_download'] ?>
 <?php if (isset($show_msg_result['atc_list'])): ?>
index 8aacf92..f532b5f 100644 (file)
@@ -58,7 +58,7 @@ function _simpleButton($id, $text, $image, $imagedir = null)
  <div id="header"></div>
  <div id="pageContainer">
   <div id="sidebarPanel" class="noprint" style="width:<?php echo $sidebar_width ?>">
-   <div id="logo"><h1><a><?php echo _("Horde") ?></a></h1></div>
+   <div id="logo"><h1><a id="logolink"><?php echo _("Horde") ?></a></h1></div>
    <ul id="dimpbarActions">
     <?php echo _simpleButton('composelink', _("_New Message"), 'compose.png') ?>
     <?php echo _simpleButton('checkmaillink', _("_Get Mail"), 'checkmail.png') ?>
@@ -91,7 +91,7 @@ function _simpleButton($id, $text, $image, $imagedir = null)
 <?php foreach ($application_folders as $val): ?>
      <li class="custom">
       <img src="<?php echo $val['icon'] ?>" alt="<?php echo $val['name'] ?>" />
-      <a title="<?php echo $val['name'] ?>" id="app<?php echo $val['app'] ?>" app="<?php echo $val['app'] ?>"><?php echo $val['name'] ?></a>
+      <a title="<?php echo $val['name'] ?>" id="app<?php echo $val['app'] ?>"><?php echo $val['name'] ?></a>
      </li>
 <?php endforeach; ?>
     </ul>
@@ -143,7 +143,7 @@ function _simpleButton($id, $text, $image, $imagedir = null)
         </li>
 <?php foreach ($application_folders as $val): ?>
         <li<?php if ($val['app'] == 'dimp') echo ' class="activeTab"' ?>>
-         <a class="applicationtab" app="<?php echo $val['app'] ?>"><img src="<?php echo $val['icon'] ?>" alt="<?php echo $val['name'] ?>" /><?php echo $val['name'] ?></a>
+         <a class="applicationtab" id="apptab<?php echo $val['app'] ?>"><img src="<?php echo $val['icon'] ?>" alt="<?php echo $val['name'] ?>" /><?php echo $val['name'] ?></a>
         </li>
 <?php endforeach; ?>
 <?php foreach ($site_menu as $key => $menu_item): if ($menu_item == 'separator') continue; ?>
@@ -209,7 +209,7 @@ function _simpleButton($id, $text, $image, $imagedir = null)
 
      <div style="display:none">
       <div id="qoptions">
-       <span class="qclose"><a>x</a></span>
+       <span id="qclose"><a>x</a></span>
        <span class="qlabel"><?php echo _("Folders: ") ?></span>
 <?php if (!empty($conf['dimp']['search']['search_all'])): ?>
        <a id="sf_all"><?php echo _("All") ?></a>
@@ -316,7 +316,7 @@ function _simpleButton($id, $text, $image, $imagedir = null)
              <td class="cc"></td>
             </tr>
             <tr id="msgAtc" style="display:none">
-             <td class="label"><span class="iconImg attachmentImg attachmentImage"></span><?php echo Horde::link('') ?><span class="iconImg arrowcollapsedImg" id="partlist_col"></span><span class="iconImg arrowexpandedImg" id="partlist_exp" style="display:none"></span></a></td>
+             <td class="label"><span class="iconImg attachmentImg attachmentImage"></span><a id="partlist_toggle"><span class="iconImg arrowcollapsedImg" id="partlist_col"></span><span class="iconImg arrowexpandedImg" id="partlist_exp" style="display:none"></span></a></td>
              <td>
               <div></div>
               <table id="partlist" style="display:none" cellspacing="2">
index 89f00fe..6a2a20e 100644 (file)
@@ -725,8 +725,8 @@ div.dimpActionsCompose {
     padding: 4px;
 }
 .mimeStatusMessage {
-    background: #ffc;
-    border: 1px #fffba4 solid;
+    margin-bottom: 4px;
+    margin-top: 2px;
 }
 .mimePartInfo {
     background: #efefef;
@@ -1074,7 +1074,7 @@ a.address:hover img {
     -webkit-border-radius: 5px;
     padding: 1px 4px;
 }
-#qoptions .qclose a, #qoptions .qclose a:visited {
+#qclose a, #qclose a:visited {
     float: right;
     margin-top: -2px;
     width: 10px;
@@ -1092,7 +1092,7 @@ a.address:hover img {
     padding: 0px 2px 2px 4px;
     text-decoration: none;
 }
-#qoptions .qclose a:hover {
+#qclose a:hover {
     background: #fff;
 }
 #qoptions .qlabel {