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 openContactWindow(url, wId) {
217 wId = "" + (new Date().getTime());
218 var w = window.open(url, wId,
219 "width=450,height=600,resizable=0");
225 function openMailComposeWindow(url, wId) {
227 wId = "" + (new Date().getTime());
228 var w = window.open(url, wId,
229 "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
230 + "location=0,directories=0,status=0,menubar=0"
237 function openMailTo(senderMailTo) {
238 var mailto = sanitizeMailTo(senderMailTo);
239 if (mailto.length > 0)
240 openMailComposeWindow(ApplicationBaseURL
241 + "/../Mail/compose?mailto=" + mailto);
243 return false; /* stop following the link */
246 function createHTTPClient() {
247 // http://developer.apple.com/internet/webcontent/xmlhttpreq.html
248 if (typeof XMLHttpRequest != "undefined")
249 return new XMLHttpRequest();
251 try { return new ActiveXObject("Msxml2.XMLHTTP"); }
253 try { return new ActiveXObject("Microsoft.XMLHTTP"); }
259 function appendDifferentiator(url) {
260 var url_nocache = url;
261 var position = url.indexOf('?', 0);
266 url_nocache += 'differentiator=' + Math.floor(Math.random()*50000);
271 function triggerAjaxRequest(url, callback, userdata) {
272 var http = createHTTPClient();
274 activeAjaxRequests += 1;
275 document.animTimer = setTimeout("checkAjaxRequestsState();", 200);
276 //url = appendDifferentiator(url);
279 http.open("POST", url, true);
281 http.onreadystatechange
283 //log ("state changed (" + http.readyState + "): " + url);
285 if (http.readyState == 4
286 && activeAjaxRequests > 0) {
288 http.callbackData = userdata;
291 activeAjaxRequests -= 1;
292 checkAjaxRequestsState();
296 activeAjaxRequests -= 1;
297 checkAjaxRequestsState();
298 log("AJAX Request, Caught Exception: " + e.name);
306 log("triggerAjaxRequest: error creating HTTP Client!");
312 function checkAjaxRequestsState() {
313 var toolbar = document.getElementById("toolbar");
315 if (activeAjaxRequests > 0
316 && !document.busyAnim) {
317 var anim = document.createElement("img");
319 document.busyAnim = anim;
320 anim.id = "progressIndicator";
321 anim.src = ResourcesURL + "/busy.gif";
322 anim.setStyle({ visibility: "hidden" });
323 toolbar.appendChild(anim);
324 anim.setStyle({ visibility: "visible" });
326 else if (activeAjaxRequests == 0
328 && document.busyAnim.parentNode) {
329 document.busyAnim.parentNode.removeChild(document.busyAnim);
330 document.busyAnim = null;
335 function isSafari() {
336 //var agt = navigator.userAgent.toLowerCase();
337 //var is_safari = ((agt.indexOf('safari')!=-1)&&(agt.indexOf('mac')!=-1))?true:false;
339 return (navigator.vendor == "Apple Computer, Inc.");
342 function isHttpStatus204(status) {
343 return (status == 204 || // Firefox
344 (isSafari() && typeof(status) == 'undefined') || // Safari
345 status == 1223); // IE
348 function getTarget(event) {
349 event = event || window.event;
351 return event.target; // W3C DOM
353 return event.srcElement; // IE
356 function preventDefault(event) {
357 if (event.preventDefault)
358 event.preventDefault(); // W3C DOM
360 event.returnValue = false; // IE
363 function resetSelection(win) {
365 if (win && win.getSelection) {
366 t = win.getSelection().toString();
367 win.getSelection().removeAllRanges();
372 function refreshOpener() {
373 if (window.opener && !window.opener.closed) {
374 window.opener.location.reload();
380 function parseQueryString() {
381 var queryArray, queryDict
382 var key, value, s, idx;
383 queryDict.length = 0;
385 queryDict = new Array();
386 queryArray = location.search.substr(1).split('&');
387 for (var i in queryArray) {
388 if (!queryArray[i]) continue ;
390 idx = s.indexOf("=");
396 key = s.substr(0, idx);
397 value = unescape(s.substr(idx + 1));
400 if (typeof queryDict[key] == 'undefined')
403 queryDict[key] = value;
408 function generateQueryString(queryDict) {
410 for (var key in queryDict) {
415 s = s + key + "=" + escape(queryDict[key]);
420 function getQueryParaArray(s) {
421 if (s.charAt(0) == "?") s = s.substr(1, s.length - 1);
425 function getQueryParaValue(s, name) {
428 t = getQueryParaArray(s);
429 for (var i = 0; i < t.length; i++) {
432 if (s.indexOf(name) != 0)
435 s = s.substr(name.length, s.length - name.length);
436 return decodeURIComponent(s);
441 /* opener callback */
443 function triggerOpenerCallback() {
444 /* this code has some issue if the folder has no proper trailing slash! */
445 if (window.opener && !window.opener.closed) {
448 t = getQueryParaValue(window.location.search, "openerurl=");
449 cburl = window.opener.location.href;
450 if (cburl[cburl.length - 1] != "/") {
451 cburl = cburl.substr(0, cburl.lastIndexOf("/") + 1);
454 window.opener.location.href = cburl;
458 /* selection mechanism */
460 function deselectAll(parent) {
461 for (var i = 0; i < parent.childNodes.length; i++) {
462 var node = parent.childNodes.item(i);
463 if (node.nodeType == 1)
468 function isNodeSelected(node) {
469 return $(node).hasClassName('_selected');
472 function acceptMultiSelect(node) {
473 var response = false;
474 var attribute = node.getAttribute('multiselect');
476 log("node '" + node.getAttribute("id")
477 + "' is still using old-stylemultiselect!");
478 response = (attribute.toLowerCase() == 'yes');
481 response = node.multiselect;
486 function onRowClick(event) {
487 var node = getTarget(event);
489 if (node.tagName == 'TD')
490 node = node.parentNode;
491 var startSelection = $(node.parentNode).getSelectedNodes();
492 if (event.shiftKey == 1
493 && (acceptMultiSelect(node.parentNode)
494 || acceptMultiSelect(node.parentNode.parentNode))) {
495 if (isNodeSelected(node) == true) {
501 $(node.parentNode).deselectAll();
505 if (startSelection != $(node.parentNode).getSelectedNodes()) {
506 var parentNode = node.parentNode;
507 if (parentNode.tagName == 'TBODY')
508 parentNode = parentNode.parentNode;
509 //log("onRowClick: parentNode = " + parentNode.tagName);
510 // parentNode is UL or TABLE
511 if (document.createEvent) {
512 var onSelectionChangeEvent;
514 onSelectionChangeEvent = document.createEvent("UIEvents");
516 onSelectionChangeEvent = document.createEvent("Events");
517 onSelectionChangeEvent.initEvent("mousedown", true, true);
518 parentNode.dispatchEvent(onSelectionChangeEvent);
520 else if (document.createEventObject) {
521 parentNode.fireEvent("onmousedown");
530 // var acceptClick = false;
532 function popupMenu(event, menuId, target) {
533 document.menuTarget = target;
535 if (document.currentPopupMenu)
536 hideMenu(document.currentPopupMenu);
538 var popup = $(menuId);
539 var menuTop = Event.pointerY(event);
540 var menuLeft = Event.pointerX(event);
541 var heightDiff = (window.innerHeight
542 - (menuTop + popup.offsetHeight));
544 menuTop += heightDiff;
546 var leftDiff = (window.innerWidth
547 - (menuLeft + popup.offsetWidth));
549 menuLeft -= popup.offsetWidth;
551 popup.setStyle({ top: menuTop + "px",
552 left: menuLeft + "px",
553 visibility: "visible" });
555 document.currentPopupMenu = popup;
557 Event.observe(document.body, "click", onBodyClickMenuHandler);
559 preventDefault(event);
562 function getParentMenu(node) {
563 var currentNode, menuNode;
567 var menure = new RegExp("(^|\s+)menu(\s+|$)", "i");
569 while (menuNode == null
571 if (menure.test(currentNode.className))
572 menuNode = currentNode;
574 currentNode = currentNode.parentNode;
579 function onBodyClickMenuHandler(event) {
580 document.body.menuTarget = null;
581 hideMenu(document.currentPopupMenu);
582 Event.stopObserving(document.body, "click", onBodyClickMenuHandler);
584 preventDefault(event);
587 function hideMenu(menuNode) { //log ("hideMenu");
590 if (menuNode.submenu) {
591 hideMenu(menuNode.submenu);
592 menuNode.submenu = null;
595 menuNode.setStyle({ visibility: "hidden" });
597 if (menuNode.parentMenuItem) {
598 menuNode.parentMenuItem.setAttribute('class', 'submenu');
599 menuNode.parentMenuItem = null;
600 menuNode.parentMenu.setAttribute('onmousemove', null);
601 menuNode.parentMenu.submenuItem = null;
602 menuNode.parentMenu.submenu = null;
603 menuNode.parentMenu = null;
606 if (document.createEvent) {
609 onhideEvent = document.createEvent("UIEvents");
611 onhideEvent = document.createEvent("Events");
612 onhideEvent.initEvent("mousedown", false, true);
613 menuNode.dispatchEvent(onhideEvent);
615 else if (document.createEventObject) { // IE
616 menuNode.fireEvent("onmousedown");
620 function onMenuEntryClick(event) {
621 var node = event.target;
623 id = getParentMenu(node).menuTarget;
624 // log("clicked " + id + "/" + id.tagName);
629 function parseQueryParameters(url) {
630 var parameters = new Array();
632 var params = url.split("?")[1];
634 var pairs = params.split("&");
635 for (var i = 0; i < pairs.length; i++) {
636 var pair = pairs[i].split("=");
637 parameters[pair[0]] = pair[1];
644 function initLogConsole() {
645 var logConsole = $("logConsole");
647 logConsole.highlighted = false;
648 Event.observe(logConsole, "dblclick", onLogDblClick, false);
649 logConsole.innerHTML = "";
650 Event.observe(window, "keydown", onBodyKeyDown);
654 function onBodyKeyDown(event) {
655 if (event.keyCode == 27) {
657 preventDefault(event);
661 function onLogDblClick(event) {
662 var logConsole = $("logConsole");
663 logConsole.innerHTML = "";
666 function toggleLogConsole(event) {
667 var logConsole = $("logConsole");
668 var display = '' + logConsole.style.display;
669 if (display.length == 0) {
670 logConsole.setStyle({ display: 'block' });
672 logConsole.setStyle({ display: '' });
675 preventDefault(event);
678 function log(message) {
681 while (logWindow.opener)
682 logWindow = logWindow.opener;
684 var logConsole = logWindow.document.getElementById("logConsole");
686 logConsole.highlighted = !logConsole.highlighted;
687 var logMessage = message.replace("<", "<", "g");
688 logMessage = logMessage.replace(" ", " ", "g");
689 logMessage = logMessage.replace("\r\n", "<br />\n", "g");
690 logMessage = logMessage.replace("\n", "<br />\n", "g");
691 logMessage += '<br />' + "\n";
692 if (logConsole.highlighted)
693 logMessage = '<div class="highlighted">' + logMessage + '</div>';
694 logConsole.innerHTML += logMessage;
698 function backtrace() {
699 var func = backtrace.caller;
700 var str = "backtrace:\n";
706 str += " " + func.name;
708 str += " (" + this + ")";
711 str += "[anonymous]\n";
721 function dropDownSubmenu(event) {
723 if (this.submenu && this.submenu != "") {
724 log ("submenu: " + this.submenu);
725 var submenuNode = $(this.submenu);
726 var parentNode = getParentMenu(node);
727 if (parentNode.submenu)
728 hideMenu(parentNode.submenu);
729 submenuNode.parentMenuItem = node;
730 submenuNode.parentMenu = parentNode;
731 parentNode.submenuItem = node;
732 parentNode.submenu = submenuNode;
734 var menuTop = (node.offsetTop - 2);
736 var heightDiff = (window.innerHeight
737 - (menuTop + submenuNode.offsetHeight));
739 menuTop += heightDiff;
741 var menuLeft = parentNode.offsetWidth - 3;
742 if (window.innerWidth
743 < (menuLeft + submenuNode.offsetWidth
744 + parentNode.cascadeLeftOffset()))
745 menuLeft = - submenuNode.offsetWidth + 3;
747 parentNode.setAttribute('onmousemove', 'checkDropDown(event);');
748 node.setAttribute('class', 'submenu-selected');
749 submenuNode.setStyle({ top: menuTop + "px",
750 left: menuLeft + "px",
751 visibility: "visible" });
755 function checkDropDown(event) {
756 var parentMenu = getParentMenu(event.target);
757 var submenuItem = parentMenu.submenuItem;
759 var menuX = event.clientX - parentMenu.cascadeLeftOffset();
760 var menuY = event.clientY - parentMenu.cascadeTopOffset();
761 var itemX = submenuItem.offsetLeft;
762 var itemY = submenuItem.offsetTop - 75;
765 && menuX < itemX + submenuItem.offsetWidth
767 || menuY > (itemY + submenuItem.offsetHeight))) {
768 hideMenu(parentMenu.submenu);
769 parentMenu.submenu = null;
770 parentMenu.submenuItem = null;
771 parentMenu.setAttribute('onmousemove', null);
777 function popupSearchMenu(event) {
778 var menuId = this.getAttribute("menuid");
779 var offset = Position.cumulativeOffset(this);
781 relX = Event.pointerX(event) - offset[0];
782 relY = Event.pointerY(event) - offset[1];
784 if (event.button == 0
786 event.cancelBubble = true;
787 event.returnValue = false;
789 if (document.currentPopupMenu)
790 hideMenu(document.currentPopupMenu);
792 var popup = $(menuId);
793 offset = Position.positionedOffset(this);
794 popup.setStyle({ top: this.offsetHeight + "px",
795 left: (offset[0] + 3) + "px",
796 visibility: "visible" });
798 document.currentPopupMenu = popup;
799 Event.observe(document.body, "click", onBodyClickMenuHandler);
803 function setSearchCriteria(event) {
804 var searchValue = $("searchValue");
805 var searchCriteria = $("searchCriteria");
807 searchValue.setAttribute("ghost-phrase", this.innerHTML);
808 searchCriteria.value = this.getAttribute('id');
811 function checkSearchValue(event) {
812 var form = event.target;
813 var searchValue = $("searchValue");
814 var ghostPhrase = searchValue.getAttribute('ghost-phrase');
816 if (searchValue.value == ghostPhrase)
817 searchValue.value = "";
820 function onSearchChange() {
821 log ("onSearchChange()...");
824 function configureSearchField() {
825 var searchValue = $("searchValue");
827 if (!searchValue) return;
829 Event.observe(searchValue, "mousedown",
830 onSearchMouseDown.bindAsEventListener(searchValue));
831 Event.observe(searchValue, "click",
832 popupSearchMenu.bindAsEventListener(searchValue));
833 Event.observe(searchValue, "blur",
834 onSearchBlur.bindAsEventListener(searchValue));
835 Event.observe(searchValue, "focus",
836 onSearchFocus.bindAsEventListener(searchValue));
837 Event.observe(searchValue, "keydown",
838 onSearchKeyDown.bindAsEventListener(searchValue));
841 function onSearchMouseDown(event) {
842 var superNode = this.parentNode.parentNode.parentNode;
843 relX = (Event.pointerX(event) - superNode.offsetLeft - this.offsetLeft);
844 relY = (Event.pointerY(event) - superNode.offsetTop - this.offsetTop);
847 event.cancelBubble = true;
848 event.returnValue = false;
852 function onSearchFocus() {
853 ghostPhrase = this.getAttribute("ghost-phrase");
854 if (this.value == ghostPhrase) {
856 this.setAttribute("modified", "");
861 this.setStyle({ color: "#000" });
864 function onSearchBlur(event) {
865 var ghostPhrase = this.getAttribute("ghost-phrase");
866 //log ("search blur: '" + this.value + "'");
868 this.setAttribute("modified", "");
869 this.setStyle({ color: "#aaa" });
870 this.value = ghostPhrase;
871 refreshCurrentFolder();
872 } else if (this.value == ghostPhrase) {
873 this.setAttribute("modified", "");
874 this.setStyle({ color: "#aaa" });
876 this.setAttribute("modified", "yes");
877 this.setStyle({ color: "#000" });
881 function onSearchKeyDown(event) {
883 clearTimeout(this.timer);
885 this.timer = setTimeout("onSearchFormSubmit()", 1000);
888 function onSearchFormSubmit(event) {
889 var searchValue = $("searchValue");
890 var searchCriteria = $("searchCriteria");
891 var ghostPhrase = searchValue.getAttribute('ghost-phrase');
893 if (searchValue.value == ghostPhrase) return;
895 search["criteria"] = searchCriteria.value;
896 search["value"] = searchValue.value;
898 refreshCurrentFolder();
901 function initCriteria() {
902 var searchCriteria = $("searchCriteria");
903 var searchValue = $("searchValue");
905 if (!searchValue) return;
907 var searchOptions = $("searchOptions").childNodesWithTag("li");
908 if (searchOptions.length > 0) {
909 var firstChild = searchOptions[0];
910 searchCriteria.value = $(firstChild).getAttribute('id');
911 searchValue.setAttribute('ghost-phrase', firstChild.innerHTML);
912 if (searchValue.value == '') {
913 searchValue.value = firstChild.innerHTML;
914 searchValue.setAttribute("modified", "");
915 searchValue.setStyle({ color: "#aaa" });
920 /* toolbar buttons */
921 function popupToolbarMenu(node, menuId) {
922 if (document.currentPopupMenu)
923 hideMenu(document.currentPopupMenu);
925 var popup = $(menuId);
926 var top = ($(node).getStyle('top') || 0) + node.offsetHeight - 2;
927 popup.setStyle({ top: top + "px",
928 left: $(node).cascadeLeftOffset() + "px",
929 visibility: "visible" });
931 document.currentPopupMenu = popup;
932 Event.observe(document.body, "click", onBodyClickMenuHandler);
935 /* contact selector */
937 function folderSubscriptionCallback(http) {
938 if (http.readyState == 4) {
939 if (isHttpStatus204(http.status)) {
940 if (http.callbackData)
941 http.callbackData["method"](http.callbackData["data"]);
944 window.alert(clabels["Unable to subscribe to that folder!"].decodeEntities());
945 document.subscriptionAjaxRequest = null;
948 log ("folderSubscriptionCallback Ajax error");
951 function subscribeToFolder(refreshCallback, refreshCallbackData) {
952 var folderData = refreshCallbackData["folder"].split(":");
953 var username = folderData[0];
954 var folderPath = folderData[1];
955 if (username != UserLogin) {
956 var url = (UserFolderURL + "../" + username
957 + folderPath + "/subscribe");
958 if (document.subscriptionAjaxRequest) {
959 document.subscriptionAjaxRequest.aborted = true;
960 document.subscriptionAjaxRequest.abort();
962 var rfCbData = { method: refreshCallback, data: refreshCallbackData };
963 document.subscriptionAjaxRequest = triggerAjaxRequest(url,
964 folderSubscriptionCallback,
968 refreshCallbackData["window"].alert(clabels["You cannot subscribe to a folder that you own!"]
972 function folderUnsubscriptionCallback(http) {
973 if (http.readyState == 4) {
974 if (isHttpStatus204(http.status)) {
975 if (http.callbackData)
976 http.callbackData["method"](http.callbackData["data"]);
979 window.alert(clabels["Unable to unsubscribe from that folder!"].decodeEntities());
980 document.unsubscriptionAjaxRequest = null;
984 function unsubscribeFromFolder(folder, refreshCallback, refreshCallbackData) {
985 if (document.body.hasClassName("popup")) {
986 window.opener.unsubscribeFromFolder(folder, refreshCallback,
987 refreshCallbackData);
990 var folderData = folder.split(":");
991 var username = folderData[0];
992 var folderPath = folderData[1];
993 if (username != UserLogin) {
994 var url = (UserFolderURL + "../" + username
995 + "/" + folderPath + "/unsubscribe");
996 if (document.unsubscriptionAjaxRequest) {
997 document.unsubscriptionAjaxRequest.aborted = true;
998 document.unsubscriptionAjaxRequest.abort();
1000 var rfCbData = { method: refreshCallback, data: refreshCallbackData };
1001 document.unsubscriptionAjaxRequest
1002 = triggerAjaxRequest(url, folderUnsubscriptionCallback,
1006 window.alert(clabels["You cannot unsubscribe from a folder that you own!"].decodeEntities());
1010 function listRowMouseDownHandler(event) {
1011 preventDefault(event);
1015 function initTabs() {
1016 var containers = document.getElementsByClassName("tabsContainer");
1017 for (var x = 0; x < containers.length; x++) {
1018 var container = containers[x];
1019 var firstTab = null;
1020 for (var i = 0; i < container.childNodes.length; i++) {
1021 if (container.childNodes[i].tagName == 'UL') {
1026 var nodes = container.childNodes[firstTab].childNodes;
1029 for (var i = 0; i < nodes.length; i++) {
1030 var currentNode = nodes[i];
1031 if (currentNode.tagName == 'LI') {
1034 Event.observe(currentNode, "mousedown",
1035 onTabMouseDown.bindAsEventListener(currentNode));
1036 Event.observe(currentNode, "click",
1037 onTabClick.bindAsEventListener(currentNode));
1038 //$(currentNode.getAttribute("target")).hide();
1042 nodes[firstTab].addClassName("first");
1043 nodes[firstTab].addClassName("active");
1044 container.activeTab = nodes[firstTab];
1046 var target = $(nodes[firstTab].getAttribute("target"));
1047 target.addClassName("active");
1052 function initMenus() {
1053 var menus = getMenus();
1055 for (var menuID in menus) {
1056 var menuDIV = $(menuID);
1058 initMenu(menuDIV, menus[menuID]);
1063 function initMenu(menuDIV, callbacks) {
1064 var lis = $(menuDIV.childNodesWithTag("ul")[0]).childNodesWithTag("li");
1065 for (var j = 0; j < lis.length; j++) {
1066 var node = $(lis[j]);
1067 Event.observe(node, "mousedown", listRowMouseDownHandler, false);
1068 var callback = callbacks[j];
1070 if (typeof(callback) == "string") {
1071 if (callback == "-")
1072 node.addClassName("separator");
1074 node.submenu = callback;
1075 node.addClassName("submenu");
1076 Event.observe(node, "mouseover", dropDownSubmenu);
1080 Event.observe(node, "mouseup",
1081 $(callback).bindAsEventListener(node));
1084 node.addClassName("disabled");
1088 function onTabMouseDown(event) {
1089 event.cancelBubble = true;
1090 preventDefault(event);
1093 function openExternalLink(anchor) {
1097 function openAclWindow(url) {
1098 var w = window.open(url, "aclWindow",
1099 "width=420,height=300,resizable=1,scrollbars=1,toolbar=0,"
1100 + "location=0,directories=0,status=0,menubar=0"
1101 + ",copyhistory=0");
1108 function getUsersRightsWindowHeight() {
1109 return usersRightsWindowHeight;
1112 function getUsersRightsWindowWidth() {
1113 return usersRightsWindowWidth;
1116 function getTopWindow() {
1117 var topWindow = null;
1118 var currentWindow = window;
1119 while (!topWindow) {
1120 if (currentWindow.document.body.hasClassName("popup")
1121 && currentWindow.opener)
1122 currentWindow = currentWindow.opener;
1124 topWindow = currentWindow;
1130 function onTabClick(event) {
1131 var node = getTarget(event); // LI element
1133 var target = node.getAttribute("target");
1135 var container = node.parentNode.parentNode;
1136 var oldTarget = container.activeTab.getAttribute("target");
1137 var content = $(target);
1138 var oldContent = $(oldTarget);
1140 oldContent.removeClassName("active");
1141 container.activeTab.removeClassName("active"); // previous LI
1142 container.activeTab = node;
1143 container.activeTab.addClassName("active"); // current LI
1144 content.addClassName("active");
1146 // Prototype alternative
1148 //oldContent.removeClassName("active");
1149 //container.activeTab.removeClassName("active"); // previous LI
1150 //container.activeTab = node;
1151 //container.activeTab.addClassName("active"); // current LI
1153 //container.activeTab.hide();
1154 //oldContent.hide();
1157 //container.activeTab = node;
1158 //container.activeTab.show();
1163 function enableAnchor(anchor) {
1164 var classStr = '' + anchor.getAttribute("class");
1165 var position = classStr.indexOf("_disabled", 0);
1166 if (position > -1) {
1167 var disabledHref = anchor.getAttribute("disabled-href");
1169 anchor.setAttribute("href", disabledHref);
1170 var disabledOnclick = anchor.getAttribute("disabled-onclick");
1171 if (disabledOnclick)
1172 anchor.setAttribute("onclick", disabledOnclick);
1173 anchor.removeClassName("_disabled");
1174 anchor.setAttribute("disabled-href", null);
1175 anchor.setAttribute("disabled-onclick", null);
1176 anchor.disabled = 0;
1181 function disableAnchor(anchor) {
1182 var classStr = '' + anchor.getAttribute("class");
1183 var position = classStr.indexOf("_disabled", 0);
1185 var href = anchor.getAttribute("href");
1187 anchor.setAttribute("disabled-href", href);
1188 var onclick = anchor.getAttribute("onclick");
1190 anchor.setAttribute("disabled-onclick", onclick);
1191 anchor.addClassName("_disabled");
1192 anchor.setAttribute("href", "#");
1193 anchor.setAttribute("onclick", "return false;");
1194 anchor.disabled = 1;
1200 var hD = "0123456789abcdef";
1201 var h = hD.substr(d & 15, 1);
1205 h = hD.substr(d & 15, 1) + h;
1211 function indexColor(number) {
1217 var colorTable = new Array(1, 1, 1);
1219 var currentValue = number;
1221 while (currentValue) {
1222 if (currentValue & 1)
1223 colorTable[index]++;
1231 + d2h((256 / colorTable[2]) - 1)
1232 + d2h((256 / colorTable[1]) - 1)
1233 + d2h((256 / colorTable[0]) - 1));
1239 function loadPreferences() {
1240 var url = UserFolderURL + "jsonDefaults";
1241 var http = createHTTPClient();
1242 http.open("GET", url, false);
1244 if (http.status == 200)
1245 userDefaults = http.responseText.evalJSON(true);
1247 url = UserFolderURL + "jsonSettings";
1248 http.open("GET", url, false);
1250 if (http.status == 200)
1251 userSettings = http.responseText.evalJSON(true);
1254 function onLoadHandler(event) {
1256 queryParameters = parseQueryParameters('' + window.location);
1257 if (!$(document.body).hasClassName("popup")) {
1261 configureSearchField();
1264 configureDragHandles();
1265 configureSortableTableHeaders();
1266 configureLinkBanner();
1267 var progressImage = $("progressIndicator");
1269 progressImage.parentNode.removeChild(progressImage);
1270 Event.observe(document.body, "contextmenu", onBodyClickContextMenu);
1273 function onBodyClickContextMenu(event) {
1274 preventDefault(event);
1277 function configureSortableTableHeaders() {
1278 var headers = document.getElementsByClassName("sortableTableHeader");
1279 for (var i = 0; i < headers.length; i++) {
1280 var header = headers[i];
1281 var anchor = $(header).childNodesWithTag("a")[0];
1283 Event.observe(anchor, "click",
1284 onHeaderClick.bindAsEventListener(anchor));
1288 function onLinkBannerClick() {
1289 activeAjaxRequests++;
1290 checkAjaxRequestsState();
1293 function onPreferencesClick(event) {
1294 var urlstr = UserFolderURL + "preferences";
1295 var w = window.open(urlstr, "User Preferences",
1296 "width=430,height=250,resizable=0,scrollbars=0");
1300 preventDefault(event);
1303 function configureLinkBanner() {
1304 var linkBanner = $("linkBanner");
1306 var anchors = linkBanner.childNodesWithTag("a");
1307 for (var i = 0; i < 2; i++) {
1308 Event.observe(anchors[i], "mousedown", listRowMouseDownHandler);
1309 Event.observe(anchors[i], "click", onLinkBannerClick);
1311 Event.observe(anchors[3], "mousedown", listRowMouseDownHandler);
1312 Event.observe(anchors[3], "click", onPreferencesClick);
1313 if (anchors.length > 4)
1314 Event.observe(anchors[4], "click", toggleLogConsole);
1318 addEvent(window, 'load', onLoadHandler);
1320 function parent$(element) {
1321 return this.opener.document.getElementById(element);
1325 function refreshCurrentFolder() {
1328 function configureDragHandles() {
1331 function getMenus() {
1334 function onHeaderClick(event) {
1335 window.alert("generic headerClick");