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[1].startsWith('/'))
155 url += folderInfos[1];
158 url = ApplicationBaseURL + folderInfos[0];
160 if (url[url.length-1] == '/')
161 url = url.substr(0, url.length-1);
166 function extractEmailAddress(mailTo) {
170 = /([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;
171 if (emailre.test(mailTo)) {
172 emailre.exec(mailTo);
179 function extractEmailName(mailTo) {
182 var tmpMailTo = mailTo.replace("<", "<");
183 tmpMailTo = tmpMailTo.replace(">", ">");
185 var emailNamere = /([ ]+)?(.+)\ </;
186 if (emailNamere.test(tmpMailTo)) {
187 emailNamere.exec(tmpMailTo);
188 emailName = RegExp.$2;
194 function sanitizeMailTo(dirtyMailTo) {
195 var emailName = extractEmailName(dirtyMailTo);
196 var email = "" + extractEmailAddress(dirtyMailTo);
199 if (emailName && emailName.length > 0)
200 mailto = emailName + ' <' + email + '>';
207 function openUserFolderSelector(callback, type) {
208 var urlstr = ApplicationBaseURL;
209 if (! urlstr.endsWith('/'))
211 urlstr += ("../../" + UserLogin + "/Contacts/userFolders");
212 var w = window.open(urlstr, "_blank",
213 "width=322,height=250,resizable=1,scrollbars=0,location=0");
215 window.userFolderCallback = callback;
216 window.userFolderType = type;
220 function openContactWindow(url, wId) {
221 if (typeof wId == "undefined")
224 var r = new RegExp("[\.\/-]", "g");
225 wId = wId.replace(r, "_");
228 var w = window.open(url, wId,
229 "width=450,height=600,resizable=0,location=0");
235 function openMailComposeWindow(url, wId) {
236 var parentWindow = this;
238 if (typeof wId == "undefined")
241 var r = new RegExp("[\.\/-]", "g");
242 wId = wId.replace(r, "_");
243 if (document.body.hasClassName("popup"))
244 parentWindow = window.opener;
247 var w = parentWindow.open(url, wId,
248 "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
249 + "location=0,directories=0,status=0,menubar=0"
257 function openMailTo(senderMailTo) {
258 var mailto = sanitizeMailTo(senderMailTo);
259 if (mailto.length > 0)
260 openMailComposeWindow(ApplicationBaseURL
261 + "/../Mail/compose?mailto=" + mailto);
263 return false; /* stop following the link */
266 function createHTTPClient() {
267 // http://developer.apple.com/internet/webcontent/xmlhttpreq.html
268 if (typeof XMLHttpRequest != "undefined")
269 return new XMLHttpRequest();
271 try { return new ActiveXObject("Msxml2.XMLHTTP"); }
273 try { return new ActiveXObject("Microsoft.XMLHTTP"); }
279 function appendDifferentiator(url) {
280 var url_nocache = url;
281 var position = url.indexOf('?', 0);
286 url_nocache += 'differentiator=' + Math.floor(Math.random()*50000);
291 function triggerAjaxRequest(url, callback, userdata) {
292 var http = createHTTPClient();
294 activeAjaxRequests += 1;
295 document.animTimer = setTimeout("checkAjaxRequestsState();", 200);
296 //url = appendDifferentiator(url);
299 http.open("POST", url, true);
301 http.onreadystatechange
303 //log ("state changed (" + http.readyState + "): " + url);
305 if (http.readyState == 4
306 && activeAjaxRequests > 0) {
309 http.callbackData = userdata;
312 activeAjaxRequests -= 1;
313 checkAjaxRequestsState();
317 activeAjaxRequests -= 1;
318 checkAjaxRequestsState();
319 log("AJAX Request, Caught Exception: " + e.name);
327 log("triggerAjaxRequest: error creating HTTP Client!");
333 function startAnimation(parent, nextNode) {
334 var anim = $("progressIndicator");
335 if (anim) return anim;
337 anim = document.createElement("img");
339 anim.id = "progressIndicator";
340 anim.src = ResourcesURL + "/busy.gif";
341 anim.setStyle({ visibility: "hidden" });
343 parent.insertBefore(anim, nextNode);
345 parent.appendChild(anim);
346 anim.setStyle({ visibility: "visible" });
351 function checkAjaxRequestsState() {
352 var toolbar = document.getElementById("toolbar");
354 if (activeAjaxRequests > 0
355 && !document.busyAnim) {
356 document.busyAnim = startAnimation(toolbar);
358 else if (activeAjaxRequests == 0
360 && document.busyAnim.parentNode) {
361 document.busyAnim.parentNode.removeChild(document.busyAnim);
362 document.busyAnim = null;
367 function isSafari3() {
368 return (navigator.appVersion.indexOf("Version") > -1);
371 function isSafari() {
372 //var agt = navigator.userAgent.toLowerCase();
373 //var is_safari = ((agt.indexOf('safari')!=-1)&&(agt.indexOf('mac')!=-1))?true:false;
375 return (navigator.vendor == "Apple Computer, Inc.");
378 function isHttpStatus204(status) {
379 return (status == 204 || // Firefox
380 (isSafari() && typeof(status) == 'undefined') || // Safari
381 status == 1223); // IE
384 function getTarget(event) {
385 event = event || window.event;
387 return event.target; // W3C DOM
389 return event.srcElement; // IE
392 function preventDefault(event) {
393 if (event.preventDefault)
394 event.preventDefault(); // W3C DOM
396 event.returnValue = false; // IE
399 function resetSelection(win) {
401 if (win && win.getSelection) {
402 t = win.getSelection().toString();
403 win.getSelection().removeAllRanges();
408 function refreshOpener() {
409 if (window.opener && !window.opener.closed) {
410 window.opener.location.reload();
416 function parseQueryString() {
417 var queryArray, queryDict
418 var key, value, s, idx;
419 queryDict.length = 0;
421 queryDict = new Array();
422 queryArray = location.search.substr(1).split('&');
423 for (var i in queryArray) {
424 if (!queryArray[i]) continue ;
426 idx = s.indexOf("=");
432 key = s.substr(0, idx);
433 value = unescape(s.substr(idx + 1));
436 if (typeof queryDict[key] == 'undefined')
439 queryDict[key] = value;
444 function generateQueryString(queryDict) {
446 for (var key in queryDict) {
451 s = s + key + "=" + escape(queryDict[key]);
456 /* selection mechanism */
458 function deselectAll(parent) {
459 for (var i = 0; i < parent.childNodes.length; i++) {
460 var node = parent.childNodes.item(i);
461 if (node.nodeType == 1)
466 function isNodeSelected(node) {
467 return $(node).hasClassName('_selected');
470 function acceptMultiSelect(node) {
471 var response = false;
472 var attribute = node.getAttribute('multiselect');
473 if (attribute && attribute.length > 0) {
474 log("node '" + node.getAttribute("id")
475 + "' is still using old-stylemultiselect!");
476 response = (attribute.toLowerCase() == 'yes');
479 response = node.multiselect;
484 function onRowClick(event) {
485 var node = getTarget(event);
488 if (node.tagName == 'TD') {
489 node = node.parentNode; // select TR
490 rowIndex = node.rowIndex - $(node).up('table').down('thead').getElementsByTagName('tr').length;
492 else if (node.tagName == 'LI') {
493 // Find index of clicked row
494 var list = node.parentNode;
495 var items = list.childNodesWithTag("li");
496 for (var i = 0; i < items.length; i++) {
497 if (items[i] == node) {
504 var initialSelection = $(node.parentNode).getSelectedNodes();
505 if ((event.shiftKey == 1 || event.ctrlKey == 1)
506 && (lastClickedRow >= 0)
507 && (acceptMultiSelect(node.parentNode)
508 || acceptMultiSelect(node.parentNode.parentNode))) {
510 $(node.parentNode).selectRange(lastClickedRow, rowIndex);
511 else if (isNodeSelected(node) == true) {
516 // At this point, should empty content of 3-pane view
518 // Single line selection
519 $(node.parentNode).deselectAll();
522 if (initialSelection != $(node.parentNode).getSelectedNodes()) {
523 // Selection has changed; fire mousedown event
524 var parentNode = node.parentNode;
525 if (parentNode.tagName == 'TBODY')
526 parentNode = parentNode.parentNode;
527 if (document.createEvent) {
528 var onSelectionChangeEvent;
530 onSelectionChangeEvent = document.createEvent("UIEvents");
532 onSelectionChangeEvent = document.createEvent("Events");
533 onSelectionChangeEvent.initEvent("mousedown", true, true);
534 parentNode.dispatchEvent(onSelectionChangeEvent);
536 else if (document.createEventObject) {
537 parentNode.fireEvent("onmousedown");
541 lastClickedRow = rowIndex;
548 // var acceptClick = false;
550 function popupMenu(event, menuId, target) {
551 document.menuTarget = target;
553 if (document.currentPopupMenu)
554 hideMenu(document.currentPopupMenu);
556 var popup = $(menuId);
561 var pageContent = $("pageContent");
562 if (popup.parentNode.tagName != "BODY") {
563 var offset = pageContent.cascadeLeftOffset();
564 deltaX = -($(popup.parentNode).cascadeLeftOffset() - offset);
565 offset = pageContent.cascadeTopOffset();
566 deltaY = -($(popup.parentNode).cascadeTopOffset() - offset);
569 var menuTop = Event.pointerY(event) + deltaY;
570 var menuLeft = Event.pointerX(event) + deltaX;
571 var heightDiff = (window.height()
572 - (menuTop + popup.offsetHeight));
574 menuTop += heightDiff;
576 var leftDiff = (window.width()
577 - (menuLeft + popup.offsetWidth));
579 menuLeft -= popup.offsetWidth;
581 if (popup.prepareVisibility)
582 popup.prepareVisibility();
583 popup.setStyle({ top: menuTop + "px",
584 left: menuLeft + "px",
585 visibility: "visible" });
587 document.currentPopupMenu = popup;
589 Event.observe(document.body, "click", onBodyClickMenuHandler);
591 preventDefault(event);
594 function getParentMenu(node) {
595 var currentNode, menuNode;
599 var menure = new RegExp("(^|\s+)menu(\s+|$)", "i");
601 while (menuNode == null
603 if (menure.test(currentNode.className))
604 menuNode = currentNode;
606 currentNode = currentNode.parentNode;
611 function onBodyClickMenuHandler(event) {
612 hideMenu(document.currentPopupMenu);
613 Event.stopObserving(document.body, "click", onBodyClickMenuHandler);
616 preventDefault(event);
619 function hideMenu(menuNode) {
622 if (menuNode.submenu) {
623 hideMenu(menuNode.submenu);
624 menuNode.submenu = null;
627 menuNode.setStyle({ visibility: "hidden" });
629 if (menuNode.parentMenuItem) {
630 Event.stopObserving(menuNode.parentMenuItem, "mouseover",
631 onMouseEnteredSubmenu);
632 Event.stopObserving(menuNode, "mouseover", onMouseEnteredSubmenu);
633 Event.stopObserving(menuNode.parentMenuItem, "mouseout", onMouseLeftSubmenu);
634 Event.stopObserving(menuNode, "mouseout", onMouseLeftSubmenu);
635 Event.stopObserving(menuNode.parentMenu, "mouseover",
636 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 if (document.createEvent) { // Safari & Mozilla
648 onhideEvent = document.createEvent("UIEvents");
650 onhideEvent = document.createEvent("Events");
651 onhideEvent.initEvent("mousedown", false, true);
652 menuNode.dispatchEvent(onhideEvent);
654 else if (document.createEventObject) { // IE
655 menuNode.fireEvent("onmousedown");
659 function onMenuEntryClick(event) {
660 var node = event.target;
662 id = getParentMenu(node).menuTarget;
667 function parseQueryParameters(url) {
668 var parameters = new Array();
670 var params = url.split("?")[1];
672 var pairs = params.split("&");
673 for (var i = 0; i < pairs.length; i++) {
674 var pair = pairs[i].split("=");
675 parameters[pair[0]] = pair[1];
682 function initLogConsole() {
683 var logConsole = $("logConsole");
685 logConsole.highlighted = false;
686 Event.observe(logConsole, "dblclick", onLogDblClick, false);
687 logConsole.innerHTML = "";
688 Event.observe(window, "keydown", onBodyKeyDown);
692 function onBodyKeyDown(event) {
693 if (event.keyCode == 27) {
695 preventDefault(event);
699 function onLogDblClick(event) {
700 var logConsole = $("logConsole");
701 logConsole.innerHTML = "";
704 function toggleLogConsole(event) {
705 var logConsole = $("logConsole");
706 var display = '' + logConsole.style.display;
707 if (display.length == 0) {
708 logConsole.setStyle({ display: 'block' });
710 logConsole.setStyle({ display: '' });
713 preventDefault(event);
716 function log(message) {
719 while (logWindow.opener)
720 logWindow = logWindow.opener;
722 var logConsole = logWindow.document.getElementById("logConsole");
724 logConsole.highlighted = !logConsole.highlighted;
725 if (message == '\c') {
726 logConsole.innerHTML = "";
729 var logMessage = message.replace("<", "<", "g");
730 logMessage = logMessage.replace(" ", " ", "g");
731 logMessage = logMessage.replace("\r\n", "<br />\n", "g");
732 logMessage = logMessage.replace("\n", "<br />\n", "g");
733 logMessage += '<br />' + "\n";
734 if (logConsole.highlighted)
735 logMessage = '<div class="highlighted">' + logMessage + '</div>';
736 logConsole.innerHTML += logMessage;
740 function backtrace() {
741 var func = backtrace.caller;
742 var str = "backtrace:\n";
748 str += " " + func.name;
750 str += " (" + this + ")";
753 str += "[anonymous]\n";
763 function popupSubmenu(event) {
764 if (this.submenu && this.submenu != "") {
765 var submenuNode = $(this.submenu);
766 var parentNode = getParentMenu(this);
767 if (parentNode.submenu)
768 hideMenu(parentNode.submenu);
769 submenuNode.parentMenuItem = this;
770 submenuNode.parentMenu = parentNode;
771 parentNode.submenuItem = this;
772 parentNode.submenu = submenuNode;
774 if (submenuNode.prepareVisibility)
775 submenuNode.prepareVisibility();
777 var menuTop = (parentNode.offsetTop - 1
780 < (menuTop + submenuNode.offsetHeight)
781 && submenuNode.offsetHeight < window.height())
782 menuTop -= submenuNode.offsetHeight - this.offsetHeight - 4;
783 var menuLeft = (parentNode.offsetLeft + parentNode.offsetWidth - 3);
785 < (menuLeft + submenuNode.offsetWidth))
786 menuLeft = parentNode.offsetLeft - submenuNode.offsetWidth + 3;
788 this.mouseInside = true;
789 Event.observe(this, "mouseover",
790 onMouseEnteredSubmenu.bindAsEventListener(this));
791 Event.observe(submenuNode, "mouseover",
792 onMouseEnteredSubmenu.bindAsEventListener(submenuNode));
793 Event.observe(this, "mouseout", onMouseLeftSubmenu.bindAsEventListener(this));
794 Event.observe(submenuNode, "mouseout",
795 onMouseLeftSubmenu.bindAsEventListener(submenuNode));
796 Event.observe(parentNode, "mouseover",
797 onMouseEnteredParentMenu.bindAsEventListener(parentNode));
798 $(this).addClassName("submenu-selected");
799 submenuNode.setStyle({ top: menuTop + "px",
800 left: menuLeft + "px",
801 visibility: "visible" });
802 preventDefault(event);
806 function onMouseEnteredParentMenu(event) {
807 if (this.submenuItem && !this.submenuItem.mouseInside)
808 hideMenu(this.submenu);
811 function onMouseEnteredSubmenu(event) {
812 $(this).mouseInside = true;
815 function onMouseLeftSubmenu(event) {
816 $(this).mouseInside = false;
820 function popupSearchMenu(event) {
821 var menuId = this.getAttribute("menuid");
822 var offset = Position.cumulativeOffset(this);
824 relX = Event.pointerX(event) - offset[0];
825 relY = Event.pointerY(event) - offset[1];
827 if (event.button == 0
829 event.cancelBubble = true;
830 event.returnValue = false;
832 if (document.currentPopupMenu)
833 hideMenu(document.currentPopupMenu);
835 var popup = $(menuId);
836 offset = Position.positionedOffset(this);
837 popup.setStyle({ top: this.offsetHeight + "px",
838 left: (offset[0] + 3) + "px",
839 visibility: "visible" });
841 document.currentPopupMenu = popup;
842 Event.observe(document.body, "click", onBodyClickMenuHandler);
846 function setSearchCriteria(event) {
847 var searchValue = $("searchValue");
848 var searchCriteria = $("searchCriteria");
850 searchValue.setAttribute("ghost-phrase", this.innerHTML);
851 searchCriteria.value = this.getAttribute('id');
853 if (this.parentNode.chosenNode)
854 this.parentNode.chosenNode.removeClassName("_chosen");
855 this.addClassName("_chosen");
856 this.parentNode.chosenNode = this;
859 function checkSearchValue(event) {
860 var form = event.target;
861 var searchValue = $("searchValue");
862 var ghostPhrase = searchValue.getAttribute('ghost-phrase');
864 if (searchValue.value == ghostPhrase)
865 searchValue.value = "";
868 function onSearchChange() {
869 log ("onSearchChange()...");
872 function configureSearchField() {
873 var searchValue = $("searchValue");
874 var searchOptions = $("searchOptions");
876 if (!searchValue) return;
878 Event.observe(searchValue, "mousedown",
879 onSearchMouseDown.bindAsEventListener(searchValue));
880 Event.observe(searchValue, "click",
881 popupSearchMenu.bindAsEventListener(searchValue));
882 Event.observe(searchValue, "blur",
883 onSearchBlur.bindAsEventListener(searchValue));
884 Event.observe(searchValue, "focus",
885 onSearchFocus.bindAsEventListener(searchValue));
886 Event.observe(searchValue, "keydown",
887 onSearchKeyDown.bindAsEventListener(searchValue));
889 if (!searchOptions) return;
891 // Set the checkmark to the first option
892 var firstOption = searchOptions.down('li');
893 firstOption.addClassName("_chosen");
894 searchOptions.chosenNode = firstOption;
897 function onSearchMouseDown(event) {
898 var superNode = this.parentNode.parentNode.parentNode;
899 relX = (Event.pointerX(event) - superNode.offsetLeft - this.offsetLeft);
900 relY = (Event.pointerY(event) - superNode.offsetTop - this.offsetTop);
903 event.cancelBubble = true;
904 event.returnValue = false;
908 function onSearchFocus() {
909 ghostPhrase = this.getAttribute("ghost-phrase");
910 if (this.value == ghostPhrase) {
912 this.setAttribute("modified", "");
917 this.setStyle({ color: "#000" });
920 function onSearchBlur(event) {
921 var ghostPhrase = this.getAttribute("ghost-phrase");
924 this.setAttribute("modified", "");
925 this.setStyle({ color: "#aaa" });
926 this.value = ghostPhrase;
927 refreshCurrentFolder();
928 } else if (this.value == ghostPhrase) {
929 this.setAttribute("modified", "");
930 this.setStyle({ color: "#aaa" });
932 this.setAttribute("modified", "yes");
933 this.setStyle({ color: "#000" });
937 function onSearchKeyDown(event) {
939 clearTimeout(this.timer);
941 this.timer = setTimeout("onSearchFormSubmit()", 1000);
944 function onSearchFormSubmit(event) {
945 var searchValue = $("searchValue");
946 var searchCriteria = $("searchCriteria");
947 var ghostPhrase = searchValue.getAttribute('ghost-phrase');
949 if (searchValue.value == ghostPhrase) return;
951 search["criteria"] = searchCriteria.value;
952 search["value"] = searchValue.value;
954 refreshCurrentFolder();
957 function initCriteria() {
958 var searchCriteria = $("searchCriteria");
959 var searchValue = $("searchValue");
961 if (!searchValue) return;
963 var searchOptions = $("searchOptions").childNodesWithTag("li");
964 if (searchOptions.length > 0) {
965 var firstChild = searchOptions[0];
966 searchCriteria.value = $(firstChild).getAttribute('id');
967 searchValue.setAttribute('ghost-phrase', firstChild.innerHTML);
968 if (searchValue.value == '') {
969 searchValue.value = firstChild.innerHTML;
970 searchValue.setAttribute("modified", "");
971 searchValue.setStyle({ color: "#aaa" });
976 /* toolbar buttons */
977 function popupToolbarMenu(node, menuId) {
978 if (document.currentPopupMenu)
979 hideMenu(document.currentPopupMenu);
981 var popup = $(menuId);
982 var top = ($(node).getStyle('top') || 0) + node.offsetHeight - 2;
983 popup.setStyle({ top: top + "px",
984 left: $(node).cascadeLeftOffset() + "px",
985 visibility: "visible" });
987 document.currentPopupMenu = popup;
988 Event.observe(document.body, "click", onBodyClickMenuHandler);
991 /* contact selector */
993 function folderSubscriptionCallback(http) {
994 if (http.readyState == 4) {
995 if (isHttpStatus204(http.status)) {
996 if (http.callbackData)
997 http.callbackData["method"](http.callbackData["data"]);
1000 window.alert(clabels["Unable to subscribe to that folder!"]);
1001 document.subscriptionAjaxRequest = null;
1004 log ("folderSubscriptionCallback Ajax error");
1007 function subscribeToFolder(refreshCallback, refreshCallbackData) {
1008 var folderData = refreshCallbackData["folder"].split(":");
1009 var username = folderData[0];
1010 var folderPath = folderData[1];
1011 if (username != UserLogin) {
1012 var url = (UserFolderURL + "../" + username
1013 + folderPath + "/subscribe");
1014 if (document.subscriptionAjaxRequest) {
1015 document.subscriptionAjaxRequest.aborted = true;
1016 document.subscriptionAjaxRequest.abort();
1019 var rfCbData = { method: refreshCallback, data: refreshCallbackData };
1020 document.subscriptionAjaxRequest = triggerAjaxRequest(url,
1021 folderSubscriptionCallback,
1025 refreshCallbackData["window"].alert(clabels["You cannot subscribe to a folder that you own!"]);
1028 function folderUnsubscriptionCallback(http) {
1029 if (http.readyState == 4) {
1030 removeFolderRequestCount--;
1031 if (isHttpStatus204(http.status)) {
1032 if (http.callbackData)
1033 http.callbackData["method"](http.callbackData["data"]);
1036 window.alert(clabels["Unable to unsubscribe from that folder!"]);
1040 function unsubscribeFromFolder(folder, refreshCallback, refreshCallbackData) {
1041 if (document.body.hasClassName("popup")) {
1042 window.opener.unsubscribeFromFolder(folder, refreshCallback,
1043 refreshCallbackData);
1046 var folderData = folder.split("_");
1047 var username = folderData[0];
1048 var folderPath = folderData[1];
1049 if (username.startsWith('/'))
1050 username = username.substring(1);
1051 if (username != UserLogin) {
1052 var url = (ApplicationBaseURL + folder + "/unsubscribe");
1053 removeFolderRequestCount++;
1054 var rfCbData = { method: refreshCallback, data: refreshCallbackData };
1055 triggerAjaxRequest(url, folderUnsubscriptionCallback, rfCbData);
1058 window.alert(clabels["You cannot unsubscribe from a folder that you own!"]);
1062 function accessToSubscribedFolder(serverFolder) {
1065 var parts = serverFolder.split(":");
1066 if (parts.length > 1) {
1067 var paths = parts[1].split("/");
1068 folder = "/" + parts[0] + "_" + paths[2];
1071 folder = serverFolder;
1076 function getSubscribedFolderOwner(serverFolder) {
1079 var parts = serverFolder.split(":");
1080 if (parts.length > 1) {
1087 function listRowMouseDownHandler(event) {
1088 preventDefault(event);
1089 //Event.stop(event);
1093 function initTabs() {
1094 var containers = document.getElementsByClassName("tabsContainer");
1095 for (var x = 0; x < containers.length; x++) {
1096 var container = containers[x];
1097 var firstTab = null;
1098 for (var i = 0; i < container.childNodes.length; i++) {
1099 if (container.childNodes[i].tagName == 'UL') {
1104 var nodes = container.childNodes[firstTab].childNodes;
1107 for (var i = 0; i < nodes.length; i++) {
1108 var currentNode = nodes[i];
1109 if (currentNode.tagName == 'LI') {
1112 Event.observe(currentNode, "mousedown",
1113 onTabMouseDown.bindAsEventListener(currentNode));
1114 Event.observe(currentNode, "click",
1115 onTabClick.bindAsEventListener(currentNode));
1116 //$(currentNode.getAttribute("target")).hide();
1120 nodes[firstTab].addClassName("first");
1121 nodes[firstTab].addClassName("active");
1122 container.activeTab = nodes[firstTab];
1124 var target = $(nodes[firstTab].getAttribute("target"));
1125 target.addClassName("active");
1130 function initMenus() {
1131 var menus = getMenus();
1133 for (var menuID in menus) {
1134 var menuDIV = $(menuID);
1136 initMenu(menuDIV, menus[menuID]);
1141 function initMenu(menuDIV, callbacks) {
1142 var lis = $(menuDIV.childNodesWithTag("ul")[0]).childNodesWithTag("li");
1143 for (var j = 0; j < lis.length; j++) {
1144 var node = $(lis[j]);
1145 Event.observe(node, "mousedown",
1146 listRowMouseDownHandler.bindAsEventListener(node),
1148 var callback = callbacks[j];
1150 if (typeof(callback) == "string") {
1151 if (callback == "-")
1152 node.addClassName("separator");
1154 node.submenu = callback;
1155 node.addClassName("submenu");
1156 Event.observe(node, "mouseover",
1157 popupSubmenu.bindAsEventListener(node));
1161 Event.observe(node, "mouseup",
1162 onBodyClickMenuHandler);
1163 Event.observe(node, "click",
1164 $(callback).bindAsEventListener(node));
1168 node.addClassName("disabled");
1172 function onTabMouseDown(event) {
1173 event.cancelBubble = true;
1174 preventDefault(event);
1177 function openExternalLink(anchor) {
1181 function openAclWindow(url) {
1182 var w = window.open(url, "aclWindow",
1183 "width=420,height=300,resizable=1,scrollbars=1,toolbar=0,"
1184 + "location=0,directories=0,status=0,menubar=0"
1185 + ",copyhistory=0");
1192 function getUsersRightsWindowHeight() {
1193 return usersRightsWindowHeight;
1196 function getUsersRightsWindowWidth() {
1197 return usersRightsWindowWidth;
1200 function getTopWindow() {
1201 var topWindow = null;
1202 var currentWindow = window;
1203 while (!topWindow) {
1204 if (currentWindow.document.body.hasClassName("popup")
1205 && currentWindow.opener)
1206 currentWindow = currentWindow.opener;
1208 topWindow = currentWindow;
1214 function onTabClick(event) {
1215 var node = getTarget(event); // LI element
1217 var target = node.getAttribute("target");
1219 var container = node.parentNode.parentNode;
1220 var oldTarget = container.activeTab.getAttribute("target");
1221 var content = $(target);
1222 var oldContent = $(oldTarget);
1224 oldContent.removeClassName("active");
1225 container.activeTab.removeClassName("active"); // previous LI
1226 container.activeTab = node;
1227 container.activeTab.addClassName("active"); // current LI
1228 content.addClassName("active");
1230 // Prototype alternative
1232 //oldContent.removeClassName("active");
1233 //container.activeTab.removeClassName("active"); // previous LI
1234 //container.activeTab = node;
1235 //container.activeTab.addClassName("active"); // current LI
1237 //container.activeTab.hide();
1238 //oldContent.hide();
1241 //container.activeTab = node;
1242 //container.activeTab.show();
1247 function enableAnchor(anchor) {
1248 var classStr = '' + anchor.getAttribute("class");
1249 var position = classStr.indexOf("_disabled", 0);
1250 if (position > -1) {
1251 var disabledHref = anchor.getAttribute("disabled-href");
1253 anchor.setAttribute("href", disabledHref);
1254 var disabledOnclick = anchor.getAttribute("disabled-onclick");
1255 if (disabledOnclick)
1256 anchor.setAttribute("onclick", disabledOnclick);
1257 anchor.removeClassName("_disabled");
1258 anchor.setAttribute("disabled-href", null);
1259 anchor.setAttribute("disabled-onclick", null);
1260 anchor.disabled = 0;
1265 function disableAnchor(anchor) {
1266 var classStr = '' + anchor.getAttribute("class");
1267 var position = classStr.indexOf("_disabled", 0);
1269 var href = anchor.getAttribute("href");
1271 anchor.setAttribute("disabled-href", href);
1272 var onclick = anchor.getAttribute("onclick");
1274 anchor.setAttribute("disabled-onclick", onclick);
1275 anchor.addClassName("_disabled");
1276 anchor.setAttribute("href", "#");
1277 anchor.setAttribute("onclick", "return false;");
1278 anchor.disabled = 1;
1284 var hD = "0123456789abcdef";
1285 var h = hD.substr(d & 15, 1);
1289 h = hD.substr(d & 15, 1) + h;
1295 function indexColor(number) {
1301 var colorTable = new Array(1, 1, 1);
1303 var currentValue = number;
1305 while (currentValue) {
1306 if (currentValue & 1)
1307 colorTable[index]++;
1315 + d2h((256 / colorTable[2]) - 1)
1316 + d2h((256 / colorTable[1]) - 1)
1317 + d2h((256 / colorTable[0]) - 1));
1323 function loadPreferences() {
1324 var url = UserFolderURL + "jsonDefaults";
1325 var http = createHTTPClient();
1326 http.open("GET", url, false);
1328 if (http.status == 200) {
1329 if (http.responseText.length > 0)
1330 userDefaults = http.responseText.evalJSON(true);
1335 url = UserFolderURL + "jsonSettings";
1336 http.open("GET", url, false);
1338 if (http.status == 200) {
1339 if (http.responseText.length > 0)
1340 userSettings = http.responseText.evalJSON(true);
1346 function onLoadHandler(event) {
1347 if (typeof UserLogin != "undefined")
1349 queryParameters = parseQueryParameters('' + window.location);
1350 if (!$(document.body).hasClassName("popup")) {
1354 configureSearchField();
1357 configureDragHandles();
1358 configureLinkBanner();
1359 var progressImage = $("progressIndicator");
1361 progressImage.parentNode.removeChild(progressImage);
1362 Event.observe(document.body, "contextmenu", onBodyClickContextMenu);
1365 function onBodyClickContextMenu(event) {
1366 preventDefault(event);
1369 function configureSortableTableHeaders(table) {
1370 var headers = $(table).getElementsByClassName("sortableTableHeader");
1371 for (var i = 0; i < headers.length; i++) {
1372 var header = headers[i];
1373 Event.observe(header, "click", onHeaderClick.bindAsEventListener(header))
1377 function onLinkBannerClick() {
1378 activeAjaxRequests++;
1379 checkAjaxRequestsState();
1382 function onPreferencesClick(event) {
1383 var urlstr = UserFolderURL + "preferences";
1384 var w = window.open(urlstr, "_blank",
1385 "width=430,height=250,resizable=0,scrollbars=0,location=0");
1389 preventDefault(event);
1392 function configureLinkBanner() {
1393 var linkBanner = $("linkBanner");
1395 var anchors = linkBanner.childNodesWithTag("a");
1396 for (var i = 1; i < 3; i++) {
1397 Event.observe(anchors[i], "mousedown", listRowMouseDownHandler);
1398 Event.observe(anchors[i], "click", onLinkBannerClick);
1400 Event.observe(anchors[4], "mousedown", listRowMouseDownHandler);
1401 Event.observe(anchors[4], "click", onPreferencesClick);
1402 if (anchors.length > 5)
1403 Event.observe(anchors[5], "click", toggleLogConsole);
1407 /* folder creation */
1408 function createFolder(name, okCB, notOkCB) {
1410 if (document.newFolderAjaxRequest) {
1411 document.newFolderAjaxRequest.aborted = true;
1412 document.newFolderAjaxRequest.abort();
1414 var url = ApplicationBaseURL + "/createFolder?name=" + name;
1415 document.newFolderAjaxRequest
1416 = triggerAjaxRequest(url, createFolderCallback,
1423 function createFolderCallback(http) {
1424 if (http.readyState == 4) {
1425 var data = http.callbackData;
1426 if (http.status == 201) {
1428 data.okCB(data.name, "/" + http.responseText, UserLogin);
1434 log("ajax problem:" + http.status);
1439 addEvent(window, 'load', onLoadHandler);
1441 function parent$(element) {
1442 return this.opener.document.getElementById(element);
1446 function refreshCurrentFolder() {
1449 function configureDragHandles() {
1452 function getMenus() {
1455 function onHeaderClick(event) {
1456 window.alert("generic headerClick");