2 Copyright (C) 2005 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 /* some generic JavaScript code for SOGo */
30 var menus = new Array();
34 var lastClickedRow = -1;
36 var weekStartIsMonday = true;
39 var allDocumentElements = null;
41 var userDefaults = null;
42 var userSettings = null;
44 // Ajax requests counts
45 var activeAjaxRequests = 0;
46 var removeFolderRequestCount = 0;
48 /* a W3C compliant document.all */
49 function getAllScopeElements(scope) {
50 var elements = new Array();
52 for (var i = 0; i < scope.childNodes.length; i++)
53 if (typeof(scope.childNodes[i]) == "object"
54 && scope.childNodes[i].tagName
55 && scope.childNodes[i].tagName != '')
57 elements.push(scope.childNodes[i]);
58 var childElements = getAllElements(scope.childNodes[i]);
59 if (childElements.length > 0)
60 elements.push(childElements);
66 function getAllElements(scope) {
73 && allDocumentElements != null)
74 elements = allDocumentElements;
77 elements = getAllScopeElements(scope);
78 if (scope == document)
79 allDocumentElements = elements;
86 http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/ */
87 function getElementsByClassName2(_tag, _class, _scope) {
88 var regexp, classes, elements, element, returnElements;
90 _scope = _scope || document;
92 elements = (!_tag || _tag == "*"
93 ? getAllElements(null)
94 : _scope.getElementsByTagName(_tag));
97 classes = _class.split(/\s+/);
98 regexp = new RegExp("(^|\s+)("+ classes.join("|") +")(\s+|$)","i");
101 for(var i = 0; element = elements[i]; i++) {
102 if (regexp.test(element.className)) {
103 returnElements.push(element);
106 return returnElements;
112 function createElement(tagName, id, classes, attributes, htmlAttributes,
114 var newElement = $(document.createElement(tagName));
116 newElement.setAttribute("id", id);
118 if (typeof(classes) == "string")
119 newElement.addClassName(classes);
121 for (var i = 0; i < classes.length; i++)
122 newElement.addClassName(classes[i]);
125 for (var i in attributes)
126 newElement[i] = attributes[i];
128 for (var i in htmlAttributes)
129 newElement.setAttribute(i, htmlAttributes[i]);
131 parentNode.appendChild(newElement);
133 return $(newElement);
136 function ml_stripActionInURL(url) {
137 if (url[url.length - 1] != '/') {
140 i = url.lastIndexOf("/");
141 if (i != -1) url = url.substring(0, i);
143 if (url[url.length - 1] != '/') // ensure trailing slash
148 function URLForFolderID(folderID) {
149 var folderInfos = folderID.split(":");
151 if (folderInfos.length > 1) {
152 url = UserFolderURL + "../" + folderInfos[0];
153 if (!(folderInfos[0].endsWith('/')
154 || folderInfos[1].startsWith('/')))
156 url += folderInfos[1];
159 url = ApplicationBaseURL + folderInfos[0];
161 if (url[url.length-1] == '/')
162 url = url.substr(0, url.length-1);
167 function extractEmailAddress(mailTo) {
171 = /([a-zA-Z0-9]+[a-zA-Z0-9\._-]+[a-zA-Z0-9]+@[a-zA-Z0-9]+[a-zA-Z0-9\._-]+[a-zA-Z0-9]+)/g;
172 if (emailre.test(mailTo)) {
173 emailre.exec(mailTo);
180 function extractEmailName(mailTo) {
183 var tmpMailTo = mailTo.replace("<", "<");
184 tmpMailTo = tmpMailTo.replace(">", ">");
186 var emailNamere = /([ ]+)?(.+)\ </;
187 if (emailNamere.test(tmpMailTo)) {
188 emailNamere.exec(tmpMailTo);
189 emailName = RegExp.$2;
195 function sanitizeMailTo(dirtyMailTo) {
196 var emailName = extractEmailName(dirtyMailTo);
197 var email = "" + extractEmailAddress(dirtyMailTo);
200 if (emailName && emailName.length > 0)
201 mailto = emailName + ' <' + email + '>';
208 function openUserFolderSelector(callback, type) {
209 var urlstr = ApplicationBaseURL;
210 if (! urlstr.endsWith('/'))
212 urlstr += ("../../" + UserLogin + "/Contacts/userFolders");
213 var w = window.open(urlstr, "_blank",
214 "width=322,height=250,resizable=1,scrollbars=0,location=0");
216 window.userFolderCallback = callback;
217 window.userFolderType = type;
221 function openContactWindow(url, wId) {
222 if (typeof wId == "undefined")
225 var r = new RegExp("[\.\/-]", "g");
226 wId = wId.replace(r, "_");
229 var w = window.open(url, wId,
230 "width=450,height=600,resizable=0,location=0");
236 function openMailComposeWindow(url, wId) {
237 var parentWindow = this;
239 if (typeof wId == "undefined")
242 var r = new RegExp("[\.\/-]", "g");
243 wId = wId.replace(r, "_");
246 if (document.body.hasClassName("popup"))
247 parentWindow = window.opener;
249 var w = parentWindow.open(url, wId,
250 "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
251 + "location=0,directories=0,status=0,menubar=0"
259 function openMailTo(senderMailTo) {
260 var mailto = sanitizeMailTo(senderMailTo);
262 if (mailto.length > 0)
263 openMailComposeWindow(ApplicationBaseURL
264 + "../Mail/compose?mailto=" + mailto);
266 return false; /* stop following the link */
269 function createHTTPClient() {
270 // http://developer.apple.com/internet/webcontent/xmlhttpreq.html
271 if (typeof XMLHttpRequest != "undefined")
272 return new XMLHttpRequest();
274 try { return new ActiveXObject("Msxml2.XMLHTTP"); }
276 try { return new ActiveXObject("Microsoft.XMLHTTP"); }
282 function appendDifferentiator(url) {
283 var url_nocache = url;
284 var position = url.indexOf('?', 0);
289 url_nocache += 'differentiator=' + Math.floor(Math.random()*50000);
294 function triggerAjaxRequest(url, callback, userdata, content, headers) {
295 var http = createHTTPClient();
297 activeAjaxRequests += 1;
298 document.animTimer = setTimeout("checkAjaxRequestsState();", 50);
299 //url = appendDifferentiator(url);
302 http.open("POST", url, true);
304 http.onreadystatechange
306 // log ("state changed (" + http.readyState + "): " + url);
308 if (http.readyState == 4
309 && activeAjaxRequests > 0) {
312 http.callbackData = userdata;
315 activeAjaxRequests -= 1;
316 checkAjaxRequestsState();
320 activeAjaxRequests -= 1;
321 checkAjaxRequestsState();
322 log("AJAX Request, Caught Exception: " + e.name);
328 for (var i in headers)
329 http.setRequestHeader(i, headers[i]);
334 log("triggerAjaxRequest: error creating HTTP Client!");
340 function startAnimation(parent, nextNode) {
341 var anim = $("progressIndicator");
342 if (anim) return anim;
344 anim = document.createElement("img");
346 anim.id = "progressIndicator";
347 anim.src = ResourcesURL + "/busy.gif";
348 anim.setStyle({ visibility: "hidden" });
350 parent.insertBefore(anim, nextNode);
352 parent.appendChild(anim);
353 anim.setStyle({ visibility: "visible" });
358 function checkAjaxRequestsState() {
359 var toolbar = document.getElementById("toolbar");
361 if (activeAjaxRequests > 0
362 && !document.busyAnim) {
363 document.busyAnim = startAnimation(toolbar);
365 else if (activeAjaxRequests == 0
367 && document.busyAnim.parentNode) {
368 document.busyAnim.parentNode.removeChild(document.busyAnim);
369 document.busyAnim = null;
374 function isSafari3() {
375 return (navigator.appVersion.indexOf("Version") > -1);
378 function isSafari() {
379 //var agt = navigator.userAgent.toLowerCase();
380 //var is_safari = ((agt.indexOf('safari')!=-1)&&(agt.indexOf('mac')!=-1))?true:false;
382 return (navigator.vendor == "Apple Computer, Inc.");
385 function isHttpStatus204(status) {
386 return (status == 204 || // Firefox
387 (isSafari() && typeof(status) == 'undefined') || // Safari
388 status == 1223); // IE
391 function getTarget(event) {
392 event = event || window.event;
394 return event.target; // W3C DOM
396 return event.srcElement; // IE
399 function preventDefault(event) {
400 if (event.preventDefault)
401 event.preventDefault(); // W3C DOM
403 event.returnValue = false; // IE
406 function resetSelection(win) {
408 if (win && win.getSelection) {
409 t = win.getSelection().toString();
410 win.getSelection().removeAllRanges();
415 function refreshOpener() {
416 if (window.opener && !window.opener.closed) {
417 window.opener.location.reload();
423 function parseQueryString() {
424 var queryArray, queryDict
425 var key, value, s, idx;
426 queryDict.length = 0;
428 queryDict = new Array();
429 queryArray = location.search.substr(1).split('&');
430 for (var i in queryArray) {
431 if (!queryArray[i]) continue ;
433 idx = s.indexOf("=");
439 key = s.substr(0, idx);
440 value = unescape(s.substr(idx + 1));
443 if (typeof queryDict[key] == 'undefined')
446 queryDict[key] = value;
451 function generateQueryString(queryDict) {
453 for (var key in queryDict) {
458 s = s + key + "=" + escape(queryDict[key]);
463 /* selection mechanism */
465 function deselectAll(parent) {
466 for (var i = 0; i < parent.childNodes.length; i++) {
467 var node = parent.childNodes.item(i);
468 if (node.nodeType == 1)
473 function isNodeSelected(node) {
474 return $(node).hasClassName('_selected');
477 function acceptMultiSelect(node) {
478 var response = false;
479 var attribute = node.getAttribute('multiselect');
480 if (attribute && attribute.length > 0) {
481 log("node '" + node.getAttribute("id")
482 + "' is still using old-stylemultiselect!");
483 response = (attribute.toLowerCase() == 'yes');
486 response = node.multiselect;
491 function onRowClick(event) {
492 var node = getTarget(event);
495 if (node.tagName == 'TD') {
496 node = node.parentNode; // select TR
497 rowIndex = node.rowIndex - $(node).up('table').down('thead').getElementsByTagName('tr').length;
499 else if (node.tagName == 'LI') {
500 // Find index of clicked row
501 var list = node.parentNode;
502 var items = list.childNodesWithTag("li");
503 for (var i = 0; i < items.length; i++) {
504 if (items[i] == node) {
511 var initialSelection = $(node.parentNode).getSelectedNodes();
512 if (initialSelection.length > 0
513 && initialSelection.indexOf(node) >= 0
514 && !Event.isLeftClick(event))
515 // Ignore non primary-click (ie right-click) inside current selection
518 if ((event.shiftKey == 1 || event.ctrlKey == 1)
519 && (lastClickedRow >= 0)
520 && (acceptMultiSelect(node.parentNode)
521 || acceptMultiSelect(node.parentNode.parentNode))) {
523 $(node.parentNode).selectRange(lastClickedRow, rowIndex);
524 else if (isNodeSelected(node) == true) {
529 // At this point, should empty content of 3-pane view
531 // Single line selection
532 $(node.parentNode).deselectAll();
535 if (initialSelection != $(node.parentNode).getSelectedNodes()) {
536 // Selection has changed; fire mousedown event
537 var parentNode = node.parentNode;
538 if (parentNode.tagName == 'TBODY')
539 parentNode = parentNode.parentNode;
540 parentNode.fire("mousedown");
543 lastClickedRow = rowIndex;
550 // var acceptClick = false;
552 function popupMenu(event, menuId, target) {
553 document.menuTarget = target;
555 if (document.currentPopupMenu)
556 hideMenu(document.currentPopupMenu);
558 var popup = $(menuId);
563 var pageContent = $("pageContent");
564 if (popup.parentNode.tagName != "BODY") {
565 var offset = pageContent.cascadeLeftOffset();
566 deltaX = -($(popup.parentNode).cascadeLeftOffset() - offset);
567 offset = pageContent.cascadeTopOffset();
568 deltaY = -($(popup.parentNode).cascadeTopOffset() - offset);
571 var menuTop = Event.pointerY(event) + deltaY;
572 var menuLeft = Event.pointerX(event) + deltaX;
573 var heightDiff = (window.height()
574 - (menuTop + popup.offsetHeight));
576 menuTop += heightDiff;
578 var leftDiff = (window.width()
579 - (menuLeft + popup.offsetWidth));
581 menuLeft -= popup.offsetWidth;
583 if (popup.prepareVisibility)
584 popup.prepareVisibility();
586 popup.setStyle({ top: menuTop + "px",
587 left: menuLeft + "px",
588 visibility: "visible" });
590 document.currentPopupMenu = popup;
592 $(document.body).observe("click", onBodyClickMenuHandler);
594 preventDefault(event);
597 function getParentMenu(node) {
598 var currentNode, menuNode;
602 var menure = new RegExp("(^|\s+)menu(\s+|$)", "i");
604 while (menuNode == null
606 if (menure.test(currentNode.className))
607 menuNode = currentNode;
609 currentNode = currentNode.parentNode;
614 function onBodyClickMenuHandler(event) {
615 hideMenu(document.currentPopupMenu);
616 document.body.stopObserving("click", onBodyClickMenuHandler);
619 preventDefault(event);
622 function hideMenu(menuNode) {
625 if (menuNode.submenu) {
626 hideMenu(menuNode.submenu);
627 menuNode.submenu = null;
630 menuNode.setStyle({ visibility: "hidden" });
631 if (menuNode.parentMenuItem) {
632 menuNode.parentMenuItem.stopObserving("mouseover",onMouseEnteredSubmenu);
633 menuNode.stopObserving("mouseover", onMouseEnteredSubmenu);
634 menuNode.parentMenuItem.stopObserving("mouseout", onMouseLeftSubmenu);
635 menuNode.stopObserving("mouseout", onMouseLeftSubmenu);
636 menuNode.parentMenu.stopObserving("mouseover", onMouseEnteredParentMenu);
637 $(menuNode.parentMenuItem).removeClassName("submenu-selected");
638 menuNode.parentMenuItem.mouseInside = false;
639 menuNode.parentMenuItem = null;
640 menuNode.parentMenu.submenuItem = null;
641 menuNode.parentMenu.submenu = null;
642 menuNode.parentMenu = null;
645 $(menuNode).fire("mousedown");
648 function onMenuEntryClick(event) {
649 var node = event.target;
651 id = getParentMenu(node).menuTarget;
656 function parseQueryParameters(url) {
657 var parameters = new Array();
659 var params = url.split("?")[1];
661 var pairs = params.split("&");
662 for (var i = 0; i < pairs.length; i++) {
663 var pair = pairs[i].split("=");
664 parameters[pair[0]] = pair[1];
671 function initLogConsole() {
672 var logConsole = $("logConsole");
674 logConsole.highlighted = false;
675 logConsole.observe("dblclick", onLogDblClick, false);
677 Event.observe(window, "keydown", onBodyKeyDown);
681 function onBodyKeyDown(event) {
682 if (event.keyCode == 27) {
684 preventDefault(event);
688 function onLogDblClick(event) {
689 var logConsole = $("logConsole");
690 logConsole.innerHTML = "";
693 function toggleLogConsole(event) {
694 var logConsole = $("logConsole");
695 var display = '' + logConsole.style.display;
696 if (display.length == 0) {
697 logConsole.setStyle({ display: 'block' });
699 logConsole.setStyle({ display: '' });
702 preventDefault(event);
705 function log(message) {
708 while (logWindow.opener)
709 logWindow = logWindow.opener;
711 var logConsole = logWindow.document.getElementById("logConsole");
713 logConsole.highlighted = !logConsole.highlighted;
714 if (message == '\c') {
715 logConsole.innerHTML = "";
718 var logMessage = message.replace("<", "<", "g");
719 logMessage = logMessage.replace(" ", " ", "g");
720 logMessage = logMessage.replace("\r\n", "<br />\n", "g");
721 logMessage = logMessage.replace("\n", "<br />\n", "g");
722 logMessage += '<br />' + "\n";
723 if (logConsole.highlighted)
724 logMessage = '<div class="highlighted">' + logMessage + '</div>';
725 logConsole.innerHTML += logMessage;
729 function backtrace() {
730 var func = backtrace.caller;
731 var str = "backtrace:\n";
737 str += " " + func.name;
739 str += " (" + this + ")";
742 str += "[anonymous]\n";
752 function popupSubmenu(event) {
753 if (this.submenu && this.submenu != "") {
754 var submenuNode = $(this.submenu);
755 var parentNode = getParentMenu(this);
756 if (parentNode.submenu)
757 hideMenu(parentNode.submenu);
758 submenuNode.parentMenuItem = this;
759 submenuNode.parentMenu = parentNode;
760 parentNode.submenuItem = this;
761 parentNode.submenu = submenuNode;
763 if (submenuNode.prepareVisibility)
764 submenuNode.prepareVisibility();
766 var menuTop = (parentNode.offsetTop - 1
770 < (menuTop + submenuNode.offsetHeight))
771 if (submenuNode.offsetHeight < window.height())
772 menuTop = window.height() - submenuNode.offsetHeight;
776 var menuLeft = (parentNode.offsetLeft + parentNode.offsetWidth - 3);
778 < (menuLeft + submenuNode.offsetWidth))
779 menuLeft = parentNode.offsetLeft - submenuNode.offsetWidth + 3;
781 this.mouseInside = true;
782 this.observe("mouseover", onMouseEnteredSubmenu);
783 submenuNode.observe("mouseover", onMouseEnteredSubmenu);
784 this.observe("mouseout", onMouseLeftSubmenu);
785 submenuNode.observe("mouseout", onMouseLeftSubmenu);
786 parentNode.observe("mouseover", onMouseEnteredParentMenu);
787 $(this).addClassName("submenu-selected");
788 submenuNode.setStyle({ top: menuTop + "px",
789 left: menuLeft + "px",
790 visibility: "visible" });
791 preventDefault(event);
795 function onMouseEnteredParentMenu(event) {
796 if (this.submenuItem && !this.submenuItem.mouseInside)
797 hideMenu(this.submenu);
800 function onMouseEnteredSubmenu(event) {
801 $(this).mouseInside = true;
804 function onMouseLeftSubmenu(event) {
805 $(this).mouseInside = false;
809 function popupSearchMenu(event) {
810 var menuId = this.getAttribute("menuid");
811 var offset = Position.cumulativeOffset(this);
813 relX = Event.pointerX(event) - offset[0];
814 relY = Event.pointerY(event) - offset[1];
816 if (event.button == 0
818 event.cancelBubble = true;
819 event.returnValue = false;
821 if (document.currentPopupMenu)
822 hideMenu(document.currentPopupMenu);
824 var popup = $(menuId);
825 offset = Position.positionedOffset(this);
826 popup.setStyle({ top: this.offsetHeight + "px",
827 left: (offset[0] + 3) + "px",
828 visibility: "visible" });
830 document.currentPopupMenu = popup;
831 $(document.body).observe("click", onBodyClickMenuHandler);
835 function setSearchCriteria(event) {
836 var searchValue = $("searchValue");
837 var searchCriteria = $("searchCriteria");
839 searchValue.ghostPhrase = this.innerHTML;
840 searchCriteria.value = this.getAttribute('id');
842 if (this.parentNode.chosenNode)
843 this.parentNode.chosenNode.removeClassName("_chosen");
844 this.addClassName("_chosen");
845 this.parentNode.chosenNode = this;
848 function checkSearchValue(event) {
849 var searchValue = $("searchValue");
851 if (searchValue.value == searchValue.ghostPhrase)
852 searchValue.value = "";
855 function configureSearchField() {
856 var searchValue = $("searchValue");
857 var searchOptions = $("searchOptions");
859 if (!searchValue) return;
861 searchValue.observe("click", popupSearchMenu);
862 searchValue.observe("blur", onSearchBlur);
863 searchValue.observe("focus", onSearchFocus);
864 searchValue.observe("keydown", onSearchKeyDown);
865 searchValue.observe("mousedown", onSearchMouseDown);
867 if (!searchOptions) return;
869 // Set the checkmark to the first option
870 var firstOption = searchOptions.down('li');
871 firstOption.addClassName("_chosen");
872 searchOptions.chosenNode = firstOption;
875 function onSearchMouseDown(event) {
876 var superNode = this.parentNode.parentNode.parentNode;
877 relX = (Event.pointerX(event) - superNode.offsetLeft - this.offsetLeft);
878 relY = (Event.pointerY(event) - superNode.offsetTop - this.offsetTop);
881 event.cancelBubble = true;
882 event.returnValue = false;
886 function onSearchFocus() {
887 ghostPhrase = this.ghostPhrase;
888 if (this.value == ghostPhrase) {
890 this.setAttribute("modified", "");
895 this.setStyle({ color: "#000" });
898 function onSearchBlur(event) {
900 this.setAttribute("modified", "");
901 this.setStyle({ color: "#aaa" });
902 this.value = this.ghostPhrase;
903 search["value"] = "";
904 if (searchValue.lastSearch != "") {
905 searchValue.lastSearch = "";
906 refreshCurrentFolder();
908 } else if (this.value == this.ghostPhrase) {
909 this.setAttribute("modified", "");
910 this.setStyle({ color: "#aaa" });
912 this.setAttribute("modified", "yes");
913 this.setStyle({ color: "#000" });
917 function onSearchKeyDown(event) {
919 clearTimeout(this.timer);
921 if (event.keyCode == 13) {
922 onSearchFormSubmit();
923 preventDefault(event);
926 this.timer = setTimeout("onSearchFormSubmit()", 1000);
929 function onSearchFormSubmit(event) {
930 var searchValue = $("searchValue");
931 var searchCriteria = $("searchCriteria");
933 if (searchValue.value != searchValue.ghostPhrase
934 && searchValue.value != searchValue.lastSearch) {
935 search["criteria"] = searchCriteria.value;
936 search["value"] = searchValue.value;
937 searchValue.lastSearch = searchValue.value;
938 refreshCurrentFolder();
942 function initCriteria() {
943 var searchCriteria = $("searchCriteria");
944 var searchValue = $("searchValue");
947 var searchOptions = $("searchOptions").childNodesWithTag("li");
948 if (searchOptions.length > 0) {
949 var firstChild = searchOptions[0];
950 searchCriteria.value = $(firstChild).getAttribute('id');
951 searchValue.ghostPhrase = firstChild.innerHTML;
952 searchValue.lastSearch = "";
953 if (searchValue.value == '') {
954 searchValue.value = firstChild.innerHTML;
955 searchValue.setAttribute("modified", "");
956 searchValue.setStyle({ color: "#aaa" });
962 /* toolbar buttons */
963 function popupToolbarMenu(node, menuId) {
964 if (document.currentPopupMenu)
965 hideMenu(document.currentPopupMenu);
967 var popup = $(menuId);
968 var top = ($(node).getStyle('top') || 0) + node.offsetHeight - 2;
969 popup.setStyle({ top: top + "px",
970 left: $(node).cascadeLeftOffset() + "px",
971 visibility: "visible" });
973 document.currentPopupMenu = popup;
974 $(document.body).observe("click", onBodyClickMenuHandler);
977 /* contact selector */
979 function folderSubscriptionCallback(http) {
980 if (http.readyState == 4) {
981 if (isHttpStatus204(http.status)) {
982 if (http.callbackData)
983 http.callbackData["method"](http.callbackData["data"]);
986 window.alert(clabels["Unable to subscribe to that folder!"]);
987 document.subscriptionAjaxRequest = null;
990 log ("folderSubscriptionCallback Ajax error");
993 function subscribeToFolder(refreshCallback, refreshCallbackData) {
994 var folderData = refreshCallbackData["folder"].split(":");
995 var username = folderData[0];
996 var folderPath = folderData[1];
997 if (username != UserLogin) {
998 var url = (UserFolderURL + "../" + username
999 + folderPath + "/subscribe");
1000 if (document.subscriptionAjaxRequest) {
1001 document.subscriptionAjaxRequest.aborted = true;
1002 document.subscriptionAjaxRequest.abort();
1005 var rfCbData = { method: refreshCallback, data: refreshCallbackData };
1006 document.subscriptionAjaxRequest = triggerAjaxRequest(url,
1007 folderSubscriptionCallback,
1011 refreshCallbackData["window"].alert(clabels["You cannot subscribe to a folder that you own!"]);
1014 function folderUnsubscriptionCallback(http) {
1015 if (http.readyState == 4) {
1016 removeFolderRequestCount--;
1017 if (isHttpStatus204(http.status)) {
1018 if (http.callbackData)
1019 http.callbackData["method"](http.callbackData["data"]);
1022 window.alert(clabels["Unable to unsubscribe from that folder!"]);
1026 function unsubscribeFromFolder(folder, refreshCallback, refreshCallbackData) {
1027 if (document.body.hasClassName("popup")) {
1028 window.opener.unsubscribeFromFolder(folder, refreshCallback,
1029 refreshCallbackData);
1032 var folderData = folder.split("_");
1033 var username = folderData[0];
1034 var folderPath = folderData[1];
1035 if (username.startsWith('/'))
1036 username = username.substring(1);
1037 if (username != UserLogin) {
1038 var url = (ApplicationBaseURL + folder + "/unsubscribe");
1039 removeFolderRequestCount++;
1040 var rfCbData = { method: refreshCallback, data: refreshCallbackData };
1041 triggerAjaxRequest(url, folderUnsubscriptionCallback, rfCbData);
1044 window.alert(clabels["You cannot unsubscribe from a folder that you own!"]);
1048 function accessToSubscribedFolder(serverFolder) {
1051 var parts = serverFolder.split(":");
1052 if (parts.length > 1) {
1053 var paths = parts[1].split("/");
1054 folder = "/" + parts[0] + "_" + paths[2];
1057 folder = serverFolder;
1062 function getSubscribedFolderOwner(serverFolder) {
1065 var parts = serverFolder.split(":");
1066 if (parts.length > 1) {
1073 function getListIndexForFolder(items, owner, folderName) {
1075 var previousOwner = null;
1077 for (var i = 0; i < items.length; i++) {
1078 var currentFolderName = items[i].lastChild.nodeValue.strip();
1079 var currentOwner = items[i].readAttribute('owner');
1080 if (currentOwner == owner) {
1081 previousOwner = currentOwner;
1082 if (currentFolderName > folderName)
1085 else if (previousOwner ||
1086 (currentOwner != UserLogin && currentOwner > owner))
1088 else if (currentOwner == "nobody")
1095 function listRowMouseDownHandler(event) {
1096 preventDefault(event);
1097 //Event.stop(event);
1101 function initTabs() {
1102 var containers = document.getElementsByClassName("tabsContainer");
1103 for (var x = 0; x < containers.length; x++) {
1104 var container = containers[x];
1105 var firstTab = null;
1106 for (var i = 0; i < container.childNodes.length; i++) {
1107 if (container.childNodes[i].tagName == 'UL') {
1112 var nodes = container.childNodes[firstTab].childNodes;
1115 for (var i = 0; i < nodes.length; i++) {
1116 var currentNode = nodes[i];
1117 if (currentNode.tagName == 'LI') {
1120 $(currentNode).observe("mousedown", onTabMouseDown);
1121 $(currentNode).observe("click", onTabClick);
1122 //$(currentNode.getAttribute("target")).hide();
1126 nodes[firstTab].addClassName("first");
1127 nodes[firstTab].addClassName("active");
1128 container.activeTab = nodes[firstTab];
1130 var target = $(nodes[firstTab].getAttribute("target"));
1131 target.addClassName("active");
1136 function initMenus() {
1137 var menus = getMenus();
1139 for (var menuID in menus) {
1140 var menuDIV = $(menuID);
1142 initMenu(menuDIV, menus[menuID]);
1147 function initMenu(menuDIV, callbacks) {
1148 var lis = $(menuDIV.down("ul")).childNodesWithTag("li");
1149 for (var j = 0; j < lis.length; j++) {
1150 var node = $(lis[j]);
1151 node.observe("mousedown", listRowMouseDownHandler, false);
1152 var callback = callbacks[j];
1154 if (typeof(callback) == "string") {
1155 if (callback == "-")
1156 node.addClassName("separator");
1158 node.submenu = callback;
1159 node.addClassName("submenu");
1160 node.observe("mouseover", popupSubmenu);
1164 node.observe("mouseup", onBodyClickMenuHandler);
1165 node.observe("click", callback);
1169 node.addClassName("disabled");
1173 function onTabMouseDown(event) {
1174 event.cancelBubble = true;
1175 preventDefault(event);
1178 function openExternalLink(anchor) {
1182 function openAclWindow(url) {
1183 var w = window.open(url, "aclWindow",
1184 "width=420,height=300,resizable=1,scrollbars=1,toolbar=0,"
1185 + "location=0,directories=0,status=0,menubar=0"
1186 + ",copyhistory=0");
1193 function getUsersRightsWindowHeight() {
1194 return usersRightsWindowHeight;
1197 function getUsersRightsWindowWidth() {
1198 return usersRightsWindowWidth;
1201 function getTopWindow() {
1202 var topWindow = null;
1203 var currentWindow = window;
1204 while (!topWindow) {
1205 if (currentWindow.document.body.hasClassName("popup")
1206 && currentWindow.opener)
1207 currentWindow = currentWindow.opener;
1209 topWindow = currentWindow;
1215 function onTabClick(event) {
1216 var node = getTarget(event); // LI element
1218 var target = node.getAttribute("target");
1220 var container = node.parentNode.parentNode;
1221 var oldTarget = container.activeTab.getAttribute("target");
1222 var content = $(target);
1223 var oldContent = $(oldTarget);
1225 oldContent.removeClassName("active");
1226 container.activeTab.removeClassName("active"); // previous LI
1227 container.activeTab = node;
1228 container.activeTab.addClassName("active"); // current LI
1229 content.addClassName("active");
1231 // Prototype alternative
1233 //oldContent.removeClassName("active");
1234 //container.activeTab.removeClassName("active"); // previous LI
1235 //container.activeTab = node;
1236 //container.activeTab.addClassName("active"); // current LI
1238 //container.activeTab.hide();
1239 //oldContent.hide();
1242 //container.activeTab = node;
1243 //container.activeTab.show();
1248 function enableAnchor(anchor) {
1249 var classStr = '' + anchor.getAttribute("class");
1250 var position = classStr.indexOf("_disabled", 0);
1251 if (position > -1) {
1252 var disabledHref = anchor.getAttribute("disabled-href");
1254 anchor.setAttribute("href", disabledHref);
1255 var disabledOnclick = anchor.getAttribute("disabled-onclick");
1256 if (disabledOnclick)
1257 anchor.setAttribute("onclick", disabledOnclick);
1258 anchor.removeClassName("_disabled");
1259 anchor.setAttribute("disabled-href", null);
1260 anchor.setAttribute("disabled-onclick", null);
1261 anchor.disabled = 0;
1266 function disableAnchor(anchor) {
1267 var classStr = '' + anchor.getAttribute("class");
1268 var position = classStr.indexOf("_disabled", 0);
1270 var href = anchor.getAttribute("href");
1272 anchor.setAttribute("disabled-href", href);
1273 var onclick = anchor.getAttribute("onclick");
1275 anchor.setAttribute("disabled-onclick", onclick);
1276 anchor.addClassName("_disabled");
1277 anchor.setAttribute("href", "#");
1278 anchor.setAttribute("onclick", "return false;");
1279 anchor.disabled = 1;
1285 var hD = "0123456789abcdef";
1286 var h = hD.substr(d & 15, 1);
1290 h = hD.substr(d & 15, 1) + h;
1296 function indexColor(number) {
1302 var colorTable = new Array(1, 1, 1);
1304 var currentValue = number;
1306 while (currentValue) {
1307 if (currentValue & 1)
1308 colorTable[index]++;
1316 + d2h((256 / colorTable[2]) - 1)
1317 + d2h((256 / colorTable[1]) - 1)
1318 + d2h((256 / colorTable[0]) - 1));
1324 function loadPreferences() {
1325 var url = UserFolderURL + "jsonDefaults";
1326 var http = createHTTPClient();
1327 http.open("GET", url, false);
1329 if (http.status == 200) {
1330 if (http.responseText.length > 0)
1331 userDefaults = http.responseText.evalJSON(true);
1336 url = UserFolderURL + "jsonSettings";
1337 http.open("GET", url, false);
1339 if (http.status == 200) {
1340 if (http.responseText.length > 0)
1341 userSettings = http.responseText.evalJSON(true);
1347 function onLoadHandler(event) {
1348 if (typeof UserLogin != "undefined")
1350 queryParameters = parseQueryParameters('' + window.location);
1351 if (!$(document.body).hasClassName("popup")) {
1355 configureSearchField();
1358 configureDragHandles();
1359 configureLinkBanner();
1360 var progressImage = $("progressIndicator");
1362 progressImage.parentNode.removeChild(progressImage);
1363 $(document.body).observe("contextmenu", onBodyClickContextMenu);
1366 function onBodyClickContextMenu(event) {
1367 preventDefault(event);
1370 function configureSortableTableHeaders(table) {
1371 var headers = $(table).getElementsByClassName("sortableTableHeader");
1372 for (var i = 0; i < headers.length; i++) {
1373 var header = headers[i];
1374 $(header).observe("click", onHeaderClick);
1378 function onLinkBannerClick() {
1379 activeAjaxRequests++;
1380 checkAjaxRequestsState();
1383 function onPreferencesClick(event) {
1384 var urlstr = UserFolderURL + "preferences";
1385 var w = window.open(urlstr, "_blank",
1386 "width=430,height=250,resizable=0,scrollbars=0,location=0");
1390 preventDefault(event);
1393 function configureLinkBanner() {
1394 var linkBanner = $("linkBanner");
1396 var moduleLinks = [ "calendar", "contacts", "mail" ];
1397 for (var i = 0; i < moduleLinks.length; i++) {
1398 var link = $(moduleLinks[i] + "BannerLink");
1400 link.observe("mousedown", listRowMouseDownHandler);
1401 link.observe("click", onLinkBannerClick);
1404 link = $("preferencesBannerLink");
1406 link.observe("mousedown", listRowMouseDownHandler);
1407 link.observe("click", onPreferencesClick);
1409 link = $("consoleBannerLink");
1411 link.observe("mousedown", listRowMouseDownHandler);
1412 link.observe("click", toggleLogConsole);
1417 /* folder creation */
1418 function createFolder(name, okCB, notOkCB) {
1420 if (document.newFolderAjaxRequest) {
1421 document.newFolderAjaxRequest.aborted = true;
1422 document.newFolderAjaxRequest.abort();
1424 var url = ApplicationBaseURL + "/createFolder?name=" + name;
1425 document.newFolderAjaxRequest
1426 = triggerAjaxRequest(url, createFolderCallback,
1433 function createFolderCallback(http) {
1434 if (http.readyState == 4) {
1435 var data = http.callbackData;
1436 if (http.status == 201) {
1438 data.okCB(data.name, "/" + http.responseText, UserLogin);
1444 log("ajax problem:" + http.status);
1449 function onFinalLoadHandler(event) {
1450 var safetyNet = $("javascriptSafetyNet");
1452 safetyNet.parentNode.removeChild(safetyNet);
1455 FastInit.addOnLoad(onLoadHandler);
1457 function parent$(element) {
1458 return this.opener.document.getElementById(element);
1462 function refreshCurrentFolder() {
1465 function configureDragHandles() {
1468 function getMenus() {
1471 function onHeaderClick(event) {
1472 window.alert("generic headerClick");