zotero/chrome/content/zotero/browser.js

843 lines
26 KiB
JavaScript
Raw Normal View History

2007-10-23 07:11:59 +00:00
/*
***** BEGIN LICENSE BLOCK *****
2009-12-28 09:47:49 +00:00
Copyright © 2009 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
2007-10-23 07:11:59 +00:00
2009-12-28 09:47:49 +00:00
This file is part of Zotero.
2007-10-23 07:11:59 +00:00
2009-12-28 09:47:49 +00:00
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
2009-12-28 09:47:49 +00:00
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
2007-10-23 07:11:59 +00:00
2009-12-28 09:47:49 +00:00
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.
2009-12-28 09:47:49 +00:00
You should have received a copy of the GNU Affero General Public License
2009-12-28 09:47:49 +00:00
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
Based on code from Greasemonkey and PiggyBank
2007-10-23 07:11:59 +00:00
***** 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;
2007-10-23 07:11:59 +00:00
this.chromeLoad = chromeLoad;
this.contentLoad = contentLoad;
this.itemUpdated = itemUpdated;
2007-10-23 07:11:59 +00:00
this.contentHide = contentHide;
this.tabClose = tabClose;
this.resize = resize;
this.updateStatus = updateStatus;
this.tabbrowser = null;
this.appcontent = null;
this.statusImage = null;
this.isScraping = false;
2007-10-23 07:11:59 +00:00
var _browserData = new Object();
var _attachmentsMap = new WeakMap();
2007-10-23 07:11:59 +00:00
var _blacklist = [
"googlesyndication.com",
"doubleclick.net",
"questionmarket.com",
"atdmt.com",
2009-04-22 00:36:29 +00:00
"aggregateknowledge.com",
"ad.yieldmanager.com"
2007-10-23 07:11:59 +00:00
];
2009-08-11 02:26:47 +00:00
var _locationBlacklist = [
"zotero://debug/"
];
2007-10-23 07:11:59 +00:00
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
2007-10-23 07:11:59 +00:00
*/
function init() {
if (!Zotero || !Zotero.initialized || !window.hasOwnProperty("gBrowser")) {
return;
}
2007-10-23 07:11:59 +00:00
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();
2007-10-23 07:11:59 +00:00
}
2.0b3 megacommit - Support for group libraries - General support for multiple libraries of different types - Streamlined sync support - Using solely libraryID and key rather than itemID, and removed all itemID-changing code - Combined two requests for increased performance and decreased server load - Added warning on user account change - Provide explicit error message on SSL failure - Removed snapshot and link toolbar buttons and changed browser context menu options and drags to create parent items + snapshots - Closes #786, Add numPages field - Fixes #1063, Duplicate item with tags broken in Sync Preview - Added better purging of deleted tags - Added local user key before first sync - Add clientDateModified to all objects for more flexibility in syncing - Added new triples-based Relation object type, currently used to store links between items copied between local and group libraries - Updated zotero.org translator for groups - Additional trigger-based consistency checks - Fixed broken URL drag in Firefox 3.5 - Disabled zeroconf menu option (no longer functional) Developer-specific changes: - Overhauled data layer - Data object constructors no longer take arguments (return to 1.0-like API) - Existing objects can be retrieved by setting id or library/key properties - id/library/key must be set for new objects before other fields - New methods: - ZoteroPane.getSelectedLibraryID() - ZoteroPane.getSelectedGroup(asID) - ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot) - ZoteroPane.addItemFromURL(url, itemType) - ZoteroPane.canEdit() - Zotero.CollectionTreeView.selectLibrary(libraryID) - New Zotero.URI methods - Changed methods - Many data object methods now take a libraryID - ZoteroPane.addAttachmentFromPage(link, itemID) - Removed saveItem and saveAttachments parameters from Zotero.Translate constructor - translate() now takes a libraryID, null for local library, or false to not save items (previously on constructor) - saveAttachments is now a translate() parameter - Zotero.flattenArguments() better handles passed objects - Zotero.File.getFileHash() (not currently used)
2009-05-14 18:23:40 +00:00
/**
* Scrapes a page (called when the capture icon is clicked
2.0b3 megacommit - Support for group libraries - General support for multiple libraries of different types - Streamlined sync support - Using solely libraryID and key rather than itemID, and removed all itemID-changing code - Combined two requests for increased performance and decreased server load - Added warning on user account change - Provide explicit error message on SSL failure - Removed snapshot and link toolbar buttons and changed browser context menu options and drags to create parent items + snapshots - Closes #786, Add numPages field - Fixes #1063, Duplicate item with tags broken in Sync Preview - Added better purging of deleted tags - Added local user key before first sync - Add clientDateModified to all objects for more flexibility in syncing - Added new triples-based Relation object type, currently used to store links between items copied between local and group libraries - Updated zotero.org translator for groups - Additional trigger-based consistency checks - Fixed broken URL drag in Firefox 3.5 - Disabled zeroconf menu option (no longer functional) Developer-specific changes: - Overhauled data layer - Data object constructors no longer take arguments (return to 1.0-like API) - Existing objects can be retrieved by setting id or library/key properties - id/library/key must be set for new objects before other fields - New methods: - ZoteroPane.getSelectedLibraryID() - ZoteroPane.getSelectedGroup(asID) - ZoteroPane.addItemFromDocument(doc, itemType, saveSnapshot) - ZoteroPane.addItemFromURL(url, itemType) - ZoteroPane.canEdit() - Zotero.CollectionTreeView.selectLibrary(libraryID) - New Zotero.URI methods - Changed methods - Many data object methods now take a libraryID - ZoteroPane.addAttachmentFromPage(link, itemID) - Removed saveItem and saveAttachments parameters from Zotero.Translate constructor - translate() now takes a libraryID, null for local library, or false to not save items (previously on constructor) - saveAttachments is now a translate() parameter - Zotero.flattenArguments() better handles passed objects - Zotero.File.getFileHash() (not currently used)
2009-05-14 18:23:40 +00:00
* @return void
2007-10-23 07:11:59 +00:00
*/
function scrapeThisPage(translator) {
2012-06-26 23:40:33 +00:00
// 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);
}
2007-10-23 07:11:59 +00:00
}
/*
* 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() {
2007-10-23 07:11:59 +00:00
var tab = _getTabObject(Zotero_Browser.tabbrowser.selectedBrowser);
tab.page.annotations.toggleCollapsed();
2007-10-23 07:11:59 +00:00
}
/*
* When chrome loads, register our event handlers with the appropriate interfaces
*/
function chromeLoad() {
2010-11-04 01:30:59 +00:00
this.tabbrowser = gBrowser;
2007-10-23 07:11:59 +00:00
this.appcontent = document.getElementById("appcontent");
this.statusImage = document.getElementById("zotero-status-image");
// this gives us onLocationChange, for updating when tabs are switched/created
2010-11-04 01:30:59 +00:00
gBrowser.tabContainer.addEventListener("TabClose",
2007-10-23 07:11:59 +00:00
function(e) {
//Zotero.debug("TabClose");
Zotero_Browser.tabClose(e);
}, false);
2010-11-04 01:30:59 +00:00
gBrowser.tabContainer.addEventListener("TabSelect",
2007-10-23 07:11:59 +00:00
function(e) {
2010-11-04 01:31:30 +00:00
//Zotero.debug("TabSelect");
2007-10-23 07:11:59 +00:00
Zotero_Browser.updateStatus();
}, false);
// this is for pageshow, for updating the status of the book icon
this.appcontent.addEventListener("pageshow", contentLoad, true);
2007-10-23 07:11:59 +00:00
// 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
Initial Zotero 1.5 Megacommit Apologies for the massive (and, due to data_access.js splitting, difficult-to-follow) commit. Please note that external code that accesses the data layer may need to be tweaked for compatibility. Here's a comprehensive-as-possible changelog: - Added server sync functionality (incomplete) - Overhaul of data layer - Split data_access.js into separate files (item.js, items.js, creator.js, etc.) - Made creators and collections first-class objects, similar to items - Constructors now take id as first parameter, e.g. new Zotero.Item(1234, 'book'), to allow explicit id setting and id changing - Made various data layer operations (including attachment fields) require a save() rather than making direct DB changes - Better handling of unsaved objects - Item.setCreator() now takes creator objects instead of creator ids, and Item.save() will auto-save unsaved creators - clone() now works on unsaved objects - Newly created object instances are now disabled after save() to force refetch of globally accessible instance using Zotero.(Items|Creators|etc.).get() - Added secondary lookup key to data objects - Deprecated getID() and getItemType() methods in favor of .id and .itemTypeID properties - toArray() deprecated in favor of serialize(), which has a somewhat modified format - Added support for multiple creators with identical data -- currently unimplemented in interface and most of data layer - Added Item.diff() for comparing item metadata - Database changes - Added SQLite triggers to enforce foreign key constraints - Added Zotero.DB.transactionVacuum flag to run a VACUUM after a transaction - Added Zotero.DB.transactionDate, .transactionDateTime, and transactionTimestamp to retrieve consistent timestamps for entire transaction - Properly store 64-bit integers - Set PRAGMA locking_mode=EXCLUSIVE on database - Set SQLite page size to 4096 on new databases - Set SQLite page cache to 8MB - Do some database cleanup and integrity checking on migration from 1.0 branch - Removed IF NOT EXISTS from userdata.sql CREATE statements -- userdata.sql is now processed only on DB initialization - Removed itemNoteTitles table and moved titles into itemNotes - Abstracted metadata edit box and note box into flexible XBL bindings with various modes, including read-only states - Massive speed-up of item tree view - Several fixes from 1.0 branch for Fx3 compatibility - Added Notifier observer to log delete events for syncing - Zotero.Utilities changes - New methods getSQLDataType() and md5() - Removed onError from Zotero.Utilities.HTTP.doGet() - Don't display more than 1024 characters in doPost() debug output - Don't display passwords in doPost() debug output - Added Zotero.Notifier.untrigger() -- currently unused - Added Zotero.reloadDataObjects() to reset all in-memory objects - Added |chars| parameter to Zotero.randomString(len, chars) - Added Zotero.Date.getUnixTimestamp() and Date.toUnixTimestamp(JSDate) - Adjusted zotero-service.js to simplify file inclusion Various things (such as tags) are temporarily broken.
2008-05-04 08:32:48 +00:00
// 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');
}
2010-03-28 07:21:17 +00:00
if(reduce) reduce.addEventListener("command",
2007-10-23 07:11:59 +00:00
function(e) { Zotero_Browser.resize(e) }, false);
2010-03-28 07:21:17 +00:00
if(enlarge) enlarge.addEventListener("command",
2007-10-23 07:11:59 +00:00
function(e) { Zotero_Browser.resize(e) }, false);
2010-03-28 07:21:17 +00:00
if(reset) reset.addEventListener("command",
2007-10-23 07:11:59 +00:00
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;
2007-10-23 07:11:59 +00:00
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) {}
}
2009-08-11 02:26:47 +00:00
try {
if (_locationBlacklist.indexOf(doc.location.href) != -1) {
return;
}
// Ignore TinyMCE popups
if (!doc.location.host && doc.location.href.indexOf("tinymce/") != -1) {
return;
}
2009-08-11 02:26:47 +00:00
}
catch (e) {}
2007-10-23 07:11:59 +00:00
// 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) {
2007-10-23 07:11:59 +00:00
// 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();
2007-10-23 07:11:59 +00:00
}
}
}
// 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;
}
}
2007-10-23 07:11:59 +00:00
}
/*
* 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);
2007-10-23 07:11:59 +00:00
}
}
/*
* 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();
2007-10-23 07:11:59 +00:00
}
/*
* 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;
2011-10-03 04:44:40 +00:00
Zotero_Browser.statusImage.addEventListener("load", function() {
document.getElementById("zotero-status-image-guidance").show();
}, false);
2007-10-23 07:11:59 +00:00
} else {
Zotero_Browser.statusImage.hidden = true;
}
// set annotation bar status
if(tab.page.annotations && tab.page.annotations.annotations.length) {
2007-10-23 07:11:59 +00:00
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);
}
2012-06-26 23:40:33 +00:00
/**
* 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();
2012-07-05 21:54:38 +00:00
collection = ZoteroPane.getSelectedCollection();
2012-06-26 23:40:33 +00:00
} 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.clearHandlers("attachmentProgress");
2012-06-26 23:40:33 +00:00
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;
});
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,
2012-06-26 23:40:33 +00:00
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);
2012-06-26 23:40:33 +00:00
if(progress === false) {
itemProgress.setError();
} else {
itemProgress.setProgress(progress);
if(progress === 100) {
itemProgress.setIcon(Zotero.Utilities.determineAttachmentIcon(attachment));
}
}
});
translate.translate(libraryID);
}
2007-10-23 07:11:59 +00:00
//////////////////////////////////////////////////////////////////////////////
//
// 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);
}
}
2007-10-23 07:11:59 +00:00
/*
* 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);
2007-10-23 07:11:59 +00:00
}
return browser.zoteroBrowserData;
2007-10-23 07:11:59 +00:00
}
/**
* Adds an annotation
2007-10-23 07:11:59 +00:00
*/
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));
2007-10-23 07:11:59 +00:00
} 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) {
2008-09-11 19:40:38 +00:00
if(doc instanceof HTMLDocument && doc.documentURI.substr(0, 6) != "about:") {
2007-10-23 07:11:59 +00:00
// get translators
var me = this;
var translate = new Zotero.Translate.Web();
2007-10-23 07:11:59 +00:00
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);
2008-09-11 19:40:38 +00:00
} else if(doc.documentURI.substr(0, 7) == "file://") {
2007-10-23 07:11:59 +00:00
this._attemptLocalFileImport(doc);
}
}
/*
* searches for a document in all of the frames of a given document
*/
Zotero_Browser.Tab.prototype._searchFrames = function(rootDoc, searchDoc) {
2009-01-12 07:31:36 +00:00
if(rootDoc == searchDoc) return true;
2007-10-23 07:11:59 +00:00
var frames = rootDoc.getElementsByTagName("frame");
for each(var frame in frames) {
if(frame.contentDocument &&
2009-05-05 00:02:18 +00:00
(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))) {
2007-10-23 07:11:59 +00:00
return true;
}
}
return false;
}
/*
* Attempts import of a file; to be run on local files only
*/
Zotero_Browser.Tab.prototype._attemptLocalFileImport = function(doc) {
2011-03-23 21:29:19 +00:00
if(doc.documentURI.match(/\.csl(\.xml|\.txt)?$/i)) {
2007-12-02 05:45:07 +00:00
// 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);
2007-12-02 05:45:07 +00:00
}
} 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();
2007-12-02 05:45:07 +00:00
translate.setLocation(file);
translate.setHandler("translators", function(obj, item) { me._translatorsAvailable(obj, item) });
translate.getTranslators();
}
2007-10-23 07:11:59 +00:00
}
/*
* 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));
2007-10-23 07:11:59 +00:00
}
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) {
2007-10-23 07:11:59 +00:00
// 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);
2007-10-23 07:11:59 +00:00
}
/*
* 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
}
2007-10-23 07:11:59 +00:00
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);
2007-10-23 07:11:59 +00:00
} else if(translate.type != "import" && translate.document.documentURI.length > 7
&& translate.document.documentURI.substr(0, 7) == "file://") {
this._attemptLocalFileImport(translate.document);
}
2007-10-23 07:11:59 +00:00
Zotero_Browser.updateStatus();
}
Zotero_Browser.init();