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 activeAjaxRequests = 0;
31 var menus = new Array();
35 var weekStartIsMonday = true;
38 var allDocumentElements = null;
40 var userDefaults = null;
41 var userSettings = null;
43 /* a W3C compliant document.all */
44 function getAllScopeElements(scope) {
45 var elements = new Array();
47 for (var i = 0; i < scope.childNodes.length; i++)
48 if (typeof(scope.childNodes[i]) == "object"
49 && scope.childNodes[i].tagName
50 && scope.childNodes[i].tagName != '')
52 elements.push(scope.childNodes[i]);
53 var childElements = getAllElements(scope.childNodes[i]);
54 if (childElements.length > 0)
55 elements.push(childElements);
61 function getAllElements(scope) {
68 && allDocumentElements != null)
69 elements = allDocumentElements;
72 elements = getAllScopeElements(scope);
73 if (scope == document)
74 allDocumentElements = elements;
81 http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/ */
82 function getElementsByClassName2(_tag, _class, _scope) {
83 var regexp, classes, elements, element, returnElements;
85 _scope = _scope || document;
87 elements = (!_tag || _tag == "*"
88 ? getAllElements(null)
89 : _scope.getElementsByTagName(_tag));
92 classes = _class.split(/\s+/);
93 regexp = new RegExp("(^|\s+)("+ classes.join("|") +")(\s+|$)","i");
96 for(var i = 0; element = elements[i]; i++) {
97 if (regexp.test(element.className)) {
98 returnElements.push(element);
101 return returnElements;
107 function createElement(tagName, id, classes, attributes, htmlAttributes,
109 var newElement = $(document.createElement(tagName));
111 newElement.setAttribute("id", id);
113 if (typeof(classes) == "string")
114 newElement.addClassName(classes);
116 for (var i = 0; i < classes.length; i++)
117 newElement.addClassName(classes[i]);
120 for (var i in attributes)
121 newElement[i] = attributes[i];
123 for (var i in htmlAttributes)
124 newElement.setAttribute(i, htmlAttributes[i]);
126 parentNode.appendChild(newElement);
128 return $(newElement);
131 function ml_stripActionInURL(url) {
132 if (url[url.length - 1] != '/') {
135 i = url.lastIndexOf("/");
136 if (i != -1) url = url.substring(0, i);
138 if (url[url.length - 1] != '/') // ensure trailing slash
143 function URLForFolderID(folderID) {
144 var folderInfos = folderID.split(":");
146 if (folderInfos.length > 1) {
147 url = UserFolderURL + "../" + folderInfos[0];
148 if (!folderInfos[1].startsWith('/'))
150 url += folderInfos[1];
153 url = ApplicationBaseURL + folderInfos[0];
155 if (url[url.length-1] == '/')
156 url = url.substr(0, url.length-1);
161 function extractEmailAddress(mailTo) {
165 = /([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;
166 if (emailre.test(mailTo)) {
167 emailre.exec(mailTo);
174 function extractEmailName(mailTo) {
177 var tmpMailTo = mailTo.replace("<", "<");
178 tmpMailTo = tmpMailTo.replace(">", ">");
180 var emailNamere = /([ ]+)?(.+)\ </;
181 if (emailNamere.test(tmpMailTo)) {
182 emailNamere.exec(tmpMailTo);
183 emailName = RegExp.$2;
189 function sanitizeMailTo(dirtyMailTo) {
190 var emailName = extractEmailName(dirtyMailTo);
191 var email = "" + extractEmailAddress(dirtyMailTo);
194 if (emailName && emailName.length > 0)
195 mailto = emailName + ' <' + email + '>';
202 function openUserFolderSelector(callback, type) {
203 var urlstr = ApplicationBaseURL;
204 if (! urlstr.endsWith('/'))
206 urlstr += ("../../" + UserLogin + "/Contacts/userFolders");
207 var w = window.open(urlstr, "_blank",
208 "width=322,height=250,resizable=1,scrollbars=0");
210 window.userFolderCallback = callback;
211 window.userFolderType = type;
215 function openMailComposeWindow(url) {
216 var w = window.open(url, null,
217 "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
218 + "location=0,directories=0,status=0,menubar=0"
225 function openMailTo(senderMailTo) {
226 var mailto = sanitizeMailTo(senderMailTo);
227 if (mailto.length > 0)
228 openMailComposeWindow(ApplicationBaseURL
229 + "/../Mail/compose?mailto=" + mailto);
231 return false; /* stop following the link */
234 function createHTTPClient() {
235 // http://developer.apple.com/internet/webcontent/xmlhttpreq.html
236 if (typeof XMLHttpRequest != "undefined")
237 return new XMLHttpRequest();
239 try { return new ActiveXObject("Msxml2.XMLHTTP"); }
241 try { return new ActiveXObject("Microsoft.XMLHTTP"); }
247 function appendDifferentiator(url) {
248 var url_nocache = url;
249 var position = url.indexOf('?', 0);
254 url_nocache += 'differentiator=' + Math.floor(Math.random()*50000);
259 function triggerAjaxRequest(url, callback, userdata) {
260 var http = createHTTPClient();
262 activeAjaxRequests += 1;
263 document.animTimer = setTimeout("checkAjaxRequestsState();", 200);
264 //url = appendDifferentiator(url);
267 http.open("POST", url, true);
269 http.onreadystatechange
271 //log ("state changed (" + http.readyState + "): " + url);
273 if (http.readyState == 4
274 && activeAjaxRequests > 0) {
276 http.callbackData = userdata;
279 activeAjaxRequests -= 1;
280 checkAjaxRequestsState();
284 activeAjaxRequests -= 1;
285 checkAjaxRequestsState();
286 log("AJAX Request, Caught Exception: " + e.name);
294 log("triggerAjaxRequest: error creating HTTP Client!");
300 function checkAjaxRequestsState() {
301 var toolbar = document.getElementById("toolbar");
303 if (activeAjaxRequests > 0
304 && !document.busyAnim) {
305 var anim = document.createElement("img");
307 document.busyAnim = anim;
308 anim.id = "progressIndicator";
309 anim.src = ResourcesURL + "/busy.gif";
310 anim.setStyle({ visibility: "hidden" });
311 toolbar.appendChild(anim);
312 anim.setStyle({ visibility: "visible" });
314 else if (activeAjaxRequests == 0
316 && document.busyAnim.parentNode) {
317 document.busyAnim.parentNode.removeChild(document.busyAnim);
318 document.busyAnim = null;
323 function isSafari() {
324 //var agt = navigator.userAgent.toLowerCase();
325 //var is_safari = ((agt.indexOf('safari')!=-1)&&(agt.indexOf('mac')!=-1))?true:false;
327 return (navigator.vendor == "Apple Computer, Inc.");
330 function isHttpStatus204(status) {
331 return (status == 204 || // Firefox
332 (isSafari() && typeof(status) == 'undefined') || // Safari
333 status == 1223); // IE
336 function getTarget(event) {
337 event = event || window.event;
339 return event.target; // W3C DOM
341 return event.srcElement; // IE
344 function preventDefault(event) {
345 if (event.preventDefault)
346 event.preventDefault(); // W3C DOM
348 event.returnValue = false; // IE
351 function resetSelection(win) {
353 if (win && win.getSelection) {
354 t = win.getSelection().toString();
355 win.getSelection().removeAllRanges();
360 function refreshOpener() {
361 if (window.opener && !window.opener.closed) {
362 window.opener.location.reload();
368 function parseQueryString() {
369 var queryArray, queryDict
370 var key, value, s, idx;
371 queryDict.length = 0;
373 queryDict = new Array();
374 queryArray = location.search.substr(1).split('&');
375 for (var i in queryArray) {
376 if (!queryArray[i]) continue ;
378 idx = s.indexOf("=");
384 key = s.substr(0, idx);
385 value = unescape(s.substr(idx + 1));
388 if (typeof queryDict[key] == 'undefined')
391 queryDict[key] = value;
396 function generateQueryString(queryDict) {
398 for (var key in queryDict) {
403 s = s + key + "=" + escape(queryDict[key]);
408 function getQueryParaArray(s) {
409 if (s.charAt(0) == "?") s = s.substr(1, s.length - 1);
413 function getQueryParaValue(s, name) {
416 t = getQueryParaArray(s);
417 for (var i = 0; i < t.length; i++) {
420 if (s.indexOf(name) != 0)
423 s = s.substr(name.length, s.length - name.length);
424 return decodeURIComponent(s);
429 /* opener callback */
431 function triggerOpenerCallback() {
432 /* this code has some issue if the folder has no proper trailing slash! */
433 if (window.opener && !window.opener.closed) {
436 t = getQueryParaValue(window.location.search, "openerurl=");
437 cburl = window.opener.location.href;
438 if (cburl[cburl.length - 1] != "/") {
439 cburl = cburl.substr(0, cburl.lastIndexOf("/") + 1);
442 window.opener.location.href = cburl;
446 /* selection mechanism */
448 function deselectAll(parent) {
449 for (var i = 0; i < parent.childNodes.length; i++) {
450 var node = parent.childNodes.item(i);
451 if (node.nodeType == 1)
456 function isNodeSelected(node) {
457 return $(node).hasClassName('_selected');
460 function acceptMultiSelect(node) {
461 var response = false;
462 var attribute = node.getAttribute('multiselect');
464 log("node '" + node.getAttribute("id")
465 + "' is still using old-stylemultiselect!");
466 response = (attribute.toLowerCase() == 'yes');
469 response = node.multiselect;
474 function onRowClick(event) {
475 var node = getTarget(event);
477 if (node.tagName == 'TD')
478 node = node.parentNode;
479 var startSelection = $(node.parentNode).getSelectedNodes();
480 if (event.shiftKey == 1
481 && (acceptMultiSelect(node.parentNode)
482 || acceptMultiSelect(node.parentNode.parentNode))) {
483 if (isNodeSelected(node) == true) {
489 $(node.parentNode).deselectAll();
493 if (startSelection != $(node.parentNode).getSelectedNodes()) {
494 var parentNode = node.parentNode;
495 if (parentNode.tagName == 'TBODY')
496 parentNode = parentNode.parentNode;
497 //log("onRowClick: parentNode = " + parentNode.tagName);
498 // parentNode is UL or TABLE
499 if (document.createEvent) {
500 var onSelectionChangeEvent;
502 onSelectionChangeEvent = document.createEvent("UIEvents");
504 onSelectionChangeEvent = document.createEvent("Events");
505 onSelectionChangeEvent.initEvent("mousedown", true, true);
506 parentNode.dispatchEvent(onSelectionChangeEvent);
508 else if (document.createEventObject) {
509 parentNode.fireEvent("onmousedown");
518 // var acceptClick = false;
520 function popupMenu(event, menuId, target) {
521 document.menuTarget = target;
523 if (document.currentPopupMenu)
524 hideMenu(document.currentPopupMenu);
526 var popup = $(menuId);
527 var menuTop = Event.pointerY(event);
528 var menuLeft = Event.pointerX(event);
529 var heightDiff = (window.innerHeight
530 - (menuTop + popup.offsetHeight));
532 menuTop += heightDiff;
534 var leftDiff = (window.innerWidth
535 - (menuLeft + popup.offsetWidth));
537 menuLeft -= popup.offsetWidth;
539 popup.setStyle({ top: menuTop + "px",
540 left: menuLeft + "px",
541 visibility: "visible" });
543 document.currentPopupMenu = popup;
545 Event.observe(document.body, "click", onBodyClickMenuHandler);
547 preventDefault(event);
550 function getParentMenu(node) {
551 var currentNode, menuNode;
555 var menure = new RegExp("(^|\s+)menu(\s+|$)", "i");
557 while (menuNode == null
559 if (menure.test(currentNode.className))
560 menuNode = currentNode;
562 currentNode = currentNode.parentNode;
567 function onBodyClickMenuHandler(event) {
568 document.body.menuTarget = null;
569 hideMenu(document.currentPopupMenu);
570 Event.stopObserving(document.body, "click", onBodyClickMenuHandler);
572 preventDefault(event);
575 function hideMenu(menuNode) { //log ("hideMenu");
578 if (menuNode.submenu) {
579 hideMenu(menuNode.submenu);
580 menuNode.submenu = null;
583 menuNode.setStyle({ visibility: "hidden" });
585 if (menuNode.parentMenuItem) {
586 menuNode.parentMenuItem.setAttribute('class', 'submenu');
587 menuNode.parentMenuItem = null;
588 menuNode.parentMenu.setAttribute('onmousemove', null);
589 menuNode.parentMenu.submenuItem = null;
590 menuNode.parentMenu.submenu = null;
591 menuNode.parentMenu = null;
594 if (document.createEvent) {
597 onhideEvent = document.createEvent("UIEvents");
599 onhideEvent = document.createEvent("Events");
600 onhideEvent.initEvent("mousedown", false, true);
601 menuNode.dispatchEvent(onhideEvent);
603 else if (document.createEventObject) { // IE
604 menuNode.fireEvent("onmousedown");
608 function onMenuEntryClick(event) {
609 var node = event.target;
611 id = getParentMenu(node).menuTarget;
612 // log("clicked " + id + "/" + id.tagName);
617 function parseQueryParameters(url) {
618 var parameters = new Array();
620 var params = url.split("?")[1];
622 var pairs = params.split("&");
623 for (var i = 0; i < pairs.length; i++) {
624 var pair = pairs[i].split("=");
625 parameters[pair[0]] = pair[1];
632 function initLogConsole() {
633 var logConsole = $("logConsole");
635 logConsole.highlighted = false;
636 Event.observe(logConsole, "dblclick", onLogDblClick, false);
637 logConsole.innerHTML = "";
638 Event.observe(window, "keydown", onBodyKeyDown);
642 function onBodyKeyDown(event) {
643 if (event.keyCode == 27) {
645 preventDefault(event);
649 function onLogDblClick(event) {
650 var logConsole = $("logConsole");
651 logConsole.innerHTML = "";
654 function toggleLogConsole(event) {
655 var logConsole = $("logConsole");
656 var display = '' + logConsole.style.display;
657 if (display.length == 0) {
658 logConsole.setStyle({ display: 'block' });
660 logConsole.setStyle({ display: '' });
663 preventDefault(event);
666 function log(message) {
669 while (logWindow.opener)
670 logWindow = logWindow.opener;
672 var logConsole = logWindow.document.getElementById("logConsole");
674 logConsole.highlighted = !logConsole.highlighted;
675 var logMessage = message.replace("<", "<", "g");
676 logMessage = logMessage.replace(" ", " ", "g");
677 logMessage = logMessage.replace("\r\n", "<br />\n", "g");
678 logMessage = logMessage.replace("\n", "<br />\n", "g");
679 logMessage += '<br />' + "\n";
680 if (logConsole.highlighted)
681 logMessage = '<div class="highlighted">' + logMessage + '</div>';
682 logConsole.innerHTML += logMessage;
686 function backtrace() {
687 var func = backtrace.caller;
688 var str = "backtrace:\n";
694 str += " " + func.name;
696 str += " (" + this + ")";
699 str += "[anonymous]\n";
709 function dropDownSubmenu(event) {
711 if (this.submenu && this.submenu != "") {
712 log ("submenu: " + this.submenu);
713 var submenuNode = $(this.submenu);
714 var parentNode = getParentMenu(node);
715 if (parentNode.submenu)
716 hideMenu(parentNode.submenu);
717 submenuNode.parentMenuItem = node;
718 submenuNode.parentMenu = parentNode;
719 parentNode.submenuItem = node;
720 parentNode.submenu = submenuNode;
722 var menuTop = (node.offsetTop - 2);
724 var heightDiff = (window.innerHeight
725 - (menuTop + submenuNode.offsetHeight));
727 menuTop += heightDiff;
729 var menuLeft = parentNode.offsetWidth - 3;
730 if (window.innerWidth
731 < (menuLeft + submenuNode.offsetWidth
732 + parentNode.cascadeLeftOffset()))
733 menuLeft = - submenuNode.offsetWidth + 3;
735 parentNode.setAttribute('onmousemove', 'checkDropDown(event);');
736 node.setAttribute('class', 'submenu-selected');
737 submenuNode.setStyle({ top: menuTop + "px",
738 left: menuLeft + "px",
739 visibility: "visible" });
743 function checkDropDown(event) {
744 var parentMenu = getParentMenu(event.target);
745 var submenuItem = parentMenu.submenuItem;
747 var menuX = event.clientX - parentMenu.cascadeLeftOffset();
748 var menuY = event.clientY - parentMenu.cascadeTopOffset();
749 var itemX = submenuItem.offsetLeft;
750 var itemY = submenuItem.offsetTop - 75;
753 && menuX < itemX + submenuItem.offsetWidth
755 || menuY > (itemY + submenuItem.offsetHeight))) {
756 hideMenu(parentMenu.submenu);
757 parentMenu.submenu = null;
758 parentMenu.submenuItem = null;
759 parentMenu.setAttribute('onmousemove', null);
765 function popupSearchMenu(event) {
766 var menuId = this.getAttribute("menuid");
767 var offset = Position.cumulativeOffset(this);
769 relX = Event.pointerX(event) - offset[0];
770 relY = Event.pointerY(event) - offset[1];
772 if (event.button == 0
774 event.cancelBubble = true;
775 event.returnValue = false;
777 if (document.currentPopupMenu)
778 hideMenu(document.currentPopupMenu);
780 var popup = $(menuId);
781 offset = Position.positionedOffset(this);
782 popup.setStyle({ top: this.offsetHeight + "px",
783 left: (offset[0] + 3) + "px",
784 visibility: "visible" });
786 document.currentPopupMenu = popup;
787 Event.observe(document.body, "click", onBodyClickMenuHandler);
791 function setSearchCriteria(event) {
792 var searchValue = $("searchValue");
793 var searchCriteria = $("searchCriteria");
795 searchValue.setAttribute("ghost-phrase", this.innerHTML);
796 searchCriteria.value = this.getAttribute('id');
799 function checkSearchValue(event) {
800 var form = event.target;
801 var searchValue = $("searchValue");
802 var ghostPhrase = searchValue.getAttribute('ghost-phrase');
804 if (searchValue.value == ghostPhrase)
805 searchValue.value = "";
808 function onSearchChange() {
809 log ("onSearchChange()...");
812 function configureSearchField() {
813 var searchValue = $("searchValue");
815 if (!searchValue) return;
817 Event.observe(searchValue, "mousedown",
818 onSearchMouseDown.bindAsEventListener(searchValue));
819 Event.observe(searchValue, "click",
820 popupSearchMenu.bindAsEventListener(searchValue));
821 Event.observe(searchValue, "blur",
822 onSearchBlur.bindAsEventListener(searchValue));
823 Event.observe(searchValue, "focus",
824 onSearchFocus.bindAsEventListener(searchValue));
825 Event.observe(searchValue, "keydown",
826 onSearchKeyDown.bindAsEventListener(searchValue));
829 function onSearchMouseDown(event) {
830 var superNode = this.parentNode.parentNode.parentNode;
831 relX = (Event.pointerX(event) - superNode.offsetLeft - this.offsetLeft);
832 relY = (Event.pointerY(event) - superNode.offsetTop - this.offsetTop);
835 event.cancelBubble = true;
836 event.returnValue = false;
840 function onSearchFocus() {
841 ghostPhrase = this.getAttribute("ghost-phrase");
842 if (this.value == ghostPhrase) {
844 this.setAttribute("modified", "");
849 this.setStyle({ color: "#000" });
852 function onSearchBlur(event) {
853 var ghostPhrase = this.getAttribute("ghost-phrase");
854 //log ("search blur: '" + this.value + "'");
856 this.setAttribute("modified", "");
857 this.setStyle({ color: "#aaa" });
858 this.value = ghostPhrase;
859 refreshCurrentFolder();
860 } else if (this.value == ghostPhrase) {
861 this.setAttribute("modified", "");
862 this.setStyle({ color: "#aaa" });
864 this.setAttribute("modified", "yes");
865 this.setStyle({ color: "#000" });
869 function onSearchKeyDown(event) {
871 clearTimeout(this.timer);
873 this.timer = setTimeout("onSearchFormSubmit()", 1000);
876 function onSearchFormSubmit(event) {
877 var searchValue = $("searchValue");
878 var searchCriteria = $("searchCriteria");
879 var ghostPhrase = searchValue.getAttribute('ghost-phrase');
881 if (searchValue.value == ghostPhrase) return;
883 search["criteria"] = searchCriteria.value;
884 search["value"] = searchValue.value;
886 refreshCurrentFolder();
889 function initCriteria() {
890 var searchCriteria = $("searchCriteria");
891 var searchValue = $("searchValue");
893 if (!searchValue) return;
895 var searchOptions = $("searchOptions").childNodesWithTag("li");
896 if (searchOptions.length > 0) {
897 var firstChild = searchOptions[0];
898 searchCriteria.value = $(firstChild).getAttribute('id');
899 searchValue.setAttribute('ghost-phrase', firstChild.innerHTML);
900 if (searchValue.value == '') {
901 searchValue.value = firstChild.innerHTML;
902 searchValue.setAttribute("modified", "");
903 searchValue.setStyle({ color: "#aaa" });
908 /* toolbar buttons */
909 function popupToolbarMenu(node, menuId) {
910 if (document.currentPopupMenu)
911 hideMenu(document.currentPopupMenu);
913 var popup = $(menuId);
914 var top = ($(node).getStyle('top') || 0) + node.offsetHeight - 2;
915 popup.setStyle({ top: top + "px",
916 left: $(node).cascadeLeftOffset() + "px",
917 visibility: "visible" });
919 document.currentPopupMenu = popup;
920 Event.observe(document.body, "click", onBodyClickMenuHandler);
923 /* contact selector */
925 function folderSubscriptionCallback(http) {
926 if (http.readyState == 4) {
927 if (isHttpStatus204(http.status)) {
928 if (http.callbackData)
929 http.callbackData["method"](http.callbackData["data"]);
932 window.alert(clabels["Unable to subscribe to that folder!"].decodeEntities());
933 document.subscriptionAjaxRequest = null;
936 log ("folderSubscriptionCallback Ajax error");
939 function subscribeToFolder(refreshCallback, refreshCallbackData) {
940 var folderData = refreshCallbackData["folder"].split(":");
941 var username = folderData[0];
942 var folderPath = folderData[1];
943 if (username != UserLogin) {
944 var url = (UserFolderURL + "../" + username
945 + folderPath + "/subscribe");
946 if (document.subscriptionAjaxRequest) {
947 document.subscriptionAjaxRequest.aborted = true;
948 document.subscriptionAjaxRequest.abort();
950 var rfCbData = { method: refreshCallback, data: refreshCallbackData };
951 document.subscriptionAjaxRequest = triggerAjaxRequest(url,
952 folderSubscriptionCallback,
956 refreshCallbackData["window"].alert(clabels["You cannot subscribe to a folder that you own!"]
960 function folderUnsubscriptionCallback(http) {
961 if (http.readyState == 4) {
962 if (isHttpStatus204(http.status)) {
963 if (http.callbackData)
964 http.callbackData["method"](http.callbackData["data"]);
967 window.alert(clabels["Unable to unsubscribe from that folder!"].decodeEntities());
968 document.unsubscriptionAjaxRequest = null;
972 function unsubscribeFromFolder(folder, refreshCallback, refreshCallbackData) {
973 if (document.body.hasClassName("popup")) {
974 window.opener.unsubscribeFromFolder(folder, refreshCallback,
975 refreshCallbackData);
978 var folderData = folder.split(":");
979 var username = folderData[0];
980 var folderPath = folderData[1];
981 if (username != UserLogin) {
982 var url = (UserFolderURL + "../" + username
983 + "/" + folderPath + "/unsubscribe");
984 if (document.unsubscriptionAjaxRequest) {
985 document.unsubscriptionAjaxRequest.aborted = true;
986 document.unsubscriptionAjaxRequest.abort();
988 var rfCbData = { method: refreshCallback, data: refreshCallbackData };
989 document.unsubscriptionAjaxRequest
990 = triggerAjaxRequest(url, folderUnsubscriptionCallback,
994 window.alert(clabels["You cannot unsubscribe from a folder that you own!"].decodeEntities());
998 function listRowMouseDownHandler(event) {
999 preventDefault(event);
1003 function initTabs() {
1004 var containers = document.getElementsByClassName("tabsContainer");
1005 for (var x = 0; x < containers.length; x++) {
1006 var container = containers[x];
1007 var firstTab = null;
1008 for (var i = 0; i < container.childNodes.length; i++) {
1009 if (container.childNodes[i].tagName == 'UL') {
1014 var nodes = container.childNodes[firstTab].childNodes;
1017 for (var i = 0; i < nodes.length; i++) {
1018 var currentNode = nodes[i];
1019 if (currentNode.tagName == 'LI') {
1022 Event.observe(currentNode, "mousedown",
1023 onTabMouseDown.bindAsEventListener(currentNode));
1024 Event.observe(currentNode, "click",
1025 onTabClick.bindAsEventListener(currentNode));
1026 //$(currentNode.getAttribute("target")).hide();
1030 nodes[firstTab].addClassName("first");
1031 nodes[firstTab].addClassName("active");
1032 container.activeTab = nodes[firstTab];
1034 var target = $(nodes[firstTab].getAttribute("target"));
1035 target.addClassName("active");
1040 function initMenus() {
1041 var menus = getMenus();
1043 for (var menuID in menus) {
1044 var menuDIV = $(menuID);
1046 initMenu(menuDIV, menus[menuID]);
1051 function initMenu(menuDIV, callbacks) {
1052 var lis = $(menuDIV.childNodesWithTag("ul")[0]).childNodesWithTag("li");
1053 for (var j = 0; j < lis.length; j++) {
1054 var node = $(lis[j]);
1055 Event.observe(node, "mousedown", listRowMouseDownHandler, false);
1056 var callback = callbacks[j];
1058 if (typeof(callback) == "string") {
1059 if (callback == "-")
1060 node.addClassName("separator");
1062 node.submenu = callback;
1063 node.addClassName("submenu");
1064 Event.observe(node, "mouseover", dropDownSubmenu);
1068 Event.observe(node, "mouseup",
1069 $(callback).bindAsEventListener(node));
1072 node.addClassName("disabled");
1076 function onTabMouseDown(event) {
1077 event.cancelBubble = true;
1078 preventDefault(event);
1081 function openExternalLink(anchor) {
1085 function openAclWindow(url) {
1086 var w = window.open(url, "aclWindow",
1087 "width=420,height=300,resizable=1,scrollbars=1,toolbar=0,"
1088 + "location=0,directories=0,status=0,menubar=0"
1089 + ",copyhistory=0");
1096 function getUsersRightsWindowHeight() {
1097 return usersRightsWindowHeight;
1100 function getUsersRightsWindowWidth() {
1101 return usersRightsWindowWidth;
1104 function getTopWindow() {
1105 var topWindow = null;
1106 var currentWindow = window;
1107 while (!topWindow) {
1108 if (currentWindow.document.body.hasClassName("popup")
1109 && currentWindow.opener)
1110 currentWindow = currentWindow.opener;
1112 topWindow = currentWindow;
1118 function onTabClick(event) {
1119 var node = getTarget(event); // LI element
1121 var target = node.getAttribute("target");
1123 var container = node.parentNode.parentNode;
1124 var oldTarget = container.activeTab.getAttribute("target");
1125 var content = $(target);
1126 var oldContent = $(oldTarget);
1128 oldContent.removeClassName("active");
1129 container.activeTab.removeClassName("active"); // previous LI
1130 container.activeTab = node;
1131 container.activeTab.addClassName("active"); // current LI
1132 content.addClassName("active");
1134 // Prototype alternative
1136 //oldContent.removeClassName("active");
1137 //container.activeTab.removeClassName("active"); // previous LI
1138 //container.activeTab = node;
1139 //container.activeTab.addClassName("active"); // current LI
1141 //container.activeTab.hide();
1142 //oldContent.hide();
1145 //container.activeTab = node;
1146 //container.activeTab.show();
1151 function enableAnchor(anchor) {
1152 var classStr = '' + anchor.getAttribute("class");
1153 var position = classStr.indexOf("_disabled", 0);
1154 if (position > -1) {
1155 var disabledHref = anchor.getAttribute("disabled-href");
1157 anchor.setAttribute("href", disabledHref);
1158 var disabledOnclick = anchor.getAttribute("disabled-onclick");
1159 if (disabledOnclick)
1160 anchor.setAttribute("onclick", disabledOnclick);
1161 anchor.removeClassName("_disabled");
1162 anchor.setAttribute("disabled-href", null);
1163 anchor.setAttribute("disabled-onclick", null);
1164 anchor.disabled = 0;
1169 function disableAnchor(anchor) {
1170 var classStr = '' + anchor.getAttribute("class");
1171 var position = classStr.indexOf("_disabled", 0);
1173 var href = anchor.getAttribute("href");
1175 anchor.setAttribute("disabled-href", href);
1176 var onclick = anchor.getAttribute("onclick");
1178 anchor.setAttribute("disabled-onclick", onclick);
1179 anchor.addClassName("_disabled");
1180 anchor.setAttribute("href", "#");
1181 anchor.setAttribute("onclick", "return false;");
1182 anchor.disabled = 1;
1188 var hD = "0123456789abcdef";
1189 var h = hD.substr(d & 15, 1);
1193 h = hD.substr(d & 15, 1) + h;
1199 function indexColor(number) {
1205 var colorTable = new Array(1, 1, 1);
1207 var currentValue = number;
1209 while (currentValue) {
1210 if (currentValue & 1)
1211 colorTable[index]++;
1219 + d2h((256 / colorTable[2]) - 1)
1220 + d2h((256 / colorTable[1]) - 1)
1221 + d2h((256 / colorTable[0]) - 1));
1227 function loadPreferences() {
1228 var url = UserFolderURL + "jsonDefaults";
1229 var http = createHTTPClient();
1230 http.open("GET", url, false);
1232 if (http.status == 200)
1233 userDefaults = http.responseText.evalJSON(true);
1235 url = UserFolderURL + "jsonSettings";
1236 http.open("GET", url, false);
1238 if (http.status == 200)
1239 userSettings = http.responseText.evalJSON(true);
1242 function onLoadHandler(event) {
1244 queryParameters = parseQueryParameters('' + window.location);
1245 if (!$(document.body).hasClassName("popup")) {
1249 configureSearchField();
1252 configureDragHandles();
1253 configureSortableTableHeaders();
1254 configureLinkBanner();
1255 var progressImage = $("progressIndicator");
1257 progressImage.parentNode.removeChild(progressImage);
1258 Event.observe(document.body, "contextmenu", onBodyClickContextMenu);
1261 function onBodyClickContextMenu(event) {
1262 preventDefault(event);
1265 function configureSortableTableHeaders() {
1266 var headers = document.getElementsByClassName("sortableTableHeader");
1267 for (var i = 0; i < headers.length; i++) {
1268 var header = headers[i];
1269 var anchor = $(header).childNodesWithTag("a")[0];
1271 Event.observe(anchor, "click",
1272 onHeaderClick.bindAsEventListener(anchor));
1276 function onLinkBannerClick() {
1277 activeAjaxRequests++;
1278 checkAjaxRequestsState();
1281 function onPreferencesClick(event) {
1282 var urlstr = UserFolderURL + "preferences";
1283 var w = window.open(urlstr, "User Preferences",
1284 "width=430,height=250,resizable=0,scrollbars=0");
1288 preventDefault(event);
1291 function configureLinkBanner() {
1292 var linkBanner = $("linkBanner");
1294 var anchors = linkBanner.childNodesWithTag("a");
1295 for (var i = 0; i < 2; i++) {
1296 Event.observe(anchors[i], "mousedown", listRowMouseDownHandler);
1297 Event.observe(anchors[i], "click", onLinkBannerClick);
1299 Event.observe(anchors[3], "mousedown", listRowMouseDownHandler);
1300 Event.observe(anchors[3], "click", onPreferencesClick);
1301 if (anchors.length > 4)
1302 Event.observe(anchors[4], "click", toggleLogConsole);
1306 addEvent(window, 'load', onLoadHandler);
1308 function parent$(element) {
1309 return this.opener.document.getElementById(element);
1313 function refreshCurrentFolder() {
1316 function configureDragHandles() {
1319 function getMenus() {
1322 function onHeaderClick(event) {
1323 window.alert("generic headerClick");