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 = null;
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) {
222 wId = "" + (new Date().getTime());
223 var w = window.open(url, wId,
224 "width=450,height=600,resizable=0,location=0");
230 function openMailComposeWindow(url, wId) {
231 var parentWindow = this;
234 wId = "" + (new Date().getTime());
236 if (document.body.hasClassName("popup"))
237 parentWindow = window.opener;
239 var w = parentWindow.open(url, wId,
240 "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
241 + "location=0,directories=0,status=0,menubar=0"
249 function openMailTo(senderMailTo) {
250 var mailto = sanitizeMailTo(senderMailTo);
251 if (mailto.length > 0)
252 openMailComposeWindow(ApplicationBaseURL
253 + "/../Mail/compose?mailto=" + mailto);
255 return false; /* stop following the link */
258 function createHTTPClient() {
259 // http://developer.apple.com/internet/webcontent/xmlhttpreq.html
260 if (typeof XMLHttpRequest != "undefined")
261 return new XMLHttpRequest();
263 try { return new ActiveXObject("Msxml2.XMLHTTP"); }
265 try { return new ActiveXObject("Microsoft.XMLHTTP"); }
271 function appendDifferentiator(url) {
272 var url_nocache = url;
273 var position = url.indexOf('?', 0);
278 url_nocache += 'differentiator=' + Math.floor(Math.random()*50000);
283 function triggerAjaxRequest(url, callback, userdata) {
284 var http = createHTTPClient();
286 activeAjaxRequests += 1;
287 document.animTimer = setTimeout("checkAjaxRequestsState();", 200);
288 //url = appendDifferentiator(url);
291 http.open("POST", url, true);
293 http.onreadystatechange
295 //log ("state changed (" + http.readyState + "): " + url);
297 if (http.readyState == 4
298 && activeAjaxRequests > 0) {
301 http.callbackData = userdata;
304 activeAjaxRequests -= 1;
305 checkAjaxRequestsState();
309 activeAjaxRequests -= 1;
310 checkAjaxRequestsState();
311 log("AJAX Request, Caught Exception: " + e.name);
319 log("triggerAjaxRequest: error creating HTTP Client!");
325 function startAnimation(parent, nextNode) {
326 var anim = $("progressIndicator");
327 if (anim) return anim;
329 anim = document.createElement("img");
331 anim.id = "progressIndicator";
332 anim.src = ResourcesURL + "/busy.gif";
333 anim.setStyle({ visibility: "hidden" });
335 parent.insertBefore(anim, nextNode);
337 parent.appendChild(anim);
338 anim.setStyle({ visibility: "visible" });
343 function checkAjaxRequestsState() {
344 var toolbar = document.getElementById("toolbar");
346 if (activeAjaxRequests > 0
347 && !document.busyAnim) {
348 document.busyAnim = startAnimation(toolbar);
350 else if (activeAjaxRequests == 0
352 && document.busyAnim.parentNode) {
353 document.busyAnim.parentNode.removeChild(document.busyAnim);
354 document.busyAnim = null;
359 function isSafari3() {
360 return (navigator.appVersion.indexOf("Version") > -1);
363 function isSafari() {
364 //var agt = navigator.userAgent.toLowerCase();
365 //var is_safari = ((agt.indexOf('safari')!=-1)&&(agt.indexOf('mac')!=-1))?true:false;
367 return (navigator.vendor == "Apple Computer, Inc.");
370 function isHttpStatus204(status) {
371 return (status == 204 || // Firefox
372 (isSafari() && typeof(status) == 'undefined') || // Safari
373 status == 1223); // IE
376 function getTarget(event) {
377 event = event || window.event;
379 return event.target; // W3C DOM
381 return event.srcElement; // IE
384 function preventDefault(event) {
385 if (event.preventDefault)
386 event.preventDefault(); // W3C DOM
388 event.returnValue = false; // IE
391 function resetSelection(win) {
393 if (win && win.getSelection) {
394 t = win.getSelection().toString();
395 win.getSelection().removeAllRanges();
400 function refreshOpener() {
401 if (window.opener && !window.opener.closed) {
402 window.opener.location.reload();
408 function parseQueryString() {
409 var queryArray, queryDict
410 var key, value, s, idx;
411 queryDict.length = 0;
413 queryDict = new Array();
414 queryArray = location.search.substr(1).split('&');
415 for (var i in queryArray) {
416 if (!queryArray[i]) continue ;
418 idx = s.indexOf("=");
424 key = s.substr(0, idx);
425 value = unescape(s.substr(idx + 1));
428 if (typeof queryDict[key] == 'undefined')
431 queryDict[key] = value;
436 function generateQueryString(queryDict) {
438 for (var key in queryDict) {
443 s = s + key + "=" + escape(queryDict[key]);
448 /* selection mechanism */
450 function deselectAll(parent) {
451 for (var i = 0; i < parent.childNodes.length; i++) {
452 var node = parent.childNodes.item(i);
453 if (node.nodeType == 1)
458 function isNodeSelected(node) {
459 return $(node).hasClassName('_selected');
462 function acceptMultiSelect(node) {
463 var response = false;
464 var attribute = node.getAttribute('multiselect');
465 if (attribute && attribute.length > 0) {
466 log("node '" + node.getAttribute("id")
467 + "' is still using old-stylemultiselect!");
468 response = (attribute.toLowerCase() == 'yes');
471 response = node.multiselect;
476 function onRowClick(event) {
477 var node = getTarget(event);
480 if (node.tagName == 'TD') {
481 node = node.parentNode; // select TR
482 rowIndex = node.rowIndex - $(node).up('table').down('thead').getElementsByTagName('tr').length;
484 else if (node.tagName == 'LI') {
485 // Find index of clicked row
486 var list = node.parentNode;
487 var items = list.childNodesWithTag("li");
488 for (var i = 0; i < items.length; i++) {
489 if (items[i] == node) {
496 var initialSelection = $(node.parentNode).getSelectedNodes();
497 if ((event.shiftKey == 1 || event.ctrlKey == 1)
499 && (acceptMultiSelect(node.parentNode)
500 || acceptMultiSelect(node.parentNode.parentNode))) {
502 $(node.parentNode).selectRange(lastClickedRow, rowIndex);
503 else if (isNodeSelected(node) == true) {
508 // At this point, should empty content of 3-pane view
510 // Single line selection
511 $(node.parentNode).deselectAll();
514 if (initialSelection != $(node.parentNode).getSelectedNodes()) {
515 // Selection has changed; fire mousedown event
516 var parentNode = node.parentNode;
517 if (parentNode.tagName == 'TBODY')
518 parentNode = parentNode.parentNode;
519 if (document.createEvent) {
520 var onSelectionChangeEvent;
522 onSelectionChangeEvent = document.createEvent("UIEvents");
524 onSelectionChangeEvent = document.createEvent("Events");
525 onSelectionChangeEvent.initEvent("mousedown", true, true);
526 parentNode.dispatchEvent(onSelectionChangeEvent);
528 else if (document.createEventObject) {
529 parentNode.fireEvent("onmousedown");
533 lastClickedRow = rowIndex;
540 // var acceptClick = false;
542 function popupMenu(event, menuId, target) {
543 document.menuTarget = target;
545 if (document.currentPopupMenu)
546 hideMenu(document.currentPopupMenu);
548 var popup = $(menuId);
553 var pageContent = $("pageContent");
554 if (popup.parentNode.tagName != "BODY") {
555 var offset = pageContent.cascadeLeftOffset();
556 deltaX = -($(popup.parentNode).cascadeLeftOffset() - offset);
557 offset = pageContent.cascadeTopOffset();
558 deltaY = -($(popup.parentNode).cascadeTopOffset() - offset);
561 var menuTop = Event.pointerY(event) + deltaY;
562 var menuLeft = Event.pointerX(event) + deltaX;
563 var heightDiff = (window.height()
564 - (menuTop + popup.offsetHeight));
566 menuTop += heightDiff;
568 var leftDiff = (window.width()
569 - (menuLeft + popup.offsetWidth));
571 menuLeft -= popup.offsetWidth;
573 if (popup.prepareVisibility)
574 popup.prepareVisibility();
575 popup.setStyle({ top: menuTop + "px",
576 left: menuLeft + "px",
577 visibility: "visible" });
579 document.currentPopupMenu = popup;
581 Event.observe(document.body, "click", onBodyClickMenuHandler);
583 preventDefault(event);
586 function getParentMenu(node) {
587 var currentNode, menuNode;
591 var menure = new RegExp("(^|\s+)menu(\s+|$)", "i");
593 while (menuNode == null
595 if (menure.test(currentNode.className))
596 menuNode = currentNode;
598 currentNode = currentNode.parentNode;
603 function onBodyClickMenuHandler(event) {
604 hideMenu(document.currentPopupMenu);
605 Event.stopObserving(document.body, "click", onBodyClickMenuHandler);
608 preventDefault(event);
611 function hideMenu(menuNode) {
614 if (menuNode.submenu) {
615 hideMenu(menuNode.submenu);
616 menuNode.submenu = null;
619 menuNode.setStyle({ visibility: "hidden" });
621 if (menuNode.parentMenuItem) {
622 Event.stopObserving(menuNode.parentMenuItem, "mouseover",
623 onMouseEnteredSubmenu);
624 Event.stopObserving(menuNode, "mouseover", onMouseEnteredSubmenu);
625 Event.stopObserving(menuNode.parentMenuItem, "mouseout", onMouseLeftSubmenu);
626 Event.stopObserving(menuNode, "mouseout", onMouseLeftSubmenu);
627 Event.stopObserving(menuNode.parentMenu, "mouseover",
628 onMouseEnteredParentMenu);
629 $(menuNode.parentMenuItem).removeClassName("submenu-selected");
630 menuNode.parentMenuItem.mouseInside = false;
631 menuNode.parentMenuItem = null;
632 menuNode.parentMenu.submenuItem = null;
633 menuNode.parentMenu.submenu = null;
634 menuNode.parentMenu = null;
637 if (document.createEvent) { // Safari & Mozilla
640 onhideEvent = document.createEvent("UIEvents");
642 onhideEvent = document.createEvent("Events");
643 onhideEvent.initEvent("mousedown", false, true);
644 menuNode.dispatchEvent(onhideEvent);
646 else if (document.createEventObject) { // IE
647 menuNode.fireEvent("onmousedown");
651 function onMenuEntryClick(event) {
652 var node = event.target;
654 id = getParentMenu(node).menuTarget;
659 function parseQueryParameters(url) {
660 var parameters = new Array();
662 var params = url.split("?")[1];
664 var pairs = params.split("&");
665 for (var i = 0; i < pairs.length; i++) {
666 var pair = pairs[i].split("=");
667 parameters[pair[0]] = pair[1];
674 function initLogConsole() {
675 var logConsole = $("logConsole");
677 logConsole.highlighted = false;
678 Event.observe(logConsole, "dblclick", onLogDblClick, false);
679 logConsole.innerHTML = "";
680 Event.observe(window, "keydown", onBodyKeyDown);
684 function onBodyKeyDown(event) {
685 if (event.keyCode == 27) {
687 preventDefault(event);
691 function onLogDblClick(event) {
692 var logConsole = $("logConsole");
693 logConsole.innerHTML = "";
696 function toggleLogConsole(event) {
697 var logConsole = $("logConsole");
698 var display = '' + logConsole.style.display;
699 if (display.length == 0) {
700 logConsole.setStyle({ display: 'block' });
702 logConsole.setStyle({ display: '' });
705 preventDefault(event);
708 function log(message) {
711 while (logWindow.opener)
712 logWindow = logWindow.opener;
714 var logConsole = logWindow.document.getElementById("logConsole");
716 logConsole.highlighted = !logConsole.highlighted;
717 if (message == '\c') {
718 logConsole.innerHTML = "";
721 var logMessage = message.replace("<", "<", "g");
722 logMessage = logMessage.replace(" ", " ", "g");
723 logMessage = logMessage.replace("\r\n", "<br />\n", "g");
724 logMessage = logMessage.replace("\n", "<br />\n", "g");
725 logMessage += '<br />' + "\n";
726 if (logConsole.highlighted)
727 logMessage = '<div class="highlighted">' + logMessage + '</div>';
728 logConsole.innerHTML += logMessage;
732 function backtrace() {
733 var func = backtrace.caller;
734 var str = "backtrace:\n";
740 str += " " + func.name;
742 str += " (" + this + ")";
745 str += "[anonymous]\n";
755 function popupSubmenu(event) {
756 if (this.submenu && this.submenu != "") {
757 var submenuNode = $(this.submenu);
758 var parentNode = getParentMenu(this);
759 if (parentNode.submenu)
760 hideMenu(parentNode.submenu);
761 submenuNode.parentMenuItem = this;
762 submenuNode.parentMenu = parentNode;
763 parentNode.submenuItem = this;
764 parentNode.submenu = submenuNode;
766 if (submenuNode.prepareVisibility)
767 submenuNode.prepareVisibility();
769 var menuTop = (parentNode.offsetTop - 1
772 < (menuTop + submenuNode.offsetHeight)
773 && submenuNode.offsetHeight < window.height())
774 menuTop -= submenuNode.offsetHeight - this.offsetHeight - 4;
775 var menuLeft = (parentNode.offsetLeft + parentNode.offsetWidth - 3);
777 < (menuLeft + submenuNode.offsetWidth))
778 menuLeft = parentNode.offsetLeft - submenuNode.offsetWidth + 3;
780 this.mouseInside = true;
781 Event.observe(this, "mouseover",
782 onMouseEnteredSubmenu.bindAsEventListener(this));
783 Event.observe(submenuNode, "mouseover",
784 onMouseEnteredSubmenu.bindAsEventListener(submenuNode));
785 Event.observe(this, "mouseout", onMouseLeftSubmenu.bindAsEventListener(this));
786 Event.observe(submenuNode, "mouseout",
787 onMouseLeftSubmenu.bindAsEventListener(submenuNode));
788 Event.observe(parentNode, "mouseover",
789 onMouseEnteredParentMenu.bindAsEventListener(parentNode));
790 $(this).addClassName("submenu-selected");
791 submenuNode.setStyle({ top: menuTop + "px",
792 left: menuLeft + "px",
793 visibility: "visible" });
794 preventDefault(event);
798 function onMouseEnteredParentMenu(event) {
799 if (this.submenuItem && !this.submenuItem.mouseInside)
800 hideMenu(this.submenu);
803 function onMouseEnteredSubmenu(event) {
804 $(this).mouseInside = true;
807 function onMouseLeftSubmenu(event) {
808 $(this).mouseInside = false;
812 function popupSearchMenu(event) {
813 var menuId = this.getAttribute("menuid");
814 var offset = Position.cumulativeOffset(this);
816 relX = Event.pointerX(event) - offset[0];
817 relY = Event.pointerY(event) - offset[1];
819 if (event.button == 0
821 event.cancelBubble = true;
822 event.returnValue = false;
824 if (document.currentPopupMenu)
825 hideMenu(document.currentPopupMenu);
827 var popup = $(menuId);
828 offset = Position.positionedOffset(this);
829 popup.setStyle({ top: this.offsetHeight + "px",
830 left: (offset[0] + 3) + "px",
831 visibility: "visible" });
833 document.currentPopupMenu = popup;
834 Event.observe(document.body, "click", onBodyClickMenuHandler);
838 function setSearchCriteria(event) {
839 var searchValue = $("searchValue");
840 var searchCriteria = $("searchCriteria");
842 searchValue.setAttribute("ghost-phrase", this.innerHTML);
843 searchCriteria.value = this.getAttribute('id');
845 if (this.parentNode.chosenNode)
846 this.parentNode.chosenNode.removeClassName("_chosen");
847 this.addClassName("_chosen");
848 this.parentNode.chosenNode = this;
851 function checkSearchValue(event) {
852 var form = event.target;
853 var searchValue = $("searchValue");
854 var ghostPhrase = searchValue.getAttribute('ghost-phrase');
856 if (searchValue.value == ghostPhrase)
857 searchValue.value = "";
860 function onSearchChange() {
861 log ("onSearchChange()...");
864 function configureSearchField() {
865 var searchValue = $("searchValue");
866 var searchOptions = $("searchOptions");
868 if (!searchValue) return;
870 Event.observe(searchValue, "mousedown",
871 onSearchMouseDown.bindAsEventListener(searchValue));
872 Event.observe(searchValue, "click",
873 popupSearchMenu.bindAsEventListener(searchValue));
874 Event.observe(searchValue, "blur",
875 onSearchBlur.bindAsEventListener(searchValue));
876 Event.observe(searchValue, "focus",
877 onSearchFocus.bindAsEventListener(searchValue));
878 Event.observe(searchValue, "keydown",
879 onSearchKeyDown.bindAsEventListener(searchValue));
881 if (!searchOptions) return;
883 // Set the checkmark to the first option
884 var firstOption = searchOptions.down('li');
885 firstOption.addClassName("_chosen");
886 searchOptions.chosenNode = firstOption;
889 function onSearchMouseDown(event) {
890 var superNode = this.parentNode.parentNode.parentNode;
891 relX = (Event.pointerX(event) - superNode.offsetLeft - this.offsetLeft);
892 relY = (Event.pointerY(event) - superNode.offsetTop - this.offsetTop);
895 event.cancelBubble = true;
896 event.returnValue = false;
900 function onSearchFocus() {
901 ghostPhrase = this.getAttribute("ghost-phrase");
902 if (this.value == ghostPhrase) {
904 this.setAttribute("modified", "");
909 this.setStyle({ color: "#000" });
912 function onSearchBlur(event) {
913 var ghostPhrase = this.getAttribute("ghost-phrase");
916 this.setAttribute("modified", "");
917 this.setStyle({ color: "#aaa" });
918 this.value = ghostPhrase;
919 refreshCurrentFolder();
920 } else if (this.value == ghostPhrase) {
921 this.setAttribute("modified", "");
922 this.setStyle({ color: "#aaa" });
924 this.setAttribute("modified", "yes");
925 this.setStyle({ color: "#000" });
929 function onSearchKeyDown(event) {
931 clearTimeout(this.timer);
933 this.timer = setTimeout("onSearchFormSubmit()", 1000);
936 function onSearchFormSubmit(event) {
937 var searchValue = $("searchValue");
938 var searchCriteria = $("searchCriteria");
939 var ghostPhrase = searchValue.getAttribute('ghost-phrase');
941 if (searchValue.value == ghostPhrase) return;
943 search["criteria"] = searchCriteria.value;
944 search["value"] = searchValue.value;
946 refreshCurrentFolder();
949 function initCriteria() {
950 var searchCriteria = $("searchCriteria");
951 var searchValue = $("searchValue");
953 if (!searchValue) return;
955 var searchOptions = $("searchOptions").childNodesWithTag("li");
956 if (searchOptions.length > 0) {
957 var firstChild = searchOptions[0];
958 searchCriteria.value = $(firstChild).getAttribute('id');
959 searchValue.setAttribute('ghost-phrase', firstChild.innerHTML);
960 if (searchValue.value == '') {
961 searchValue.value = firstChild.innerHTML;
962 searchValue.setAttribute("modified", "");
963 searchValue.setStyle({ color: "#aaa" });
968 /* toolbar buttons */
969 function popupToolbarMenu(node, menuId) {
970 if (document.currentPopupMenu)
971 hideMenu(document.currentPopupMenu);
973 var popup = $(menuId);
974 var top = ($(node).getStyle('top') || 0) + node.offsetHeight - 2;
975 popup.setStyle({ top: top + "px",
976 left: $(node).cascadeLeftOffset() + "px",
977 visibility: "visible" });
979 document.currentPopupMenu = popup;
980 Event.observe(document.body, "click", onBodyClickMenuHandler);
983 /* contact selector */
985 function folderSubscriptionCallback(http) {
986 if (http.readyState == 4) {
987 if (isHttpStatus204(http.status)) {
988 if (http.callbackData)
989 http.callbackData["method"](http.callbackData["data"]);
992 window.alert(clabels["Unable to subscribe to that folder!"]);
993 document.subscriptionAjaxRequest = null;
996 log ("folderSubscriptionCallback Ajax error");
999 function subscribeToFolder(refreshCallback, refreshCallbackData) {
1000 var folderData = refreshCallbackData["folder"].split(":");
1001 var username = folderData[0];
1002 var folderPath = folderData[1];
1003 if (username != UserLogin) {
1004 var url = (UserFolderURL + "../" + username
1005 + folderPath + "/subscribe");
1006 if (document.subscriptionAjaxRequest) {
1007 document.subscriptionAjaxRequest.aborted = true;
1008 document.subscriptionAjaxRequest.abort();
1011 var rfCbData = { method: refreshCallback, data: refreshCallbackData };
1012 document.subscriptionAjaxRequest = triggerAjaxRequest(url,
1013 folderSubscriptionCallback,
1017 refreshCallbackData["window"].alert(clabels["You cannot subscribe to a folder that you own!"]);
1020 function folderUnsubscriptionCallback(http) {
1021 if (http.readyState == 4) {
1022 removeFolderRequestCount--;
1023 if (isHttpStatus204(http.status)) {
1024 if (http.callbackData)
1025 http.callbackData["method"](http.callbackData["data"]);
1028 window.alert(clabels["Unable to unsubscribe from that folder!"]);
1032 function unsubscribeFromFolder(folder, refreshCallback, refreshCallbackData) {
1033 if (document.body.hasClassName("popup")) {
1034 window.opener.unsubscribeFromFolder(folder, refreshCallback,
1035 refreshCallbackData);
1038 var folderData = folder.split("_");
1039 var username = folderData[0];
1040 var folderPath = folderData[1];
1041 if (username.startsWith('/'))
1042 username = username.substring(1);
1043 if (username != UserLogin) {
1044 var url = (ApplicationBaseURL + folder + "/unsubscribe");
1045 removeFolderRequestCount++;
1046 var rfCbData = { method: refreshCallback, data: refreshCallbackData };
1047 triggerAjaxRequest(url, folderUnsubscriptionCallback, rfCbData);
1050 window.alert(clabels["You cannot unsubscribe from a folder that you own!"]);
1054 function accessToSubscribedFolder(serverFolder) {
1057 var parts = serverFolder.split(":");
1058 if (parts.length > 1) {
1059 var paths = parts[1].split("/");
1060 folder = "/" + parts[0] + "_" + paths[2];
1063 folder = serverFolder;
1068 function getSubscribedFolderOwner(serverFolder) {
1071 var parts = serverFolder.split(":");
1072 if (parts.length > 1) {
1079 function listRowMouseDownHandler(event) {
1080 preventDefault(event);
1081 //Event.stop(event);
1085 function initTabs() {
1086 var containers = document.getElementsByClassName("tabsContainer");
1087 for (var x = 0; x < containers.length; x++) {
1088 var container = containers[x];
1089 var firstTab = null;
1090 for (var i = 0; i < container.childNodes.length; i++) {
1091 if (container.childNodes[i].tagName == 'UL') {
1096 var nodes = container.childNodes[firstTab].childNodes;
1099 for (var i = 0; i < nodes.length; i++) {
1100 var currentNode = nodes[i];
1101 if (currentNode.tagName == 'LI') {
1104 Event.observe(currentNode, "mousedown",
1105 onTabMouseDown.bindAsEventListener(currentNode));
1106 Event.observe(currentNode, "click",
1107 onTabClick.bindAsEventListener(currentNode));
1108 //$(currentNode.getAttribute("target")).hide();
1112 nodes[firstTab].addClassName("first");
1113 nodes[firstTab].addClassName("active");
1114 container.activeTab = nodes[firstTab];
1116 var target = $(nodes[firstTab].getAttribute("target"));
1117 target.addClassName("active");
1122 function initMenus() {
1123 var menus = getMenus();
1125 for (var menuID in menus) {
1126 var menuDIV = $(menuID);
1128 initMenu(menuDIV, menus[menuID]);
1133 function initMenu(menuDIV, callbacks) {
1134 var lis = $(menuDIV.childNodesWithTag("ul")[0]).childNodesWithTag("li");
1135 for (var j = 0; j < lis.length; j++) {
1136 var node = $(lis[j]);
1137 Event.observe(node, "mousedown",
1138 listRowMouseDownHandler.bindAsEventListener(node),
1140 var callback = callbacks[j];
1142 if (typeof(callback) == "string") {
1143 if (callback == "-")
1144 node.addClassName("separator");
1146 node.submenu = callback;
1147 node.addClassName("submenu");
1148 Event.observe(node, "mouseover",
1149 popupSubmenu.bindAsEventListener(node));
1153 Event.observe(node, "mouseup",
1154 onBodyClickMenuHandler);
1155 Event.observe(node, "click",
1156 $(callback).bindAsEventListener(node));
1160 node.addClassName("disabled");
1164 function onTabMouseDown(event) {
1165 event.cancelBubble = true;
1166 preventDefault(event);
1169 function openExternalLink(anchor) {
1173 function openAclWindow(url) {
1174 var w = window.open(url, "aclWindow",
1175 "width=420,height=300,resizable=1,scrollbars=1,toolbar=0,"
1176 + "location=0,directories=0,status=0,menubar=0"
1177 + ",copyhistory=0");
1184 function getUsersRightsWindowHeight() {
1185 return usersRightsWindowHeight;
1188 function getUsersRightsWindowWidth() {
1189 return usersRightsWindowWidth;
1192 function getTopWindow() {
1193 var topWindow = null;
1194 var currentWindow = window;
1195 while (!topWindow) {
1196 if (currentWindow.document.body.hasClassName("popup")
1197 && currentWindow.opener)
1198 currentWindow = currentWindow.opener;
1200 topWindow = currentWindow;
1206 function onTabClick(event) {
1207 var node = getTarget(event); // LI element
1209 var target = node.getAttribute("target");
1211 var container = node.parentNode.parentNode;
1212 var oldTarget = container.activeTab.getAttribute("target");
1213 var content = $(target);
1214 var oldContent = $(oldTarget);
1216 oldContent.removeClassName("active");
1217 container.activeTab.removeClassName("active"); // previous LI
1218 container.activeTab = node;
1219 container.activeTab.addClassName("active"); // current LI
1220 content.addClassName("active");
1222 // Prototype alternative
1224 //oldContent.removeClassName("active");
1225 //container.activeTab.removeClassName("active"); // previous LI
1226 //container.activeTab = node;
1227 //container.activeTab.addClassName("active"); // current LI
1229 //container.activeTab.hide();
1230 //oldContent.hide();
1233 //container.activeTab = node;
1234 //container.activeTab.show();
1239 function enableAnchor(anchor) {
1240 var classStr = '' + anchor.getAttribute("class");
1241 var position = classStr.indexOf("_disabled", 0);
1242 if (position > -1) {
1243 var disabledHref = anchor.getAttribute("disabled-href");
1245 anchor.setAttribute("href", disabledHref);
1246 var disabledOnclick = anchor.getAttribute("disabled-onclick");
1247 if (disabledOnclick)
1248 anchor.setAttribute("onclick", disabledOnclick);
1249 anchor.removeClassName("_disabled");
1250 anchor.setAttribute("disabled-href", null);
1251 anchor.setAttribute("disabled-onclick", null);
1252 anchor.disabled = 0;
1257 function disableAnchor(anchor) {
1258 var classStr = '' + anchor.getAttribute("class");
1259 var position = classStr.indexOf("_disabled", 0);
1261 var href = anchor.getAttribute("href");
1263 anchor.setAttribute("disabled-href", href);
1264 var onclick = anchor.getAttribute("onclick");
1266 anchor.setAttribute("disabled-onclick", onclick);
1267 anchor.addClassName("_disabled");
1268 anchor.setAttribute("href", "#");
1269 anchor.setAttribute("onclick", "return false;");
1270 anchor.disabled = 1;
1276 var hD = "0123456789abcdef";
1277 var h = hD.substr(d & 15, 1);
1281 h = hD.substr(d & 15, 1) + h;
1287 function indexColor(number) {
1293 var colorTable = new Array(1, 1, 1);
1295 var currentValue = number;
1297 while (currentValue) {
1298 if (currentValue & 1)
1299 colorTable[index]++;
1307 + d2h((256 / colorTable[2]) - 1)
1308 + d2h((256 / colorTable[1]) - 1)
1309 + d2h((256 / colorTable[0]) - 1));
1315 function loadPreferences() {
1316 var url = UserFolderURL + "jsonDefaults";
1317 var http = createHTTPClient();
1318 http.open("GET", url, false);
1320 if (http.status == 200)
1321 userDefaults = http.responseText.evalJSON(true);
1323 url = UserFolderURL + "jsonSettings";
1324 http.open("GET", url, false);
1326 if (http.status == 200)
1327 userSettings = http.responseText.evalJSON(true);
1330 function onLoadHandler(event) {
1331 if (typeof UserLogin != "undefined")
1333 queryParameters = parseQueryParameters('' + window.location);
1334 if (!$(document.body).hasClassName("popup")) {
1338 configureSearchField();
1341 configureDragHandles();
1342 configureLinkBanner();
1343 var progressImage = $("progressIndicator");
1345 progressImage.parentNode.removeChild(progressImage);
1346 Event.observe(document.body, "contextmenu", onBodyClickContextMenu);
1349 function onBodyClickContextMenu(event) {
1350 preventDefault(event);
1353 function configureSortableTableHeaders(table) {
1354 var headers = $(table).getElementsByClassName("sortableTableHeader");
1355 for (var i = 0; i < headers.length; i++) {
1356 var header = headers[i];
1357 Event.observe(header, "click", onHeaderClick.bindAsEventListener(header))
1361 function onLinkBannerClick() {
1362 activeAjaxRequests++;
1363 checkAjaxRequestsState();
1366 function onPreferencesClick(event) {
1367 var urlstr = UserFolderURL + "preferences";
1368 var w = window.open(urlstr, "_blank",
1369 "width=430,height=250,resizable=0,scrollbars=0,location=0");
1373 preventDefault(event);
1376 function configureLinkBanner() {
1377 var linkBanner = $("linkBanner");
1379 var anchors = linkBanner.childNodesWithTag("a");
1380 for (var i = 1; i < 3; i++) {
1381 Event.observe(anchors[i], "mousedown", listRowMouseDownHandler);
1382 Event.observe(anchors[i], "click", onLinkBannerClick);
1384 Event.observe(anchors[4], "mousedown", listRowMouseDownHandler);
1385 Event.observe(anchors[4], "click", onPreferencesClick);
1386 if (anchors.length > 5)
1387 Event.observe(anchors[5], "click", toggleLogConsole);
1391 /* folder creation */
1392 function createFolder(name, okCB, notOkCB) {
1394 if (document.newFolderAjaxRequest) {
1395 document.newFolderAjaxRequest.aborted = true;
1396 document.newFolderAjaxRequest.abort();
1398 var url = ApplicationBaseURL + "/createFolder?name=" + name;
1399 document.newFolderAjaxRequest
1400 = triggerAjaxRequest(url, createFolderCallback,
1407 function createFolderCallback(http) {
1408 if (http.readyState == 4) {
1409 var data = http.callbackData;
1410 if (http.status == 201) {
1412 data.okCB(data.name, "/" + http.responseText, UserLogin);
1418 log("ajax problem:" + http.status);
1423 addEvent(window, 'load', onLoadHandler);
1425 function parent$(element) {
1426 return this.opener.document.getElementById(element);
1430 function refreshCurrentFolder() {
1433 function configureDragHandles() {
1436 function getMenus() {
1439 function onHeaderClick(event) {
1440 window.alert("generic headerClick");