
This change should improve Firefox startup time. If the Zotero pane is opened before Zotero has initialized, the pane will be blocked with a progress bar until it's done. Standalone currently does the same, but it should be changed to just delay opening the window if possible. The upgrade wizard has been disabled for schema upgrades, in the hope that upgrades can be done in a way that won't break compatibility with earlier versions (or that can at least be done in a way such that we can put out point releases of the last major version that provide compatibility during beta/post-upgrade periods). This patch likely breaks many things, and definitely breaks connector mode. This change also removes upgrade steps for databases from Zotero 2.1b2 and earlier. Users with such databases will need to upgrade via Zotero 4.0.x first or delete their data directories and start anew. This should only affect users who haven't opened Zotero since Nov. 2010.
843 lines
No EOL
26 KiB
JavaScript
843 lines
No EOL
26 KiB
JavaScript
/*
|
|
***** BEGIN LICENSE BLOCK *****
|
|
|
|
Copyright © 2009 Center for History and New Media
|
|
George Mason University, Fairfax, Virginia, USA
|
|
http://zotero.org
|
|
|
|
This file is part of Zotero.
|
|
|
|
Zotero is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Zotero is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
Based on code from Greasemonkey and PiggyBank
|
|
|
|
***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
//
|
|
// Zotero Ingester Browser Functions
|
|
//
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Zotero_Browser
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Class to interface with the browser when ingesting data
|
|
|
|
var Zotero_Browser = new function() {
|
|
this.init = init;
|
|
this.scrapeThisPage = scrapeThisPage;
|
|
this.annotatePage = annotatePage;
|
|
this.toggleMode = toggleMode;
|
|
this.toggleCollapsed = toggleCollapsed;
|
|
this.chromeLoad = chromeLoad;
|
|
this.contentLoad = contentLoad;
|
|
this.itemUpdated = itemUpdated;
|
|
this.contentHide = contentHide;
|
|
this.tabClose = tabClose;
|
|
this.resize = resize;
|
|
this.updateStatus = updateStatus;
|
|
|
|
this.tabbrowser = null;
|
|
this.appcontent = null;
|
|
this.statusImage = null;
|
|
this.isScraping = false;
|
|
|
|
var _browserData = new Object();
|
|
|
|
var _blacklist = [
|
|
"googlesyndication.com",
|
|
"doubleclick.net",
|
|
"questionmarket.com",
|
|
"atdmt.com",
|
|
"aggregateknowledge.com",
|
|
"ad.yieldmanager.com"
|
|
];
|
|
|
|
var _locationBlacklist = [
|
|
"zotero://debug/"
|
|
];
|
|
|
|
var tools = {
|
|
'zotero-annotate-tb-add':{
|
|
cursor:"pointer",
|
|
event:"click",
|
|
callback:function(e) { _add("annotation", e) }
|
|
},
|
|
'zotero-annotate-tb-highlight':{
|
|
cursor:"text",
|
|
event:"mouseup",
|
|
callback:function(e) { _add("highlight", e) }
|
|
},
|
|
'zotero-annotate-tb-unhighlight':{
|
|
cursor:"text",
|
|
event:"mouseup",
|
|
callback:function(e) { _add("unhighlight", e) }
|
|
}
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Public Zotero_Browser methods
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
/**
|
|
* Initialize some variables and prepare event listeners for when chrome is done loading
|
|
*/
|
|
function init() {
|
|
if (!Zotero || Zotero.skipLoading || !window.hasOwnProperty("gBrowser")) {
|
|
return;
|
|
}
|
|
|
|
window.addEventListener("load",
|
|
function(e) { Zotero_Browser.chromeLoad(e) }, false);
|
|
|
|
ZoteroPane_Local.addReloadListener(reload);
|
|
reload();
|
|
}
|
|
|
|
/**
|
|
* Called when Zotero is reloaded
|
|
*/
|
|
function reload() {
|
|
// Handles the display of a div showing progress in scraping
|
|
Zotero_Browser.progress = new Zotero.ProgressWindow();
|
|
}
|
|
|
|
/**
|
|
* Scrapes a page (called when the capture icon is clicked
|
|
* @return void
|
|
*/
|
|
function scrapeThisPage(translator) {
|
|
// Perform translation
|
|
var tab = _getTabObject(Zotero_Browser.tabbrowser.selectedBrowser);
|
|
if(tab.page.translators && tab.page.translators.length) {
|
|
tab.page.translate.setTranslator(translator || tab.page.translators[0]);
|
|
Zotero_Browser.performTranslation(tab.page.translate);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* flags a page for annotation
|
|
*/
|
|
function annotatePage(id, browser) {
|
|
if (browser) {
|
|
var tab = _getTabObject(browser);
|
|
}
|
|
else {
|
|
var tab = _getTabObject(this.tabbrowser.selectedBrowser);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* toggles a tool on/off
|
|
*/
|
|
function toggleMode(toggleTool, ignoreOtherTools) {
|
|
// make sure other tools are turned off
|
|
if(!ignoreOtherTools) {
|
|
for(var tool in tools) {
|
|
if(tool != toggleTool && document.getElementById(tool).getAttribute("tool-active")) {
|
|
toggleMode(tool, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
// make sure annotation action is toggled
|
|
var tab = _getTabObject(Zotero_Browser.tabbrowser.selectedBrowser);
|
|
if(tab.page && tab.page.annotations && tab.page.annotations.clearAction) tab.page.annotations.clearAction();
|
|
|
|
if(!toggleTool) return;
|
|
|
|
var body = Zotero_Browser.tabbrowser.selectedBrowser.contentDocument.getElementsByTagName("body")[0];
|
|
var addElement = document.getElementById(toggleTool);
|
|
|
|
if(addElement.getAttribute("tool-active")) {
|
|
// turn off
|
|
body.style.cursor = "auto";
|
|
addElement.removeAttribute("tool-active");
|
|
Zotero_Browser.tabbrowser.selectedBrowser.removeEventListener(tools[toggleTool].event, tools[toggleTool].callback, true);
|
|
} else {
|
|
body.style.cursor = tools[toggleTool].cursor;
|
|
addElement.setAttribute("tool-active", "true");
|
|
Zotero_Browser.tabbrowser.selectedBrowser.addEventListener(tools[toggleTool].event, tools[toggleTool].callback, true);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* expands all annotations
|
|
*/
|
|
function toggleCollapsed() {
|
|
var tab = _getTabObject(Zotero_Browser.tabbrowser.selectedBrowser);
|
|
tab.page.annotations.toggleCollapsed();
|
|
}
|
|
|
|
/*
|
|
* When chrome loads, register our event handlers with the appropriate interfaces
|
|
*/
|
|
function chromeLoad() {
|
|
this.tabbrowser = gBrowser;
|
|
this.appcontent = document.getElementById("appcontent");
|
|
this.statusImage = document.getElementById("zotero-status-image");
|
|
|
|
// this gives us onLocationChange, for updating when tabs are switched/created
|
|
gBrowser.tabContainer.addEventListener("TabClose",
|
|
function(e) {
|
|
//Zotero.debug("TabClose");
|
|
Zotero_Browser.tabClose(e);
|
|
}, false);
|
|
gBrowser.tabContainer.addEventListener("TabSelect",
|
|
function(e) {
|
|
//Zotero.debug("TabSelect");
|
|
Zotero_Browser.updateStatus();
|
|
}, false);
|
|
// this is for pageshow, for updating the status of the book icon
|
|
this.appcontent.addEventListener("pageshow", contentLoad, true);
|
|
// this is for turning off the book icon when a user navigates away from a page
|
|
this.appcontent.addEventListener("pagehide",
|
|
function(e) {
|
|
//Zotero.debug("pagehide");
|
|
Zotero_Browser.contentHide(e);
|
|
}, true);
|
|
|
|
this.tabbrowser.addEventListener("resize",
|
|
function(e) { Zotero_Browser.resize(e) }, false);
|
|
// Resize on text zoom changes
|
|
|
|
// Fx2
|
|
var reduce = document.getElementById('cmd_textZoomReduce');
|
|
if (reduce) {
|
|
var enlarge = document.getElementById('cmd_textZoomEnlarge');
|
|
var reset = document.getElementById('cmd_textZoomReset');
|
|
}
|
|
// Fx3
|
|
else {
|
|
var reduce = document.getElementById('cmd_fullZoomReduce');
|
|
var enlarge = document.getElementById('cmd_fullZoomEnlarge');
|
|
var reset = document.getElementById('cmd_fullZoomReset');
|
|
}
|
|
|
|
if(reduce) reduce.addEventListener("command",
|
|
function(e) { Zotero_Browser.resize(e) }, false);
|
|
if(enlarge) enlarge.addEventListener("command",
|
|
function(e) { Zotero_Browser.resize(e) }, false);
|
|
if(reset) reset.addEventListener("command",
|
|
function(e) { Zotero_Browser.resize(e) }, false);
|
|
}
|
|
|
|
/*
|
|
* An event handler called when a new document is loaded. Creates a new document
|
|
* object, and updates the status of the capture icon
|
|
*/
|
|
function contentLoad(event) {
|
|
var doc = event.originalTarget;
|
|
var isHTML = doc instanceof HTMLDocument;
|
|
var rootDoc = (doc instanceof HTMLDocument ? doc.defaultView.top.document : doc);
|
|
var browser = Zotero_Browser.tabbrowser.getBrowserForDocument(rootDoc);
|
|
if(!browser) return;
|
|
|
|
if(isHTML) {
|
|
// ignore blacklisted domains
|
|
try {
|
|
if(doc.domain) {
|
|
for each(var blacklistedURL in _blacklist) {
|
|
if(doc.domain.substr(doc.domain.length-blacklistedURL.length) == blacklistedURL) {
|
|
Zotero.debug("Ignoring blacklisted URL "+doc.location);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (e) {}
|
|
}
|
|
|
|
try {
|
|
if (_locationBlacklist.indexOf(doc.location.href) != -1) {
|
|
return;
|
|
}
|
|
|
|
// Ignore TinyMCE popups
|
|
if (!doc.location.host && doc.location.href.indexOf("tinymce/") != -1) {
|
|
return;
|
|
}
|
|
}
|
|
catch (e) {}
|
|
|
|
// get data object
|
|
var tab = _getTabObject(browser);
|
|
|
|
if(isHTML && !Zotero.isConnector) {
|
|
var annotationID = Zotero.Annotate.getAnnotationIDFromURL(browser.currentURI.spec);
|
|
if(annotationID) {
|
|
if(Zotero.Annotate.isAnnotated(annotationID)) {
|
|
//window.alert(Zotero.getString("annotations.oneWindowWarning"));
|
|
} else if(!tab.page.annotations) {
|
|
// enable annotation
|
|
tab.page.annotations = new Zotero.Annotations(Zotero_Browser, browser, annotationID);
|
|
var saveAnnotations = function() {
|
|
tab.page.annotations.save();
|
|
tab.page.annotations = undefined;
|
|
};
|
|
browser.contentWindow.addEventListener('beforeunload', saveAnnotations, false);
|
|
browser.contentWindow.addEventListener('close', saveAnnotations, false);
|
|
tab.page.annotations.load();
|
|
}
|
|
}
|
|
}
|
|
|
|
// detect translators
|
|
tab.detectTranslators(rootDoc, doc);
|
|
|
|
// register metadata updated event
|
|
if(isHTML) {
|
|
var contentWin = doc.defaultView;
|
|
if(!contentWin.haveZoteroEventListener) {
|
|
contentWin.addEventListener("ZoteroItemUpdated", function(event) { itemUpdated(event.originalTarget) }, false);
|
|
contentWin.haveZoteroEventListener = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* called to unregister Zotero icon, etc.
|
|
*/
|
|
function contentHide(event) {
|
|
var doc = event.originalTarget;
|
|
if(!(doc instanceof HTMLDocument)) return;
|
|
|
|
var rootDoc = (doc instanceof HTMLDocument ? doc.defaultView.top.document : doc);
|
|
var browser = Zotero_Browser.tabbrowser.getBrowserForDocument(rootDoc);
|
|
if(!browser) return;
|
|
|
|
var tab = _getTabObject(browser);
|
|
if(!tab) return;
|
|
|
|
if(doc == tab.page.document || doc == rootDoc) {
|
|
// clear translator only if the page on which the pagehide event was called is
|
|
// either the page to which the translator corresponded, or the root document
|
|
// (the second check is probably paranoid, but won't hurt)
|
|
tab.clear();
|
|
}
|
|
|
|
// update status
|
|
if(Zotero_Browser.tabbrowser.selectedBrowser == browser) {
|
|
updateStatus();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when item should be updated due to a DOM event
|
|
*/
|
|
function itemUpdated(doc) {
|
|
try {
|
|
var rootDoc = (doc instanceof HTMLDocument ? doc.defaultView.top.document : doc);
|
|
var browser = Zotero_Browser.tabbrowser.getBrowserForDocument(rootDoc);
|
|
var tab = _getTabObject(browser);
|
|
if(doc == tab.page.document || doc == rootDoc) tab.clear();
|
|
tab.detectTranslators(rootDoc, doc);
|
|
} catch(e) {
|
|
Zotero.debug(e);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* called when a tab is closed
|
|
*/
|
|
function tabClose(event) {
|
|
// Save annotations when closing a tab, since the browser is already
|
|
// gone from tabbrowser by the time contentHide() gets called
|
|
var tab = _getTabObject(event.target);
|
|
if(tab.page && tab.page.annotations) tab.page.annotations.save();
|
|
tab.clear();
|
|
|
|
// To execute if document object does not exist
|
|
toggleMode();
|
|
}
|
|
|
|
|
|
/*
|
|
* called when the window is resized
|
|
*/
|
|
function resize(event) {
|
|
var tab = _getTabObject(this.tabbrowser.selectedBrowser);
|
|
if(!tab.page.annotations) return;
|
|
|
|
tab.page.annotations.refresh();
|
|
}
|
|
|
|
/*
|
|
* Updates the status of the capture icon to reflect the scrapability or lack
|
|
* thereof of the current page
|
|
*/
|
|
function updateStatus() {
|
|
var tab = _getTabObject(Zotero_Browser.tabbrowser.selectedBrowser);
|
|
|
|
var captureIcon = tab.getCaptureIcon();
|
|
if(captureIcon) {
|
|
Zotero_Browser.statusImage.src = captureIcon;
|
|
Zotero_Browser.statusImage.tooltipText = tab.getCaptureTooltip();
|
|
Zotero_Browser.statusImage.hidden = false;
|
|
|
|
Zotero_Browser.statusImage.addEventListener("load", function() {
|
|
document.getElementById("zotero-status-image-guidance").show();
|
|
}, false);
|
|
} else {
|
|
Zotero_Browser.statusImage.hidden = true;
|
|
}
|
|
|
|
// set annotation bar status
|
|
if(tab.page.annotations && tab.page.annotations.annotations.length) {
|
|
document.getElementById('zotero-annotate-tb').hidden = false;
|
|
toggleMode();
|
|
} else {
|
|
document.getElementById('zotero-annotate-tb').hidden = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when status bar icon is right-clicked
|
|
*/
|
|
this.onStatusPopupShowing = function(e) {
|
|
var popup = e.target;
|
|
while(popup.hasChildNodes()) popup.removeChild(popup.lastChild);
|
|
|
|
var tab = _getTabObject(this.tabbrowser.selectedBrowser);
|
|
var translators = tab.page.translators;
|
|
for(var i=0, n=translators.length; i<n; i++) {
|
|
let translator = translators[i];
|
|
|
|
var menuitem = document.createElement("menuitem");
|
|
menuitem.setAttribute("label",
|
|
Zotero.getString("ingester.saveToZoteroUsing", translator.label));
|
|
menuitem.setAttribute("image", (translator.itemType === "multiple"
|
|
? "chrome://zotero/skin/treesource-collection.png"
|
|
: Zotero.ItemTypes.getImageSrc(translator.itemType)));
|
|
menuitem.setAttribute("class", "menuitem-iconic");
|
|
menuitem.addEventListener("command", function(e) {
|
|
scrapeThisPage(translator);
|
|
}, false);
|
|
popup.appendChild(menuitem);
|
|
}
|
|
|
|
popup.appendChild(document.createElement("menuseparator"));
|
|
|
|
var menuitem = document.createElement("menuitem");
|
|
menuitem.setAttribute("label", Zotero.getString("locate.libraryLookup.label"));
|
|
menuitem.setAttribute("tooltiptext", Zotero.getString("locate.libraryLookup.tooltip"));
|
|
menuitem.setAttribute("image", "chrome://zotero/skin/locate-library-lookup.png");
|
|
menuitem.setAttribute("class", "menuitem-iconic");
|
|
menuitem.addEventListener("command", _constructLookupFunction(tab, function(event, obj) {
|
|
var urls = [];
|
|
for each(var item in obj.newItems) {
|
|
var url = Zotero.OpenURL.resolve(item);
|
|
if(url) urls.push(url);
|
|
}
|
|
ZoteroPane.loadURI(urls, event);
|
|
}), false);
|
|
popup.appendChild(menuitem);
|
|
|
|
var locateEngines = Zotero.LocateManager.getVisibleEngines();
|
|
Zotero_LocateMenu.addLocateEngines(popup, locateEngines,
|
|
_constructLookupFunction(tab, function(e, obj) {
|
|
Zotero_LocateMenu.locateItem(e, obj.newItems);
|
|
}), true);
|
|
}
|
|
|
|
/**
|
|
* Translates using the specified translation instance. setTranslator() must already
|
|
* have been called
|
|
* @param {Zotero.Translate} translate
|
|
*/
|
|
this.performTranslation = function(translate, libraryID, collection) {
|
|
if (Zotero.locked) {
|
|
Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.scrapeError"));
|
|
var desc = Zotero.localeJoin([
|
|
Zotero.getString('general.operationInProgress'),
|
|
Zotero.getString('general.operationInProgress.waitUntilFinishedAndTryAgain')
|
|
]);
|
|
Zotero_Browser.progress.addDescription(desc);
|
|
Zotero_Browser.progress.show();
|
|
Zotero_Browser.progress.startCloseTimer(8000);
|
|
return;
|
|
}
|
|
|
|
if (!Zotero.stateCheck()) {
|
|
Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.scrapeError"));
|
|
var desc = Zotero.getString("ingester.scrapeErrorDescription.previousError")
|
|
+ ' ' + Zotero.getString("general.restartFirefoxAndTryAgain", Zotero.appName);
|
|
Zotero_Browser.progress.addDescription(desc);
|
|
Zotero_Browser.progress.show();
|
|
Zotero_Browser.progress.startCloseTimer(8000);
|
|
return;
|
|
}
|
|
|
|
Zotero_Browser.progress.show();
|
|
Zotero_Browser.isScraping = true;
|
|
|
|
// Get libraryID and collectionID
|
|
if(libraryID === undefined && ZoteroPane && !Zotero.isConnector) {
|
|
try {
|
|
if (!ZoteroPane.collectionsView.editable) {
|
|
Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.scrapeError"));
|
|
var desc = Zotero.getString('save.error.cannotMakeChangesToCollection');
|
|
Zotero_Browser.progress.addDescription(desc);
|
|
Zotero_Browser.progress.show();
|
|
Zotero_Browser.progress.startCloseTimer(8000);
|
|
return;
|
|
}
|
|
|
|
libraryID = ZoteroPane.getSelectedLibraryID();
|
|
collection = ZoteroPane.getSelectedCollection();
|
|
} catch(e) {}
|
|
}
|
|
|
|
if(Zotero.isConnector) {
|
|
Zotero.Connector.callMethod("getSelectedCollection", {}, function(response, status) {
|
|
if(status !== 200) {
|
|
Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.scraping"));
|
|
} else {
|
|
Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.scrapingTo"),
|
|
"chrome://zotero/skin/treesource-"+(response.id ? "collection" : "library")+".png",
|
|
response.name+"\u2026");
|
|
}
|
|
});
|
|
} else {
|
|
var name;
|
|
if(collection) {
|
|
name = collection.name;
|
|
} else if(libraryID) {
|
|
name = Zotero.Libraries.getName(libraryID);
|
|
} else {
|
|
name = Zotero.getString("pane.collections.library");
|
|
}
|
|
|
|
Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.scrapingTo"),
|
|
"chrome://zotero/skin/treesource-"+(collection ? "collection" : "library")+".png",
|
|
name+"\u2026");
|
|
}
|
|
|
|
translate.clearHandlers("done");
|
|
translate.clearHandlers("itemDone");
|
|
|
|
translate.setHandler("done", function(obj, returnValue) {
|
|
if(!returnValue) {
|
|
Zotero_Browser.progress.show();
|
|
Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.scrapeError"));
|
|
// Include link to Known Translator Issues page
|
|
var url = "http://www.zotero.org/documentation/known_translator_issues";
|
|
var linkText = '<a href="' + url + '" tooltiptext="' + url + '">'
|
|
+ Zotero.getString('ingester.scrapeErrorDescription.linkText') + '</a>';
|
|
Zotero_Browser.progress.addDescription(Zotero.getString("ingester.scrapeErrorDescription", linkText));
|
|
Zotero_Browser.progress.startCloseTimer(8000);
|
|
} else {
|
|
Zotero_Browser.progress.startCloseTimer();
|
|
}
|
|
Zotero_Browser.isScraping = false;
|
|
});
|
|
|
|
var attachmentsMap = new WeakMap();
|
|
|
|
translate.setHandler("itemDone", function(obj, dbItem, item) {
|
|
Zotero_Browser.progress.show();
|
|
var itemProgress = new Zotero_Browser.progress.ItemProgress(Zotero.ItemTypes.getImageSrc(item.itemType),
|
|
item.title);
|
|
itemProgress.setProgress(100);
|
|
for(var i=0; i<item.attachments.length; i++) {
|
|
var attachment = item.attachments[i];
|
|
attachmentsMap.set(attachment,
|
|
new Zotero_Browser.progress.ItemProgress(
|
|
Zotero.Utilities.determineAttachmentIcon(attachment),
|
|
attachment.title, itemProgress));
|
|
}
|
|
|
|
// add item to collection, if one was specified
|
|
if(collection) {
|
|
collection.addItem(dbItem.id);
|
|
}
|
|
});
|
|
|
|
translate.setHandler("attachmentProgress", function(obj, attachment, progress, error) {
|
|
var itemProgress = attachmentsMap.get(attachment);
|
|
if(progress === false) {
|
|
itemProgress.setError();
|
|
} else {
|
|
itemProgress.setProgress(progress);
|
|
if(progress === 100) {
|
|
itemProgress.setIcon(Zotero.Utilities.determineAttachmentIcon(attachment));
|
|
}
|
|
}
|
|
});
|
|
|
|
translate.translate(libraryID);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Private Zotero_Browser methods
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
function _constructLookupFunction(tab, success) {
|
|
return function(e) {
|
|
tab.page.translate.setTranslator(tab.page.translators[0]);
|
|
tab.page.translate.clearHandlers("done");
|
|
tab.page.translate.clearHandlers("itemDone");
|
|
tab.page.translate.setHandler("done", function(obj, status) {
|
|
if(status) {
|
|
success(e, obj);
|
|
Zotero_Browser.progress.close();
|
|
} else {
|
|
Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.lookup.error"));
|
|
Zotero_Browser.progress.startCloseTimer(8000);
|
|
}
|
|
});
|
|
|
|
Zotero_Browser.progress.show();
|
|
Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.lookup.performing"));
|
|
tab.page.translate.translate(false);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Gets a data object given a browser window object
|
|
*/
|
|
function _getTabObject(browser) {
|
|
if(!browser) return false;
|
|
if(!browser.zoteroBrowserData) {
|
|
browser.zoteroBrowserData = new Zotero_Browser.Tab(browser);
|
|
}
|
|
return browser.zoteroBrowserData;
|
|
}
|
|
|
|
/**
|
|
* Adds an annotation
|
|
*/
|
|
function _add(type, e) {
|
|
var tab = _getTabObject(Zotero_Browser.tabbrowser.selectedBrowser);
|
|
|
|
if(type == "annotation") {
|
|
// ignore click if it's on an existing annotation
|
|
if(e.target.getAttribute("zotero-annotation")) return;
|
|
|
|
var annotation = tab.page.annotations.createAnnotation();
|
|
annotation.initWithEvent(e);
|
|
|
|
// disable add mode, now that we've used it
|
|
toggleMode();
|
|
} else {
|
|
try {
|
|
var selection = Zotero_Browser.tabbrowser.selectedBrowser.contentWindow.getSelection();
|
|
} catch(err) {
|
|
return;
|
|
}
|
|
if(selection.isCollapsed) return;
|
|
|
|
if(type == "highlight") {
|
|
tab.page.annotations.highlight(selection.getRangeAt(0));
|
|
} else if(type == "unhighlight") {
|
|
tab.page.annotations.unhighlight(selection.getRangeAt(0));
|
|
}
|
|
|
|
selection.removeAllRanges();
|
|
}
|
|
|
|
// stop propagation
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Zotero_Browser.Tab
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
Zotero_Browser.Tab = function(browser) {
|
|
this.browser = browser;
|
|
this.page = new Object();
|
|
}
|
|
|
|
/*
|
|
* clears page-specific information
|
|
*/
|
|
Zotero_Browser.Tab.prototype.clear = function() {
|
|
delete this.page;
|
|
this.page = new Object();
|
|
}
|
|
|
|
/*
|
|
* detects translators for this browser object
|
|
*/
|
|
Zotero_Browser.Tab.prototype.detectTranslators = function(rootDoc, doc) {
|
|
if(doc instanceof HTMLDocument && doc.documentURI.substr(0, 6) != "about:") {
|
|
// get translators
|
|
var me = this;
|
|
|
|
var translate = new Zotero.Translate.Web();
|
|
translate.setDocument(doc);
|
|
translate.setHandler("translators", function(obj, item) { me._translatorsAvailable(obj, item) });
|
|
translate.setHandler("pageModified", function(translate, doc) { Zotero_Browser.itemUpdated(doc) });
|
|
translate.getTranslators(true);
|
|
} else if(doc.documentURI.substr(0, 7) == "file://") {
|
|
this._attemptLocalFileImport(doc);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* searches for a document in all of the frames of a given document
|
|
*/
|
|
Zotero_Browser.Tab.prototype._searchFrames = function(rootDoc, searchDoc) {
|
|
if(rootDoc == searchDoc) return true;
|
|
var frames = rootDoc.getElementsByTagName("frame");
|
|
for each(var frame in frames) {
|
|
if(frame.contentDocument &&
|
|
(frame.contentDocument == searchDoc ||
|
|
this._searchFrames(frame.contentDocument, searchDoc))) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
var frames = rootDoc.getElementsByTagName("iframe");
|
|
for each(var frame in frames) {
|
|
if(frame.contentDocument &&
|
|
(frame.contentDocument == searchDoc ||
|
|
this._searchFrames(frame.contentDocument, searchDoc))) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Attempts import of a file; to be run on local files only
|
|
*/
|
|
Zotero_Browser.Tab.prototype._attemptLocalFileImport = function(doc) {
|
|
if(doc.documentURI.match(/\.csl(\.xml|\.txt)?$/i)) {
|
|
// read CSL string
|
|
var csl = Zotero.File.getContentsFromURL(doc.documentURI);
|
|
if(csl.indexOf("http://purl.org/net/xbiblio/csl") != -1) {
|
|
// looks like a CSL; try to import
|
|
Zotero.Styles.install(csl, doc.documentURI);
|
|
}
|
|
} else {
|
|
// see if we can import this file
|
|
var file = Components.classes["@mozilla.org/network/protocol;1?name=file"]
|
|
.getService(Components.interfaces.nsIFileProtocolHandler)
|
|
.getFileFromURLSpec(doc.documentURI);
|
|
|
|
var me = this;
|
|
var translate = new Zotero.Translate.Import();
|
|
translate.setLocation(file);
|
|
translate.setHandler("translators", function(obj, item) { me._translatorsAvailable(obj, item) });
|
|
translate.getTranslators();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* returns the URL of the image representing the translator to be called on the
|
|
* current page, or false if the page cannot be scraped
|
|
*/
|
|
Zotero_Browser.Tab.prototype.getCaptureIcon = function() {
|
|
if(this.page.translators && this.page.translators.length) {
|
|
var itemType = this.page.translators[0].itemType;
|
|
return (itemType === "multiple"
|
|
? "chrome://zotero/skin/treesource-collection.png"
|
|
: Zotero.ItemTypes.getImageSrc(itemType));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
Zotero_Browser.Tab.prototype.getCaptureTooltip = function() {
|
|
if (this.page.translators && this.page.translators.length) {
|
|
var arr = [Zotero.getString('ingester.saveToZotero')];
|
|
if (this.page.translators[0].itemType == 'multiple') {
|
|
arr.push('...');
|
|
}
|
|
arr.push (' ' , '(' + this.page.translators[0].label + ')');
|
|
return Zotero.localeJoin(arr, '');
|
|
}
|
|
return '';
|
|
}
|
|
|
|
|
|
/**********CALLBACKS**********/
|
|
|
|
/*
|
|
* called when a user is supposed to select items
|
|
*/
|
|
Zotero_Browser.Tab.prototype._selectItems = function(obj, itemList, callback) {
|
|
// this is kinda ugly, mozillazine made me do it! honest!
|
|
var io = { dataIn:itemList, dataOut:null }
|
|
var newDialog = window.openDialog("chrome://zotero/content/ingester/selectitems.xul",
|
|
"_blank","chrome,modal,centerscreen,resizable=yes", io);
|
|
|
|
if(!io.dataOut) { // user selected no items, so close the progress indicatior
|
|
Zotero_Browser.progress.close();
|
|
}
|
|
|
|
callback(io.dataOut);
|
|
}
|
|
|
|
/*
|
|
* called when translators are available
|
|
*/
|
|
Zotero_Browser.Tab.prototype._translatorsAvailable = function(translate, translators) {
|
|
if(translators && translators.length) {
|
|
//see if we should keep the previous set of translators
|
|
if(//we already have a translator for part of this page
|
|
this.page.translators && this.page.translators.length && this.page.document.location
|
|
//and the page is still there
|
|
&& this.page.document.defaultView && !this.page.document.defaultView.closed
|
|
//this set of translators is not targeting the same URL as a previous set of translators,
|
|
// because otherwise we want to use the newer set
|
|
&& this.page.document.location.href != translate.document.location.href
|
|
//the best translator we had was of higher priority than the new set
|
|
&& (this.page.translators[0].priority < translators[0].priority
|
|
//or the priority was the same, but...
|
|
|| (this.page.translators[0].priority == translators[0].priority
|
|
//the previous set of translators targets the top frame or the current one does not either
|
|
&& (this.page.document.defaultView == this.page.document.defaultView.top
|
|
|| translate.document.defaultView !== this.page.document.defaultView.top)
|
|
))
|
|
) {
|
|
return; //keep what we had
|
|
} else {
|
|
this.clear(); //clear URL bar icon
|
|
}
|
|
|
|
this.page.translate = translate;
|
|
this.page.translators = translators;
|
|
this.page.document = translate.document;
|
|
|
|
this.page.translate.clearHandlers("select");
|
|
this.page.translate.setHandler("select", this._selectItems);
|
|
} else if(translate.type != "import" && translate.document.documentURI.length > 7
|
|
&& translate.document.documentURI.substr(0, 7) == "file://") {
|
|
this._attemptLocalFileImport(translate.document);
|
|
}
|
|
|
|
Zotero_Browser.updateStatus();
|
|
}
|
|
|
|
Zotero_Browser.init(); |