?? addressingwidgetoverlay.js
字號:
//function awRecipientErrorCommand(errItem, element){ // remove the angle brackets from the general error message to construct // the title for the alert. someday we'll pass this info using a real // exception object, and then this code can go away. // var generalErrString; if (errItem.value != "") generalErrString = errItem.value.slice(1, errItem.value.length-1); else generalErrString = "Unknown LDAP server problem encountered"; // try and get the string of the specific error to contruct the complete // err msg, otherwise fall back to something generic. This message is // handed to us as an nsISupportsString in the param slot of the // autocomplete error item, by agreement documented in // nsILDAPAutoCompFormatter.idl // var specificErrString = ""; try { var specificError = errItem.param.QueryInterface(Components.interfaces.nsISupportsString); specificErrString = specificError.data; } catch (ex) {} if (specificErrString == "") specificErrString = "Internal error"; if (gPromptService) gPromptService.alert(window, generalErrString, specificErrString); else window.alert(generalErrString + ": " + specificErrString);}function awRecipientKeyPress(event, element){ switch(event.keyCode) { case KeyEvent.DOM_VK_UP: awArrowHit(element, -1); break; case KeyEvent.DOM_VK_DOWN: awArrowHit(element, 1); break; case KeyEvent.DOM_VK_RETURN: case KeyEvent.DOM_VK_TAB: // if the user text contains a comma or a line return, ignore if (element.value.search(',') != -1) { var addresses = element.value; element.value = ""; // clear out the current line so we don't try to autocomplete it.. parseAndAddAddresses(addresses, awGetPopupElement(awGetRowByInputElement(element)).selectedItem.getAttribute("value")); } else if (event.keyCode == KeyEvent.DOM_VK_TAB) awTabFromRecipient(element, event); break; }}function awArrowHit(inputElement, direction){ var row = awGetRowByInputElement(inputElement) + direction; if (row) { var nextInput = awGetInputElement(row); if (nextInput) awSetFocus(row, nextInput); else if (inputElement.value) awAppendNewRow(true); }}function awRecipientKeyDown(event, element){ switch(event.keyCode) { case 46: case 8: /* do not query directly the value of the text field else the autocomplete widget could potentially alter it value while doing some internal cleanup, instead, query the value through the first child */ if (!element.value) awDeleteHit(element); // We need to stop the event else the listbox will receive it and the // function awKeyDown will be executed! event.stopPropagation(); break; }}function awKeyDown(event, listboxElement){ switch(event.keyCode) { case 46: case 8: /* Warning, the listboxElement.selectedItems will change everytime we delete a row */ var selItems = listboxElement.selectedItems; var length = listboxElement.selectedItems.length; for (var i = 1; i <= length; i++) { var inputs = listboxElement.selectedItems[0].getElementsByTagName(awInputElementName()); if (inputs && inputs.length == 1) awDeleteHit(inputs[0]); } break; }}function awMenulistKeyPress(event, element){ switch(event.keyCode) { case 9: awTabFromMenulist(element, event); break; }}/* ::::::::::: addressing widget dummy rows ::::::::::::::::: */var gAWContentHeight = 0;var gAWRowHeight = 0;function awFitDummyRows(){ awCalcContentHeight(); awCreateOrRemoveDummyRows();}function awCreateOrRemoveDummyRows(){ var listbox = document.getElementById("addressingWidget"); var listboxHeight = listbox.boxObject.height; // remove rows to remove scrollbar var kids = listbox.childNodes; for (var i = kids.length-1; gAWContentHeight > listboxHeight && i >= 0; --i) { if (kids[i].hasAttribute("_isDummyRow")) { gAWContentHeight -= gAWRowHeight; listbox.removeChild(kids[i]); } } // add rows to fill space if (gAWRowHeight) { while (gAWContentHeight+gAWRowHeight < listboxHeight) { awCreateDummyItem(listbox); gAWContentHeight += gAWRowHeight; } }}function awCalcContentHeight(){ var listbox = document.getElementById("addressingWidget"); var items = listbox.getElementsByTagName("listitem"); gAWContentHeight = 0; if (items.length > 0) { // all rows are forced to a uniform height in xul listboxes, so // find the first listitem with a boxObject and use it as precedent var i = 0; do { gAWRowHeight = items[i].boxObject.height; ++i; } while (i < items.length && !gAWRowHeight); gAWContentHeight = gAWRowHeight*items.length; }}function awCreateDummyItem(aParent){ var titem = document.createElement("listitem"); titem.setAttribute("_isDummyRow", "true"); titem.setAttribute("class", "dummy-row"); for (var i = awGetNumberOfCols(); i > 0; i--) awCreateDummyCell(titem); if (aParent) aParent.appendChild(titem); return titem;}function awCreateDummyCell(aParent){ var cell = document.createElement("listcell"); cell.setAttribute("class", "addressingWidgetCell dummy-row-cell"); if (aParent) aParent.appendChild(cell); return cell;}function awGetNextDummyRow(){ // gets the next row from the top down var listbox = document.getElementById("addressingWidget"); var kids = listbox.childNodes; for (var i = 0; i < kids.length; ++i) { if (kids[i].hasAttribute("_isDummyRow")) return kids[i]; } return null;}function awSizerListen(){ // when splitter is clicked, fill in necessary dummy rows each time the mouse is moved awCalcContentHeight(); // precalculate document.addEventListener("mousemove", awSizerMouseMove, true); document.addEventListener("mouseup", awSizerMouseUp, false);}function awSizerMouseMove(){ awCreateOrRemoveDummyRows(2);}function awSizerMouseUp(){ document.removeEventListener("mousemove", awSizerMouseUp, false); document.removeEventListener("mouseup", awSizerMouseUp, false);}function awDocumentKeyPress(event){ try { var id = event.target.getAttribute('id'); if (id.substr(0, 11) == 'addressCol1') awMenulistKeyPress(event, event.target); } catch (e) { }}function awRecipientInputCommand(event, inputElement){ gContentChanged=true; setupAutocomplete(); }// Given an arbitrary block of text like a comma delimited list of names or a names separated by spaces,// we will try to autocomplete each of the names and then take the FIRST match for each name, adding it the// addressing widget on the compose window.var gAutomatedAutoCompleteListener = null;function parseAndAddAddresses(addressText, recipientType){ // strip any leading >> characters inserted by the autocomplete widget var strippedAddresses = addressText.replace(/.* >> /, ""); var hdrParser = Components.classes["@mozilla.org/messenger/headerparser;1"].getService(Components.interfaces.nsIMsgHeaderParser); var addresses = {}; var names = {}; var fullNames = {}; var numAddresses = hdrParser.parseHeadersWithArray(strippedAddresses, addresses, names, fullNames); if (numAddresses > 0) { // we need to set up our own autocomplete session and search for results setupAutocomplete(); // be safe, make sure we are setup if (!gAutomatedAutoCompleteListener) gAutomatedAutoCompleteListener = new AutomatedAutoCompleteHandler(); gAutomatedAutoCompleteListener.init(fullNames.value, numAddresses, recipientType); }}function AutomatedAutoCompleteHandler(){}// state driven self contained object which will autocomplete a block of addresses without any UI. // force picks the first match and adds it to the addressing widget, then goes on to the next // name to complete.AutomatedAutoCompleteHandler.prototype ={ param: this, sessionName: null, namesToComplete: {}, numNamesToComplete: 0, indexIntoNames: 0, numSessionsToSearch: 0, numSessionsSearched: 0, recipientType: null, searchResults: null, init:function(namesToComplete, numNamesToComplete, recipientType) { this.indexIntoNames = 0; this.numNamesToComplete = numNamesToComplete; this.namesToComplete = namesToComplete; this.recipientType = recipientType; // set up the auto complete sessions to use setupAutocomplete(); this.autoCompleteNextAddress(); }, autoCompleteNextAddress:function() { this.numSessionsToSearch = 0; this.numSessionsSearched = 0; this.searchResults = new Array; if (this.indexIntoNames < this.numNamesToComplete && this.namesToComplete[this.indexIntoNames]) { if (this.namesToComplete[this.indexIntoNames].search('@') == -1) // don't autocomplete if address has an @ sign in it { // make sure total session count is updated before we kick off ANY actual searches if (gAutocompleteSession) this.numSessionsToSearch++; if (gLDAPSession && gCurrentAutocompleteDirectory) this.numSessionsToSearch++; if (gAutocompleteSession) { gAutocompleteSession.onAutoComplete(this.namesToComplete[this.indexIntoNames], null, this); // AB searches are actually synchronous. So by the time we get here we have already looked up results. // if we WERE going to also do an LDAP lookup, then check to see if we have a valid match in the AB, if we do // don't bother with the LDAP search too just return if (gLDAPSession && gCurrentAutocompleteDirectory && this.searchResults[0] && this.searchResults[0].defaultItemIndex != -1) { this.processAllResults(); return; } } if (gLDAPSession && gCurrentAutocompleteDirectory) gLDAPSession.onStartLookup(this.namesToComplete[this.indexIntoNames], null, this); } if (!this.numSessionsToSearch) this.processAllResults(); // ldap and ab are turned off, so leave text alone } }, onStatus:function(aStatus) { return; }, onAutoComplete: function(aResults, aStatus) { // store the results until all sessions are done and have reported in if (aResults) this.searchResults[this.numSessionsSearched] = aResults; this.numSessionsSearched++; // bump our counter if (this.numSessionsToSearch <= this.numSessionsSearched) setTimeout('gAutomatedAutoCompleteListener.processAllResults()', 0); // we are all done }, processAllResults: function() { // Take the first result and add it to the compose window var addressToAdd; // loop through the results looking for the non default case (default case is the address book with only one match, the default domain) var sessionIndex; var searchResultsForSession; for (sessionIndex in this.searchResults) { searchResultsForSession = this.searchResults[sessionIndex]; if (searchResultsForSession && searchResultsForSession.defaultItemIndex > -1) { addressToAdd = searchResultsForSession.items.QueryElementAt(searchResultsForSession.defaultItemIndex, Components.interfaces.nsIAutoCompleteItem).value; break; } } // still no match? loop through looking for the -1 default index if (!addressToAdd) { for (sessionIndex in this.searchResults) { searchResultsForSession = this.searchResults[sessionIndex]; if (searchResultsForSession && searchResultsForSession.defaultItemIndex == -1) { addressToAdd = searchResultsForSession.items.QueryElementAt(0, Components.interfaces.nsIAutoCompleteItem).value; break; } } } // no matches anywhere...just use what we were given if (!addressToAdd) addressToAdd = this.namesToComplete[this.indexIntoNames]; // that will automatically set the focus on a new available row, and make sure it is visible awAddRecipient(this.recipientType ? this.recipientType : "addr_to", addressToAdd); this.indexIntoNames++; this.autoCompleteNextAddress(); }, QueryInterface : function(iid) { if (iid.equals(Components.interfaces.nsIAutoCompleteListener) || iid.equals(Components.interfaces.nsISupports)) return this; throw Components.results.NS_NOINTERFACE; }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -