2008-09-26 00:34:54 -07:00
|
|
|
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
|
2008-05-02 13:15:45 -07:00
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is Mozilla Mobile Browser.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Mozilla Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2008
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Mark Finkle <mfinkle@mozilla.com>
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
2009-08-25 21:49:26 -07:00
|
|
|
Cu.import("resource://gre/modules/utils.js");
|
|
|
|
Cu.import("resource://gre/modules/PluralForm.jsm");
|
2008-10-01 12:54:16 -07:00
|
|
|
|
2009-04-22 13:45:51 -07:00
|
|
|
const TOOLBARSTATE_LOADING = 1;
|
|
|
|
const TOOLBARSTATE_LOADED = 2;
|
2008-05-02 13:15:45 -07:00
|
|
|
|
2008-09-29 06:53:49 -07:00
|
|
|
[
|
2009-03-05 15:30:28 -08:00
|
|
|
[
|
|
|
|
"gHistSvc",
|
|
|
|
"@mozilla.org/browser/nav-history-service;1",
|
|
|
|
[Ci.nsINavHistoryService, Ci.nsIBrowserHistory]
|
|
|
|
],
|
2009-10-09 05:34:02 -07:00
|
|
|
[
|
|
|
|
"gFaviconService",
|
|
|
|
"@mozilla.org/browser/favicon-service;1",
|
|
|
|
[Ci.nsIFaviconService]
|
|
|
|
],
|
|
|
|
[
|
|
|
|
"gIOService",
|
|
|
|
"@mozilla.org/network/io-service;1",
|
|
|
|
[Ci.nsIIOService],
|
|
|
|
],
|
2009-03-05 15:30:28 -08:00
|
|
|
[
|
|
|
|
"gURIFixup",
|
|
|
|
"@mozilla.org/docshell/urifixup;1",
|
|
|
|
[Ci.nsIURIFixup]
|
2009-03-05 18:45:52 -08:00
|
|
|
],
|
|
|
|
[
|
|
|
|
"gPrefService",
|
|
|
|
"@mozilla.org/preferences-service;1",
|
|
|
|
[Ci.nsIPrefBranch2]
|
2009-10-12 11:23:29 -07:00
|
|
|
],
|
|
|
|
[
|
|
|
|
"gFocusManager",
|
|
|
|
"@mozilla.org/focus-manager;1",
|
|
|
|
[Ci.nsIFocusManager]
|
2009-11-23 23:46:01 -08:00
|
|
|
],
|
|
|
|
[
|
|
|
|
"gObserverService",
|
|
|
|
"@mozilla.org/observer-service;1",
|
|
|
|
[Ci.nsIObserverService]
|
2009-03-05 15:30:28 -08:00
|
|
|
]
|
|
|
|
].forEach(function (service) {
|
|
|
|
let [name, contract, ifaces] = service;
|
2008-09-29 06:53:49 -07:00
|
|
|
window.__defineGetter__(name, function () {
|
|
|
|
delete window[name];
|
2009-03-05 15:30:28 -08:00
|
|
|
window[name] = Cc[contract].getService(ifaces.splice(0, 1)[0]);
|
|
|
|
if (ifaces.length)
|
2009-04-17 07:41:44 -07:00
|
|
|
ifaces.forEach(function (i) { return window[name].QueryInterface(i); });
|
2009-03-05 15:30:28 -08:00
|
|
|
return window[name];
|
2008-09-29 06:53:49 -07:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2008-07-03 23:39:25 -07:00
|
|
|
var BrowserUI = {
|
2008-05-02 13:15:45 -07:00
|
|
|
_edit : null,
|
|
|
|
_throbber : null,
|
|
|
|
_favicon : null,
|
2009-07-08 07:55:07 -07:00
|
|
|
_dialogs: [],
|
2008-05-02 13:15:45 -07:00
|
|
|
|
2009-09-30 12:14:06 -07:00
|
|
|
_domWillOpenModalDialog: function(e) {
|
|
|
|
if (!e.isTrusted)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// We're about to open a modal dialog, make sure the opening
|
|
|
|
// tab is brought to the front.
|
|
|
|
|
2009-10-14 13:44:09 -07:00
|
|
|
let window = e.target.top;
|
|
|
|
for (let i = 0; i < Browser._tabs.length; i++) {
|
|
|
|
if (Browser._tabs[i].browser.contentWindow == window) {
|
2009-09-30 12:14:06 -07:00
|
|
|
Browser.selectedTab = Browser._tabs[i];
|
2009-10-14 13:44:09 -07:00
|
|
|
break;
|
2009-09-30 12:14:06 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2008-08-19 23:09:22 -07:00
|
|
|
_titleChanged : function(aDocument) {
|
2009-01-08 22:51:13 -08:00
|
|
|
var browser = Browser.selectedBrowser;
|
2008-08-19 23:09:22 -07:00
|
|
|
if (browser && aDocument != browser.contentDocument)
|
2008-05-02 13:15:45 -07:00
|
|
|
return;
|
|
|
|
|
2008-09-27 07:07:04 -07:00
|
|
|
var caption = aDocument.title;
|
|
|
|
if (!caption) {
|
|
|
|
caption = this.getDisplayURI(browser);
|
|
|
|
if (caption == "about:blank")
|
|
|
|
caption = "";
|
|
|
|
}
|
2009-09-18 21:17:52 -07:00
|
|
|
|
|
|
|
this._setURI(caption);
|
2008-05-02 13:15:45 -07:00
|
|
|
},
|
|
|
|
|
2009-07-16 08:45:50 -07:00
|
|
|
/*
|
|
|
|
* Dispatched by window.close() to allow us to turn window closes into tabs
|
|
|
|
* closes.
|
|
|
|
*/
|
|
|
|
_domWindowClose: function (aEvent) {
|
|
|
|
if (!aEvent.isTrusted)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Find the relevant tab, and close it.
|
|
|
|
let browsers = Browser.browsers;
|
|
|
|
for (let i = 0; i < browsers.length; i++) {
|
|
|
|
if (browsers[i].contentWindow == aEvent.target) {
|
|
|
|
Browser.closeTab(Browser.getTabAtIndex(i));
|
|
|
|
aEvent.preventDefault();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2008-05-02 13:15:45 -07:00
|
|
|
_linkAdded : function(aEvent) {
|
2009-06-08 11:09:18 -07:00
|
|
|
let link = aEvent.originalTarget;
|
2008-11-10 09:57:53 -08:00
|
|
|
if (!link || !link.href)
|
2008-05-02 13:15:45 -07:00
|
|
|
return;
|
|
|
|
|
2008-11-10 09:55:22 -08:00
|
|
|
if (/\bicon\b/i(link.rel)) {
|
2010-03-04 12:12:15 -08:00
|
|
|
// Must have an owner document and not be in a frame
|
2009-10-09 05:34:02 -07:00
|
|
|
var ownerDoc = link.ownerDocument;
|
2010-03-04 12:12:15 -08:00
|
|
|
if (!ownerDoc || ownerDoc.defaultView.frameElement)
|
2009-10-09 05:34:02 -07:00
|
|
|
return;
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-10-09 05:34:02 -07:00
|
|
|
let tab = Browser.getTabForDocument(ownerDoc);
|
|
|
|
tab.setIcon(link.href);
|
2009-01-30 08:58:26 -08:00
|
|
|
// If the link changes after pageloading, update it right away.
|
|
|
|
// otherwise we wait until the pageload finishes
|
2009-10-09 05:34:02 -07:00
|
|
|
if ((tab.browser == Browser.selectedBrowser) && !tab.isLoading())
|
|
|
|
this._updateIcon(tab.browser.mIconURL);
|
2008-05-02 13:15:45 -07:00
|
|
|
}
|
2009-08-26 12:29:46 -07:00
|
|
|
else if (/\bsearch\b/i(link.rel)) {
|
|
|
|
var type = link.type && link.type.toLowerCase();
|
|
|
|
type = type.replace(/^\s+|\s*(?:;.*)?$/g, "");
|
|
|
|
if (type == "application/opensearchdescription+xml" && link.title && /^(?:https?|ftp):/i.test(link.href)) {
|
|
|
|
var engine = { title: link.title, href: link.href };
|
|
|
|
|
|
|
|
BrowserSearch.addPageSearchEngine(engine, link.ownerDocument);
|
|
|
|
}
|
|
|
|
}
|
2008-05-02 13:15:45 -07:00
|
|
|
},
|
|
|
|
|
2009-06-24 15:43:26 -07:00
|
|
|
_updateButtons : function(aBrowser) {
|
2009-11-22 20:08:18 -08:00
|
|
|
let back = document.getElementById("cmd_back");
|
|
|
|
let forward = document.getElementById("cmd_forward");
|
2009-06-24 15:43:26 -07:00
|
|
|
|
|
|
|
back.setAttribute("disabled", !aBrowser.canGoBack);
|
|
|
|
forward.setAttribute("disabled", !aBrowser.canGoForward);
|
|
|
|
},
|
|
|
|
|
2009-11-22 20:08:18 -08:00
|
|
|
_updateToolbarButton: function() {
|
|
|
|
let icons = document.getElementById("urlbar-icons");
|
|
|
|
if (Browser.selectedTab.isLoading() && icons.getAttribute("mode") != "loading") {
|
|
|
|
icons.setAttribute("mode", "loading");
|
|
|
|
}
|
|
|
|
else if (icons.getAttribute("mode") != "view") {
|
|
|
|
icons.setAttribute("mode", "view");
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2008-08-19 23:09:22 -07:00
|
|
|
_tabSelect : function(aEvent) {
|
2009-11-22 20:08:18 -08:00
|
|
|
let browser = Browser.selectedBrowser;
|
2008-08-19 23:09:22 -07:00
|
|
|
this._titleChanged(browser.contentDocument);
|
2009-11-22 20:08:18 -08:00
|
|
|
this._updateToolbarButton();
|
2009-06-24 15:43:26 -07:00
|
|
|
this._updateButtons(browser);
|
2009-10-09 05:34:02 -07:00
|
|
|
this._updateIcon(browser.mIconURL);
|
2009-07-05 09:22:09 -07:00
|
|
|
this.updateStar();
|
2008-05-02 13:15:45 -07:00
|
|
|
},
|
|
|
|
|
2009-08-24 08:00:28 -07:00
|
|
|
showToolbar : function showToolbar(aEdit) {
|
2009-04-22 13:45:51 -07:00
|
|
|
this.hidePanel();
|
2009-09-18 21:17:52 -07:00
|
|
|
this._editURI(aEdit);
|
2008-08-19 12:19:47 -07:00
|
|
|
},
|
|
|
|
|
2009-08-24 07:18:26 -07:00
|
|
|
_toolbarLocked: 0,
|
2009-11-23 23:46:01 -08:00
|
|
|
|
|
|
|
isToolbarLocked: function isToolbarLocked() {
|
|
|
|
return this._toolbarLocked;
|
|
|
|
},
|
|
|
|
|
2009-08-24 07:18:26 -07:00
|
|
|
lockToolbar: function lockToolbar() {
|
|
|
|
this._toolbarLocked++;
|
|
|
|
document.getElementById("toolbar-moveable-container").top = "0";
|
2009-11-02 21:13:42 -08:00
|
|
|
if (this._toolbarLocked == 1)
|
|
|
|
Browser.forceChromeReflow();
|
2009-08-24 07:18:26 -07:00
|
|
|
},
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-08-24 07:18:26 -07:00
|
|
|
unlockToolbar: function unlockToolbar() {
|
|
|
|
if (!this._toolbarLocked)
|
|
|
|
return;
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-08-24 07:18:26 -07:00
|
|
|
this._toolbarLocked--;
|
2009-08-26 10:18:13 -07:00
|
|
|
if (!this._toolbarLocked)
|
2009-08-24 07:18:26 -07:00
|
|
|
document.getElementById("toolbar-moveable-container").top = "";
|
|
|
|
},
|
|
|
|
|
2009-09-18 21:17:52 -07:00
|
|
|
_setURI: function _setURI(aCaption) {
|
|
|
|
if (this.isAutoCompleteOpen())
|
|
|
|
this._edit.defaultValue = aCaption;
|
|
|
|
else
|
|
|
|
this._edit.value = aCaption;
|
|
|
|
},
|
|
|
|
|
|
|
|
_editURI : function _editURI(aEdit) {
|
2008-12-09 22:21:08 -08:00
|
|
|
var icons = document.getElementById("urlbar-icons");
|
2009-06-25 21:48:10 -07:00
|
|
|
if (aEdit && icons.getAttribute("mode") != "edit") {
|
2008-12-09 22:21:08 -08:00
|
|
|
icons.setAttribute("mode", "edit");
|
2009-06-25 21:23:01 -07:00
|
|
|
this._edit.defaultValue = this._edit.value;
|
2008-12-10 23:05:55 -08:00
|
|
|
|
2009-01-08 22:51:13 -08:00
|
|
|
let urlString = this.getDisplayURI(Browser.selectedBrowser);
|
2008-12-10 23:05:55 -08:00
|
|
|
if (urlString == "about:blank")
|
|
|
|
urlString = "";
|
|
|
|
this._edit.value = urlString;
|
2009-09-30 12:19:42 -07:00
|
|
|
|
|
|
|
// This is a workaround for bug 488420, needed to cycle focus for the
|
|
|
|
// IME state to be set properly. Testing shows we only really need to
|
|
|
|
// do this the first time.
|
|
|
|
this._edit.blur();
|
2009-10-12 11:23:29 -07:00
|
|
|
gFocusManager.setFocus(this._edit, Ci.nsIFocusManager.FLAG_NOSCROLL);
|
2008-09-11 18:11:46 -07:00
|
|
|
}
|
2009-11-22 20:08:18 -08:00
|
|
|
else if (!aEdit) {
|
|
|
|
this._updateToolbarButton();
|
2008-09-11 18:11:46 -07:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2009-07-08 07:55:07 -07:00
|
|
|
_closeOrQuit: function _closeOrQuit() {
|
|
|
|
// Close active dialog, if we have one. If not then close the application.
|
|
|
|
let dialog = this.activeDialog;
|
|
|
|
if (dialog)
|
|
|
|
dialog.close();
|
|
|
|
else
|
2009-08-25 13:04:25 -07:00
|
|
|
window.close();
|
2009-07-08 07:55:07 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
get activeDialog() {
|
|
|
|
// Return the topmost dialog
|
|
|
|
if (this._dialogs.length)
|
|
|
|
return this._dialogs[this._dialogs.length - 1];
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
|
|
|
|
pushDialog : function pushDialog(aDialog) {
|
|
|
|
// If we have a dialog push it on the stack and set the attr for CSS
|
|
|
|
if (aDialog) {
|
2009-08-24 07:18:26 -07:00
|
|
|
this.lockToolbar();
|
2009-07-08 07:55:07 -07:00
|
|
|
this._dialogs.push(aDialog);
|
2009-07-20 13:22:22 -07:00
|
|
|
document.getElementById("toolbar-main").setAttribute("dialog", "true");
|
2009-11-23 09:23:59 -08:00
|
|
|
Elements.contentShowing.setAttribute("disabled", "true");
|
2009-07-08 07:55:07 -07:00
|
|
|
}
|
|
|
|
},
|
2009-07-21 08:28:29 -07:00
|
|
|
|
2009-07-08 07:55:07 -07:00
|
|
|
popDialog : function popDialog() {
|
2009-08-24 07:22:26 -07:00
|
|
|
if (this._dialogs.length) {
|
2009-07-08 07:55:07 -07:00
|
|
|
this._dialogs.pop();
|
2009-08-24 07:22:26 -07:00
|
|
|
this.unlockToolbar();
|
|
|
|
}
|
2009-07-08 07:55:07 -07:00
|
|
|
|
|
|
|
// If no more dialogs are being displayed, remove the attr for CSS
|
2009-11-23 09:23:59 -08:00
|
|
|
if (!this._dialogs.length) {
|
2009-07-20 13:22:22 -07:00
|
|
|
document.getElementById("toolbar-main").removeAttribute("dialog");
|
2009-11-23 09:23:59 -08:00
|
|
|
Elements.contentShowing.removeAttribute("disabled");
|
|
|
|
}
|
2009-07-08 07:55:07 -07:00
|
|
|
},
|
|
|
|
|
2009-08-14 10:30:50 -07:00
|
|
|
pushPopup: function pushPopup(aPanel, aElements) {
|
2009-12-04 12:03:56 -08:00
|
|
|
this._hidePopup();
|
2010-01-15 21:41:48 -08:00
|
|
|
this._popup = { "panel": aPanel,
|
2009-08-14 10:30:50 -07:00
|
|
|
"elements": (aElements instanceof Array) ? aElements : [aElements] };
|
2009-12-04 12:03:56 -08:00
|
|
|
this._dispatchPopupChanged();
|
2009-08-14 10:30:50 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
popPopup: function popPopup() {
|
|
|
|
this._popup = null;
|
2009-12-04 12:03:56 -08:00
|
|
|
this._dispatchPopupChanged();
|
2009-08-14 10:30:50 -07:00
|
|
|
},
|
|
|
|
|
2009-12-04 12:03:56 -08:00
|
|
|
_dispatchPopupChanged: function _dispatchPopupChanged() {
|
|
|
|
let stack = document.getElementById("stack");
|
|
|
|
let event = document.createEvent("Events");
|
|
|
|
event.initEvent("PopupChanged", true, false);
|
|
|
|
event.popup = this._popup;
|
|
|
|
stack.dispatchEvent(event);
|
|
|
|
},
|
|
|
|
|
|
|
|
_hidePopup: function _hidePopup() {
|
2009-08-14 10:30:50 -07:00
|
|
|
if (!this._popup)
|
|
|
|
return;
|
2009-12-04 12:03:56 -08:00
|
|
|
let panel = this._popup.panel;
|
|
|
|
if (panel.hide)
|
|
|
|
panel.hide();
|
|
|
|
},
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-12-04 12:03:56 -08:00
|
|
|
_isEventInsidePopup: function _isEventInsidePopup(aEvent) {
|
|
|
|
if (!this._popup)
|
2009-12-17 14:35:48 -08:00
|
|
|
return false;
|
2009-12-04 12:03:56 -08:00
|
|
|
let elements = this._popup.elements;
|
2009-10-28 23:12:10 -07:00
|
|
|
let targetNode = aEvent ? aEvent.target : null;
|
2009-12-04 12:03:56 -08:00
|
|
|
while (targetNode && elements.indexOf(targetNode) == -1)
|
2009-08-14 10:30:50 -07:00
|
|
|
targetNode = targetNode.parentNode;
|
2009-12-04 12:03:56 -08:00
|
|
|
return targetNode ? true : false;
|
2009-08-14 10:30:50 -07:00
|
|
|
},
|
|
|
|
|
2009-12-17 14:35:48 -08:00
|
|
|
switchPane : function switchPane(id) {
|
2009-11-03 10:32:44 -08:00
|
|
|
let button = document.getElementsByAttribute("linkedpanel", id)[0];
|
|
|
|
if (button)
|
|
|
|
button.checked = true;
|
2009-12-17 14:35:48 -08:00
|
|
|
|
|
|
|
let pane = document.getElementById(id);
|
|
|
|
document.getElementById("panel-items").selectedPanel = pane;
|
2008-09-28 06:45:47 -07:00
|
|
|
},
|
|
|
|
|
2009-05-28 22:58:30 -07:00
|
|
|
get toolbarH() {
|
|
|
|
if (!this._toolbarH) {
|
|
|
|
let toolbar = document.getElementById("toolbar-main");
|
|
|
|
this._toolbarH = toolbar.boxObject.height;
|
|
|
|
}
|
|
|
|
return this._toolbarH;
|
|
|
|
},
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-08-17 14:05:06 -07:00
|
|
|
get sidebarW() {
|
|
|
|
if (!this._sidebarW) {
|
|
|
|
let sidebar = document.getElementById("browser-controls");
|
|
|
|
this._sidebarW = sidebar.boxObject.width;
|
|
|
|
}
|
|
|
|
return this._sidebarW;
|
|
|
|
},
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-08-17 14:05:06 -07:00
|
|
|
get starButton() {
|
|
|
|
delete this.starButton;
|
|
|
|
return this.starButton = document.getElementById("tool-star");
|
|
|
|
},
|
2009-05-28 22:58:30 -07:00
|
|
|
|
2009-03-31 11:45:24 -07:00
|
|
|
sizeControls : function(windowW, windowH) {
|
2009-10-15 09:54:36 -07:00
|
|
|
// tabs
|
|
|
|
document.getElementById("tabs").resize();
|
|
|
|
|
2009-09-09 20:32:13 -07:00
|
|
|
// awesomebar
|
2009-01-13 14:04:36 -08:00
|
|
|
let popup = document.getElementById("popup_autocomplete");
|
2009-05-28 22:58:30 -07:00
|
|
|
popup.top = this.toolbarH;
|
2009-09-01 20:35:08 -07:00
|
|
|
popup.height = windowH - this.toolbarH;
|
|
|
|
popup.width = windowW;
|
2008-11-21 21:12:25 -08:00
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
// form helper
|
|
|
|
let formHelper = document.getElementById("form-helper-container");
|
|
|
|
formHelper.top = windowH - formHelper.getBoundingClientRect().height;
|
2008-08-19 12:19:47 -07:00
|
|
|
},
|
|
|
|
|
2008-05-02 13:15:45 -07:00
|
|
|
init : function() {
|
2008-07-03 23:39:25 -07:00
|
|
|
this._edit = document.getElementById("urlbar-edit");
|
|
|
|
this._throbber = document.getElementById("urlbar-throbber");
|
|
|
|
this._favicon = document.getElementById("urlbar-favicon");
|
2008-05-02 13:15:45 -07:00
|
|
|
this._favicon.addEventListener("error", this, false);
|
|
|
|
|
2009-07-21 17:05:01 -07:00
|
|
|
let urlbarEditArea = document.getElementById("urlbar-editarea");
|
|
|
|
urlbarEditArea.addEventListener("click", this, false);
|
|
|
|
urlbarEditArea.addEventListener("mousedown", this, false);
|
2009-07-14 07:16:23 -07:00
|
|
|
|
2009-08-17 23:07:48 -07:00
|
|
|
document.getElementById("toolbar-main").ignoreDrag = true;
|
|
|
|
|
2009-08-25 21:49:26 -07:00
|
|
|
let tabs = document.getElementById("tabs");
|
|
|
|
tabs.addEventListener("TabSelect", this, true);
|
|
|
|
tabs.addEventListener("TabOpen", this, true);
|
2009-07-14 07:16:23 -07:00
|
|
|
|
2008-11-21 21:12:25 -08:00
|
|
|
let browsers = document.getElementById("browsers");
|
2009-07-16 08:45:50 -07:00
|
|
|
browsers.addEventListener("DOMWindowClose", this, true);
|
|
|
|
|
2009-07-23 09:01:46 -07:00
|
|
|
// XXX these really want to listen to only the current browser
|
2008-11-21 21:12:25 -08:00
|
|
|
browsers.addEventListener("DOMTitleChanged", this, true);
|
|
|
|
browsers.addEventListener("DOMLinkAdded", this, true);
|
2009-09-30 12:14:06 -07:00
|
|
|
browsers.addEventListener("DOMWillOpenModalDialog", this, true);
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-08-14 10:30:50 -07:00
|
|
|
// listening mousedown for automatically dismiss some popups (e.g. larry)
|
|
|
|
window.addEventListener("mousedown", this, true);
|
2009-07-16 08:45:50 -07:00
|
|
|
|
2009-08-24 08:00:28 -07:00
|
|
|
// listening escape to dismiss dialog on VK_ESCAPE
|
|
|
|
window.addEventListener("keypress", this, true);
|
|
|
|
|
2009-12-17 14:35:48 -08:00
|
|
|
// Push the panel initialization out of the startup path
|
2010-03-20 14:33:35 -07:00
|
|
|
// (Using an event because we have no good way to delay-init [Bug 535366])
|
|
|
|
browsers.addEventListener("load", function() {
|
|
|
|
// We only want to delay one time
|
|
|
|
browsers.removeEventListener("load", arguments.callee, false);
|
|
|
|
|
2009-12-17 14:35:48 -08:00
|
|
|
// We unhide the panelUI so the XBL and settings can initialize
|
|
|
|
Elements.panelUI.hidden = false;
|
2010-03-20 14:33:35 -07:00
|
|
|
|
|
|
|
// Init the views
|
2009-12-17 14:35:48 -08:00
|
|
|
ExtensionsView.init();
|
|
|
|
DownloadsView.init();
|
|
|
|
PreferencesView.init();
|
|
|
|
ConsoleView.init();
|
2010-03-20 14:33:35 -07:00
|
|
|
}, false);
|
2008-05-02 13:15:45 -07:00
|
|
|
},
|
|
|
|
|
2009-05-26 18:46:44 -07:00
|
|
|
uninit : function() {
|
|
|
|
ExtensionsView.uninit();
|
2009-10-14 12:04:33 -07:00
|
|
|
ConsoleView.uninit();
|
2009-05-26 18:46:44 -07:00
|
|
|
},
|
|
|
|
|
2008-11-21 21:12:25 -08:00
|
|
|
update : function(aState) {
|
2009-06-18 22:14:04 -07:00
|
|
|
let icons = document.getElementById("urlbar-icons");
|
2009-10-09 05:34:02 -07:00
|
|
|
let browser = Browser.selectedBrowser;
|
2009-09-08 11:14:59 -07:00
|
|
|
|
2008-11-21 21:12:25 -08:00
|
|
|
switch (aState) {
|
|
|
|
case TOOLBARSTATE_LOADED:
|
2009-09-21 09:32:50 -07:00
|
|
|
if (icons.getAttribute("mode") != "edit")
|
2009-09-18 21:17:52 -07:00
|
|
|
icons.setAttribute("mode", "view");
|
2009-10-09 05:34:02 -07:00
|
|
|
|
|
|
|
this._updateIcon(browser.mIconURL);
|
2008-11-21 21:12:25 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TOOLBARSTATE_LOADING:
|
2009-09-21 09:32:50 -07:00
|
|
|
if (icons.getAttribute("mode") != "edit")
|
2009-09-18 21:17:52 -07:00
|
|
|
icons.setAttribute("mode", "loading");
|
2009-06-18 22:14:04 -07:00
|
|
|
|
2009-10-09 05:34:02 -07:00
|
|
|
browser.mIconURL = "";
|
|
|
|
this._updateIcon();
|
2008-11-21 21:12:25 -08:00
|
|
|
break;
|
2008-10-22 08:39:00 -07:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2009-10-09 05:34:02 -07:00
|
|
|
_updateIcon : function(aIconSrc) {
|
|
|
|
this._favicon.src = aIconSrc || "";
|
2009-01-08 22:51:13 -08:00
|
|
|
if (Browser.selectedTab.isLoading()) {
|
2008-11-21 21:12:25 -08:00
|
|
|
this._throbber.hidden = false;
|
2008-10-22 08:39:00 -07:00
|
|
|
this._throbber.setAttribute("loading", "true");
|
2008-11-21 21:12:25 -08:00
|
|
|
this._favicon.hidden = true;
|
2008-10-22 08:39:00 -07:00
|
|
|
}
|
|
|
|
else {
|
2008-11-21 21:12:25 -08:00
|
|
|
this._favicon.hidden = false;
|
|
|
|
this._throbber.hidden = true;
|
2008-10-22 08:39:00 -07:00
|
|
|
this._throbber.removeAttribute("loading");
|
2008-05-02 13:15:45 -07:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2008-09-27 07:07:04 -07:00
|
|
|
getDisplayURI : function(browser) {
|
|
|
|
var uri = browser.currentURI;
|
|
|
|
|
|
|
|
if (!this._URIFixup)
|
|
|
|
this._URIFixup = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup);
|
|
|
|
|
|
|
|
try {
|
|
|
|
uri = this._URIFixup.createExposableURI(uri);
|
|
|
|
} catch (ex) {}
|
|
|
|
|
|
|
|
return uri.spec;
|
|
|
|
},
|
|
|
|
|
2008-05-02 13:15:45 -07:00
|
|
|
/* Set the location to the current content */
|
2009-09-18 21:17:52 -07:00
|
|
|
updateURI : function() {
|
2009-01-08 22:51:13 -08:00
|
|
|
var browser = Browser.selectedBrowser;
|
2008-09-06 21:06:04 -07:00
|
|
|
|
2008-11-21 21:12:25 -08:00
|
|
|
// FIXME: deckbrowser should not fire TabSelect on the initial tab (bug 454028)
|
2008-09-06 21:06:04 -07:00
|
|
|
if (!browser.currentURI)
|
|
|
|
return;
|
|
|
|
|
2009-06-24 15:43:26 -07:00
|
|
|
// Update the navigation buttons
|
|
|
|
this._updateButtons(browser);
|
2008-05-02 13:15:45 -07:00
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
// Close the forms assistant
|
|
|
|
FormHelper.close();
|
|
|
|
|
2008-05-02 13:15:45 -07:00
|
|
|
// Check for a bookmarked page
|
2008-12-15 08:44:27 -08:00
|
|
|
this.updateStar();
|
2008-07-03 23:39:25 -07:00
|
|
|
|
2008-09-27 07:07:04 -07:00
|
|
|
var urlString = this.getDisplayURI(browser);
|
2009-04-22 13:45:51 -07:00
|
|
|
if (urlString == "about:blank")
|
2008-07-03 23:39:25 -07:00
|
|
|
urlString = "";
|
2008-05-02 13:15:45 -07:00
|
|
|
|
2009-09-18 21:17:52 -07:00
|
|
|
this._setURI(urlString);
|
2008-05-02 13:15:45 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
goToURI : function(aURI) {
|
2009-09-13 21:49:09 -07:00
|
|
|
aURI = aURI || this._edit.value;
|
2008-05-02 13:15:45 -07:00
|
|
|
if (!aURI)
|
2009-09-13 21:49:09 -07:00
|
|
|
return;
|
|
|
|
|
2009-11-24 10:23:41 -08:00
|
|
|
// Make sure we're online before attempting to load
|
|
|
|
Util.forceOnline();
|
|
|
|
|
2009-10-28 20:55:47 -07:00
|
|
|
// Give the new page lots of room
|
|
|
|
Browser.hideSidebars();
|
2009-11-30 22:04:55 -08:00
|
|
|
this.closeAutoComplete(true);
|
2009-10-28 20:55:47 -07:00
|
|
|
|
2009-10-08 22:49:43 -07:00
|
|
|
this._edit.value = aURI;
|
2008-05-06 07:56:21 -07:00
|
|
|
|
2008-07-15 08:21:39 -07:00
|
|
|
var flags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
|
|
|
|
getBrowser().loadURIWithFlags(aURI, flags, null, null);
|
2009-03-05 15:30:28 -08:00
|
|
|
|
|
|
|
gHistSvc.markPageAsTyped(gURIFixup.createFixupURI(aURI, 0));
|
2008-05-02 13:15:45 -07:00
|
|
|
},
|
|
|
|
|
2009-12-03 06:04:57 -08:00
|
|
|
showAutoComplete : function showAutoComplete() {
|
2009-09-18 21:17:52 -07:00
|
|
|
if (this.isAutoCompleteOpen())
|
|
|
|
return;
|
2009-12-03 06:04:57 -08:00
|
|
|
|
2009-08-26 12:29:46 -07:00
|
|
|
BrowserSearch.updateSearchButtons();
|
2009-12-03 06:04:57 -08:00
|
|
|
|
2008-12-09 10:38:31 -08:00
|
|
|
this._edit.showHistoryPopup();
|
2008-07-16 08:41:38 -07:00
|
|
|
},
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-11-30 22:04:55 -08:00
|
|
|
closeAutoComplete: function closeAutoComplete(aResetInput) {
|
2010-02-16 18:21:13 -08:00
|
|
|
if (!this.isAutoCompleteOpen())
|
|
|
|
return;
|
|
|
|
|
2009-11-30 22:04:55 -08:00
|
|
|
if (aResetInput)
|
|
|
|
this._edit.popup.close();
|
|
|
|
else
|
|
|
|
this._edit.popup.closePopup();
|
|
|
|
},
|
2008-07-16 08:41:38 -07:00
|
|
|
|
2009-09-18 21:17:52 -07:00
|
|
|
isAutoCompleteOpen: function isAutoCompleteOpen() {
|
|
|
|
return this._edit.popup.popupOpen;
|
|
|
|
},
|
|
|
|
|
2008-11-21 21:12:25 -08:00
|
|
|
doButtonSearch : function(button) {
|
2008-07-16 08:41:38 -07:00
|
|
|
if (!("engine" in button) || !button.engine)
|
|
|
|
return;
|
|
|
|
|
2009-09-18 21:17:52 -07:00
|
|
|
// We don't want the button to look pressed for now
|
|
|
|
button.parentNode.selectedItem = null;
|
2009-10-28 20:55:47 -07:00
|
|
|
|
|
|
|
// Give the new page lots of room
|
|
|
|
Browser.hideSidebars();
|
2009-11-30 22:04:55 -08:00
|
|
|
this.closeAutoComplete(false);
|
2008-07-16 08:41:38 -07:00
|
|
|
|
2009-11-24 10:23:41 -08:00
|
|
|
// Make sure we're online before attempting to load
|
|
|
|
Util.forceOnline();
|
|
|
|
|
2010-03-10 11:19:05 -08:00
|
|
|
let submission = button.engine.getSubmission(this._edit.value, null);
|
|
|
|
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
|
|
|
getBrowser().loadURIWithFlags(submission.uri.spec, flags, null, null, submission.postData);
|
2008-07-16 08:41:38 -07:00
|
|
|
},
|
|
|
|
|
2008-12-15 08:44:27 -08:00
|
|
|
updateStar : function() {
|
2009-01-08 22:51:13 -08:00
|
|
|
if (PlacesUtils.getMostRecentBookmarkForURI(Browser.selectedBrowser.currentURI) != -1)
|
2009-08-17 14:05:06 -07:00
|
|
|
this.starButton.setAttribute("starred", "true");
|
2008-12-15 08:44:27 -08:00
|
|
|
else
|
2009-08-17 14:05:06 -07:00
|
|
|
this.starButton.removeAttribute("starred");
|
2008-12-15 08:44:27 -08:00
|
|
|
},
|
|
|
|
|
2009-06-30 11:43:45 -07:00
|
|
|
newTab : function newTab(aURI) {
|
2009-08-26 10:24:27 -07:00
|
|
|
aURI = aURI || "about:blank";
|
|
|
|
let tab = Browser.addTab(aURI, true);
|
|
|
|
|
2009-09-22 15:05:20 -07:00
|
|
|
this.hidePanel();
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-09-18 21:17:52 -07:00
|
|
|
if (aURI == "about:blank") {
|
2009-11-30 22:04:55 -08:00
|
|
|
// Display awesomebar UI
|
2009-09-18 21:17:52 -07:00
|
|
|
this.showToolbar(true);
|
2009-08-26 10:24:27 -07:00
|
|
|
this.showAutoComplete();
|
2009-09-18 21:17:52 -07:00
|
|
|
}
|
2009-10-28 20:55:47 -07:00
|
|
|
else {
|
|
|
|
// Give the new page lots of room
|
|
|
|
Browser.hideSidebars();
|
2009-11-30 22:04:55 -08:00
|
|
|
this.closeAutoComplete(true);
|
2009-10-28 20:55:47 -07:00
|
|
|
}
|
|
|
|
|
2009-08-25 20:45:11 -07:00
|
|
|
return tab;
|
2008-05-02 13:15:45 -07:00
|
|
|
},
|
|
|
|
|
2009-04-17 07:41:44 -07:00
|
|
|
closeTab : function closeTab(aTab) {
|
2009-06-15 05:44:30 -07:00
|
|
|
// If no tab is passed in, assume the current tab
|
|
|
|
Browser.closeTab(aTab || Browser.selectedTab);
|
2008-09-28 23:43:33 -07:00
|
|
|
},
|
|
|
|
|
2009-04-17 07:41:44 -07:00
|
|
|
selectTab : function selectTab(aTab) {
|
2009-01-08 22:51:13 -08:00
|
|
|
Browser.selectedTab = aTab;
|
2009-02-10 13:52:23 -08:00
|
|
|
},
|
|
|
|
|
2009-04-17 07:41:44 -07:00
|
|
|
hideTabs: function hideTabs() {
|
2009-07-17 16:17:57 -07:00
|
|
|
/*
|
2009-04-17 07:41:44 -07:00
|
|
|
if (ws.isWidgetVisible("tabs-container")) {
|
|
|
|
let widthOfTabs = document.getElementById("tabs-container").boxObject.width;
|
|
|
|
ws.panBy(widthOfTabs, 0, true);
|
|
|
|
}
|
2009-07-17 16:17:57 -07:00
|
|
|
*/
|
2009-04-17 07:41:44 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
hideControls: function hideControls() {
|
2009-07-17 16:17:57 -07:00
|
|
|
/*
|
2009-04-17 07:41:44 -07:00
|
|
|
if (ws.isWidgetVisible("browser-controls")) {
|
|
|
|
let widthOfControls = document.getElementById("browser-controls").boxObject.width;
|
|
|
|
ws.panBy(-widthOfControls, 0, true);
|
|
|
|
}
|
2009-07-17 16:17:57 -07:00
|
|
|
*/
|
2009-04-17 07:41:44 -07:00
|
|
|
},
|
|
|
|
|
2009-08-25 21:49:26 -07:00
|
|
|
isTabsVisible: function isTabsVisible() {
|
2009-08-28 12:08:39 -07:00
|
|
|
// The _1, _2 and _3 are to make the js2 emacs mode happy
|
|
|
|
let [leftvis,_1,_2,_3] = Browser.computeSidebarVisibility();
|
2009-08-25 21:49:26 -07:00
|
|
|
return (leftvis > 0.002);
|
|
|
|
},
|
|
|
|
|
2009-04-17 07:41:44 -07:00
|
|
|
showPanel: function showPanel(aPage) {
|
2009-12-17 14:35:48 -08:00
|
|
|
Elements.panelUI.left = 0;
|
|
|
|
Elements.panelUI.hidden = false;
|
2009-11-23 09:23:59 -08:00
|
|
|
Elements.contentShowing.setAttribute("disabled", "true");
|
|
|
|
|
2009-04-17 07:41:44 -07:00
|
|
|
if (aPage != undefined)
|
|
|
|
this.switchPane(aPage);
|
|
|
|
},
|
|
|
|
|
|
|
|
hidePanel: function hidePanel() {
|
2009-12-17 14:35:48 -08:00
|
|
|
Elements.panelUI.hidden = true;
|
2009-11-23 09:23:59 -08:00
|
|
|
Elements.contentShowing.removeAttribute("disabled");
|
2008-05-02 13:15:45 -07:00
|
|
|
},
|
2009-12-17 14:35:48 -08:00
|
|
|
|
|
|
|
isPanelVisible: function isPanelVisible() {
|
|
|
|
return (!Elements.panelUI.hidden && Elements.panelUI.left == 0);
|
|
|
|
},
|
|
|
|
|
2009-09-23 09:09:44 -07:00
|
|
|
switchTask: function switchTask() {
|
|
|
|
try {
|
|
|
|
let phone = Cc["@mozilla.org/phone/support;1"].createInstance(Ci.nsIPhoneSupport);
|
|
|
|
phone.switchTask();
|
|
|
|
} catch(e) { }
|
|
|
|
},
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-11-18 13:09:01 -08:00
|
|
|
#ifdef WINCE
|
|
|
|
updateDefaultBrowser: function updateDefaultBrowser(aSet) {
|
|
|
|
try {
|
|
|
|
let phone = Cc["@mozilla.org/phone/support;1"].getService(Ci.nsIPhoneSupport);
|
|
|
|
if (aSet)
|
|
|
|
phone.setDefaultBrowser();
|
|
|
|
else
|
|
|
|
phone.restoreDefaultBrowser();
|
|
|
|
} catch(e) { }
|
|
|
|
},
|
|
|
|
#endif
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2008-05-02 13:15:45 -07:00
|
|
|
handleEvent: function (aEvent) {
|
|
|
|
switch (aEvent.type) {
|
2008-07-03 23:39:25 -07:00
|
|
|
// Browser events
|
2009-09-30 12:14:06 -07:00
|
|
|
case "DOMWillOpenModalDialog":
|
|
|
|
this._domWillOpenModalDialog(aEvent);
|
|
|
|
break;
|
2008-05-02 13:15:45 -07:00
|
|
|
case "DOMTitleChanged":
|
2008-08-19 23:09:22 -07:00
|
|
|
this._titleChanged(aEvent.target);
|
2008-05-02 13:15:45 -07:00
|
|
|
break;
|
|
|
|
case "DOMLinkAdded":
|
|
|
|
this._linkAdded(aEvent);
|
2009-07-16 08:45:50 -07:00
|
|
|
break;
|
|
|
|
case "DOMWindowClose":
|
|
|
|
this._domWindowClose(aEvent);
|
2008-05-02 13:15:45 -07:00
|
|
|
break;
|
2008-08-19 23:09:22 -07:00
|
|
|
case "TabSelect":
|
|
|
|
this._tabSelect(aEvent);
|
|
|
|
break;
|
2009-08-25 21:49:26 -07:00
|
|
|
case "TabOpen":
|
2009-12-01 20:20:58 -08:00
|
|
|
{
|
|
|
|
if (!this.isTabsVisible() && Browser.selectedTab.chromeTab != aEvent.target)
|
2009-08-25 21:49:26 -07:00
|
|
|
NewTabPopup.show(aEvent.target);
|
2009-12-01 20:20:58 -08:00
|
|
|
|
|
|
|
// Workaround to hide the tabstrip if it is partially visible
|
|
|
|
// See bug 524469
|
|
|
|
let [tabstripV,,,] = Browser.computeSidebarVisibility();
|
|
|
|
if (tabstripV > 0 && tabstripV < 1)
|
|
|
|
Browser.hideSidebars();
|
|
|
|
|
2009-08-25 21:49:26 -07:00
|
|
|
break;
|
2009-12-01 20:20:58 -08:00
|
|
|
}
|
2008-07-03 23:39:25 -07:00
|
|
|
// URL textbox events
|
2008-05-02 13:15:45 -07:00
|
|
|
case "click":
|
2008-11-12 18:40:57 -08:00
|
|
|
this.doCommand("cmd_openLocation");
|
2008-05-02 13:15:45 -07:00
|
|
|
break;
|
|
|
|
case "keypress":
|
2008-07-16 08:41:38 -07:00
|
|
|
if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
|
2009-09-18 21:17:52 -07:00
|
|
|
let dialog = this.activeDialog;
|
2009-08-24 08:00:28 -07:00
|
|
|
if (dialog)
|
|
|
|
dialog.close();
|
2008-07-16 08:41:38 -07:00
|
|
|
}
|
2008-05-02 13:15:45 -07:00
|
|
|
break;
|
2009-07-21 17:05:01 -07:00
|
|
|
case "mousedown":
|
2009-12-04 12:03:56 -08:00
|
|
|
if (!this._isEventInsidePopup(aEvent))
|
|
|
|
this._hidePopup();
|
2009-08-14 10:30:50 -07:00
|
|
|
|
2009-07-21 17:05:01 -07:00
|
|
|
if (aEvent.detail == 2 &&
|
|
|
|
aEvent.button == 0 &&
|
|
|
|
gPrefService.getBoolPref("browser.urlbar.doubleClickSelectsAll")) {
|
|
|
|
this._edit.editor.selectAll();
|
|
|
|
aEvent.preventDefault();
|
|
|
|
}
|
|
|
|
break;
|
2008-07-03 23:39:25 -07:00
|
|
|
// Favicon events
|
2008-05-02 13:15:45 -07:00
|
|
|
case "error":
|
2009-10-09 05:34:02 -07:00
|
|
|
this._favicon.src = "";
|
2008-05-02 13:15:45 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
supportsCommand : function(cmd) {
|
|
|
|
var isSupported = false;
|
|
|
|
switch (cmd) {
|
|
|
|
case "cmd_back":
|
|
|
|
case "cmd_forward":
|
|
|
|
case "cmd_reload":
|
2010-02-16 15:38:37 -08:00
|
|
|
case "cmd_forceReload":
|
2008-05-02 13:15:45 -07:00
|
|
|
case "cmd_stop":
|
|
|
|
case "cmd_go":
|
2008-11-12 18:40:57 -08:00
|
|
|
case "cmd_openLocation":
|
2008-05-02 13:15:45 -07:00
|
|
|
case "cmd_star":
|
|
|
|
case "cmd_bookmarks":
|
2009-03-19 16:20:32 -07:00
|
|
|
case "cmd_quit":
|
|
|
|
case "cmd_close":
|
2008-07-25 11:10:35 -07:00
|
|
|
case "cmd_menu":
|
|
|
|
case "cmd_newTab":
|
|
|
|
case "cmd_closeTab":
|
2008-08-19 19:18:36 -07:00
|
|
|
case "cmd_actions":
|
2008-09-10 17:38:02 -07:00
|
|
|
case "cmd_panel":
|
2008-09-06 23:54:06 -07:00
|
|
|
case "cmd_sanitize":
|
2008-10-09 21:11:27 -07:00
|
|
|
case "cmd_zoomin":
|
|
|
|
case "cmd_zoomout":
|
2008-05-02 13:15:45 -07:00
|
|
|
isSupported = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
isSupported = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return isSupported;
|
|
|
|
},
|
|
|
|
|
|
|
|
isCommandEnabled : function(cmd) {
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
doCommand : function(cmd) {
|
|
|
|
var browser = getBrowser();
|
|
|
|
switch (cmd) {
|
|
|
|
case "cmd_back":
|
|
|
|
browser.goBack();
|
|
|
|
break;
|
|
|
|
case "cmd_forward":
|
|
|
|
browser.goForward();
|
|
|
|
break;
|
|
|
|
case "cmd_reload":
|
|
|
|
browser.reload();
|
|
|
|
break;
|
2010-02-16 15:38:37 -08:00
|
|
|
case "cmd_forceReload":
|
|
|
|
{
|
|
|
|
const reloadFlags = Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY |
|
|
|
|
Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
|
|
|
|
browser.reloadWithFlags(reloadFlags);
|
|
|
|
break;
|
|
|
|
}
|
2008-05-02 13:15:45 -07:00
|
|
|
case "cmd_stop":
|
|
|
|
browser.stop();
|
|
|
|
break;
|
|
|
|
case "cmd_go":
|
|
|
|
this.goToURI();
|
|
|
|
break;
|
2008-11-12 18:40:57 -08:00
|
|
|
case "cmd_openLocation":
|
2009-08-24 08:00:28 -07:00
|
|
|
this.showToolbar(true);
|
2009-09-18 21:17:52 -07:00
|
|
|
this.showAutoComplete();
|
2008-11-12 18:40:57 -08:00
|
|
|
break;
|
2008-05-02 13:15:45 -07:00
|
|
|
case "cmd_star":
|
|
|
|
{
|
|
|
|
var bookmarkURI = browser.currentURI;
|
2009-03-03 06:31:51 -08:00
|
|
|
var bookmarkTitle = browser.contentDocument.title || bookmarkURI.spec;
|
2008-05-02 13:15:45 -07:00
|
|
|
|
2009-08-17 14:05:06 -07:00
|
|
|
let autoClose = false;
|
|
|
|
|
2008-10-01 12:54:16 -07:00
|
|
|
if (PlacesUtils.getMostRecentBookmarkForURI(bookmarkURI) == -1) {
|
2009-11-19 11:40:54 -08:00
|
|
|
let bmsvc = PlacesUtils.bookmarks;
|
|
|
|
let bookmarkId = bmsvc.insertBookmark(BookmarkList.mobileRoot, bookmarkURI,
|
|
|
|
bmsvc.DEFAULT_INDEX,
|
|
|
|
bookmarkTitle);
|
2009-07-05 09:22:09 -07:00
|
|
|
this.updateStar();
|
2008-05-02 13:15:45 -07:00
|
|
|
|
2009-08-17 14:05:06 -07:00
|
|
|
// autoclose the bookmark popup
|
|
|
|
autoClose = true;
|
2008-05-02 13:15:45 -07:00
|
|
|
}
|
2009-08-17 14:05:06 -07:00
|
|
|
|
|
|
|
// Show/hide bookmark popup
|
|
|
|
BookmarkPopup.toggle(autoClose);
|
2008-05-02 13:15:45 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case "cmd_bookmarks":
|
2009-10-14 15:43:20 -07:00
|
|
|
BookmarkList.show();
|
2008-05-02 13:15:45 -07:00
|
|
|
break;
|
2009-03-19 16:20:32 -07:00
|
|
|
case "cmd_quit":
|
|
|
|
goQuitApplication();
|
|
|
|
break;
|
|
|
|
case "cmd_close":
|
2009-07-08 07:55:07 -07:00
|
|
|
this._closeOrQuit();
|
2009-03-19 16:20:32 -07:00
|
|
|
break;
|
2008-07-25 11:10:35 -07:00
|
|
|
case "cmd_menu":
|
|
|
|
break;
|
|
|
|
case "cmd_newTab":
|
|
|
|
this.newTab();
|
|
|
|
break;
|
|
|
|
case "cmd_closeTab":
|
2008-11-21 21:12:25 -08:00
|
|
|
this.closeTab();
|
2008-08-19 19:18:36 -07:00
|
|
|
break;
|
2008-09-06 23:54:06 -07:00
|
|
|
case "cmd_sanitize":
|
2009-05-20 10:31:53 -07:00
|
|
|
{
|
|
|
|
// disable the button temporarily to indicate something happened
|
|
|
|
let button = document.getElementById("prefs-clear-data");
|
|
|
|
button.disabled = true;
|
|
|
|
setTimeout(function() { button.disabled = false; }, 5000);
|
|
|
|
|
2008-09-06 23:54:06 -07:00
|
|
|
Sanitizer.sanitize();
|
2008-08-19 19:18:36 -07:00
|
|
|
break;
|
2009-05-20 10:31:53 -07:00
|
|
|
}
|
2008-09-10 17:38:02 -07:00
|
|
|
case "cmd_panel":
|
|
|
|
{
|
2009-12-17 14:35:48 -08:00
|
|
|
if (BrowserUI.isPanelVisible())
|
2009-04-17 07:41:44 -07:00
|
|
|
this.hidePanel();
|
2009-12-17 14:35:48 -08:00
|
|
|
else
|
|
|
|
this.showPanel();
|
2008-09-10 12:30:52 -07:00
|
|
|
break;
|
2008-09-10 17:38:02 -07:00
|
|
|
}
|
2008-10-09 21:11:27 -07:00
|
|
|
case "cmd_zoomin":
|
2009-11-24 11:44:05 -08:00
|
|
|
Browser.zoom(-1);
|
2008-10-09 21:11:27 -07:00
|
|
|
break;
|
|
|
|
case "cmd_zoomout":
|
2009-11-24 11:44:05 -08:00
|
|
|
Browser.zoom(1);
|
2008-10-09 21:11:27 -07:00
|
|
|
break;
|
2008-05-02 13:15:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-08-25 21:49:26 -07:00
|
|
|
var NewTabPopup = {
|
|
|
|
_timeout: 0,
|
|
|
|
_tabs: [],
|
|
|
|
|
|
|
|
get box() {
|
|
|
|
delete this.box;
|
|
|
|
return this.box = document.getElementById("newtab-popup");
|
|
|
|
},
|
|
|
|
|
|
|
|
_updateLabel: function() {
|
2009-11-19 13:40:13 -08:00
|
|
|
let newtabStrings = Elements.browserBundle.getString("newtabpopup.opened");
|
2009-08-25 21:49:26 -07:00
|
|
|
let label = PluralForm.get(this._tabs.length, newtabStrings).replace("#1", this._tabs.length);
|
|
|
|
|
|
|
|
this.box.firstChild.setAttribute("value", label);
|
|
|
|
},
|
|
|
|
|
|
|
|
hide: function() {
|
|
|
|
if (this._timeout) {
|
|
|
|
clearTimeout(this._timeout);
|
|
|
|
this._timeout = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._tabs = [];
|
|
|
|
this.box.hidden = true;
|
2009-10-12 11:35:01 -07:00
|
|
|
BrowserUI.popPopup();
|
2009-08-25 21:49:26 -07:00
|
|
|
},
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-08-25 21:49:26 -07:00
|
|
|
show: function(aTab) {
|
2009-12-01 20:20:58 -08:00
|
|
|
BrowserUI.pushPopup(this, this.box);
|
|
|
|
|
2009-08-25 21:49:26 -07:00
|
|
|
this._tabs.push(aTab);
|
|
|
|
this._updateLabel();
|
|
|
|
|
|
|
|
this.box.top = aTab.getBoundingClientRect().top + (aTab.getBoundingClientRect().height / 3);
|
|
|
|
this.box.hidden = false;
|
|
|
|
|
|
|
|
if (this._timeout)
|
|
|
|
clearTimeout(this._timeout);
|
|
|
|
|
|
|
|
this._timeout = setTimeout(function(self) {
|
|
|
|
self.hide();
|
|
|
|
}, 2000, this);
|
|
|
|
},
|
|
|
|
|
|
|
|
selectTab: function() {
|
|
|
|
BrowserUI.selectTab(this._tabs.pop());
|
|
|
|
this.hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-17 14:05:06 -07:00
|
|
|
var BookmarkPopup = {
|
|
|
|
get box() {
|
|
|
|
delete this.box;
|
|
|
|
return this.box = document.getElementById("bookmark-popup");
|
|
|
|
},
|
|
|
|
|
|
|
|
_bookmarkPopupTimeout: -1,
|
|
|
|
|
2009-12-01 09:27:17 -08:00
|
|
|
hide : function hide() {
|
2009-08-17 14:05:06 -07:00
|
|
|
if (this._bookmarkPopupTimeout != -1) {
|
|
|
|
clearTimeout(this._bookmarkPopupTimeout);
|
|
|
|
this._bookmarkPopupTimeout = -1;
|
|
|
|
}
|
|
|
|
this.box.hidden = true;
|
2009-10-12 11:35:01 -07:00
|
|
|
BrowserUI.popPopup();
|
2009-08-17 14:05:06 -07:00
|
|
|
},
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-12-01 09:27:17 -08:00
|
|
|
show : function show(aAutoClose) {
|
|
|
|
const margin = 10;
|
|
|
|
|
2009-08-17 14:05:06 -07:00
|
|
|
this.box.hidden = false;
|
|
|
|
|
2009-12-01 09:27:17 -08:00
|
|
|
let [,,,controlsW] = Browser.computeSidebarVisibility();
|
|
|
|
this.box.left = window.innerWidth - (this.box.getBoundingClientRect().width + controlsW + margin);
|
|
|
|
this.box.top = BrowserUI.starButton.getBoundingClientRect().top + margin;
|
|
|
|
|
2009-08-17 14:05:06 -07:00
|
|
|
if (aAutoClose) {
|
|
|
|
this._bookmarkPopupTimeout = setTimeout(function (self) {
|
|
|
|
self._bookmarkPopupTimeout = -1;
|
|
|
|
self.hide();
|
|
|
|
}, 2000, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
// include starButton here, so that click-to-dismiss works as expected
|
|
|
|
BrowserUI.pushPopup(this, [this.box, BrowserUI.starButton]);
|
|
|
|
},
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-12-01 09:27:17 -08:00
|
|
|
toggle : function toggle(aAutoClose) {
|
2009-08-17 14:05:06 -07:00
|
|
|
if (this.box.hidden)
|
|
|
|
this.show(aAutoClose);
|
|
|
|
else
|
|
|
|
this.hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-02 13:15:45 -07:00
|
|
|
var BookmarkHelper = {
|
2009-02-24 22:20:45 -08:00
|
|
|
_panel: null,
|
|
|
|
_editor: null,
|
|
|
|
|
2009-07-08 07:55:07 -07:00
|
|
|
edit: function BH_edit(aURI) {
|
2009-08-17 14:05:06 -07:00
|
|
|
if (!aURI)
|
|
|
|
aURI = getBrowser().currentURI;
|
|
|
|
|
2009-02-24 22:20:45 -08:00
|
|
|
let itemId = PlacesUtils.getMostRecentBookmarkForURI(aURI);
|
|
|
|
if (itemId == -1)
|
|
|
|
return;
|
|
|
|
|
2009-04-08 22:40:05 -07:00
|
|
|
let title = PlacesUtils.bookmarks.getItemTitle(itemId);
|
2009-04-21 13:55:05 -07:00
|
|
|
let tags = PlacesUtils.tagging.getTagsForURI(aURI, {});
|
|
|
|
|
2009-11-23 08:44:34 -08:00
|
|
|
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
|
|
|
this._editor = document.createElementNS(XULNS, "placeitem");
|
2009-04-21 13:55:05 -07:00
|
|
|
this._editor.setAttribute("id", "bookmark-item");
|
|
|
|
this._editor.setAttribute("flex", "1");
|
|
|
|
this._editor.setAttribute("type", "bookmark");
|
|
|
|
this._editor.setAttribute("ui", "manage");
|
|
|
|
this._editor.setAttribute("title", title);
|
|
|
|
this._editor.setAttribute("uri", aURI.spec);
|
2009-11-23 08:44:34 -08:00
|
|
|
this._editor.setAttribute("itemid", itemId);
|
2009-07-07 06:45:01 -07:00
|
|
|
this._editor.setAttribute("tags", tags.join(", "));
|
2009-10-28 23:12:10 -07:00
|
|
|
this._editor.setAttribute("onclose", "BookmarkHelper.hide()");
|
2009-04-21 13:55:05 -07:00
|
|
|
document.getElementById("bookmark-form").appendChild(this._editor);
|
2009-04-08 22:40:05 -07:00
|
|
|
|
2009-05-06 22:51:47 -07:00
|
|
|
let toolbar = document.getElementById("toolbar-main");
|
|
|
|
let top = toolbar.top + toolbar.boxObject.height;
|
|
|
|
|
2009-02-24 22:20:45 -08:00
|
|
|
this._panel = document.getElementById("bookmark-container");
|
2009-05-06 22:51:47 -07:00
|
|
|
this._panel.top = (top < 0 ? 0 : top);
|
2009-04-21 13:55:05 -07:00
|
|
|
this._panel.hidden = false;
|
2009-10-28 23:12:10 -07:00
|
|
|
BrowserUI.pushPopup(this, this._panel);
|
2009-02-24 22:20:45 -08:00
|
|
|
|
2009-04-21 13:55:05 -07:00
|
|
|
let self = this;
|
2009-12-04 12:03:56 -08:00
|
|
|
Browser.forceChromeReflow();
|
|
|
|
self._editor.startEditing();
|
2008-05-02 13:15:45 -07:00
|
|
|
},
|
|
|
|
|
2009-10-25 21:21:49 -07:00
|
|
|
save: function BH_save() {
|
|
|
|
this._editor.stopEditing(true);
|
|
|
|
},
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-10-28 23:12:10 -07:00
|
|
|
hide: function BH_hide() {
|
2008-12-15 08:44:27 -08:00
|
|
|
BrowserUI.updateStar();
|
2009-02-24 22:20:45 -08:00
|
|
|
|
2009-07-08 07:55:07 -07:00
|
|
|
// Note: the _editor will have already saved the data, if needed, by the time
|
|
|
|
// this method is called, since this method is called via the "close" event.
|
2009-04-21 13:55:05 -07:00
|
|
|
this._editor.parentNode.removeChild(this._editor);
|
2009-07-08 07:55:07 -07:00
|
|
|
this._editor = null;
|
|
|
|
|
|
|
|
this._panel.hidden = true;
|
2009-10-28 23:12:10 -07:00
|
|
|
BrowserUI.popPopup();
|
2008-07-14 14:11:15 -07:00
|
|
|
},
|
2008-05-02 13:15:45 -07:00
|
|
|
};
|
2009-02-24 22:20:45 -08:00
|
|
|
|
|
|
|
var BookmarkList = {
|
|
|
|
_panel: null,
|
|
|
|
_bookmarks: null,
|
2009-10-20 20:32:36 -07:00
|
|
|
_manageButtton: null,
|
2009-02-24 22:20:45 -08:00
|
|
|
|
2009-11-19 11:40:54 -08:00
|
|
|
get mobileRoot() {
|
|
|
|
let items = PlacesUtils.annotations.getItemsWithAnnotation("mobile/bookmarksRoot", {});
|
|
|
|
if (!items.length)
|
|
|
|
throw "Couldn't find mobile bookmarks root!";
|
|
|
|
|
|
|
|
delete this.mobileRoot;
|
|
|
|
return this.mobileRoot = items[0];
|
|
|
|
},
|
|
|
|
|
2009-02-24 22:20:45 -08:00
|
|
|
show: function() {
|
|
|
|
this._panel = document.getElementById("bookmarklist-container");
|
2009-07-02 09:19:03 -07:00
|
|
|
this._panel.width = window.innerWidth;
|
|
|
|
this._panel.height = window.innerHeight;
|
2009-04-08 22:40:05 -07:00
|
|
|
this._panel.hidden = false;
|
2009-07-08 07:55:07 -07:00
|
|
|
BrowserUI.pushDialog(this);
|
2009-02-24 22:20:45 -08:00
|
|
|
|
|
|
|
this._bookmarks = document.getElementById("bookmark-items");
|
2009-10-20 20:32:36 -07:00
|
|
|
this._bookmarks.addEventListener("BookmarkRemove", this, true);
|
2009-02-24 22:20:45 -08:00
|
|
|
this._bookmarks.manageUI = false;
|
|
|
|
this._bookmarks.openFolder();
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-10-20 20:32:36 -07:00
|
|
|
this._manageButton = document.getElementById("tool-bookmarks-manage");
|
|
|
|
this._manageButton.disabled = (this._bookmarks.items.length == 0);
|
2009-02-24 22:20:45 -08:00
|
|
|
},
|
|
|
|
|
|
|
|
close: function() {
|
|
|
|
BrowserUI.updateStar();
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-12-09 16:14:40 -08:00
|
|
|
this._bookmarks.close();
|
|
|
|
|
2009-10-20 20:32:36 -07:00
|
|
|
if (this._bookmarks.manageUI)
|
|
|
|
this.toggleManage();
|
2009-02-24 22:20:45 -08:00
|
|
|
this._bookmarks.blur();
|
2009-10-20 20:32:36 -07:00
|
|
|
this._bookmarks.removeEventListener("BookmarkRemove", this, true);
|
|
|
|
|
2009-02-24 22:20:45 -08:00
|
|
|
this._panel.hidden = true;
|
2009-07-08 07:55:07 -07:00
|
|
|
BrowserUI.popDialog();
|
2009-02-24 22:20:45 -08:00
|
|
|
},
|
|
|
|
|
|
|
|
toggleManage: function() {
|
|
|
|
this._bookmarks.manageUI = !(this._bookmarks.manageUI);
|
2009-10-20 20:32:36 -07:00
|
|
|
this._manageButton.checked = this._bookmarks.manageUI;
|
2009-02-24 22:20:45 -08:00
|
|
|
},
|
|
|
|
|
|
|
|
openBookmark: function() {
|
|
|
|
let item = this._bookmarks.activeItem;
|
2009-02-24 22:20:45 -08:00
|
|
|
if (item.spec) {
|
2009-08-17 10:56:51 -07:00
|
|
|
this.close();
|
2009-04-17 07:41:44 -07:00
|
|
|
BrowserUI.goToURI(item.spec);
|
2009-02-24 22:20:45 -08:00
|
|
|
}
|
2009-10-20 20:32:36 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
handleEvent: function(aEvent) {
|
|
|
|
if (aEvent.type == "BookmarkRemove") {
|
|
|
|
if (this._bookmarks.isRootFolder && this._bookmarks.items.length == 1) {
|
|
|
|
this._manageButton.disabled = true;
|
|
|
|
this.toggleManage();
|
|
|
|
}
|
|
|
|
}
|
2009-02-24 22:20:45 -08:00
|
|
|
}
|
|
|
|
};
|
2009-06-24 09:42:53 -07:00
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
var FormHelper = {
|
2010-03-01 13:10:31 -08:00
|
|
|
_open: false,
|
2009-10-23 21:04:51 -07:00
|
|
|
_nodes: null,
|
|
|
|
get _container() {
|
|
|
|
delete this._container;
|
|
|
|
return this._container = document.getElementById("form-helper-container");
|
|
|
|
},
|
|
|
|
|
|
|
|
get _helperSpacer() {
|
|
|
|
delete this._helperSpacer;
|
|
|
|
return this._helperSpacer = document.getElementById("form-helper-spacer");
|
|
|
|
},
|
|
|
|
|
|
|
|
get _selectContainer() {
|
|
|
|
delete this._selectContainer;
|
|
|
|
return this._selectContainer = document.getElementById("select-container");
|
|
|
|
},
|
|
|
|
|
2010-03-09 19:42:04 -08:00
|
|
|
get _autofillContainer() {
|
|
|
|
delete this._autofillContainer;
|
|
|
|
return this._autofillContainer = document.getElementById("form-helper-autofill");
|
|
|
|
},
|
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
_getRectForElement: function formHelper_getRectForElement(aElement) {
|
2010-03-02 08:34:20 -08:00
|
|
|
const kDistanceMax = 100;
|
2009-10-23 21:04:51 -07:00
|
|
|
let elRect = Browser.getBoundingContentRect(aElement);
|
|
|
|
let bv = Browser._browserView;
|
|
|
|
|
|
|
|
let labels = this.getLabelsFor(aElement);
|
|
|
|
for (let i=0; i<labels.length; i++) {
|
|
|
|
let labelRect = Browser.getBoundingContentRect(labels[i]);
|
|
|
|
if (labelRect.left < elRect.left) {
|
2010-03-04 09:01:07 -08:00
|
|
|
let isClose = Math.abs(labelRect.left - elRect.left) - labelRect.width < kDistanceMax &&
|
|
|
|
Math.abs(labelRect.top - elRect.top) - labelRect.height < kDistanceMax;
|
|
|
|
if (isClose) {
|
2010-03-02 08:34:20 -08:00
|
|
|
let width = labelRect.width + elRect.width + (elRect.left - labelRect.left - labelRect.width);
|
|
|
|
return new Rect(labelRect.left, labelRect.top, width, elRect.height).expandToIntegers();
|
|
|
|
}
|
2009-10-23 21:04:51 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return elRect;
|
|
|
|
},
|
|
|
|
|
|
|
|
_update: function(aPreviousElement, aNewElement) {
|
|
|
|
this._updateSelect(aPreviousElement, aNewElement);
|
|
|
|
|
2010-03-09 19:42:04 -08:00
|
|
|
// Setup autofill UI
|
|
|
|
if (aNewElement instanceof HTMLInputElement && aNewElement.type == "text") {
|
|
|
|
let suggestions = this._getSuggestions();
|
|
|
|
this._setSuggestions(suggestions);
|
|
|
|
} else {
|
|
|
|
this._autofillContainer.hidden = true;
|
|
|
|
}
|
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
let height = Math.floor(this._container.getBoundingClientRect().height);
|
|
|
|
this._container.top = window.innerHeight - height;
|
|
|
|
|
|
|
|
document.getElementById("form-helper-previous").disabled = this._getPrevious() ? false : true;
|
|
|
|
document.getElementById("form-helper-next").disabled = this._getNext() ? false : true;
|
|
|
|
},
|
|
|
|
|
|
|
|
_updateSelect: function(aPreviousElement, aNewElement) {
|
|
|
|
let previousIsSelect = this._isValidSelectElement(aPreviousElement);
|
|
|
|
let currentIsSelect = this._isValidSelectElement(aNewElement);
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
if (currentIsSelect && !previousIsSelect) {
|
|
|
|
this._selectContainer.height = window.innerHeight / 1.8;
|
|
|
|
|
|
|
|
let rootNode = this._container;
|
|
|
|
rootNode.insertBefore(this._selectContainer, rootNode.lastChild);
|
|
|
|
|
|
|
|
SelectHelper.show(aNewElement);
|
|
|
|
}
|
|
|
|
else if (currentIsSelect && previousIsSelect) {
|
|
|
|
SelectHelper.reset();
|
|
|
|
SelectHelper.show(aNewElement);
|
|
|
|
}
|
|
|
|
else if (!currentIsSelect && previousIsSelect) {
|
|
|
|
let rootNode = this._container.parentNode;
|
|
|
|
rootNode.insertBefore(this._selectContainer, rootNode.lastChild);
|
|
|
|
|
|
|
|
SelectHelper.close();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_isValidElement: function(aElement) {
|
|
|
|
if (aElement.disabled)
|
|
|
|
return false;
|
|
|
|
|
2009-12-09 00:03:04 -08:00
|
|
|
if (aElement.getAttribute("role") == "button" && aElement.hasAttribute("tabindex"))
|
|
|
|
return this._isElementVisible(aElement);
|
|
|
|
|
2009-11-30 08:49:48 -08:00
|
|
|
if (this._isValidSelectElement(aElement) || aElement instanceof HTMLTextAreaElement)
|
2009-11-11 21:15:56 -08:00
|
|
|
return this._isElementVisible(aElement);
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2010-03-01 13:10:31 -08:00
|
|
|
if (aElement instanceof HTMLInputElement || aElement instanceof HTMLButtonElement) {
|
2009-12-09 00:15:39 -08:00
|
|
|
let ignoreInputElements = ["checkbox", "radio", "hidden", "reset", "button"];
|
2009-10-23 21:04:51 -07:00
|
|
|
let isValidElement = (ignoreInputElements.indexOf(aElement.type) == -1);
|
|
|
|
if (!isValidElement)
|
2009-12-09 00:15:39 -08:00
|
|
|
return false;
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-11-11 21:15:56 -08:00
|
|
|
return this._isElementVisible(aElement);
|
2009-10-23 21:04:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
|
|
|
_isValidSelectElement: function(aElement) {
|
|
|
|
return (aElement instanceof HTMLSelectElement) || (aElement instanceof Ci.nsIDOMXULMenuListElement);
|
|
|
|
},
|
|
|
|
|
2009-11-11 21:15:56 -08:00
|
|
|
_isElementVisible: function(aElement) {
|
2010-03-01 13:10:31 -08:00
|
|
|
let style = aElement.ownerDocument.defaultView.getComputedStyle(aElement, null);
|
|
|
|
let isVisible = (style.getPropertyValue("visibility") != "hidden");
|
|
|
|
let isOpaque = (style.getPropertyValue("opacity") != 0);
|
|
|
|
|
2009-11-11 21:15:56 -08:00
|
|
|
let rect = aElement.getBoundingClientRect();
|
2010-03-01 13:10:31 -08:00
|
|
|
return isVisible && isOpaque && (rect.height != 0 || rect.width != 0);
|
2009-11-11 21:15:56 -08:00
|
|
|
},
|
2009-10-29 10:09:22 -07:00
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
_getAll: function() {
|
|
|
|
let elements = [];
|
2009-12-09 00:03:04 -08:00
|
|
|
|
|
|
|
// get all the documents
|
|
|
|
let documents = [getBrowser().contentDocument];
|
2010-02-16 20:54:54 -08:00
|
|
|
let iframes = getBrowser().contentDocument.querySelectorAll("iframe, frame");
|
2009-12-09 00:03:04 -08:00
|
|
|
for (let i = 0; i < iframes.length; i++)
|
|
|
|
documents.push(iframes[i].contentDocument);
|
|
|
|
|
|
|
|
for (let i = 0; i < documents.length; i++) {
|
|
|
|
let nodes = documents[i].querySelectorAll("input, button, select, textarea, [role=button]");
|
|
|
|
|
|
|
|
for (let j =0; j < nodes.length; j++) {
|
|
|
|
let node = nodes[j];
|
|
|
|
if (this._isValidElement(node))
|
2010-01-08 16:29:26 -08:00
|
|
|
elements.push(node);
|
2009-12-09 00:03:04 -08:00
|
|
|
}
|
2009-10-23 21:04:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
function orderByTabIndex(a, b) {
|
2010-01-15 21:41:48 -08:00
|
|
|
// for an explanation on tabbing navigation see
|
2009-11-11 12:30:34 -08:00
|
|
|
// http://www.w3.org/TR/html401/interact/forms.html#h-17.11.1
|
|
|
|
// In resume tab index navigation order is 1, 2, 3, ..., 32767, 0
|
|
|
|
if (a.tabIndex == 0 || b.tabIndex == 0)
|
|
|
|
return b.tabIndex;
|
|
|
|
|
|
|
|
return a.tabIndex > b.tabIndex;
|
2009-10-23 21:04:51 -07:00
|
|
|
}
|
|
|
|
return elements.sort(orderByTabIndex);
|
|
|
|
},
|
|
|
|
|
|
|
|
_getPrevious: function() {
|
2009-12-16 10:09:30 -08:00
|
|
|
let index = this._nodes.indexOf(this._currentElement);
|
|
|
|
return (index != -1 ? this._nodes[--index] : null);
|
2009-10-23 21:04:51 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
_getNext: function() {
|
2009-12-16 10:09:30 -08:00
|
|
|
let index = this._nodes.indexOf(this._currentElement);
|
|
|
|
return (index != -1 ? this._nodes[++index] : null);
|
2009-10-23 21:04:51 -07:00
|
|
|
},
|
|
|
|
|
2010-03-09 19:42:04 -08:00
|
|
|
_fac: Cc["@mozilla.org/satchel/form-autocomplete;1"].getService(Ci.nsIFormAutoComplete),
|
|
|
|
_getSuggestions: function() {
|
|
|
|
let suggestions = [];
|
|
|
|
let currentValue = this._currentElement.value;
|
|
|
|
let results = this._fac.autoCompleteSearch(this._currentElement.name, currentValue, this._currentElement, null);
|
|
|
|
if (results.matchCount > 0) {
|
|
|
|
for (let i = 0; i < results.matchCount; i++) {
|
|
|
|
let value = results.getValueAt(i);
|
|
|
|
suggestions.push(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return suggestions;
|
|
|
|
},
|
|
|
|
|
|
|
|
_setSuggestions: function(aSuggestions) {
|
|
|
|
let autofill = this._autofillContainer;
|
|
|
|
while (autofill.hasChildNodes())
|
|
|
|
autofill.removeChild(autofill.lastChild);
|
|
|
|
|
|
|
|
let fragment = document.createDocumentFragment();
|
|
|
|
for (let i = 0; i < aSuggestions.length; i++) {
|
|
|
|
let value = aSuggestions[i];
|
|
|
|
let button = document.createElement("label");
|
|
|
|
button.setAttribute("value", value);
|
|
|
|
fragment.appendChild(button);
|
|
|
|
}
|
|
|
|
autofill.appendChild(fragment);
|
|
|
|
autofill.hidden = !aSuggestions.length;
|
|
|
|
},
|
|
|
|
|
|
|
|
doAutoFill: function formHelperDoAutoFill(aElement) {
|
|
|
|
if (!this._currentElement)
|
|
|
|
return;
|
|
|
|
|
2010-03-11 05:48:51 -08:00
|
|
|
// Suggestions are only in <label>s. Ignore the rest.
|
|
|
|
if (aElement instanceof Ci.nsIDOMXULLabelElement)
|
|
|
|
this._currentElement.value = aElement.value;
|
2010-03-09 19:42:04 -08:00
|
|
|
},
|
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
getLabelsFor: function(aElement) {
|
|
|
|
let associatedLabels = [];
|
|
|
|
if (this._isValidElement(aElement)) {
|
|
|
|
let labels = aElement.ownerDocument.getElementsByTagName("label");
|
|
|
|
for (let i=0; i<labels.length; i++) {
|
|
|
|
if (labels[i].getAttribute("for") == aElement.id)
|
|
|
|
associatedLabels.push(labels[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aElement.parentNode instanceof HTMLLabelElement)
|
|
|
|
associatedLabels.push(aElement.parentNode);
|
|
|
|
|
2009-11-11 21:15:56 -08:00
|
|
|
return associatedLabels.filter(this._isElementVisible);
|
2009-10-23 21:04:51 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
_currentElement: null,
|
|
|
|
getCurrentElement: function() {
|
|
|
|
return this._currentElement;
|
|
|
|
},
|
|
|
|
|
|
|
|
setCurrentElement: function(aElement) {
|
|
|
|
if (!aElement)
|
|
|
|
return;
|
|
|
|
|
|
|
|
let previousElement = this._currentElement;
|
|
|
|
this._currentElement = aElement;
|
|
|
|
this._update(previousElement, aElement);
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
let containerHeight = this._container.getBoundingClientRect().height;
|
|
|
|
this._helperSpacer.setAttribute("height", containerHeight);
|
|
|
|
|
|
|
|
this.zoom(aElement);
|
|
|
|
gFocusManager.setFocus(aElement, Ci.nsIFocusManager.FLAG_NOSCROLL);
|
|
|
|
},
|
|
|
|
|
|
|
|
goToPrevious: function formHelperGoToPrevious() {
|
|
|
|
let previous = this._getPrevious();
|
|
|
|
this.setCurrentElement(previous);
|
|
|
|
},
|
|
|
|
|
|
|
|
goToNext: function formHelperGoToNext() {
|
|
|
|
let next = this._getNext();
|
|
|
|
this.setCurrentElement(next);
|
|
|
|
},
|
|
|
|
|
|
|
|
open: function formHelperOpen(aElement) {
|
2010-01-08 16:18:12 -08:00
|
|
|
if (this._open == true && aElement == this._currentElement &&
|
|
|
|
gFocusManager.focusedElement == this._currentElement)
|
|
|
|
return false;
|
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
this._open = true;
|
2010-02-16 15:34:04 -08:00
|
|
|
window.addEventListener("keyup", this, false);
|
2009-12-11 11:27:23 -08:00
|
|
|
let bv = Browser._browserView;
|
|
|
|
bv.ignorePageScroll(true);
|
2009-10-23 21:04:51 -07:00
|
|
|
|
|
|
|
this._container.hidden = false;
|
|
|
|
this._helperSpacer.hidden = false;
|
|
|
|
|
|
|
|
this._nodes = this._getAll();
|
2010-01-08 16:29:26 -08:00
|
|
|
this.setCurrentElement(aElement);
|
2010-01-08 16:18:12 -08:00
|
|
|
return true;
|
2009-10-23 21:04:51 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
close: function formHelperHide() {
|
|
|
|
if (!this._open)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._updateSelect(this._currentElement, null);
|
|
|
|
|
|
|
|
this._helperSpacer.hidden = true;
|
2010-03-09 19:42:04 -08:00
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
// give the form spacer area back to the content
|
|
|
|
let bv = Browser._browserView;
|
2010-01-14 13:35:08 -08:00
|
|
|
Browser.forceChromeReflow();
|
2009-10-23 21:04:51 -07:00
|
|
|
Browser.contentScrollboxScroller.scrollBy(0, 0);
|
|
|
|
bv.onAfterVisibleMove();
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-12-11 11:27:23 -08:00
|
|
|
bv.ignorePageScroll(false);
|
2009-10-23 21:04:51 -07:00
|
|
|
|
2010-02-16 15:34:04 -08:00
|
|
|
window.removeEventListener("keyup", this, false);
|
2009-10-23 21:04:51 -07:00
|
|
|
this._container.hidden = true;
|
|
|
|
this._currentElement = null;
|
|
|
|
this._open = false;
|
|
|
|
},
|
|
|
|
|
2009-11-25 12:51:03 -08:00
|
|
|
handleEvent: function formHelperHandleEvent(aEvent) {
|
2010-01-13 11:56:32 -08:00
|
|
|
let isChromeFocused = gFocusManager.getFocusedElementForWindow(window, false, {}) == gFocusManager.focusedElement;
|
2010-02-16 15:34:04 -08:00
|
|
|
if (isChromeFocused)
|
2009-11-25 12:51:03 -08:00
|
|
|
return;
|
|
|
|
|
2010-01-13 11:56:32 -08:00
|
|
|
let currentElement = this.getCurrentElement();
|
2010-03-09 19:42:04 -08:00
|
|
|
switch (aEvent.keyCode) {
|
|
|
|
case aEvent.DOM_VK_DOWN:
|
|
|
|
if (currentElement instanceof HTMLTextAreaElement) {
|
|
|
|
let existSelection = currentElement.selectionEnd - currentElement.selectionStart;
|
|
|
|
let isEnd = (currentElement.textLength == currentElement.selectionEnd);
|
|
|
|
if (!isEnd || existSelection)
|
|
|
|
return;
|
|
|
|
}
|
2009-11-25 12:51:03 -08:00
|
|
|
|
2010-03-09 19:42:04 -08:00
|
|
|
this.goToNext();
|
|
|
|
break;
|
2009-11-25 12:51:03 -08:00
|
|
|
|
2010-03-09 19:42:04 -08:00
|
|
|
case aEvent.DOM_VK_UP:
|
|
|
|
if (currentElement instanceof HTMLTextAreaElement) {
|
|
|
|
let existSelection = currentElement.selectionEnd - currentElement.selectionStart;
|
|
|
|
let isStart = (currentElement.selectionEnd == 0);
|
|
|
|
if (!isStart || existSelection)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.goToPrevious();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case aEvent.DOM_VK_RETURN:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
let target = aEvent.target;
|
|
|
|
if (currentElement instanceof HTMLInputElement && currentElement.type == "text") {
|
|
|
|
let suggestions = this._getSuggestions();
|
|
|
|
this._setSuggestions(suggestions);
|
|
|
|
|
|
|
|
let height = Math.floor(this._container.getBoundingClientRect().height);
|
|
|
|
this._container.top = window.innerHeight - height;
|
|
|
|
this._helperSpacer.setAttribute("height", height);
|
|
|
|
|
|
|
|
// XXX if we are at the bottom of the page we need to give back the content
|
|
|
|
// area by refreshing it
|
|
|
|
if (suggestions.length == 0) {
|
|
|
|
let bv = Browser._browserView;
|
|
|
|
Browser.forceChromeReflow();
|
|
|
|
Browser.contentScrollboxScroller.scrollBy(0, 0);
|
|
|
|
bv.onAfterVisibleMove();
|
|
|
|
}
|
|
|
|
} else if (currentElement == target && this._isValidSelectElement(target)) {
|
|
|
|
SelectHelper.unselectAll();
|
|
|
|
SelectHelper.selectByIndex(target.selectedIndex);
|
|
|
|
}
|
|
|
|
break;
|
2009-11-25 12:51:03 -08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
zoom: function formHelperZoom(aElement) {
|
|
|
|
let zoomLevel = Browser._getZoomLevelForElement(aElement);
|
|
|
|
zoomLevel = Math.min(Math.max(kBrowserFormZoomLevelMin, zoomLevel), kBrowserFormZoomLevelMax);
|
|
|
|
|
|
|
|
let elRect = this._getRectForElement(aElement);
|
|
|
|
let zoomRect = Browser._getZoomRectForPoint(elRect.center().x, elRect.y, zoomLevel);
|
|
|
|
|
|
|
|
Browser.setVisibleRect(zoomRect);
|
2009-11-27 21:37:01 -08:00
|
|
|
},
|
|
|
|
|
|
|
|
canShowUIFor: function(aElement) {
|
2010-01-13 11:56:32 -08:00
|
|
|
if (!aElement)
|
|
|
|
return false;
|
|
|
|
|
2009-12-09 00:15:39 -08:00
|
|
|
// Some forms elements are valid in the sense that we want the Form
|
|
|
|
// Assistant to stop on it, but we don't want it to display when
|
|
|
|
// the user clicks on it
|
|
|
|
let formExceptions = ["submit", "image", "file"];
|
|
|
|
if (aElement instanceof HTMLInputElement && formExceptions.indexOf(aElement.type) != -1)
|
2010-01-15 21:41:48 -08:00
|
|
|
return false;
|
2009-12-09 00:15:39 -08:00
|
|
|
|
2010-03-01 13:10:31 -08:00
|
|
|
if (aElement instanceof HTMLButtonElement || (aElement.getAttribute("role") == "button" && aElement.hasAttribute("tabindex")))
|
|
|
|
return false;
|
|
|
|
|
2009-12-09 00:15:39 -08:00
|
|
|
return this._isValidElement(aElement);
|
2009-10-23 21:04:51 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-09-17 13:17:57 -07:00
|
|
|
function SelectWrapper(aControl) {
|
2010-01-08 16:29:26 -08:00
|
|
|
this._control = aControl;
|
2009-09-17 13:17:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
SelectWrapper.prototype = {
|
2009-10-08 22:51:42 -07:00
|
|
|
get selectedIndex() { return this._control.selectedIndex; },
|
2009-09-17 13:17:57 -07:00
|
|
|
get multiple() { return this._control.multiple; },
|
|
|
|
get options() { return this._control.options; },
|
|
|
|
get children() { return this._control.children; },
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-09-17 13:17:57 -07:00
|
|
|
getText: function(aChild) { return aChild.text; },
|
|
|
|
isOption: function(aChild) { return aChild instanceof HTMLOptionElement; },
|
|
|
|
isGroup: function(aChild) { return aChild instanceof HTMLOptGroupElement; },
|
|
|
|
select: function(aIndex, aSelected, aClearAll) {
|
2009-11-27 21:37:01 -08:00
|
|
|
let selectElement = this._control.QueryInterface(Ci.nsISelectElement);
|
2009-09-17 13:17:57 -07:00
|
|
|
selectElement.setOptionsSelectedByIndex(aIndex, aIndex, aSelected, aClearAll, false, true);
|
|
|
|
},
|
|
|
|
focus: function() { this._control.focus(); },
|
|
|
|
fireOnChange: function() {
|
2009-11-27 21:37:01 -08:00
|
|
|
let control = this._control;
|
2009-10-08 22:51:42 -07:00
|
|
|
let evt = document.createEvent("Events");
|
|
|
|
evt.initEvent("change", true, true, window, 0,
|
|
|
|
false, false,
|
|
|
|
false, false, null);
|
2010-01-15 21:41:48 -08:00
|
|
|
control.dispatchEvent(evt);
|
2009-09-17 13:17:57 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
function MenulistWrapper(aControl) {
|
2010-01-08 16:29:26 -08:00
|
|
|
this._control = aControl;
|
2009-09-17 13:17:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
MenulistWrapper.prototype = {
|
2009-10-08 22:51:42 -07:00
|
|
|
get selectedIndex() { return this._control.selectedIndex; },
|
2009-09-17 13:17:57 -07:00
|
|
|
get multiple() { return false; },
|
|
|
|
get options() { return this._control.menupopup.children; },
|
|
|
|
get children() { return this._control.menupopup.children; },
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-09-17 13:17:57 -07:00
|
|
|
getText: function(aChild) { return aChild.label; },
|
|
|
|
isOption: function(aChild) { return aChild instanceof Ci.nsIDOMXULSelectControlItemElement; },
|
|
|
|
isGroup: function(aChild) { return false },
|
|
|
|
select: function(aIndex, aSelected, aClearAll) {
|
|
|
|
this._control.selectedIndex = aIndex;
|
|
|
|
},
|
|
|
|
focus: function() { this._control.focus(); },
|
|
|
|
fireOnChange: function() {
|
|
|
|
let control = this._control;
|
2009-10-08 22:51:42 -07:00
|
|
|
let evt = document.createEvent("XULCommandEvent");
|
|
|
|
evt.initCommandEvent("command", true, true, window, 0,
|
|
|
|
false, false,
|
|
|
|
false, false, null);
|
2010-01-15 21:41:48 -08:00
|
|
|
control.dispatchEvent(evt);
|
2009-09-17 13:17:57 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-06-24 09:42:53 -07:00
|
|
|
var SelectHelper = {
|
|
|
|
_panel: null,
|
|
|
|
_list: null,
|
|
|
|
_control: null,
|
2009-07-06 10:14:46 -07:00
|
|
|
_selectedIndexes: [],
|
|
|
|
|
|
|
|
_getSelectedIndexes: function() {
|
|
|
|
let indexes = [];
|
|
|
|
let control = this._control;
|
|
|
|
|
2009-10-08 22:51:42 -07:00
|
|
|
if (control.multiple) {
|
2009-07-06 10:14:46 -07:00
|
|
|
for (let i = 0; i < control.options.length; i++) {
|
|
|
|
if (control.options[i].selected)
|
2009-07-28 20:36:00 -07:00
|
|
|
indexes.push(i);
|
2009-07-06 10:14:46 -07:00
|
|
|
}
|
|
|
|
}
|
2009-10-08 22:51:42 -07:00
|
|
|
else {
|
|
|
|
indexes.push(control.selectedIndex);
|
|
|
|
}
|
2009-07-06 10:14:46 -07:00
|
|
|
|
|
|
|
return indexes;
|
|
|
|
},
|
2009-06-24 09:42:53 -07:00
|
|
|
|
|
|
|
show: function(aControl) {
|
|
|
|
if (!aControl)
|
|
|
|
return;
|
|
|
|
|
2009-09-17 13:17:57 -07:00
|
|
|
if (aControl instanceof HTMLSelectElement)
|
|
|
|
this._control = new SelectWrapper(aControl);
|
|
|
|
else if (aControl instanceof Ci.nsIDOMXULMenuListElement)
|
|
|
|
this._control = new MenulistWrapper(aControl);
|
|
|
|
else
|
|
|
|
throw "Unknown list element";
|
|
|
|
|
2009-07-06 10:14:46 -07:00
|
|
|
this._selectedIndexes = this._getSelectedIndexes();
|
2009-06-24 09:42:53 -07:00
|
|
|
|
|
|
|
this._list = document.getElementById("select-list");
|
2009-06-29 11:33:05 -07:00
|
|
|
this._list.setAttribute("multiple", this._control.multiple ? "true" : "false");
|
2009-06-24 09:42:53 -07:00
|
|
|
|
2009-07-28 20:36:00 -07:00
|
|
|
let firstSelected = null;
|
2009-08-13 16:41:45 -07:00
|
|
|
|
2009-06-24 09:42:53 -07:00
|
|
|
let optionIndex = 0;
|
|
|
|
let children = this._control.children;
|
|
|
|
for (let i=0; i<children.length; i++) {
|
|
|
|
let child = children[i];
|
2009-09-17 13:17:57 -07:00
|
|
|
if (this._control.isGroup(child)) {
|
2009-06-24 09:42:53 -07:00
|
|
|
let group = document.createElement("option");
|
2009-06-29 11:33:05 -07:00
|
|
|
group.setAttribute("label", child.label);
|
2009-06-24 09:42:53 -07:00
|
|
|
this._list.appendChild(group);
|
|
|
|
group.className = "optgroup";
|
|
|
|
|
|
|
|
let subchildren = child.children;
|
|
|
|
for (let ii=0; ii<subchildren.length; ii++) {
|
|
|
|
let subchild = subchildren[ii];
|
|
|
|
let item = document.createElement("option");
|
2009-09-17 13:17:57 -07:00
|
|
|
item.setAttribute("label", this._control.getText(subchild));
|
2009-06-24 09:42:53 -07:00
|
|
|
this._list.appendChild(item);
|
|
|
|
item.className = "in-optgroup";
|
|
|
|
item.optionIndex = optionIndex++;
|
2009-07-28 20:36:00 -07:00
|
|
|
if (subchild.selected) {
|
2009-06-24 09:42:53 -07:00
|
|
|
item.setAttribute("selected", "true");
|
2009-07-28 20:36:00 -07:00
|
|
|
firstSelected = firstSelected ? firstSelected : item;
|
|
|
|
}
|
2009-06-24 09:42:53 -07:00
|
|
|
}
|
2009-09-17 13:17:57 -07:00
|
|
|
} else if (this._control.isOption(child)) {
|
2009-06-24 09:42:53 -07:00
|
|
|
let item = document.createElement("option");
|
2009-09-17 13:17:57 -07:00
|
|
|
item.setAttribute("label", this._control.getText(child));
|
2009-06-24 09:42:53 -07:00
|
|
|
this._list.appendChild(item);
|
|
|
|
item.optionIndex = optionIndex++;
|
2009-07-28 20:36:00 -07:00
|
|
|
if (child.selected) {
|
2009-06-24 09:42:53 -07:00
|
|
|
item.setAttribute("selected", "true");
|
2009-07-28 20:36:00 -07:00
|
|
|
firstSelected = firstSelected ? firstSelected : item;
|
|
|
|
}
|
2009-06-24 09:42:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this._panel = document.getElementById("select-container");
|
|
|
|
this._panel.hidden = false;
|
|
|
|
|
2009-07-28 20:36:00 -07:00
|
|
|
this._scrollElementIntoView(firstSelected);
|
|
|
|
|
2009-06-24 09:42:53 -07:00
|
|
|
this._list.addEventListener("click", this, false);
|
|
|
|
},
|
|
|
|
|
2009-07-28 20:36:00 -07:00
|
|
|
_scrollElementIntoView: function(aElement) {
|
|
|
|
if (!aElement)
|
|
|
|
return;
|
|
|
|
|
|
|
|
let index = -1;
|
|
|
|
this._forEachOption(
|
|
|
|
function(aItem, aIndex) {
|
|
|
|
if (aElement.optionIndex == aItem.optionIndex)
|
|
|
|
index = aIndex;
|
|
|
|
}
|
|
|
|
);
|
2009-08-13 16:41:45 -07:00
|
|
|
|
2009-07-28 20:36:00 -07:00
|
|
|
if (index == -1)
|
|
|
|
return;
|
2009-08-13 16:41:45 -07:00
|
|
|
|
2010-02-16 15:34:04 -08:00
|
|
|
let scrollBoxObject = this._list.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
|
2009-07-28 20:36:00 -07:00
|
|
|
let itemHeight = aElement.getBoundingClientRect().height;
|
|
|
|
let visibleItemsCount = this._list.boxObject.height / itemHeight;
|
|
|
|
if ((index + 1) > visibleItemsCount) {
|
|
|
|
let delta = Math.ceil(visibleItemsCount / 2);
|
|
|
|
scrollBoxObject.scrollTo(0, ((index + 1) - delta) * itemHeight);
|
|
|
|
}
|
2010-02-16 15:34:04 -08:00
|
|
|
else {
|
|
|
|
scrollBoxObject.scrollTo(0, 0);
|
|
|
|
}
|
2009-07-28 20:36:00 -07:00
|
|
|
},
|
|
|
|
|
2009-06-24 09:42:53 -07:00
|
|
|
_forEachOption: function(aCallback) {
|
|
|
|
let children = this._list.children;
|
|
|
|
for (let i = 0; i < children.length; i++) {
|
|
|
|
let item = children[i];
|
|
|
|
if (!item.hasOwnProperty("optionIndex"))
|
|
|
|
continue;
|
2009-07-28 20:36:00 -07:00
|
|
|
aCallback(item, i);
|
2009-06-24 09:42:53 -07:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_updateControl: function() {
|
2009-07-06 10:14:46 -07:00
|
|
|
let currentSelectedIndexes = this._getSelectedIndexes();
|
|
|
|
|
|
|
|
let isIdentical = currentSelectedIndexes.length == this._selectedIndexes.length;
|
|
|
|
if (isIdentical) {
|
|
|
|
for (let i = 0; i < currentSelectedIndexes.length; i++) {
|
|
|
|
if (currentSelectedIndexes[i] != this._selectedIndexes[i]) {
|
|
|
|
isIdentical = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-15 21:41:48 -08:00
|
|
|
if (!isIdentical)
|
2009-09-17 13:17:57 -07:00
|
|
|
this._control.fireOnChange();
|
2009-06-24 09:42:53 -07:00
|
|
|
},
|
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
reset: function() {
|
2009-11-27 21:37:01 -08:00
|
|
|
this._updateControl();
|
2009-10-23 21:04:51 -07:00
|
|
|
let empty = this._list.cloneNode(false);
|
|
|
|
this._list.parentNode.replaceChild(empty, this._list);
|
|
|
|
this._list = empty;
|
|
|
|
},
|
|
|
|
|
2009-06-24 09:42:53 -07:00
|
|
|
close: function() {
|
|
|
|
this._list.removeEventListener("click", this, false);
|
|
|
|
this._panel.hidden = true;
|
2010-01-15 21:41:48 -08:00
|
|
|
|
2009-10-23 21:04:51 -07:00
|
|
|
this.reset();
|
2009-06-24 09:42:53 -07:00
|
|
|
},
|
|
|
|
|
2010-02-16 15:34:04 -08:00
|
|
|
unselectAll: function() {
|
|
|
|
this._forEachOption(function(aItem, aIndex) aItem.selected = false);
|
|
|
|
},
|
|
|
|
|
|
|
|
selectByIndex: function(aIndex) {
|
|
|
|
for (let i = 0; i < this._list.childNodes.length; i++) {
|
|
|
|
let option = this._list.childNodes[i];
|
|
|
|
if (option.optionIndex == aIndex) {
|
|
|
|
option.selected = true;
|
|
|
|
this._scrollElementIntoView(option);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2009-06-24 09:42:53 -07:00
|
|
|
handleEvent: function(aEvent) {
|
|
|
|
switch (aEvent.type) {
|
|
|
|
case "click":
|
|
|
|
let item = aEvent.target;
|
|
|
|
if (item && item.hasOwnProperty("optionIndex")) {
|
|
|
|
if (this._control.multiple) {
|
|
|
|
// Toggle the item state
|
|
|
|
item.selected = !item.selected;
|
2009-09-17 13:17:57 -07:00
|
|
|
this._control.select(item.optionIndex, item.selected, false);
|
2009-06-24 09:42:53 -07:00
|
|
|
}
|
|
|
|
else {
|
2010-02-16 15:34:04 -08:00
|
|
|
this.unselectAll();
|
2009-06-24 09:42:53 -07:00
|
|
|
|
|
|
|
// Select the new one and update the control
|
|
|
|
item.selected = true;
|
2009-09-17 13:17:57 -07:00
|
|
|
this._control.select(item.optionIndex, true, true);
|
2009-06-24 09:42:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2009-08-17 14:05:06 -07:00
|
|
|
|
|
|
|
function removeBookmarksForURI(aURI) {
|
|
|
|
//XXX blargle xpconnect! might not matter, but a method on
|
|
|
|
// nsINavBookmarksService that takes an array of items to
|
|
|
|
// delete would be faster. better yet, a method that takes a URI!
|
|
|
|
let itemIds = PlacesUtils.getBookmarksForURI(aURI);
|
|
|
|
itemIds.forEach(PlacesUtils.bookmarks.removeItem);
|
|
|
|
|
|
|
|
BrowserUI.updateStar();
|
|
|
|
}
|