From 8db83b24004a4a24ff341fd720da50e7560371b3 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Fri, 18 Aug 2006 22:40:04 +0000 Subject: [PATCH] Monotone-Parent: 7f5811c1b6714c74ee06eb4b31576840c3f57e54 Monotone-Revision: 76bb24f493028584cf594de6c86a062fc8d24909 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2006-08-18T22:40:04 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 11 + UI/WebServerResources/ContactsUI.js | 64 ++-- UI/WebServerResources/MailerUI.js | 83 ++--- UI/WebServerResources/SchedulerUI.js | 313 ++++++++++++++++++ UI/WebServerResources/UIxAppointmentEditor.js | 4 +- UI/WebServerResources/generic.js | 231 ++++++++++--- 6 files changed, 566 insertions(+), 140 deletions(-) diff --git a/ChangeLog b/ChangeLog index c423f4544..1a477e9b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2006-08-18 Wolfgang Sourdeau + * UI/WebServerResources/ContactsUI.js, + UI/WebServerResources/MailerUI.js: adapted to the code refactoring + in generic.js. + + * UI/WebServerResources/SchedulerUI.js: implemented functions to + handle the new widgets. XmlHTTPRequest code taken from + MailerUI.js. + + * UI/WebServerResources/generic.js: put some functions related to + element selections as methods to HTMLElement and HTMLTableElement. + * UI/Scheduler/UIxCalAptListView.[hm]: new class designed to display the list of appointments (embodies the code-size of UIxCalAptListView; answers to the "aptlist" method). diff --git a/UI/WebServerResources/ContactsUI.js b/UI/WebServerResources/ContactsUI.js index 8f2614e19..ae8f274c1 100644 --- a/UI/WebServerResources/ContactsUI.js +++ b/UI/WebServerResources/ContactsUI.js @@ -67,21 +67,6 @@ function toggleMailSelect(sender) { row.className = sender.checked ? "tableview_selected" : "tableview"; } -function collectSelectedRows() { - var rows = new Array(); - var contactsList = document.getElementById('contactsList'); - var tbody = (contactsList.getElementsByTagName('tbody'))[0]; - var selectedRows = getSelectedNodes(tbody); - - for (var i = 0; i < selectedRows.length; i++) { - var row = selectedRows[i]; - var rowId = row.getAttribute('id'); - rows[rows.length] = rowId; - } - - return rows; -} - /* mail editor */ function validateEditorInput(sender) { @@ -336,12 +321,10 @@ function onContactContextMenu(event, element) onMenuClick(event, 'contactMenu'); var topNode = document.getElementById('contactsList'); - var selectedNodeIds = collectSelectedRows(); - topNode.menuSelectedRows = selectedNodeIds; - for (var i = 0; i < selectedNodeIds.length; i++) { - var selectedNode = document.getElementById(selectedNodeIds[i]); - deselectNode (selectedNode); - } + var selectedNodes = topNode.getSelectedRows(); + topNode.menuSelectedRows = selectedNodes; + for (var i = 0; i < selectedNodes.length; i++) + deselectNode(selectedNode); topNode.menuSelectedEntry = element; selectNode(element); } @@ -355,11 +338,9 @@ function onContactContextMenuHide(event) topNode.menuSelectedEntry = null; } if (topNode.menuSelectedRows) { - var nodeIds = topNode.menuSelectedRows; - for (var i = 0; i < nodeIds.length; i++) { - var node = document.getElementById(nodeIds[i]); - selectNode (node); - } + var nodes = topNode.menuSelectedRows; + for (var i = 0; i < nodes.length; i++) + selectNode (nodes[i]); topNode.menuSelectedRows = null; } } @@ -419,7 +400,9 @@ function storeCachedMessage(cachedContact) function onMessageSelectionChange() { - var selection = collectSelectedRows(); + var contactsList = document.getElementById('contactsList'); + + var selection = contactsList.getSelectedRowsId(); if (selection.length == 1) { var idx = selection[0]; @@ -671,9 +654,9 @@ function onMenuDeleteContact(event, node) function onToolbarEditSelectedContacts(event) { - var rows; - - rows = collectSelectedRows(); + var contactsList = document.getElementById('contactsList'); + var rows = contactsList.getSelectedRowsId(); + for (var i = 0; i < rows.length; i++) { openContactWindow(null, 'edit_' + rows[i], ApplicationBaseURL + currentContactFolder @@ -685,9 +668,9 @@ function onToolbarEditSelectedContacts(event) function onToolbarWriteToSelectedContacts(event) { - var rows; - - rows = collectSelectedRows(); + var contactsList = document.getElementById('contactsList'); + var rows = contactsList.getSelectedRowsId(); + for (var i = 0; i < rows.length; i++) { openContactWindow(null, 'writeto_' + rows[i], ApplicationBaseURL + currentContactFolder @@ -699,10 +682,10 @@ function onToolbarWriteToSelectedContacts(event) function uixDeleteSelectedContacts(sender) { - var rows; var failCount = 0; - - rows = collectSelectedRows(); + var contactsList = document.getElementById('contactsList'); + var rows = contactsList.getSelectedRowsId(); + for (var i = 0; i < rows.length; i++) { var url, http, rowElem; @@ -811,17 +794,14 @@ function onSearchKeyDown(searchValue) function onConfirmContactSelection() { - var rows = collectSelectedRows(); - var folderLi = document.getElementById(currentContactFolder); var currentContactFolderName = folderLi.innerHTML; + var contactsList = document.getElementById('contactsList'); + var rows = contactsList.getSelectedRows(); for (i = 0; i < rows.length; i++) { - var row = document.getElementById(rows[i]); -// opener.window.log (rows[i] + " selected."); -// opener.window.log (row.cells.length); - var cid = row.getAttribute("contactid"); + var cid = rows[i].getAttribute("contactid"); if (cid) { var cname = '' + row.getAttribute("contactname"); diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index ca3cd9a34..f2a83dff2 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -67,21 +67,6 @@ function toggleMailSelect(sender) { row.className = sender.checked ? "tableview_selected" : "tableview"; } -function collectSelectedRows() { - var rows = new Array(); - var messageList = document.getElementById('messageList'); - var tbody = (messageList.getElementsByTagName('tbody'))[0]; - var selectedRows = getSelectedNodes(tbody); - - for (var i = 0; i < selectedRows.length; i++) { - var row = selectedRows[i]; - var rowId = row.getAttribute('id').substring(4); - rows[rows.length] = rowId; - } - - return rows; -} - function clearSearch(sender) { var searchField = window.document.getElementById("search"); if (searchField) searchField.value=""; @@ -332,15 +317,16 @@ function reopenToRemoveLocationBar() { function openMessageWindowsForSelection(sender, action) { - var rows = collectSelectedRows(); + var messageList = document.getElementById("messageList"); + var rows = messageList.getSelectedRowsId(); var idset = ""; - - for (var i = 0; i < rows.length; i++) { + + for (var i = 0; i < rows.length; i++) win = openMessageWindow(sender, - rows[i] /* msguid */, + rows[i].substr(4) /* msguid */, ApplicationBaseURL + currentMailbox - + "/" + rows[i] + "/" + action /* url */); - } + + "/" + rows[i].substr(4) + + "/" + action /* url */); } function mailListMarkMessage(sender, action, msguid, markread) @@ -419,17 +405,19 @@ function ctxFolderDelete(sender) { /* bulk delete of messages */ function uixDeleteSelectedMessages(sender) { - var rows; var failCount = 0; - rows = collectSelectedRows(); + var messageList = document.getElementById("messageList"); + var rows = messageList.getSelectedRows(); + for (var i = 0; i < rows.length; i++) { var url, http, rowElem; /* send AJAX request (synchronously) */ url = (ApplicationBaseURL + currentMailbox + "/" - + rows[i] + "/trash?jsonly=1"); + + rows[i].getAttribute("id").substr(4) + + "/trash?jsonly=1"); http = createHTTPClient(); http.open("POST", url, false /* not async */); http.send(""); @@ -443,9 +431,7 @@ function uixDeleteSelectedMessages(sender) { /* remove from page */ /* line-through would be nicer, but hiding is OK too */ - rowElem = document.getElementById("row_" + rows[i]); - - rowElem.parentNode.removeChild(rowElem); + rowElem.parentNode.removeChild(rows[i]); } if (failCount > 0) @@ -610,12 +596,10 @@ function onMessageContextMenu(event, element) onMenuClick(event, 'messageListMenu'); var topNode = document.getElementById('messageList'); - var selectedNodeIds = collectSelectedRows(); - topNode.menuSelectedRows = selectedNodeIds; - for (var i = 0; i < selectedNodeIds.length; i++) { - var selectedNode = document.getElementById("row_" + selectedNodeIds[i]); - deselectNode (selectedNode); - } + var selectedNodes = topNode.getSelectedRows(); + for (var i = 0; i < selectedNodes.length; i++) + deselectNode (selectedNodes[i]); + topNode.menuSelectedRows = selectedNodes; topNode.menuSelectedEntry = element; selectNode(element); } @@ -629,11 +613,9 @@ function onMessageContextMenuHide(event) topNode.menuSelectedEntry = null; } if (topNode.menuSelectedRows) { - var nodeIds = topNode.menuSelectedRows; - for (var i = 0; i < nodeIds.length; i++) { - var node = document.getElementById("row_" + nodeIds[i]); - selectNode (node); - } + var nodes = topNode.menuSelectedRows; + for (var i = 0; i < nodes.length; i++) + selectNode(nodes[i]); topNode.menuSelectedRows = null; } } @@ -720,16 +702,17 @@ function storeCachedMessage(cachedMessage) function onMessageSelectionChange() { - var selection = collectSelectedRows(); - if (selection.length == 1) - { - var idx = selection[0]; + var messageList = document.getElementById("messageList"); + var rows = messageList.getSelectedRowsId(); - if (currentMessages[currentMailbox] != idx) { - currentMessages[currentMailbox] = idx; - loadMessage(idx); - } + if (rows.length == 1) { + var idx = rows[0].substr(4); + + if (currentMessages[currentMailbox] != idx) { + currentMessages[currentMailbox] = idx; + loadMessage(idx); } + } } function loadMessage(idx) @@ -794,10 +777,10 @@ function processMailboxMenuAction(mailbox) if (currentNode) { action = currentNode.getAttribute('mailboxaction'); - var rows = collectSelectedRows(); - var rString = rows.join(', '); - alert("performing '" + action + "' on " + rString - + " to " + mailboxName); +// var rows = collectSelectedRows(); +// var rString = rows.join(', '); +// alert("performing '" + action + "' on " + rString +// + " to " + mailboxName); } } diff --git a/UI/WebServerResources/SchedulerUI.js b/UI/WebServerResources/SchedulerUI.js index 3cf6d7282..09e7a9881 100644 --- a/UI/WebServerResources/SchedulerUI.js +++ b/UI/WebServerResources/SchedulerUI.js @@ -1,3 +1,67 @@ +var activeAjaxRequests = 0; + +var sortOrder = ''; +var sortKey = ''; + +function triggerAjaxRequest(url, callback, userdata) { + this.http = createHTTPClient(); + + activeAjaxRequests += 1; + document.animTimer = setTimeout("checkAjaxRequestsState();", 200); + + if (http) { + http.onreadystatechange + = function() { + try { + if (http.readyState == 4 + && activeAjaxRequests > 0) { + if (!http.aborted) { + http.callbackData = userdata; + callback(http); + } + activeAjaxRequests -= 1; + checkAjaxRequestsState(); + } + } + catch( e ) { + activeAjaxRequests -= 1; + checkAjaxRequestsState(); + alert('AJAX Request, Caught Exception: ' + e.description); + } + }; + http.url = url; + http.open("GET", url, true); + http.send(""); + } + + return http; +} + +function checkAjaxRequestsState() +{ + if (activeAjaxRequests > 0 + && !document.busyAnim) { + var anim = document.createElement("img"); + document.busyAnim = anim; + anim.setAttribute("src", ResourcesURL + '/busy.gif'); + anim.style.position = "absolute;"; + anim.style.top = "2.5em;"; + anim.style.right = "1em;"; + anim.style.visibility = "hidden;"; + anim.style.zindex = "1;"; + var folderTree = document.getElementById("toolbar"); + folderTree.appendChild(anim); + anim.style.visibility = "visible;"; + } else if (activeAjaxRequests == 0 + && document.busyAnim) { + document.busyAnim.parentNode.removeChild(document.busyAnim); + document.busyAnim = null; + } +} + +var currentDay = ''; +var currentView = 'day'; + function newEvent(sender) { var urlstr = ApplicationBaseURL + "new"; @@ -44,3 +108,252 @@ function onContactRefresh(node) return false; } + +function onDaySelect(node) +{ + currentDay = node.getAttribute("day"); + + var td = node.getParentWithTagName("td"); + var table = td.getParentWithTagName("table"); + +// log ("table.selected: " + table.selected); + + if (document.selectedDate) + deselectNode(document.selectedDate); + + selectNode(td); + document.selectedDate = td; + + changeDayDisplay(currentDay, null); + + return false; +} + +function initCriteria() +{ +} + +function onDateSelectorGotoMonth(node) +{ + var day = node.getAttribute("date"); + + changeDateSelectorDisplay(day); + + return false; +} + +function onCalendarGotoDay(node) +{ + var day = node.getAttribute("date"); + + changeDayDisplay(day); + + return false; +} + +function gotoToday() +{ + changeDateSelectorDisplay(); + changeDayDisplay(); + + return false; +} + +function dateSelectorCallback(http) +{ + var div = document.getElementById("dateSelectorView"); + + if (http.readyState == 4 + && http.status == 200) { + document.dateSelectorAjaxRequest = null; + div.innerHTML = http.responseText; + if (currentDay.length > 0) + restoreCurrentDaySelection(div); + } + else + log ("ajax fuckage"); +} + +function appointmentsListCallback(http) +{ + var div = document.getElementById("appointmentsListView"); + + if (http.readyState == 4 + && http.status == 200) { + log ("babla"); + document.dateSelectorAjaxRequest = null; + log ("babla"); + div.innerHTML = http.responseText; + log ("babla"); + + log ("received " + http.callbackData); + var params = parseQueryParameters(http.callbackData); + sortKey = params["sort"]; + sortOrder = params["desc"]; + + log ("sorting = " + sortKey + sortOrder); + } + else + log ("ajax fuckage"); +} + +function restoreCurrentDaySelection(div) +{ + var elements = div.getElementsByTagName("a"); + var day = null; + var i = 7; + while (!day && i < elements.length) + { + day = elements[i].getAttribute("day"); + i++; + } + + if (day + && day.substr(0, 6) == currentDay.substr(0, 6)) + { + for (i = 0; i < elements.length; i++) { + day = elements[i].getAttribute("day"); + if (day && day == currentDay) { + var td = elements[i].getParentWithTagName("td"); + if (document.selectedDate) + deselectNode(document.selectedDate); + selectNode(td); + document.selectedDate = td; + } + } + } +} + +function changeDateSelectorDisplay(day, event) +{ + var url = ApplicationBaseURL + "dateselector"; + if (day) + url += "?day=" + day; + +// if (currentDay.length > 0) +// url += '&selectedDay=' + currentDay; + + if (document.dateSelectorAjaxRequest) { + document.dateSelectorAjaxRequest.aborted = true; + document.dateSelectorAjaxRequest.abort(); + } + + document.dateSelectorAjaxRequest = triggerAjaxRequest(url, + dateSelectorCallback, + null); +// log ('should go to ' + day); +} + +function changeDayDisplay(day, event) +{ + var url = ApplicationBaseURL + "dayview"; + + if (day) + url += "?day=" + day; + + if (document.dayDisplayAjaxRequest) { + document.dayDisplayAjaxRequest.aborted = true; + document.dayDisplayAjaxRequest.abort(); + } + document.dayDisplayAjaxRequest = triggerAjaxRequest(url, + dayDisplayCallback, + null); + + return false; +} + +function dayDisplayCallback(http) +{ + var div = document.getElementById("calendarView"); + + if (http.readyState == 4 + && http.status == 200) { + document.dateSelectorAjaxRequest = null; + div.innerHTML = http.responseText; + } + else + log ("ajax fuckage"); +} + +function popupCalendar(node) +{ + var inputId = node.getAttribute("inputId"); + var dateFormat = node.getAttribute("dateFormat"); + + var calendar = new skycalendar(document.getElementById(inputId)); + calendar.setCalendarPage(ResourcesURL + "/skycalendar.html"); + calendar.setDateFormat(dateFormat); + calendar.popup(); + + return false; +} + +function onAppointmentContextMenu(event, element) +{ + var topNode = document.getElementById('appointmentsList'); + log(topNode); + + + var menu = document.getElementById('appointmentsListMenu'); + + menu.addEventListener("hideMenu", onAppointmentContextMenuHide, false); + onMenuClick(event, 'appointmentsListMenu'); + + var topNode = document.getElementById('appointmentsList'); + var selectedNodeIds = collectSelectedRows(); + topNode.menuSelectedRows = selectedNodeIds; + for (var i = 0; i < selectedNodeIds.length; i++) { + var selectedNode = document.getElementById(selectedNodeIds[i]); + deselectNode (selectedNode); + } + topNode.menuSelectedEntry = element; + selectNode(element); +} + +function onAppointmentContextMenuHide(event) +{ + var topNode = document.getElementById('appointmentsList'); + + if (topNode.menuSelectedEntry) { + deselectNode(topNode.menuSelectedEntry); + topNode.menuSelectedEntry = null; + } + if (topNode.menuSelectedRows) { + var nodeIds = topNode.menuSelectedRows; + for (var i = 0; i < nodeIds.length; i++) { + var node = document.getElementById(nodeIds[i]); + selectNode (node); + } + topNode.menuSelectedRows = null; + } +} + +function onAppointmentsSelectionChange() +{ +} + +function _loadAppointmentHref(href) { + if (this.document.appointmentsListAjaxRequest) { + this.document.appointmentsListAjaxRequest.aborted = true; + this.document.appointmentsListAjaxRequest.abort(); + } + url = ApplicationBaseURL + href; + log ("url: " + url); + this.document.appointmentsListAjaxRequest + = triggerAjaxRequest(url, appointmentsListCallback, href); + + return false; +} + +function onHeaderClick(node) +{ + var href = node.getAttribute("href"); + + return _loadAppointmentHref(href); +} + +function refreshAppointments() { + var href = "aptlist?desc=" + sortOrder + "&sort=" + sortKey; + + return _loadAppointmentHref(href); +} diff --git a/UI/WebServerResources/UIxAppointmentEditor.js b/UI/WebServerResources/UIxAppointmentEditor.js index 3c27bc34c..b9dc5324a 100644 --- a/UI/WebServerResources/UIxAppointmentEditor.js +++ b/UI/WebServerResources/UIxAppointmentEditor.js @@ -98,6 +98,8 @@ function submitMeeting(thisForm) { action.setAttribute("value", "save"); thisForm.submit(); - opener.window.location.reload(); + + opener.window.refreshAppointments(); + window.close(); } diff --git a/UI/WebServerResources/generic.js b/UI/WebServerResources/generic.js index 20e72b56d..feeb30367 100644 --- a/UI/WebServerResources/generic.js +++ b/UI/WebServerResources/generic.js @@ -25,6 +25,7 @@ /* generic stuff */ var logConsole; +var queryParameters; // logArea = null; var allDocumentElements = null; @@ -291,10 +292,12 @@ function removeClassName(node, className) { /* selection mechanism */ function selectNode(node) { +// log ("selecting a node: '" + node.tagName + "'"); addClassName(node, '_selected'); } function deselectNode(node) { +// log ("deselecting a node: '" + node.tagName + "'"); removeClassName(node, '_selected'); } @@ -320,25 +323,12 @@ function acceptMultiSelect(node) { return (accept == 'yes'); } -function getSelectedNodes(parentNode) { - var selArray = new Array(); - - for (var i = 0; i < parentNode.childNodes.length; i++) { - node = parentNode.childNodes.item(i); - if (node.nodeType == 1 - && isNodeSelected(node)) - selArray.push(node); - } - - return selArray; -} - function onRowClick(event) { var node = event.target; if (node.tagName == 'TD') node = node.parentNode; - var startSelection = getSelectedNodes(node.parentNode); + var startSelection = node.parentNode.getSelectedNodes(); if (event.shiftKey == 1 && (acceptMultiSelect(node.parentNode) || acceptMultiSelect(node.parentNode.parentNode))) { @@ -351,7 +341,8 @@ function onRowClick(event) { deselectAll(node.parentNode); selectNode(node); } - if (startSelection != getSelectedNodes(node.parentNode)) { + + if (startSelection != node.parentNode.getSelectedNodes()) { var parentNode = node.parentNode; if (parentNode.tagName == 'TBODY') parentNode = parentNode.parentNode; @@ -476,12 +467,53 @@ function onMenuEntryClick(event, menuId) return false; } +function initQueryParameters() { + queryParameters = parseQueryParameters('' + window.location); +} + +function parseQueryParameters(url) { + var parameters = new Array(); + + var params = url.split("?")[1]; + if (params) { + var pairs = params.split("&"); + for (var i = 0; i < pairs.length; i++) { + var pair = pairs[i].split("="); + parameters[pair[0]] = pair[1]; + } + } + + return parameters; +} + function initLogConsole() { - logConsole = document.getElementById('logConsole'); - logConsole.innerHTML = 'X'; + var logConsole = document.getElementById('logConsole'); + logConsole.innerHTML = 'X'; + + var node = document.getElementsByTagName('body')[0]; + + node.addEventListener("keydown", onBodyKeyDown, false); + logConsole.addEventListener("dblclick", onLogDblClick, false); +} + +function onBodyKeyDown(event) +{ + if (event.keyCode == 27) { + toggleLogConsole(); + event.cancelBubble = true; + event.returnValue = false; + } +} + +function onLogDblClick(event) +{ + var logConsole = document.getElementById('logConsole'); + logConsole.innerHTML = 'X'; } function toggleLogConsole() { + var logConsole = document.getElementById('logConsole'); + var visibility = '' + logConsole.style.visibility; if (visibility.length == 0) { logConsole.style.visibility = 'visible;'; @@ -493,6 +525,7 @@ function toggleLogConsole() { } function log(message) { + var logConsole = document.getElementById('logConsole'); logConsole.innerHTML += message + '
' + "\n"; } @@ -506,27 +539,24 @@ function dropDownSubmenu(event) var parentNode = getParentMenu(node); if (parentNode.submenu) hideMenu(event, parentNode.submenu); - var menuTop = (node.parentNode.parentNode.offsetTop - + node.offsetTop - 1); + submenuNode.parentMenuItem = node; + submenuNode.parentMenu = parentNode; + parentNode.submenuItem = node; + parentNode.submenu = submenuNode; + + var menuTop = (node.offsetTop - 2); var heightDiff = (window.innerHeight - (menuTop + submenuNode.offsetHeight)); if (heightDiff < 0) menuTop += heightDiff; - var menuLeft = (node.parentNode.parentNode.offsetLeft - + node.parentNode.parentNode.offsetWidth - - 2); - var leftDiff = (window.innerWidth - - (menuLeft + submenuNode.offsetWidth)); - if (leftDiff < 0) - menuLeft -= (node.parentNode.parentNode.offsetWidth - + submenuNode.offsetWidth - - 4); - submenuNode.parentMenuItem = node; - submenuNode.parentMenu = parentNode; - parentNode.submenuItem = node; - parentNode.submenu = submenuNode; + var menuLeft = parentNode.offsetWidth - 3; + if (window.innerWidth + < (menuLeft + submenuNode.offsetWidth + + parentNode.cascadeLeftOffset())) + menuLeft = -submenuNode.offsetWidth + 3; + parentNode.setAttribute('onmousemove', 'checkDropDown(event);'); node.setAttribute('class', 'submenu-selected'); submenuNode.style.top = menuTop + "px;"; @@ -537,24 +567,24 @@ function dropDownSubmenu(event) function checkDropDown(event) { - var parentNode = getParentMenu(event.target); - var submenuNode = parentNode.submenu; - if (submenuNode) + var parentMenu = getParentMenu(event.target); + var submenuItem = parentMenu.submenuItem; + if (submenuItem) { - var submenuItem = parentNode.submenuItem; - var itemX = submenuItem.offsetLeft + parentNode.offsetLeft; - var itemY = submenuItem.offsetTop + parentNode.offsetTop; + var menuX = event.clientX - parentMenu.cascadeLeftOffset(); + var menuY = event.clientY - parentMenu.cascadeTopOffset(); + var itemX = submenuItem.offsetLeft; + var itemY = submenuItem.offsetTop - 75; - if (event.clientX >= itemX - && event.clientX < submenuNode.offsetLeft - && (event.clientY < itemY - || event.clientY > (itemY - + submenuItem.offsetHeight))) + if (menuX >= itemX + && menuX < itemX + submenuItem.offsetWidth + && (menuY < itemY + || menuY > (itemY + submenuItem.offsetHeight))) { - hideMenu(event, submenuNode); - parentNode.submenu = null; - parentNode.submenuItem = null; - parentNode.setAttribute('onmousemove', null); + hideMenu(event, parentMenu.submenu); + parentMenu.submenu = null; + parentMenu.submenuItem = null; + parentMenu.setAttribute('onmousemove', null); } } } @@ -743,3 +773,110 @@ function addContact(selectorId, contactId, contactName) return false; } + +/* custom extensions to the DOM api */ +HTMLElement.prototype.getParentWithTagName = function(tagName) { + var currentElement = this; + tagName = tagName.toUpperCase(); + + currentElement = currentElement.parentNode; + while (currentElement + && currentElement.tagName != tagName) { + currentElement = currentElement.parentNode; + } + + return currentElement; +} + +HTMLElement.prototype.cascadeLeftOffset = function() { + var currentElement = this; + + var offset = 0; + while (currentElement) { + offset += currentElement.offsetLeft; + currentElement = currentElement.getParentWithTagName("div"); + } + + return offset; +} + +HTMLElement.prototype.cascadeTopOffset = function() { + var currentElement = this; + var offset = 0; + + var i = 0; + + while (currentElement + && currentElement instanceof HTMLElement) { + offset += currentElement.offsetTop; + currentElement = currentElement.parentNode; + i++; + } + + return offset; +} + +HTMLElement.prototype.dump = function(additionalInfo, additionalKeys) { + var id = this.getAttribute("id"); + var nclass = this.getAttribute("class"); + + var str = this.tagName; + if (id) + str += "; id = " + id; + if (nclass) + str += "; class = " + nclass; + + if (additionalInfo) + str += "; " + additionalInfo; + + if (additionalKeys) + for (var i = 0; i < additionalKeys.length; i++) { + var value = this.getAttribute(additionalKeys[i]); + if (value) + str += "; " + additionalKeys[i] + " = " + value; + } + + log (str); +} + +HTMLElement.prototype.getSelectedNodes = function() { + var selArray = new Array(); + + for (var i = 0; i < this.childNodes.length; i++) { + node = this.childNodes.item(i); + if (node.nodeType == 1 + && isNodeSelected(node)) + selArray.push(node); + } + + return selArray; +} + +HTMLElement.prototype.getSelectedNodesId = function() { + var selArray = new Array(); + + for (var i = 0; i < this.childNodes.length; i++) { + node = this.childNodes.item(i); + if (node.nodeType == 1 + && isNodeSelected(node)) + selArray.push(node.getAttribute("id")); + } + + return selArray; +} + +HTMLTableElement.prototype.getSelectedRows = function() { + var rows = new Array(); + + var tbody = (this.getElementsByTagName('tbody'))[0]; + + return tbody.getSelectedNodes(); +} + +HTMLTableElement.prototype.getSelectedRowsId = function() { + var rows = new Array(); + + var tbody = (this.getElementsByTagName('tbody'))[0]; + + return tbody.getSelectedNodesId(); +}