Merge branch 'attachment-progress'
This commit is contained in:
commit
d26bb24849
11 changed files with 583 additions and 266 deletions
|
@ -50,8 +50,6 @@ var Zotero_Browser = new function() {
|
||||||
this.tabClose = tabClose;
|
this.tabClose = tabClose;
|
||||||
this.resize = resize;
|
this.resize = resize;
|
||||||
this.updateStatus = updateStatus;
|
this.updateStatus = updateStatus;
|
||||||
this.finishScraping = finishScraping;
|
|
||||||
this.itemDone = itemDone;
|
|
||||||
|
|
||||||
this.tabbrowser = null;
|
this.tabbrowser = null;
|
||||||
this.appcontent = null;
|
this.appcontent = null;
|
||||||
|
@ -447,51 +445,6 @@ var Zotero_Browser = new function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Callback to be executed when scraping is complete
|
|
||||||
*/
|
|
||||||
function finishScraping(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Callback to be executed when an item has been finished
|
|
||||||
*/
|
|
||||||
function itemDone(obj, dbItem, item, collection) {
|
|
||||||
var title = item.title;
|
|
||||||
var icon = Zotero.ItemTypes.getImageSrc(item.itemType);
|
|
||||||
Zotero_Browser.progress.show();
|
|
||||||
Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.scraping"));
|
|
||||||
Zotero_Browser.progress.addLines([title], [icon]);
|
|
||||||
|
|
||||||
// add item to collection, if one was specified
|
|
||||||
if(collection) {
|
|
||||||
collection.addItem(dbItem.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Zotero_Browser.isScraping) {
|
|
||||||
// initialize close timer between item saves in case translator doesn't call done
|
|
||||||
Zotero_Browser.progress.startCloseTimer(10000); // is this long enough?
|
|
||||||
} else {
|
|
||||||
// if we aren't supposed to be scraping now, the translator is broken; assume we're
|
|
||||||
// done
|
|
||||||
Zotero_Browser.progress.startCloseTimer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when status bar icon is right-clicked
|
* Called when status bar icon is right-clicked
|
||||||
*/
|
*/
|
||||||
|
@ -725,6 +678,28 @@ Zotero_Browser.Tab.prototype.translate = function(libraryID, collectionID, trans
|
||||||
var collection = false;
|
var collection = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Zotero.isConnector) {
|
||||||
|
Zotero.Connector.callMethod("getSelectedCollection", {}, function(response, status) {
|
||||||
|
if(status !== 200) return;
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
// use first translator available
|
// use first translator available
|
||||||
|
@ -733,8 +708,54 @@ Zotero_Browser.Tab.prototype.translate = function(libraryID, collectionID, trans
|
||||||
this.page.translate.clearHandlers("done");
|
this.page.translate.clearHandlers("done");
|
||||||
this.page.translate.clearHandlers("itemDone");
|
this.page.translate.clearHandlers("itemDone");
|
||||||
|
|
||||||
this.page.translate.setHandler("done", function(obj, item) { Zotero_Browser.finishScraping(obj, item) });
|
this.page.translate.setHandler("done", function(obj, returnValue) {
|
||||||
this.page.translate.setHandler("itemDone", function(obj, dbItem, item) { Zotero_Browser.itemDone(obj, dbItem, item, collection) });
|
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();
|
||||||
|
|
||||||
|
this.page.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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.page.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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.page.translate.translate(libraryID);
|
this.page.translate.translate(libraryID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
windowtype="alert:alert">
|
windowtype="alert:alert">
|
||||||
|
|
||||||
<hbox id="zotero-progress-box">
|
<hbox id="zotero-progress-box">
|
||||||
<vbox id="zotero-progress-text-box">
|
<vbox id="zotero-progress-text-box" flex="1">
|
||||||
<label id="zotero-progress-text-headline"/>
|
<hbox id="zotero-progress-text-headline" pack="start"/>
|
||||||
</vbox>
|
</vbox>
|
||||||
</hbox>
|
</hbox>
|
||||||
</window>
|
</window>
|
||||||
|
|
|
@ -220,6 +220,7 @@ Zotero.Attachments = new function(){
|
||||||
var urlRe = /^https?:\/\/[^\s]*$/;
|
var urlRe = /^https?:\/\/[^\s]*$/;
|
||||||
var matches = urlRe.exec(url);
|
var matches = urlRe.exec(url);
|
||||||
if (!matches) {
|
if (!matches) {
|
||||||
|
if(callback) callback(false);
|
||||||
throw ("Invalid URL '" + url + "' in Zotero.Attachments.importFromURL()");
|
throw ("Invalid URL '" + url + "' in Zotero.Attachments.importFromURL()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,9 +298,11 @@ Zotero.Attachments = new function(){
|
||||||
|
|
||||||
if (mimeType == 'application/pdf' &&
|
if (mimeType == 'application/pdf' &&
|
||||||
Zotero.MIME.sniffForMIMEType(str) != 'application/pdf') {
|
Zotero.MIME.sniffForMIMEType(str) != 'application/pdf') {
|
||||||
Zotero.debug("Downloaded PDF did not have MIME type "
|
var errString = "Downloaded PDF did not have MIME type "
|
||||||
+ "'application/pdf' in Attachments.importFromURL()", 2);
|
+ "'application/pdf' in Attachments.importFromURL()";
|
||||||
|
Zotero.debug(errString, 2);
|
||||||
attachmentItem.erase();
|
attachmentItem.erase();
|
||||||
|
if(callback) callback(false, new Error(errString));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,6 +315,8 @@ Zotero.Attachments = new function(){
|
||||||
Zotero.Notifier.trigger('add', 'item', itemID);
|
Zotero.Notifier.trigger('add', 'item', itemID);
|
||||||
Zotero.Notifier.trigger('modify', 'item', sourceItemID);
|
Zotero.Notifier.trigger('modify', 'item', sourceItemID);
|
||||||
|
|
||||||
|
if(callback) callback(attachmentItem);
|
||||||
|
|
||||||
// We don't have any way of knowing that the file
|
// We don't have any way of knowing that the file
|
||||||
// is flushed to disk, so we just wait a second
|
// is flushed to disk, so we just wait a second
|
||||||
// and hope for the best -- we'll index it later
|
// and hope for the best -- we'll index it later
|
||||||
|
@ -325,6 +330,7 @@ Zotero.Attachments = new function(){
|
||||||
catch (e) {
|
catch (e) {
|
||||||
// Clean up
|
// Clean up
|
||||||
attachmentItem.erase();
|
attachmentItem.erase();
|
||||||
|
if(callback) callback(false, e);
|
||||||
|
|
||||||
throw (e);
|
throw (e);
|
||||||
}
|
}
|
||||||
|
@ -346,8 +352,6 @@ Zotero.Attachments = new function(){
|
||||||
nsIURL.spec = url;
|
nsIURL.spec = url;
|
||||||
wbp.saveURI(nsIURL, null, null, null, null, file);
|
wbp.saveURI(nsIURL, null, null, null, null, file);
|
||||||
|
|
||||||
if(callback) callback(attachmentItem);
|
|
||||||
|
|
||||||
return attachmentItem;
|
return attachmentItem;
|
||||||
}
|
}
|
||||||
catch (e){
|
catch (e){
|
||||||
|
@ -553,7 +557,7 @@ Zotero.Attachments = new function(){
|
||||||
Zotero.Fulltext.indexDocument(document, itemID);
|
Zotero.Fulltext.indexDocument(document, itemID);
|
||||||
Zotero.Notifier.trigger('refresh', 'item', itemID);
|
Zotero.Notifier.trigger('refresh', 'item', itemID);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
callback(attachmentItem);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -612,6 +616,7 @@ Zotero.Attachments = new function(){
|
||||||
// Clean up
|
// Clean up
|
||||||
var item = Zotero.Items.get(itemID);
|
var item = Zotero.Items.get(itemID);
|
||||||
item.erase();
|
item.erase();
|
||||||
|
if(callback) callback(false, e);
|
||||||
|
|
||||||
throw (e);
|
throw (e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ Zotero.Translate.ItemSaver.prototype = {
|
||||||
if(typedArraysSupported) {
|
if(typedArraysSupported) {
|
||||||
// Get rid of attachments that we won't be able to save properly and add ids
|
// Get rid of attachments that we won't be able to save properly and add ids
|
||||||
for(var j=0; j<item.attachments.length; j++) {
|
for(var j=0; j<item.attachments.length; j++) {
|
||||||
if(!item.attachments[j].url || item.attachments[j].mimeType === "text/html") {
|
if(item.attachments[j].url && item.attachments[j].mimeType !== "text/html") {
|
||||||
item.attachments.splice(j--, 1);
|
item.attachments.splice(j--, 1);
|
||||||
} else {
|
} else {
|
||||||
item.attachments[j].id = Zotero.Utilities.randomString();
|
item.attachments[j].id = Zotero.Utilities.randomString();
|
||||||
|
|
|
@ -107,30 +107,22 @@ Zotero.ProgressWindowSet = new function() {
|
||||||
* Pass the active window into the constructor
|
* Pass the active window into the constructor
|
||||||
*/
|
*/
|
||||||
Zotero.ProgressWindow = function(_window){
|
Zotero.ProgressWindow = function(_window){
|
||||||
this.show = show;
|
var self = this,
|
||||||
this.changeHeadline = changeHeadline;
|
_window = null,
|
||||||
this.addLines = addLines;
|
_progressWindow = null,
|
||||||
this.addDescription = addDescription;
|
_windowLoaded = false,
|
||||||
this.startCloseTimer = startCloseTimer;
|
_windowLoading = false,
|
||||||
this.close = close;
|
_timeoutID = false,
|
||||||
|
_closing = false,
|
||||||
|
_mouseWasOver = false,
|
||||||
|
_deferredUntilWindowLoad = [],
|
||||||
|
_deferredUntilWindowLoadThis = [],
|
||||||
|
_deferredUntilWindowLoadArgs = [];
|
||||||
|
|
||||||
var _window = null;
|
/**
|
||||||
|
* Shows the progress window
|
||||||
var _progressWindow = null;
|
*/
|
||||||
var _windowLoaded = false;
|
this.show = function show() {
|
||||||
var _windowLoading = false;
|
|
||||||
var _timeoutID = false;
|
|
||||||
var _mouseWasOver = false
|
|
||||||
|
|
||||||
// keep track of all of these things in case they're called before we're
|
|
||||||
// done loading the progress window
|
|
||||||
var _loadHeadline = '';
|
|
||||||
var _loadLines = [];
|
|
||||||
var _loadIcons = [];
|
|
||||||
var _loadDescription = null;
|
|
||||||
|
|
||||||
|
|
||||||
function show() {
|
|
||||||
if(_windowLoading || _windowLoaded) { // already loading or loaded
|
if(_windowLoading || _windowLoaded) { // already loading or loaded
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -164,57 +156,54 @@ Zotero.ProgressWindow = function(_window){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeHeadline(headline) {
|
/**
|
||||||
if(_windowLoaded) {
|
* Changes the "headline" shown at the top of the progress window
|
||||||
_progressWindow.document.getElementById("zotero-progress-text-headline").value = headline;
|
*/
|
||||||
} else {
|
this.changeHeadline = _deferUntilWindowLoad(function changeHeadline(text, icon, postText) {
|
||||||
_loadHeadline = headline;
|
var doc = _progressWindow.document,
|
||||||
}
|
headline = doc.getElementById("zotero-progress-text-headline");
|
||||||
|
while(headline.hasChildNodes()) headline.removeChild(headline.firstChild);
|
||||||
|
|
||||||
|
var preNode = doc.createElement("label");
|
||||||
|
preNode.setAttribute("value", text);
|
||||||
|
preNode.setAttribute("crop", "end");
|
||||||
|
headline.appendChild(preNode);
|
||||||
|
|
||||||
|
if(icon) {
|
||||||
|
var img = doc.createElement("image");
|
||||||
|
img.width = 16;
|
||||||
|
img.height = 16;
|
||||||
|
img.setAttribute("src", icon);
|
||||||
|
headline.appendChild(img);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addLines(labels, icons) {
|
if(postText) {
|
||||||
if(_windowLoaded) {
|
var postNode = doc.createElement("label");
|
||||||
|
postNode.style.marginLeft = 0;
|
||||||
|
postNode.setAttribute("value", " "+postText);
|
||||||
|
postNode.setAttribute("crop", "end");
|
||||||
|
postNode.setAttribute("flex", "1");
|
||||||
|
headline.appendChild(postNode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a line to the progress window with the specified icon
|
||||||
|
*/
|
||||||
|
this.addLines = _deferUntilWindowLoad(function addLines(labels, icons) {
|
||||||
for (var i in labels) {
|
for (var i in labels) {
|
||||||
var newText = _progressWindow.document.createElement("description");
|
new this.ItemProgress(icons[i], labels[i]);
|
||||||
newText.appendChild(
|
|
||||||
_progressWindow.document.createTextNode(labels[i])
|
|
||||||
);
|
|
||||||
newText.setAttribute("class", "zotero-progress-item-label");
|
|
||||||
newText.setAttribute("crop", "end");
|
|
||||||
|
|
||||||
var newImageHolder = _progressWindow.document.createElement("vbox");
|
|
||||||
var newImage = _progressWindow.document.createElement("image");
|
|
||||||
newImage.setAttribute("class", "zotero-progress-item-icon");
|
|
||||||
newImage.setAttribute("src", icons[i]);
|
|
||||||
newImage.setAttribute("flex", 0);
|
|
||||||
newImage.setAttribute("orient", "horizontal");
|
|
||||||
newImage.setAttribute("pack", "start");
|
|
||||||
newImageHolder.appendChild(newImage);
|
|
||||||
|
|
||||||
var newHB = _progressWindow.document.createElement("hbox");
|
|
||||||
newHB.setAttribute("class", "zotero-progress-item-hbox");
|
|
||||||
|
|
||||||
newHB.appendChild(newImageHolder);
|
|
||||||
newHB.appendChild(newText);
|
|
||||||
|
|
||||||
_progressWindow.document.getElementById("zotero-progress-text-box").appendChild(newHB);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_move();
|
_move();
|
||||||
} else {
|
});
|
||||||
_loadLines = _loadLines.concat(labels);
|
|
||||||
_loadIcons = _loadIcons.concat(icons);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* Add a description to the progress window
|
* Add a description to the progress window
|
||||||
*
|
*
|
||||||
* <a> elements are turned into XUL links
|
* <a> elements are turned into XUL links
|
||||||
*/
|
*/
|
||||||
function addDescription(text) {
|
this.addDescription = _deferUntilWindowLoad(function addDescription(text) {
|
||||||
if(_windowLoaded) {
|
|
||||||
var newHB = _progressWindow.document.createElement("hbox");
|
var newHB = _progressWindow.document.createElement("hbox");
|
||||||
newHB.setAttribute("class", "zotero-progress-item-hbox");
|
newHB.setAttribute("class", "zotero-progress-item-hbox");
|
||||||
var newDescription = _progressWindow.document.createElement("description");
|
var newDescription = _progressWindow.document.createElement("description");
|
||||||
|
@ -240,13 +229,17 @@ Zotero.ProgressWindow = function(_window){
|
||||||
_progressWindow.document.getElementById("zotero-progress-text-box").appendChild(newHB);
|
_progressWindow.document.getElementById("zotero-progress-text-box").appendChild(newHB);
|
||||||
|
|
||||||
_move();
|
_move();
|
||||||
} else {
|
});
|
||||||
_loadDescription = text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
function startCloseTimer(ms, requireMouseOver) {
|
* Sets a timer to close the progress window. If a previous close timer was set,
|
||||||
|
* clears it.
|
||||||
|
* @param {Integer} ms The number of milliseconds to wait before closing the progress
|
||||||
|
* window.
|
||||||
|
* @param {Boolean} [requireMouseOver] If true, wait until the mouse has touched the
|
||||||
|
* window before closing.
|
||||||
|
*/
|
||||||
|
this.startCloseTimer = function startCloseTimer(ms, requireMouseOver) {
|
||||||
if (_windowLoaded || _windowLoading) {
|
if (_windowLoaded || _windowLoading) {
|
||||||
if (requireMouseOver && !_mouseWasOver) {
|
if (requireMouseOver && !_mouseWasOver) {
|
||||||
return;
|
return;
|
||||||
|
@ -261,10 +254,14 @@ Zotero.ProgressWindow = function(_window){
|
||||||
}
|
}
|
||||||
|
|
||||||
_timeoutID = _progressWindow.setTimeout(_timeout, ms);
|
_timeoutID = _progressWindow.setTimeout(_timeout, ms);
|
||||||
|
_closing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
/**
|
||||||
|
* Immediately closes the progress window if it is open.
|
||||||
|
*/
|
||||||
|
this.close = function close() {
|
||||||
_disableTimeout();
|
_disableTimeout();
|
||||||
_windowLoaded = false;
|
_windowLoaded = false;
|
||||||
_windowLoading = false;
|
_windowLoading = false;
|
||||||
|
@ -275,23 +272,104 @@ Zotero.ProgressWindow = function(_window){
|
||||||
} catch(ex) {}
|
} catch(ex) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new object representing a line in the progressWindow. This is the OO
|
||||||
|
* version of addLines() above.
|
||||||
|
*/
|
||||||
|
this.ItemProgress = _deferUntilWindowLoad(function(iconSrc, title, parentItemProgress) {
|
||||||
|
this._itemText = _progressWindow.document.createElement("description");
|
||||||
|
this._itemText.appendChild(_progressWindow.document.createTextNode(title));
|
||||||
|
this._itemText.setAttribute("class", "zotero-progress-item-label");
|
||||||
|
this._itemText.setAttribute("crop", "end");
|
||||||
|
|
||||||
|
this._image = _progressWindow.document.createElement("hbox");
|
||||||
|
this._image.setAttribute("class", "zotero-progress-item-icon");
|
||||||
|
this._image.setAttribute("flex", 0);
|
||||||
|
this._image.style.width = "16px";
|
||||||
|
this._image.style.backgroundRepeat = "no-repeat";
|
||||||
|
this.setIcon(iconSrc);
|
||||||
|
|
||||||
|
this._hbox = _progressWindow.document.createElement("hbox");
|
||||||
|
this._hbox.setAttribute("class", "zotero-progress-item-hbox");
|
||||||
|
if(parentItemProgress) {
|
||||||
|
this._hbox.style.marginLeft = "16px";
|
||||||
|
this._hbox.zoteroIsChildItem;
|
||||||
|
} else {
|
||||||
|
this._hbox.setAttribute("parent", "true");
|
||||||
|
}
|
||||||
|
this._hbox.style.opacity = "0.5";
|
||||||
|
|
||||||
|
this._hbox.appendChild(this._image);
|
||||||
|
this._hbox.appendChild(this._itemText);
|
||||||
|
|
||||||
|
var container = _progressWindow.document.getElementById("zotero-progress-text-box");
|
||||||
|
if(parentItemProgress) {
|
||||||
|
var nextItem = parentItemProgress._hbox.nextSibling;
|
||||||
|
while(nextItem && nextItem.zoteroIsChildItem) {
|
||||||
|
nextItem = nextItem.nextSibling;
|
||||||
|
}
|
||||||
|
container.insertBefore(this._hbox, nextItem);
|
||||||
|
} else {
|
||||||
|
container.appendChild(this._hbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
_move();
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current save progress for this item.
|
||||||
|
* @param {Integer} percent A percentage from 0 to 100.
|
||||||
|
*/
|
||||||
|
this.ItemProgress.prototype.setProgress = _deferUntilWindowLoad(function(percent) {
|
||||||
|
if(percent != 0 && percent != 100) {
|
||||||
|
// Indication of partial progress, so we will use the circular indicator
|
||||||
|
this._image.style.backgroundImage = "url('chrome://zotero/skin/progress_arcs.png')";
|
||||||
|
this._image.style.backgroundPosition = "-"+(Math.round(percent/100*nArcs)*16)+"px 0";
|
||||||
|
this._hbox.style.opacity = percent/200+.5;
|
||||||
|
this._hbox.style.filter = "alpha(opacity = "+(percent/2+50)+")";
|
||||||
|
} else if(percent == 100) {
|
||||||
|
this._image.style.backgroundImage = "url('"+this._iconSrc+"')";
|
||||||
|
this._image.style.backgroundPosition = "";
|
||||||
|
this._hbox.style.opacity = "1";
|
||||||
|
this._hbox.style.filter = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the icon for this item.
|
||||||
|
* @param {Integer} percent A percentage from 0 to 100.
|
||||||
|
*/
|
||||||
|
this.ItemProgress.prototype.setIcon = _deferUntilWindowLoad(function(iconSrc) {
|
||||||
|
this._image.style.backgroundImage = "url('"+iconSrc+"')";
|
||||||
|
this._image.style.backgroundPosition = "";
|
||||||
|
this._iconSrc = iconSrc;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that an error occurred saving this item.
|
||||||
|
*/
|
||||||
|
this.ItemProgress.prototype.setError = _deferUntilWindowLoad(function() {
|
||||||
|
this._image.style.backgroundImage = "url('chrome://zotero/skin/cross.png')";
|
||||||
|
this._image.style.backgroundPosition = "";
|
||||||
|
this._itemText.style.color = "red";
|
||||||
|
this._hbox.style.opacity = "1";
|
||||||
|
this._hbox.style.filter = "";
|
||||||
|
});
|
||||||
|
|
||||||
function _onWindowLoaded() {
|
function _onWindowLoaded() {
|
||||||
_windowLoading = false;
|
_windowLoading = false;
|
||||||
_windowLoaded = true;
|
_windowLoaded = true;
|
||||||
|
|
||||||
_move();
|
_move();
|
||||||
// do things we delayed because the window was loading
|
|
||||||
changeHeadline(_loadHeadline);
|
|
||||||
addLines(_loadLines, _loadIcons);
|
|
||||||
if (_loadDescription) {
|
|
||||||
addDescription(_loadDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset parameters
|
// do things we delayed because the window was loading
|
||||||
_loadHeadline = '';
|
for(var i=0; i<_deferredUntilWindowLoad.length; i++) {
|
||||||
_loadLines = [];
|
_deferredUntilWindowLoad[i].apply(_deferredUntilWindowLoadThis[i],
|
||||||
_loadIcons = [];
|
_deferredUntilWindowLoadArgs[i]);
|
||||||
_loadDescription = null;
|
}
|
||||||
|
_deferredUntilWindowLoad = [];
|
||||||
|
_deferredUntilWindowLoadThis = [];
|
||||||
|
_deferredUntilWindowLoadArgs = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function _move() {
|
function _move() {
|
||||||
|
@ -303,7 +381,7 @@ Zotero.ProgressWindow = function(_window){
|
||||||
}
|
}
|
||||||
|
|
||||||
function _timeout() {
|
function _timeout() {
|
||||||
close(); // could check to see if we're really supposed to close yet
|
self.close(); // could check to see if we're really supposed to close yet
|
||||||
// (in case multiple scrapers are operating at once)
|
// (in case multiple scrapers are operating at once)
|
||||||
_timeoutID = false;
|
_timeoutID = false;
|
||||||
}
|
}
|
||||||
|
@ -319,7 +397,6 @@ Zotero.ProgressWindow = function(_window){
|
||||||
_timeoutID = false;
|
_timeoutID = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable the close timer when the mouse is over the window
|
* Disable the close timer when the mouse is over the window
|
||||||
*/
|
*/
|
||||||
|
@ -328,8 +405,7 @@ Zotero.ProgressWindow = function(_window){
|
||||||
_disableTimeout();
|
_disableTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* Start the close timer when the mouse leaves the window
|
* Start the close timer when the mouse leaves the window
|
||||||
*
|
*
|
||||||
* Note that this onmouseout doesn't work correctly on popups in Fx2,
|
* Note that this onmouseout doesn't work correctly on popups in Fx2,
|
||||||
|
@ -345,11 +421,27 @@ Zotero.ProgressWindow = function(_window){
|
||||||
&& (e.screenY >= top) && e.screenY <= (top + this.outerHeight)) {
|
&& (e.screenY >= top) && e.screenY <= (top + this.outerHeight)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
startCloseTimer();
|
if(_closing) self.startCloseTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function _onMouseUp(e) {
|
function _onMouseUp(e) {
|
||||||
close();
|
self.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a function to ensure it isn't called until the window is loaded
|
||||||
|
*/
|
||||||
|
function _deferUntilWindowLoad(fn) {
|
||||||
|
return function() {
|
||||||
|
if(_window.closed) return;
|
||||||
|
|
||||||
|
if(_windowLoaded) {
|
||||||
|
fn.apply(this, Array.prototype.slice.call(arguments));
|
||||||
|
} else {
|
||||||
|
_deferredUntilWindowLoad.push(fn);
|
||||||
|
_deferredUntilWindowLoadThis.push(this);
|
||||||
|
_deferredUntilWindowLoadArgs.push(Array.prototype.slice.call(arguments));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,35 @@ const CONNECTOR_API_VERSION = 2;
|
||||||
Zotero.Server.Connector = function() {};
|
Zotero.Server.Connector = function() {};
|
||||||
Zotero.Server.Connector._waitingForSelection = {};
|
Zotero.Server.Connector._waitingForSelection = {};
|
||||||
Zotero.Server.Connector.Data = {};
|
Zotero.Server.Connector.Data = {};
|
||||||
|
Zotero.Server.Connector.AttachmentProgressManager = new function() {
|
||||||
|
var attachmentsInProgress = new WeakMap(),
|
||||||
|
attachmentProgress = {},
|
||||||
|
i = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds attachments to attachment progress manager
|
||||||
|
*/
|
||||||
|
this.add = function(attachments) {
|
||||||
|
for(var i=0; i<attachments.length; i++) {
|
||||||
|
var attachment = attachments[i];
|
||||||
|
attachmentsInProgress.set(attachment, (attachment.id = i++));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on attachment progress
|
||||||
|
*/
|
||||||
|
this.onProgress = function(attachment, progress, error) {
|
||||||
|
attachmentProgress[attachmentsInProgress.get(attachment)] = progress;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets progress for a given progressID
|
||||||
|
*/
|
||||||
|
this.getProgressForID = function(progressID) {
|
||||||
|
return progressID in attachmentProgress ? attachmentProgress[progressID] : 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists all available translators, including code for translators that should be run on every page
|
* Lists all available translators, including code for translators that should be run on every page
|
||||||
|
@ -169,7 +198,7 @@ Zotero.Server.Connector.Detect.prototype = {
|
||||||
* cookie - document.cookie or equivalent
|
* cookie - document.cookie or equivalent
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* If a single item, sends response code 201 with no body.
|
* If a single item, sends response code 201 with item in body.
|
||||||
* If multiple items, sends response code 300 with the following content:
|
* If multiple items, sends response code 300 with the following content:
|
||||||
* items - list of items in the format typically passed to the selectItems handler
|
* items - list of items in the format typically passed to the selectItems handler
|
||||||
* instanceID - an ID that must be maintained for the subsequent Zotero.Connector.Select call
|
* instanceID - an ID that must be maintained for the subsequent Zotero.Connector.Select call
|
||||||
|
@ -246,9 +275,14 @@ Zotero.Server.Connector.SavePage.prototype = {
|
||||||
if(collection) {
|
if(collection) {
|
||||||
collection.addItem(item.id);
|
collection.addItem(item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonItems.push(jsonItem);
|
jsonItems.push(jsonItem);
|
||||||
});
|
});
|
||||||
translate.setHandler("done", function(obj, item) {
|
translate.setHandler("attachmentProgress", function(obj, attachment, progress, error) {
|
||||||
|
Zotero.Server.Connector.AttachmentProgressManager.onProgress(attachment, progress, error);
|
||||||
|
});
|
||||||
|
translate.setHandler("itemsDone", function(obj, item) {
|
||||||
|
Zotero.Server.Connector.AttachmentProgressManager.add(item.attachments);
|
||||||
Zotero.Browser.deleteHiddenBrowser(me._browser);
|
Zotero.Browser.deleteHiddenBrowser(me._browser);
|
||||||
if(jsonItems.length || me.selectedItems === false) {
|
if(jsonItems.length || me.selectedItems === false) {
|
||||||
me.sendResponse(201, "application/json", JSON.stringify({"items":jsonItems}));
|
me.sendResponse(201, "application/json", JSON.stringify({"items":jsonItems}));
|
||||||
|
@ -269,7 +303,7 @@ Zotero.Server.Connector.SavePage.prototype = {
|
||||||
* Accepts:
|
* Accepts:
|
||||||
* items - an array of JSON format items
|
* items - an array of JSON format items
|
||||||
* Returns:
|
* Returns:
|
||||||
* 201 response code with empty body
|
* 201 response code with item in body.
|
||||||
*/
|
*/
|
||||||
Zotero.Server.Connector.SaveItem = function() {};
|
Zotero.Server.Connector.SaveItem = function() {};
|
||||||
Zotero.Server.Endpoints["/connector/saveItems"] = Zotero.Server.Connector.SaveItem;
|
Zotero.Server.Endpoints["/connector/saveItems"] = Zotero.Server.Connector.SaveItem;
|
||||||
|
@ -299,22 +333,23 @@ Zotero.Server.Connector.SaveItem.prototype = {
|
||||||
// save items
|
// save items
|
||||||
var itemSaver = new Zotero.Translate.ItemSaver(libraryID,
|
var itemSaver = new Zotero.Translate.ItemSaver(libraryID,
|
||||||
Zotero.Translate.ItemSaver.ATTACHMENT_MODE_DOWNLOAD, 1, undefined, cookieSandbox);
|
Zotero.Translate.ItemSaver.ATTACHMENT_MODE_DOWNLOAD, 1, undefined, cookieSandbox);
|
||||||
itemSaver.saveItems(data.items, function(returnValue, data) {
|
itemSaver.saveItems(data.items, function(returnValue, newItems) {
|
||||||
if(returnValue) {
|
if(returnValue) {
|
||||||
try {
|
try {
|
||||||
for each(var item in data) {
|
for each(var item in newItems) {
|
||||||
if(collection) collection.addItem(item.id);
|
if(collection) collection.addItem(item.id);
|
||||||
}
|
}
|
||||||
sendResponseCallback(201);
|
|
||||||
|
sendResponseCallback(201, "application/json", JSON.stringify({"items":data.items}));
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
Zotero.logError(e);
|
Zotero.logError(e);
|
||||||
sendResponseCallback(500);
|
sendResponseCallback(500);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sendResponseCallback(500);
|
sendResponseCallback(500);
|
||||||
throw data;
|
throw newItems;
|
||||||
}
|
}
|
||||||
});
|
}, Zotero.Server.Connector.AttachmentProgressManager.onProgress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,6 +469,31 @@ Zotero.Server.Connector.SelectItems.prototype = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets progress for an attachment that is currently being saved
|
||||||
|
*
|
||||||
|
* Accepts:
|
||||||
|
* Array of attachment IDs returned by savePage, saveItems, or saveSnapshot
|
||||||
|
* Returns:
|
||||||
|
* 200 response code with current progress in body. Progress is either a number
|
||||||
|
* between 0 and 100 or "false" to indicate that saving failed.
|
||||||
|
*/
|
||||||
|
Zotero.Server.Connector.Progress = function() {};
|
||||||
|
Zotero.Server.Endpoints["/connector/attachmentProgress"] = Zotero.Server.Connector.Progress;
|
||||||
|
Zotero.Server.Connector.Progress.prototype = {
|
||||||
|
"supportedMethods":["POST"],
|
||||||
|
"supportedDataTypes":["application/json"],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {String} data POST data or GET query string
|
||||||
|
* @param {Function} sendResponseCallback function to send HTTP response
|
||||||
|
*/
|
||||||
|
"init":function(data, sendResponseCallback) {
|
||||||
|
sendResponseCallback(200, "application/json",
|
||||||
|
JSON.stringify([Zotero.Server.Connector.AttachmentProgressManager.getProgressForID(id) for each(id in data)]));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get code for a translator
|
* Get code for a translator
|
||||||
*
|
*
|
||||||
|
@ -459,6 +519,64 @@ Zotero.Server.Connector.GetTranslatorCode.prototype = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get selected collection
|
||||||
|
*
|
||||||
|
* Accepts:
|
||||||
|
* Nothing
|
||||||
|
* Returns:
|
||||||
|
* libraryID
|
||||||
|
* libraryName
|
||||||
|
* collectionID
|
||||||
|
* collectionName
|
||||||
|
*/
|
||||||
|
Zotero.Server.Connector.GetSelectedCollection = function() {};
|
||||||
|
Zotero.Server.Endpoints["/connector/getSelectedCollection"] = Zotero.Server.Connector.GetSelectedCollection;
|
||||||
|
Zotero.Server.Connector.GetSelectedCollection.prototype = {
|
||||||
|
"supportedMethods":["POST"],
|
||||||
|
"supportedDataTypes":["application/json"],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a 200 response to say the server is alive
|
||||||
|
* @param {String} data POST data or GET query string
|
||||||
|
* @param {Function} sendResponseCallback function to send HTTP response
|
||||||
|
*/
|
||||||
|
"init":function(postData, sendResponseCallback) {
|
||||||
|
var zp = Zotero.getActiveZoteroPane(),
|
||||||
|
libraryID = null,
|
||||||
|
collection = null,
|
||||||
|
editable = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
libraryID = zp.getSelectedLibraryID();
|
||||||
|
collection = zp.getSelectedCollection();
|
||||||
|
editable = zp.collectionsView.editable;
|
||||||
|
} catch(e) {}
|
||||||
|
|
||||||
|
var response = {
|
||||||
|
"editable":editable,
|
||||||
|
"libraryID":libraryID
|
||||||
|
};
|
||||||
|
|
||||||
|
if(libraryID) {
|
||||||
|
response.libraryName = Zotero.Libraries.getName(libraryID);
|
||||||
|
} else {
|
||||||
|
response.libraryName = Zotero.getString("pane.collections.library");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(collection && collection.id) {
|
||||||
|
response.id = collection.id;
|
||||||
|
response.name = collection.name;
|
||||||
|
} else {
|
||||||
|
response.id = null;
|
||||||
|
response.name = response.libraryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendResponseCallback(200, "application/json", JSON.stringify(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test connection
|
* Test connection
|
||||||
*
|
*
|
||||||
|
|
|
@ -131,27 +131,15 @@ Zotero.Translate.Sandbox = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fire itemSaving event
|
||||||
|
translate._runHandler("itemSaving", item);
|
||||||
|
|
||||||
if(translate instanceof Zotero.Translate.Web) {
|
if(translate instanceof Zotero.Translate.Web) {
|
||||||
// For web translators, we queue saves
|
// For web translators, we queue saves
|
||||||
translate.saveQueue.push(item);
|
translate.saveQueue.push(item);
|
||||||
translate._runHandler("itemSaving", item);
|
|
||||||
} else {
|
} else {
|
||||||
var newItem;
|
// Save items
|
||||||
translate._itemSaver.saveItems([item], function(returnValue, data) {
|
translate._saveItems([item]);
|
||||||
if(returnValue) {
|
|
||||||
newItem = data[0];
|
|
||||||
translate.newItems.push(newItem);
|
|
||||||
} else {
|
|
||||||
translate.complete(false, data);
|
|
||||||
throw data;
|
|
||||||
}
|
|
||||||
}, function(arg1, arg2, arg3) {
|
|
||||||
translate._attachmentProgress(arg1, arg2, arg3);
|
|
||||||
});
|
|
||||||
|
|
||||||
translate._runHandler("itemSaving", item);
|
|
||||||
// pass both the saved item and the original JS array item
|
|
||||||
translate._runHandler("itemDone", newItem, item);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1014,7 +1002,8 @@ Zotero.Translate.Base.prototype = {
|
||||||
|
|
||||||
this._libraryID = libraryID;
|
this._libraryID = libraryID;
|
||||||
this._saveAttachments = saveAttachments === undefined || saveAttachments;
|
this._saveAttachments = saveAttachments === undefined || saveAttachments;
|
||||||
this._attachmentsSaving = [];
|
this._savingAttachments = [];
|
||||||
|
this._savingItems = 0;
|
||||||
|
|
||||||
var me = this;
|
var me = this;
|
||||||
if(typeof this.translator[0] === "object") {
|
if(typeof this.translator[0] === "object") {
|
||||||
|
@ -1143,14 +1132,11 @@ Zotero.Translate.Base.prototype = {
|
||||||
|
|
||||||
if(returnValue) {
|
if(returnValue) {
|
||||||
if(this.saveQueue.length) {
|
if(this.saveQueue.length) {
|
||||||
var me = this;
|
this._saveItems(this.saveQueue);
|
||||||
this._itemSaver.saveItems(this.saveQueue.slice(),
|
this.saveQueue = [];
|
||||||
function(returnValue, data) { me._itemsSaved(returnValue, data); },
|
|
||||||
function(arg1, arg2, arg3) { me._attachmentProgress(arg1, arg2, arg3); });
|
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
this._debug("Translation successful");
|
|
||||||
}
|
}
|
||||||
|
this._debug("Translation successful");
|
||||||
} else {
|
} else {
|
||||||
if(error) {
|
if(error) {
|
||||||
// report error to console
|
// report error to console
|
||||||
|
@ -1176,61 +1162,79 @@ Zotero.Translate.Base.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback executed when items have been saved (which may happen asynchronously, if in
|
* Saves items to the database, taking care to defer attachmentProgress notifications
|
||||||
* connector)
|
* until after save
|
||||||
*
|
|
||||||
* @param {Boolean} returnValue Whether saving was successful
|
|
||||||
* @param {Zotero.Item[]|Error} data If returnValue is true, this will be an array of
|
|
||||||
* Zotero.Item objects. If returnValue is false, this will
|
|
||||||
* be a string error message.
|
|
||||||
*/
|
*/
|
||||||
"_itemsSaved":function(returnValue, data) {
|
"_saveItems":function(items) {
|
||||||
|
var me = this,
|
||||||
|
itemDoneEventsDispatched = false,
|
||||||
|
deferredProgress = [],
|
||||||
|
attachmentsWithProgress = [];
|
||||||
|
|
||||||
|
this._savingItems++;
|
||||||
|
this._itemSaver.saveItems(items.slice(), function(returnValue, newItems) {
|
||||||
if(returnValue) {
|
if(returnValue) {
|
||||||
// trigger deferred itemDone events
|
// Remove attachments not being saved from item.attachments
|
||||||
var nItems = data.length;
|
for(var i=0; i<items.length; i++) {
|
||||||
for(var i=0; i<nItems; i++) {
|
var item = items[i];
|
||||||
this._runHandler("itemDone", data[i], this.saveQueue[i]);
|
for(var j=0; j<item.attachments.length; j++) {
|
||||||
|
if(attachmentsWithProgress.indexOf(item.attachments[j]) === -1) {
|
||||||
|
item.attachments.splice(j--, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.saveQueue = [];
|
// Trigger itemDone events
|
||||||
} else {
|
for(var i=0, nItems = items.length; i<nItems; i++) {
|
||||||
Zotero.logError(data);
|
me._runHandler("itemDone", newItems[i], items[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(returnValue) {
|
// Specify that itemDone event was dispatched, so that we don't defer
|
||||||
this._checkIfDone();
|
// attachmentProgress notifications anymore
|
||||||
|
itemDoneEventsDispatched = true;
|
||||||
|
|
||||||
|
// Run deferred attachmentProgress notifications
|
||||||
|
for(var i=0; i<deferredProgress.length; i++) {
|
||||||
|
me._runHandler("attachmentProgress", deferredProgress[i][0],
|
||||||
|
deferredProgress[i][1], deferredProgress[i][2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
me.newItems = me.newItems.concat(newItems);
|
||||||
|
me._savingItems--;
|
||||||
|
me._checkIfDone();
|
||||||
} else {
|
} else {
|
||||||
this._runHandler("done", returnValue);
|
Zotero.logError(newItems);
|
||||||
|
me.complete(returnValue, newItems);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
function(attachment, progress, error) {
|
||||||
/**
|
var attachmentIndex = me._savingAttachments.indexOf(attachment);
|
||||||
* Callback for attachment progress, passed as third argument to Zotero.ItemSaver#saveItems
|
if(progress === false || progress === 100) {
|
||||||
*
|
if(attachmentIndex !== -1) {
|
||||||
* @param {Object} attachment Attachment object to be saved. Should remain the same between
|
me._savingAttachments.splice(attachmentIndex, 1);
|
||||||
* repeated calls to callback.
|
}
|
||||||
* @param {Boolean|Number} progress Percent complete, or false if an error occurred.
|
|
||||||
* @param {Error} [error] Error, if an error occurred during saving.
|
|
||||||
*/
|
|
||||||
"_attachmentProgress":function(attachment, progress, error) {
|
|
||||||
Zotero.debug("Attachment progress (progress = "+progress+")");
|
|
||||||
Zotero.debug(attachment);
|
|
||||||
var attachmentIndex = this._attachmentsSaving.indexOf(attachment);
|
|
||||||
if((progress === false || progress === 100) && attachmentIndex !== -1) {
|
|
||||||
this._attachmentsSaving.splice(attachmentIndex, 1);
|
|
||||||
} else if(attachmentIndex === -1) {
|
} else if(attachmentIndex === -1) {
|
||||||
this._attachmentsSaving.push(attachment);
|
me._savingAttachments.push(attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._runHandler("attachmentProgress", attachment, progress, error);
|
if(itemDoneEventsDispatched) {
|
||||||
this._checkIfDone();
|
// itemDone event has already fired, so we can fire attachmentProgress
|
||||||
|
// notifications
|
||||||
|
me._runHandler("attachmentProgress", attachment, progress, error);
|
||||||
|
me._checkIfDone();
|
||||||
|
} else {
|
||||||
|
// Defer until after we fire the itemDone event
|
||||||
|
deferredProgress.push([attachment, progress, error]);
|
||||||
|
attachmentsWithProgress.push(attachment);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if saving done, and if so, fires done event
|
* Checks if saving done, and if so, fires done event
|
||||||
*/
|
*/
|
||||||
"_checkIfDone":function() {
|
"_checkIfDone":function() {
|
||||||
if(!this._attachmentsSaving.length) {
|
if(!this._savingItems && !this._savingAttachments.length && !this._currentState) {
|
||||||
this._runHandler("done", true);
|
this._runHandler("done", true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -87,7 +87,18 @@ Zotero.Translate.ItemSaver.ATTACHMENT_MODE_DOWNLOAD = 1;
|
||||||
Zotero.Translate.ItemSaver.ATTACHMENT_MODE_FILE = 2;
|
Zotero.Translate.ItemSaver.ATTACHMENT_MODE_FILE = 2;
|
||||||
|
|
||||||
Zotero.Translate.ItemSaver.prototype = {
|
Zotero.Translate.ItemSaver.prototype = {
|
||||||
"saveItems":function(items, callback) {
|
/**
|
||||||
|
* Saves items to Standalone or the server
|
||||||
|
* @param items Items in Zotero.Item.toArray() format
|
||||||
|
* @param {Function} callback A callback to be executed when saving is complete. If saving
|
||||||
|
* succeeded, this callback will be passed true as the first argument and a list of items
|
||||||
|
* saved as the second. If saving failed, the callback will be passed false as the first
|
||||||
|
* argument and an error object as the second
|
||||||
|
* @param {Function} [attachmentCallback] A callback that receives information about attachment
|
||||||
|
* save progress. The callback will be called as attachmentCallback(attachment, false, error)
|
||||||
|
* on failure or attachmentCallback(attachment, progressPercent) periodically during saving.
|
||||||
|
*/
|
||||||
|
"saveItems":function(items, callback, attachmentCallback) {
|
||||||
// if no open transaction, open a transaction and add a timer call to close it
|
// if no open transaction, open a transaction and add a timer call to close it
|
||||||
var openedTransaction = false;
|
var openedTransaction = false;
|
||||||
if(!Zotero.DB.transactionInProgress()) {
|
if(!Zotero.DB.transactionInProgress()) {
|
||||||
|
@ -110,8 +121,8 @@ Zotero.Translate.ItemSaver.prototype = {
|
||||||
newItem = Zotero.Items.get(myID);
|
newItem = Zotero.Items.get(myID);
|
||||||
} else {
|
} else {
|
||||||
if(type == "attachment") { // handle attachments differently
|
if(type == "attachment") { // handle attachments differently
|
||||||
newItem = this._saveAttachment(item);
|
newItem = this._saveAttachment(item, null, attachmentCallback);
|
||||||
if(!newItem) return;
|
if(!newItem) continue;
|
||||||
var myID = newItem.id;
|
var myID = newItem.id;
|
||||||
} else {
|
} else {
|
||||||
var typeID = Zotero.ItemTypes.getID(type);
|
var typeID = Zotero.ItemTypes.getID(type);
|
||||||
|
@ -137,8 +148,10 @@ Zotero.Translate.ItemSaver.prototype = {
|
||||||
// handle attachments
|
// handle attachments
|
||||||
if(item.attachments) {
|
if(item.attachments) {
|
||||||
for(var i=0; i<item.attachments.length; i++) {
|
for(var i=0; i<item.attachments.length; i++) {
|
||||||
var newAttachment = this._saveAttachment(item.attachments[i], myID);
|
var newAttachment = this._saveAttachment(item.attachments[i], myID, attachmentCallback);
|
||||||
if(newAttachment) this._saveTags(item.attachments[i], newAttachment);
|
if(typeof newAttachment === "object") {
|
||||||
|
this._saveTags(item.attachments[i], newAttachment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,13 +216,13 @@ Zotero.Translate.ItemSaver.prototype = {
|
||||||
return topLevelCollection;
|
return topLevelCollection;
|
||||||
},
|
},
|
||||||
|
|
||||||
"_saveAttachmentFile":function(attachment, parentID) {
|
"_saveAttachmentFile":function(attachment, parentID, attachmentCallback) {
|
||||||
const urlRe = /(([A-Za-z]+):\/\/[^\s]*)/i;
|
const urlRe = /(([A-Za-z]+):\/\/[^\s]*)/i;
|
||||||
Zotero.debug("Translate: Adding attachment", 4);
|
Zotero.debug("Translate: Adding attachment", 4);
|
||||||
|
|
||||||
if(!attachment.url && !attachment.path) {
|
if(!attachment.url && !attachment.path) {
|
||||||
Zotero.debug("Translate: Ignoring attachment: no path or URL specified", 2);
|
Zotero.debug("Translate: Ignoring attachment: no path or URL specified", 2);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!attachment.path) {
|
if(!attachment.path) {
|
||||||
|
@ -221,34 +234,40 @@ Zotero.Translate.ItemSaver.prototype = {
|
||||||
attachment.url = false;
|
attachment.url = false;
|
||||||
} else if(protocol != "http" && protocol != "https") {
|
} else if(protocol != "http" && protocol != "https") {
|
||||||
Zotero.debug("Translate: Unrecognized protocol "+protocol, 2);
|
Zotero.debug("Translate: Unrecognized protocol "+protocol, 2);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!attachment.path) {
|
if(!attachment.path) {
|
||||||
// create from URL
|
// create from URL
|
||||||
|
attachment.linkMode = "linked_file";
|
||||||
try {
|
try {
|
||||||
var myID = Zotero.Attachments.linkFromURL(attachment.url, parentID,
|
var myID = Zotero.Attachments.linkFromURL(attachment.url, parentID,
|
||||||
(attachment.mimeType ? attachment.mimeType : undefined),
|
(attachment.mimeType ? attachment.mimeType : undefined),
|
||||||
(attachment.title ? attachment.title : undefined));
|
(attachment.title ? attachment.title : undefined));
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
Zotero.debug("Translate: Error adding attachment "+attachment.url, 2);
|
Zotero.debug("Translate: Error adding attachment "+attachment.url, 2);
|
||||||
return;
|
attachmentCallback(attachment, false, e);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
Zotero.debug("Translate: Created attachment; id is "+myID, 4);
|
Zotero.debug("Translate: Created attachment; id is "+myID, 4);
|
||||||
|
attachmentCallback(attachment, 100);
|
||||||
var newItem = Zotero.Items.get(myID);
|
var newItem = Zotero.Items.get(myID);
|
||||||
} else {
|
} else {
|
||||||
var file = this._parsePath(attachment.path);
|
var file = this._parsePath(attachment.path);
|
||||||
if(!file || !file.exists()) return;
|
if(!file || !file.exists()) return;
|
||||||
|
|
||||||
if (attachment.url) {
|
if (attachment.url) {
|
||||||
|
attachment.linkMode = "imported_url";
|
||||||
var myID = Zotero.Attachments.importSnapshotFromFile(file,
|
var myID = Zotero.Attachments.importSnapshotFromFile(file,
|
||||||
attachment.url, attachment.title, attachment.mimeType, attachment.charset,
|
attachment.url, attachment.title, attachment.mimeType, attachment.charset,
|
||||||
parentID);
|
parentID);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
attachment.linkMode = "imported_file";
|
||||||
var myID = Zotero.Attachments.importFromFile(file, parentID);
|
var myID = Zotero.Attachments.importFromFile(file, parentID);
|
||||||
}
|
}
|
||||||
|
attachmentCallback(attachment, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
var newItem = Zotero.Items.get(myID);
|
var newItem = Zotero.Items.get(myID);
|
||||||
|
@ -306,7 +325,7 @@ Zotero.Translate.ItemSaver.prototype = {
|
||||||
return file;
|
return file;
|
||||||
},
|
},
|
||||||
|
|
||||||
"_saveAttachmentDownload":function(attachment, parentID) {
|
"_saveAttachmentDownload":function(attachment, parentID, attachmentCallback) {
|
||||||
Zotero.debug("Translate: Adding attachment", 4);
|
Zotero.debug("Translate: Adding attachment", 4);
|
||||||
|
|
||||||
// determine whether to save attachments at all
|
// determine whether to save attachments at all
|
||||||
|
@ -319,7 +338,7 @@ Zotero.Translate.ItemSaver.prototype = {
|
||||||
var shouldAttach = ((attachment.document
|
var shouldAttach = ((attachment.document
|
||||||
|| (attachment.mimeType && attachment.mimeType == "text/html")) && automaticSnapshots)
|
|| (attachment.mimeType && attachment.mimeType == "text/html")) && automaticSnapshots)
|
||||||
|| downloadAssociatedFiles;
|
|| downloadAssociatedFiles;
|
||||||
if(!shouldAttach) return;
|
if(!shouldAttach) return false;
|
||||||
|
|
||||||
if(attachment.document) {
|
if(attachment.document) {
|
||||||
attachment.document = Zotero.Translate.DOMWrapper.unwrap(attachment.document);
|
attachment.document = Zotero.Translate.DOMWrapper.unwrap(attachment.document);
|
||||||
|
@ -327,10 +346,18 @@ Zotero.Translate.ItemSaver.prototype = {
|
||||||
|
|
||||||
if(attachment.snapshot === false || !this._saveFiles) {
|
if(attachment.snapshot === false || !this._saveFiles) {
|
||||||
// if snapshot is explicitly set to false, attach as link
|
// if snapshot is explicitly set to false, attach as link
|
||||||
|
attachment.linkMode = "linked_url";
|
||||||
if(attachment.document) {
|
if(attachment.document) {
|
||||||
|
try {
|
||||||
Zotero.Attachments.linkFromURL(attachment.document.location.href, parentID,
|
Zotero.Attachments.linkFromURL(attachment.document.location.href, parentID,
|
||||||
(attachment.mimeType ? attachment.mimeType : attachment.document.contentType),
|
(attachment.mimeType ? attachment.mimeType : attachment.document.contentType),
|
||||||
(attachment.title ? attachment.title : attachment.document.title));
|
(attachment.title ? attachment.title : attachment.document.title));
|
||||||
|
attachmentCallback(attachment, 100);
|
||||||
|
} catch(e) {
|
||||||
|
Zotero.debug("Translate: Error adding attachment "+attachment.url, 2);
|
||||||
|
attachmentCallback(attachment, false, e);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if(!attachment.mimeType || !attachment.title) {
|
if(!attachment.mimeType || !attachment.title) {
|
||||||
Zotero.debug("Translate: Either mimeType or title is missing; attaching file will be slower", 3);
|
Zotero.debug("Translate: Either mimeType or title is missing; attaching file will be slower", 3);
|
||||||
|
@ -340,19 +367,33 @@ Zotero.Translate.ItemSaver.prototype = {
|
||||||
Zotero.Attachments.linkFromURL(attachment.url, parentID,
|
Zotero.Attachments.linkFromURL(attachment.url, parentID,
|
||||||
(attachment.mimeType ? attachment.mimeType : undefined),
|
(attachment.mimeType ? attachment.mimeType : undefined),
|
||||||
(attachment.title ? attachment.title : undefined));
|
(attachment.title ? attachment.title : undefined));
|
||||||
|
attachmentCallback(attachment, 100);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
Zotero.debug("Translate: Error adding attachment "+attachment.url, 2);
|
Zotero.debug("Translate: Error adding attachment "+attachment.url, 2);
|
||||||
|
attachmentCallback(attachment, false, e);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if snapshot is not explicitly set to false, retrieve snapshot
|
// if snapshot is not explicitly set to false, retrieve snapshot
|
||||||
if(attachment.document) {
|
if(attachment.document) {
|
||||||
if(automaticSnapshots) {
|
if(automaticSnapshots) {
|
||||||
try {
|
try {
|
||||||
Zotero.Attachments.importFromDocument(attachment.document, parentID, attachment.title);
|
attachment.linkMode = "imported_url";
|
||||||
|
Zotero.Attachments.importFromDocument(attachment.document,
|
||||||
|
parentID, attachment.title, function(status, err) {
|
||||||
|
if(status) {
|
||||||
|
attachmentCallback(attachment, 100);
|
||||||
|
} else {
|
||||||
|
attachmentCallback(attachment, false, err);
|
||||||
|
}
|
||||||
|
}, this._libraryID);
|
||||||
|
attachmentCallback(attachment, 0);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
Zotero.debug("Translate: Error attaching document", 2);
|
Zotero.debug("Translate: Error attaching document", 2);
|
||||||
|
attachmentCallback(attachment, false, e);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// Save attachment if snapshot pref enabled or not HTML
|
// Save attachment if snapshot pref enabled or not HTML
|
||||||
// (in which case downloadAssociatedFiles applies)
|
// (in which case downloadAssociatedFiles applies)
|
||||||
|
@ -364,14 +405,27 @@ Zotero.Translate.ItemSaver.prototype = {
|
||||||
var fileBaseName = Zotero.Attachments.getFileBaseNameFromItem(parentID);
|
var fileBaseName = Zotero.Attachments.getFileBaseNameFromItem(parentID);
|
||||||
try {
|
try {
|
||||||
Zotero.debug('Importing attachment from URL');
|
Zotero.debug('Importing attachment from URL');
|
||||||
|
attachment.linkMode = "imported_url";
|
||||||
Zotero.Attachments.importFromURL(attachment.url, parentID, title,
|
Zotero.Attachments.importFromURL(attachment.url, parentID, title,
|
||||||
fileBaseName, null, mimeType, this._libraryID, null, this._cookieSandbox);
|
fileBaseName, null, mimeType, this._libraryID, function(status, err) {
|
||||||
|
// TODO: actually indicate progress during download
|
||||||
|
if(status) {
|
||||||
|
attachmentCallback(attachment, 100);
|
||||||
|
} else {
|
||||||
|
attachmentCallback(attachment, false, err);
|
||||||
|
}
|
||||||
|
}, this._cookieSandbox);
|
||||||
|
attachmentCallback(attachment, 0);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
Zotero.debug("Translate: Error adding attachment "+attachment.url, 2);
|
Zotero.debug("Translate: Error adding attachment "+attachment.url, 2);
|
||||||
|
attachmentCallback(attachment, false, e);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
"_saveFields":function(item, newItem) {
|
"_saveFields":function(item, newItem) {
|
||||||
|
|
|
@ -1575,5 +1575,16 @@ Zotero.Utilities = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return length;
|
return length;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the icon for a JSON-style attachment
|
||||||
|
*/
|
||||||
|
"determineAttachmentIcon":function(attachment) {
|
||||||
|
if(attachment.linkMode === "linked_url") {
|
||||||
|
return Zotero.ItemTypes.getImageSrc("attachment-web-link");
|
||||||
|
}
|
||||||
|
return Zotero.ItemTypes.getImageSrc(attachment.mimeType === "application/pdf"
|
||||||
|
? "attachment-pdf" : "attachment-snapshot");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -412,6 +412,7 @@ save.error.cannotAddFilesToCollection = You cannot add files to the currently se
|
||||||
ingester.saveToZotero = Save to Zotero
|
ingester.saveToZotero = Save to Zotero
|
||||||
ingester.saveToZoteroUsing = Save to Zotero using "%S"
|
ingester.saveToZoteroUsing = Save to Zotero using "%S"
|
||||||
ingester.scraping = Saving Item…
|
ingester.scraping = Saving Item…
|
||||||
|
ingester.scrapingTo = Saving to
|
||||||
ingester.scrapeComplete = Item Saved
|
ingester.scrapeComplete = Item Saved
|
||||||
ingester.scrapeError = Could Not Save Item
|
ingester.scrapeError = Could Not Save Item
|
||||||
ingester.scrapeErrorDescription = An error occurred while saving this item. Check %S for more information.
|
ingester.scrapeErrorDescription = An error occurred while saving this item. Check %S for more information.
|
||||||
|
|
|
@ -228,12 +228,18 @@ label.zotero-text-link {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
padding-bottom: 3px;
|
padding: 3px 0 3px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-progress-text-headline
|
#zotero-progress-text-headline
|
||||||
{
|
{
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zotero-progress-icon-headline {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zotero-progress-item-icon
|
.zotero-progress-item-icon
|
||||||
|
@ -245,8 +251,13 @@ label.zotero-text-link {
|
||||||
.zotero-progress-item-hbox
|
.zotero-progress-item-hbox
|
||||||
{
|
{
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zotero-progress-item-hbox[parent]
|
||||||
|
{
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
margin-bottom: 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.zotero-progress-item-label
|
.zotero-progress-item-label
|
||||||
|
|
Loading…
Reference in a new issue