/* ***** 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.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Joe Hewitt (original author) * * 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 ***** */ /*************************************************************** * InspectorApp ------------------------------------------------- * The primary object that controls the Inspector application. ****************************************************************/ //////////// global variables ///////////////////// var inspector; //////////// global constants //////////////////// const kSearchRegURL = "resource:///res/inspector/search-registry.rdf"; const kWindowDataSourceCID = "@mozilla.org/rdf/datasource;1?name=window-mediator"; const kClipboardHelperCID = "@mozilla.org/widget/clipboardhelper;1"; const kPromptServiceCID = "@mozilla.org/embedcomp/prompt-service;1"; const nsIWebNavigation = Components.interfaces.nsIWebNavigation; ////////////////////////////////////////////////// window.addEventListener("load", InspectorApp_initialize, false); window.addEventListener("unload", InspectorApp_destroy, false); function InspectorApp_initialize() { inspector = new InspectorApp(); // window.arguments may be either a string or a node. // If passed via a command line handler, it will be a uri string. // If passed via navigator hooks, it will be a dom node to inspect. var initNode, initURI; if (window.arguments && window.arguments.length) { if (typeof window.arguments[0] == "string") { initURI = window.arguments[0]; } else if (window.arguments[0] instanceof Components.interfaces.nsIDOMNode) { initNode = window.arguments[0]; } } inspector.initialize(initNode, initURI); } function InspectorApp_destroy() { inspector.destroy(); } //////////////////////////////////////////////////////////////////////////// //// class InspectorApp function InspectorApp() { } InspectorApp.prototype = { //////////////////////////////////////////////////////////////////////////// //// Initialization mSearchService: null, mShowBrowser: false, mClipboardHelper: null, mPromptService: null, get document() { return this.mDocPanel.viewer.subject }, get searchRegistry() { return this.mSearchService }, get panelset() { return this.mPanelSet; }, initialize: function(aTarget, aURI) { this.mInitTarget = aTarget; //this.initSearch(); var el = document.getElementById("bxBrowser"); el.addEventListener("pageshow", BrowserPageShowListener, true); this.setBrowser(false, true); //this.setSearch(false, true); this.mClipboardHelper = XPCU.getService(kClipboardHelperCID, "nsIClipboardHelper"); this.mPromptService = XPCU.getService(kPromptServiceCID, "nsIPromptService"); this.mPanelSet = document.getElementById("bxPanelSet"); this.mPanelSet.addObserver("panelsetready", this, false); this.mPanelSet.initialize(); if (aURI) { this.gotoURL(aURI); } }, destroy: function() { InsUtil.persistAll("bxDocPanel"); InsUtil.persistAll("bxObjectPanel"); }, //////////////////////////////////////////////////////////////////////////// //// Viewer Panels initViewerPanels: function() { this.mDocPanel = this.mPanelSet.getPanel(0); this.mDocPanel.addObserver("subjectChange", this, false); this.mObjectPanel = this.mPanelSet.getPanel(1); if (this.mInitTarget) { if (this.mInitTarget.nodeType == Node.DOCUMENT_NODE) this.setTargetDocument(this.mInitTarget); else if (this.mInitTarget.nodeType == Node.ELEMENT_NODE) { this.setTargetDocument(this.mInitTarget.ownerDocument); this.mDocPanel.params = this.mInitTarget; } this.mInitTarget = null; } }, onEvent: function(aEvent) { switch (aEvent.type) { case "panelsetready": this.initViewerPanels(); break; case "subjectChange": if (aEvent.target == this.mDocPanel.viewer && aEvent.subject && "location" in aEvent.subject) { this.locationText = aEvent.subject.location; // display document url } } }, //////////////////////////////////////////////////////////////////////////// //// UI Commands doViewerCommand: function(aCommand) { this.mPanelSet.execCommand(aCommand); }, showOpenURLDialog: function() { var bundle = this.mPanelSet.stringBundle; var msg = bundle.getString("inspectURL.message"); var title = bundle.getString("inspectURL.title"); var url = { value: "http://" }; var dummy = { value: false }; var go = this.mPromptService.prompt(window, title, msg, url, null, dummy); if (go) { this.gotoURL(url.value); } }, showPrefsDialog: function() { goPreferences("advancedItem", "chrome://inspector/content/prefs/pref-inspector.xul", "inspector"); }, toggleBrowser: function(aToggleSplitter) { this.setBrowser(!this.mShowBrowser, aToggleSplitter) }, setBrowser: function(aValue, aToggleSplitter) { this.mShowBrowser = aValue; if (aToggleSplitter) this.openSplitter("Browser", aValue); var cmd = document.getElementById("cmdToggleBrowser"); cmd.setAttribute("checked", aValue); }, toggleSearch: function(aToggleSplitter) { this.setSearch(!this.mShowSearch, aToggleSplitter); }, setSearch: function(aValue, aToggleSplitter) { this.mShowSearch = aValue; if (aToggleSplitter) this.openSplitter("Search", aValue); var cmd = document.getElementById("cmdToggleSearch"); cmd.setAttribute("checked", aValue); }, openSplitter: function(aName, aTruth) { var splitter = document.getElementById("spl" + aName); if (aTruth) splitter.open(); else splitter.close(); }, /* XXXcaa The following code needs to evaluated. What does it do? Why does nobody call it? If deemed necessary, turn it back on with the right callers, and localize it. */ /* runSearch: function() { var path = null; // TODO: should persist last path chosen in a pref var file = FilePickerUtils.pickFile("Find Search File", path, ["filterXML"], "Open"); if (file) { var ioService = XPCU.getService("@mozilla.org/network/io-service;1","nsIIOService"); var fileHandler = XPCU.QI(ioService.getProtocolHandler("file"), "nsIFileProtocolHandler"); var url = fileHandler.getURLSpecFromFile(file); this.startSearchModule(url); } }, viewSearchItem: function() { if (this.mCurrentSearch.canViewItems) window.openDialog("chrome://inspector/content/utilWindow.xul", "viewItem", "chrome,resizable"); }, doViewSearchItem: function(aWindow) { var idx = this.getSelectedSearchIndex(); var el = this.mCurrentSearch.viewItemAt(idx); aWindow.document.title = this.mCurrentSearch.getItemDescription(idx); aWindow.document.getElementById("bxCenter").appendChild(el); }, editSearchItem: function() { }, onSearchTreeClick: function(aEvent) { if (aEvent.detail == 2) { // double click this.viewSearchItem(); } }, copySearchItemLine: function() { var mod = this.mSearchService.currentModule; var idx = this.mSearchService.getSelectedIndex(0); var text = mod.getItemText(idx); this.mClipboardHelper.copyString(text); }, // XXX what is this? It doesn't seem to get called from anywhere? copySearchItemAll: function() { var text = this.getAllSearchItemText(); this.mClipboardHelper.copyString(text); }, saveSearchItemText: function() { var target = FilePickerUtils.pickFile("Save Results As", null, ["filterAll", "filterText"], "Save"); var text = this.getAllSearchItemText(); var file = new File(target.path); file.open('w'); file.write(text); file.close(); }, getAllSearchItemText: function() { var mod = this.mSearchService.currentModule; var len = mod.resultCount; var text = ""; for (var i = 0; i < len; i++) { text += mod.getItemText(i) + "\r"; } return text; }, */ exit: function() { window.close(); // Todo: remove observer service here }, //////////////////////////////////////////////////////////////////////////// //// Navigation gotoTypedURL: function() { var url = document.getElementById("tfURLBar").value; this.gotoURL(url); }, gotoURL: function(aURL, aNoSaveHistory) { this.mPendingURL = aURL; this.mPendingNoSave = aNoSaveHistory; this.browseToURL(aURL); this.setBrowser(true, true); }, browseToURL: function(aURL) { try { this.webNavigation.loadURI(aURL, nsIWebNavigation.LOAD_FLAGS_NONE, null, null, null); } catch(ex) { // nsIWebNavigation.loadURI will spit out an appropriate user prompt, so // we don't need to do anything here. See nsDocShell::DisplayLoadError() } }, goToWindow: function(aMenuitem) { this.setTargetWindowById(aMenuitem.id); }, setTargetWindowById: function(aResId) { var windowManager = XPCU.getService(kWindowDataSourceCID, "nsIWindowDataSource"); var win = windowManager.getWindowForResource(aResId); if (win) { this.setTargetWindow(win); this.setBrowser(false, true); } else { var bundle = this.mPanelSet.stringBundle; var msg = bundle.getString("inspectWindow.error.message"); var title = bundle.getString("inspectWindow.error.title"); this.mPromptService.alert(window, title, msg); } }, setTargetWindow: function(aWindow) { this.setTargetDocument(aWindow.document); }, setTargetDocument: function(aDoc) { this.mDocPanel.subject = aDoc; }, get webNavigation() { var browser = document.getElementById("ifBrowser"); return browser.webNavigation; }, //////////////////////////////////////////////////////////////////////////// //// UI Labels getters and setters get locationText() { return document.getElementById("tfURLBar").value; }, set locationText(aText) { document.getElementById("tfURLBar").value = aText; }, get statusText() { return document.getElementById("txStatus").value; }, set statusText(aText) { document.getElementById("txStatus").value = aText; }, get progress() { return document.getElementById("pmStatus").value; }, set progress(aPct) { document.getElementById("pmStatus").value = aPct; }, /* XXXcaa -- What is this? get searchTitle(aTitle) { return document.getElementById("splSearch").label; }, set searchTitle(aTitle) { var splitter = document.getElementById("splSearch"); splitter.setAttribute("label", "Search" + (aTitle ? " - " + aTitle : "")); }, */ //////////////////////////////////////////////////////////////////////////// //// Document Loading documentLoaded: function() { this.setTargetWindow(_content); var url = this.webNavigation.currentURI.spec; // put the url into the urlbar this.locationText = url; // add url to the history, unless explicity told not to if (!this.mPendingNoSave) this.addToHistory(url); this.mPendingURL = null; this.mPendingNoSave = null; }, //////////////////////////////////////////////////////////////////////////// //// Search /* initSearch: function() { var ss = new inSearchService(); this.mSearchService = ss; ss.addSearchObserver(this); ss.resultsTree = document.getElementById("trSearch"); ss.contextMenu = document.getElementById("ppSearchResults"); ss.contextMenuInsertPt = document.getElementById("ppSearchResults-insertion"); ss.contextMenuInsert = inSearchService.INSERT_BEFORE; }, startSearchModule: function(aModuleURL) { this.mSearchService.startModule(aModuleURL); }, clearSearchResults: function() { this.searchTitle = null; this.statusText = ""; this.progress = 0; this.mSearchService.clearSearch(); }, //////////////////////////////////////////////////////////////////////////// //// interface inISearchObserver onSearchStart: function(aModule) { this.searchTitle = aModule.title; this.toggleSearch(true, true); }, onSearchResult: function(aModule) { if (aModule.isPastMilestone) { this.statusText = "Searching - " + aModule.resultCount + " results found."; // XXX localize this.progress = aModule.progressPercent; } }, onSearchEnd: function(aModule, aResult) { var diff = Math.round(aModule.elapsed / 100) / 10; this.progress = 100; this.statusText = "Search complete - " + aModule.resultCount + " results found ("+diff+"s)"; // XXX localize }, onSearchError: function(aModule, aMessage) { alert("Unable to complete this search due to the following error:\n" + aMessage); }, */ //////////////////////////////////////////////////////////////////////////// //// History addToHistory: function(aURL) { }, //////////////////////////////////////////////////////////////////////////// //// Uncategorized get isViewingContent() { return this.mPanelSet.getPanel(0).subject != null; }, fillInTooltip: function(tipElement) { var retVal = false; var textNode = document.getElementById("txTooltip"); if (textNode) { try { var tipText = tipElement.getAttribute("tooltiptext"); if (tipText != "") { textNode.setAttribute("value", tipText); retVal = true; } } catch (e) { } } return retVal; }, initPopup: function(aPopup) { var items = aPopup.getElementsByTagName("menuitem"); var js, fn, item; for (var i = 0; i < items.length; i++) { item = items[i]; fn = "isDisabled" in item ? item.isDisabled : null; if (!fn) { js = item.getAttribute("isDisabled"); if (js) { fn = new Function(js); item.isDisabled = fn; } else { item.isDisabled = null; // to prevent annoying "strict" warning messages } } if (fn) { if (item.isDisabled()) item.setAttribute("disabled", "true"); else item.removeAttribute("disabled"); } fn = null; } }, emptyChildren: function(aNode) { while (aNode.childNodes.length > 0) { aNode.removeChild(aNode.lastChild); } }, onSplitterOpen: function(aSplitter) { if (aSplitter.id == "splBrowser") { this.setBrowser(aSplitter.isOpened, false); } else if (aSplitter.id == "splSearch") { this.setSearch(aSplitter.isOpened, false); } }, // needed by overlayed commands from viewer to get references to a specific // viewer object by name getViewer: function(aUID) { return this.mPanelSet.registry.getViewerByUID(aUID); } }; //////////////////////////////////////////////////////////////////////////// //// event listeners function BrowserPageShowListener(aEvent) { // since we will also get pageshow events for frame documents, // make sure we respond to the top-level document load if (aEvent.target.defaultView == _content) inspector.documentLoaded(); } function UtilWindowOpenListener(aWindow) { inspector.doViewSearchItem(aWindow); }