michael@0: michael@0: michael@0: # -*- Mode: HTML -*- michael@0: # This Source Code Form is subject to the terms of the Mozilla Public michael@0: # License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: # file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: michael@0: michael@0: %actionsDTD; michael@0: ]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: null michael@0: null michael@0: false michael@0: null michael@0: michael@0: null michael@0: null michael@0: null michael@0: null michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: let utils = {}; michael@0: Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm", utils); michael@0: utils.PrivateBrowsingUtils michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: 14 michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: false michael@0: false michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: = 1) michael@0: this.mController.handleTab(); michael@0: break; michael@0: case KeyEvent.DOM_VK_UP: michael@0: case KeyEvent.DOM_VK_DOWN: michael@0: case KeyEvent.DOM_VK_PAGE_UP: michael@0: case KeyEvent.DOM_VK_PAGE_DOWN: michael@0: cancel = this.mController.handleKeyNavigation(aEvent.keyCode); michael@0: break; michael@0: } michael@0: } michael@0: michael@0: // Handle keys we know aren't part of a shortcut, even with Alt or michael@0: // Ctrl. michael@0: switch (aEvent.keyCode) { michael@0: case KeyEvent.DOM_VK_ESCAPE: michael@0: cancel = this.mController.handleEscape(); michael@0: break; michael@0: case KeyEvent.DOM_VK_RETURN: michael@0: #ifdef XP_MACOSX michael@0: // Prevent the default action, since it will beep on Mac michael@0: if (aEvent.metaKey) michael@0: aEvent.preventDefault(); michael@0: #endif michael@0: this.mEnterEvent = aEvent; michael@0: cancel = this.mController.handleEnter(false); michael@0: break; michael@0: case KeyEvent.DOM_VK_DELETE: michael@0: #ifdef XP_MACOSX michael@0: case KeyEvent.DOM_VK_BACK_SPACE: michael@0: if (aEvent.shiftKey) michael@0: #endif michael@0: cancel = this.mController.handleDelete(); michael@0: break; michael@0: case KeyEvent.DOM_VK_DOWN: michael@0: case KeyEvent.DOM_VK_UP: michael@0: if (aEvent.altKey) michael@0: this.toggleHistoryPopup(); michael@0: break; michael@0: #ifndef XP_MACOSX michael@0: case KeyEvent.DOM_VK_F4: michael@0: this.toggleHistoryPopup(); michael@0: break; michael@0: #endif michael@0: } michael@0: michael@0: if (cancel) { michael@0: aEvent.stopPropagation(); michael@0: aEvent.preventDefault(); michael@0: } michael@0: michael@0: return true; michael@0: ]]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: false michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: false michael@0: false michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: 0) michael@0: this.tree.treeBoxObject.ensureRowIsVisible(val < 0 ? 0 : val); michael@0: // Fire select event on xul:tree so that accessibility API michael@0: // support layer can fire appropriate accessibility events. michael@0: var event = document.createEvent('Events'); michael@0: event.initEvent("select", true, true); michael@0: this.tree.dispatchEvent(event); michael@0: return val; michael@0: ]]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: 100 ? width : 100); michael@0: michael@0: // Adjust the direction of the autocomplete popup list based on the textbox direction, bug 649840 michael@0: var popupDirection = aElement.ownerDocument.defaultView.getComputedStyle(aElement).direction; michael@0: this.style.direction = popupDirection; michael@0: michael@0: this.openPopup(aElement, "after_start", 0, 0, false, false); michael@0: } michael@0: ]]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: document.getAnonymousElementByAttribute(this, "anonid", "tree"); michael@0: michael@0: michael@0: michael@0: document.getAnonymousElementByAttribute(this, "anonid", "treecols"); michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: null michael@0: false michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: 6 michael@0: michael@0: michael@0: -1 michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: aMaxRow && aIndex != aMaxRow) michael@0: newIdx = aMaxRow; michael@0: else if (!aReverse && aIndex == -1 || newIdx < 0 && aIndex != 0) michael@0: newIdx = 0; michael@0: michael@0: if (newIdx < 0 && aIndex == 0 || newIdx > aMaxRow && aIndex == aMaxRow) michael@0: aIndex = -1; michael@0: else michael@0: aIndex = newIdx; michael@0: michael@0: return aIndex; michael@0: ]]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: 0 michael@0: 0 michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: 100 ? width : 100); michael@0: // invalidate() depends on the width attribute michael@0: this._invalidate(); michael@0: michael@0: this.openPopup(aElement, "after_start", 0, 0, false, false); michael@0: } michael@0: ]]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: = matchCount) michael@0: return; michael@0: michael@0: var item; michael@0: michael@0: // trim the leading/trailing whitespace michael@0: var trimmedSearchString = controller.searchString.replace(/^\s+/, "").replace(/\s+$/, ""); michael@0: michael@0: // Unescape the URI spec for showing as an entry in the popup michael@0: let url = Components.classes["@mozilla.org/intl/texttosuburi;1"]. michael@0: getService(Components.interfaces.nsITextToSubURI). michael@0: unEscapeURIForUI("UTF-8", controller.getValueAt(this._currentIndex)); michael@0: michael@0: if (typeof this.input.trimValue == "function") michael@0: url = this.input.trimValue(url); michael@0: michael@0: if (this._currentIndex < existingItemsCount) { michael@0: // re-use the existing item michael@0: item = this.richlistbox.childNodes[this._currentIndex]; michael@0: michael@0: // Completely re-use the existing richlistitem if it's the same michael@0: if (item.getAttribute("text") == trimmedSearchString && michael@0: item.getAttribute("url") == url) { michael@0: item.collapsed = false; michael@0: this._currentIndex++; michael@0: continue; michael@0: } michael@0: } michael@0: else { michael@0: // need to create a new item michael@0: item = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "richlistitem"); michael@0: } michael@0: michael@0: // set these attributes before we set the class michael@0: // so that we can use them from the constructor michael@0: item.setAttribute("image", controller.getImageAt(this._currentIndex)); michael@0: item.setAttribute("url", url); michael@0: item.setAttribute("title", controller.getCommentAt(this._currentIndex)); michael@0: item.setAttribute("type", controller.getStyleAt(this._currentIndex)); michael@0: item.setAttribute("text", trimmedSearchString); michael@0: michael@0: if (this._currentIndex < existingItemsCount) { michael@0: // re-use the existing item michael@0: item._adjustAcItem(); michael@0: item.collapsed = false; michael@0: } michael@0: else { michael@0: // set the class at the end so we can use the attributes michael@0: // in the xbl constructor michael@0: item.className = "autocomplete-richlistitem"; michael@0: this.richlistbox.appendChild(item); michael@0: } michael@0: michael@0: this._currentIndex++; michael@0: } michael@0: michael@0: // yield after each batch of items so that typing the url bar is responsive michael@0: setTimeout(function (self) { self._appendCurrentResult(); }, 0, this); michael@0: ]]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: document.getAnonymousElementByAttribute(this, "anonid", "richlistbox"); michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: ") is related to the class of the image, michael@0: // and is not "visible" text so don't use it for the label (for accessibility). michael@0: return title + " " + url; michael@0: ]]> michael@0: michael@0: michael@0: michael@0: null michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: = 0) { michael@0: // Start the next search from where this one finished michael@0: startIndex = matchIndex + searchLen; michael@0: regions.push([matchIndex, startIndex]); michael@0: } michael@0: } michael@0: michael@0: // Sort the regions by start position then end position michael@0: regions = regions.sort(function(a, b) let (start = a[0] - b[0]) michael@0: start == 0 ? a[1] - b[1] : start); michael@0: michael@0: // Generate the boundary indices from each region michael@0: let start = 0; michael@0: let end = 0; michael@0: let boundaries = []; michael@0: let len = regions.length; michael@0: for (let i = 0; i < len; i++) { michael@0: // We have a new boundary if the start of the next is past the end michael@0: let region = regions[i]; michael@0: if (region[0] > end) { michael@0: // First index is the beginning of match michael@0: boundaries.push(start); michael@0: // Second index is the beginning of non-match michael@0: boundaries.push(end); michael@0: michael@0: // Track the new region now that we've stored the previous one michael@0: start = region[0]; michael@0: } michael@0: michael@0: // Push back the end index for the current or new region michael@0: end = Math.max(end, region[1]); michael@0: } michael@0: michael@0: // Add the last region michael@0: boundaries.push(start); michael@0: boundaries.push(end); michael@0: michael@0: // Put on the end boundary if necessary michael@0: if (end < aText.length) michael@0: boundaries.push(aText.length); michael@0: michael@0: // Skip the first item because it's always 0 michael@0: return boundaries.slice(1); michael@0: ]]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: = 0) { michael@0: let [,action, param] = url.match(/^moz-action:([^,]+),(.*)$/); michael@0: this.setAttribute("actiontype", action); michael@0: url = param; michael@0: let desc = "]]>&action.switchToTab.label; michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: 0) { michael@0: // Subtract a little less to account for subpixel rounding michael@0: widthDiff -= childWidth - .5; michael@0: michael@0: // Add to the tooltip if it's not hidden and has text michael@0: let childText = children[i].textContent; michael@0: if (childText) michael@0: tooltip.push(childText); michael@0: } michael@0: } michael@0: michael@0: // If the children take up more space than the parent.. overflow! michael@0: if (widthDiff < 0) { michael@0: // Re-show the ellipsis now that we know it's needed michael@0: aEllipsis.style.visibility = "visible"; michael@0: michael@0: // Separate text components with a ndash -- michael@0: aParentBox.tooltipText = tooltip.join(" \u2013 "); michael@0: } michael@0: ]]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: Date.now() michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: 30) { michael@0: var item = event.target; michael@0: michael@0: while (item && item.localName != "richlistitem") michael@0: item = item.parentNode; michael@0: michael@0: if (!item) michael@0: return; michael@0: michael@0: var rc = this.getIndexOfItem(item); michael@0: if (rc != this.selectedIndex) michael@0: this.selectedIndex = rc; michael@0: michael@0: this.mLastMoveTime = Date.now(); michael@0: } michael@0: ]]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: Date.now() michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: 30) { michael@0: var rc = this.parentNode.treeBoxObject.getRowAt(event.clientX, event.clientY); michael@0: if (rc != this.parentNode.currentIndex) michael@0: this.parentNode.view.selection.select(rc); michael@0: this.mLastMoveTime = Date.now(); michael@0: } michael@0: ]]> michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: