kolab-webclient/dimp
Jeroen van Meeuwen
vanmeeuwen at kolabsys.com
Tue Jan 11 00:58:52 CET 2011
kolab-webclient/dimp/patches/dimp-1.1.6/0001-fix-broken-folder-images.patch | 2197 +++++++++
kolab-webclient/dimp/patches/dimp-1.1.6/0002-close-context-menu.patch | 21
kolab-webclient/dimp/patches/dimp-1.1.6/0003-acl-view.patch | 83
kolab-webclient/dimp/patches/dimp-1.1.6/0004-folders-view.patch | 41
kolab-webclient/dimp/patches/dimp-1.1.6/0005-itip-handling.patch | 69
kolab-webclient/dimp/patches/dimp-1.1.6/0006-copy-msgs-with-ctrl.patch | 629 ++
kolab-webclient/dimp/patches/dimp-1.1.6/series | 13
kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_HK_GW_ItipHandling.diff | 72
kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_BL_CloseContextMenu.diff | 45
kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_GW_AclView.diff | 107
kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_GW_FoldersView.diff | 100
kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_MS_CopyMessagesWithCtrl.diff | 629 --
kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_MS_FixBrokenFolderImages.diff | 2235 ----------
13 files changed, 3047 insertions(+), 3194 deletions(-)
New commits:
commit dffe0f2c514be3c639f03641e35dfd138250a475
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date: Mon Jan 10 23:58:21 2011 +0000
Rebase patches onto the actual dimp-h3-1.1.6.tar.gz sources
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/0001-fix-broken-folder-images.patch b/kolab-webclient/dimp/patches/dimp-1.1.6/0001-fix-broken-folder-images.patch
new file mode 100644
index 0000000..528468e
--- /dev/null
+++ b/kolab-webclient/dimp/patches/dimp-1.1.6/0001-fix-broken-folder-images.patch
@@ -0,0 +1,2197 @@
+diff -ur dimp-h3-1.1.6.orig/js/DimpBase.js dimp-h3-1.1.6/js/DimpBase.js
+--- dimp-h3-1.1.6.orig/js/DimpBase.js 2010-09-27 19:14:31.000000000 +0100
++++ dimp-h3-1.1.6/js/DimpBase.js 2011-01-10 23:49:33.895945000 +0000
+@@ -1 +1,2146 @@
+-var DimpBase={bcache:$H(),delay_onload:(!Prototype.Browser.Gecko&&!Prototype.Browser.Opera),lastrow:-1,mo_sidebar:$H(),pivotrow:-1,ppcache:$H(),ppfifo:[],showPreview:DIMP.conf.preview_pref,sfiltersfolder:$H({sf_all:"all",sf_current:"current"}),sfilters:$H({sf_msgall:"msgall",sf_from:"from",sf_to:"to",sf_subject:"subject"}),unseen_regex:new RegExp("(^|\\s)unseen(\\s|$)"),_select:function(c,a){var b=c.get("rownum");if(b.size()==1){this.lastrow=this.pivotrow=b.first()}this.toggleButtons();if($("previewPane").visible()){if(a.right){this.clearPreviewPane()}else{if(a.delay){(this.bcache.get("initPP")||this.bcache.set("initPP",this.initPreviewPane.bind(this))).delay(a.delay)}else{this.initPreviewPane()}}}},_deselect:function(d,b){var c=this.viewport.getSelected(),a=c.size();if(!a){this.lastrow=this.pivotrow=-1}this.toggleButtons();if(b.right||!a){this.clearPreviewPane()}else{if((a==1)&&$("previewPane").visible()){this._loadPreview(c.get("dataob").first())}}},msgSelect:function(g,c
){var b,e=this.viewport.createSelection("domid",g),a=e.get("rownum").first(),d=this.isSelected("domid",g),f=this.selectedCount();this.lastrow=a;$("msgList_filter").blur();if(c.shift){if(f){if(!d||f!=1){b=[a,this.pivotrow];this.viewport.select($A($R(b.min(),b.max())),{range:true})}return}}else{if(c.ctrl){this.pivotrow=a;if(d){this.viewport.deselect(e,{right:c.right});return}else{if(c.right||f){this.viewport.select(e,{add:true,right:c.right});return}}}}this.viewport.select(e,{right:c.right})},selectAll:function(){this.viewport.select($A($R(1,this.viewport.getMetaData("total_rows"))),{range:true})},isSelected:function(b,a){return this.viewport.getSelected().contains(b,a)},selectedCount:function(){return(this.viewport)?this.viewport.getSelected().size():0},resetSelected:function(){if(this.viewport){this.viewport.deselect(this.viewport.getSelected(),{clearall:true})}this.toggleButtons();this.clearPreviewPane()},moveSelected:function(a,g){var e,d,f,b,c;if(g){if(!this.viewport.getM
etaData("total_rows")){return}e=a}else{if(a==0){return}c=thi!
s.viewpo
rt.getSelected();switch(c.size()){case 0:e=this.viewport.currentOffset();e+=(a>0)?1:this.viewport.getPageSize("current");break;case 1:d=c.get("dataob").first();e=d.rownum+a;break;default:c=c.get("rownum");e=(a>0?c.max():c.min())+a;break}e=(a>0)?Math.min(e,this.viewport.getMetaData("total_rows")):Math.max(e,1)}f=this.viewport.createSelection("rownum",e);if(f.size()){b=f.get("dataob").first();if(!d||b.imapuid!=d.imapuid){this.viewport.scrollTo(b.rownum);this.viewport.select(f,{delay:0.3})}}else{this.offset=e;this.viewport.requestContentRefresh(e-1)}},go:function(e,b){var d,a,c;if(e.startsWith("compose:")){return}if(e.startsWith("msg:")){c=e.indexOf(":",4);a=e.substring(4,c);this.uid=e.substring(c+1);e="folder:"+a}if(e.startsWith("folder:")){a=e.substring(7);if(this.folder!=a||!$("dimpmain_folder").visible()){this.highlightSidebar(this.getFolderId(a));if(!$("dimpmain_folder").visible()){$("dimpmain_portal").hide();$("dimpmain_folder").show()}if(!Object.isUndefined(this.folder)){
this._addHistory(e)}}this.loadFolder(a);return}this.folder=null;$("dimpmain_folder").hide();$("dimpmain_portal").update(DIMP.text.loading).show();if(e.startsWith("app:")){d=e.substr(4);if(d=="imp"||d=="dimp"){this.go("folder:INBOX");return}this.highlightSidebar("app"+d);this._addHistory(e,b);if(b){this.iframeContent(e,b)}else{if(DIMP.conf.app_urls[d]){this.iframeContent(e,DIMP.conf.app_urls[d])}}return}switch(e){case"portal":this.highlightSidebar("appportal");this._addHistory(e);DimpCore.setTitle(DIMP.text.portal);DimpCore.doAction("ShowPortal",{},[],this.bcache.get("portalC")||this.bcache.set("portalC",this._portalCallback.bind(this)));break;case"options":this.highlightSidebar("appoptions");this._addHistory(e);DimpCore.setTitle(DIMP.text.prefs);this.iframeContent(e,DIMP.conf.prefs_url);break}},_addHistory:function(b,a){if(Horde.dhtmlHistory.getCurrentLocation()!=b){Horde.dhtmlHistory.add(b,a)}},highlightSidebar:function(b){if($("foldersLoading").visible()){this.highlightSid
ebar.bind(this,b).defer();return}$("sidebarPanel").select(".!
on").inv
oke("removeClassName","on");var a=$(b);if(!a){return}if(!a.match("LI")){a=a.up();if(!a){return}}a.addClassName("on");a.ancestors().find(function(c){if(c.hasClassName("subfolders")){this._toggleSubFolder(c.id.substring(3),"exp")}else{return(c.id=="foldersSidebar")}},this)},iframeContent:function(b,d){if(b===null){b=d}var a=$("dimpmain_portal"),c;if(!a){DimpCore.showNotifications([{type:"horde.error",message:"Bad portal!"}]);return}c=new Element("IFRAME",{id:"iframe"+b,className:"iframe",frameBorder:0,src:d});this._resizeIE6Iframe(c);if(b=="options"){c.observe("load",function(){$("iframeoptions").contentWindow.document.getElementById("menu").style.display="none"})}a.insert(c)},msgWindow:function(b){this.updateUnseenUID(b,0);var a=DIMP.conf.message_url;a+=(a.include("?")?"&":"?")+$H({folder:b.view,uid:b.imapuid}).toQueryString();DimpCore.popupWindow(a,"msgview"+b.view+b.imapuid)},composeMailbox:function(a){var b=this.viewport.getSelected();if(!b.size()){return}b.get("dataob").ea
ch(function(c){DimpCore.compose(a,{folder:c.view,uid:c.imapuid})})},loadFolder:function(b,a){if(!this.viewport){this._createViewPort()}if(!a){this.resetSelected();if(this.folder==b){this.searchfilterClear(false);return}this.searchfilterClear(true);$("folderName").update(DIMP.text.loading);$("msgHeader").update();this.folderswitch=true;this.folder=b}this.viewport.loadView(b,{folder:b},this.uid?{imapuid:DimpCore.toUIDString(this.uid,b)}:null,a)},_createViewPort:function(){var b=$("msgList_filter"),a=this.setMessageListTitle.bind(this);this.viewport=new ViewPort({content_container:"msgList",empty_container:"msgList_empty",error_container:"msgList_error",fetch_action:"ListMessages",template:this.message_list_template,buffer_pages:DIMP.conf.buffer_pages,limit_factor:DIMP.conf.limit_factor,viewport_wait:DIMP.conf.viewport_wait,show_split_pane:this.showPreview,split_pane:"previewPane",splitbar:"splitBar",content_class:"msglist",row_class:"msgRow",selected_class:"selectedRow",ajaxRe
quest:DimpCore.doAction.bind(DimpCore),norows:true,onScrollI!
dle:a,on
Slide:a,onViewChange:function(){DimpCore.addGC(this.viewport.visibleRows())}.bind(this),onContent:function(f){var e,d,c=((this.viewport.getMetaData("sortby")==DIMP.conf.sortthread)&&this.viewport.getMetaData("thread"));if(this.viewport.isFiltering()){d=this.sfilters.get(this._getSearchfilterField()).capitalize();e=new RegExp("("+$F("msgList_filter")+")","i")}f.get("dataob").each(function(k){var h,i,g,j=$(k.domid);if(c&&c[k.imapuid]){h=j.down(".msgSubject");i=h.cloneNode(false);g=c[k.imapuid];$R(0,g.length,true).each(function(l){i.insert($($("thread_img_"+g.charAt(l)).cloneNode(false)).writeAttribute("id",""))});h.replace(i.insert(h.getText().escapeHTML()))}if(k.atc){j.down(".msgSize").insert({top:$($("atc_img_"+k.atc).cloneNode(false)).writeAttribute("id","")})}DimpCore.addMouseEvents({id:k.domid,type:k.menutype});if(d=="From"||d=="Subject"){h=j.down(".msg"+d);h.update(h.getText().escapeHTML().gsub(e,'<span class="searchMatch">#{1}</span>'))}},this);this.setMessageListTitle()
}.bind(this),onComplete:function(){var e,c,d=this.viewport.getMetaData("label");if(this.uid){e=this.viewport.getViewportSelection().search({imapuid:{equal:[this.uid]},view:{equal:[this.folder]}});if(e.size()){this.viewport.scrollTo(e.get("rownum").first());this.viewport.select(e)}}else{if(this.offset){this.viewport.select(this.viewport.createSelection("rownum",this.offset))}}this.offset=this.uid=null;d=this.viewport.getMetaData("label");if(d){$("folderName").update(d)}if(this.folderswitch){this.folderswitch=false;if(this.folder==DIMP.conf.spam_folder){if(!DIMP.conf.spam_spamfolder&&DimpCore.buttons.indexOf("button_spam")!=-1){[$("button_spam").up(),$("ctx_message_spam")].invoke("hide")}if(DimpCore.buttons.indexOf("button_ham")!=-1){[$("button_ham").up(),$("ctx_message_ham")].invoke("show")}}else{if(DimpCore.buttons.indexOf("button_spam")!=-1){[$("button_spam").up(),$("ctx_message_spam")].invoke("show")}if(DimpCore.buttons.indexOf("button_ham")!=-1){if(DIMP.conf.ham_spamfolde
r){[$("button_ham").up(),$("ctx_message_ham")].invoke("hide"!
)}else{[
$("button_ham").up(),$("ctx_message_ham")].invoke("show")}}}}else{if(this.filtertoggle){if(this.filtertoggle==1&&this.viewport.getMetaData("sortby")==DIMP.conf.sortthread){c=DIMP.conf.sortdate}this.filtertoggle=0}}this.setSortColumns(c);if(this.viewport.isFiltering()){this.resetSelected();this.updateTitle()}else{this.setFolderLabel(this.folder,this.viewport.getMetaData("unseen"))}}.bind(this),onFetch:this.msgListLoading.bind(this,true),onEndFetch:this.msgListLoading.bind(this,false),onWait:function(){if($("dimpmain_folder").visible()){DimpCore.showNotifications([{type:"horde.warning",message:DIMP.text.listmsg_wait}])}},onFail:function(){if($("dimpmain_folder").visible()){DimpCore.showNotifications([{type:"horde.error",message:DIMP.text.listmsg_timeout}])}this.msgListLoading(false)}.bind(this),onFirstContent:function(){this.clearPreviewPane();$("msgList").observe("dblclick",this._handleMsgListDblclick.bindAsEventListener(this))}.bind(this),onClearRows:function(c){c.each(functi
on(d){var e=$(d).down("div.msCheck");if(e){DimpCore.addGC(e)}if(d.id){DimpCore.removeMouseEvents(d)}})},onBeforeResize:function(){var c=this.viewport.getSelected();this.isvisible=(c.size()==1)&&(this.viewport.isVisible(c.get("rownum").first())==0)}.bind(this),onAfterResize:function(){if(this.isvisible){this.viewport.scrollTo(this.viewport.getSelected().get("rownum").first())}}.bind(this),selectCallback:this._select.bind(this),deselectCallback:this._deselect.bind(this)});if(!this.showPreview){$("msgList").addClassName("msglistNoPreview")}this.viewport.addFilter("ListMessages",this._addSearchfilterParams.bind(this));b.observe("keyup",this._searchfilterOnKeyup.bind(this));b.observe("focus",this._searchfilterOnFocus.bind(this));b.observe("blur",this._searchfilterOnBlur.bind(this));b.addClassName("msgFilterDefault")},_addMouseEvents:function(b,c){var a;switch(c.type){case"draft":case"message":new Drag(c.id,this._msgDragConfig);a=$(c.id).down("div.msCheck");if(a.visible()){a.obser
ve("mousedown",this.bcache.get("handleMLC")||this.bcache.set!
("handle
MLC",this._handleMsgListCheckbox.bindAsEventListener(this)));a.observe("contextmenu",Event.stop)}break;case"container":case"folder":new Drag(c.id,this._folderDragConfig);break;case"special":c.type="folder";break}c.onShow=this.bcache.get("onMS")||this.bcache.set("onMS",this._onMenuShow.bind(this));b(c)},_removeMouseEvents:function(b,a){var c,e=$(a).readAttribute("id");if(e&&(c=DragDrop.Drags.get_drag(e))){c.destroy()}b(a)},_onMenuShow:function(a){var e,c,b,d;switch(a.ctx){case"ctx_folder":e=$("ctx_folder_create","ctx_folder_rename","ctx_folder_delete");c=DimpCore.DMenu.element();if(c.readAttribute("mbox")=="INBOX"){e.invoke("hide")}else{if(DIMP.conf.fixed_folders.indexOf(c.readAttribute("mbox"))!=-1){e.shift();e.invoke("hide")}else{e.invoke("show")}}if(c.hasAttribute("u")){$("ctx_folder_poll").hide();$("ctx_folder_nopoll").show()}else{$("ctx_folder_poll").show();$("ctx_folder_nopoll").hide()}break;case"ctx_message":[$("ctx_message_reply_list")].invoke(this.viewport.createSelec
tion("domid",a.id).get("dataob").first().listmsg?"show":"hide");break;case"ctx_reply":d=this.viewport.getSelected();if(d.size()==1){b=d.get("dataob").first()}[$("ctx_reply_reply_list")].invoke(b&&b.listmsg?"show":"hide");break;case"ctx_otheractions":$("oa_seen","oa_unseen","oa_flagged","oa_clear","oa_sep1","oa_blacklist","oa_whitelist","oa_sep2","oa_undelete").compact().invoke(this.viewport.getSelected().size()?"show":"hide");break}return true},_onResize:function(){if(this.viewport){this.viewport.onResize()}this._resizeIE6()},_handleMsgListDblclick:function(b){var a=this._getMsgRow(b);if(!a){return}var c=this.viewport.createSelection("domid",a.id).get("dataob").first();c.draft?DimpCore.compose("resume",{folder:c.view,uid:c.imapuid}):this.msgWindow(c);b.stop()},_handleMsgListCheckbox:function(b){var a=this._getMsgRow(b);if(!a){return}this.msgSelect(a.readAttribute("id"),{ctrl:true,right:true});b.stop()},_getMsgRow:function(a){a=a.element();if(a&&!a.hasClassName("msgRow")){a=a
.up(".msgRow")}return a},updateTitle:function(){var b,a,c;if!
(this.vi
ewport.isFiltering()){a=DIMP.text.search+" :: "+this.viewport.getMetaData("total_rows")+" "+DIMP.text.resfound}else{b=$(this.getFolderId(this.folder));if(b){c=b.readAttribute("u");a=b.readAttribute("l");if(c>0){a+=" ("+c+")"}}else{a=this.viewport.getMetaData("label")}}DimpCore.setTitle(a)},sort:function(d){if(this.viewport.getMetaData("sortlimit")){return}var b,c,a=d.element();if(!a.hasAttribute("sortby")){a=a.up("[sortby]");if(!a){return}}c=parseInt(a.readAttribute("sortby"),10);if(c==this.viewport.getMetaData("sortby")){b={sortdir:(this.viewport.getMetaData("sortdir")?0:1)};this.viewport.setMetaData({sortdir:b.sortdir})}else{b={sortby:c};this.viewport.setMetaData({sortby:b.sortby})}this.setSortColumns(c);this.viewport.reload(b)},setSortColumns:function(c){var b,a=$("msglistHeader");if(Object.isUndefined(c)){c=this.viewport.getMetaData("sortby")}b=a.down("small[sortby="+c+"]");if(b&&b.up().visible()){b.up(1).childElements().invoke("toggle")}b=a.down("div.msgFrom a");if((this
.viewport.isFiltering()&&this.fspecial)||this.viewport.getMetaData("special")){b.hide().next().show()}else{b.show().next().hide()}b=a.down("div.msgSubject a");if(this.viewport.isFiltering()||this.viewport.getMetaData("nothread")||this.viewport.getMetaData("sortlimit")){b.show().next().hide();b.down().hide()}else{b.down().show()}a.childElements().invoke("removeClassName","sortup").invoke("removeClassName","sortdown");a.down("div a[sortby="+c+"]").up().addClassName(this.viewport.getMetaData("sortdir")?"sortup":"sortdown")},togglePreviewPane:function(){this.showPreview=!this.showPreview;$("previewtoggle").setText(this.showPreview?DIMP.text.hide_preview:DIMP.text.show_preview);[$("msgList")].invoke(this.showPreview?"removeClassName":"addClassName","msglistNoPreview");DimpCore.doAction("SetPrefValue",{pref:"show_preview",value:this.showPreview?1:0});this.viewport.showSplitPane(this.showPreview);if(this.showPreview){this.initPreviewPane()}this.updateTitle()},_loadPreview:function(
c){var a=$("previewPane"),b;if(!a.visible()){return}if(this.!
pp&&this
.pp==c){return}this.pp=c;if(this.ppfifo.indexOf(c.vp_id)!=-1){return this._loadPreviewCallback(this.ppcache.get(c.vp_id))}b=a.positionedOffset();$("msgLoading").setStyle({position:"absolute",top:(b.top+10)+"px",left:(b.left+10)+"px"}).show();DimpCore.doAction("ShowPreview",{},DimpCore.toUIDArray(this.viewport.createSelection("dataob",c)),this.bcache.get("loadPC")||this.bcache.set("loadPC",this._loadPreviewCallback.bind(this)))},_loadPreviewCallback:function(resp){var row,search,tmp,tmp2,pm=$("previewMsg"),r=resp.response;if(!r.error){search=this.viewport.getViewportSelection(r.view).search({vp_id:{equal:[r.uid]}});if(search.size()){row=search.get("dataob").first();this.updateUnseenUID(row,0)}}if(this.pp&&this.pp.vp_id!=r.uid){return}if(r.error||this.viewport.getSelected().size()!=1){if(r.error){DimpCore.showNotifications([{type:r.errortype,message:r.error}])}this.clearPreviewPane();return}this._expirePPCache([r.uid]);this.ppcache.set(r.uid,resp);this.ppfifo.push(r.uid);DimpCo
re.removeAddressLinks(pm);DIMP.conf.msg_index=r.index;DIMP.conf.msg_folder=r.folder;DIMP.conf.msg_source_link=r.source_link;tmp=pm.select(".subject");tmp.invoke("update",r.subject);switch(r.priority){case"high":case"low":tmp.invoke("insert",{top:$($(r.priority+"_priority_img").cloneNode(false)).writeAttribute("id",false)});break}pm.select(".from").invoke("update",r.from);$("msgHeadersColl").select(".date").invoke("update",r.minidate);$("msgHeaderDate").select(".date").invoke("update",r.fulldate);["to","cc"].each(function(a){if(r[a]){pm.select("."+a).invoke("update",r[a])}[$("msgHeader"+a.capitalize())].invoke(r[a]?"show":"hide")});$("msgHeadersColl").select(".attachmentImage").invoke(r.atc_label?"show":"hide");if(r.atc_label){tmp=$("msgAtc").show().down(".label");tmp2=$("partlist");tmp2.hide().previous().update(r.atc_label+" "+r.atc_download);if(r.atc_list){$("partlist_col").show();$("partlist_exp").hide();tmp.down().hide().next().show();tmp2.update(r.atc_list)}else{tmp.down
().show().next().hide()}}else{$("msgAtc").hide()}$("msgBody"!
).down()
.update(r.msgtext);$("msgLoading","previewInfo").invoke("hide");$("previewPane").scrollTop=0;pm.show();if(r.js){eval(r.js.join(";"))}DimpCore.buildAddressLinks(pm);this._addHistory("msg:"+row.view+":"+row.imapuid)},initPreviewPane:function(){var a=this.viewport.getSelected();if(a.size()!=1){this.clearPreviewPane()}else{this._loadPreview(a.get("dataob").first())}},clearPreviewPane:function(){$("msgLoading","previewMsg").invoke("hide");$("previewInfo").show();this.pp=null},_expirePPCache:function(a){this.ppfifo=this.ppfifo.without(a);a.each(this.ppcache.unset.bind(this.ppcache));if(this.ppfifo.size()>20){this.ppcache.unset(this.ppfifo.shift())}},updateUnseenUID:function(b,e){var c,a,d=0;if(!b.bg){return false}a=b.bg.match(this.unseen_regex);if((e&&a)||(!e&&!a)){return false}c=this.viewport.createSelection("dataob",b);if(e){this.viewport.updateFlag(c,"unseen",true);++d}else{this.viewport.updateFlag(c,"unseen",false);--d}return this.updateUnseenStatus(b.view,d)},updateUnseenStatu
s:function(b,c){if(c==0){return false}var a=parseInt($(this.getFolderId(b)).readAttribute("u"))+c;this.viewport.setMetaData({unseen:a});this.setFolderLabel(b,a);return true},setMessageListTitle:function(){var b,a=this.viewport.getMetaData("total_rows");if(a>0){b=this.viewport.currentOffset();$("msgHeader").update(DIMP.text.messages+" "+(b+1)+" - "+(Math.min(b+this.viewport.getPageSize(),a))+" "+DIMP.text.of+" "+a)}else{$("msgHeader").update(DIMP.text.nomessages)}},setFolderLabel:function(b,c){var a,d=this.getFolderId(b);a=$(d);if(!a||!a.hasAttribute("u")){return}c=parseInt(c);a.writeAttribute("u",c);if(b=="INBOX"&&window.fluid){window.fluid.setDockBadge(c?c:"")}$(d+"_label").update((c>0)?new Element("STRONG").insert(a.readAttribute("l")).insert(" ").insert(new Element("SPAN",{className:"count",dir:"ltr"}).insert("("+c+")")):a.readAttribute("l"));if(this.folder==b){this.updateTitle()}},getFolderId:function(a){return"fld"+decodeURIComponent(a).replace(/_/g,"__").replace(/
\W/g,"_")},getSubFolderId:function(a){return"sub"+a},pollFol!
ders:fun
ction(){this.setPollFolders();var a={};if(this.folder&&$("dimpmain_folder").visible()){a=this.viewport.addRequestParams({})}$("button_checkmail").setText("["+DIMP.text.check+"]");DimpCore.doAction("PollFolders",a,[],this.bcache.get("pollFC")||this.bcache.set("pollFC",this._pollFoldersCallback.bind(this)))},_pollFoldersCallback:function(a){a=a.response;if(a.poll){$H(a.poll).each(function(b){this.setFolderLabel(b.key,b.value);if(this.viewport){this.viewport.setMetaData({unseen:b.value},b.key)}},this)}if(a.quota){$("quota").update(a.quota)}$("button_checkmail").setText(DIMP.text.getmail)},setPollFolders:function(){if(DIMP.conf.refresh_time){if(this.pollPE){this.pollPE.stop()}this.pollPE=new PeriodicalExecuter(this.pollFolders.bind(this),DIMP.conf.refresh_time)}},_portalCallback:function(b){if(b.response.linkTags){var a=$$("HEAD").first();b.response.linkTags.each(function(c){var d=new Element("LINK",{type:"text/css",rel:"stylesheet",href:c.href});if(c.media){d.media=c.media}a.ins
ert(d)})}$("dimpmain_portal").update(b.response.portal);$("dimpmain_portal").select("h1.header a").each(this.bcache.get("portalClkLink")||this.bcache.set("portalClkLink",function(c){c.observe("click",function(f,g){this.go("app:"+g.readAttribute("app"));f.stop()}.bindAsEventListener(this,c))}.bind(this)))},_searchfilterOnKeyup:function(){if(this.searchobserve){clearTimeout(this.searchobserve)}this.searchobserve=(this.bcache.get("searchfilterR")||this.bcache.set("searchfilterR",this.searchfilterRun.bind(this))).delay(0.5)},searchfilterRun:function(){if(!this.viewport.isFiltering()){this.filtertoggle=1;this.fspecial=this.viewport.getMetaData("special")}this.viewport.runFilter($F("msgList_filter"))},_searchfilterOnFocus:function(){var a=$("qoptions");if($("msgList_filter").hasClassName("msgFilterDefault")){this._setFilterText(false)}if(!a.visible()){$("sf_current").update(this.viewport.getMetaData("label"));this._setSearchfilterParams(this.viewport.getMetaData("special")?"to":"f
rom","msg");this._setSearchfilterParams("current","folder");!
a.show()
;this.viewport.onResize()}},_searchfilterOnBlur:function(){if(!$F("msgList_filter")){this._setFilterText(true)}},searchfilterClear:function(a){if(!$("qoptions").visible()){return}if(this.searchobserve){clearTimeout(this.searchobserve);this.searchobserve=null}this._setFilterText(true);$("qoptions").hide();this.filtertoggle=2;this.resetSelected();this.viewport.onResize(a);this.viewport.stopFilter(a)},_setFilterText:function(b){var a=$("msgList_filter");if(b){a.setValue(DIMP.text.search);a.addClassName("msgFilterDefault")}else{a.setValue("");a.removeClassName("msgFilterDefault")}},_setSearchfilterParams:function(d,a){var b=(a=="folder")?this.sfiltersfolder:this.sfilters;b.keys().each(function(c){$(c).writeAttribute("className",(d==b.get(c))?"qselected":"")})},updateSearchfilter:function(b,a){this._setSearchfilterParams(b,a);if($F("msgList_filter")){this.viewport.runFilter()}},_addSearchfilterParams:function(){var a=this.sfiltersfolder.keys().find(function(b){return $(b).hasClass
Name("qselected")});return{searchfolder:this.sfiltersfolder.get(a),searchmsg:this.sfilters.get(this._getSearchfilterField())}},_getSearchfilterField:function(){return this.sfilters.keys().find(function(a){return $(a).hasClassName("qselected")})},toggleButtons:function(){var a=(this.selectedCount()==0);DimpCore.buttons.each(function(c){var d=$(c);if(d){[d.up()].invoke(a?"addClassName":"removeClassName","disabled");DimpCore.DMenu.disable(c+"_img",true,a)}})},_folderDropHandler:function(c,d){var g,f,e,b=c.readAttribute("mbox"),a=c.readAttribute("ftype");if(d.hasClassName("folder")){g=(c==$("dropbase"));if(g||(a!="special"&&!this.isSubfolder(d,c))){DimpCore.doAction("RenameFolder",{old_name:d.readAttribute("mbox"),new_parent:g?"":b,new_name:d.readAttribute("l")},[],this.bcache.get("folderC")||this.bcache.set("folderC",this._folderCallback.bind(this)))}}else{if(a!="container"){f=this.viewport.getSelected();if(f.size()){e=f}else{if(d.readAttribute("mbox")!=b){e=this.viewport.creat
eSelection("domid",d.id)}}if(e.size()&&this.folder!=b){this.!
viewport
.updateFlag(e,"deletedmsg",true);DimpCore.doAction("MoveMessage",this.viewport.addRequestParams({tofld:b}),DimpCore.toUIDArray(e),this.bcache.get("deleteC")||this.bcache.set("deleteC",this._deleteCallback.bind(this)))}}}},_dragCaption:function(){var a=this.selectedCount();return a+" "+(a==1?DIMP.text.message:DIMP.text.messages)},_keydownHandler:function(f){if(!$("dimpmain_folder").visible()||f.findElement("FORM")||RedBox.overlayVisible()){return}var i,h,b,g,d,a=f.keyCode||f.charCode,c=this.viewport.getSelected();switch(a){case Event.KEY_DELETE:case Event.KEY_BACKSPACE:b=c.get("dataob");if(f.shiftKey){this.moveSelected((b.last().rownum==this.viewport.getMetaData("total_rows"))?(b.first().rownum-1):(b.last().rownum+1),true)}this.flag("deleted",b);f.stop();break;case Event.KEY_UP:case Event.KEY_DOWN:if(f.shiftKey&&this.lastrow!=-1){g=this.viewport.createSelection("rownum",this.lastrow+((a==Event.KEY_UP)?-1:1));if(g.size()){g=g.get("dataob").first();this.viewport.scrollTo(g.rownu
m);this.msgSelect(g.domid,{shift:true})}}else{this.moveSelected(a==Event.KEY_UP?-1:1)}f.stop();break;case Event.KEY_PAGEUP:case Event.KEY_PAGEDOWN:if(!f.ctrlKey&&!f.shiftKey&&!f.altKey&&!f.metaKey){h=this.viewport.getPageSize()-1;move=h*(a==Event.KEY_PAGEUP?-1:1);if(c.size()==1){i=this.viewport.currentOffset();d=c.get("rownum").first()-1;switch(a){case Event.KEY_PAGEUP:if(i!=d){move=i-d}break;case Event.KEY_PAGEDOWN:if((i+h)!=d){move=i+h-d}break}}this.moveSelected(move);f.stop()}break;case Event.KEY_HOME:case Event.KEY_END:this.moveSelected(a==Event.KEY_HOME?1:this.viewport.getMetaData("total_rows"),true);f.stop();break;case Event.KEY_RETURN:if(!f.element().match("input")){if(c.size()==1){this.msgWindow(c.get("dataob").first())}}f.stop();break;case 65:case 97:if(f.ctrlKey){this.selectAll();f.stop()}break}},renameFolder:function(a){if(Object.isUndefined(a)){return}a=$(a);var b=this._createFolderForm(function(c){this._folderAction(a,c,"rename");return false}.bindAsEventListene
r(this),DIMP.text.rename_prompt);b.down("input").setValue(a.!
readAttr
ibute("l"))},createBaseFolder:function(){this._createFolderForm(function(a){this._folderAction("",a,"create");return false}.bindAsEventListener(this),DIMP.text.create_prompt)},createSubFolder:function(a){if(Object.isUndefined(a)){return false}this._createFolderForm(function(b){this._folderAction($(a),b,"createsub");return false}.bindAsEventListener(this),DIMP.text.createsub_prompt)},_createFolderForm:function(a,b){var c=new Element("FORM",{action:"#",id:"RB_folder"}).insert(new Element("P").insert(b)).insert(new Element("INPUT",{type:"text",size:15})).insert(new Element("INPUT",{type:"button",className:"button",value:DIMP.text.ok}).observe("click",a)).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(d){if((d.keyCode||d.charCode)==Event.KEY_RETURN){d.stop();a(d)}});RedBox.overlay=true;RedBox.onDisplay=Form.focusFi
rstElement.curry(c);RedBox.showHtml(c);return c},_closeRedBox:function(){var a=RedBox.getWindowContents();DimpCore.addGC([a,a.descendants()].flatten());RedBox.close()},_folderAction:function(b,d,h){this._closeRedBox();var c,g,f,a=d.findElement("form");f=$F(a.down("input"));if(f){switch(h){case"rename":if(b.readAttribute("l")!=f){c="RenameFolder";g={old_name:b.readAttribute("mbox"),new_parent:b.up().hasClassName("folderlist")?"":b.up(1).previous().readAttribute("mbox"),new_name:f}}break;case"create":case"createsub":c="CreateFolder";g={folder:f};if(h=="createsub"){g.parent=b.readAttribute("mbox")}break}if(c){DimpCore.doAction(c,g,[],this.bcache.get("folderC")||this.bcache.set("folderC",this._folderCallback.bind(this)))}}},_folderCallback:function(a){a=a.response;a.d.each(this.deleteFolder.bind(this));a.c.each(this.changeFolder.bind(this));a.a.each(this.createFolder.bind(this))},_deleteCallback:function(b){this.msgListLoading(false);this._pollFoldersCallback(b);if(!b.response.u
ids||b.response.folder!=this.folder){return}var a=this.viewp!
ort.getV
iewportSelection().search({view:{equal:[b.response.folder]},imapuid:{equal:b.response.uids[b.response.folder]}});if(a.size()){if(b.response.remove){this.viewport.remove(a,{cacheid:b.response.cacheid,noupdate:b.response.viewport});this._expirePPCache(a.get("uid"))}else{this.viewport.updateFlag(a,"deletedmsg",true)}}},_emptyFolderCallback:function(a){if(a.response.mbox){if(this.folder==a.response.mbox){this.viewport.reload();this.clearPreviewPane()}this.setFolderLabel(a.response.mbox,0)}},_flagAllCallback:function(a){if(a.response.mbox){this.setFolderLabel(a.response.mbox,a.response.u)}},_folderLoadCallback:function(b){this._folderCallback(b);var d=$("specialfolders","normalfolders").compact(),c=$("normalfolders"),a=c.getStyle("max-height");d.invoke("observe","click",this._handleFolderMouseEvent.bindAsEventListener(this,"click"));d.invoke("observe","mouseover",this._handleFolderMouseEvent.bindAsEventListener(this,"over"));if(DIMP.conf.is_ie6){d.invoke("observe","mouseout",this.
_handleFolderMouseEvent.bindAsEventListener(this,"out"))}$("foldersLoading").hide();$("foldersSidebar").show();if(a!==null||(Prototype.Browser.IE&&Object.isUndefined(a)&&(c.getStyle("height")=="0px"))){this._sizeFolderlist();Event.observe(window,"resize",this._sizeFolderlist.bind(this))}if(b.response.quota){$("quota").update(b.response.quota)}},_handleFolderMouseEvent:function(f,d){var c,b=f.element(),a=b.up(".folder")||b.up(".custom");if(!a){return}c=a.readAttribute("ftype");switch(d){case"over":if(DIMP.conf.is_ie6){a.addClassName("over")}if(c&&!this.mo_sidebar.get(a.id)){DimpCore.addMouseEvents({id:a.id,type:c});this.mo_sidebar.set(a.id,1)}break;case"out":a.removeClassName("over");break;case"click":if(b.hasClassName("exp")||b.hasClassName("col")){this._toggleSubFolder(a.id,"tog")}else{switch(c){case"container":f.stop();break;case"folder":case"special":f.stop();return this.go("folder:"+a.readAttribute("mbox"));break}}break}},_toggleSubFolder:function(b,c){b=$(b);var a=$(thi
s.getSubFolderId(b.id));if(a&&(c=="tog"||(c=="exp"&&!a.visib!
le())||(
c=="col"&&a.visible()))){b.firstDescendant().writeAttribute({className:a.toggle().visible()?"col":"exp"})}if(b.descendantOf("specialfolders")){this._sizeFolderlist()}},createFolder:function(c){var b,f,i,g,h,e=this.getFolderId(c.m),a=decodeURIComponent(c.m),d=this.getSubFolderId(e),j=$(d);i=new Element("LI",{className:"folder",id:e,l:c.l,mbox:a,ftype:((c.co)?"container":((c.s)?"special":"folder"))});b=new Element("DIV",{className:c.cl||"base",id:e+"_div"});if(c.i){b.update(c.i)}if(c.ch){b.writeAttribute({className:"exp"}).observe("mouseover",this.bcache.get("mo_folder")||this.bcache.set("mo_folder",function(k){k=k.element();if(DragDrop.Drags.drag&&k.hasClassName("exp")){this._toggleSubFolder(k.up(),"exp")}}.bindAsEventListener(this)))}i.insert(b).insert(new Element("A",{id:e+"_label",title:c.l}).insert(c.l));if(j){if(j.insert({before:i}).visible()){b.removeClassName("exp").addClassName("col")}}else{if(c.s){h=$("specialfolders")}else{h=$(this.getSubFolderId(this.getFolderId(c.p
a)));h=(h)?h.down("UL"):$("normalfolders")}g=a.toLowerCase();f=h.childElements().find(function(k){var l=k.readAttribute("mbox");return l&&(!c.s||l!="INBOX")&&(g<l.toLowerCase())});if(f){f.insert({before:i})}else{h.insert(i)}if(c.ch){i.insert({after:new Element("LI",{className:"subfolders",id:d}).insert(new Element("UL")).hide()})}}new Drop(i,this._folderDropConfig);if(c.po){i.writeAttribute("u","");this.setFolderLabel(a,c.u)}},deleteFolder:function(a){var b=decodeURIComponent(a),c;if(this.folder==b){this.go("folder:INBOX")}c=this.getFolderId(a);this.deleteFolderElt(c,true)},changeFolder:function(b){var d=this.getFolderId(b.m),a=$(d+"_div"),c=a&&a.hasClassName("col");this.deleteFolderElt(d,!b.ch);if(b.co&&this.folder==b.m){this.go("folder:INBOX")}this.createFolder(b);if(b.ch&&c){a.removeClassName("exp").addClassName("col")}},deleteFolderElt:function(d,b){var c=$(d);DimpCore.addGC($(c,d+"_div",d+"_label"));if(b){var a=$(this.getSubFolderId(d));if(a){a.remove()}}[DragDrop.Drags
.get_drag(d),DragDrop.Drops.get_drop(d)].compact().invoke("d!
estroy")
;DimpCore.removeMouseEvents(c);this.mo_sidebar.unset(d,1);DimpCore.addGC(c);if(this.viewport){this.viewport.deleteView(d)}c.remove()},_sizeFolderlist:function(){var a=$("normalfolders");a.setStyle({height:(document.viewport.getHeight()-a.cumulativeOffset()[1]-10)+"px"})},flag:function(f,d,e){var c,b,h,g=[],a=1;if(d){if(Object.isUndefined(e)){h=this.viewport.createSelection("dataob",d)}else{h=this.viewport.getViewportSelection().search({imapuid:{equal:[d]},view:{equal:[e]}});if(!h.size()&&e!=this.folder){h=this.viewport.getViewportSelection(e).search({imapuid:{equal:[d]}})}}}else{h=this.viewport.getSelected()}switch(f){case"allUnseen":case"allSeen":DimpCore.doAction((f=="allUnseen")?"MarkFolderUnseen":"MarkFolderSeen",{folder:e},[],this.bcache.get("flagAC")||this.bcache.set("flagAC",this._flagAllCallback.bind(this)));if(e==this.folder){this.viewport.updateFlag(this.createSelection("rownum",$A($R(1,this.viewport.getMetaData("total_rows")))),"unseen",f=="allUnseen")}break;case"d
eleted":case"undeleted":case"spam":case"ham":case"blacklist":case"whitelist":if(!h.size()){break}if(f=="deleted"){h=h.search({isdel:{not:[true]}});if(!h.size()){break}h.set({isdel:true})}else{if(f=="undeleted"){h.set({isdel:false})}}b=this.viewport.addRequestParams({});if(f=="deleted"||f=="undeleted"){this.viewport.updateFlag(h,"deletedmsg",f=="deleted")}if(f=="undeleted"){DimpCore.doAction("UndeleteMessage",b,DimpCore.toUIDArray(h))}else{c={deleted:"DeleteMessage",spam:"ReportSpam",ham:"ReportHam",blacklist:"Blacklist",whitelist:"Whitelist"};DimpCore.doAction(c[f],b,DimpCore.toUIDArray(h),this.bcache.get("deleteC")||this.bcache.set("deleteC",this._deleteCallback.bind(this)),{asynchronous:!(d&&e)});if(f=="spam"||f=="ham"){this.msgListLoading(true)}}break;case"unseen":case"seen":if(!h.size()){break}b={folder:this.folder,messageFlag:"-seen"};if(f=="seen"){a=0;b.messageFlag="seen"}h.get("dataob").each(function(i){if(this.updateUnseenUID(i,a)){g.push(i)}},this);if(g.size()){Dimp
Core.doAction("MarkMessage",b,DimpCore.toUIDArray(this.viewp!
ort.crea
teSelection("dataob",g)))}break;case"flagged":case"clear":if(!h.size()){break}b={folder:this.folder,messageFlag:((f=="flagged")?"flagged":"-flagged")};this.viewport.updateFlag(h,"flagged",f=="flagged");DimpCore.doAction("MarkMessage",b,DimpCore.toUIDArray(h));break;case"answered":this.viewport.updateFlag(h,"answered",true);this.viewport.updateFlag(h,"flagged",false);break}},purgeDeleted:function(){DimpCore.doAction("PurgeDeleted",this.viewport.addRequestParams({}),[],this.bcache.get("deleteC")||this.bcache.set("deleteC",this._deleteCallback.bind(this)))},modifyPollFolder:function(a,b){DimpCore.doAction("ModifyPollFolder",{folder:a,add:(b)?1:0},[],this.bcache.get("modifyPFC")||this.bcache.set("modifyPFC",this._modifyPollFolderCallback.bind(this)))},_modifyPollFolderCallback:function(a){a=a.response;var b=a.folder,d,c={response:{poll:{}}};d=$(this.getFolderId(b));if(a.add){c.response.poll[b]=a.poll.u;d.writeAttribute("u",0)}else{c.response.poll[b]=0}this._pollFoldersCallback(c)
;if(!a.add){d.removeAttribute("u")}},msgListLoading:function(a){var b;if(this.fl_visible!=a){this.fl_visible=a;if(a){b=$("msgList").positionedOffset();$("folderLoading").setStyle({position:"absolute",top:(b.top+10)+"px",left:(b.left+10)+"px"});Effect.Appear("folderLoading",{duration:0.2});$(document.body).setStyle({cursor:"progress"})}else{Effect.Fade("folderLoading",{duration:0.2});$(document.body).setStyle({cursor:"default"})}}},isSubfolder:function(b,d){var a=$(this.getSubFolderId(b.readAttribute("id")));return a&&d.descendantOf(a)},_onLoad:function(){var b=DimpCore.clickObserveHandler,a;if(Horde.dhtmlHistory.initialize()){Horde.dhtmlHistory.addListener(this.go.bind(this))}this._setFilterText(true);if(!Horde.dhtmlHistory.getCurrentLocation()){if(DIMP.conf.login_view=="inbox"){this.go("folder:INBOX")}else{this.go("portal");if(DIMP.conf.background_inbox){this.loadFolder("INBOX",true)}}}DimpCore.addPopdown("button_reply","reply");DimpCore.DMenu.disable("button_reply_img",tru
e,true);DimpCore.addPopdown("button_forward","forward");Dimp!
Core.DMe
nu.disable("button_forward_img",true,true);DimpCore.addPopdown("button_other","otheractions");a=$("logo");if(a.visible()){b({d:a.down("a"),f:this.go.bind(this,"portal")})}a=$("dimpbarActions");b({d:a.down(".composelink"),f:DimpCore.compose.bind(DimpCore,"new")});b({d:a.down(".refreshlink"),f:this.pollFolders.bind(this)});a=$("serviceActions");["portal","options"].each(function(c){var e=$("app"+c);if(e){b({d:e,f:this.go.bind(this,c)})}},this);a=$("applogout");if(a){b({d:a,f:DimpCore.logout.bind(DimpCore)})}a=$("applicationfolders");if(a){a.select("ul li.custom a").each(function(c){b({d:c,f:this.go.bind(this,"app:"+c.readAttribute("app"))})},this)}b({d:$("newfolder"),f:this.createBaseFolder.bind(this)});new Drop("dropbase",this._folderDropConfig);a=$("hometab");if(a){b({d:a,f:this.go.bind(this,"portal")})}$("tabbar").select("a.applicationtab").each(function(c){b({d:c,f:this.go.bind(this,"app:"+c.readAttribute("app"))})},this);b({d:$("button_reply"),f:this.composeMailbox.bind(th
is,"reply"),ns:true});b({d:$("button_forward"),f:this.composeMailbox.bind(this,DIMP.conf.forward_default),ns:true});["spam","ham","deleted"].each(function(c){var e=$("button_"+c);if(e){b({d:e,f:this.flag.bind(this,c)})}},this);b({d:$("button_compose"),f:DimpCore.compose.bind(DimpCore,"new")});b({d:$("button_other"),f:function(c){DimpCore.DMenu.trigger(c.findElement("A").next(),true)},p:true});b({d:$("qoptions").down(".qclose a"),f:this.searchfilterClear.bind(this,false)});["all","current"].each(function(c){var e=$("sf_"+c);if(e){b({d:e,f:this.updateSearchfilter.bind(this,c,"folder")})}},this);["msgall","from","to","subject"].each(function(c){b({d:$("sf_"+c),f:this.updateSearchfilter.bind(this,c,"msg")})},this);b({d:$("msglistHeader"),f:this.sort.bind(this),p:true});b({d:$("ctx_folder_create"),f:function(){this.createSubFolder(DimpCore.DMenu.element())}.bind(this),ns:true});b({d:$("ctx_folder_rename"),f:function(){this.renameFolder(DimpCore.DMenu.element())}.bind(this),ns:tru
e});b({d:$("ctx_folder_empty"),f:function(){if(window.confir!
m(DIMP.t
ext.empty_folder)){DimpCore.doAction("EmptyFolder",{folder:DimpCore.DMenu.element().readAttribute("mbox")},[],this._emptyFolderCallback.bind(this))}}.bind(this),ns:true});b({d:$("ctx_folder_delete"),f:function(){if(window.confirm(DIMP.text.delete_folder)){DimpCore.doAction("DeleteFolder",{folder:DimpCore.DMenu.element().readAttribute("mbox")},[],this.bcache.get("folderC")||this.bcache.set("folderC",this._folderCallback.bind(this)))}}.bind(this),ns:true});["ctx_folder_seen","ctx_folder_unseen"].each(function(c){b({d:$(c),f:function(d){this.flag(d,null,DimpCore.DMenu.element().readAttribute("mbox"))}.bind(this,c=="ctx_folder_seen"?"allSeen":"allUnseen"),ns:true})},this);["ctx_folder_poll","ctx_folder_nopoll"].each(function(c){b({d:$(c),f:function(d){this.modifyPollFolder(DimpCore.DMenu.element().readAttribute("mbox"),d)}.bind(this,c=="ctx_folder_poll"),ns:true})},this);b({d:$("ctx_container_create"),f:function(){this.createSubFolder(DimpCore.DMenu.element())}.bind(this),ns:true
});b({d:$("ctx_container_rename"),f:function(){this.renameFolder(DimpCore.DMenu.element())}.bind(this),ns:true});["reply","reply_all","reply_list","forward_all","forward_body","forward_attachments"].each(function(c){b({d:$("ctx_message_"+c),f:this.composeMailbox.bind(this,c),ns:true})},this);["seen","unseen","flagged","clear","spam","ham","blacklist","whitelist","deleted","undeleted"].each(function(c){var e=$("ctx_message_"+c);if(e){b({d:e,f:this.flag.bind(this,c),ns:true})}},this);b({d:$("ctx_draft_resume"),f:this.composeMailbox.bind(this,"resume")});["flagged","clear","deleted","undeleted"].each(function(c){var e=$("ctx_draft_"+c);if(e){b({d:e,f:this.flag.bind(this,c),ns:true})}},this);["reply","reply_all","reply_list"].each(function(c){b({d:$("ctx_reply_"+c),f:this.composeMailbox.bind(this,c),ns:true})},this);["forward_all","forward_body","forward_attachments"].each(function(c){b({d:$("ctx_forward_"+c),f:this.composeMailbox.bind(this,c),ns:true})},this);b({d:$("previewtog
gle"),f:this.togglePreviewPane.bind(this),ns:true});["seen",!
"unseen"
,"flagged","clear","blacklist","whitelist","undeleted"].each(function(c){var e=$("oa_"+c);if(e){b({d:e,f:this.flag.bind(this,c),ns:true})}},this);b({d:$("oa_selectall"),f:this.selectAll.bind(this),ns:true});a=$("oa_purge_deleted");if(a){b({d:a,f:this.purgeDeleted.bind(this),ns:true})}$("expandHeaders","collapseHeaders").each(function(c){b({d:c,f:function(){$("msgHeadersColl","msgHeaders").invoke("toggle")},ns:true})},this);$("msg_newwin","msg_newwin_options").compact().each(function(c){b({d:c,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()},_resizeIE6:function(){if(DIMP.conf.is_ie6){var a=parseInt($("sidebarPanel").getStyle("width"),10),b=document.viewport.getWidth()-a-30;$("normalfolders").setStyle({width:a+"px"});$("dimpmain").setStyle({width:b+"px"});$("msglist").setStyle({width:(b-5)+"px
"});$("msgBody").setStyle({width:(b-25)+"px"});a=$("dimpmain_portal").down("IFRAME");if(a){this._resizeIE6Iframe(a)}}},_resizeIE6Iframe:function(a){if(DIMP.conf.is_ie6){a.setStyle({width:$("dimpmain").getStyle("width"),height:(document.viewport.getHeight()-20)+"px"})}}};DimpBase._msgDragConfig={scroll:"normalfolders",threshold:5,caption:DimpBase._dragCaption.bind(DimpBase),onStart:function(c,b){var a={right:b.isRightClick()},f=c.element.id;c.selectIfNoDrag=false;if(!a.right&&(b.ctrlKey||b.metaKey)){this.msgSelect(f,$H({ctrl:true}).merge(a).toObject())}else{if(b.shiftKey){this.msgSelect(f,$H({shift:true}).merge(a).toObject())}else{if(this.isSelected("domid",f)){if(!a.right&&this.selectedCount()){c.selectIfNoDrag=true}}else{this.msgSelect(f,a)}}}}.bind(DimpBase),onEnd:function(b,a){if(b.selectIfNoDrag&&!b.wasDragged){this.msgSelect(b.element.id,{right:a.isRightClick()})}}.bind(DimpBase)};DimpBase._folderDragConfig={ghosting:true,offset:{x:5,y:5},scroll:"normalfolders",threshol
d:5,onDrag:function(b,a){if(!b.wasDragged){$("newfolder").hi!
de();$("
dropbase").show();b.ghost.removeClassName("on")}},onEnd:function(b,a){if(b.wasDragged){$("newfolder").show();$("dropbase").hide()}}};DimpBase._folderDropConfig={hoverclass:"dragdrop",caption:function(e,f){var g=f.readAttribute("l"),c=e.readAttribute("ftype"),b=e.readAttribute("l"),a=DIMP.text.moveto;if(e==$("dropbase")){return a.replace(/%s/,g).replace(/%s/,DIMP.text.baselevel)}else{if(f.hasClassName("folder")){return(c!="special"&&!this.isSubfolder(f,e))?a.replace(/%s/,g).replace(/%s/,b):""}else{return c!="container"?a.replace(/%s/,this._dragCaption()).replace(/%s/,b):""}}}.bind(DimpBase),onDrop:DimpBase._folderDropHandler.bind(DimpBase)};document.observe("dom:loaded",function(){$("dimpLoading").hide();$("dimpPage").show();DimpCore.doAction("ListFolders",{},[],DimpBase._folderLoadCallback.bind(DimpBase));if(!DimpBase.delay_onload){DimpBase._onLoad()}if(DIMP.conf.is_ie6){document.observe("selectstart",Event.stop)}if(!DIMP.conf.search_all){DimpBase.sfiltersfolder.unset("sf_all
")}DimpBase.setPollFolders();document.observe("keydown",DimpBase._keydownHandler.bind(DimpBase));Event.observe(window,"resize",DimpBase._onResize.bind(DimpBase));if(DIMP.conf.is_ie6){var a=[],b;if(b=$("dimpbarActions")){a.push(b.select("SPAN"))}if(b=$("serviceActions")){a.push(b.select("LI.servicelink"))}if(b=$("applicationfolders")){a.push(b.select("UL LI"))}a.flatten().compact().each(function(c){c.observe("mouseover",c.addClassName.curry("over")).observe("mouseout",c.removeClassName.curry("over"))})}});if(DimpBase.delay_onload){Event.observe(window,"load",DimpBase._onLoad.bind(DimpBase))}DimpCore.onDoActionComplete=function(a){if(DimpBase.viewport&&a.response.viewport){DimpBase.viewport.ajaxResponse(a.response.viewport)}};DimpCore.addMouseEvents=DimpCore.addMouseEvents.wrap(DimpBase._addMouseEvents.bind(DimpBase));DimpCore.removeMouseEvents=DimpCore.removeMouseEvents.wrap(DimpBase._removeMouseEvents.bind(DimpBase));
+\ No newline at end of file
++/**
++ * DimpBase.js - Javascript used in the base DIMP page.
++ *
++ * $Horde: dimp/js/src/DimpBase.js,v 1.1.2.118 2009-05-20 18:27:51 slusarz Exp $
++ *
++ * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
++ *
++ * See the enclosed file COPYING for license information (GPL). If you
++ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
++ */
++
++var DimpBase = {
++ // Vars used and defaulting to null/false:
++ // filtertoggle, fl_visible, folder, folderswitch, fspecial, isvisible,
++ // message_list_template, offset, pollpe, pp, searchobserve, uid,
++ // viewport
++ bcache: $H(),
++ delay_onload: (!Prototype.Browser.Gecko && !Prototype.Browser.Opera),
++ lastrow: -1,
++ mo_sidebar: $H(),
++ pivotrow: -1,
++ ppcache: $H(),
++ ppfifo: [],
++ showPreview: DIMP.conf.preview_pref,
++
++ sfiltersfolder: $H({ sf_all: 'all', sf_current: 'current' }),
++ sfilters: $H({ sf_msgall: 'msgall', sf_from: 'from', sf_to: 'to', sf_subject: 'subject' }),
++
++ unseen_regex: new RegExp("(^|\\s)unseen(\\s|$)"),
++
++ // Message selection functions
++
++ // vs = (ViewPort_Selection) A ViewPort_Selection object.
++ // opts = (object) Boolean options [delay, right]
++ _select: function(vs, opts)
++ {
++ var d = vs.get('rownum');
++ if (d.size() == 1) {
++ this.lastrow = this.pivotrow = d.first();
++ }
++
++ this.toggleButtons();
++
++ if ($('previewPane').visible()) {
++ if (opts.right) {
++ this.clearPreviewPane();
++ } else {
++ if (opts.delay) {
++ (this.bcache.get('initPP') || this.bcache.set('initPP', this.initPreviewPane.bind(this))).delay(opts.delay);
++ } else {
++ this.initPreviewPane();
++ }
++ }
++ }
++ },
++
++ // vs = (ViewPort_Selection) A ViewPort_Selection object.
++ // opts = (object) Boolean options [right]
++ _deselect: function(vs, opts)
++ {
++ var sel = this.viewport.getSelected(),
++ count = sel.size();
++ if (!count) {
++ this.lastrow = this.pivotrow = -1;
++ }
++
++ this.toggleButtons();
++ if (opts.right || !count) {
++ this.clearPreviewPane();
++ } else if ((count == 1) && $('previewPane').visible()) {
++ this._loadPreview(sel.get('dataob').first());
++ }
++ },
++
++ // id = (string) DOM ID
++ // opts = (Object) Boolean options [ctrl, right, shift]
++ msgSelect: function(id, opts)
++ {
++ var bounds,
++ row = this.viewport.createSelection('domid', id),
++ rownum = row.get('rownum').first(),
++ sel = this.isSelected('domid', id),
++ selcount = this.selectedCount();
++
++ this.lastrow = rownum;
++
++ // Some browsers need to stop the mousedown event before it propogates
++ // down to the browser level in order to prevent text selection on
++ // drag/drop actions. Clicking on a message should always lose focus
++ // from the search input, because the user may immediately start
++ // keyboard navigation after that. Thus, we need to ensure that a
++ // message click loses focus on the search input.
++ $('msgList_filter').blur();
++
++ if (opts.shift) {
++ if (selcount) {
++ if (!sel || selcount != 1) {
++ bounds = [ rownum, this.pivotrow ];
++ this.viewport.select($A($R(bounds.min(), bounds.max())), { range: true });
++ }
++ return;
++ }
++ } else if (opts.ctrl) {
++ this.pivotrow = rownum;
++ if (sel) {
++ this.viewport.deselect(row, { right: opts.right });
++ return;
++ } else if (opts.right || selcount) {
++ this.viewport.select(row, { add: true, right: opts.right });
++ return;
++ }
++ }
++
++ this.viewport.select(row, { right: opts.right });
++ },
++
++ selectAll: function()
++ {
++ this.viewport.select($A($R(1, this.viewport.getMetaData('total_rows'))), { range: true });
++ },
++
++ isSelected: function(format, data)
++ {
++ return this.viewport.getSelected().contains(format, data);
++ },
++
++ selectedCount: function()
++ {
++ return (this.viewport) ? this.viewport.getSelected().size() : 0;
++ },
++
++ resetSelected: function()
++ {
++ if (this.viewport) {
++ this.viewport.deselect(this.viewport.getSelected(), { clearall: true });
++ }
++ this.toggleButtons();
++ this.clearPreviewPane();
++ },
++
++ // absolute = Is num an absolute row number - from 1 -> page_size (true) -
++ // or a relative change from the current selected value (false)
++ // If no current selected value, the first message in the
++ // current viewport is selected.
++ moveSelected: function(num, absolute)
++ {
++ var curr, curr_row, row, row_data, sel;
++
++ if (absolute) {
++ if (!this.viewport.getMetaData('total_rows')) {
++ return;
++ }
++ curr = num;
++ } else {
++ if (num == 0) {
++ return;
++ }
++
++ sel = this.viewport.getSelected();
++ switch (sel.size()) {
++ case 0:
++ curr = this.viewport.currentOffset();
++ curr += (num > 0) ? 1 : this.viewport.getPageSize('current');
++ break;
++
++ case 1:
++ curr_row = sel.get('dataob').first();
++ curr = curr_row.rownum + num;
++ break;
++
++ default:
++ sel = sel.get('rownum');
++ curr = (num > 0 ? sel.max() : sel.min()) + num;
++ break;
++ }
++ curr = (num > 0) ? Math.min(curr, this.viewport.getMetaData('total_rows')) : Math.max(curr, 1);
++ }
++
++ row = this.viewport.createSelection('rownum', curr);
++ if (row.size()) {
++ row_data = row.get('dataob').first();
++ if (!curr_row || row_data.imapuid != curr_row.imapuid) {
++ this.viewport.scrollTo(row_data.rownum);
++ this.viewport.select(row, { delay: 0.3 });
++ }
++ } else {
++ this.offset = curr;
++ this.viewport.requestContentRefresh(curr - 1);
++ }
++ },
++ // End message selection functions
++
++ go: function(loc, data)
++ {
++ var app, f, separator;
++
++ if (loc.startsWith('compose:')) {
++ return;
++ }
++
++ if (loc.startsWith('msg:')) {
++ separator = loc.indexOf(':', 4);
++ f = loc.substring(4, separator);
++ this.uid = loc.substring(separator + 1);
++ loc = 'folder:' + f;
++ // Now fall through to the 'folder:' check below.
++ }
++
++ if (loc.startsWith('folder:')) {
++ f = loc.substring(7);
++ if (this.folder != f || !$('dimpmain_folder').visible()) {
++ this.highlightSidebar(this.getFolderId(f));
++ if (!$('dimpmain_folder').visible()) {
++ $('dimpmain_portal').hide();
++ $('dimpmain_folder').show();
++ }
++ // This catches the refresh case - no need to re-add to history
++ if (!Object.isUndefined(this.folder)) {
++ this._addHistory(loc);
++ }
++ }
++ this.loadFolder(f);
++ return;
++ }
++
++ this.folder = null;
++ $('dimpmain_folder').hide();
++ $('dimpmain_portal').update(DIMP.text.loading).show();
++
++ if (loc.startsWith('app:')) {
++ app = loc.substr(4);
++ if (app == 'imp' || app == 'dimp') {
++ this.go('folder:INBOX');
++ return;
++ }
++ this.highlightSidebar('app' + app);
++ this._addHistory(loc, data);
++ if (data) {
++ this.iframeContent(loc, data);
++ } else if (DIMP.conf.app_urls[app]) {
++ this.iframeContent(loc, DIMP.conf.app_urls[app]);
++ }
++ return;
++ }
++
++ switch (loc) {
++ case 'portal':
++ this.highlightSidebar('appportal');
++ this._addHistory(loc);
++ DimpCore.setTitle(DIMP.text.portal);
++ DimpCore.doAction('ShowPortal', {}, [], this.bcache.get('portalC') || this.bcache.set('portalC', this._portalCallback.bind(this)));
++ break;
++
++ case 'options':
++ this.highlightSidebar('appoptions');
++ this._addHistory(loc);
++ DimpCore.setTitle(DIMP.text.prefs);
++ this.iframeContent(loc, DIMP.conf.prefs_url);
++ break;
++ }
++ },
++
++ _addHistory: function(loc, data)
++ {
++ if (Horde.dhtmlHistory.getCurrentLocation() != loc) {
++ Horde.dhtmlHistory.add(loc, data);
++ }
++ },
++
++ highlightSidebar: function(id)
++ {
++ // Folder bar may not be fully loaded yet.
++ if ($('foldersLoading').visible()) {
++ this.highlightSidebar.bind(this, id).defer();
++ return;
++ }
++
++ $('sidebarPanel').select('.on').invoke('removeClassName', 'on');
++
++ var elt = $(id);
++ if (!elt) {
++ return;
++ }
++ if (!elt.match('LI')) {
++ elt = elt.up();
++ if (!elt) {
++ return;
++ }
++ }
++ elt.addClassName('on');
++
++ // Make sure all subfolders are expanded
++ elt.ancestors().find(function(n) {
++ if (n.hasClassName('subfolders')) {
++ this._toggleSubFolder(n.id.substring(3), 'exp');
++ } else {
++ return (n.id == 'foldersSidebar');
++ }
++ }, this);
++ },
++
++ iframeContent: function(name, loc)
++ {
++ if (name === null) {
++ name = loc;
++ }
++
++ var container = $('dimpmain_portal'), iframe;
++ if (!container) {
++ DimpCore.showNotifications([ { type: 'horde.error', message: 'Bad portal!' } ]);
++ return;
++ }
++
++ iframe = new Element('IFRAME', { id: 'iframe' + name, className: 'iframe', frameBorder: 0, src: loc });
++ this._resizeIE6Iframe(iframe);
++
++ // Hide menu in prefs pages.
++ if (name == 'options') {
++ iframe.observe('load', function() { $('iframeoptions').contentWindow.document.getElementById('menu').style.display = 'none'; });
++ }
++
++ container.insert(iframe);
++ },
++
++ // r = ViewPort row data
++ msgWindow: function(r)
++ {
++ this.updateUnseenUID(r, 0);
++ var url = DIMP.conf.message_url;
++ url += (url.include('?') ? '&' : '?') +
++ $H({ folder: r.view,
++ uid: r.imapuid }).toQueryString();
++ DimpCore.popupWindow(url, 'msgview' + r.view + r.imapuid);
++ },
++
++ composeMailbox: function(type)
++ {
++ var sel = this.viewport.getSelected();
++ if (!sel.size()) {
++ return;
++ }
++ sel.get('dataob').each(function(s) {
++ DimpCore.compose(type, { folder: s.view, uid: s.imapuid });
++ });
++ },
++
++ loadFolder: function(f, background)
++ {
++ if (!this.viewport) {
++ this._createViewPort();
++ }
++
++ if (!background) {
++ this.resetSelected();
++
++ if (this.folder == f) {
++ this.searchfilterClear(false);
++ return;
++ }
++
++ this.searchfilterClear(true);
++ $('folderName').update(DIMP.text.loading);
++ $('msgHeader').update();
++ this.folderswitch = true;
++ this.folder = f;
++ }
++
++ this.viewport.loadView(f, { folder: f }, this.uid ? { imapuid: DimpCore.toUIDString(this.uid, f) } : null, background);
++ },
++
++ _createViewPort: function()
++ {
++ var mf = $('msgList_filter'),
++ // No need to cache - this function only called once.
++ settitle = this.setMessageListTitle.bind(this);
++
++ this.viewport = new ViewPort({
++ content_container: 'msgList',
++ empty_container: 'msgList_empty',
++ error_container: 'msgList_error',
++ fetch_action: 'ListMessages',
++ template: this.message_list_template,
++ buffer_pages: DIMP.conf.buffer_pages,
++ limit_factor: DIMP.conf.limit_factor,
++ viewport_wait: DIMP.conf.viewport_wait,
++ show_split_pane: this.showPreview,
++ split_pane: 'previewPane',
++ splitbar: 'splitBar',
++ content_class: 'msglist',
++ row_class: 'msgRow',
++ selected_class: 'selectedRow',
++ ajaxRequest: DimpCore.doAction.bind(DimpCore),
++ norows: true,
++ onScrollIdle: settitle,
++ onSlide: settitle,
++ onViewChange: function() {
++ DimpCore.addGC(this.viewport.visibleRows());
++ }.bind(this),
++ onContent: function(rows) {
++ var mf, search,
++ thread = ((this.viewport.getMetaData('sortby') == DIMP.conf.sortthread) && this.viewport.getMetaData('thread'));
++ if (this.viewport.isFiltering()) {
++ search = this.sfilters.get(this._getSearchfilterField()).capitalize();
++ mf = new RegExp("(" + $F('msgList_filter') + ")", "i");
++ }
++ rows.get('dataob').each(function(row) {
++ var elt, tmp, u,
++ r = $(row.domid);
++ // Add thread graphics
++ if (thread && thread[row.imapuid]) {
++ elt = r.down('.msgSubject');
++ tmp = elt.cloneNode(false);
++ u = thread[row.imapuid];
++ $R(0, u.length, true).each(function(i) {
++ tmp.insert($($('thread_img_' + u.charAt(i)).cloneNode(false)).writeAttribute('id', ''));
++ });
++ elt.replace(tmp.insert(elt.getText().escapeHTML()));
++ }
++ // Add attachment graphics
++ if (row.atc) {
++ r.down('.msgSize').insert({ top: $($('atc_img_' + row.atc).cloneNode(false)).writeAttribute('id', '') });
++ }
++
++ // Add context menu.
++ DimpCore.addMouseEvents({ id: row.domid, type: row.menutype });
++
++ // Highlight search terms
++ if (search == 'From' || search == 'Subject') {
++ elt = r.down('.msg' + search);
++ elt.update(elt.getText().escapeHTML().gsub(mf, '<span class="searchMatch">#{1}</span>'));
++ }
++ }, this);
++ this.setMessageListTitle();
++ }.bind(this),
++ onComplete: function() {
++ var row, ssc,
++ l = this.viewport.getMetaData('label');
++
++ if (this.uid) {
++ row = this.viewport.getViewportSelection().search({ imapuid: { equal: [ this.uid ] }, view: { equal: [ this.folder ] } });
++ if (row.size()) {
++ this.viewport.scrollTo(row.get('rownum').first());
++ this.viewport.select(row);
++ }
++ } else if (this.offset) {
++ this.viewport.select(this.viewport.createSelection('rownum', this.offset));
++ }
++ this.offset = this.uid = null;
++
++ // 'label' will not be set if there has been an error
++ // retrieving data from the server.
++ l = this.viewport.getMetaData('label');
++ if (l) {
++ $('folderName').update(l);
++ }
++
++ if (this.folderswitch) {
++ this.folderswitch = false;
++ if (this.folder == DIMP.conf.spam_folder) {
++ if (!DIMP.conf.spam_spamfolder &&
++ DimpCore.buttons.indexOf('button_spam') != -1) {
++ [ $('button_spam').up(), $('ctx_message_spam') ].invoke('hide');
++ }
++ if (DimpCore.buttons.indexOf('button_ham') != -1) {
++ [ $('button_ham').up(), $('ctx_message_ham') ].invoke('show');
++ }
++ } else {
++ if (DimpCore.buttons.indexOf('button_spam') != -1) {
++ [ $('button_spam').up(), $('ctx_message_spam') ].invoke('show');
++ }
++ if (DimpCore.buttons.indexOf('button_ham') != -1) {
++ if (DIMP.conf.ham_spamfolder) {
++ [ $('button_ham').up(), $('ctx_message_ham') ].invoke('hide');
++ } else {
++ [ $('button_ham').up(), $('ctx_message_ham') ].invoke('show');
++ }
++ }
++ }
++ } else if (this.filtertoggle) {
++ if (this.filtertoggle == 1 &&
++ this.viewport.getMetaData('sortby') == DIMP.conf.sortthread) {
++ ssc = DIMP.conf.sortdate;
++ }
++ this.filtertoggle = 0;
++ }
++
++ this.setSortColumns(ssc);
++
++ if (this.viewport.isFiltering()) {
++ this.resetSelected();
++ this.updateTitle();
++ } else {
++ this.setFolderLabel(this.folder, this.viewport.getMetaData('unseen'));
++ }
++ }.bind(this),
++ onFetch: this.msgListLoading.bind(this, true),
++ onEndFetch: this.msgListLoading.bind(this, false),
++ onWait: function() {
++ if ($('dimpmain_folder').visible()) {
++ DimpCore.showNotifications([ { type: 'horde.warning', message: DIMP.text.listmsg_wait } ]);
++ }
++ },
++ onFail: function() {
++ if ($('dimpmain_folder').visible()) {
++ DimpCore.showNotifications([ { type: 'horde.error', message: DIMP.text.listmsg_timeout } ]);
++ }
++ this.msgListLoading(false);
++ }.bind(this),
++ onFirstContent: function() {
++ this.clearPreviewPane();
++ $('msgList').observe('dblclick', this._handleMsgListDblclick.bindAsEventListener(this));
++ }.bind(this),
++ onClearRows: function(r) {
++ r.each(function(row) {
++ var c = $(row).down('div.msCheck');
++ if (c) {
++ DimpCore.addGC(c);
++ }
++ if (row.id) {
++ DimpCore.removeMouseEvents(row);
++ }
++ });
++ },
++ onBeforeResize: function() {
++ var sel = this.viewport.getSelected();
++ this.isvisible = (sel.size() == 1) && (this.viewport.isVisible(sel.get('rownum').first()) == 0);
++ }.bind(this),
++ onAfterResize: function() {
++ if (this.isvisible) {
++ this.viewport.scrollTo(this.viewport.getSelected().get('rownum').first());
++ }
++ }.bind(this),
++ selectCallback: this._select.bind(this),
++ deselectCallback: this._deselect.bind(this)
++ });
++
++ // If starting in no preview mode, need to set the no preview class
++ if (!this.showPreview) {
++ $('msgList').addClassName('msglistNoPreview');
++ }
++
++ // 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');
++ },
++
++ _addMouseEvents: function(parentfunc, p)
++ {
++ var elt;
++
++ switch (p.type) {
++ case 'draft':
++ case 'message':
++ new Drag(p.id, this._msgDragConfig);
++ elt = $(p.id).down('div.msCheck');
++ if (elt.visible()) {
++ elt.observe('mousedown', this.bcache.get('handleMLC') || this.bcache.set('handleMLC', this._handleMsgListCheckbox.bindAsEventListener(this)));
++ elt.observe('contextmenu', Event.stop);
++ }
++ break;
++
++ case 'container':
++ case 'folder':
++ new Drag(p.id, this._folderDragConfig);
++ break;
++
++ case 'special':
++ // For purposes of the contextmenu, treat special folders
++ // like regular folders.
++ p.type = 'folder';
++ break;
++ }
++ p.onShow = this.bcache.get('onMS') || this.bcache.set('onMS', this._onMenuShow.bind(this));
++ parentfunc(p);
++ },
++
++ _removeMouseEvents: function(parentfunc, elt)
++ {
++ var d, id = $(elt).readAttribute('id');
++ if (id && (d = DragDrop.Drags.get_drag(id))) {
++ d.destroy();
++ }
++ parentfunc(elt);
++ },
++
++ _onMenuShow: function(ctx)
++ {
++ var elts, folder, ob, sel;
++
++ switch (ctx.ctx) {
++ case 'ctx_folder':
++ elts = $('ctx_folder_create', 'ctx_folder_rename', 'ctx_folder_delete');
++ folder = DimpCore.DMenu.element();
++ if (folder.readAttribute('mbox') == 'INBOX') {
++ elts.invoke('hide');
++ } else if (DIMP.conf.fixed_folders.indexOf(folder.readAttribute('mbox')) != -1) {
++ elts.shift();
++ elts.invoke('hide');
++ } else {
++ elts.invoke('show');
++ }
++
++ if (folder.hasAttribute('u')) {
++ $('ctx_folder_poll').hide();
++ $('ctx_folder_nopoll').show();
++ } else {
++ $('ctx_folder_poll').show();
++ $('ctx_folder_nopoll').hide();
++ }
++ break;
++
++ case 'ctx_message':
++ [ $('ctx_message_reply_list') ].invoke( this.viewport.createSelection('domid', ctx.id).get('dataob').first().listmsg ? 'show' : 'hide');
++ break;
++
++ case 'ctx_reply':
++ sel = this.viewport.getSelected();
++ if (sel.size() == 1) {
++ ob = sel.get('dataob').first();
++ }
++ [ $('ctx_reply_reply_list') ].invoke(ob && ob.listmsg ? 'show' : 'hide');
++ break;
++
++ case 'ctx_otheractions':
++ $('oa_seen', 'oa_unseen', 'oa_flagged', 'oa_clear', 'oa_sep1', 'oa_blacklist', 'oa_whitelist', 'oa_sep2', 'oa_undelete').compact().invoke(this.viewport.getSelected().size() ? 'show' : 'hide');
++ break;
++ }
++ return true;
++ },
++
++ _onResize: function()
++ {
++ if (this.viewport) {
++ this.viewport.onResize();
++ }
++ this._resizeIE6();
++ },
++
++ _handleMsgListDblclick: function(e)
++ {
++ var elt = this._getMsgRow(e);
++ if (!elt) {
++ return;
++ }
++ var 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)
++ {
++ var elt = this._getMsgRow(e);
++ if (!elt) {
++ return;
++ }
++ this.msgSelect(elt.readAttribute('id'), { ctrl: true, right: true });
++ e.stop();
++ },
++
++ _getMsgRow: function(e)
++ {
++ e = e.element();
++ if (e && !e.hasClassName('msgRow')) {
++ e = e.up('.msgRow');
++ }
++ return e;
++ },
++
++ updateTitle: function()
++ {
++ var elt, label, unseen;
++ if (this.viewport.isFiltering()) {
++ label = DIMP.text.search + ' :: ' + this.viewport.getMetaData('total_rows') + ' ' + DIMP.text.resfound;
++ } else {
++ elt = $(this.getFolderId(this.folder));
++ if (elt) {
++ unseen = elt.readAttribute('u');
++ label = elt.readAttribute('l');
++ if (unseen > 0) {
++ label += ' (' + unseen + ')';
++ }
++ } else {
++ label = this.viewport.getMetaData('label');
++ }
++ }
++ DimpCore.setTitle(label);
++ },
++
++ sort: function(e)
++ {
++ // Don't change sort if we are past the sortlimit
++ if (this.viewport.getMetaData('sortlimit')) {
++ return;
++ }
++
++ var s, sortby,
++ elt = e.element();
++ if (!elt.hasAttribute('sortby')) {
++ elt = elt.up('[sortby]');
++ if (!elt) {
++ return;
++ }
++ }
++ sortby = parseInt(elt.readAttribute('sortby'), 10);
++
++ if (sortby == this.viewport.getMetaData('sortby')) {
++ s = { sortdir: (this.viewport.getMetaData('sortdir') ? 0 : 1) };
++ this.viewport.setMetaData({ sortdir: s.sortdir });
++ } else {
++ s = { sortby: sortby };
++ this.viewport.setMetaData({ sortby: s.sortby });
++ }
++ this.setSortColumns(sortby);
++ this.viewport.reload(s);
++ },
++
++ setSortColumns: function(sortby)
++ {
++ var tmp,
++ m = $('msglistHeader');
++
++ if (Object.isUndefined(sortby)) {
++ sortby = this.viewport.getMetaData('sortby');
++ }
++
++ tmp = m.down('small[sortby=' + sortby + ']');
++ if (tmp && tmp.up().visible()) {
++ tmp.up(1).childElements().invoke('toggle');
++ }
++
++ tmp = m.down('div.msgFrom a');
++ if ((this.viewport.isFiltering() && this.fspecial) ||
++ this.viewport.getMetaData('special')) {
++ tmp.hide().next().show();
++ } else {
++ tmp.show().next().hide();
++ }
++
++ tmp = m.down('div.msgSubject a');
++ if (this.viewport.isFiltering() ||
++ this.viewport.getMetaData('nothread') ||
++ this.viewport.getMetaData('sortlimit')) {
++ tmp.show().next().hide();
++ tmp.down().hide();
++ } else {
++ tmp.down().show();
++ }
++
++ m.childElements().invoke('removeClassName', 'sortup').invoke('removeClassName', 'sortdown');
++ m.down('div a[sortby=' + sortby + ']').up().addClassName(this.viewport.getMetaData('sortdir') ? 'sortup' : 'sortdown');
++ },
++
++ // Preview pane functions
++ togglePreviewPane: function()
++ {
++ this.showPreview = !this.showPreview;
++ $('previewtoggle').setText(this.showPreview ? DIMP.text.hide_preview : DIMP.text.show_preview);
++ [ $('msgList') ].invoke(this.showPreview ? 'removeClassName' : 'addClassName', 'msglistNoPreview');
++ new Ajax.Request(DimpCore.addSID(DIMP.conf.URI_PREFS), { parameters: { app: 'dimp', pref: 'show_preview', value: this.showPreview ? 1 : 0 } });
++ this.viewport.showSplitPane(this.showPreview);
++ if (this.showPreview) {
++ this.initPreviewPane();
++ }
++ this.updateTitle();
++ },
++
++ _loadPreview: function(data)
++ {
++ var pp = $('previewPane'), pp_offset;
++ if (!pp.visible()) {
++ return;
++ }
++ if (this.pp &&
++ this.pp == data) {
++ return;
++ }
++ this.pp = data;
++
++ if (this.ppfifo.indexOf(data.vp_id) != -1) {
++ return this._loadPreviewCallback(this.ppcache.get(data.vp_id));
++ }
++
++ pp_offset = pp.positionedOffset();
++ $('msgLoading').setStyle({ position: 'absolute', top: (pp_offset.top + 10) + 'px', left: (pp_offset.left + 10) + 'px' }).show();
++
++ DimpCore.doAction('ShowPreview', {}, DimpCore.toUIDArray(this.viewport.createSelection('dataob', data)), this.bcache.get('loadPC') || this.bcache.set('loadPC', this._loadPreviewCallback.bind(this)));
++ },
++
++ _loadPreviewCallback: function(resp)
++ {
++ var row, search, tmp, tmp2,
++ pm = $('previewMsg'),
++ r = resp.response;
++
++ if (!r.error) {
++ search = this.viewport.getViewportSelection(r.view).search({ vp_id: { equal: [ r.uid ] } });
++ if (search.size()) {
++ row = search.get('dataob').first();
++ this.updateUnseenUID(row, 0);
++ }
++ }
++
++ if (this.pp &&
++ this.pp.vp_id != r.uid) {
++ return;
++ }
++
++ if (r.error || this.viewport.getSelected().size() != 1) {
++ if (r.error) {
++ DimpCore.showNotifications([ { type: r.errortype, message: r.error } ]);
++ }
++ this.clearPreviewPane();
++ return;
++ }
++
++ // Store in cache.
++ this._expirePPCache([ r.uid ]);
++ this.ppcache.set(r.uid, resp);
++ this.ppfifo.push(r.uid);
++
++ DimpCore.removeAddressLinks(pm);
++
++ DIMP.conf.msg_index = r.index;
++ DIMP.conf.msg_folder = r.folder;
++ DIMP.conf.msg_source_link = r.source_link;
++
++ // Add subject/priority
++ tmp = pm.select('.subject');
++ tmp.invoke('update', r.subject);
++ switch (r.priority) {
++ case 'high':
++ case 'low':
++ tmp.invoke('insert', { top: $($(r.priority + '_priority_img').cloneNode(false)).writeAttribute('id', false) });
++ break;
++ }
++
++ // Add from/date
++ pm.select('.from').invoke('update', r.from);
++ $('msgHeadersColl').select('.date').invoke('update', r.minidate);
++ $('msgHeaderDate').select('.date').invoke('update', r.fulldate);
++
++ // Add to/cc
++ [ 'to', 'cc' ].each(function(a) {
++ if (r[a]) {
++ pm.select('.' + a).invoke('update', r[a]);
++ }
++ [ $('msgHeader' + a.capitalize()) ].invoke(r[a] ? 'show' : 'hide');
++ });
++
++ // Add attachment information
++ $('msgHeadersColl').select('.attachmentImage').invoke(r.atc_label ? 'show' : 'hide');
++ if (r.atc_label) {
++ tmp = $('msgAtc').show().down('.label');
++ tmp2 = $('partlist');
++ tmp2.hide().previous().update(r.atc_label + ' ' + r.atc_download);
++ if (r.atc_list) {
++ $('partlist_col').show();
++ $('partlist_exp').hide();
++ tmp.down().hide().next().show();
++ tmp2.update(r.atc_list);
++ } else {
++ tmp.down().show().next().hide();
++ }
++ } else {
++ $('msgAtc').hide();
++ }
++
++ $('msgBody').down().update(r.msgtext);
++ $('msgLoading', 'previewInfo').invoke('hide');
++ $('previewPane').scrollTop = 0;
++ pm.show();
++
++ if (r.js) {
++ eval(r.js.join(';'));
++ }
++ DimpCore.buildAddressLinks(pm);
++ this._addHistory('msg:' + row.view + ':' + row.imapuid);
++ },
++
++ initPreviewPane: function()
++ {
++ var sel = this.viewport.getSelected();
++ if (sel.size() != 1) {
++ this.clearPreviewPane();
++ } else {
++ this._loadPreview(sel.get('dataob').first());
++ }
++ },
++
++ clearPreviewPane: function()
++ {
++ $('msgLoading', 'previewMsg').invoke('hide');
++ $('previewInfo').show();
++ this.pp = null;
++ },
++
++ _expirePPCache: function(ids)
++ {
++ this.ppfifo = this.ppfifo.without(ids);
++ ids.each(this.ppcache.unset.bind(this.ppcache));
++ // Preview pane cache size is 20 entries. Given that a reasonable guess
++ // of an average e-mail size is 10 KB (including headers), also make
++ // an estimate that the JSON data size will be approx. 10 KB. 200 KB
++ // should be a fairly safe caching value for any recent browser.
++ if (this.ppfifo.size() > 20) {
++ this.ppcache.unset(this.ppfifo.shift());
++ }
++ },
++
++ // Labeling functions
++ updateUnseenUID: function(r, setflag)
++ {
++ var sel, unseenset,
++ unseen = 0;
++ if (!r.bg) {
++ return false;
++ }
++ unseenset = r.bg.match(this.unseen_regex);
++ if ((setflag && unseenset) || (!setflag && !unseenset)) {
++ return false;
++ }
++
++ sel = this.viewport.createSelection('dataob', r);
++ if (setflag) {
++ this.viewport.updateFlag(sel, 'unseen', true);
++ ++unseen;
++ } else {
++ this.viewport.updateFlag(sel, 'unseen', false);
++ --unseen;
++ }
++
++ return this.updateUnseenStatus(r.view, unseen);
++ },
++
++ updateUnseenStatus: function(mbox, change)
++ {
++ if (change == 0) {
++ return false;
++ }
++ var unseen = parseInt($(this.getFolderId(mbox)).readAttribute('u')) + change;
++ this.viewport.setMetaData({ unseen: unseen });
++ this.setFolderLabel(mbox, unseen);
++ return true;
++ },
++
++ setMessageListTitle: function()
++ {
++ var offset,
++ rows = this.viewport.getMetaData('total_rows');
++ if (rows > 0) {
++ offset = this.viewport.currentOffset();
++ $('msgHeader').update(DIMP.text.messages + ' ' + (offset + 1) + ' - ' + (Math.min(offset + this.viewport.getPageSize(), rows)) + ' ' + DIMP.text.of + ' ' + rows);
++ } else {
++ $('msgHeader').update(DIMP.text.nomessages);
++ }
++ },
++
++ setFolderLabel: function(f, unseen)
++ {
++ var elt, fid = this.getFolderId(f);
++ elt = $(fid);
++ if (!elt || !elt.hasAttribute('u')) {
++ return;
++ }
++
++ unseen = parseInt(unseen);
++ elt.writeAttribute('u', unseen);
++
++ if (f == 'INBOX' && window.fluid) {
++ window.fluid.setDockBadge(unseen ? unseen : '');
++ }
++
++ $(fid + '_label').update((unseen > 0) ?
++ new Element('STRONG').insert(elt.readAttribute('l')).insert(' ').insert(new Element('SPAN', { className: 'count', dir: 'ltr' }).insert('(' + unseen + ')')) :
++ elt.readAttribute('l'));
++
++ if (this.folder == f) {
++ this.updateTitle();
++ }
++ },
++
++ getFolderId: function(f)
++ {
++ return 'fld' + decodeURIComponent(f).replace(/_/g,'__').replace(/\W/g, '_');
++ },
++
++ getSubFolderId: function(f)
++ {
++ return 'sub' + f;
++ },
++
++ /* Folder list updates. */
++ pollFolders: function()
++ {
++ // Reset poll folder counter.
++ this.setPollFolders();
++ var args = {};
++ if (this.folder && $('dimpmain_folder').visible()) {
++ args = this.viewport.addRequestParams({});
++ }
++ $('button_checkmail').setText('[' + DIMP.text.check + ']');
++ DimpCore.doAction('PollFolders', args, [], this.bcache.get('pollFC') || this.bcache.set('pollFC', this._pollFoldersCallback.bind(this)));
++ },
++
++ _pollFoldersCallback: function(r)
++ {
++ r = r.response;
++ if (r.poll) {
++ $H(r.poll).each(function(u) {
++ this.setFolderLabel(u.key, u.value);
++ if (this.viewport) {
++ this.viewport.setMetaData({ unseen: u.value }, u.key);
++ }
++ }, this);
++ }
++ if (r.quota) {
++ $('quota').update(r.quota);
++ }
++ $('button_checkmail').setText(DIMP.text.getmail);
++ },
++
++ setPollFolders: function()
++ {
++ if (DIMP.conf.refresh_time) {
++ if (this.pollPE) {
++ this.pollPE.stop();
++ }
++ // Don't cache - this code is only run once.
++ this.pollPE = new PeriodicalExecuter(this.pollFolders.bind(this), DIMP.conf.refresh_time);
++ }
++ },
++
++ _portalCallback: function(r)
++ {
++ if (r.response.linkTags) {
++ var head = $$('HEAD').first();
++ r.response.linkTags.each(function(newLink) {
++ var link = new Element('LINK', { type: 'text/css', rel: 'stylesheet', href: newLink.href });
++ if (newLink.media) {
++ link.media = newLink.media;
++ }
++ head.insert(link);
++ });
++ }
++ $('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);
++ }
++ this.searchobserve = (this.bcache.get('searchfilterR') || this.bcache.set('searchfilterR', this.searchfilterRun.bind(this))).delay(0.5);
++ },
++
++ searchfilterRun: function()
++ {
++ if (!this.viewport.isFiltering()) {
++ this.filtertoggle = 1;
++ this.fspecial = this.viewport.getMetaData('special');
++ }
++ this.viewport.runFilter($F('msgList_filter'));
++ },
++
++ _searchfilterOnFocus: function()
++ {
++ var q = $('qoptions');
++
++ if ($('msgList_filter').hasClassName('msgFilterDefault')) {
++ this._setFilterText(false);
++ }
++
++ if (!q.visible()) {
++ $('sf_current').update(this.viewport.getMetaData('label'));
++ this._setSearchfilterParams(this.viewport.getMetaData('special') ? 'to' : 'from', 'msg');
++ this._setSearchfilterParams('current', 'folder');
++ q.show();
++ this.viewport.onResize();
++ }
++ },
++
++ _searchfilterOnBlur: function()
++ {
++ if (!$F('msgList_filter')) {
++ this._setFilterText(true);
++ }
++ },
++
++ // reset = (boolean) TODO
++ searchfilterClear: function(reset)
++ {
++ if (!$('qoptions').visible()) {
++ return;
++ }
++ if (this.searchobserve) {
++ clearTimeout(this.searchobserve);
++ this.searchobserve = null;
++ }
++ this._setFilterText(true);
++ $('qoptions').hide();
++ this.filtertoggle = 2;
++ this.resetSelected();
++ this.viewport.onResize(reset);
++ this.viewport.stopFilter(reset);
++ },
++
++ // d = (boolean) Deactivate filter input?
++ _setFilterText: function(d)
++ {
++ var mf = $('msgList_filter');
++ if (d) {
++ mf.setValue(DIMP.text.search);
++ mf.addClassName('msgFilterDefault');
++ } else {
++ mf.setValue('');
++ mf.removeClassName('msgFilterDefault');
++ }
++ },
++
++ // type = 'folder' or 'msg'
++ _setSearchfilterParams: function(id, type)
++ {
++ var c = (type == 'folder') ? this.sfiltersfolder : this.sfilters;
++ c.keys().each(function(i) {
++ $(i).writeAttribute('className', (id == c.get(i)) ? 'qselected' : '');
++ });
++ },
++
++ updateSearchfilter: function(id, type)
++ {
++ this._setSearchfilterParams(id, type);
++ if ($F('msgList_filter')) {
++ this.viewport.runFilter();
++ }
++ },
++
++ _addSearchfilterParams: function()
++ {
++ var sf = this.sfiltersfolder.keys().find(function(s) {
++ return $(s).hasClassName('qselected');
++ });
++ return { searchfolder: this.sfiltersfolder.get(sf), searchmsg: this.sfilters.get(this._getSearchfilterField()) };
++ },
++
++ _getSearchfilterField: function()
++ {
++ return this.sfilters.keys().find(function(s) {
++ return $(s).hasClassName('qselected');
++ });
++ },
++
++ /* Enable/Disable DIMP action buttons as needed. */
++ toggleButtons: function()
++ {
++ var disable = (this.selectedCount() == 0);
++ DimpCore.buttons.each(function(b) {
++ var elt = $(b);
++ if (elt) {
++ [ elt.up() ].invoke(disable ? 'addClassName' : 'removeClassName', 'disabled');
++ DimpCore.DMenu.disable(b + '_img', true, disable);
++ }
++ });
++ },
++
++ /* Drag/Drop handler. */
++ _folderDropHandler: function(drop, drag)
++ {
++ var dropbase, sel, uids,
++ foldername = drop.readAttribute('mbox'),
++ ftype = drop.readAttribute('ftype');
++
++ if (drag.hasClassName('folder')) {
++ dropbase = (drop == $('dropbase'));
++ if (dropbase ||
++ (ftype != 'special' && !this.isSubfolder(drag, drop))) {
++ DimpCore.doAction('RenameFolder', { old_name: drag.readAttribute('mbox'), new_parent: dropbase ? '' : foldername, new_name: drag.readAttribute('l') }, [], this.bcache.get('folderC') || this.bcache.set('folderC', this._folderCallback.bind(this)));
++ }
++ } else if (ftype != 'container') {
++ sel = this.viewport.getSelected();
++
++ if (sel.size()) {
++ // Dragging multiple selected messages.
++ uids = sel;
++ } else if (drag.readAttribute('mbox') != foldername) {
++ // Dragging a single unselected message.
++ uids = this.viewport.createSelection('domid', drag.id);
++ }
++
++ // Don't allow drag/drop to the current folder.
++ if (uids.size() && this.folder != foldername) {
++ this.viewport.updateFlag(uids, 'deletedmsg', true);
++ DimpCore.doAction('MoveMessage', this.viewport.addRequestParams({ tofld: foldername }), DimpCore.toUIDArray(uids), this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)));
++ }
++ }
++ },
++
++ _dragCaption: function()
++ {
++ var cnt = this.selectedCount();
++ return cnt + ' ' + (cnt == 1 ? DIMP.text.message : DIMP.text.messages);
++ },
++
++ /* Keydown event handler */
++ _keydownHandler: function(e)
++ {
++ // Only catch keyboard shortcuts in message list view. Disable catching
++ // when in form elements or the RedBox overlay is visible.
++ if (!$('dimpmain_folder').visible() ||
++ e.findElement('FORM') ||
++ RedBox.overlayVisible()) {
++ return;
++ }
++
++ var co, ps, r, row, rowoff,
++ kc = e.keyCode || e.charCode,
++ sel = this.viewport.getSelected();
++
++ switch (kc) {
++ case Event.KEY_DELETE:
++ case Event.KEY_BACKSPACE:
++ r = sel.get('dataob');
++ if (e.shiftKey) {
++ this.moveSelected((r.last().rownum == this.viewport.getMetaData('total_rows')) ? (r.first().rownum - 1) : (r.last().rownum + 1), true);
++ }
++ this.flag('deleted', r);
++ e.stop();
++ break;
++
++ case Event.KEY_UP:
++ case Event.KEY_DOWN:
++ if (e.shiftKey && this.lastrow != -1) {
++ row = this.viewport.createSelection('rownum', this.lastrow + ((kc == Event.KEY_UP) ? -1 : 1));
++ if (row.size()) {
++ row = row.get('dataob').first();
++ this.viewport.scrollTo(row.rownum);
++ this.msgSelect(row.domid, { shift: true });
++ }
++ } else {
++ this.moveSelected(kc == Event.KEY_UP ? -1 : 1);
++ }
++ e.stop();
++ break;
++
++ case Event.KEY_PAGEUP:
++ case Event.KEY_PAGEDOWN:
++ if (!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey) {
++ ps = this.viewport.getPageSize() - 1;
++ move = ps * (kc == Event.KEY_PAGEUP ? -1 : 1);
++ if (sel.size() == 1) {
++ co = this.viewport.currentOffset();
++ rowoff = sel.get('rownum').first() - 1;
++ switch (kc) {
++ case Event.KEY_PAGEUP:
++ if (co != rowoff) {
++ move = co - rowoff;
++ }
++ break;
++
++ case Event.KEY_PAGEDOWN:
++ if ((co + ps) != rowoff) {
++ move = co + ps - rowoff;
++ }
++ break;
++ }
++ }
++ this.moveSelected(move);
++ e.stop();
++ }
++ break;
++
++ case Event.KEY_HOME:
++ case Event.KEY_END:
++ this.moveSelected(kc == Event.KEY_HOME ? 1 : this.viewport.getMetaData('total_rows'), true);
++ e.stop();
++ break;
++
++ case Event.KEY_RETURN:
++ if (!e.element().match('input')) {
++ // Popup message window if single message is selected.
++ if (sel.size() == 1) {
++ this.msgWindow(sel.get('dataob').first());
++ }
++ }
++ e.stop();
++ break;
++
++ case 65: // A
++ case 97: // a
++ if (e.ctrlKey) {
++ this.selectAll();
++ e.stop();
++ }
++ break;
++ }
++ },
++
++ /* Handle rename folder actions. */
++ renameFolder: function(folder)
++ {
++ if (Object.isUndefined(folder)) {
++ return;
++ }
++
++ folder = $(folder);
++ var n = this._createFolderForm(function(e) { this._folderAction(folder, e, 'rename'); return false; }.bindAsEventListener(this), DIMP.text.rename_prompt);
++ n.down('input').setValue(folder.readAttribute('l'));
++ },
++
++ /* Handle insert folder actions. */
++ createBaseFolder: function()
++ {
++ this._createFolderForm(function(e) { this._folderAction('', e, 'create'); return false; }.bindAsEventListener(this), DIMP.text.create_prompt);
++ },
++
++ createSubFolder: function(folder)
++ {
++ if (Object.isUndefined(folder)) {
++ return false;
++ }
++
++ this._createFolderForm(function(e) { this._folderAction($(folder), e, 'createsub'); return false; }.bindAsEventListener(this), DIMP.text.createsub_prompt);
++ },
++
++ _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); } });
++
++ RedBox.overlay = true;
++ RedBox.onDisplay = Form.focusFirstElement.curry(n);
++ RedBox.showHtml(n);
++ return n;
++ },
++
++ _closeRedBox: function()
++ {
++ var c = RedBox.getWindowContents();
++ DimpCore.addGC([ c, c.descendants() ].flatten());
++ RedBox.close();
++ },
++
++ _folderAction: function(folder, e, mode)
++ {
++ this._closeRedBox();
++
++ var action, params, val,
++ form = e.findElement('form');
++ val = $F(form.down('input'));
++
++ if (val) {
++ switch (mode) {
++ case 'rename':
++ if (folder.readAttribute('l') != val) {
++ action = 'RenameFolder';
++ params = { old_name: folder.readAttribute('mbox'),
++ new_parent: folder.up().hasClassName('folderlist') ? '' : folder.up(1).previous().readAttribute('mbox'),
++ new_name: val };
++ }
++ break;
++
++ case 'create':
++ case 'createsub':
++ action = 'CreateFolder';
++ params = { folder: val };
++ if (mode == 'createsub') {
++ params.parent = folder.readAttribute('mbox');
++ }
++ break;
++ }
++ if (action) {
++ DimpCore.doAction(action, params, [], this.bcache.get('folderC') || this.bcache.set('folderC', this._folderCallback.bind(this)));
++ }
++ }
++ },
++
++ /* Folder action callback functions. */
++ _folderCallback: function(r)
++ {
++ r = r.response;
++ r.d.each(this.deleteFolder.bind(this));
++ r.c.each(this.changeFolder.bind(this));
++ r.a.each(this.createFolder.bind(this));
++ },
++
++ _deleteCallback: function(r)
++ {
++ this.msgListLoading(false);
++ this._pollFoldersCallback(r);
++
++ if (!r.response.uids ||
++ r.response.folder != this.folder) {
++ return;
++ }
++
++ var search = this.viewport.getViewportSelection().search({ view: { equal: [ r.response.folder ] }, imapuid: { equal: r.response.uids[r.response.folder] } });
++ if (search.size()) {
++ if (r.response.remove) {
++ this.viewport.remove(search, { cacheid: r.response.cacheid, noupdate: r.response.viewport });
++ this._expirePPCache(search.get('uid'));
++ } else {
++ // Need this to catch spam deletions.
++ this.viewport.updateFlag(search, 'deletedmsg', true);
++ }
++ }
++ },
++
++ _emptyFolderCallback: function(r)
++ {
++ if (r.response.mbox) {
++ if (this.folder == r.response.mbox) {
++ this.viewport.reload();
++ this.clearPreviewPane();
++ }
++ this.setFolderLabel(r.response.mbox, 0);
++ }
++ },
++
++ _flagAllCallback: function(r)
++ {
++ if (r.response.mbox) {
++ this.setFolderLabel(r.response.mbox, r.response.u);
++ }
++ },
++
++ _folderLoadCallback: function(r)
++ {
++ this._folderCallback(r);
++
++ var elts = $('specialfolders', 'normalfolders').compact(),
++ 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'));
++ }
++
++ $('foldersLoading').hide();
++ $('foldersSidebar').show();
++
++ // Fix for IE6 - which doesn't support max-height. We need to search
++ // for height: 0px instead (comment in IE 6 CSS explains this is
++ // needed for auto sizing).
++ if (nfheight !== null ||
++ (Prototype.Browser.IE &&
++ Object.isUndefined(nfheight) &&
++ (nf.getStyle('height') == '0px'))) {
++ this._sizeFolderlist();
++ Event.observe(window, 'resize', this._sizeFolderlist.bind(this));
++ }
++
++ if (r.response.quota) {
++ $('quota').update(r.response.quota);
++ }
++ },
++
++ _handleFolderMouseEvent: function(e, action)
++ {
++ var type,
++ elt = e.element(),
++ li = elt.up('.folder') || elt.up('.custom');
++ if (!li) {
++ return;
++ }
++ type = li.readAttribute('ftype');
++
++ switch (action) {
++ case 'over':
++ if (DIMP.conf.is_ie6) {
++ li.addClassName('over');
++ }
++ if (type && !this.mo_sidebar.get(li.id)) {
++ DimpCore.addMouseEvents({ id: li.id, type: type });
++ this.mo_sidebar.set(li.id, 1);
++ }
++ break;
++
++ case 'out':
++ li.removeClassName('over');
++ break;
++
++ case 'click':
++ if (elt.hasClassName('exp') || elt.hasClassName('col')) {
++ this._toggleSubFolder(li.id, 'tog');
++ } else {
++ switch (type) {
++ case 'container':
++ e.stop();
++ break;
++
++ case 'folder':
++ case 'special':
++ e.stop();
++ return this.go('folder:' + li.readAttribute('mbox'));
++ break;
++ }
++ }
++ break;
++ }
++ },
++
++ _toggleSubFolder: function(base, mode)
++ {
++ base = $(base);
++ var s = $(this.getSubFolderId(base.id));
++ if (s &&
++ (mode == 'tog' ||
++ (mode == 'exp' && !s.visible()) ||
++ (mode == 'col' && s.visible()))) {
++ base.firstDescendant().writeAttribute({ className: s.toggle().visible() ? 'col' : 'exp' });
++ }
++ if (base.descendantOf('specialfolders')) {
++ this._sizeFolderlist();
++ }
++ },
++
++ // Folder actions.
++ // For format of the ob object, see DIMP::_createFolderElt().
++ createFolder: function(ob)
++ {
++ var div, f_node, li, ll, parent_e,
++ fid = this.getFolderId(ob.m),
++ mbox = decodeURIComponent(ob.m),
++ submboxid = this.getSubFolderId(fid),
++ submbox = $(submboxid);
++
++ li = new Element('LI', { className: 'folder', id: fid, l: ob.l, mbox: mbox, ftype: ((ob.co) ? 'container' : ((ob.s) ? 'special' : 'folder')) });
++
++ div = new Element('DIV', { className: ob.cl || 'base', id: fid + '_div' });
++ if (ob.i) {
++ div.setStyle({ backgroundImage: 'url("' + ob.i + '")' });
++ }
++ if (ob.ch) {
++ div.writeAttribute({ className: 'exp' }).observe('mouseover', this.bcache.get('mo_folder') || this.bcache.set('mo_folder', function(e) {
++ e = e.element();
++ if (DragDrop.Drags.drag && e.hasClassName('exp')) {
++ this._toggleSubFolder(e.up(), 'exp');
++ }
++ }.bindAsEventListener(this)));
++ }
++
++ li.insert(div).insert(new Element('A', { id: fid + '_label', title: ob.l }).insert(ob.l));
++
++ // Now walk through the parent <ul> to find the right place to
++ // insert the new folder.
++ if (submbox) {
++ if (submbox.insert({ before: li }).visible()) {
++ // If an expanded parent mailbox was deleted, we need to toggle
++ // the icon accordingly.
++ div.removeClassName('exp').addClassName('col');
++ }
++ } else {
++ if (ob.s) {
++ parent_e = $('specialfolders');
++ } else {
++ parent_e = $(this.getSubFolderId(this.getFolderId(ob.pa)));
++ parent_e = (parent_e) ? parent_e.down('UL') : $('normalfolders');
++ }
++
++ ll = mbox.toLowerCase();
++ f_node = parent_e.childElements().find(function(node) {
++ var nodembox = node.readAttribute('mbox');
++ return nodembox &&
++ (!ob.s || nodembox != 'INBOX') &&
++ (ll < nodembox.toLowerCase());
++ });
++
++ if (f_node) {
++ f_node.insert({ before: li });
++ } else {
++ parent_e.insert(li);
++ }
++
++ // Make sure the sub<mbox> ul is created if necessary.
++ if (ob.ch) {
++ li.insert({ after: new Element('LI', { className: 'subfolders', id: submboxid }).insert(new Element('UL')).hide() });
++ }
++ }
++
++ // Make the new folder a drop target.
++ new Drop(li, this._folderDropConfig);
++
++ // Check for unseen messages
++ if (ob.po) {
++ li.writeAttribute('u', '');
++ this.setFolderLabel(mbox, ob.u);
++ }
++ },
++
++ deleteFolder: function(folder)
++ {
++ var f = decodeURIComponent(folder), fid;
++ if (this.folder == f) {
++ this.go('folder:INBOX');
++ }
++
++ fid = this.getFolderId(folder);
++ this.deleteFolderElt(fid, true);
++ },
++
++ changeFolder: function(ob)
++ {
++ var fid = this.getFolderId(ob.m),
++ fdiv = $(fid + '_div'),
++ oldexpand = fdiv && fdiv.hasClassName('col');
++ this.deleteFolderElt(fid, !ob.ch);
++ if (ob.co && this.folder == ob.m) {
++ this.go('folder:INBOX');
++ }
++ this.createFolder(ob);
++ if (ob.ch && oldexpand) {
++ fdiv.removeClassName('exp').addClassName('col');
++ }
++ },
++
++ deleteFolderElt: function(fid, sub)
++ {
++ var f = $(fid);
++ DimpCore.addGC($(f, fid + '_div', fid + '_label'));
++ if (sub) {
++ var submbox = $(this.getSubFolderId(fid));
++ if (submbox) {
++ submbox.remove();
++ }
++ }
++ [ DragDrop.Drags.get_drag(fid), DragDrop.Drops.get_drop(fid) ].compact().invoke('destroy');
++ DimpCore.removeMouseEvents(f);
++ this.mo_sidebar.unset(fid, 1);
++ DimpCore.addGC(f);
++ if (this.viewport) {
++ this.viewport.deleteView(fid);
++ }
++ f.remove();
++ },
++
++ _sizeFolderlist: function()
++ {
++ var nf = $('normalfolders');
++ nf.setStyle({ height: (document.viewport.getHeight() - nf.cumulativeOffset()[1] - 10) + 'px' });
++ },
++
++ /* Flag actions for message list. */
++ flag: function(action, index, folder)
++ {
++ var actionCall, args, vs,
++ obs = [],
++ unseenstatus = 1;
++
++ if (index) {
++ if (Object.isUndefined(folder)) {
++ vs = this.viewport.createSelection('dataob', index);
++ } else {
++ vs = this.viewport.getViewportSelection().search({ imapuid: { equal: [ index ] }, view: { equal: [ folder ] } });
++ if (!vs.size() && folder != this.folder) {
++ vs = this.viewport.getViewportSelection(folder).search({ imapuid: { equal: [ index ] } });
++ }
++ }
++ } else {
++ vs = this.viewport.getSelected();
++ }
++
++ switch (action) {
++ case 'allUnseen':
++ case 'allSeen':
++ DimpCore.doAction((action == 'allUnseen') ? 'MarkFolderUnseen' : 'MarkFolderSeen', { folder: folder }, [], this.bcache.get('flagAC') || this.bcache.set('flagAC', this._flagAllCallback.bind(this)));
++ if (folder == this.folder) {
++ this.viewport.updateFlag(this.createSelection('rownum', $A($R(1, this.viewport.getMetaData('total_rows')))), 'unseen', action == 'allUnseen');
++ }
++ break;
++
++ case 'deleted':
++ case 'undeleted':
++ case 'spam':
++ case 'ham':
++ case 'blacklist':
++ case 'whitelist':
++ if (!vs.size()) {
++ break;
++ }
++
++ // Make sure that any given row is not deleted more than once.
++ // Need to explicitly mark here because message may already be
++ // flagged deleted when we load page (i.e. switching to using
++ // trash folder).
++ if (action == 'deleted') {
++ vs = vs.search({ isdel: { not: [ true ] } });
++ if (!vs.size()) {
++ break;
++ }
++ vs.set({ isdel: true });
++ } else if (action == 'undeleted') {
++ vs.set({ isdel: false });
++ }
++
++ args = this.viewport.addRequestParams({});
++ if (action == 'deleted' || action == 'undeleted') {
++ this.viewport.updateFlag(vs, 'deletedmsg', action == 'deleted'); }
++
++ if (action == 'undeleted') {
++ DimpCore.doAction('UndeleteMessage', args, DimpCore.toUIDArray(vs));
++ } else {
++ actionCall = { deleted: 'DeleteMessage', spam: 'ReportSpam', ham: 'ReportHam', blacklist: 'Blacklist', whitelist: 'Whitelist' };
++ // This needs to be synchronous Ajax if we are calling from a
++ // popup window because Mozilla will not correctly call the
++ // callback function if the calling window has been closed.
++ DimpCore.doAction(actionCall[action], args, DimpCore.toUIDArray(vs), this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)), { asynchronous: !(index && folder) });
++
++ // If reporting spam, to indicate to the user that something is
++ // happening (since spam reporting may not be instantaneous).
++ if (action == 'spam' || action == 'ham') {
++ this.msgListLoading(true);
++ }
++ }
++ break;
++
++ case 'unseen':
++ case 'seen':
++ if (!vs.size()) {
++ break;
++ }
++ args = { folder: this.folder, messageFlag: '-seen' };
++ if (action == 'seen') {
++ unseenstatus = 0;
++ args.messageFlag = 'seen';
++ }
++ vs.get('dataob').each(function(s) {
++ if (this.updateUnseenUID(s, unseenstatus)) {
++ obs.push(s);
++ }
++ }, this);
++
++ if (obs.size()) {
++ DimpCore.doAction('MarkMessage', args, DimpCore.toUIDArray(this.viewport.createSelection('dataob', obs)));
++ }
++ break;
++
++ case 'flagged':
++ case 'clear':
++ if (!vs.size()) {
++ break;
++ }
++ args = {
++ folder: this.folder,
++ messageFlag: ((action == 'flagged') ? 'flagged' : '-flagged')
++ };
++ this.viewport.updateFlag(vs, 'flagged', action == 'flagged');
++ DimpCore.doAction('MarkMessage', args, DimpCore.toUIDArray(vs));
++ break;
++
++ case 'answered':
++ this.viewport.updateFlag(vs, 'answered', true);
++ this.viewport.updateFlag(vs, 'flagged', false);
++ break;
++ }
++ },
++
++ /* Miscellaneous folder actions. */
++ purgeDeleted: function()
++ {
++ DimpCore.doAction('PurgeDeleted', this.viewport.addRequestParams({}), [], this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)));
++ },
++
++ modifyPollFolder: function(folder, add)
++ {
++ DimpCore.doAction('ModifyPollFolder', { folder: folder, add: (add) ? 1 : 0 }, [], this.bcache.get('modifyPFC') || this.bcache.set('modifyPFC', this._modifyPollFolderCallback.bind(this)));
++ },
++
++ _modifyPollFolderCallback: function(r)
++ {
++ r = r.response;
++ var f = r.folder, fid, p = { response: { poll: {} } };
++ fid = $(this.getFolderId(f));
++
++ if (r.add) {
++ p.response.poll[f] = r.poll.u;
++ fid.writeAttribute('u', 0);
++ } else {
++ p.response.poll[f] = 0;
++ }
++
++ this._pollFoldersCallback(p);
++
++ if (!r.add) {
++ fid.removeAttribute('u');
++ }
++ },
++
++ msgListLoading: function(show)
++ {
++ var ml_offset;
++
++ if (this.fl_visible != show) {
++ this.fl_visible = show;
++ if (show) {
++ ml_offset = $('msgList').positionedOffset();
++ $('folderLoading').setStyle({ position: 'absolute', top: (ml_offset.top + 10) + 'px', left: (ml_offset.left + 10) + 'px' });
++ Effect.Appear('folderLoading', { duration: 0.2 });
++ $(document.body).setStyle({ cursor: 'progress' });
++ } else {
++ Effect.Fade('folderLoading', { duration: 0.2 });
++ $(document.body).setStyle({ cursor: 'default' });
++ }
++ }
++ },
++
++ // p = (element) Parent element
++ // c = (element) Child element
++ isSubfolder: function(p, c)
++ {
++ var sf = $(this.getSubFolderId(p.readAttribute('id')));
++ return sf && c.descendantOf(sf);
++ },
++
++ /* Onload function. */
++ _onLoad: function() {
++ var C = DimpCore.clickObserveHandler, tmp;
++
++ if (Horde.dhtmlHistory.initialize()) {
++ Horde.dhtmlHistory.addListener(this.go.bind(this));
++ }
++
++ this._setFilterText(true);
++
++ /* Initialize the starting page if necessary. addListener() will have
++ * already fired if there is a current location so only do a go()
++ * call if there is no current location. */
++ if (!Horde.dhtmlHistory.getCurrentLocation()) {
++ if (DIMP.conf.login_view == 'inbox') {
++ this.go('folder:INBOX');
++ } else {
++ this.go('portal');
++ if (DIMP.conf.background_inbox) {
++ this.loadFolder('INBOX', true);
++ }
++ }
++ }
++
++ /* Add popdown menus. */
++ DimpCore.addPopdown('button_reply', 'reply');
++ DimpCore.DMenu.disable('button_reply_img', true, true);
++ DimpCore.addPopdown('button_forward', 'forward');
++ 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') });
++ }
++
++ tmp = $('dimpbarActions');
++ C({ d: tmp.down('.composelink'), f: DimpCore.compose.bind(DimpCore, 'new') });
++ C({ d: tmp.down('.refreshlink'), f: this.pollFolders.bind(this) });
++
++ tmp = $('serviceActions');
++ [ '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: DimpCore.logout.bind(DimpCore) });
++ }
++
++ tmp = $('applicationfolders');
++ if (tmp) {
++ tmp.select('ul 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'), f: DimpCore.compose.bind(DimpCore, 'new') });
++ C({ d: $('button_other'), f: function(e) { DimpCore.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(DimpCore.DMenu.element()); }.bind(this), ns: true });
++ C({ d: $('ctx_folder_rename'), f: function() { this.renameFolder(DimpCore.DMenu.element()); }.bind(this), ns: true });
++ C({ d: $('ctx_folder_empty'), f: function() { if (window.confirm(DIMP.text.empty_folder)) { DimpCore.doAction('EmptyFolder', { folder: DimpCore.DMenu.element().readAttribute('mbox') }, [], this._emptyFolderCallback.bind(this)); } }.bind(this), ns: true });
++ C({ d: $('ctx_folder_delete'), f: function() { if (window.confirm(DIMP.text.delete_folder)) { DimpCore.doAction('DeleteFolder', { folder: DimpCore.DMenu.element().readAttribute('mbox') }, [], 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, DimpCore.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(DimpCore.DMenu.element().readAttribute('mbox'), modify); }.bind(this, a == 'ctx_folder_poll'), ns: true });
++ }, this);
++ C({ d: $('ctx_container_create'), f: function() { this.createSubFolder(DimpCore.DMenu.element()); }.bind(this), ns: true });
++ C({ d: $('ctx_container_rename'), f: function() { this.renameFolder(DimpCore.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 });
++ }
++
++ $('expandHeaders', 'collapseHeaders').each(function(a) {
++ C({ d: a, f: function() { $('msgHeadersColl', 'msgHeaders').invoke('toggle'); }, ns: true });
++ }, this);
++ $('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();
++ },
++
++ // IE 6 width fixes (See Bug #6793)
++ _resizeIE6: function()
++ {
++ if (DIMP.conf.is_ie6) {
++ var tmp = parseInt($('sidebarPanel').getStyle('width'), 10),
++ tmp1 = document.viewport.getWidth() - tmp - 30;
++ $('normalfolders').setStyle({ width: tmp + 'px' });
++ $('dimpmain').setStyle({ width: tmp1 + 'px' });
++ $('msglist').setStyle({ width: (tmp1 - 5) + 'px' });
++ $('msgBody').setStyle({ width: (tmp1 - 25) + 'px' });
++ tmp = $('dimpmain_portal').down('IFRAME');
++ if (tmp) {
++ this._resizeIE6Iframe(tmp);
++ }
++ }
++ },
++
++ _resizeIE6Iframe: function(iframe)
++ {
++ if (DIMP.conf.is_ie6) {
++ iframe.setStyle({ width: $('dimpmain').getStyle('width'), height: (document.viewport.getHeight() - 20) + 'px' });
++ }
++ }
++};
++
++/* Need to add after DimpBase is defined. */
++DimpBase._msgDragConfig = {
++ scroll: 'normalfolders',
++ threshold: 5,
++ caption: DimpBase._dragCaption.bind(DimpBase),
++ onStart: function(d, e) {
++ var args = { right: e.isRightClick() },
++ id = d.element.id;
++
++ d.selectIfNoDrag = false;
++
++ // Handle selection first.
++ if (!args.right && (e.ctrlKey || e.metaKey)) {
++ this.msgSelect(id, $H({ ctrl: true }).merge(args).toObject());
++ } else if (e.shiftKey) {
++ this.msgSelect(id, $H({ shift: true }).merge(args).toObject());
++ } else if (this.isSelected('domid', id)) {
++ if (!args.right && this.selectedCount()) {
++ d.selectIfNoDrag = true;
++ }
++ } else {
++ this.msgSelect(id, args);
++ }
++ }.bind(DimpBase),
++ onEnd: function(d, e) {
++ if (d.selectIfNoDrag && !d.wasDragged) {
++ this.msgSelect(d.element.id, { right: e.isRightClick() });
++ }
++ }.bind(DimpBase)
++};
++
++DimpBase._folderDragConfig = {
++ ghosting: true,
++ offset: { x: 5, y: 5 },
++ scroll: 'normalfolders',
++ threshold: 5,
++ onDrag: function(d, e) {
++ if (!d.wasDragged) {
++ $('newfolder').hide();
++ $('dropbase').show();
++ d.ghost.removeClassName('on');
++ }
++ },
++ onEnd: function(d, e) {
++ if (d.wasDragged) {
++ $('newfolder').show();
++ $('dropbase').hide();
++ }
++ }
++};
++
++DimpBase._folderDropConfig = {
++ hoverclass: 'dragdrop',
++ caption: function(drop, drag) {
++ var d = drag.readAttribute('l'),
++ ftype = drop.readAttribute('ftype'),
++ l = drop.readAttribute('l'),
++ m = DIMP.text.moveto;
++ if (drop == $('dropbase')) {
++ return m.replace(/%s/, d).replace(/%s/, DIMP.text.baselevel);
++ } else if (drag.hasClassName('folder')) {
++ return (ftype != 'special' && !this.isSubfolder(drag, drop)) ? m.replace(/%s/, d).replace(/%s/, l) : '';
++ } else {
++ return ftype != 'container' ? m.replace(/%s/, this._dragCaption()).replace(/%s/, l) : '';
++ }
++ }.bind(DimpBase),
++ onDrop: DimpBase._folderDropHandler.bind(DimpBase)
++};
++
++/* Stuff to do immediately when page is ready. */
++document.observe('dom:loaded', function() {
++ $('dimpLoading').hide();
++ $('dimpPage').show();
++
++ /* Create the folder list. Any pending notifications will be caught via
++ * the return from this call. */
++ DimpCore.doAction('ListFolders', {}, [], DimpBase._folderLoadCallback.bind(DimpBase));
++
++ /* Start message list loading as soon as possible. */
++ if (!DimpBase.delay_onload) {
++ DimpBase._onLoad();
++ }
++
++ /* Disable text selection in preview pane for IE 6. */
++ if (DIMP.conf.is_ie6) {
++ document.observe('selectstart', Event.stop);
++ }
++
++ /* Remove unneeded search folders. */
++ if (!DIMP.conf.search_all) {
++ DimpBase.sfiltersfolder.unset('sf_all');
++ }
++
++ /* Check for new mail. */
++ DimpBase.setPollFolders();
++
++ /* Bind key shortcuts. */
++ document.observe('keydown', DimpBase._keydownHandler.bind(DimpBase));
++
++ /* Resize elements on window size change. */
++ Event.observe(window, 'resize', DimpBase._onResize.bind(DimpBase));
++
++ /* Since IE 6 doesn't support hover over non-links, use javascript events
++ * to replicate mouseover CSS behavior. */
++ if (DIMP.conf.is_ie6) {
++ var links = [], tmp;
++ if (tmp = $('dimpbarActions')) {
++ links.push(tmp.select('SPAN'));
++ }
++ if (tmp = $('serviceActions')) {
++ links.push(tmp.select('LI.servicelink'));
++ }
++ if (tmp = $('applicationfolders')) {
++ links.push(tmp.select('UL LI'));
++ }
++ links.flatten().compact().each(function(e) {
++ e.observe('mouseover', e.addClassName.curry('over')).observe('mouseout', e.removeClassName.curry('over'));
++ });
++ }
++});
++
++/* Stuff to do after window is completely loaded. Don't init viewport until
++ * now for non-Gecko/Opera browsers since sizing functions might not work
++ * properly before. */
++if (DimpBase.delay_onload) {
++ Event.observe(window, 'load', DimpBase._onLoad.bind(DimpBase));
++}
++
++/* Need to register a callback function for doAction to catch viewport
++ * information returned from the server. */
++DimpCore.onDoActionComplete = function(r) {
++ if (DimpBase.viewport && r.response.viewport) {
++ DimpBase.viewport.ajaxResponse(r.response.viewport);
++ }
++};
++
++/* Extend these functions from DimpCore since additional processing needs to
++ * be done re: drag/drop and menu manipulation. */
++DimpCore.addMouseEvents = DimpCore.addMouseEvents.wrap(DimpBase._addMouseEvents.bind(DimpBase));
++DimpCore.removeMouseEvents = DimpCore.removeMouseEvents.wrap(DimpBase._removeMouseEvents.bind(DimpBase));
+diff -ur dimp-h3-1.1.6.orig/js/src/DimpBase.js dimp-h3-1.1.6/js/src/DimpBase.js
+--- dimp-h3-1.1.6.orig/js/src/DimpBase.js 2010-09-27 19:14:34.000000000 +0100
++++ dimp-h3-1.1.6/js/src/DimpBase.js 2011-01-10 23:49:33.897945000 +0000
+@@ -1548,7 +1548,7 @@
+
+ div = new Element('DIV', { className: ob.cl || 'base', id: fid + '_div' });
+ if (ob.i) {
+- div.update(ob.i);
++ div.setStyle({ backgroundImage: 'url("' + ob.i + '")' });
+ }
+ if (ob.ch) {
+ div.writeAttribute({ className: 'exp' }).observe('mouseover', this.bcache.get('mo_folder') || this.bcache.set('mo_folder', function(e) {
+Only in dimp-h3-1.1.6/js/src: DimpBase.js.orig
+diff -ur dimp-h3-1.1.6.orig/lib/DIMP.php dimp-h3-1.1.6/lib/DIMP.php
+--- dimp-h3-1.1.6.orig/lib/DIMP.php 2010-09-27 19:14:30.000000000 +0100
++++ dimp-h3-1.1.6/lib/DIMP.php 2011-01-10 23:49:33.897945000 +0000
+@@ -436,8 +436,13 @@
+ }
+
+ if ($elt['user_icon']) {
+- $ob->cl = 'custom';
+- $ob->i = Horde::img($elt['icon'], $elt['alt'], '', $elt['icondir']);
++ $ob->cl = 'customimg';
++ $dir = empty($elt['icondir'])
++ ? $GLOBALS['registry']->getImageDir()
++ : $elt['icondir'];
++ $ob->i = empty($dir)
++ ? $elt['icon']
++ : $dir . '/' . $elt['icon'];
+ }
+
+ return $ob;
+Only in dimp-h3-1.1.6/lib: DIMP.php.orig
+diff -ur dimp-h3-1.1.6.orig/themes/screen.css dimp-h3-1.1.6/themes/screen.css
+--- dimp-h3-1.1.6.orig/themes/screen.css 2008-09-05 15:17:01.000000000 +0100
++++ dimp-h3-1.1.6/themes/screen.css 2011-01-10 23:49:33.897945000 +0000
+@@ -464,7 +464,7 @@
+ height: 100%;
+ background: transparent url("graphics/folder_create.png") center left no-repeat;
+ }
+-#sidebarPanel .drafts, #sidebarPanel .inbox, #sidebarPanel .sent, #sidebarPanel .spam, #sidebarPanel .trash {
++#sidebarPanel .drafts, #sidebarPanel .inbox, #sidebarPanel .sent, #sidebarPanel .spam, #sidebarPanel .trash, #sidebarPanel .customimg {
+ display: inline;
+ float: left;
+ width: 20px;
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/0002-close-context-menu.patch b/kolab-webclient/dimp/patches/dimp-1.1.6/0002-close-context-menu.patch
new file mode 100644
index 0000000..ab764f0
--- /dev/null
+++ b/kolab-webclient/dimp/patches/dimp-1.1.6/0002-close-context-menu.patch
@@ -0,0 +1,21 @@
+diff -ur dimp-h3-1.1.6-0001-fix-broken-folder-images/js/DimpBase.js dimp-h3-1.1.6/js/DimpBase.js
+--- dimp-h3-1.1.6-0001-fix-broken-folder-images/js/DimpBase.js 2011-01-10 23:49:33.895945000 +0000
++++ dimp-h3-1.1.6/js/DimpBase.js 2011-01-10 23:50:59.238945002 +0000
+@@ -1510,6 +1510,7 @@
+
+ case 'folder':
+ case 'special':
++ DimpCore.DMenu.close();
+ e.stop();
+ return this.go('folder:' + li.readAttribute('mbox'));
+ break;
+@@ -1887,7 +1888,7 @@
+ tmp = $('applicationfolders');
+ if (tmp) {
+ tmp.select('ul li.custom a').each(function(s) {
+- C({ d: s, f: this.go.bind(this, 'app:' + s.readAttribute('app')) });
++ C({ d: s, f: function(data){DimpCore.DMenu.close(); this.go('app:' + s.readAttribute('app'), data)}.bind(this) });
+ }, this);
+ }
+
+Only in dimp-h3-1.1.6/js: DimpBase.js.orig
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/0003-acl-view.patch b/kolab-webclient/dimp/patches/dimp-1.1.6/0003-acl-view.patch
new file mode 100644
index 0000000..d537ee6
--- /dev/null
+++ b/kolab-webclient/dimp/patches/dimp-1.1.6/0003-acl-view.patch
@@ -0,0 +1,83 @@
+diff -ur dimp-h3-1.1.6-0002-close-context-menu/js/DimpBase.js dimp-h3-1.1.6/js/DimpBase.js
+--- dimp-h3-1.1.6-0002-close-context-menu/js/DimpBase.js 2011-01-10 23:50:59.238945002 +0000
++++ dimp-h3-1.1.6/js/DimpBase.js 2011-01-10 23:52:13.909945003 +0000
+@@ -1926,6 +1926,7 @@
+ C({ d: $('ctx_folder_rename'), f: function() { this.renameFolder(DimpCore.DMenu.element()); }.bind(this), ns: true });
+ C({ d: $('ctx_folder_empty'), f: function() { if (window.confirm(DIMP.text.empty_folder)) { DimpCore.doAction('EmptyFolder', { folder: DimpCore.DMenu.element().readAttribute('mbox') }, [], this._emptyFolderCallback.bind(this)); } }.bind(this), ns: true });
+ C({ d: $('ctx_folder_delete'), f: function() { if (window.confirm(DIMP.text.delete_folder)) { DimpCore.doAction('DeleteFolder', { folder: DimpCore.DMenu.element().readAttribute('mbox') }, [], this.bcache.get('folderC') || this.bcache.set('folderC', this._folderCallback.bind(this))); } }.bind(this), ns: true });
++ C({ d: $('ctx_folder_rights'), f: function() { this.go('app:horde', DIMP.conf.folder_rights + '&' + $H({ folder: DimpCore.DMenu.element().readAttribute('mbox') }).toQueryString() ) }.bind(this), ns: true });
+ [ 'ctx_folder_seen', 'ctx_folder_unseen' ].each(function(a) {
+ C({ d: $(a), f: function(type) { this.flag(type, null, DimpCore.DMenu.element().readAttribute('mbox')); }.bind(this, a == 'ctx_folder_seen' ? 'allSeen' : 'allUnseen'), ns: true });
+ }, this);
+diff -ur dimp-h3-1.1.6-0002-close-context-menu/js/DimpBase.js.orig dimp-h3-1.1.6/js/DimpBase.js.orig
+--- dimp-h3-1.1.6-0002-close-context-menu/js/DimpBase.js.orig 2011-01-10 23:49:33.895945000 +0000
++++ dimp-h3-1.1.6/js/DimpBase.js.orig 2011-01-10 23:50:59.238945002 +0000
+@@ -1510,6 +1510,7 @@
+
+ case 'folder':
+ case 'special':
++ DimpCore.DMenu.close();
+ e.stop();
+ return this.go('folder:' + li.readAttribute('mbox'));
+ break;
+@@ -1887,7 +1888,7 @@
+ tmp = $('applicationfolders');
+ if (tmp) {
+ tmp.select('ul li.custom a').each(function(s) {
+- C({ d: s, f: this.go.bind(this, 'app:' + s.readAttribute('app')) });
++ C({ d: s, f: function(data){DimpCore.DMenu.close(); this.go('app:' + s.readAttribute('app'), data)}.bind(this) });
+ }, this);
+ }
+
+diff -ur dimp-h3-1.1.6-0002-close-context-menu/lib/DIMP.php dimp-h3-1.1.6/lib/DIMP.php
+--- dimp-h3-1.1.6-0002-close-context-menu/lib/DIMP.php 2011-01-10 23:49:33.897945000 +0000
++++ dimp-h3-1.1.6/lib/DIMP.php 2011-01-10 23:52:13.910945003 +0000
+@@ -166,6 +166,7 @@
+ 'message_url' => Horde::url($dimp_webroot . '/message.php'),
+ 'compose_url' => Horde::url($dimp_webroot . '/compose.php'),
+ 'prefs_url' => str_replace('&', '&', Horde::getServiceLink('options', 'dimp')),
++ 'folder_rights' => Util::addParameter(Horde::url($registry->get('webroot', 'imp') . '/acl.php', true), array('app' => 'imp', 'group'=> 'acl'), null, false),
+
+ 'sortthread' => SORTTHREAD,
+ 'sortdate' => SORTDATE,
+diff -ur dimp-h3-1.1.6-0002-close-context-menu/lib/DIMP.php.orig dimp-h3-1.1.6/lib/DIMP.php.orig
+--- dimp-h3-1.1.6-0002-close-context-menu/lib/DIMP.php.orig 2010-09-27 19:14:30.000000000 +0100
++++ dimp-h3-1.1.6/lib/DIMP.php.orig 2011-01-10 23:49:33.897945000 +0000
+@@ -436,8 +436,13 @@
+ }
+
+ if ($elt['user_icon']) {
+- $ob->cl = 'custom';
+- $ob->i = Horde::img($elt['icon'], $elt['alt'], '', $elt['icondir']);
++ $ob->cl = 'customimg';
++ $dir = empty($elt['icondir'])
++ ? $GLOBALS['registry']->getImageDir()
++ : $elt['icondir'];
++ $ob->i = empty($dir)
++ ? $elt['icon']
++ : $dir . '/' . $elt['icon'];
+ }
+
+ return $ob;
+diff -ur dimp-h3-1.1.6-0002-close-context-menu/po/de_DE.po dimp-h3-1.1.6/po/de_DE.po
+--- dimp-h3-1.1.6-0002-close-context-menu/po/de_DE.po 2010-10-25 13:50:13.000000000 +0100
++++ dimp-h3-1.1.6/po/de_DE.po 2011-01-10 23:52:13.910945003 +0000
+@@ -798,3 +798,6 @@
+ #: lib/DIMP.php:216
+ msgid "results found"
+ msgstr "Ergebnisse gefunden"
++
++msgid "Share Folder"
++msgstr "Berechtigungen"
+Only in dimp-h3-1.1.6/po: de_DE.po.orig
+diff -ur dimp-h3-1.1.6-0002-close-context-menu/templates/index/index.inc dimp-h3-1.1.6/templates/index/index.inc
+--- dimp-h3-1.1.6-0002-close-context-menu/templates/index/index.inc 2008-12-07 22:22:20.000000000 +0000
++++ dimp-h3-1.1.6/templates/index/index.inc 2011-01-10 23:52:13.911945002 +0000
+@@ -323,6 +323,7 @@
+ <a id="ctx_folder_rename"><?php echo $folder_edit . _("Rename Folder") ?></a>
+ <a id="ctx_folder_empty"><?php echo $delete . _("Empty Folder") ?></a>
+ <a id="ctx_folder_delete"><?php echo Horde::img('folders/folder_delete.png') . _("Delete Folder") ?></a>
++ <a id="ctx_folder_rights"><?php echo Horde::img('folders/folder.png') . _("Share Folder") ?></a>
+ <div id="ctx_folder_seen_sep" class="sep"></div>
+ <a id="ctx_folder_seen"><?php echo $mailseen . _("Mark all as Read") ?></a>
+ <a id="ctx_folder_unseen"><?php echo $mailunseen . _("Mark all as New") ?></a>
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/0004-folders-view.patch b/kolab-webclient/dimp/patches/dimp-1.1.6/0004-folders-view.patch
new file mode 100644
index 0000000..d448885
--- /dev/null
+++ b/kolab-webclient/dimp/patches/dimp-1.1.6/0004-folders-view.patch
@@ -0,0 +1,41 @@
+diff -ur dimp-h3-1.1.6-0003-acl-view/config/menu.php.dist dimp-h3-1.1.6/config/menu.php.dist
+--- dimp-h3-1.1.6-0003-acl-view/config/menu.php.dist 2008-03-10 20:19:35.000000000 +0000
++++ dimp-h3-1.1.6/config/menu.php.dist 2011-01-10 23:53:29.632945001 +0000
+@@ -28,3 +28,14 @@
+ // 'text' => 'Say Hi!',
+ // 'icon' => $GLOBALS['registry']->getImageDir('horde') . '/horde.png'),
+ // );
++
++// Load configuration files in .d directory
++$directory = dirname(__FILE__) . '/menu.d';
++if (file_exists($directory) && is_dir($directory)) {
++ $sub_files = glob("$directory/*.php");
++ if ($sub_files) {
++ foreach ($sub_files as $sub_file) {
++ require_once $sub_file;
++ }
++ }
++ }
+diff -ur dimp-h3-1.1.6-0003-acl-view/po/de_DE.po dimp-h3-1.1.6/po/de_DE.po
+--- dimp-h3-1.1.6-0003-acl-view/po/de_DE.po 2011-01-10 23:52:13.910945003 +0000
++++ dimp-h3-1.1.6/po/de_DE.po 2011-01-10 23:53:29.633945001 +0000
+@@ -17,6 +17,9 @@
+ "Content-Transfer-Encoding: 8bit\n"
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
++msgid "Folder Subscription"
++msgstr "Ordner verwalten"
++
+ #: lib/Views/ShowMessage.php:295
+ #, php-format
+ msgid "%d Attachment"
+diff -ur dimp-h3-1.1.6-0003-acl-view/po/de_DE.po.orig dimp-h3-1.1.6/po/de_DE.po.orig
+--- dimp-h3-1.1.6-0003-acl-view/po/de_DE.po.orig 2010-10-25 13:50:13.000000000 +0100
++++ dimp-h3-1.1.6/po/de_DE.po.orig 2011-01-10 23:52:13.910945003 +0000
+@@ -798,3 +798,6 @@
+ #: lib/DIMP.php:216
+ msgid "results found"
+ msgstr "Ergebnisse gefunden"
++
++msgid "Share Folder"
++msgstr "Berechtigungen"
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/0005-itip-handling.patch b/kolab-webclient/dimp/patches/dimp-1.1.6/0005-itip-handling.patch
new file mode 100644
index 0000000..e3a5e7a
--- /dev/null
+++ b/kolab-webclient/dimp/patches/dimp-1.1.6/0005-itip-handling.patch
@@ -0,0 +1,69 @@
+diff -ur dimp-h3-1.1.6-0004-folders-view/imp.php dimp-h3-1.1.6/imp.php
+--- dimp-h3-1.1.6-0004-folders-view/imp.php 2010-09-27 19:14:30.000000000 +0100
++++ dimp-h3-1.1.6/imp.php 2011-01-10 23:54:42.525945001 +0000
+@@ -730,6 +730,29 @@
+ $result = $prefs->setValue(Util::getPost('pref'), Util::getPost('value'));
+ }
+ break;
++
++case 'iTip':
++ $selection = Util::getPost('selection');
++ $component = Util::getPost('component');
++ $action = str_replace('_', '-', $selection);
++ $_POST['action'] = array($component => $action);
++
++ if (empty($indices)) {
++ break;
++ }
++ $idx_string = _getIdxString($indices);
++
++ /* Parse MIME info and create the body of the message. */
++ require_once IMP_BASE . '/lib/MIME/Contents.php';
++ $imp_contents = &IMP_Contents::singleton($idx_string);
++
++ $cr = !$imp_contents->buildMessage();
++
++ if (is_a($cr, 'PEAR_Error')) {
++ $notification->push($cr, 'horde.error');
++ }
++
++ break;
+ }
+
+ // Clear the output buffer that we started above, and log any unexpected
+Only in dimp-h3-1.1.6/: imp.php.orig
+diff -ur dimp-h3-1.1.6-0004-folders-view/js/DimpBase.js dimp-h3-1.1.6/js/DimpBase.js
+--- dimp-h3-1.1.6-0004-folders-view/js/DimpBase.js 2011-01-10 23:52:13.909945003 +0000
++++ dimp-h3-1.1.6/js/DimpBase.js 2011-01-10 23:54:42.527945001 +0000
+@@ -1660,6 +1660,20 @@
+ nf.setStyle({ height: (document.viewport.getHeight() - nf.cumulativeOffset()[1] - 10) + 'px' });
+ },
+
++ itip: function(action, index, folder, component)
++ {
++ var args, vs;
++
++ vs = this.viewport.getViewportSelection().search({ imapuid: { equal: [ index ] }, view: { equal: [ folder ] } });
++ if (!vs.size() && folder != this.folder) {
++ vs = this.viewport.getViewportSelection(folder).search({ imapuid: { equal: [ index ] } });
++ }
++
++ args = this.viewport.addRequestParams({ selection: action, component: component });
++
++ DimpCore.doAction('iTip', args, DimpCore.toUIDArray(vs));
++ },
++
+ /* Flag actions for message list. */
+ flag: function(action, index, folder)
+ {
+diff -ur dimp-h3-1.1.6-0004-folders-view/js/DimpBase.js.orig dimp-h3-1.1.6/js/DimpBase.js.orig
+--- dimp-h3-1.1.6-0004-folders-view/js/DimpBase.js.orig 2011-01-10 23:50:59.238945002 +0000
++++ dimp-h3-1.1.6/js/DimpBase.js.orig 2011-01-10 23:52:13.909945003 +0000
+@@ -1926,6 +1926,7 @@
+ C({ d: $('ctx_folder_rename'), f: function() { this.renameFolder(DimpCore.DMenu.element()); }.bind(this), ns: true });
+ C({ d: $('ctx_folder_empty'), f: function() { if (window.confirm(DIMP.text.empty_folder)) { DimpCore.doAction('EmptyFolder', { folder: DimpCore.DMenu.element().readAttribute('mbox') }, [], this._emptyFolderCallback.bind(this)); } }.bind(this), ns: true });
+ C({ d: $('ctx_folder_delete'), f: function() { if (window.confirm(DIMP.text.delete_folder)) { DimpCore.doAction('DeleteFolder', { folder: DimpCore.DMenu.element().readAttribute('mbox') }, [], this.bcache.get('folderC') || this.bcache.set('folderC', this._folderCallback.bind(this))); } }.bind(this), ns: true });
++ C({ d: $('ctx_folder_rights'), f: function() { this.go('app:horde', DIMP.conf.folder_rights + '&' + $H({ folder: DimpCore.DMenu.element().readAttribute('mbox') }).toQueryString() ) }.bind(this), ns: true });
+ [ 'ctx_folder_seen', 'ctx_folder_unseen' ].each(function(a) {
+ C({ d: $(a), f: function(type) { this.flag(type, null, DimpCore.DMenu.element().readAttribute('mbox')); }.bind(this, a == 'ctx_folder_seen' ? 'allSeen' : 'allUnseen'), ns: true });
+ }, this);
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/0006-copy-msgs-with-ctrl.patch b/kolab-webclient/dimp/patches/dimp-1.1.6/0006-copy-msgs-with-ctrl.patch
new file mode 100644
index 0000000..610c11c
--- /dev/null
+++ b/kolab-webclient/dimp/patches/dimp-1.1.6/0006-copy-msgs-with-ctrl.patch
@@ -0,0 +1,629 @@
+diff -ur dimp-h3-1.1.6-0005-itip-handling/js/DimpBase.js dimp-h3-1.1.6/js/DimpBase.js
+--- dimp-h3-1.1.6-0005-itip-handling/js/DimpBase.js 2011-01-10 23:54:42.527945001 +0000
++++ dimp-h3-1.1.6/js/DimpBase.js 2011-01-10 23:56:26.328944998 +0000
+@@ -1175,7 +1175,7 @@
+ },
+
+ /* Drag/Drop handler. */
+- _folderDropHandler: function(drop, drag)
++ _folderDropHandler: function(drop, drag, e)
+ {
+ var dropbase, sel, uids,
+ foldername = drop.readAttribute('mbox'),
+@@ -1198,10 +1198,14 @@
+ uids = this.viewport.createSelection('domid', drag.id);
+ }
+
+- // Don't allow drag/drop to the current folder.
+- if (uids.size() && this.folder != foldername) {
+- this.viewport.updateFlag(uids, 'deletedmsg', true);
+- DimpCore.doAction('MoveMessage', this.viewport.addRequestParams({ tofld: foldername }), DimpCore.toUIDArray(uids), this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)));
++ if (uids.size()) {
++ if (e.ctrlKey) {
++ DimpCore.doAction('CopyMessage', this.viewport.addRequestParams({ tofld: foldername }), DimpCore.toUIDArray(uids), this.bcache.get('pollFC') || this.bcache.set('pollFC', this._pollFoldersCallback.bind(this)));
++ } else if (this.folder != foldername) {
++ // Don't allow drag/drop to the current folder.
++ this.viewport.updateFlag(uids, 'deletedmsg', true);
++ DimpCore.doAction('MoveMessage', this.viewport.addRequestParams({ tofld: foldername }), DimpCore.toUIDArray(uids), this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)));
++ }
+ }
+ }
+ },
+@@ -2073,17 +2077,20 @@
+
+ DimpBase._folderDropConfig = {
+ hoverclass: 'dragdrop',
+- caption: function(drop, drag) {
+- var d = drag.readAttribute('l'),
++ caption: function(drop, drag, e) {
++ var m,
++ d = drag.readAttribute('l'),
+ ftype = drop.readAttribute('ftype'),
+- l = drop.readAttribute('l'),
+- m = DIMP.text.moveto;
++ l = drop.readAttribute('l');
+ if (drop == $('dropbase')) {
+- return m.replace(/%s/, d).replace(/%s/, DIMP.text.baselevel);
+- } else if (drag.hasClassName('folder')) {
+- return (ftype != 'special' && !this.isSubfolder(drag, drop)) ? m.replace(/%s/, d).replace(/%s/, l) : '';
++ return DIMP.text.moveto.replace(/%s/, d).replace(/%s/, DIMP.text.baselevel);
+ } else {
+- return ftype != 'container' ? m.replace(/%s/, this._dragCaption()).replace(/%s/, l) : '';
++ m = (e.ctrlKey) ? DIMP.text.copyto : DIMP.text.moveto;
++ if (drag.hasClassName('folder')) {
++ return (ftype != 'special' && !this.isSubfolder(drag, drop)) ? m.replace(/%s/, d).replace(/%s/, l) : '';
++ } else {
++ return ftype != 'container' ? m.replace(/%s/, this._dragCaption()).replace(/%s/, l) : '';
++ }
+ }
+ }.bind(DimpBase),
+ onDrop: DimpBase._folderDropHandler.bind(DimpBase)
+diff -ur dimp-h3-1.1.6-0005-itip-handling/js/dragdrop.js dimp-h3-1.1.6/js/dragdrop.js
+--- dimp-h3-1.1.6-0005-itip-handling/js/dragdrop.js 2009-08-07 18:23:40.000000000 +0100
++++ dimp-h3-1.1.6/js/dragdrop.js 2011-01-10 23:56:26.329945003 +0000
+@@ -1 +1,452 @@
+-var DragDrop={Drags:{drags:$H(),register:function(a){if(!this.drags.size()){if(!this.div){this.div=new Element("DIV",{className:a.options.classname}).hide()}$(document.body).insert(this.div)}this.drags.set(a.element.readAttribute("id"),a)},unregister:function(a){if(this.drag==a.element){this.drag.deactivate()}this.drags.unset(a.element.readAttribute("id"));if(!this.drags.size()&&this.div){this.div.remove()}},get_drag:function(a){return this.drags.get(Object.isElement(a)?$(a).readAttribute("id"):a)},activate:function(a){if(this.drag){this.deactivate()}this.drag=a;this.mousemoveE=a._mouseMove.bindAsEventListener(a);this.mouseupE=a._mouseUp.bindAsEventListener(a);document.observe("mousemove",this.mousemoveE);document.observe("mouseup",this.mouseupE)},deactivate:function(){if(this.drag){this.drag=null;document.stopObserving("mousemove",this.mousemoveE);document.stopObserving("mouseup",this.mouseupE)}}},Drops:{drops:$H(),register:function(a){this.drops.set(a.element.readAttribut
e("id"),a)},unregister:function(a){if(this.drop==a.element){this.drop=null}this.drops.unset(a.element.readAttribute("id"))},get_drop:function(a){return this.drops.get(Object.isElement(a)?$(a).readAttribute("id"):a)}},validDrop:function(a){var b=DragDrop.Drops.drop;return(b&&a&&a!=b.element&&(!b.options.accept.size()||b.options.accept.include(a.tagName)))}},Drag=Class.create({initialize:function(a){this.element=$(a);this.options=Object.extend({caption:"",classname:"drag",constraint:null,ghosting:false,scroll:null,snap:null,threshold:0,onDrag:null,onEnd:null,onStart:null},arguments[1]||{});this.mousedownE=this._mouseDown.bindAsEventListener(this);this.element.observe("mousedown",this.mousedownE);if(this.options.scroll){this.options.scroll=$(this.options.scroll)}DragDrop.Drags.register(this);if(Prototype.Browser.IE){this.element.observe("selectstart",Event.stop)}else{if(Prototype.Browser.Gecko){this.element.setStyle({MozUserSelect:"none"})}}},destroy:function(){this.element.sto
pObserving("mousedown",this.mousedownE);DragDrop.Drags.unreg!
ister(th
is)},_mouseDown:function(a){$(document.body).setStyle({cursor:"default"});DragDrop.Drags.activate(this);this.move=0;this.wasDragged=false;this.lastdrag=this.lastcaption=null;if(Object.isFunction(this.options.onStart)){this.options.onStart(this,a)}if(!Prototype.Browser.IE&&!Prototype.Browser.Gecko){a.stop()}},_mouseMove:function(f){var b,c,a,d;if(++this.move<=this.options.threshold){return}this.lastCoord=d=[f.pointerX(),f.pointerY()];if(this.options.ghosting){if(!this.ghost){b=this.element.offsetLeft;c=this.element.offsetTop;this.ghost=$(this.element.cloneNode(true)).writeAttribute("id",null).setOpacity(0.7).clonePosition(this.element,{setLeft:false,setTop:false}).setStyle({left:b+"px",position:"absolute",top:c+"px",zIndex:parseInt(this.element.getStyle("zIndex"))+1});this.element.insert({before:this.ghost});a=this.ghost.viewportOffset();this.ghostOffset=[a[0]-b,a[1]-c]}d[0]-=this.ghostOffset[0];d[1]-=this.ghostOffset[1];switch(this.options.constraint){case"horizontal":d[1]=th
is.ghost.offsetTop;break;case"vertical":d[0]=this.ghost.offsetLeft;break}if(this.options.snap){d=this.options.snap(d[0],d[1],this.element)}if(this.options.offset){d[0]+=this.options.offset.x;d[1]+=this.options.offset.y}this._setContents(this.ghost,d[0],d[1])}this._onMoveDrag(d);if(Object.isFunction(this.options.onDrag)){this.options.onDrag(this,f)}this.wasDragged=true;if(this.options.scroll){this._onMoveScroll()}},_mouseUp:function(a){var b=DragDrop.Drops.drop;this._stopScrolling();if(this.ghost){this.ghost.remove();this.ghost=null}DragDrop.Drags.div.hide();if(DragDrop.validDrop(this.element)&&Object.isFunction(b.options.onDrop)){b.options.onDrop(b.element,this.element)}DragDrop.Drags.deactivate();if(Object.isFunction(this.options.onEnd)){this.options.onEnd(this,a)}},_onMoveDrag:function(g){var f,c,e,b,a,h=DragDrop.Drops.drop,i=DragDrop.Drags.div;if(h&&h.element!=this.lastdrag){if(DragDrop.validDrop(this.element)){b=h.options.caption;if(b){c=Object.isFunction(b)?b(h.element,
this.element):b;if(c&&h.options.hoverclass){e=h.options.hove!
rclass}a
=true}}else{a=true}this.lastdrag=h.element}else{if((!h&&this.lastdrag)||(this.move==(this.options.threshold+1))){a=true;this.lastdrag=null}}if(a){if(!c){f=this.options.caption;c=Object.isFunction(f)?f(this.element):f}this.lastcaption=c;i.update(c).writeAttribute({className:e||this.options.classname});if(c.empty()){i.hide()}}if(!this.lastcaption.empty()){this._setContents(i,g[0]+15,g[1]+(this.ghost?(this.ghost.getHeight()+5):5))}},_onMoveScroll:function(){this._stopScrolling();var e,d,b,a=this.options.scroll,c=a.getDimensions();if(a.scrollHeight==c.height){return}e=document.viewport.getScrollOffsets();d=a.viewportOffset(),b=[0,0];d[0]+=a.scrollLeft+e.left;d[2]=d[0]+c.width;if(this.lastCoord[0]>d[2]||this.lastCoord[0]<d[0]){return}d[1]+=a.scrollTop+e.top;d[3]=d[1]+c.height;if(this.lastCoord[1]<d[1]){b[1]=this.lastCoord[1]-d[1]}if(this.lastCoord[1]>d[3]){b[1]=this.lastCoord[1]-d[3]}if(b[0]||b[1]){this.lastScrolled=new Date();this.scrollInterval=setInterval(this._scroll.bind(this
,b[0]*15,b[1]*15),10)}},_stopScrolling:function(){if(this.scrollInterval){clearInterval(this.scrollInterval);this.scrollInterval=null}},_scroll:function(a,e){var c=new Date(),d=c-this.lastScrolled,b=this.options.scroll;this.lastScrolled=c;b.scrollTop+=e*d/1000},_setContents:function(c,a,e){var d=document.viewport.getDimensions(),b=c.getDimensions();if((a+b.width>d.width)||(e+b.height>d.height)){c.hide()}else{c.setStyle({left:a+"px",top:e+"px"}).show()}}}),Drop=Class.create({initialize:function(a){this.element=$(a);this.options=Object.extend({accept:[],caption:"",hoverclass:"",onDrop:null,onOut:null,onOver:null},arguments[1]||{});this.mouseoverE=this._mouseOver.bindAsEventListener(this);this.mouseoutE=this._mouseOut.bindAsEventListener(this);this.element.observe("mouseover",this.mouseoverE);this.element.observe("mouseout",this.mouseoutE);DragDrop.Drops.register(this)},destroy:function(){this.element.stopObserving("mouseover",this.mouseoverE);this.element.stopObserving("mouseo
ut",this.mouseoutE);DragDrop.Drops.unregister(this)},_mouseO!
ver:func
tion(a){if(DragDrop.Drags.drag){DragDrop.Drops.drop=this;if(Object.isFunction(this.options.onOver)){this.options.onOver(this.element,DragDrop.Drags.drag)}}},_mouseOut:function(a){if(Object.isFunction(this.options.onOut)){this.options.onOut(this.element,DragDrop.Drags.drag)}DragDrop.Drops.drop=null}});
+\ No newline at end of file
++/**
++ * dragdrop.js - A minimalist library to handle drag/drop actions.
++ * Requires prototype.js 1.6.0.2+
++ *
++ * Adapted from SkyByte.js/SkyByteDD.js v1.0-beta, May 17 2007
++ * (c) 2007 Aleksandras Ilarionovas (Alex)
++ * http://www.skybyte.net/scripts/
++ *
++ * Scrolling and ghosting code adapted from script.aculo.us dragdrop.js v1.8.0
++ * (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
++ * (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi at oriontransfer.co.nz)
++ *
++ * The original scripts were freely distributable under the terms of an
++ * MIT-style license.
++ *
++ * Usage:
++ * new Drag(element, {
++ * classname: '', // Class name of the drag element
++ * caption: '', // Either string or function to set caption
++ * // on mouse move
++ * ghosting: false, // Show ghost outline when dragging.
++ * offset: { x:0, y:0 }, // An offset to apply to ghosted elements.
++ * scroll: element, // Scroll this element when above/below.
++ * // Only working for vertical elements
++ * snap: null, // If ghosting, snap allows to specify
++ * // coords at which the ghosted image will
++ * // "snap" into place.
++ * threshold: 0, // Move threshold
++ * // For the following functions, d = drop element, e = event object
++ * onStart: function(d,e), // A function to run on mousedown
++ * onDrag: function(d,e), // A function to run on mousemove
++ * onEnd: function(d,e) // A function to run on mouseup
++ * });
++ *
++ * new Drop(element, {
++ * accept: [], // Accept filter by tag name(s) or leave empty
++ * // to accept all tags
++ * caption: '', // Either string or function to set caption on
++ * // mouse over
++ * hoverclass: '', // Change the drag element to this class when
++ * // hovering over an element.
++ * onDrop: function(drop,drag) // Function fired when mouse button
++ * // released (a/k/a a drop event)
++ * onOver: function(drop,drag) // Function fired when mouse over zone
++ * onOut: function(drop,drag) // Function fired when mouse leaves the
++ * // zone
++ * });
++ *
++ * $Horde
++ *
++ * @author Michael Slusarz <slusarz at curecanti.org>
++ */
++
++var DragDrop = {
++ Drags: {
++ drags: $H(),
++
++ register: function(obj)
++ {
++ if (!this.drags.size()) {
++ if (!this.div) {
++ this.div = new Element('DIV', { className: obj.options.classname }).hide();
++ }
++ $(document.body).insert(this.div);
++ }
++
++ this.drags.set(obj.element.readAttribute('id'), obj);
++ },
++
++ unregister: function(obj)
++ {
++ if (this.drag == obj.element) {
++ this.drag.deactivate();
++ }
++
++ this.drags.unset(obj.element.readAttribute('id'));
++
++ if (!this.drags.size() && this.div) {
++ this.div.remove();
++ }
++ },
++
++ get_drag: function(el)
++ {
++ return this.drags.get(Object.isElement(el) ? $(el).readAttribute('id') : el);
++ },
++
++ activate: function(drag)
++ {
++ if (this.drag) {
++ this.deactivate();
++ }
++ this.drag = drag;
++ this.mousemoveE = drag._mouseMove.bindAsEventListener(drag);
++ this.mouseupE = drag._mouseUp.bindAsEventListener(drag);
++ document.observe('mousemove', this.mousemoveE);
++ document.observe('mouseup', this.mouseupE);
++ },
++
++ deactivate: function()
++ {
++ if (this.drag) {
++ this.drag = null;
++ document.stopObserving('mousemove', this.mousemoveE);
++ document.stopObserving('mouseup', this.mouseupE);
++ }
++ }
++ },
++
++ Drops: {
++ drops: $H(),
++
++ register: function(obj)
++ {
++ this.drops.set(obj.element.readAttribute('id'), obj);
++ },
++
++ unregister: function(obj)
++ {
++ if (this.drop == obj.element) {
++ this.drop = null;
++ }
++
++ this.drops.unset(obj.element.readAttribute('id'));
++ },
++
++ get_drop: function(el)
++ {
++ return this.drops.get(Object.isElement(el) ? $(el).readAttribute('id') : el);
++ }
++ },
++
++ validDrop: function(el)
++ {
++ var d = DragDrop.Drops.drop;
++ return (d &&
++ el &&
++ el != d.element &&
++ (!d.options.accept.size() ||
++ d.options.accept.include(el.tagName)));
++ }
++},
++
++Drag = Class.create({
++
++ initialize: function(el) {
++ this.element = $(el);
++ this.options = Object.extend({
++ caption: '',
++ classname: 'drag',
++ constraint: null,
++ ghosting: false,
++ scroll: null,
++ snap: null,
++ threshold: 0,
++ onDrag: null,
++ onEnd: null,
++ onStart: null
++ }, arguments[1] || {});
++ this.mousedownE = this._mouseDown.bindAsEventListener(this);
++ this.element.observe('mousedown', this.mousedownE);
++ if (this.options.scroll) {
++ this.options.scroll = $(this.options.scroll);
++ }
++ DragDrop.Drags.register(this);
++
++ // Disable text selection.
++ // See: http://ajaxcookbook.org/disable-text-selection/
++ // Stopping the event on mousedown works on all browsers, but avoid
++ // that if possible because it will prevent any event handlers further
++ // up the DOM tree from firing.
++ if (Prototype.Browser.IE) {
++ this.element.observe('selectstart', Event.stop);
++ } else if (Prototype.Browser.Gecko) {
++ this.element.setStyle({ MozUserSelect: 'none' });
++ }
++ },
++
++ destroy: function()
++ {
++ this.element.stopObserving('mousedown', this.mousedownE);
++ DragDrop.Drags.unregister(this);
++ },
++
++ _mouseDown: function(e)
++ {
++ $(document.body).setStyle({ cursor: 'default' });
++ DragDrop.Drags.activate(this);
++ this.move = 0;
++ this.wasDragged = false;
++ this.lastcaption = null;
++
++ if (Object.isFunction(this.options.onStart)) {
++ this.options.onStart(this, e);
++ }
++
++ if (!Prototype.Browser.IE && !Prototype.Browser.Gecko) {
++ e.stop();
++ }
++ },
++
++ _mouseMove: function(e)
++ {
++ var oleft, otop, vo, xy;
++
++ if (++this.move <= this.options.threshold) {
++ return;
++ }
++
++ this.lastCoord = xy = [ e.pointerX(), e.pointerY() ];
++
++ if (this.options.ghosting) {
++ if (!this.ghost) {
++ oleft = this.element.offsetLeft;
++ otop = this.element.offsetTop;
++ this.ghost = $(this.element.cloneNode(true)).writeAttribute('id', null).setOpacity(0.7).clonePosition(this.element, { setLeft: false, setTop: false }).setStyle({ left: oleft + 'px', position: 'absolute', top: otop + 'px', zIndex: parseInt(this.element.getStyle('zIndex')) + 1 });
++ this.element.insert({ before: this.ghost });
++ vo = this.ghost.viewportOffset();
++ this.ghostOffset = [ vo[0] - oleft, vo[1] - otop ];
++ }
++
++ xy[0] -= this.ghostOffset[0];
++ xy[1] -= this.ghostOffset[1];
++
++ switch (this.options.constraint) {
++ case 'horizontal':
++ xy[1] = this.ghost.offsetTop;
++ break;
++
++ case 'vertical':
++ xy[0] = this.ghost.offsetLeft;
++ break;
++ }
++
++ if (this.options.snap) {
++ xy = this.options.snap(xy[0], xy[1], this.element);
++ }
++
++ if (this.options.offset) {
++ xy[0] += this.options.offset.x;
++ xy[1] += this.options.offset.y;
++ }
++
++ this._setContents(this.ghost, xy[0], xy[1]);
++ }
++
++ this._onMoveDrag(xy, e);
++
++ if (Object.isFunction(this.options.onDrag)) {
++ this.options.onDrag(this, e);
++ }
++
++ this.wasDragged = true;
++
++ if (this.options.scroll) {
++ this._onMoveScroll();
++ }
++ },
++
++ _mouseUp: function(e)
++ {
++ var d = DragDrop.Drops.drop;
++
++ this._stopScrolling();
++
++ if (this.ghost) {
++ this.ghost.remove();
++ this.ghost = null;
++ }
++ DragDrop.Drags.div.hide();
++
++ if (DragDrop.validDrop(this.element) &&
++ Object.isFunction(d.options.onDrop)) {
++ d.options.onDrop(d.element, this.element, e);
++ }
++
++ DragDrop.Drags.deactivate();
++
++ if (Object.isFunction(this.options.onEnd)) {
++ this.options.onEnd(this, e);
++ }
++ },
++
++ _onMoveDrag: function(xy, e)
++ {
++ var c_opt, caption, cname, d_cap,
++ d = DragDrop.Drops.drop,
++ div = DragDrop.Drags.div,
++ d_update = true;
++
++ if (d && DragDrop.validDrop(this.element)) {
++ d_cap = d.options.caption;
++ if (d_cap) {
++ caption = Object.isFunction(d_cap) ? d_cap(d.element, this.element, e) : d_cap;
++ if (caption && d.options.hoverclass) {
++ cname = d.options.hoverclass;
++ }
++ } else {
++ d_update = false;
++ }
++ }
++
++ if (d_update) {
++ if (!caption) {
++ c_opt = this.options.caption;
++ caption = Object.isFunction(c_opt) ? c_opt(this.element) : c_opt;
++ }
++ if (caption != this.lastcaption) {
++ this.lastcaption = caption;
++ div.update(caption).writeAttribute({ className: cname || this.options.classname });
++ if (caption.empty()) {
++ div.hide();
++ }
++ }
++ }
++
++ if (!this.lastcaption.empty()) {
++ this._setContents(div, xy[0] + 15, xy[1] + (this.ghost ? (this.ghost.getHeight() + 5) : 5));
++ }
++ },
++
++ _onMoveScroll: function()
++ {
++ this._stopScrolling();
++
++ var delta, p, speed,
++ s = this.options.scroll,
++ dim = s.getDimensions();
++
++ // No need to scroll if element is not current scrolling.
++ if (s.scrollHeight == dim.height) {
++ return;
++ }
++
++ delta = document.viewport.getScrollOffsets();
++ p = s.viewportOffset(),
++ speed = [ 0, 0 ];
++
++ p[0] += s.scrollLeft + delta.left;
++ p[2] = p[0] + dim.width;
++
++ // Only scroll if directly above/below element
++ if (this.lastCoord[0] > p[2] ||
++ this.lastCoord[0] < p[0]) {
++ return;
++ }
++
++ p[1] += s.scrollTop + delta.top;
++ p[3] = p[1] + dim.height;
++
++ // Left scroll
++ //if (this.lastCoord[0] < p[0]) {
++ // speed[0] = this.lastCoord[0] - p[0];
++ //}
++ // Top scroll
++ if (this.lastCoord[1] < p[1]) {
++ speed[1] = this.lastCoord[1] - p[1];
++ }
++ // Scroll right
++ //if (this.lastCoord[0] > p[2]) {
++ // speed[0] = this.lastCoord[0] - p[2];
++ //}
++ // Scroll left
++ if (this.lastCoord[1] > p[3]) {
++ speed[1] = this.lastCoord[1] - p[3];
++ }
++
++ if (speed[0] || speed[1]) {
++ this.lastScrolled = new Date();
++ this.scrollInterval = setInterval(this._scroll.bind(this, speed[0] * 15, speed[1] * 15), 10);
++ }
++ },
++
++ _stopScrolling: function()
++ {
++ if (this.scrollInterval) {
++ clearInterval(this.scrollInterval);
++ this.scrollInterval = null;
++ }
++ },
++
++ _scroll: function(x, y)
++ {
++ var current = new Date(),
++ delta = current - this.lastScrolled,
++ s = this.options.scroll;
++ this.lastScrolled = current;
++
++ //s.scrollLeft += x * delta / 1000;
++ s.scrollTop += y * delta / 1000;
++ },
++
++ _setContents: function(elt, x, y)
++ {
++ var d_pos = document.viewport.getDimensions(),
++ e_pos = elt.getDimensions();
++
++ if ((x + e_pos.width > d_pos.width) ||
++ (y + e_pos.height > d_pos.height)) {
++ elt.hide();
++ } else {
++ elt.setStyle({ left: x + 'px', top: y + 'px' }).show();
++ }
++ }
++
++}),
++
++Drop = Class.create({
++
++ initialize: function(el)
++ {
++ this.element = $(el);
++ this.options = Object.extend({
++ accept: [],
++ caption: '',
++ hoverclass: '',
++ onDrop: null,
++ onOut: null,
++ onOver: null
++ }, arguments[1] || {});
++ this.mouseoverE = this._mouseOver.bindAsEventListener(this);
++ this.mouseoutE = this._mouseOut.bindAsEventListener(this);
++ this.element.observe('mouseover', this.mouseoverE);
++ this.element.observe('mouseout', this.mouseoutE);
++ DragDrop.Drops.register(this);
++ },
++
++ destroy: function()
++ {
++ this.element.stopObserving('mouseover', this.mouseoverE);
++ this.element.stopObserving('mouseout', this.mouseoutE);
++ DragDrop.Drops.unregister(this);
++ },
++
++ _mouseOver: function(e)
++ {
++ if (DragDrop.Drags.drag) {
++ DragDrop.Drops.drop = this;
++ if (Object.isFunction(this.options.onOver)) {
++ this.options.onOver(this.element, DragDrop.Drags.drag);
++ }
++ }
++ },
++
++ _mouseOut: function(e)
++ {
++ if (Object.isFunction(this.options.onOut)) {
++ this.options.onOut(this.element, DragDrop.Drags.drag);
++ }
++ DragDrop.Drops.drop = null;
++ }
++});
+diff -ur dimp-h3-1.1.6-0005-itip-handling/js/src/dragdrop.js dimp-h3-1.1.6/js/src/dragdrop.js
+--- dimp-h3-1.1.6-0005-itip-handling/js/src/dragdrop.js 2008-08-04 19:58:11.000000000 +0100
++++ dimp-h3-1.1.6/js/src/dragdrop.js 2011-01-10 23:56:26.330945006 +0000
+@@ -188,7 +188,7 @@
+ DragDrop.Drags.activate(this);
+ this.move = 0;
+ this.wasDragged = false;
+- this.lastdrag = this.lastcaption = null;
++ this.lastcaption = null;
+
+ if (Object.isFunction(this.options.onStart)) {
+ this.options.onStart(this, e);
+@@ -244,7 +244,7 @@
+ this._setContents(this.ghost, xy[0], xy[1]);
+ }
+
+- this._onMoveDrag(xy);
++ this._onMoveDrag(xy, e);
+
+ if (Object.isFunction(this.options.onDrag)) {
+ this.options.onDrag(this, e);
+@@ -271,7 +271,7 @@
+
+ if (DragDrop.validDrop(this.element) &&
+ Object.isFunction(d.options.onDrop)) {
+- d.options.onDrop(d.element, this.element);
++ d.options.onDrop(d.element, this.element, e);
+ }
+
+ DragDrop.Drags.deactivate();
+@@ -281,30 +281,23 @@
+ }
+ },
+
+- _onMoveDrag: function(xy)
++ _onMoveDrag: function(xy, e)
+ {
+- var c_opt, caption, cname, d_cap, d_update,
++ var c_opt, caption, cname, d_cap,
+ d = DragDrop.Drops.drop,
+- div = DragDrop.Drags.div;
++ div = DragDrop.Drags.div,
++ d_update = true;
+
+- if (d && d.element != this.lastdrag) {
+- if (DragDrop.validDrop(this.element)) {
+- d_cap = d.options.caption;
+- if (d_cap) {
+- caption = Object.isFunction(d_cap) ? d_cap(d.element, this.element) : d_cap;
+- if (caption && d.options.hoverclass) {
+- cname = d.options.hoverclass;
+- }
+- d_update = true;
++ if (d && DragDrop.validDrop(this.element)) {
++ d_cap = d.options.caption;
++ if (d_cap) {
++ caption = Object.isFunction(d_cap) ? d_cap(d.element, this.element, e) : d_cap;
++ if (caption && d.options.hoverclass) {
++ cname = d.options.hoverclass;
+ }
+ } else {
+- d_update = true;
++ d_update = false;
+ }
+- this.lastdrag = d.element;
+- } else if ((!d && this.lastdrag) ||
+- (this.move == (this.options.threshold + 1))) {
+- d_update = true;
+- this.lastdrag = null;
+ }
+
+ if (d_update) {
+@@ -312,10 +305,12 @@
+ c_opt = this.options.caption;
+ caption = Object.isFunction(c_opt) ? c_opt(this.element) : c_opt;
+ }
+- this.lastcaption = caption;
+- div.update(caption).writeAttribute({ className: cname || this.options.classname });
+- if (caption.empty()) {
+- div.hide();
++ if (caption != this.lastcaption) {
++ this.lastcaption = caption;
++ div.update(caption).writeAttribute({ className: cname || this.options.classname });
++ if (caption.empty()) {
++ div.hide();
++ }
+ }
+ }
+
+diff -ur dimp-h3-1.1.6-0005-itip-handling/lib/DIMP.php dimp-h3-1.1.6/lib/DIMP.php
+--- dimp-h3-1.1.6-0005-itip-handling/lib/DIMP.php 2011-01-10 23:52:13.910945003 +0000
++++ dimp-h3-1.1.6/lib/DIMP.php 2011-01-10 23:56:26.330945006 +0000
+@@ -219,6 +219,7 @@
+ 'showtext' => _("Show Quoted Text"),
+ 'lines' => _("lines"),
+ 'ok' => _("Ok"),
++ 'copyto' => _("Copy %s to %s"),
+ 'moveto' => _("Move %s to %s"),
+ 'baselevel' => _("base level of the folder tree"),
+ 'cancel' => _("Cancel"),
+diff -ur dimp-h3-1.1.6-0005-itip-handling/lib/DIMP.php.orig dimp-h3-1.1.6/lib/DIMP.php.orig
+--- dimp-h3-1.1.6-0005-itip-handling/lib/DIMP.php.orig 2011-01-10 23:49:33.897945000 +0000
++++ dimp-h3-1.1.6/lib/DIMP.php.orig 2011-01-10 23:52:13.910945003 +0000
+@@ -166,6 +166,7 @@
+ 'message_url' => Horde::url($dimp_webroot . '/message.php'),
+ 'compose_url' => Horde::url($dimp_webroot . '/compose.php'),
+ 'prefs_url' => str_replace('&', '&', Horde::getServiceLink('options', 'dimp')),
++ 'folder_rights' => Util::addParameter(Horde::url($registry->get('webroot', 'imp') . '/acl.php', true), array('app' => 'imp', 'group'=> 'acl'), null, false),
+
+ 'sortthread' => SORTTHREAD,
+ 'sortdate' => SORTDATE,
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/series b/kolab-webclient/dimp/patches/dimp-1.1.6/series
index ecb3f6d..56ab895 100644
--- a/kolab-webclient/dimp/patches/dimp-1.1.6/series
+++ b/kolab-webclient/dimp/patches/dimp-1.1.6/series
@@ -1,6 +1,7 @@
-t_dimp_H_MS_FixBrokenFolderImages.diff
-t_dimp_H_BL_CloseContextMenu.diff
-t_dimp_H_GW_AclView.diff
-t_dimp_H_GW_FoldersView.diff
-t_dimp_HK_GW_ItipHandling.diff
-t_dimp_H_MS_CopyMessagesWithCtrl.diff
\ No newline at end of file
+0001-fix-broken-folder-images.patch
+0002-close-context-menu.patch
+0003-acl-view.patch
+0004-folders-view.patch
+0005-itip-handling.patch
+0006-copy-msgs-with-ctrl.patch
+
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_HK_GW_ItipHandling.diff b/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_HK_GW_ItipHandling.diff
deleted file mode 100644
index b20c9f0..0000000
--- a/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_HK_GW_ItipHandling.diff
+++ /dev/null
@@ -1,72 +0,0 @@
-From: Gunnar Wrobel <p at rdus.de>
-Subject: [PATCH] t/dimp/HK/GW/ItipHandling
-
-Allow handling iTip messages in dimp.
-
-Signed-off-by: Gunnar Wrobel <p at rdus.de>
-
----
- imp.php | 23 +++++++
- js/DimpBase.js | 14 ++++
- 2 files changed, 108 insertions(+), 27 deletions(-)
-
-diff --git a/imp.php b/imp.php
-index f8b9b5c..70264fe 100644
---- a/imp.php
-+++ b/imp.php
-@@ -710,6 +710,29 @@ case 'SendMDN':
- $imp_ui = new IMP_UI_Message();
- $imp_ui->MDNCheck($ob->header, true);
- break;
-+
-+case 'iTip':
-+ $selection = Util::getPost('selection');
-+ $component = Util::getPost('component');
-+ $action = str_replace('_', '-', $selection);
-+ $_POST['action'] = array($component => $action);
-+
-+ if (empty($indices)) {
-+ break;
-+ }
-+ $idx_string = _getIdxString($indices);
-+
-+ /* Parse MIME info and create the body of the message. */
-+ require_once IMP_BASE . '/lib/MIME/Contents.php';
-+ $imp_contents = &IMP_Contents::singleton($idx_string);
-+
-+ $cr = !$imp_contents->buildMessage();
-+
-+ if (is_a($cr, 'PEAR_Error')) {
-+ $notification->push($cr, 'horde.error');
-+ }
-+
-+ break;
- }
-
- // Clear the output buffer that we started above, and log any unexpected
-diff --git a/js/DimpBase.js b/js/DimpBase.js
-index 96cd917..39a728b 100644
---- a/js/DimpBase.js
-+++ b/js/DimpBase.js
-@@ -1663,6 +1663,20 @@ var DimpBase = {
- nf.setStyle({ height: (document.viewport.getHeight() - nf.cumulativeOffset()[1] - 10) + 'px' });
- },
-
-+ itip: function(action, index, folder, component)
-+ {
-+ var args, vs;
-+
-+ vs = this.viewport.getViewportSelection().search({ imapuid: { equal: [ index ] }, view: { equal: [ folder ] } });
-+ if (!vs.size() && folder != this.folder) {
-+ vs = this.viewport.getViewportSelection(folder).search({ imapuid: { equal: [ index ] } });
-+ }
-+
-+ args = this.viewport.addRequestParams({ selection: action, component: component });
-+
-+ DimpCore.doAction('iTip', args, DimpCore.toUIDArray(vs));
-+ },
-+
- /* Flag actions for message list. */
- flag: function(action, index, folder)
- {
-
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_BL_CloseContextMenu.diff b/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_BL_CloseContextMenu.diff
deleted file mode 100644
index e7c40b0..0000000
--- a/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_BL_CloseContextMenu.diff
+++ /dev/null
@@ -1,45 +0,0 @@
-From: Gunnar Wrobel <p at rdus.de>
-Subject: [PATCH] t/dimp/H/BL/CloseContextMenu
-
-Close the context menu when clicking into the Dimp menu.
-
-Provided by Boris Lorbeer <B.Lorbeer at science-computing.de>
-
-Signed-off-by: Gunnar Wrobel <p at rdus.de>
-
----
- js/DimpBase.js | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/js/DimpBase.js b/js/DimpBase.js
-index c4eb9f4..d90f09b 100644
---- a/js/DimpBase.js
-+++ b/js/DimpBase.js
-@@ -1507,6 +1507,7 @@ var DimpBase = {
-
- case 'folder':
- case 'special':
-+ DimpCore.DMenu.close();
- e.stop();
- return this.go('folder:' + li.readAttribute('mbox'));
- break;
-@@ -1903,7 +1904,7 @@ var DimpBase = {
- tmp = $('applicationfolders');
- if (tmp) {
- tmp.select('ul li.custom a').each(function(s) {
-- C({ d: s, f: this.go.bind(this, 'app:' + s.readAttribute('app')) });
-+ C({ d: s, f: function(data){DimpCore.DMenu.close(); this.go('app:' + s.readAttribute('app'), data)}.bind(this) });
- }, this);
- }
-
---
-tg: (19ee6e6..) t/dimp/H/BL/CloseContextMenu (depends on: t/kronolith/HK/GW/AnonymousiCalDownload)
---
-TOPGIT patch commit log
-=======================
-
-commit b4b3190a4fb88e1843ff86adde4897dea21046db
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Mon Jul 20 09:39:24 2009 +0200
-
- Close the context menu when clicking into the Dimp menu.
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_GW_AclView.diff b/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_GW_AclView.diff
deleted file mode 100644
index c3da779..0000000
--- a/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_GW_AclView.diff
+++ /dev/null
@@ -1,107 +0,0 @@
-From: Gunnar Wrobel <p at rdus.de>
-Subject: [PATCH] t/dimp/H/GW/AclView
-
-Provide a possibility to edit IMAP folder acls within DIMP.
-
-kolab/issue3455 (There is no convenient/dimp-like way in dimp to set folder acls)
-https://www.intevation.de/roundup/kolab/issue3455
-
-[#8060] Additional entry in the folder popup to set IMAP ACLs
-http://bugs.horde.org/ticket/8060
-
-Signed-off-by: Gunnar Wrobel <p at rdus.de>
-
----
- js/DimpBase.js | 1 +
- lib/DIMP.php | 1 +
- .../dimp/locale/de_DE/LC_MESSAGES/dimp.mo | Bin 168731 -> 168778 bytes
- po/de_DE.po | 3 +++
- templates/index/index.inc | 1 +
- 7 files changed, 29 insertions(+), 2 deletions(-)
-
-diff --git a/js/DimpBase.js b/js/DimpBase.js
-index 39a728b..c4eb9f4 100644
---- a/js/DimpBase.js
-+++ b/js/DimpBase.js
-@@ -1941,6 +1941,7 @@ var DimpBase = {
- C({ d: $('ctx_folder_rename'), f: function() { this.renameFolder(DimpCore.DMenu.element()); }.bind(this), ns: true });
- C({ d: $('ctx_folder_empty'), f: function() { if (window.confirm(DIMP.text.empty_folder)) { DimpCore.doAction('EmptyFolder', { folder: DimpCore.DMenu.element().readAttribute('mbox') }, [], this._emptyFolderCallback.bind(this)); } }.bind(this), ns: true });
- C({ d: $('ctx_folder_delete'), f: function() { if (window.confirm(DIMP.text.delete_folder)) { DimpCore.doAction('DeleteFolder', { folder: DimpCore.DMenu.element().readAttribute('mbox') }, [], this.bcache.get('folderC') || this.bcache.set('folderC', this._folderCallback.bind(this))); } }.bind(this), ns: true });
-+ C({ d: $('ctx_folder_rights'), f: function() { this.go('app:horde', DIMP.conf.folder_rights + '&' + $H({ folder: DimpCore.DMenu.element().readAttribute('mbox') }).toQueryString() ) }.bind(this), ns: true });
- [ 'ctx_folder_seen', 'ctx_folder_unseen' ].each(function(a) {
- C({ d: $(a), f: function(type) { this.flag(type, null, DimpCore.DMenu.element().readAttribute('mbox')); }.bind(this, a == 'ctx_folder_seen' ? 'allSeen' : 'allUnseen'), ns: true });
- }, this);
-diff --git a/lib/DIMP.php b/lib/DIMP.php
-index 0aa3b78..92a1e55 100644
---- a/lib/DIMP.php
-+++ b/lib/DIMP.php
-@@ -145,6 +145,7 @@ class DIMP {
- 'message_url' => Horde::url($dimp_webroot . '/message.php'),
- 'compose_url' => Horde::url($dimp_webroot . '/compose.php'),
- 'prefs_url' => str_replace('&', '&', Horde::getServiceLink('options', 'dimp')),
-+ 'folder_rights' => Util::addParameter(Horde::url($registry->get('webroot', 'imp') . '/acl.php', true), array('app' => 'imp', 'group'=> 'acl'), null, false),
-
- 'sortthread' => SORTTHREAD,
- 'sortdate' => SORTDATE,
-diff --git a/locale/de_DE/LC_MESSAGES/dimp.mo b/locale/de_DE/LC_MESSAGES/dimp.mo
-index 2f1c11c..973776f 100644
-Binary files a/locale/de_DE/LC_MESSAGES/dimp.mo and b/locale/de_DE/LC_MESSAGES/dimp.mo differ
-diff --git a/po/de_DE.po b/po/de_DE.po
-index a536db6..0486297 100644
---- a/po/de_DE.po
-+++ b/po/de_DE.po
-@@ -791,3 +791,6 @@ msgstr "entfernen"
- #: lib/DIMP.php:191
- msgid "results found"
- msgstr "Ergebnisse gefunden"
-+
-+msgid "Share Folder"
-+msgstr "Berechtigungen"
-diff --git a/templates/index/index.inc b/templates/index/index.inc
-index 21939e0..7c02fe7 100644
---- a/templates/index/index.inc
-+++ b/templates/index/index.inc
-@@ -323,6 +323,7 @@ function _createDA($text, $image, $id = null, $class = '', $show_text = true)
- <a id="ctx_folder_rename"><?php echo $folder_edit . _("Rename Folder") ?></a>
- <a id="ctx_folder_empty"><?php echo $delete . _("Empty Folder") ?></a>
- <a id="ctx_folder_delete"><?php echo Horde::img('folders/folder_delete.png') . _("Delete Folder") ?></a>
-+ <a id="ctx_folder_rights"><?php echo Horde::img('folders/folder.png') . _("Share Folder") ?></a>
- <div id="ctx_folder_seen_sep" class="sep"></div>
- <a id="ctx_folder_seen"><?php echo $mailseen . _("Mark all as Read") ?></a>
- <a id="ctx_folder_unseen"><?php echo $mailunseen . _("Mark all as New") ?></a>
-
---
-tg: (f251c16..) t/dimp/H/GW/AclView (depends on: t/dimp/H/GW/FoldersView)
---
-TOPGIT patch commit log
-=======================
-
-commit e9630629c7479c73d3eb156f00544c34e95f0597
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Mon Jul 20 09:36:01 2009 +0200
-
- Fix translation and improve header.
-
-commit 57041c04c322dd7dc57da5b171923b7ab000ec0a
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Sun Jun 21 23:58:30 2009 +0200
-
- German translation.
-
-commit cac1482cec6c96a8a1d7fb7c0e8c2433877728f5
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Fri Mar 13 12:04:03 2009 +0000
-
- Complete the patch description.
-
-commit 7a349ad9da06264378e84e54d7424f5dc78a9154
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Fri Mar 13 12:00:43 2009 +0000
-
- Reduce the functionality of the ACL view when calling from DIMP. In addition add the call to the acl settings page within the folder context menu.
-
-commit 2fdc4d0fcd6e4956129f6ec11501112568b99c6d
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Sun Mar 8 19:59:30 2009 +0000
-
- Completed a draft.
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_GW_FoldersView.diff b/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_GW_FoldersView.diff
deleted file mode 100644
index 24a486d..0000000
--- a/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_GW_FoldersView.diff
+++ /dev/null
@@ -1,100 +0,0 @@
-From: Gunnar Wrobel <p at rdus.de>
-Subject: [PATCH] t/dimp/H/GW/FoldersView
-
-Provide a folders menu for dimp.
-
-kolab/issue3456 (There is no view in dimp that allows folder subscription)
-https://www.intevation.de/roundup/kolab/issue3456
-
-[#8059] DIMP provides no view to subscribe/unsubscribe to folders
-http://bugs.horde.org/ticket/8059
-
-Signed-off-by: Gunnar Wrobel <p at rdus.de>
-
----
- config/menu.php | 9 ++++++++-
- po/de_DE.po | 3 +++
- 2 files changed, 25 insertions(+), 6 deletions(-)
-
-diff --git a/config/menu.php b/config/menu.php
-index 0c6ebe9..b5e0a5c 100644
---- a/config/menu.php.dist
-+++ b/config/menu.php.dist
-@@ -28,3 +28,14 @@
- // 'text' => 'Say Hi!',
- // 'icon' => $GLOBALS['registry']->getImageDir('horde') . '/horde.png'),
- // );
-+
-+// Load configuration files in .d directory
-+$directory = dirname(__FILE__) . '/menu.d';
-+if (file_exists($directory) && is_dir($directory)) {
-+ $sub_files = glob("$directory/*.php");
-+ if ($sub_files) {
-+ foreach ($sub_files as $sub_file) {
-+ require_once $sub_file;
-+ }
-+ }
-+ }
-
-diff --git a/po/de_DE.po b/po/de_DE.po
-index 65e8824..a536db6 100644
---- a/po/de_DE.po
-+++ b/po/de_DE.po
-@@ -16,6 +16,9 @@ msgstr ""
- "Content-Transfer-Encoding: 8bit\n"
- "Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-+msgid "Folder Subscription"
-+msgstr "Ordner verwalten"
-+
- #: lib/Views/ShowMessage.php:295
- #, php-format
- msgid "%d Attachment"
-
---
-tg: (a6f8c8b..) t/dimp/H/GW/FoldersView (depends on: t/kronolith/H/GW/UseDayHourStartEndAlsoInFBView)
---
-TOPGIT patch commit log
-=======================
-
-commit c16643e792c3b185bc74bef7a600c06857b19406
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Mon Nov 9 23:16:11 2009 +0100
-
- Fix tag name from view_imp to imp_view.
-
-commit 93403a869ff14d7868d4cc9c4687ea1270e3c225
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Mon Jun 22 08:39:51 2009 +0200
-
- Typo
-
-commit ad147a4b42d61800400a2a779e884ee050358811
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Mon Jun 22 00:06:14 2009 +0200
-
- Fixed menu entry name, added translation, fixed image.
-
-commit a1966161022108d9bf4831a8613b1db9a4e68c4d
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Fri Mar 13 11:06:45 2009 +0000
-
- Include issue references in the patch description.
-
-commit de8c5e8cac0bfb29c9cf94989016487302da653f
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Fri Mar 13 11:04:54 2009 +0000
-
- Exclude IMP specific functionality as requested by Sascha wilde in kolab/issue3456 (There is no view in dimp that allows folder subscription).
-
-commit 9c9a343c04cf11f857bfeb4148f0ab9d9df7dce6
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Sun Mar 8 19:06:05 2009 +0000
-
- Completed the hack.
-
-commit caa539aac138c4b77376ab9f4a4a86691709a96b
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Sun Mar 8 19:01:41 2009 +0000
-
- Completed the hack.
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_MS_CopyMessagesWithCtrl.diff b/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_MS_CopyMessagesWithCtrl.diff
deleted file mode 100644
index ea6040c..0000000
--- a/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_MS_CopyMessagesWithCtrl.diff
+++ /dev/null
@@ -1,629 +0,0 @@
-From: Gunnar Wrobel <p at rdus.de>
-Subject: [PATCH] t/dimp/H/MS/CopyMessagesWithCtrl
-
-Allow copying messages with Drag&Drop while holding Ctrl.
-
-https://www.intevation.de/roundup/kolab/issue4080
-
-STATUS: MERGED in HEAD but not in FRAMEWORK_3
-
-Signed-off-by: Gunnar Wrobel <p at rdus.de>
-
-diff -Naur a/DimpBase.js b/js/DimpBase.js
---- a/DimpBase.js 2010-04-14 22:21:28.000000000 +0200
-+++ b/js/DimpBase.js 2010-04-14 22:20:38.000000000 +0200
-@@ -1175,7 +1175,7 @@
- },
-
- /* Drag/Drop handler. */
-- _folderDropHandler: function(drop, drag)
-+ _folderDropHandler: function(drop, drag, e)
- {
- var dropbase, sel, uids,
- foldername = drop.readAttribute('mbox'),
-@@ -1198,10 +1198,14 @@
- uids = this.viewport.createSelection('domid', drag.id);
- }
-
-- // Don't allow drag/drop to the current folder.
-- if (uids.size() && this.folder != foldername) {
-- this.viewport.updateFlag(uids, 'deletedmsg', true);
-- DimpCore.doAction('MoveMessage', this.viewport.addRequestParams({ tofld: foldername }), DimpCore.toUIDArray(uids), this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)));
-+ if (uids.size()) {
-+ if (e.ctrlKey) {
-+ DimpCore.doAction('CopyMessage', this.viewport.addRequestParams({ tofld: foldername }), DimpCore.toUIDArray(uids), this.bcache.get('pollFC') || this.bcache.set('pollFC', this._pollFoldersCallback.bind(this)));
-+ } else if (this.folder != foldername) {
-+ // Don't allow drag/drop to the current folder.
-+ this.viewport.updateFlag(uids, 'deletedmsg', true);
-+ DimpCore.doAction('MoveMessage', this.viewport.addRequestParams({ tofld: foldername }), DimpCore.toUIDArray(uids), this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)));
-+ }
- }
- }
- },
-@@ -2073,17 +2077,20 @@
-
- DimpBase._folderDropConfig = {
- hoverclass: 'dragdrop',
-- caption: function(drop, drag) {
-- var d = drag.readAttribute('l'),
-+ caption: function(drop, drag, e) {
-+ var m,
-+ d = drag.readAttribute('l'),
- ftype = drop.readAttribute('ftype'),
-- l = drop.readAttribute('l'),
-- m = DIMP.text.moveto;
-+ l = drop.readAttribute('l');
- if (drop == $('dropbase')) {
-- return m.replace(/%s/, d).replace(/%s/, DIMP.text.baselevel);
-- } else if (drag.hasClassName('folder')) {
-- return (ftype != 'special' && !this.isSubfolder(drag, drop)) ? m.replace(/%s/, d).replace(/%s/, l) : '';
-+ return DIMP.text.moveto.replace(/%s/, d).replace(/%s/, DIMP.text.baselevel);
- } else {
-- return ftype != 'container' ? m.replace(/%s/, this._dragCaption()).replace(/%s/, l) : '';
-+ m = (e.ctrlKey) ? DIMP.text.copyto : DIMP.text.moveto;
-+ if (drag.hasClassName('folder')) {
-+ return (ftype != 'special' && !this.isSubfolder(drag, drop)) ? m.replace(/%s/, d).replace(/%s/, l) : '';
-+ } else {
-+ return ftype != 'container' ? m.replace(/%s/, this._dragCaption()).replace(/%s/, l) : '';
-+ }
- }
- }.bind(DimpBase),
- onDrop: DimpBase._folderDropHandler.bind(DimpBase)
-diff -Naur a/dragdrop.js b/js/dragdrop.js
---- a/dragdrop.js 2010-04-14 22:21:28.000000000 +0200
-+++ b/js/dragdrop.js 2010-04-14 22:20:38.000000000 +0200
-@@ -1 +1,452 @@
--var DragDrop={Drags:{drags:$H(),register:function(a){if(!this.drags.size()){if(!this.div){this.div=new Element("DIV",{className:a.options.classname}).hide()}$(document.body).insert(this.div)}this.drags.set(a.element.readAttribute("id"),a)},unregister:function(a){if(this.drag==a.element){this.drag.deactivate()}this.drags.unset(a.element.readAttribute("id"));if(!this.drags.size()&&this.div){this.div.remove()}},get_drag:function(a){return this.drags.get(Object.isElement(a)?$(a).readAttribute("id"):a)},activate:function(a){if(this.drag){this.deactivate()}this.drag=a;this.mousemoveE=a._mouseMove.bindAsEventListener(a);this.mouseupE=a._mouseUp.bindAsEventListener(a);document.observe("mousemove",this.mousemoveE);document.observe("mouseup",this.mouseupE)},deactivate:function(){if(this.drag){this.drag=null;document.stopObserving("mousemove",this.mousemoveE);document.stopObserving("mouseup",this.mouseupE)}}},Drops:{drops:$H(),register:function(a){this.drops.set(a.element.readAttribut
e("id"),a)},unregister:function(a){if(this.drop==a.element){this.drop=null}this.drops.unset(a.element.readAttribute("id"))},get_drop:function(a){return this.drops.get(Object.isElement(a)?$(a).readAttribute("id"):a)}},validDrop:function(a){var b=DragDrop.Drops.drop;return(b&&a&&a!=b.element&&(!b.options.accept.size()||b.options.accept.include(a.tagName)))}},Drag=Class.create({initialize:function(a){this.element=$(a);this.options=Object.extend({caption:"",classname:"drag",constraint:null,ghosting:false,scroll:null,snap:null,threshold:0,onDrag:null,onEnd:null,onStart:null},arguments[1]||{});this.mousedownE=this._mouseDown.bindAsEventListener(this);this.element.observe("mousedown",this.mousedownE);if(this.options.scroll){this.options.scroll=$(this.options.scroll)}DragDrop.Drags.register(this);if(Prototype.Browser.IE){this.element.observe("selectstart",Event.stop)}else{if(Prototype.Browser.Gecko){this.element.setStyle({MozUserSelect:"none"})}}},destroy:function(){this.element.sto
pObserving("mousedown",this.mousedownE);DragDrop.Drags.unreg!
ister(th
is)},_mouseDown:function(a){$(document.body).setStyle({cursor:"default"});DragDrop.Drags.activate(this);this.move=0;this.wasDragged=false;this.lastdrag=this.lastcaption=null;if(Object.isFunction(this.options.onStart)){this.options.onStart(this,a)}if(!Prototype.Browser.IE&&!Prototype.Browser.Gecko){a.stop()}},_mouseMove:function(f){var b,c,a,d;if(++this.move<=this.options.threshold){return}this.lastCoord=d=[f.pointerX(),f.pointerY()];if(this.options.ghosting){if(!this.ghost){b=this.element.offsetLeft;c=this.element.offsetTop;this.ghost=$(this.element.cloneNode(true)).writeAttribute("id",null).setOpacity(0.7).clonePosition(this.element,{setLeft:false,setTop:false}).setStyle({left:b+"px",position:"absolute",top:c+"px",zIndex:parseInt(this.element.getStyle("zIndex"))+1});this.element.insert({before:this.ghost});a=this.ghost.viewportOffset();this.ghostOffset=[a[0]-b,a[1]-c]}d[0]-=this.ghostOffset[0];d[1]-=this.ghostOffset[1];switch(this.options.constraint){case"horizontal":d[1]=th
is.ghost.offsetTop;break;case"vertical":d[0]=this.ghost.offsetLeft;break}if(this.options.snap){d=this.options.snap(d[0],d[1],this.element)}if(this.options.offset){d[0]+=this.options.offset.x;d[1]+=this.options.offset.y}this._setContents(this.ghost,d[0],d[1])}this._onMoveDrag(d);if(Object.isFunction(this.options.onDrag)){this.options.onDrag(this,f)}this.wasDragged=true;if(this.options.scroll){this._onMoveScroll()}},_mouseUp:function(a){var b=DragDrop.Drops.drop;this._stopScrolling();if(this.ghost){this.ghost.remove();this.ghost=null}DragDrop.Drags.div.hide();if(DragDrop.validDrop(this.element)&&Object.isFunction(b.options.onDrop)){b.options.onDrop(b.element,this.element)}DragDrop.Drags.deactivate();if(Object.isFunction(this.options.onEnd)){this.options.onEnd(this,a)}},_onMoveDrag:function(g){var f,c,e,b,a,h=DragDrop.Drops.drop,i=DragDrop.Drags.div;if(h&&h.element!=this.lastdrag){if(DragDrop.validDrop(this.element)){b=h.options.caption;if(b){c=Object.isFunction(b)?b(h.element,
this.element):b;if(c&&h.options.hoverclass){e=h.options.hove!
rclass}a
=true}}else{a=true}this.lastdrag=h.element}else{if((!h&&this.lastdrag)||(this.move==(this.options.threshold+1))){a=true;this.lastdrag=null}}if(a){if(!c){f=this.options.caption;c=Object.isFunction(f)?f(this.element):f}this.lastcaption=c;i.update(c).writeAttribute({className:e||this.options.classname});if(c.empty()){i.hide()}}if(!this.lastcaption.empty()){this._setContents(i,g[0]+15,g[1]+(this.ghost?(this.ghost.getHeight()+5):5))}},_onMoveScroll:function(){this._stopScrolling();var e,d,b,a=this.options.scroll,c=a.getDimensions();if(a.scrollHeight==c.height){return}e=document.viewport.getScrollOffsets();d=a.viewportOffset(),b=[0,0];d[0]+=a.scrollLeft+e.left;d[2]=d[0]+c.width;if(this.lastCoord[0]>d[2]||this.lastCoord[0]<d[0]){return}d[1]+=a.scrollTop+e.top;d[3]=d[1]+c.height;if(this.lastCoord[1]<d[1]){b[1]=this.lastCoord[1]-d[1]}if(this.lastCoord[1]>d[3]){b[1]=this.lastCoord[1]-d[3]}if(b[0]||b[1]){this.lastScrolled=new Date();this.scrollInterval=setInterval(this._scroll.bind(this
,b[0]*15,b[1]*15),10)}},_stopScrolling:function(){if(this.scrollInterval){clearInterval(this.scrollInterval);this.scrollInterval=null}},_scroll:function(a,e){var c=new Date(),d=c-this.lastScrolled,b=this.options.scroll;this.lastScrolled=c;b.scrollTop+=e*d/1000},_setContents:function(c,a,e){var d=document.viewport.getDimensions(),b=c.getDimensions();if((a+b.width>d.width)||(e+b.height>d.height)){c.hide()}else{c.setStyle({left:a+"px",top:e+"px"}).show()}}}),Drop=Class.create({initialize:function(a){this.element=$(a);this.options=Object.extend({accept:[],caption:"",hoverclass:"",onDrop:null,onOut:null,onOver:null},arguments[1]||{});this.mouseoverE=this._mouseOver.bindAsEventListener(this);this.mouseoutE=this._mouseOut.bindAsEventListener(this);this.element.observe("mouseover",this.mouseoverE);this.element.observe("mouseout",this.mouseoutE);DragDrop.Drops.register(this)},destroy:function(){this.element.stopObserving("mouseover",this.mouseoverE);this.element.stopObserving("mouseo
ut",this.mouseoutE);DragDrop.Drops.unregister(this)},_mouseO!
ver:func
tion(a){if(DragDrop.Drags.drag){DragDrop.Drops.drop=this;if(Object.isFunction(this.options.onOver)){this.options.onOver(this.element,DragDrop.Drags.drag)}}},_mouseOut:function(a){if(Object.isFunction(this.options.onOut)){this.options.onOut(this.element,DragDrop.Drags.drag)}DragDrop.Drops.drop=null}});
-\ No newline at end of file
-+/**
-+ * dragdrop.js - A minimalist library to handle drag/drop actions.
-+ * Requires prototype.js 1.6.0.2+
-+ *
-+ * Adapted from SkyByte.js/SkyByteDD.js v1.0-beta, May 17 2007
-+ * (c) 2007 Aleksandras Ilarionovas (Alex)
-+ * http://www.skybyte.net/scripts/
-+ *
-+ * Scrolling and ghosting code adapted from script.aculo.us dragdrop.js v1.8.0
-+ * (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-+ * (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi at oriontransfer.co.nz)
-+ *
-+ * The original scripts were freely distributable under the terms of an
-+ * MIT-style license.
-+ *
-+ * Usage:
-+ * new Drag(element, {
-+ * classname: '', // Class name of the drag element
-+ * caption: '', // Either string or function to set caption
-+ * // on mouse move
-+ * ghosting: false, // Show ghost outline when dragging.
-+ * offset: { x:0, y:0 }, // An offset to apply to ghosted elements.
-+ * scroll: element, // Scroll this element when above/below.
-+ * // Only working for vertical elements
-+ * snap: null, // If ghosting, snap allows to specify
-+ * // coords at which the ghosted image will
-+ * // "snap" into place.
-+ * threshold: 0, // Move threshold
-+ * // For the following functions, d = drop element, e = event object
-+ * onStart: function(d,e), // A function to run on mousedown
-+ * onDrag: function(d,e), // A function to run on mousemove
-+ * onEnd: function(d,e) // A function to run on mouseup
-+ * });
-+ *
-+ * new Drop(element, {
-+ * accept: [], // Accept filter by tag name(s) or leave empty
-+ * // to accept all tags
-+ * caption: '', // Either string or function to set caption on
-+ * // mouse over
-+ * hoverclass: '', // Change the drag element to this class when
-+ * // hovering over an element.
-+ * onDrop: function(drop,drag) // Function fired when mouse button
-+ * // released (a/k/a a drop event)
-+ * onOver: function(drop,drag) // Function fired when mouse over zone
-+ * onOut: function(drop,drag) // Function fired when mouse leaves the
-+ * // zone
-+ * });
-+ *
-+ * $Horde
-+ *
-+ * @author Michael Slusarz <slusarz at curecanti.org>
-+ */
-+
-+var DragDrop = {
-+ Drags: {
-+ drags: $H(),
-+
-+ register: function(obj)
-+ {
-+ if (!this.drags.size()) {
-+ if (!this.div) {
-+ this.div = new Element('DIV', { className: obj.options.classname }).hide();
-+ }
-+ $(document.body).insert(this.div);
-+ }
-+
-+ this.drags.set(obj.element.readAttribute('id'), obj);
-+ },
-+
-+ unregister: function(obj)
-+ {
-+ if (this.drag == obj.element) {
-+ this.drag.deactivate();
-+ }
-+
-+ this.drags.unset(obj.element.readAttribute('id'));
-+
-+ if (!this.drags.size() && this.div) {
-+ this.div.remove();
-+ }
-+ },
-+
-+ get_drag: function(el)
-+ {
-+ return this.drags.get(Object.isElement(el) ? $(el).readAttribute('id') : el);
-+ },
-+
-+ activate: function(drag)
-+ {
-+ if (this.drag) {
-+ this.deactivate();
-+ }
-+ this.drag = drag;
-+ this.mousemoveE = drag._mouseMove.bindAsEventListener(drag);
-+ this.mouseupE = drag._mouseUp.bindAsEventListener(drag);
-+ document.observe('mousemove', this.mousemoveE);
-+ document.observe('mouseup', this.mouseupE);
-+ },
-+
-+ deactivate: function()
-+ {
-+ if (this.drag) {
-+ this.drag = null;
-+ document.stopObserving('mousemove', this.mousemoveE);
-+ document.stopObserving('mouseup', this.mouseupE);
-+ }
-+ }
-+ },
-+
-+ Drops: {
-+ drops: $H(),
-+
-+ register: function(obj)
-+ {
-+ this.drops.set(obj.element.readAttribute('id'), obj);
-+ },
-+
-+ unregister: function(obj)
-+ {
-+ if (this.drop == obj.element) {
-+ this.drop = null;
-+ }
-+
-+ this.drops.unset(obj.element.readAttribute('id'));
-+ },
-+
-+ get_drop: function(el)
-+ {
-+ return this.drops.get(Object.isElement(el) ? $(el).readAttribute('id') : el);
-+ }
-+ },
-+
-+ validDrop: function(el)
-+ {
-+ var d = DragDrop.Drops.drop;
-+ return (d &&
-+ el &&
-+ el != d.element &&
-+ (!d.options.accept.size() ||
-+ d.options.accept.include(el.tagName)));
-+ }
-+},
-+
-+Drag = Class.create({
-+
-+ initialize: function(el) {
-+ this.element = $(el);
-+ this.options = Object.extend({
-+ caption: '',
-+ classname: 'drag',
-+ constraint: null,
-+ ghosting: false,
-+ scroll: null,
-+ snap: null,
-+ threshold: 0,
-+ onDrag: null,
-+ onEnd: null,
-+ onStart: null
-+ }, arguments[1] || {});
-+ this.mousedownE = this._mouseDown.bindAsEventListener(this);
-+ this.element.observe('mousedown', this.mousedownE);
-+ if (this.options.scroll) {
-+ this.options.scroll = $(this.options.scroll);
-+ }
-+ DragDrop.Drags.register(this);
-+
-+ // Disable text selection.
-+ // See: http://ajaxcookbook.org/disable-text-selection/
-+ // Stopping the event on mousedown works on all browsers, but avoid
-+ // that if possible because it will prevent any event handlers further
-+ // up the DOM tree from firing.
-+ if (Prototype.Browser.IE) {
-+ this.element.observe('selectstart', Event.stop);
-+ } else if (Prototype.Browser.Gecko) {
-+ this.element.setStyle({ MozUserSelect: 'none' });
-+ }
-+ },
-+
-+ destroy: function()
-+ {
-+ this.element.stopObserving('mousedown', this.mousedownE);
-+ DragDrop.Drags.unregister(this);
-+ },
-+
-+ _mouseDown: function(e)
-+ {
-+ $(document.body).setStyle({ cursor: 'default' });
-+ DragDrop.Drags.activate(this);
-+ this.move = 0;
-+ this.wasDragged = false;
-+ this.lastcaption = null;
-+
-+ if (Object.isFunction(this.options.onStart)) {
-+ this.options.onStart(this, e);
-+ }
-+
-+ if (!Prototype.Browser.IE && !Prototype.Browser.Gecko) {
-+ e.stop();
-+ }
-+ },
-+
-+ _mouseMove: function(e)
-+ {
-+ var oleft, otop, vo, xy;
-+
-+ if (++this.move <= this.options.threshold) {
-+ return;
-+ }
-+
-+ this.lastCoord = xy = [ e.pointerX(), e.pointerY() ];
-+
-+ if (this.options.ghosting) {
-+ if (!this.ghost) {
-+ oleft = this.element.offsetLeft;
-+ otop = this.element.offsetTop;
-+ this.ghost = $(this.element.cloneNode(true)).writeAttribute('id', null).setOpacity(0.7).clonePosition(this.element, { setLeft: false, setTop: false }).setStyle({ left: oleft + 'px', position: 'absolute', top: otop + 'px', zIndex: parseInt(this.element.getStyle('zIndex')) + 1 });
-+ this.element.insert({ before: this.ghost });
-+ vo = this.ghost.viewportOffset();
-+ this.ghostOffset = [ vo[0] - oleft, vo[1] - otop ];
-+ }
-+
-+ xy[0] -= this.ghostOffset[0];
-+ xy[1] -= this.ghostOffset[1];
-+
-+ switch (this.options.constraint) {
-+ case 'horizontal':
-+ xy[1] = this.ghost.offsetTop;
-+ break;
-+
-+ case 'vertical':
-+ xy[0] = this.ghost.offsetLeft;
-+ break;
-+ }
-+
-+ if (this.options.snap) {
-+ xy = this.options.snap(xy[0], xy[1], this.element);
-+ }
-+
-+ if (this.options.offset) {
-+ xy[0] += this.options.offset.x;
-+ xy[1] += this.options.offset.y;
-+ }
-+
-+ this._setContents(this.ghost, xy[0], xy[1]);
-+ }
-+
-+ this._onMoveDrag(xy, e);
-+
-+ if (Object.isFunction(this.options.onDrag)) {
-+ this.options.onDrag(this, e);
-+ }
-+
-+ this.wasDragged = true;
-+
-+ if (this.options.scroll) {
-+ this._onMoveScroll();
-+ }
-+ },
-+
-+ _mouseUp: function(e)
-+ {
-+ var d = DragDrop.Drops.drop;
-+
-+ this._stopScrolling();
-+
-+ if (this.ghost) {
-+ this.ghost.remove();
-+ this.ghost = null;
-+ }
-+ DragDrop.Drags.div.hide();
-+
-+ if (DragDrop.validDrop(this.element) &&
-+ Object.isFunction(d.options.onDrop)) {
-+ d.options.onDrop(d.element, this.element, e);
-+ }
-+
-+ DragDrop.Drags.deactivate();
-+
-+ if (Object.isFunction(this.options.onEnd)) {
-+ this.options.onEnd(this, e);
-+ }
-+ },
-+
-+ _onMoveDrag: function(xy, e)
-+ {
-+ var c_opt, caption, cname, d_cap,
-+ d = DragDrop.Drops.drop,
-+ div = DragDrop.Drags.div,
-+ d_update = true;
-+
-+ if (d && DragDrop.validDrop(this.element)) {
-+ d_cap = d.options.caption;
-+ if (d_cap) {
-+ caption = Object.isFunction(d_cap) ? d_cap(d.element, this.element, e) : d_cap;
-+ if (caption && d.options.hoverclass) {
-+ cname = d.options.hoverclass;
-+ }
-+ } else {
-+ d_update = false;
-+ }
-+ }
-+
-+ if (d_update) {
-+ if (!caption) {
-+ c_opt = this.options.caption;
-+ caption = Object.isFunction(c_opt) ? c_opt(this.element) : c_opt;
-+ }
-+ if (caption != this.lastcaption) {
-+ this.lastcaption = caption;
-+ div.update(caption).writeAttribute({ className: cname || this.options.classname });
-+ if (caption.empty()) {
-+ div.hide();
-+ }
-+ }
-+ }
-+
-+ if (!this.lastcaption.empty()) {
-+ this._setContents(div, xy[0] + 15, xy[1] + (this.ghost ? (this.ghost.getHeight() + 5) : 5));
-+ }
-+ },
-+
-+ _onMoveScroll: function()
-+ {
-+ this._stopScrolling();
-+
-+ var delta, p, speed,
-+ s = this.options.scroll,
-+ dim = s.getDimensions();
-+
-+ // No need to scroll if element is not current scrolling.
-+ if (s.scrollHeight == dim.height) {
-+ return;
-+ }
-+
-+ delta = document.viewport.getScrollOffsets();
-+ p = s.viewportOffset(),
-+ speed = [ 0, 0 ];
-+
-+ p[0] += s.scrollLeft + delta.left;
-+ p[2] = p[0] + dim.width;
-+
-+ // Only scroll if directly above/below element
-+ if (this.lastCoord[0] > p[2] ||
-+ this.lastCoord[0] < p[0]) {
-+ return;
-+ }
-+
-+ p[1] += s.scrollTop + delta.top;
-+ p[3] = p[1] + dim.height;
-+
-+ // Left scroll
-+ //if (this.lastCoord[0] < p[0]) {
-+ // speed[0] = this.lastCoord[0] - p[0];
-+ //}
-+ // Top scroll
-+ if (this.lastCoord[1] < p[1]) {
-+ speed[1] = this.lastCoord[1] - p[1];
-+ }
-+ // Scroll right
-+ //if (this.lastCoord[0] > p[2]) {
-+ // speed[0] = this.lastCoord[0] - p[2];
-+ //}
-+ // Scroll left
-+ if (this.lastCoord[1] > p[3]) {
-+ speed[1] = this.lastCoord[1] - p[3];
-+ }
-+
-+ if (speed[0] || speed[1]) {
-+ this.lastScrolled = new Date();
-+ this.scrollInterval = setInterval(this._scroll.bind(this, speed[0] * 15, speed[1] * 15), 10);
-+ }
-+ },
-+
-+ _stopScrolling: function()
-+ {
-+ if (this.scrollInterval) {
-+ clearInterval(this.scrollInterval);
-+ this.scrollInterval = null;
-+ }
-+ },
-+
-+ _scroll: function(x, y)
-+ {
-+ var current = new Date(),
-+ delta = current - this.lastScrolled,
-+ s = this.options.scroll;
-+ this.lastScrolled = current;
-+
-+ //s.scrollLeft += x * delta / 1000;
-+ s.scrollTop += y * delta / 1000;
-+ },
-+
-+ _setContents: function(elt, x, y)
-+ {
-+ var d_pos = document.viewport.getDimensions(),
-+ e_pos = elt.getDimensions();
-+
-+ if ((x + e_pos.width > d_pos.width) ||
-+ (y + e_pos.height > d_pos.height)) {
-+ elt.hide();
-+ } else {
-+ elt.setStyle({ left: x + 'px', top: y + 'px' }).show();
-+ }
-+ }
-+
-+}),
-+
-+Drop = Class.create({
-+
-+ initialize: function(el)
-+ {
-+ this.element = $(el);
-+ this.options = Object.extend({
-+ accept: [],
-+ caption: '',
-+ hoverclass: '',
-+ onDrop: null,
-+ onOut: null,
-+ onOver: null
-+ }, arguments[1] || {});
-+ this.mouseoverE = this._mouseOver.bindAsEventListener(this);
-+ this.mouseoutE = this._mouseOut.bindAsEventListener(this);
-+ this.element.observe('mouseover', this.mouseoverE);
-+ this.element.observe('mouseout', this.mouseoutE);
-+ DragDrop.Drops.register(this);
-+ },
-+
-+ destroy: function()
-+ {
-+ this.element.stopObserving('mouseover', this.mouseoverE);
-+ this.element.stopObserving('mouseout', this.mouseoutE);
-+ DragDrop.Drops.unregister(this);
-+ },
-+
-+ _mouseOver: function(e)
-+ {
-+ if (DragDrop.Drags.drag) {
-+ DragDrop.Drops.drop = this;
-+ if (Object.isFunction(this.options.onOver)) {
-+ this.options.onOver(this.element, DragDrop.Drags.drag);
-+ }
-+ }
-+ },
-+
-+ _mouseOut: function(e)
-+ {
-+ if (Object.isFunction(this.options.onOut)) {
-+ this.options.onOut(this.element, DragDrop.Drags.drag);
-+ }
-+ DragDrop.Drops.drop = null;
-+ }
-+});
-diff -Naur a/src/dragdrop.js b/js/src/dragdrop.js
---- a/src/dragdrop.js 2010-04-14 22:21:28.000000000 +0200
-+++ b/js/src/dragdrop.js 2010-04-14 22:20:38.000000000 +0200
-@@ -188,7 +188,7 @@
- DragDrop.Drags.activate(this);
- this.move = 0;
- this.wasDragged = false;
-- this.lastdrag = this.lastcaption = null;
-+ this.lastcaption = null;
-
- if (Object.isFunction(this.options.onStart)) {
- this.options.onStart(this, e);
-@@ -244,7 +244,7 @@
- this._setContents(this.ghost, xy[0], xy[1]);
- }
-
-- this._onMoveDrag(xy);
-+ this._onMoveDrag(xy, e);
-
- if (Object.isFunction(this.options.onDrag)) {
- this.options.onDrag(this, e);
-@@ -271,7 +271,7 @@
-
- if (DragDrop.validDrop(this.element) &&
- Object.isFunction(d.options.onDrop)) {
-- d.options.onDrop(d.element, this.element);
-+ d.options.onDrop(d.element, this.element, e);
- }
-
- DragDrop.Drags.deactivate();
-@@ -281,30 +281,23 @@
- }
- },
-
-- _onMoveDrag: function(xy)
-+ _onMoveDrag: function(xy, e)
- {
-- var c_opt, caption, cname, d_cap, d_update,
-+ var c_opt, caption, cname, d_cap,
- d = DragDrop.Drops.drop,
-- div = DragDrop.Drags.div;
-+ div = DragDrop.Drags.div,
-+ d_update = true;
-
-- if (d && d.element != this.lastdrag) {
-- if (DragDrop.validDrop(this.element)) {
-- d_cap = d.options.caption;
-- if (d_cap) {
-- caption = Object.isFunction(d_cap) ? d_cap(d.element, this.element) : d_cap;
-- if (caption && d.options.hoverclass) {
-- cname = d.options.hoverclass;
-- }
-- d_update = true;
-+ if (d && DragDrop.validDrop(this.element)) {
-+ d_cap = d.options.caption;
-+ if (d_cap) {
-+ caption = Object.isFunction(d_cap) ? d_cap(d.element, this.element, e) : d_cap;
-+ if (caption && d.options.hoverclass) {
-+ cname = d.options.hoverclass;
- }
- } else {
-- d_update = true;
-+ d_update = false;
- }
-- this.lastdrag = d.element;
-- } else if ((!d && this.lastdrag) ||
-- (this.move == (this.options.threshold + 1))) {
-- d_update = true;
-- this.lastdrag = null;
- }
-
- if (d_update) {
-@@ -312,10 +305,12 @@
- c_opt = this.options.caption;
- caption = Object.isFunction(c_opt) ? c_opt(this.element) : c_opt;
- }
-- this.lastcaption = caption;
-- div.update(caption).writeAttribute({ className: cname || this.options.classname });
-- if (caption.empty()) {
-- div.hide();
-+ if (caption != this.lastcaption) {
-+ this.lastcaption = caption;
-+ div.update(caption).writeAttribute({ className: cname || this.options.classname });
-+ if (caption.empty()) {
-+ div.hide();
-+ }
- }
- }
-
-diff -Naur /kolab/var/kolab/www/client/dimp/lib/DIMP.php b/lib/DIMP.php
---- /kolab/var/kolab/www/client/dimp/lib/DIMP.php 2010-04-14 22:21:28.000000000 +0200
-+++ b/lib/DIMP.php 2010-04-14 22:20:38.000000000 +0200
-@@ -215,6 +215,7 @@
- 'showtext' => _("Show Quoted Text"),
- 'lines' => _("lines"),
- 'ok' => _("Ok"),
-+ 'copyto' => _("Copy %s to %s"),
- 'moveto' => _("Move %s to %s"),
- 'baselevel' => _("base level of the folder tree"),
- 'cancel' => _("Cancel"),
diff --git a/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_MS_FixBrokenFolderImages.diff b/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_MS_FixBrokenFolderImages.diff
deleted file mode 100644
index de5686d..0000000
--- a/kolab-webclient/dimp/patches/dimp-1.1.6/t_dimp_H_MS_FixBrokenFolderImages.diff
+++ /dev/null
@@ -1,2235 +0,0 @@
-From: Gunnar Wrobel <p at rdus.de>
-Subject: [PATCH] t/dimp/H/MS/FixBrokenFolderImages
-
-Fixes broken custom folder images within DIMP.
-
-http://bugs.horde.org/ticket/7831
-
-https://www.intevation.de/roundup/kolab/issue3328
-
-STATUS: MERGED in HEAD but not in FRAMEWORK_3
-
-Signed-off-by: Gunnar Wrobel <p at rdus.de>
-
----
- /js/DimpBase.js | 2149 ++++++++++++++++++++++++++++++++-
- js/src/DimpBase.js | 2 +-
- lib/DIMP.php | 9 +-
- themes/screen.css | 2 +-
- 4 files changed, 2157 insertions(+), 5 deletions(-)
-
-diff --git a/js/DimpBase.js b/js/DimpBase.js
-new file mode 100644
-index 0000000..96cd917
---- /dev/null
-+++ b/js/DimpBase.js
-@@ -0,0 +1,2146 @@
-+/**
-+ * DimpBase.js - Javascript used in the base DIMP page.
-+ *
-+ * $Horde: dimp/js/src/DimpBase.js,v 1.1.2.118 2009-05-20 18:27:51 slusarz Exp $
-+ *
-+ * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
-+ *
-+ * See the enclosed file COPYING for license information (GPL). If you
-+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
-+ */
-+
-+var DimpBase = {
-+ // Vars used and defaulting to null/false:
-+ // filtertoggle, fl_visible, folder, folderswitch, fspecial, isvisible,
-+ // message_list_template, offset, pollpe, pp, searchobserve, uid,
-+ // viewport
-+ bcache: $H(),
-+ delay_onload: (!Prototype.Browser.Gecko && !Prototype.Browser.Opera),
-+ lastrow: -1,
-+ mo_sidebar: $H(),
-+ pivotrow: -1,
-+ ppcache: $H(),
-+ ppfifo: [],
-+ showPreview: DIMP.conf.preview_pref,
-+
-+ sfiltersfolder: $H({ sf_all: 'all', sf_current: 'current' }),
-+ sfilters: $H({ sf_msgall: 'msgall', sf_from: 'from', sf_to: 'to', sf_subject: 'subject' }),
-+
-+ unseen_regex: new RegExp("(^|\\s)unseen(\\s|$)"),
-+
-+ // Message selection functions
-+
-+ // vs = (ViewPort_Selection) A ViewPort_Selection object.
-+ // opts = (object) Boolean options [delay, right]
-+ _select: function(vs, opts)
-+ {
-+ var d = vs.get('rownum');
-+ if (d.size() == 1) {
-+ this.lastrow = this.pivotrow = d.first();
-+ }
-+
-+ this.toggleButtons();
-+
-+ if ($('previewPane').visible()) {
-+ if (opts.right) {
-+ this.clearPreviewPane();
-+ } else {
-+ if (opts.delay) {
-+ (this.bcache.get('initPP') || this.bcache.set('initPP', this.initPreviewPane.bind(this))).delay(opts.delay);
-+ } else {
-+ this.initPreviewPane();
-+ }
-+ }
-+ }
-+ },
-+
-+ // vs = (ViewPort_Selection) A ViewPort_Selection object.
-+ // opts = (object) Boolean options [right]
-+ _deselect: function(vs, opts)
-+ {
-+ var sel = this.viewport.getSelected(),
-+ count = sel.size();
-+ if (!count) {
-+ this.lastrow = this.pivotrow = -1;
-+ }
-+
-+ this.toggleButtons();
-+ if (opts.right || !count) {
-+ this.clearPreviewPane();
-+ } else if ((count == 1) && $('previewPane').visible()) {
-+ this._loadPreview(sel.get('dataob').first());
-+ }
-+ },
-+
-+ // id = (string) DOM ID
-+ // opts = (Object) Boolean options [ctrl, right, shift]
-+ msgSelect: function(id, opts)
-+ {
-+ var bounds,
-+ row = this.viewport.createSelection('domid', id),
-+ rownum = row.get('rownum').first(),
-+ sel = this.isSelected('domid', id),
-+ selcount = this.selectedCount();
-+
-+ this.lastrow = rownum;
-+
-+ // Some browsers need to stop the mousedown event before it propogates
-+ // down to the browser level in order to prevent text selection on
-+ // drag/drop actions. Clicking on a message should always lose focus
-+ // from the search input, because the user may immediately start
-+ // keyboard navigation after that. Thus, we need to ensure that a
-+ // message click loses focus on the search input.
-+ $('msgList_filter').blur();
-+
-+ if (opts.shift) {
-+ if (selcount) {
-+ if (!sel || selcount != 1) {
-+ bounds = [ rownum, this.pivotrow ];
-+ this.viewport.select($A($R(bounds.min(), bounds.max())), { range: true });
-+ }
-+ return;
-+ }
-+ } else if (opts.ctrl) {
-+ this.pivotrow = rownum;
-+ if (sel) {
-+ this.viewport.deselect(row, { right: opts.right });
-+ return;
-+ } else if (opts.right || selcount) {
-+ this.viewport.select(row, { add: true, right: opts.right });
-+ return;
-+ }
-+ }
-+
-+ this.viewport.select(row, { right: opts.right });
-+ },
-+
-+ selectAll: function()
-+ {
-+ this.viewport.select($A($R(1, this.viewport.getMetaData('total_rows'))), { range: true });
-+ },
-+
-+ isSelected: function(format, data)
-+ {
-+ return this.viewport.getSelected().contains(format, data);
-+ },
-+
-+ selectedCount: function()
-+ {
-+ return (this.viewport) ? this.viewport.getSelected().size() : 0;
-+ },
-+
-+ resetSelected: function()
-+ {
-+ if (this.viewport) {
-+ this.viewport.deselect(this.viewport.getSelected(), { clearall: true });
-+ }
-+ this.toggleButtons();
-+ this.clearPreviewPane();
-+ },
-+
-+ // absolute = Is num an absolute row number - from 1 -> page_size (true) -
-+ // or a relative change from the current selected value (false)
-+ // If no current selected value, the first message in the
-+ // current viewport is selected.
-+ moveSelected: function(num, absolute)
-+ {
-+ var curr, curr_row, row, row_data, sel;
-+
-+ if (absolute) {
-+ if (!this.viewport.getMetaData('total_rows')) {
-+ return;
-+ }
-+ curr = num;
-+ } else {
-+ if (num == 0) {
-+ return;
-+ }
-+
-+ sel = this.viewport.getSelected();
-+ switch (sel.size()) {
-+ case 0:
-+ curr = this.viewport.currentOffset();
-+ curr += (num > 0) ? 1 : this.viewport.getPageSize('current');
-+ break;
-+
-+ case 1:
-+ curr_row = sel.get('dataob').first();
-+ curr = curr_row.rownum + num;
-+ break;
-+
-+ default:
-+ sel = sel.get('rownum');
-+ curr = (num > 0 ? sel.max() : sel.min()) + num;
-+ break;
-+ }
-+ curr = (num > 0) ? Math.min(curr, this.viewport.getMetaData('total_rows')) : Math.max(curr, 1);
-+ }
-+
-+ row = this.viewport.createSelection('rownum', curr);
-+ if (row.size()) {
-+ row_data = row.get('dataob').first();
-+ if (!curr_row || row_data.imapuid != curr_row.imapuid) {
-+ this.viewport.scrollTo(row_data.rownum);
-+ this.viewport.select(row, { delay: 0.3 });
-+ }
-+ } else {
-+ this.offset = curr;
-+ this.viewport.requestContentRefresh(curr - 1);
-+ }
-+ },
-+ // End message selection functions
-+
-+ go: function(loc, data)
-+ {
-+ var app, f, separator;
-+
-+ if (loc.startsWith('compose:')) {
-+ return;
-+ }
-+
-+ if (loc.startsWith('msg:')) {
-+ separator = loc.indexOf(':', 4);
-+ f = loc.substring(4, separator);
-+ this.uid = loc.substring(separator + 1);
-+ loc = 'folder:' + f;
-+ // Now fall through to the 'folder:' check below.
-+ }
-+
-+ if (loc.startsWith('folder:')) {
-+ f = loc.substring(7);
-+ if (this.folder != f || !$('dimpmain_folder').visible()) {
-+ this.highlightSidebar(this.getFolderId(f));
-+ if (!$('dimpmain_folder').visible()) {
-+ $('dimpmain_portal').hide();
-+ $('dimpmain_folder').show();
-+ }
-+ // This catches the refresh case - no need to re-add to history
-+ if (!Object.isUndefined(this.folder)) {
-+ this._addHistory(loc);
-+ }
-+ }
-+ this.loadFolder(f);
-+ return;
-+ }
-+
-+ this.folder = null;
-+ $('dimpmain_folder').hide();
-+ $('dimpmain_portal').update(DIMP.text.loading).show();
-+
-+ if (loc.startsWith('app:')) {
-+ app = loc.substr(4);
-+ if (app == 'imp' || app == 'dimp') {
-+ this.go('folder:INBOX');
-+ return;
-+ }
-+ this.highlightSidebar('app' + app);
-+ this._addHistory(loc, data);
-+ if (data) {
-+ this.iframeContent(loc, data);
-+ } else if (DIMP.conf.app_urls[app]) {
-+ this.iframeContent(loc, DIMP.conf.app_urls[app]);
-+ }
-+ return;
-+ }
-+
-+ switch (loc) {
-+ case 'portal':
-+ this.highlightSidebar('appportal');
-+ this._addHistory(loc);
-+ DimpCore.setTitle(DIMP.text.portal);
-+ DimpCore.doAction('ShowPortal', {}, [], this.bcache.get('portalC') || this.bcache.set('portalC', this._portalCallback.bind(this)));
-+ break;
-+
-+ case 'options':
-+ this.highlightSidebar('appoptions');
-+ this._addHistory(loc);
-+ DimpCore.setTitle(DIMP.text.prefs);
-+ this.iframeContent(loc, DIMP.conf.prefs_url);
-+ break;
-+ }
-+ },
-+
-+ _addHistory: function(loc, data)
-+ {
-+ if (Horde.dhtmlHistory.getCurrentLocation() != loc) {
-+ Horde.dhtmlHistory.add(loc, data);
-+ }
-+ },
-+
-+ highlightSidebar: function(id)
-+ {
-+ // Folder bar may not be fully loaded yet.
-+ if ($('foldersLoading').visible()) {
-+ this.highlightSidebar.bind(this, id).defer();
-+ return;
-+ }
-+
-+ $('sidebarPanel').select('.on').invoke('removeClassName', 'on');
-+
-+ var elt = $(id);
-+ if (!elt) {
-+ return;
-+ }
-+ if (!elt.match('LI')) {
-+ elt = elt.up();
-+ if (!elt) {
-+ return;
-+ }
-+ }
-+ elt.addClassName('on');
-+
-+ // Make sure all subfolders are expanded
-+ elt.ancestors().find(function(n) {
-+ if (n.hasClassName('subfolders')) {
-+ this._toggleSubFolder(n.id.substring(3), 'exp');
-+ } else {
-+ return (n.id == 'foldersSidebar');
-+ }
-+ }, this);
-+ },
-+
-+ iframeContent: function(name, loc)
-+ {
-+ if (name === null) {
-+ name = loc;
-+ }
-+
-+ var container = $('dimpmain_portal'), iframe;
-+ if (!container) {
-+ DimpCore.showNotifications([ { type: 'horde.error', message: 'Bad portal!' } ]);
-+ return;
-+ }
-+
-+ iframe = new Element('IFRAME', { id: 'iframe' + name, className: 'iframe', frameBorder: 0, src: loc });
-+ this._resizeIE6Iframe(iframe);
-+
-+ // Hide menu in prefs pages.
-+ if (name == 'options') {
-+ iframe.observe('load', function() { $('iframeoptions').contentWindow.document.getElementById('menu').style.display = 'none'; });
-+ }
-+
-+ container.insert(iframe);
-+ },
-+
-+ // r = ViewPort row data
-+ msgWindow: function(r)
-+ {
-+ this.updateUnseenUID(r, 0);
-+ var url = DIMP.conf.message_url;
-+ url += (url.include('?') ? '&' : '?') +
-+ $H({ folder: r.view,
-+ uid: r.imapuid }).toQueryString();
-+ DimpCore.popupWindow(url, 'msgview' + r.view + r.imapuid);
-+ },
-+
-+ composeMailbox: function(type)
-+ {
-+ var sel = this.viewport.getSelected();
-+ if (!sel.size()) {
-+ return;
-+ }
-+ sel.get('dataob').each(function(s) {
-+ DimpCore.compose(type, { folder: s.view, uid: s.imapuid });
-+ });
-+ },
-+
-+ loadFolder: function(f, background)
-+ {
-+ if (!this.viewport) {
-+ this._createViewPort();
-+ }
-+
-+ if (!background) {
-+ this.resetSelected();
-+
-+ if (this.folder == f) {
-+ this.searchfilterClear(false);
-+ return;
-+ }
-+
-+ this.searchfilterClear(true);
-+ $('folderName').update(DIMP.text.loading);
-+ $('msgHeader').update();
-+ this.folderswitch = true;
-+ this.folder = f;
-+ }
-+
-+ this.viewport.loadView(f, { folder: f }, this.uid ? { imapuid: DimpCore.toUIDString(this.uid, f) } : null, background);
-+ },
-+
-+ _createViewPort: function()
-+ {
-+ var mf = $('msgList_filter'),
-+ // No need to cache - this function only called once.
-+ settitle = this.setMessageListTitle.bind(this);
-+
-+ this.viewport = new ViewPort({
-+ content_container: 'msgList',
-+ empty_container: 'msgList_empty',
-+ error_container: 'msgList_error',
-+ fetch_action: 'ListMessages',
-+ template: this.message_list_template,
-+ buffer_pages: DIMP.conf.buffer_pages,
-+ limit_factor: DIMP.conf.limit_factor,
-+ viewport_wait: DIMP.conf.viewport_wait,
-+ show_split_pane: this.showPreview,
-+ split_pane: 'previewPane',
-+ splitbar: 'splitBar',
-+ content_class: 'msglist',
-+ row_class: 'msgRow',
-+ selected_class: 'selectedRow',
-+ ajaxRequest: DimpCore.doAction.bind(DimpCore),
-+ norows: true,
-+ onScrollIdle: settitle,
-+ onSlide: settitle,
-+ onViewChange: function() {
-+ DimpCore.addGC(this.viewport.visibleRows());
-+ }.bind(this),
-+ onContent: function(rows) {
-+ var mf, search,
-+ thread = ((this.viewport.getMetaData('sortby') == DIMP.conf.sortthread) && this.viewport.getMetaData('thread'));
-+ if (this.viewport.isFiltering()) {
-+ search = this.sfilters.get(this._getSearchfilterField()).capitalize();
-+ mf = new RegExp("(" + $F('msgList_filter') + ")", "i");
-+ }
-+ rows.get('dataob').each(function(row) {
-+ var elt, tmp, u,
-+ r = $(row.domid);
-+ // Add thread graphics
-+ if (thread && thread[row.imapuid]) {
-+ elt = r.down('.msgSubject');
-+ tmp = elt.cloneNode(false);
-+ u = thread[row.imapuid];
-+ $R(0, u.length, true).each(function(i) {
-+ tmp.insert($($('thread_img_' + u.charAt(i)).cloneNode(false)).writeAttribute('id', ''));
-+ });
-+ elt.replace(tmp.insert(elt.getText().escapeHTML()));
-+ }
-+ // Add attachment graphics
-+ if (row.atc) {
-+ r.down('.msgSize').insert({ top: $($('atc_img_' + row.atc).cloneNode(false)).writeAttribute('id', '') });
-+ }
-+
-+ // Add context menu.
-+ DimpCore.addMouseEvents({ id: row.domid, type: row.menutype });
-+
-+ // Highlight search terms
-+ if (search == 'From' || search == 'Subject') {
-+ elt = r.down('.msg' + search);
-+ elt.update(elt.getText().escapeHTML().gsub(mf, '<span class="searchMatch">#{1}</span>'));
-+ }
-+ }, this);
-+ this.setMessageListTitle();
-+ }.bind(this),
-+ onComplete: function() {
-+ var row, ssc,
-+ l = this.viewport.getMetaData('label');
-+
-+ if (this.uid) {
-+ row = this.viewport.getViewportSelection().search({ imapuid: { equal: [ this.uid ] }, view: { equal: [ this.folder ] } });
-+ if (row.size()) {
-+ this.viewport.scrollTo(row.get('rownum').first());
-+ this.viewport.select(row);
-+ }
-+ } else if (this.offset) {
-+ this.viewport.select(this.viewport.createSelection('rownum', this.offset));
-+ }
-+ this.offset = this.uid = null;
-+
-+ // 'label' will not be set if there has been an error
-+ // retrieving data from the server.
-+ l = this.viewport.getMetaData('label');
-+ if (l) {
-+ $('folderName').update(l);
-+ }
-+
-+ if (this.folderswitch) {
-+ this.folderswitch = false;
-+ if (this.folder == DIMP.conf.spam_folder) {
-+ if (!DIMP.conf.spam_spamfolder &&
-+ DimpCore.buttons.indexOf('button_spam') != -1) {
-+ [ $('button_spam').up(), $('ctx_message_spam') ].invoke('hide');
-+ }
-+ if (DimpCore.buttons.indexOf('button_ham') != -1) {
-+ [ $('button_ham').up(), $('ctx_message_ham') ].invoke('show');
-+ }
-+ } else {
-+ if (DimpCore.buttons.indexOf('button_spam') != -1) {
-+ [ $('button_spam').up(), $('ctx_message_spam') ].invoke('show');
-+ }
-+ if (DimpCore.buttons.indexOf('button_ham') != -1) {
-+ if (DIMP.conf.ham_spamfolder) {
-+ [ $('button_ham').up(), $('ctx_message_ham') ].invoke('hide');
-+ } else {
-+ [ $('button_ham').up(), $('ctx_message_ham') ].invoke('show');
-+ }
-+ }
-+ }
-+ } else if (this.filtertoggle) {
-+ if (this.filtertoggle == 1 &&
-+ this.viewport.getMetaData('sortby') == DIMP.conf.sortthread) {
-+ ssc = DIMP.conf.sortdate;
-+ }
-+ this.filtertoggle = 0;
-+ }
-+
-+ this.setSortColumns(ssc);
-+
-+ if (this.viewport.isFiltering()) {
-+ this.resetSelected();
-+ this.updateTitle();
-+ } else {
-+ this.setFolderLabel(this.folder, this.viewport.getMetaData('unseen'));
-+ }
-+ }.bind(this),
-+ onFetch: this.msgListLoading.bind(this, true),
-+ onEndFetch: this.msgListLoading.bind(this, false),
-+ onWait: function() {
-+ if ($('dimpmain_folder').visible()) {
-+ DimpCore.showNotifications([ { type: 'horde.warning', message: DIMP.text.listmsg_wait } ]);
-+ }
-+ },
-+ onFail: function() {
-+ if ($('dimpmain_folder').visible()) {
-+ DimpCore.showNotifications([ { type: 'horde.error', message: DIMP.text.listmsg_timeout } ]);
-+ }
-+ this.msgListLoading(false);
-+ }.bind(this),
-+ onFirstContent: function() {
-+ this.clearPreviewPane();
-+ $('msgList').observe('dblclick', this._handleMsgListDblclick.bindAsEventListener(this));
-+ }.bind(this),
-+ onClearRows: function(r) {
-+ r.each(function(row) {
-+ var c = $(row).down('div.msCheck');
-+ if (c) {
-+ DimpCore.addGC(c);
-+ }
-+ if (row.id) {
-+ DimpCore.removeMouseEvents(row);
-+ }
-+ });
-+ },
-+ onBeforeResize: function() {
-+ var sel = this.viewport.getSelected();
-+ this.isvisible = (sel.size() == 1) && (this.viewport.isVisible(sel.get('rownum').first()) == 0);
-+ }.bind(this),
-+ onAfterResize: function() {
-+ if (this.isvisible) {
-+ this.viewport.scrollTo(this.viewport.getSelected().get('rownum').first());
-+ }
-+ }.bind(this),
-+ selectCallback: this._select.bind(this),
-+ deselectCallback: this._deselect.bind(this)
-+ });
-+
-+ // If starting in no preview mode, need to set the no preview class
-+ if (!this.showPreview) {
-+ $('msgList').addClassName('msglistNoPreview');
-+ }
-+
-+ // 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');
-+ },
-+
-+ _addMouseEvents: function(parentfunc, p)
-+ {
-+ var elt;
-+
-+ switch (p.type) {
-+ case 'draft':
-+ case 'message':
-+ new Drag(p.id, this._msgDragConfig);
-+ elt = $(p.id).down('div.msCheck');
-+ if (elt.visible()) {
-+ elt.observe('mousedown', this.bcache.get('handleMLC') || this.bcache.set('handleMLC', this._handleMsgListCheckbox.bindAsEventListener(this)));
-+ elt.observe('contextmenu', Event.stop);
-+ }
-+ break;
-+
-+ case 'container':
-+ case 'folder':
-+ new Drag(p.id, this._folderDragConfig);
-+ break;
-+
-+ case 'special':
-+ // For purposes of the contextmenu, treat special folders
-+ // like regular folders.
-+ p.type = 'folder';
-+ break;
-+ }
-+ p.onShow = this.bcache.get('onMS') || this.bcache.set('onMS', this._onMenuShow.bind(this));
-+ parentfunc(p);
-+ },
-+
-+ _removeMouseEvents: function(parentfunc, elt)
-+ {
-+ var d, id = $(elt).readAttribute('id');
-+ if (id && (d = DragDrop.Drags.get_drag(id))) {
-+ d.destroy();
-+ }
-+ parentfunc(elt);
-+ },
-+
-+ _onMenuShow: function(ctx)
-+ {
-+ var elts, folder, ob, sel;
-+
-+ switch (ctx.ctx) {
-+ case 'ctx_folder':
-+ elts = $('ctx_folder_create', 'ctx_folder_rename', 'ctx_folder_delete');
-+ folder = DimpCore.DMenu.element();
-+ if (folder.readAttribute('mbox') == 'INBOX') {
-+ elts.invoke('hide');
-+ } else if (DIMP.conf.fixed_folders.indexOf(folder.readAttribute('mbox')) != -1) {
-+ elts.shift();
-+ elts.invoke('hide');
-+ } else {
-+ elts.invoke('show');
-+ }
-+
-+ if (folder.hasAttribute('u')) {
-+ $('ctx_folder_poll').hide();
-+ $('ctx_folder_nopoll').show();
-+ } else {
-+ $('ctx_folder_poll').show();
-+ $('ctx_folder_nopoll').hide();
-+ }
-+ break;
-+
-+ case 'ctx_message':
-+ [ $('ctx_message_reply_list') ].invoke( this.viewport.createSelection('domid', ctx.id).get('dataob').first().listmsg ? 'show' : 'hide');
-+ break;
-+
-+ case 'ctx_reply':
-+ sel = this.viewport.getSelected();
-+ if (sel.size() == 1) {
-+ ob = sel.get('dataob').first();
-+ }
-+ [ $('ctx_reply_reply_list') ].invoke(ob && ob.listmsg ? 'show' : 'hide');
-+ break;
-+
-+ case 'ctx_otheractions':
-+ $('oa_seen', 'oa_unseen', 'oa_flagged', 'oa_clear', 'oa_sep1', 'oa_blacklist', 'oa_whitelist', 'oa_sep2', 'oa_undelete').compact().invoke(this.viewport.getSelected().size() ? 'show' : 'hide');
-+ break;
-+ }
-+ return true;
-+ },
-+
-+ _onResize: function()
-+ {
-+ if (this.viewport) {
-+ this.viewport.onResize();
-+ }
-+ this._resizeIE6();
-+ },
-+
-+ _handleMsgListDblclick: function(e)
-+ {
-+ var elt = this._getMsgRow(e);
-+ if (!elt) {
-+ return;
-+ }
-+ var 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)
-+ {
-+ var elt = this._getMsgRow(e);
-+ if (!elt) {
-+ return;
-+ }
-+ this.msgSelect(elt.readAttribute('id'), { ctrl: true, right: true });
-+ e.stop();
-+ },
-+
-+ _getMsgRow: function(e)
-+ {
-+ e = e.element();
-+ if (e && !e.hasClassName('msgRow')) {
-+ e = e.up('.msgRow');
-+ }
-+ return e;
-+ },
-+
-+ updateTitle: function()
-+ {
-+ var elt, label, unseen;
-+ if (this.viewport.isFiltering()) {
-+ label = DIMP.text.search + ' :: ' + this.viewport.getMetaData('total_rows') + ' ' + DIMP.text.resfound;
-+ } else {
-+ elt = $(this.getFolderId(this.folder));
-+ if (elt) {
-+ unseen = elt.readAttribute('u');
-+ label = elt.readAttribute('l');
-+ if (unseen > 0) {
-+ label += ' (' + unseen + ')';
-+ }
-+ } else {
-+ label = this.viewport.getMetaData('label');
-+ }
-+ }
-+ DimpCore.setTitle(label);
-+ },
-+
-+ sort: function(e)
-+ {
-+ // Don't change sort if we are past the sortlimit
-+ if (this.viewport.getMetaData('sortlimit')) {
-+ return;
-+ }
-+
-+ var s, sortby,
-+ elt = e.element();
-+ if (!elt.hasAttribute('sortby')) {
-+ elt = elt.up('[sortby]');
-+ if (!elt) {
-+ return;
-+ }
-+ }
-+ sortby = parseInt(elt.readAttribute('sortby'), 10);
-+
-+ if (sortby == this.viewport.getMetaData('sortby')) {
-+ s = { sortdir: (this.viewport.getMetaData('sortdir') ? 0 : 1) };
-+ this.viewport.setMetaData({ sortdir: s.sortdir });
-+ } else {
-+ s = { sortby: sortby };
-+ this.viewport.setMetaData({ sortby: s.sortby });
-+ }
-+ this.setSortColumns(sortby);
-+ this.viewport.reload(s);
-+ },
-+
-+ setSortColumns: function(sortby)
-+ {
-+ var tmp,
-+ m = $('msglistHeader');
-+
-+ if (Object.isUndefined(sortby)) {
-+ sortby = this.viewport.getMetaData('sortby');
-+ }
-+
-+ tmp = m.down('small[sortby=' + sortby + ']');
-+ if (tmp && tmp.up().visible()) {
-+ tmp.up(1).childElements().invoke('toggle');
-+ }
-+
-+ tmp = m.down('div.msgFrom a');
-+ if ((this.viewport.isFiltering() && this.fspecial) ||
-+ this.viewport.getMetaData('special')) {
-+ tmp.hide().next().show();
-+ } else {
-+ tmp.show().next().hide();
-+ }
-+
-+ tmp = m.down('div.msgSubject a');
-+ if (this.viewport.isFiltering() ||
-+ this.viewport.getMetaData('nothread') ||
-+ this.viewport.getMetaData('sortlimit')) {
-+ tmp.show().next().hide();
-+ tmp.down().hide();
-+ } else {
-+ tmp.down().show();
-+ }
-+
-+ m.childElements().invoke('removeClassName', 'sortup').invoke('removeClassName', 'sortdown');
-+ m.down('div a[sortby=' + sortby + ']').up().addClassName(this.viewport.getMetaData('sortdir') ? 'sortup' : 'sortdown');
-+ },
-+
-+ // Preview pane functions
-+ togglePreviewPane: function()
-+ {
-+ this.showPreview = !this.showPreview;
-+ $('previewtoggle').setText(this.showPreview ? DIMP.text.hide_preview : DIMP.text.show_preview);
-+ [ $('msgList') ].invoke(this.showPreview ? 'removeClassName' : 'addClassName', 'msglistNoPreview');
-+ new Ajax.Request(DimpCore.addSID(DIMP.conf.URI_PREFS), { parameters: { app: 'dimp', pref: 'show_preview', value: this.showPreview ? 1 : 0 } });
-+ this.viewport.showSplitPane(this.showPreview);
-+ if (this.showPreview) {
-+ this.initPreviewPane();
-+ }
-+ this.updateTitle();
-+ },
-+
-+ _loadPreview: function(data)
-+ {
-+ var pp = $('previewPane'), pp_offset;
-+ if (!pp.visible()) {
-+ return;
-+ }
-+ if (this.pp &&
-+ this.pp == data) {
-+ return;
-+ }
-+ this.pp = data;
-+
-+ if (this.ppfifo.indexOf(data.vp_id) != -1) {
-+ return this._loadPreviewCallback(this.ppcache.get(data.vp_id));
-+ }
-+
-+ pp_offset = pp.positionedOffset();
-+ $('msgLoading').setStyle({ position: 'absolute', top: (pp_offset.top + 10) + 'px', left: (pp_offset.left + 10) + 'px' }).show();
-+
-+ DimpCore.doAction('ShowPreview', {}, DimpCore.toUIDArray(this.viewport.createSelection('dataob', data)), this.bcache.get('loadPC') || this.bcache.set('loadPC', this._loadPreviewCallback.bind(this)));
-+ },
-+
-+ _loadPreviewCallback: function(resp)
-+ {
-+ var row, search, tmp, tmp2,
-+ pm = $('previewMsg'),
-+ r = resp.response;
-+
-+ if (!r.error) {
-+ search = this.viewport.getViewportSelection(r.view).search({ vp_id: { equal: [ r.uid ] } });
-+ if (search.size()) {
-+ row = search.get('dataob').first();
-+ this.updateUnseenUID(row, 0);
-+ }
-+ }
-+
-+ if (this.pp &&
-+ this.pp.vp_id != r.uid) {
-+ return;
-+ }
-+
-+ if (r.error || this.viewport.getSelected().size() != 1) {
-+ if (r.error) {
-+ DimpCore.showNotifications([ { type: r.errortype, message: r.error } ]);
-+ }
-+ this.clearPreviewPane();
-+ return;
-+ }
-+
-+ // Store in cache.
-+ this._expirePPCache([ r.uid ]);
-+ this.ppcache.set(r.uid, resp);
-+ this.ppfifo.push(r.uid);
-+
-+ DimpCore.removeAddressLinks(pm);
-+
-+ DIMP.conf.msg_index = r.index;
-+ DIMP.conf.msg_folder = r.folder;
-+ DIMP.conf.msg_source_link = r.source_link;
-+
-+ // Add subject/priority
-+ tmp = pm.select('.subject');
-+ tmp.invoke('update', r.subject);
-+ switch (r.priority) {
-+ case 'high':
-+ case 'low':
-+ tmp.invoke('insert', { top: $($(r.priority + '_priority_img').cloneNode(false)).writeAttribute('id', false) });
-+ break;
-+ }
-+
-+ // Add from/date
-+ pm.select('.from').invoke('update', r.from);
-+ $('msgHeadersColl').select('.date').invoke('update', r.minidate);
-+ $('msgHeaderDate').select('.date').invoke('update', r.fulldate);
-+
-+ // Add to/cc
-+ [ 'to', 'cc' ].each(function(a) {
-+ if (r[a]) {
-+ pm.select('.' + a).invoke('update', r[a]);
-+ }
-+ [ $('msgHeader' + a.capitalize()) ].invoke(r[a] ? 'show' : 'hide');
-+ });
-+
-+ // Add attachment information
-+ $('msgHeadersColl').select('.attachmentImage').invoke(r.atc_label ? 'show' : 'hide');
-+ if (r.atc_label) {
-+ tmp = $('msgAtc').show().down('.label');
-+ tmp2 = $('partlist');
-+ tmp2.hide().previous().update(r.atc_label + ' ' + r.atc_download);
-+ if (r.atc_list) {
-+ $('partlist_col').show();
-+ $('partlist_exp').hide();
-+ tmp.down().hide().next().show();
-+ tmp2.update(r.atc_list);
-+ } else {
-+ tmp.down().show().next().hide();
-+ }
-+ } else {
-+ $('msgAtc').hide();
-+ }
-+
-+ $('msgBody').down().update(r.msgtext);
-+ $('msgLoading', 'previewInfo').invoke('hide');
-+ $('previewPane').scrollTop = 0;
-+ pm.show();
-+
-+ if (r.js) {
-+ eval(r.js.join(';'));
-+ }
-+ DimpCore.buildAddressLinks(pm);
-+ this._addHistory('msg:' + row.view + ':' + row.imapuid);
-+ },
-+
-+ initPreviewPane: function()
-+ {
-+ var sel = this.viewport.getSelected();
-+ if (sel.size() != 1) {
-+ this.clearPreviewPane();
-+ } else {
-+ this._loadPreview(sel.get('dataob').first());
-+ }
-+ },
-+
-+ clearPreviewPane: function()
-+ {
-+ $('msgLoading', 'previewMsg').invoke('hide');
-+ $('previewInfo').show();
-+ this.pp = null;
-+ },
-+
-+ _expirePPCache: function(ids)
-+ {
-+ this.ppfifo = this.ppfifo.without(ids);
-+ ids.each(this.ppcache.unset.bind(this.ppcache));
-+ // Preview pane cache size is 20 entries. Given that a reasonable guess
-+ // of an average e-mail size is 10 KB (including headers), also make
-+ // an estimate that the JSON data size will be approx. 10 KB. 200 KB
-+ // should be a fairly safe caching value for any recent browser.
-+ if (this.ppfifo.size() > 20) {
-+ this.ppcache.unset(this.ppfifo.shift());
-+ }
-+ },
-+
-+ // Labeling functions
-+ updateUnseenUID: function(r, setflag)
-+ {
-+ var sel, unseenset,
-+ unseen = 0;
-+ if (!r.bg) {
-+ return false;
-+ }
-+ unseenset = r.bg.match(this.unseen_regex);
-+ if ((setflag && unseenset) || (!setflag && !unseenset)) {
-+ return false;
-+ }
-+
-+ sel = this.viewport.createSelection('dataob', r);
-+ if (setflag) {
-+ this.viewport.updateFlag(sel, 'unseen', true);
-+ ++unseen;
-+ } else {
-+ this.viewport.updateFlag(sel, 'unseen', false);
-+ --unseen;
-+ }
-+
-+ return this.updateUnseenStatus(r.view, unseen);
-+ },
-+
-+ updateUnseenStatus: function(mbox, change)
-+ {
-+ if (change == 0) {
-+ return false;
-+ }
-+ var unseen = parseInt($(this.getFolderId(mbox)).readAttribute('u')) + change;
-+ this.viewport.setMetaData({ unseen: unseen });
-+ this.setFolderLabel(mbox, unseen);
-+ return true;
-+ },
-+
-+ setMessageListTitle: function()
-+ {
-+ var offset,
-+ rows = this.viewport.getMetaData('total_rows');
-+ if (rows > 0) {
-+ offset = this.viewport.currentOffset();
-+ $('msgHeader').update(DIMP.text.messages + ' ' + (offset + 1) + ' - ' + (Math.min(offset + this.viewport.getPageSize(), rows)) + ' ' + DIMP.text.of + ' ' + rows);
-+ } else {
-+ $('msgHeader').update(DIMP.text.nomessages);
-+ }
-+ },
-+
-+ setFolderLabel: function(f, unseen)
-+ {
-+ var elt, fid = this.getFolderId(f);
-+ elt = $(fid);
-+ if (!elt || !elt.hasAttribute('u')) {
-+ return;
-+ }
-+
-+ unseen = parseInt(unseen);
-+ elt.writeAttribute('u', unseen);
-+
-+ if (f == 'INBOX' && window.fluid) {
-+ window.fluid.setDockBadge(unseen ? unseen : '');
-+ }
-+
-+ $(fid + '_label').update((unseen > 0) ?
-+ new Element('STRONG').insert(elt.readAttribute('l')).insert(' ').insert(new Element('SPAN', { className: 'count', dir: 'ltr' }).insert('(' + unseen + ')')) :
-+ elt.readAttribute('l'));
-+
-+ if (this.folder == f) {
-+ this.updateTitle();
-+ }
-+ },
-+
-+ getFolderId: function(f)
-+ {
-+ return 'fld' + decodeURIComponent(f).replace(/_/g,'__').replace(/\W/g, '_');
-+ },
-+
-+ getSubFolderId: function(f)
-+ {
-+ return 'sub' + f;
-+ },
-+
-+ /* Folder list updates. */
-+ pollFolders: function()
-+ {
-+ // Reset poll folder counter.
-+ this.setPollFolders();
-+ var args = {};
-+ if (this.folder && $('dimpmain_folder').visible()) {
-+ args = this.viewport.addRequestParams({});
-+ }
-+ $('button_checkmail').setText('[' + DIMP.text.check + ']');
-+ DimpCore.doAction('PollFolders', args, [], this.bcache.get('pollFC') || this.bcache.set('pollFC', this._pollFoldersCallback.bind(this)));
-+ },
-+
-+ _pollFoldersCallback: function(r)
-+ {
-+ r = r.response;
-+ if (r.poll) {
-+ $H(r.poll).each(function(u) {
-+ this.setFolderLabel(u.key, u.value);
-+ if (this.viewport) {
-+ this.viewport.setMetaData({ unseen: u.value }, u.key);
-+ }
-+ }, this);
-+ }
-+ if (r.quota) {
-+ $('quota').update(r.quota);
-+ }
-+ $('button_checkmail').setText(DIMP.text.getmail);
-+ },
-+
-+ setPollFolders: function()
-+ {
-+ if (DIMP.conf.refresh_time) {
-+ if (this.pollPE) {
-+ this.pollPE.stop();
-+ }
-+ // Don't cache - this code is only run once.
-+ this.pollPE = new PeriodicalExecuter(this.pollFolders.bind(this), DIMP.conf.refresh_time);
-+ }
-+ },
-+
-+ _portalCallback: function(r)
-+ {
-+ if (r.response.linkTags) {
-+ var head = $$('HEAD').first();
-+ r.response.linkTags.each(function(newLink) {
-+ var link = new Element('LINK', { type: 'text/css', rel: 'stylesheet', href: newLink.href });
-+ if (newLink.media) {
-+ link.media = newLink.media;
-+ }
-+ head.insert(link);
-+ });
-+ }
-+ $('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);
-+ }
-+ this.searchobserve = (this.bcache.get('searchfilterR') || this.bcache.set('searchfilterR', this.searchfilterRun.bind(this))).delay(0.5);
-+ },
-+
-+ searchfilterRun: function()
-+ {
-+ if (!this.viewport.isFiltering()) {
-+ this.filtertoggle = 1;
-+ this.fspecial = this.viewport.getMetaData('special');
-+ }
-+ this.viewport.runFilter($F('msgList_filter'));
-+ },
-+
-+ _searchfilterOnFocus: function()
-+ {
-+ var q = $('qoptions');
-+
-+ if ($('msgList_filter').hasClassName('msgFilterDefault')) {
-+ this._setFilterText(false);
-+ }
-+
-+ if (!q.visible()) {
-+ $('sf_current').update(this.viewport.getMetaData('label'));
-+ this._setSearchfilterParams(this.viewport.getMetaData('special') ? 'to' : 'from', 'msg');
-+ this._setSearchfilterParams('current', 'folder');
-+ q.show();
-+ this.viewport.onResize();
-+ }
-+ },
-+
-+ _searchfilterOnBlur: function()
-+ {
-+ if (!$F('msgList_filter')) {
-+ this._setFilterText(true);
-+ }
-+ },
-+
-+ // reset = (boolean) TODO
-+ searchfilterClear: function(reset)
-+ {
-+ if (!$('qoptions').visible()) {
-+ return;
-+ }
-+ if (this.searchobserve) {
-+ clearTimeout(this.searchobserve);
-+ this.searchobserve = null;
-+ }
-+ this._setFilterText(true);
-+ $('qoptions').hide();
-+ this.filtertoggle = 2;
-+ this.resetSelected();
-+ this.viewport.onResize(reset);
-+ this.viewport.stopFilter(reset);
-+ },
-+
-+ // d = (boolean) Deactivate filter input?
-+ _setFilterText: function(d)
-+ {
-+ var mf = $('msgList_filter');
-+ if (d) {
-+ mf.setValue(DIMP.text.search);
-+ mf.addClassName('msgFilterDefault');
-+ } else {
-+ mf.setValue('');
-+ mf.removeClassName('msgFilterDefault');
-+ }
-+ },
-+
-+ // type = 'folder' or 'msg'
-+ _setSearchfilterParams: function(id, type)
-+ {
-+ var c = (type == 'folder') ? this.sfiltersfolder : this.sfilters;
-+ c.keys().each(function(i) {
-+ $(i).writeAttribute('className', (id == c.get(i)) ? 'qselected' : '');
-+ });
-+ },
-+
-+ updateSearchfilter: function(id, type)
-+ {
-+ this._setSearchfilterParams(id, type);
-+ if ($F('msgList_filter')) {
-+ this.viewport.runFilter();
-+ }
-+ },
-+
-+ _addSearchfilterParams: function()
-+ {
-+ var sf = this.sfiltersfolder.keys().find(function(s) {
-+ return $(s).hasClassName('qselected');
-+ });
-+ return { searchfolder: this.sfiltersfolder.get(sf), searchmsg: this.sfilters.get(this._getSearchfilterField()) };
-+ },
-+
-+ _getSearchfilterField: function()
-+ {
-+ return this.sfilters.keys().find(function(s) {
-+ return $(s).hasClassName('qselected');
-+ });
-+ },
-+
-+ /* Enable/Disable DIMP action buttons as needed. */
-+ toggleButtons: function()
-+ {
-+ var disable = (this.selectedCount() == 0);
-+ DimpCore.buttons.each(function(b) {
-+ var elt = $(b);
-+ if (elt) {
-+ [ elt.up() ].invoke(disable ? 'addClassName' : 'removeClassName', 'disabled');
-+ DimpCore.DMenu.disable(b + '_img', true, disable);
-+ }
-+ });
-+ },
-+
-+ /* Drag/Drop handler. */
-+ _folderDropHandler: function(drop, drag)
-+ {
-+ var dropbase, sel, uids,
-+ foldername = drop.readAttribute('mbox'),
-+ ftype = drop.readAttribute('ftype');
-+
-+ if (drag.hasClassName('folder')) {
-+ dropbase = (drop == $('dropbase'));
-+ if (dropbase ||
-+ (ftype != 'special' && !this.isSubfolder(drag, drop))) {
-+ DimpCore.doAction('RenameFolder', { old_name: drag.readAttribute('mbox'), new_parent: dropbase ? '' : foldername, new_name: drag.readAttribute('l') }, [], this.bcache.get('folderC') || this.bcache.set('folderC', this._folderCallback.bind(this)));
-+ }
-+ } else if (ftype != 'container') {
-+ sel = this.viewport.getSelected();
-+
-+ if (sel.size()) {
-+ // Dragging multiple selected messages.
-+ uids = sel;
-+ } else if (drag.readAttribute('mbox') != foldername) {
-+ // Dragging a single unselected message.
-+ uids = this.viewport.createSelection('domid', drag.id);
-+ }
-+
-+ // Don't allow drag/drop to the current folder.
-+ if (uids.size() && this.folder != foldername) {
-+ this.viewport.updateFlag(uids, 'deletedmsg', true);
-+ DimpCore.doAction('MoveMessage', this.viewport.addRequestParams({ tofld: foldername }), DimpCore.toUIDArray(uids), this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)));
-+ }
-+ }
-+ },
-+
-+ _dragCaption: function()
-+ {
-+ var cnt = this.selectedCount();
-+ return cnt + ' ' + (cnt == 1 ? DIMP.text.message : DIMP.text.messages);
-+ },
-+
-+ /* Keydown event handler */
-+ _keydownHandler: function(e)
-+ {
-+ // Only catch keyboard shortcuts in message list view. Disable catching
-+ // when in form elements or the RedBox overlay is visible.
-+ if (!$('dimpmain_folder').visible() ||
-+ e.findElement('FORM') ||
-+ RedBox.overlayVisible()) {
-+ return;
-+ }
-+
-+ var co, ps, r, row, rowoff,
-+ kc = e.keyCode || e.charCode,
-+ sel = this.viewport.getSelected();
-+
-+ switch (kc) {
-+ case Event.KEY_DELETE:
-+ case Event.KEY_BACKSPACE:
-+ r = sel.get('dataob');
-+ if (e.shiftKey) {
-+ this.moveSelected((r.last().rownum == this.viewport.getMetaData('total_rows')) ? (r.first().rownum - 1) : (r.last().rownum + 1), true);
-+ }
-+ this.flag('deleted', r);
-+ e.stop();
-+ break;
-+
-+ case Event.KEY_UP:
-+ case Event.KEY_DOWN:
-+ if (e.shiftKey && this.lastrow != -1) {
-+ row = this.viewport.createSelection('rownum', this.lastrow + ((kc == Event.KEY_UP) ? -1 : 1));
-+ if (row.size()) {
-+ row = row.get('dataob').first();
-+ this.viewport.scrollTo(row.rownum);
-+ this.msgSelect(row.domid, { shift: true });
-+ }
-+ } else {
-+ this.moveSelected(kc == Event.KEY_UP ? -1 : 1);
-+ }
-+ e.stop();
-+ break;
-+
-+ case Event.KEY_PAGEUP:
-+ case Event.KEY_PAGEDOWN:
-+ if (!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey) {
-+ ps = this.viewport.getPageSize() - 1;
-+ move = ps * (kc == Event.KEY_PAGEUP ? -1 : 1);
-+ if (sel.size() == 1) {
-+ co = this.viewport.currentOffset();
-+ rowoff = sel.get('rownum').first() - 1;
-+ switch (kc) {
-+ case Event.KEY_PAGEUP:
-+ if (co != rowoff) {
-+ move = co - rowoff;
-+ }
-+ break;
-+
-+ case Event.KEY_PAGEDOWN:
-+ if ((co + ps) != rowoff) {
-+ move = co + ps - rowoff;
-+ }
-+ break;
-+ }
-+ }
-+ this.moveSelected(move);
-+ e.stop();
-+ }
-+ break;
-+
-+ case Event.KEY_HOME:
-+ case Event.KEY_END:
-+ this.moveSelected(kc == Event.KEY_HOME ? 1 : this.viewport.getMetaData('total_rows'), true);
-+ e.stop();
-+ break;
-+
-+ case Event.KEY_RETURN:
-+ if (!e.element().match('input')) {
-+ // Popup message window if single message is selected.
-+ if (sel.size() == 1) {
-+ this.msgWindow(sel.get('dataob').first());
-+ }
-+ }
-+ e.stop();
-+ break;
-+
-+ case 65: // A
-+ case 97: // a
-+ if (e.ctrlKey) {
-+ this.selectAll();
-+ e.stop();
-+ }
-+ break;
-+ }
-+ },
-+
-+ /* Handle rename folder actions. */
-+ renameFolder: function(folder)
-+ {
-+ if (Object.isUndefined(folder)) {
-+ return;
-+ }
-+
-+ folder = $(folder);
-+ var n = this._createFolderForm(function(e) { this._folderAction(folder, e, 'rename'); return false; }.bindAsEventListener(this), DIMP.text.rename_prompt);
-+ n.down('input').setValue(folder.readAttribute('l'));
-+ },
-+
-+ /* Handle insert folder actions. */
-+ createBaseFolder: function()
-+ {
-+ this._createFolderForm(function(e) { this._folderAction('', e, 'create'); return false; }.bindAsEventListener(this), DIMP.text.create_prompt);
-+ },
-+
-+ createSubFolder: function(folder)
-+ {
-+ if (Object.isUndefined(folder)) {
-+ return false;
-+ }
-+
-+ this._createFolderForm(function(e) { this._folderAction($(folder), e, 'createsub'); return false; }.bindAsEventListener(this), DIMP.text.createsub_prompt);
-+ },
-+
-+ _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); } });
-+
-+ RedBox.overlay = true;
-+ RedBox.onDisplay = Form.focusFirstElement.curry(n);
-+ RedBox.showHtml(n);
-+ return n;
-+ },
-+
-+ _closeRedBox: function()
-+ {
-+ var c = RedBox.getWindowContents();
-+ DimpCore.addGC([ c, c.descendants() ].flatten());
-+ RedBox.close();
-+ },
-+
-+ _folderAction: function(folder, e, mode)
-+ {
-+ this._closeRedBox();
-+
-+ var action, params, val,
-+ form = e.findElement('form');
-+ val = $F(form.down('input'));
-+
-+ if (val) {
-+ switch (mode) {
-+ case 'rename':
-+ if (folder.readAttribute('l') != val) {
-+ action = 'RenameFolder';
-+ params = { old_name: folder.readAttribute('mbox'),
-+ new_parent: folder.up().hasClassName('folderlist') ? '' : folder.up(1).previous().readAttribute('mbox'),
-+ new_name: val };
-+ }
-+ break;
-+
-+ case 'create':
-+ case 'createsub':
-+ action = 'CreateFolder';
-+ params = { folder: val };
-+ if (mode == 'createsub') {
-+ params.parent = folder.readAttribute('mbox');
-+ }
-+ break;
-+ }
-+ if (action) {
-+ DimpCore.doAction(action, params, [], this.bcache.get('folderC') || this.bcache.set('folderC', this._folderCallback.bind(this)));
-+ }
-+ }
-+ },
-+
-+ /* Folder action callback functions. */
-+ _folderCallback: function(r)
-+ {
-+ r = r.response;
-+ r.d.each(this.deleteFolder.bind(this));
-+ r.c.each(this.changeFolder.bind(this));
-+ r.a.each(this.createFolder.bind(this));
-+ },
-+
-+ _deleteCallback: function(r)
-+ {
-+ this.msgListLoading(false);
-+ this._pollFoldersCallback(r);
-+
-+ if (!r.response.uids ||
-+ r.response.folder != this.folder) {
-+ return;
-+ }
-+
-+ var search = this.viewport.getViewportSelection().search({ view: { equal: [ r.response.folder ] }, imapuid: { equal: r.response.uids[r.response.folder] } });
-+ if (search.size()) {
-+ if (r.response.remove) {
-+ this.viewport.remove(search, { cacheid: r.response.cacheid, noupdate: r.response.viewport });
-+ this._expirePPCache(search.get('uid'));
-+ } else {
-+ // Need this to catch spam deletions.
-+ this.viewport.updateFlag(search, 'deletedmsg', true);
-+ }
-+ }
-+ },
-+
-+ _emptyFolderCallback: function(r)
-+ {
-+ if (r.response.mbox) {
-+ if (this.folder == r.response.mbox) {
-+ this.viewport.reload();
-+ this.clearPreviewPane();
-+ }
-+ this.setFolderLabel(r.response.mbox, 0);
-+ }
-+ },
-+
-+ _flagAllCallback: function(r)
-+ {
-+ if (r.response.mbox) {
-+ this.setFolderLabel(r.response.mbox, r.response.u);
-+ }
-+ },
-+
-+ _folderLoadCallback: function(r)
-+ {
-+ this._folderCallback(r);
-+
-+ var elts = $('specialfolders', 'normalfolders').compact(),
-+ 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'));
-+ }
-+
-+ $('foldersLoading').hide();
-+ $('foldersSidebar').show();
-+
-+ // Fix for IE6 - which doesn't support max-height. We need to search
-+ // for height: 0px instead (comment in IE 6 CSS explains this is
-+ // needed for auto sizing).
-+ if (nfheight !== null ||
-+ (Prototype.Browser.IE &&
-+ Object.isUndefined(nfheight) &&
-+ (nf.getStyle('height') == '0px'))) {
-+ this._sizeFolderlist();
-+ Event.observe(window, 'resize', this._sizeFolderlist.bind(this));
-+ }
-+
-+ if (r.response.quota) {
-+ $('quota').update(r.response.quota);
-+ }
-+ },
-+
-+ _handleFolderMouseEvent: function(e, action)
-+ {
-+ var type,
-+ elt = e.element(),
-+ li = elt.up('.folder') || elt.up('.custom');
-+ if (!li) {
-+ return;
-+ }
-+ type = li.readAttribute('ftype');
-+
-+ switch (action) {
-+ case 'over':
-+ if (DIMP.conf.is_ie6) {
-+ li.addClassName('over');
-+ }
-+ if (type && !this.mo_sidebar.get(li.id)) {
-+ DimpCore.addMouseEvents({ id: li.id, type: type });
-+ this.mo_sidebar.set(li.id, 1);
-+ }
-+ break;
-+
-+ case 'out':
-+ li.removeClassName('over');
-+ break;
-+
-+ case 'click':
-+ if (elt.hasClassName('exp') || elt.hasClassName('col')) {
-+ this._toggleSubFolder(li.id, 'tog');
-+ } else {
-+ switch (type) {
-+ case 'container':
-+ e.stop();
-+ break;
-+
-+ case 'folder':
-+ case 'special':
-+ e.stop();
-+ return this.go('folder:' + li.readAttribute('mbox'));
-+ break;
-+ }
-+ }
-+ break;
-+ }
-+ },
-+
-+ _toggleSubFolder: function(base, mode)
-+ {
-+ base = $(base);
-+ var s = $(this.getSubFolderId(base.id));
-+ if (s &&
-+ (mode == 'tog' ||
-+ (mode == 'exp' && !s.visible()) ||
-+ (mode == 'col' && s.visible()))) {
-+ base.firstDescendant().writeAttribute({ className: s.toggle().visible() ? 'col' : 'exp' });
-+ }
-+ if (base.descendantOf('specialfolders')) {
-+ this._sizeFolderlist();
-+ }
-+ },
-+
-+ // Folder actions.
-+ // For format of the ob object, see DIMP::_createFolderElt().
-+ createFolder: function(ob)
-+ {
-+ var div, f_node, li, ll, parent_e,
-+ fid = this.getFolderId(ob.m),
-+ mbox = decodeURIComponent(ob.m),
-+ submboxid = this.getSubFolderId(fid),
-+ submbox = $(submboxid);
-+
-+ li = new Element('LI', { className: 'folder', id: fid, l: ob.l, mbox: mbox, ftype: ((ob.co) ? 'container' : ((ob.s) ? 'special' : 'folder')) });
-+
-+ div = new Element('DIV', { className: ob.cl || 'base', id: fid + '_div' });
-+ if (ob.i) {
-+ div.setStyle({ backgroundImage: 'url("' + ob.i + '")' });
-+ }
-+ if (ob.ch) {
-+ div.writeAttribute({ className: 'exp' }).observe('mouseover', this.bcache.get('mo_folder') || this.bcache.set('mo_folder', function(e) {
-+ e = e.element();
-+ if (DragDrop.Drags.drag && e.hasClassName('exp')) {
-+ this._toggleSubFolder(e.up(), 'exp');
-+ }
-+ }.bindAsEventListener(this)));
-+ }
-+
-+ li.insert(div).insert(new Element('A', { id: fid + '_label', title: ob.l }).insert(ob.l));
-+
-+ // Now walk through the parent <ul> to find the right place to
-+ // insert the new folder.
-+ if (submbox) {
-+ if (submbox.insert({ before: li }).visible()) {
-+ // If an expanded parent mailbox was deleted, we need to toggle
-+ // the icon accordingly.
-+ div.removeClassName('exp').addClassName('col');
-+ }
-+ } else {
-+ if (ob.s) {
-+ parent_e = $('specialfolders');
-+ } else {
-+ parent_e = $(this.getSubFolderId(this.getFolderId(ob.pa)));
-+ parent_e = (parent_e) ? parent_e.down('UL') : $('normalfolders');
-+ }
-+
-+ ll = mbox.toLowerCase();
-+ f_node = parent_e.childElements().find(function(node) {
-+ var nodembox = node.readAttribute('mbox');
-+ return nodembox &&
-+ (!ob.s || nodembox != 'INBOX') &&
-+ (ll < nodembox.toLowerCase());
-+ });
-+
-+ if (f_node) {
-+ f_node.insert({ before: li });
-+ } else {
-+ parent_e.insert(li);
-+ }
-+
-+ // Make sure the sub<mbox> ul is created if necessary.
-+ if (ob.ch) {
-+ li.insert({ after: new Element('LI', { className: 'subfolders', id: submboxid }).insert(new Element('UL')).hide() });
-+ }
-+ }
-+
-+ // Make the new folder a drop target.
-+ new Drop(li, this._folderDropConfig);
-+
-+ // Check for unseen messages
-+ if (ob.po) {
-+ li.writeAttribute('u', '');
-+ this.setFolderLabel(mbox, ob.u);
-+ }
-+ },
-+
-+ deleteFolder: function(folder)
-+ {
-+ var f = decodeURIComponent(folder), fid;
-+ if (this.folder == f) {
-+ this.go('folder:INBOX');
-+ }
-+
-+ fid = this.getFolderId(folder);
-+ this.deleteFolderElt(fid, true);
-+ },
-+
-+ changeFolder: function(ob)
-+ {
-+ var fid = this.getFolderId(ob.m),
-+ fdiv = $(fid + '_div'),
-+ oldexpand = fdiv && fdiv.hasClassName('col');
-+ this.deleteFolderElt(fid, !ob.ch);
-+ if (ob.co && this.folder == ob.m) {
-+ this.go('folder:INBOX');
-+ }
-+ this.createFolder(ob);
-+ if (ob.ch && oldexpand) {
-+ fdiv.removeClassName('exp').addClassName('col');
-+ }
-+ },
-+
-+ deleteFolderElt: function(fid, sub)
-+ {
-+ var f = $(fid);
-+ DimpCore.addGC($(f, fid + '_div', fid + '_label'));
-+ if (sub) {
-+ var submbox = $(this.getSubFolderId(fid));
-+ if (submbox) {
-+ submbox.remove();
-+ }
-+ }
-+ [ DragDrop.Drags.get_drag(fid), DragDrop.Drops.get_drop(fid) ].compact().invoke('destroy');
-+ DimpCore.removeMouseEvents(f);
-+ this.mo_sidebar.unset(fid, 1);
-+ DimpCore.addGC(f);
-+ if (this.viewport) {
-+ this.viewport.deleteView(fid);
-+ }
-+ f.remove();
-+ },
-+
-+ _sizeFolderlist: function()
-+ {
-+ var nf = $('normalfolders');
-+ nf.setStyle({ height: (document.viewport.getHeight() - nf.cumulativeOffset()[1] - 10) + 'px' });
-+ },
-+
-+ /* Flag actions for message list. */
-+ flag: function(action, index, folder)
-+ {
-+ var actionCall, args, vs,
-+ obs = [],
-+ unseenstatus = 1;
-+
-+ if (index) {
-+ if (Object.isUndefined(folder)) {
-+ vs = this.viewport.createSelection('dataob', index);
-+ } else {
-+ vs = this.viewport.getViewportSelection().search({ imapuid: { equal: [ index ] }, view: { equal: [ folder ] } });
-+ if (!vs.size() && folder != this.folder) {
-+ vs = this.viewport.getViewportSelection(folder).search({ imapuid: { equal: [ index ] } });
-+ }
-+ }
-+ } else {
-+ vs = this.viewport.getSelected();
-+ }
-+
-+ switch (action) {
-+ case 'allUnseen':
-+ case 'allSeen':
-+ DimpCore.doAction((action == 'allUnseen') ? 'MarkFolderUnseen' : 'MarkFolderSeen', { folder: folder }, [], this.bcache.get('flagAC') || this.bcache.set('flagAC', this._flagAllCallback.bind(this)));
-+ if (folder == this.folder) {
-+ this.viewport.updateFlag(this.createSelection('rownum', $A($R(1, this.viewport.getMetaData('total_rows')))), 'unseen', action == 'allUnseen');
-+ }
-+ break;
-+
-+ case 'deleted':
-+ case 'undeleted':
-+ case 'spam':
-+ case 'ham':
-+ case 'blacklist':
-+ case 'whitelist':
-+ if (!vs.size()) {
-+ break;
-+ }
-+
-+ // Make sure that any given row is not deleted more than once.
-+ // Need to explicitly mark here because message may already be
-+ // flagged deleted when we load page (i.e. switching to using
-+ // trash folder).
-+ if (action == 'deleted') {
-+ vs = vs.search({ isdel: { not: [ true ] } });
-+ if (!vs.size()) {
-+ break;
-+ }
-+ vs.set({ isdel: true });
-+ } else if (action == 'undeleted') {
-+ vs.set({ isdel: false });
-+ }
-+
-+ args = this.viewport.addRequestParams({});
-+ if (action == 'deleted' || action == 'undeleted') {
-+ this.viewport.updateFlag(vs, 'deletedmsg', action == 'deleted'); }
-+
-+ if (action == 'undeleted') {
-+ DimpCore.doAction('UndeleteMessage', args, DimpCore.toUIDArray(vs));
-+ } else {
-+ actionCall = { deleted: 'DeleteMessage', spam: 'ReportSpam', ham: 'ReportHam', blacklist: 'Blacklist', whitelist: 'Whitelist' };
-+ // This needs to be synchronous Ajax if we are calling from a
-+ // popup window because Mozilla will not correctly call the
-+ // callback function if the calling window has been closed.
-+ DimpCore.doAction(actionCall[action], args, DimpCore.toUIDArray(vs), this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)), { asynchronous: !(index && folder) });
-+
-+ // If reporting spam, to indicate to the user that something is
-+ // happening (since spam reporting may not be instantaneous).
-+ if (action == 'spam' || action == 'ham') {
-+ this.msgListLoading(true);
-+ }
-+ }
-+ break;
-+
-+ case 'unseen':
-+ case 'seen':
-+ if (!vs.size()) {
-+ break;
-+ }
-+ args = { folder: this.folder, messageFlag: '-seen' };
-+ if (action == 'seen') {
-+ unseenstatus = 0;
-+ args.messageFlag = 'seen';
-+ }
-+ vs.get('dataob').each(function(s) {
-+ if (this.updateUnseenUID(s, unseenstatus)) {
-+ obs.push(s);
-+ }
-+ }, this);
-+
-+ if (obs.size()) {
-+ DimpCore.doAction('MarkMessage', args, DimpCore.toUIDArray(this.viewport.createSelection('dataob', obs)));
-+ }
-+ break;
-+
-+ case 'flagged':
-+ case 'clear':
-+ if (!vs.size()) {
-+ break;
-+ }
-+ args = {
-+ folder: this.folder,
-+ messageFlag: ((action == 'flagged') ? 'flagged' : '-flagged')
-+ };
-+ this.viewport.updateFlag(vs, 'flagged', action == 'flagged');
-+ DimpCore.doAction('MarkMessage', args, DimpCore.toUIDArray(vs));
-+ break;
-+
-+ case 'answered':
-+ this.viewport.updateFlag(vs, 'answered', true);
-+ this.viewport.updateFlag(vs, 'flagged', false);
-+ break;
-+ }
-+ },
-+
-+ /* Miscellaneous folder actions. */
-+ purgeDeleted: function()
-+ {
-+ DimpCore.doAction('PurgeDeleted', this.viewport.addRequestParams({}), [], this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)));
-+ },
-+
-+ modifyPollFolder: function(folder, add)
-+ {
-+ DimpCore.doAction('ModifyPollFolder', { folder: folder, add: (add) ? 1 : 0 }, [], this.bcache.get('modifyPFC') || this.bcache.set('modifyPFC', this._modifyPollFolderCallback.bind(this)));
-+ },
-+
-+ _modifyPollFolderCallback: function(r)
-+ {
-+ r = r.response;
-+ var f = r.folder, fid, p = { response: { poll: {} } };
-+ fid = $(this.getFolderId(f));
-+
-+ if (r.add) {
-+ p.response.poll[f] = r.poll.u;
-+ fid.writeAttribute('u', 0);
-+ } else {
-+ p.response.poll[f] = 0;
-+ }
-+
-+ this._pollFoldersCallback(p);
-+
-+ if (!r.add) {
-+ fid.removeAttribute('u');
-+ }
-+ },
-+
-+ msgListLoading: function(show)
-+ {
-+ var ml_offset;
-+
-+ if (this.fl_visible != show) {
-+ this.fl_visible = show;
-+ if (show) {
-+ ml_offset = $('msgList').positionedOffset();
-+ $('folderLoading').setStyle({ position: 'absolute', top: (ml_offset.top + 10) + 'px', left: (ml_offset.left + 10) + 'px' });
-+ Effect.Appear('folderLoading', { duration: 0.2 });
-+ $(document.body).setStyle({ cursor: 'progress' });
-+ } else {
-+ Effect.Fade('folderLoading', { duration: 0.2 });
-+ $(document.body).setStyle({ cursor: 'default' });
-+ }
-+ }
-+ },
-+
-+ // p = (element) Parent element
-+ // c = (element) Child element
-+ isSubfolder: function(p, c)
-+ {
-+ var sf = $(this.getSubFolderId(p.readAttribute('id')));
-+ return sf && c.descendantOf(sf);
-+ },
-+
-+ /* Onload function. */
-+ _onLoad: function() {
-+ var C = DimpCore.clickObserveHandler, tmp;
-+
-+ if (Horde.dhtmlHistory.initialize()) {
-+ Horde.dhtmlHistory.addListener(this.go.bind(this));
-+ }
-+
-+ this._setFilterText(true);
-+
-+ /* Initialize the starting page if necessary. addListener() will have
-+ * already fired if there is a current location so only do a go()
-+ * call if there is no current location. */
-+ if (!Horde.dhtmlHistory.getCurrentLocation()) {
-+ if (DIMP.conf.login_view == 'inbox') {
-+ this.go('folder:INBOX');
-+ } else {
-+ this.go('portal');
-+ if (DIMP.conf.background_inbox) {
-+ this.loadFolder('INBOX', true);
-+ }
-+ }
-+ }
-+
-+ /* Add popdown menus. */
-+ DimpCore.addPopdown('button_reply', 'reply');
-+ DimpCore.DMenu.disable('button_reply_img', true, true);
-+ DimpCore.addPopdown('button_forward', 'forward');
-+ 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') });
-+ }
-+
-+ tmp = $('dimpbarActions');
-+ C({ d: tmp.down('.composelink'), f: DimpCore.compose.bind(DimpCore, 'new') });
-+ C({ d: tmp.down('.refreshlink'), f: this.pollFolders.bind(this) });
-+
-+ tmp = $('serviceActions');
-+ [ '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: DimpCore.logout.bind(DimpCore) });
-+ }
-+
-+ tmp = $('applicationfolders');
-+ if (tmp) {
-+ tmp.select('ul 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'), f: DimpCore.compose.bind(DimpCore, 'new') });
-+ C({ d: $('button_other'), f: function(e) { DimpCore.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(DimpCore.DMenu.element()); }.bind(this), ns: true });
-+ C({ d: $('ctx_folder_rename'), f: function() { this.renameFolder(DimpCore.DMenu.element()); }.bind(this), ns: true });
-+ C({ d: $('ctx_folder_empty'), f: function() { if (window.confirm(DIMP.text.empty_folder)) { DimpCore.doAction('EmptyFolder', { folder: DimpCore.DMenu.element().readAttribute('mbox') }, [], this._emptyFolderCallback.bind(this)); } }.bind(this), ns: true });
-+ C({ d: $('ctx_folder_delete'), f: function() { if (window.confirm(DIMP.text.delete_folder)) { DimpCore.doAction('DeleteFolder', { folder: DimpCore.DMenu.element().readAttribute('mbox') }, [], 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, DimpCore.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(DimpCore.DMenu.element().readAttribute('mbox'), modify); }.bind(this, a == 'ctx_folder_poll'), ns: true });
-+ }, this);
-+ C({ d: $('ctx_container_create'), f: function() { this.createSubFolder(DimpCore.DMenu.element()); }.bind(this), ns: true });
-+ C({ d: $('ctx_container_rename'), f: function() { this.renameFolder(DimpCore.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 });
-+ }
-+
-+ $('expandHeaders', 'collapseHeaders').each(function(a) {
-+ C({ d: a, f: function() { $('msgHeadersColl', 'msgHeaders').invoke('toggle'); }, ns: true });
-+ }, this);
-+ $('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();
-+ },
-+
-+ // IE 6 width fixes (See Bug #6793)
-+ _resizeIE6: function()
-+ {
-+ if (DIMP.conf.is_ie6) {
-+ var tmp = parseInt($('sidebarPanel').getStyle('width'), 10),
-+ tmp1 = document.viewport.getWidth() - tmp - 30;
-+ $('normalfolders').setStyle({ width: tmp + 'px' });
-+ $('dimpmain').setStyle({ width: tmp1 + 'px' });
-+ $('msglist').setStyle({ width: (tmp1 - 5) + 'px' });
-+ $('msgBody').setStyle({ width: (tmp1 - 25) + 'px' });
-+ tmp = $('dimpmain_portal').down('IFRAME');
-+ if (tmp) {
-+ this._resizeIE6Iframe(tmp);
-+ }
-+ }
-+ },
-+
-+ _resizeIE6Iframe: function(iframe)
-+ {
-+ if (DIMP.conf.is_ie6) {
-+ iframe.setStyle({ width: $('dimpmain').getStyle('width'), height: (document.viewport.getHeight() - 20) + 'px' });
-+ }
-+ }
-+};
-+
-+/* Need to add after DimpBase is defined. */
-+DimpBase._msgDragConfig = {
-+ scroll: 'normalfolders',
-+ threshold: 5,
-+ caption: DimpBase._dragCaption.bind(DimpBase),
-+ onStart: function(d, e) {
-+ var args = { right: e.isRightClick() },
-+ id = d.element.id;
-+
-+ d.selectIfNoDrag = false;
-+
-+ // Handle selection first.
-+ if (!args.right && (e.ctrlKey || e.metaKey)) {
-+ this.msgSelect(id, $H({ ctrl: true }).merge(args).toObject());
-+ } else if (e.shiftKey) {
-+ this.msgSelect(id, $H({ shift: true }).merge(args).toObject());
-+ } else if (this.isSelected('domid', id)) {
-+ if (!args.right && this.selectedCount()) {
-+ d.selectIfNoDrag = true;
-+ }
-+ } else {
-+ this.msgSelect(id, args);
-+ }
-+ }.bind(DimpBase),
-+ onEnd: function(d, e) {
-+ if (d.selectIfNoDrag && !d.wasDragged) {
-+ this.msgSelect(d.element.id, { right: e.isRightClick() });
-+ }
-+ }.bind(DimpBase)
-+};
-+
-+DimpBase._folderDragConfig = {
-+ ghosting: true,
-+ offset: { x: 5, y: 5 },
-+ scroll: 'normalfolders',
-+ threshold: 5,
-+ onDrag: function(d, e) {
-+ if (!d.wasDragged) {
-+ $('newfolder').hide();
-+ $('dropbase').show();
-+ d.ghost.removeClassName('on');
-+ }
-+ },
-+ onEnd: function(d, e) {
-+ if (d.wasDragged) {
-+ $('newfolder').show();
-+ $('dropbase').hide();
-+ }
-+ }
-+};
-+
-+DimpBase._folderDropConfig = {
-+ hoverclass: 'dragdrop',
-+ caption: function(drop, drag) {
-+ var d = drag.readAttribute('l'),
-+ ftype = drop.readAttribute('ftype'),
-+ l = drop.readAttribute('l'),
-+ m = DIMP.text.moveto;
-+ if (drop == $('dropbase')) {
-+ return m.replace(/%s/, d).replace(/%s/, DIMP.text.baselevel);
-+ } else if (drag.hasClassName('folder')) {
-+ return (ftype != 'special' && !this.isSubfolder(drag, drop)) ? m.replace(/%s/, d).replace(/%s/, l) : '';
-+ } else {
-+ return ftype != 'container' ? m.replace(/%s/, this._dragCaption()).replace(/%s/, l) : '';
-+ }
-+ }.bind(DimpBase),
-+ onDrop: DimpBase._folderDropHandler.bind(DimpBase)
-+};
-+
-+/* Stuff to do immediately when page is ready. */
-+document.observe('dom:loaded', function() {
-+ $('dimpLoading').hide();
-+ $('dimpPage').show();
-+
-+ /* Create the folder list. Any pending notifications will be caught via
-+ * the return from this call. */
-+ DimpCore.doAction('ListFolders', {}, [], DimpBase._folderLoadCallback.bind(DimpBase));
-+
-+ /* Start message list loading as soon as possible. */
-+ if (!DimpBase.delay_onload) {
-+ DimpBase._onLoad();
-+ }
-+
-+ /* Disable text selection in preview pane for IE 6. */
-+ if (DIMP.conf.is_ie6) {
-+ document.observe('selectstart', Event.stop);
-+ }
-+
-+ /* Remove unneeded search folders. */
-+ if (!DIMP.conf.search_all) {
-+ DimpBase.sfiltersfolder.unset('sf_all');
-+ }
-+
-+ /* Check for new mail. */
-+ DimpBase.setPollFolders();
-+
-+ /* Bind key shortcuts. */
-+ document.observe('keydown', DimpBase._keydownHandler.bind(DimpBase));
-+
-+ /* Resize elements on window size change. */
-+ Event.observe(window, 'resize', DimpBase._onResize.bind(DimpBase));
-+
-+ /* Since IE 6 doesn't support hover over non-links, use javascript events
-+ * to replicate mouseover CSS behavior. */
-+ if (DIMP.conf.is_ie6) {
-+ var links = [], tmp;
-+ if (tmp = $('dimpbarActions')) {
-+ links.push(tmp.select('SPAN'));
-+ }
-+ if (tmp = $('serviceActions')) {
-+ links.push(tmp.select('LI.servicelink'));
-+ }
-+ if (tmp = $('applicationfolders')) {
-+ links.push(tmp.select('UL LI'));
-+ }
-+ links.flatten().compact().each(function(e) {
-+ e.observe('mouseover', e.addClassName.curry('over')).observe('mouseout', e.removeClassName.curry('over'));
-+ });
-+ }
-+});
-+
-+/* Stuff to do after window is completely loaded. Don't init viewport until
-+ * now for non-Gecko/Opera browsers since sizing functions might not work
-+ * properly before. */
-+if (DimpBase.delay_onload) {
-+ Event.observe(window, 'load', DimpBase._onLoad.bind(DimpBase));
-+}
-+
-+/* Need to register a callback function for doAction to catch viewport
-+ * information returned from the server. */
-+DimpCore.onDoActionComplete = function(r) {
-+ if (DimpBase.viewport && r.response.viewport) {
-+ DimpBase.viewport.ajaxResponse(r.response.viewport);
-+ }
-+};
-+
-+/* Extend these functions from DimpCore since additional processing needs to
-+ * be done re: drag/drop and menu manipulation. */
-+DimpCore.addMouseEvents = DimpCore.addMouseEvents.wrap(DimpBase._addMouseEvents.bind(DimpBase));
-+DimpCore.removeMouseEvents = DimpCore.removeMouseEvents.wrap(DimpBase._removeMouseEvents.bind(DimpBase));
-diff --git a/js/src/DimpBase.js b/js/src/DimpBase.js
-index 9c1668e..96cd917 100644
---- a/js/src/DimpBase.js
-+++ b/js/src/DimpBase.js
-@@ -1545,7 +1545,7 @@ var DimpBase = {
-
- div = new Element('DIV', { className: ob.cl || 'base', id: fid + '_div' });
- if (ob.i) {
-- div.update(ob.i);
-+ div.setStyle({ backgroundImage: 'url("' + ob.i + '")' });
- }
- if (ob.ch) {
- div.writeAttribute({ className: 'exp' }).observe('mouseover', this.bcache.get('mo_folder') || this.bcache.set('mo_folder', function(e) {
-diff --git a/lib/DIMP.php b/lib/DIMP.php
-index 8518210..0aa3b78 100644
---- a/lib/DIMP.php
-+++ b/lib/DIMP.php
-@@ -414,8 +414,13 @@ class DIMP {
- }
-
- if ($elt['user_icon']) {
-- $ob->cl = 'custom';
-- $ob->i = Horde::img($elt['icon'], $elt['alt'], '', $elt['icondir']);
-+ $ob->cl = 'customimg';
-+ $dir = empty($elt['icondir'])
-+ ? $GLOBALS['registry']->getImageDir()
-+ : $elt['icondir'];
-+ $ob->i = empty($dir)
-+ ? $elt['icon']
-+ : $dir . '/' . $elt['icon'];
- }
-
- return $ob;
-diff --git a/themes/screen.css b/themes/screen.css
-index c33b148..cce11b3 100644
---- a/themes/screen.css
-+++ b/themes/screen.css
-@@ -464,7 +464,7 @@ div.msgSize img {
- height: 100%;
- background: transparent url("graphics/folder_create.png") center left no-repeat;
- }
--#sidebarPanel .drafts, #sidebarPanel .inbox, #sidebarPanel .sent, #sidebarPanel .spam, #sidebarPanel .trash {
-+#sidebarPanel .drafts, #sidebarPanel .inbox, #sidebarPanel .sent, #sidebarPanel .spam, #sidebarPanel .trash, #sidebarPanel .customimg {
- display: inline;
- float: left;
- width: 20px;
---
-tg: (6938161..) t/dimp/H/MS/FixBrokenFolderImages (depends on: master)
---
-TOPGIT patch commit log
-=======================
-
-commit 12a42ba2183476ce329b567490ff5013727d8a39
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Sat Feb 7 23:54:51 2009 +0000
-
- Fix the style name.
-
-commit 8588d2b184f6244655c219104b4d8119f0ea4644
-Author: Gunnar Wrobel <p at rdus.de>
-Date: Sat Feb 7 18:43:00 2009 +0000
-
- kolab/issue3328 ([Webclient] DIMP groupware folder names display bug)
More information about the commits
mailing list