home *** CD-ROM | disk | FTP | other *** search
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: NPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Netscape 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/NPL/
- *
- * 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 <hewitt@netscape.com> (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 NPL, 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 NPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
- /***************************************************************
- * inSearchModule -----------------------------------------------
- * Encapsulates an ISML module and exposes it to inSearchService.
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- * REQUIRED IMPORTS:
- * chrome://inspector/content/jsutil/xpcom/XPCU.js
- * chrome://inspector/content/jsutil/rdf/RDFU.js
- * chrome://inspector/content/jsutil/rdf/RDFArray.js
- * chrome://inspector/content/jsutil/xul/inFormManager.js
- * chrome://inspector/content/search/xul/inSearchUtils.js
- ****************************************************************/
-
- //////////// global variables /////////////////////
-
- //////////// global constants ////////////////////
-
- ////////////////////////////////////////////////////////////////////////////
- //// class inSearchModule
-
- function inSearchModule(aBaseURL)
- {
- this.mObservers = [];
- this.mBaseURL = aBaseURL;
- }
-
- inSearchModule.prototype =
- {
- mTitle: null,
- mBaseURL: null,
- mImpl: null,
- mDialogElementIds: null,
- mDialogURL: null,
- mContextMenuItems: null,
- mColumns: null,
- mColDelimiter: null,
- mNameSpace: null,
-
- mRDFArray: null,
- mResult: null,
- mObservers: null,
-
- mStartTime: null,
- mElapsed: 0,
-
- //////////////////////////////////////////////////////////////////////////
- //// Properties
-
- get searchService() { return this.mSearchService},
- set searchService(aVal) { this.mSearchService = aVal },
-
- get title() { return this.mTitle },
- get baseURL() { return this.mBaseURL },
- get defaultIconURL() { return this.mDefaultIconURL },
-
- get datasource() { return this.mRDFArray.datasource },
- get resultCount() { return this.mRDFArray.length },
- get progressPercent() { return this.mImpl.progressPercent },
- get progressText() { return this.mImp.progressText },
- get isPastMilestone() { return this.mImpl.isPastMilestone },
- get elapsed() { return this.mElapsed },
-
- //////////////////////////////////////////////////////////////////////////
- //// Initialization
-
- initFromElement: function(aSearchEl)
- {
- this.parseSearch(aSearchEl);
-
- if (this.mImpl.constructor)
- this.mImpl.constructor();
- },
-
- //////////////////////////////////////////////////////////////////////////
- //// Parser
-
- parseSearch: function(aSearchEl)
- {
- // get the title
- this.mTitle = aSearchEl.getAttribute("title");
- // get the default icon url
- this.mDefaultIconURL = aSearchEl.getAttribute("defaultIcon");
- // get the namespace
- var ns = aSearchEl.getAttribute("namespace")
- this.mNameSpace = ns ? ns : kInspectorNSURI;
-
- this.parseDialog(aSearchEl);
- this.parseContextMenu(aSearchEl);
- this.parseColumns(aSearchEl);
- this.parseImplementation(aSearchEl);
- },
-
- parseDialog: function(aSearchEl)
- {
- var els = aSearchEl.getElementsByTagNameNS(kISMLNSURI, "dialog");
- if (els.length > 0) {
- var dialogEl = els[0];
-
- // get the array of dialog element ids
- var ids = dialogEl.getAttribute("elements");
- if (ids)
- this.mDialogElementIds = ids.split(",");
-
- // get the dialog url
- this.setDialogURL(dialogEl.getAttribute("href"));
- // get the dialog parameters
- this.mDialogResizable = (dialogEl.getAttribute("resizable") == "true") ? true : false;
- }
- },
-
- parseContextMenu: function(aSearchEl)
- {
- var els = aSearchEl.getElementsByTagNameNS(kISMLNSURI, "contextmenu");
- if (els.length > 0) {
- var kids = els[0].childNodes;
- this.mContextMenu = [];
- for (var i = 0; i < kids.length; ++i) {
- this.mContextMenu[i] = kids[i].cloneNode(true);
- }
- }
- },
-
- parseColumns: function(aSearchEl)
- {
- // get the result columns
- var els = aSearchEl.getElementsByTagNameNS(kISMLNSURI, "columns");
- if (els.length > 0) {
- this.mColumns = [];
- var cols = els[0];
- this.mColDelimiter = cols.getAttribute("delimiter");
-
- var kids = cols.childNodes;
- var col, data;
- for (var i= 0; i < kids.length; ++i) {
- col = kids[i];
- if (col.nodeType == Node.ELEMENT_NODE) { // ignore non-element nodes
- data = {
- name: col.getAttribute("name"),
- title: col.getAttribute("title"),
- flex: col.getAttribute("flex"),
- className: col.getAttribute("class"),
- copy: col.getAttribute("copy") == "true"
- };
- this.mColumns.push(data);
- }
- }
- }
- },
-
- parseImplementation: function(aSearchEl)
- {
- this.mImpl = this.getDefaultImplementation();
-
- // get the implementation object
- var els = aSearchEl.getElementsByTagNameNS(kISMLNSURI, "implementation");
- if (els.length > 0) {
- var kids = aSearchEl.getElementsByTagNameNS(kISMLNSURI, "*");
- for (var i = 0; i < kids.length; i++) {
- if (kids[i].localName == "property")
- this.parseProperty(kids[i]);
- if (kids[i].localName == "method")
- this.parseMethod(kids[i]);
- }
- }
- },
-
- parseProperty: function(aPropEl)
- {
- var name = aPropEl.getAttribute("name");
- var fn = null;
-
- // look for a getter
- try {
- fn = this.getCodeTagFunction(aPropEl, "getter", null);
- if (fn)
- this.mImpl.__defineGetter__(name, fn);
- } catch (ex) {
- throw "### SYNTAX ERROR IN ISML GETTER \"" + name + "\" ###\n" + ex;
- }
-
- // look for a setter
- try {
- fn = this.getCodeTagFunction(aPropEl, "setter", ["val"]);
- if (fn)
- this.mImpl.__defineSetter__(name, fn);
- } catch (ex) {
- throw "### SYNTAX ERROR IN ISML SETTER \"" + name + "\" ###\n" + ex;
- }
- },
-
- parseMethod: function(aMethodEl)
- {
- var name = aMethodEl.getAttribute("name");
- var def = aMethodEl.getAttribute("defaultCommand") == "true";
-
- // get all the parameters
- var els = aMethodEl.getElementsByTagNameNS(kISMLNSURI, "parameter");
- var params = [];
- for (var i = 0; i < els.length; i++) {
- params[i] = els[i].getAttribute("name");
- }
-
- // get the body javascript and create the function
- try {
- var fn = this.getCodeTagFunction(aMethodEl, "body", params);
- this.mImpl[name] = fn;
- if (def)
- this.mImpl.__DefaultCmd__ = fn;
- } catch (ex) {
- throw "### SYNTAX ERROR IN ISML METHOD \"" + name + "\" ###\n" + ex;
- }
- },
-
- getCodeTagFunction: function(aParent, aLocalName, aParams)
- {
- var els = aParent.getElementsByTagNameNS(kISMLNSURI, aLocalName);
- if (els.length) {
- var body = els[0];
- // try to determine where the code is located
- var node = body.childNodes.length > 0 ? body.firstChild : body;
- return this.getJSFunction(aParams, node.nodeValue);
- }
-
- return null;
- },
-
- getJSFunction: function(aParams, aCode)
- {
- var params = "";
- if (aParams) {
- for (var i = 0; i < aParams.length; i++) {
- params += aParams[i];
- if (i < aParams.length-1) params += ",";
- }
- }
-
- var js = "function(" + params + ") " +
- "{" +
- (aCode ? aCode : "") +
- "}";
-
- var fn;
- eval("fn = " + js);
- return fn;
- },
-
- getDefaultImplementation: function()
- {
- return { module: this };
- },
-
- //////////////////////////////////////////////////////////////////////////
- //// Dialog box
-
- openDialog: function()
- {
- window.openDialog(this.mDialogURL, "inSearchModule_dialog",
- "chrome,modal,resizable="+this.mDialogResizable, this);
- },
-
- processDialog: function(aWindow)
- {
- var map = inFormManager.readWindow(aWindow, this.mDialogElementIds);
- this.implStartSearch(map);
- },
-
- //////////////////////////////////////////////////////////////////////////
- //// Searching
-
- startSearch: function()
- {
- if (this.mDialogURL) {
- this.openDialog();
- } else
- this.implStartSearch(null);
- },
-
- implStartSearch: function(aMap)
- {
- this.mStartTime = new Date();
- this.mElapsed = 0;
-
- this.notifySearchStart();
- this.initDataSource();
- this.prepareForResult();
- this.mImpl.searchStart(aMap);
- },
-
- stopSearch: function()
- {
- this.searchEnd();
- },
-
- //////////////////////////////////////////////////////////////////////////
- //// Result Returns
-
- setResultProperty: function(aAttr, aValue)
- {
- this.mResult[aAttr] = aValue;
- },
-
- searchResultReady: function()
- {
- this.mRDFArray.add(this.mResult);
- this.notifySearchResult();
- this.prepareForResult();
- },
-
- searchError: function(aMsg)
- {
- },
-
- searchEnd: function()
- {
- this.mElapsed = new Date() - this.mStartTime;
- this.notifySearchEnd();
- },
-
- //////////////////////////////////////////////////////////////////////////
- //// Columns
-
- get columnCount() { return this.mColumns.length },
-
- getColumn: function(aIndex) { return this.mColumns[aIndex] },
- getColumnName: function(aIndex) { return this.mColumns[aIndex].name },
- getColumnTitle: function(aIndex) { return this.mColumns[aIndex].title },
- getColumnClassName: function(aIndex) { return this.mColumns[aIndex].className },
- getColumnFlex: function(aIndex) { return this.mColumns[aIndex].flex },
-
- //////////////////////////////////////////////////////////////////////////
- //// RDF Datasource
-
- initDataSource: function()
- {
- this.mRDFArray = new RDFArray(this.mNameSpace, "inspector:searchResults", "results");
- this.mRDFArray.initialize();
- },
-
- getResultPropertyAt: function(aIndex, aProp)
- {
- return this.mRDFArray.get(aIndex, aProp);
- },
-
- getItemText: function(aIndex)
- {
- var cols = this.mColumns;
- var text = [];
- for (var i = 0; i < cols.length; ++i) {
- if (cols[i].copy) {
- text.push(this.getResultPropertyAt(aIndex, cols[i].name));
- }
- }
- return text.join(this.mColDelimiter);
- },
-
- //////////////////////////////////////////////////////////////////////////
- //// Context Menu
-
- installContextMenu: function(aMenu, aInsertionPoint, aDir)
- {
- if (this.mContextMenu) {
- aMenu._searchModule = this;
- var item;
- this.mMenuItems = [];
- if (this.mContextMenu.length == 0)
- aInsertionPoint.setAttribute("hide", "true");
- for (var i = 0; i < this.mContextMenu.length; ++i) {
- item = this.mContextMenu[i];
- this.mMenuItems.push(item);
- this.installSearchReference(item);
- if (aDir == inSearchService.INSERT_BEFORE)
- aMenu.insertBefore(item, aInsertionPoint);
- else {
- // NOT YET IMPLEMENTED
- }
- }
- }
- },
-
- uninstallContextMenu: function(aMenu, aInsertionPoint, aDir)
- {
- if (this.mContextMenu) {
- if (this.mContextMenu.length == 0)
- aInsertionPoint.removeAttribute("hide");
- // remove the menu items
- for (var i = 0; i < this.mContextMenu.length; ++i)
- aMenu.removeChild(this.mMenuItems[i]);
- }
- },
-
- installSearchReference: function(aItem)
- {
- if (aItem.nodeType == Node.ELEMENT_NODE) {
- if (aItem.localName == "menuitem") {
- aItem.search = this.mImpl;
- for (var i = 0; i < aItem.childNodes.length; ++i)
- this.installSearchReference(aItem.childNodes[i]);
- }
- }
- },
-
- //////////////////////////////////////////////////////////////////////////
- //// Event Notification
-
- // NOTE TO SELF - this code could be cut down to nothing if you write a module
- // called "ObserverManager" to do the work for you
-
- addSearchObserver: function(aObserver)
- {
- this.mObservers.push(aObserver);
- },
-
- removeSearchObserver: function(aObserver)
- {
- var o;
- var obs = this.mObservers;
- for (var i = 0; i < obs.length; i++) {
- o = obs[i];
- if (o == aObserver) {
- obs.splice(i, 1);
- return;
- }
- }
- },
-
- notifySearchStart: function()
- {
- var o = this.mObservers;
- for (var i = 0; i < o.length; i++)
- o[i].onSearchStart(this);
- },
-
- notifySearchResult: function()
- {
- var o = this.mObservers;
- for (var i = 0; i < o.length; i++)
- o[i].onSearchResult(this);
- },
-
- notifySearchEnd: function(aResult)
- {
- var o = this.mObservers;
- for (var i = 0; i < o.length; i++)
- o[i].onSearchEnd(this, aResult);
- },
-
- notifySearchError: function(aMsg)
- {
- var o = this.mObservers;
- for (var i = 0; i < o.length; i++)
- o[i].onSearchError(this, aMsg);
- },
-
- //////////////////////////////////////////////////////////////////////////
- //// Uncategorized
-
- callDefaultCommand: function()
- {
- if (this.mImpl.__DefaultCmd__)
- this.mImpl.__DefaultCmd__();
- },
-
- prepareForResult: function()
- {
- this.mResult = { _icon: this.mDefaultIconURL };
- },
-
- setDialogURL: function(aURL)
- {
- this.mDialogURL = aURL;
- // This block below doesn't work for now because none of the local file implementations
- // implement SetURL. So, for now, the url in the search file MUST be absolute :(
- /* this.mDialogURL = aURL;
- var baseFile = inSearchUtils.createLocalFile(this.mBaseURL);
- try {
- baseFile.append(aURL);
- } catch (ex) {
- basefile = inSearchUtils.createLocalFile(aURL);
- }
-
- var file = XPCU.QI(file, "nsIFile");
-
- var ioService = XPCU.getService("@mozilla.org/network/io-service;1", "nsIIOService");
- var fileHandler = XPCU.QI(ioService.getProtocolHandler("file"), "nsIFileProtocolHandler");
-
- this.mDialogURL = fileHandler.getURLSpecFromFile(basefile);
- */
- }
-
- };
-
- //////////////////////////////////////////////////////////////////////////
- //// Event Listeners
-
-