Async Zotero.Translators.get* and Zotero.Translate.getTranslators

This mostly works, but there is still much to be done:

- getTranslators() calls in preferences_export.js and quickCopy.js need
  to be made asynchronous
- getTranslators() calls in mimeTypeHandler.js need to be made
  asynchronous. This looks hard, since there is a synchronous Mozilla
  API involved
- I need to test lookup, the connector server, and export more to make
  sure that they actually work
- This API needs to be implemented for the connector and bookmarklet
- Translators should be read off the disk using async IO
This commit is contained in:
Simon Kornblith 2013-08-16 13:43:22 -04:00
parent 5040fba8bb
commit 540a54515e
8 changed files with 329 additions and 361 deletions

View File

@ -41,9 +41,9 @@ var Zotero_File_Exporter = function() {
* Performs the actual export operation * Performs the actual export operation
**/ **/
Zotero_File_Exporter.prototype.save = function() { Zotero_File_Exporter.prototype.save = function() {
var translation = new Zotero.Translate.Export(); var translation = new Zotero.Translate.Export(),
var translators = translation.getTranslators(); me = this;
translation.getTranslators().then(function(translators) {
// present options dialog // present options dialog
var io = {translators:translators} var io = {translators:translators}
window.openDialog("chrome://zotero/content/exportOptions.xul", window.openDialog("chrome://zotero/content/exportOptions.xul",
@ -61,28 +61,28 @@ Zotero_File_Exporter.prototype.save = function() {
if(io.displayOptions.exportFileData) { if(io.displayOptions.exportFileData) {
// if the result will be a folder, don't append any extension or use // if the result will be a folder, don't append any extension or use
// filters // filters
fp.defaultString = this.name; fp.defaultString = me.name;
fp.appendFilters(Components.interfaces.nsIFilePicker.filterAll); fp.appendFilters(Components.interfaces.nsIFilePicker.filterAll);
} else { } else {
// if the result will be a file, append an extension and use filters // if the result will be a file, append an extension and use filters
fp.defaultString = this.name+(io.selectedTranslator.target ? "."+io.selectedTranslator.target : ""); fp.defaultString = me.name+(io.selectedTranslator.target ? "."+io.selectedTranslator.target : "");
fp.defaultExtension = io.selectedTranslator.target; fp.defaultExtension = io.selectedTranslator.target;
fp.appendFilter(io.selectedTranslator.label, "*."+(io.selectedTranslator.target ? io.selectedTranslator.target : "*")); fp.appendFilter(io.selectedTranslator.label, "*."+(io.selectedTranslator.target ? io.selectedTranslator.target : "*"));
} }
var rv = fp.show(); var rv = fp.show();
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
if(this.collection) { if(me.collection) {
translation.setCollection(this.collection); translation.setCollection(me.collection);
} else if(this.items) { } else if(me.items) {
translation.setItems(this.items); translation.setItems(me.items);
} }
translation.setLocation(fp.file); translation.setLocation(fp.file);
translation.setTranslator(io.selectedTranslator); translation.setTranslator(io.selectedTranslator);
translation.setDisplayOptions(io.displayOptions); translation.setDisplayOptions(io.displayOptions);
translation.setHandler("itemDone", Zotero_File_Interface.updateProgress); translation.setHandler("itemDone", Zotero_File_Interface.updateProgress);
translation.setHandler("done", this._exportDone); translation.setHandler("done", me._exportDone);
Zotero.UnresponsiveScriptIndicator.disable(); Zotero.UnresponsiveScriptIndicator.disable();
Zotero_File_Interface.Progress.show( Zotero_File_Interface.Progress.show(
Zotero.getString("fileInterface.itemsExported") Zotero.getString("fileInterface.itemsExported")
@ -90,6 +90,7 @@ Zotero_File_Exporter.prototype.save = function() {
translation.translate() translation.translate()
} }
return false; return false;
}).done();
} }
/* /*
@ -207,9 +208,7 @@ var Zotero_File_Interface = new function() {
} }
var translation = new Zotero.Translate.Import(); var translation = new Zotero.Translate.Import();
if(!file) { (file ? Q(file) : translation.getTranslators().then(function(translators) {
var translators = translation.getTranslators();
const nsIFilePicker = Components.interfaces.nsIFilePicker; const nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes["@mozilla.org/filepicker;1"] var fp = Components.classes["@mozilla.org/filepicker;1"]
.createInstance(nsIFilePicker); .createInstance(nsIFilePicker);
@ -225,8 +224,9 @@ var Zotero_File_Interface = new function() {
return false; return false;
} }
file = fp.file; return fp.file;
} })).then(function(file) {
if(!file) return; // no file if user cancelled
translation.setLocation(file); translation.setLocation(file);
// get translators again, bc now we can check against the file // get translators again, bc now we can check against the file
@ -234,6 +234,7 @@ var Zotero_File_Interface = new function() {
_importTranslatorsAvailable(obj, item, createNewCollection); _importTranslatorsAvailable(obj, item, createNewCollection);
}); });
translators = translation.getTranslators(); translators = translation.getTranslators();
}).done();
} }

View File

@ -115,7 +115,7 @@ const Zotero_Lookup = new function () {
translate.setSearch(item); translate.setSearch(item);
// be lenient about translators // be lenient about translators
var translators = translate.getTranslators(); translate.getTranslators().then(function(translators) {
translate.setTranslator(translators); translate.setTranslator(translators);
translate.setHandler("done", function(translate, success) { translate.setHandler("done", function(translate, success) {
@ -140,6 +140,7 @@ const Zotero_Lookup = new function () {
}); });
translate.translate(libraryID); translate.translate(libraryID);
});
})(item); })(item);
} }

View File

@ -466,12 +466,13 @@ function init() {
// get translators, with code for unsupported translators // get translators, with code for unsupported translators
if(!viewerMode) { if(!viewerMode) {
Zotero.Translators.getAllForType(translatorType, new function() { Zotero.Translators.getAllForType(translatorType, true).
then(new function() {
var type = translatorType; var type = translatorType;
return function(translators) { return function(translators) {
haveTranslators(translators, type); haveTranslators(translators, type);
} }
}, true); });
} }
} }

View File

@ -48,7 +48,8 @@ Zotero_TranslatorTesters = new function() {
var testers = []; var testers = [];
var waitingForTranslators = TEST_TYPES.length; var waitingForTranslators = TEST_TYPES.length;
for(var i=0; i<TEST_TYPES.length; i++) { for(var i=0; i<TEST_TYPES.length; i++) {
Zotero.Translators.getAllForType(TEST_TYPES[i], new function() { Zotero.Translators.getAllForType(TEST_TYPES[i], true).
then(new function() {
var type = TEST_TYPES[i]; var type = TEST_TYPES[i];
return function(translators) { return function(translators) {
try { try {
@ -66,7 +67,7 @@ Zotero_TranslatorTesters = new function() {
Zotero.logError(e); Zotero.logError(e);
} }
}; };
}, true); });
}; };
}; };

View File

@ -1033,7 +1033,7 @@ Zotero.Schema = new function(){
var translatorsDir = Zotero.getTranslatorsDirectory(); var translatorsDir = Zotero.getTranslatorsDirectory();
translatorsDir.remove(true); translatorsDir.remove(true);
Zotero.getTranslatorsDirectory(); // recreate directory Zotero.getTranslatorsDirectory(); // recreate directory
return Zotero.Translators.init() return Zotero.Translators.reinit()
.then(function () self.updateBundledFiles('translators', null, false)) .then(function () self.updateBundledFiles('translators', null, false))
.then(function () { .then(function () {
var stylesDir = Zotero.getStylesDirectory(); var stylesDir = Zotero.getStylesDirectory();
@ -1058,7 +1058,7 @@ Zotero.Schema = new function(){
var translatorsDir = Zotero.getTranslatorsDirectory(); var translatorsDir = Zotero.getTranslatorsDirectory();
translatorsDir.remove(true); translatorsDir.remove(true);
Zotero.getTranslatorsDirectory(); // recreate directory Zotero.getTranslatorsDirectory(); // recreate directory
return Zotero.Translators.init() return Zotero.Translators.reinit()
.then(function () self.updateBundledFiles('translators', null, true)) .then(function () self.updateBundledFiles('translators', null, true))
.then(callback); .then(callback);
} }
@ -1535,7 +1535,7 @@ Zotero.Schema = new function(){
} }
// Rebuild caches // Rebuild caches
yield Zotero.Translators.init(); yield Zotero.Translators.reinit();
Zotero.Styles.init(); Zotero.Styles.init();
} }
catch (e) { catch (e) {

View File

@ -89,13 +89,18 @@ Zotero.Server.Connector.GetTranslators.prototype = {
// Translator data // Translator data
if(data.url) { if(data.url) {
var me = this; var me = this;
Zotero.Translators.getWebTranslatorsForLocation(data.url, function(data) { Zotero.Translators.getWebTranslatorsForLocation(data.url).then(function(data) {
sendResponseCallback(200, "application/json", sendResponseCallback(200, "application/json",
JSON.stringify(me._serializeTranslators(data[0]))); JSON.stringify(me._serializeTranslators(data[0])));
}); });
} else { } else {
var responseData = this._serializeTranslators(Zotero.Translators.getAll()); Zotero.Translators.getAll().then(function(translators) {
var responseData = this._serializeTranslators(translators);
sendResponseCallback(200, "application/json", JSON.stringify(responseData)); sendResponseCallback(200, "application/json", JSON.stringify(responseData));
}).fail(function() {
sendResponseCallback(500);
throw e;
}).done();
} }
}, },

View File

@ -295,13 +295,8 @@ Zotero.Translate.Sandbox = {
var translatorsHandlerSet = false; var translatorsHandlerSet = false;
safeTranslator.getTranslators = function() { safeTranslator.getTranslators = function() {
if(!translation._handlers["translators"] || !translation._handlers["translators"].length) { if(!translation._handlers["translators"] || !translation._handlers["translators"].length) {
if(Zotero.isConnector) {
throw new Error('Translator must register a "translators" handler to '+ throw new Error('Translator must register a "translators" handler to '+
'call getTranslators() in this translation environment.'); 'call getTranslators() in this translation environment.');
} else {
translate._debug('COMPAT WARNING: Translator must register a "translators" handler to '+
'call getTranslators() in connector');
}
} }
if(!translatorsHandlerSet) { if(!translatorsHandlerSet) {
translation.setHandler("translators", function() { translation.setHandler("translators", function() {
@ -331,12 +326,11 @@ Zotero.Translate.Sandbox = {
if(callback) { if(callback) {
translate.incrementAsyncProcesses("safeTranslator#getTranslatorObject()"); translate.incrementAsyncProcesses("safeTranslator#getTranslatorObject()");
} else { } else {
translate._debug("COMPAT WARNING: Translator must pass a callback to getTranslatorObject() to operate in connector"); throw new Error("Translator must pass a callback to getTranslatorObject() to "+
"operate in this translation environment.");
} }
var sandbox; var translator = translation.translator[0];
var haveTranslatorFunction = function(translator) {
translation.translator[0] = translator;
translation._loadTranslator(translator, function() { translation._loadTranslator(translator, function() {
if(Zotero.isFx && !Zotero.isBookmarklet) { if(Zotero.isFx && !Zotero.isBookmarklet) {
// do same origin check // do same origin check
@ -371,7 +365,6 @@ Zotero.Translate.Sandbox = {
"connectors."); "connectors.");
} }
if(callback) {
try { try {
callback(sandbox); callback(sandbox);
} catch(e) { } catch(e) {
@ -379,30 +372,9 @@ Zotero.Translate.Sandbox = {
return; return;
} }
translate.decrementAsyncProcesses("safeTranslator#getTranslatorObject()"); translate.decrementAsyncProcesses("safeTranslator#getTranslatorObject()");
}
}); });
}; };
if(typeof translation.translator[0] === "object") {
haveTranslatorFunction(translation.translator[0]);
return translation._sandboxManager.sandbox;
} else {
if(Zotero.isConnector && (!Zotero.isFx || Zotero.isBookmarklet) && !callback) {
throw new Error("Translator must pass a callback to getTranslatorObject() to "+
"operate in this translation environment.");
}
Zotero.Translators.get(translation.translator[0], haveTranslatorFunction);
if(Zotero.isConnector && Zotero.isFx && !callback) {
while(!sandbox && translate._currentState) {
// This processNextEvent call is used to handle a deprecated case
Zotero.mainThread.processNextEvent(true);
}
}
if(sandbox) return sandbox;
}
};
// TODO security is not super-tight here, as someone could pass something into arg // TODO security is not super-tight here, as someone could pass something into arg
// that gets evaluated in the wrong scope in Fx < 4. We should wrap this. // that gets evaluated in the wrong scope in Fx < 4. We should wrap this.
@ -1010,9 +982,11 @@ Zotero.Translate.Base.prototype = {
* @param {Boolean} [checkSetTranslator] If true, the appropriate detect function is run on the * @param {Boolean} [checkSetTranslator] If true, the appropriate detect function is run on the
* set document/text/etc. using the translator set by setTranslator. * set document/text/etc. using the translator set by setTranslator.
* getAllTranslators parameter is meaningless in this context. * getAllTranslators parameter is meaningless in this context.
* @return {Zotero.Translator[]} An array of {@link Zotero.Translator} objects * @return {Promise} Promise for an array of {@link Zotero.Translator} objects
*/ */
"getTranslators":function(getAllTranslators, checkSetTranslator) { "getTranslators":function(getAllTranslators, checkSetTranslator) {
var potentialTranslators;
// do not allow simultaneous instances of getTranslators // do not allow simultaneous instances of getTranslators
if(this._currentState === "detect") throw new Error("getTranslators: detection is already running"); if(this._currentState === "detect") throw new Error("getTranslators: detection is already running");
this._currentState = "detect"; this._currentState = "detect";
@ -1021,10 +995,10 @@ Zotero.Translate.Base.prototype = {
if(checkSetTranslator) { if(checkSetTranslator) {
// setTranslator must be called beforehand if checkSetTranslator is set // setTranslator must be called beforehand if checkSetTranslator is set
if( !this.translator || !this.translator[0] ) { if( !this.translator || !this.translator[0] ) {
throw new Error("getTranslators: translator must be set via setTranslator before calling" + return Q.reject(new Error("getTranslators: translator must be set via setTranslator before calling" +
" getTranslators with the checkSetTranslator flag"); " getTranslators with the checkSetTranslator flag"));
} }
var translators = new Array(); var promises = new Array();
var t; var t;
for(var i=0, n=this.translator.length; i<n; i++) { for(var i=0, n=this.translator.length; i<n; i++) {
if(typeof(this.translator[i]) == 'string') { if(typeof(this.translator[i]) == 'string') {
@ -1034,80 +1008,80 @@ Zotero.Translate.Base.prototype = {
t = this.translator[i]; t = this.translator[i];
} }
/**TODO: check that the translator is of appropriate type?*/ /**TODO: check that the translator is of appropriate type?*/
if(t) translators.push(t); if(t) promises.push(t);
} }
if(!translators.length) throw new Error("getTranslators: no valid translators were set."); if(!promises.length) return Q.reject(new Error("getTranslators: no valid translators were set"));
this._getTranslatorsTranslatorsReceived(translators); potentialTranslators = Q.all(promises);
} else { } else {
this._getTranslatorsGetPotentialTranslators(); potentialTranslators = this._getTranslatorsGetPotentialTranslators();
} }
// if detection returns immediately, return found translators // if detection returns immediately, return found translators
if(!this._currentState) return this._foundTranslators; var me = this, deferred = Q.defer();
}, return potentialTranslators.spread(function(allPotentialTranslators, properToProxyFunctions) {
me._potentialTranslators = [];
/** me._foundTranslators = [];
* Get all potential translators
* @return {Zotero.Translator[]}
*/
"_getTranslatorsGetPotentialTranslators":function() {
var me = this;
Zotero.Translators.getAllForType(this.type,
function(translators) { me._getTranslatorsTranslatorsReceived(translators) });
},
/**
* Called on completion of {@link #_getTranslatorsGetPotentialTranslators} call
*/
"_getTranslatorsTranslatorsReceived":function(allPotentialTranslators, properToProxyFunctions) {
this._potentialTranslators = [];
this._foundTranslators = [];
// this gets passed out by Zotero.Translators.getWebTranslatorsForLocation() because it is // this gets passed out by Zotero.Translators.getWebTranslatorsForLocation() because it is
// specific for each translator, but we want to avoid making a copy of a translator whenever // specific for each translator, but we want to avoid making a copy of a translator whenever
// possible. // possible.
this._properToProxyFunctions = properToProxyFunctions ? properToProxyFunctions : null; me._properToProxyFunctions = properToProxyFunctions ? properToProxyFunctions : null;
this._waitingForRPC = false; me._waitingForRPC = false;
for(var i=0, n=allPotentialTranslators.length; i<n; i++) { for(var i=0, n=allPotentialTranslators.length; i<n; i++) {
var translator = allPotentialTranslators[i]; var translator = allPotentialTranslators[i];
if(translator.runMode === Zotero.Translator.RUN_MODE_IN_BROWSER) { if(translator.runMode === Zotero.Translator.RUN_MODE_IN_BROWSER) {
this._potentialTranslators.push(translator); me._potentialTranslators.push(translator);
} else if(this instanceof Zotero.Translate.Web && Zotero.Connector) { } else if(me instanceof Zotero.Translate.Web && Zotero.Connector) {
this._waitingForRPC = true; me._waitingForRPC = true;
} }
} }
if(this._waitingForRPC) { // Attach handler for translators, so that we can return a
var me = this; // promise that provides them.
Zotero.Connector.callMethod("detect", {"uri":this.location.toString(), // TODO make me._detect() return a promise
"cookie":this.document.cookie, var translatorsHandler = function(obj, translators) {
"html":this.document.documentElement.innerHTML}, me.removeHandler("translators", translatorsHandler);
function(returnValue) { me._getTranslatorsRPCComplete(returnValue) }); deferred.resolve(translators);
} }
me.setHandler("translators", translatorsHandler);
me._detect();
this._detect(); if(me._waitingForRPC) {
}, // Try detect in Zotero Standalone. If this fails, it fails; we shouldn't
// get hung up about it.
/** Zotero.Connector.callMethod("detect", {"uri":me.location.toString(),
* Called on completion of detect RPC for "cookie":me.document.cookie,
* {@link Zotero.Translate.Base#_getTranslatorsTranslatorsReceived} "html":me.document.documentElement.innerHTML}).then(function(rpcTranslators) {
*/ me._waitingForRPC = false;
"_getTranslatorsRPCComplete":function(rpcTranslators) {
this._waitingForRPC = false;
// if there are translators, add them to the list of found translators // if there are translators, add them to the list of found translators
if(rpcTranslators) { if(rpcTranslators) {
for(var i=0, n=rpcTranslators.length; i<n; i++) { for(var i=0, n=rpcTranslators.length; i<n; i++) {
rpcTranslators[i].runMode = Zotero.Translator.RUN_MODE_ZOTERO_STANDALONE; rpcTranslators[i].runMode = Zotero.Translator.RUN_MODE_ZOTERO_STANDALONE;
} }
this._foundTranslators = this._foundTranslators.concat(rpcTranslators); me._foundTranslators = me._foundTranslators.concat(rpcTranslators);
} }
// call _detectTranslatorsCollected to return detected translators // call _detectTranslatorsCollected to return detected translators
if(this._currentState === null) { if(me._currentState === null) {
this._detectTranslatorsCollected(); me._detectTranslatorsCollected();
} }
});
}
}).fail(function(e) {
Zotero.logError(e);
me.complete(false, e);
}).then(deferred.promise);
},
/**
* Get all potential translators (without running detect)
* @return {Promise} Promise for an array of {@link Zotero.Translator} objects
*/
"_getTranslatorsGetPotentialTranslators":function() {
return Zotero.Translators.getAllForType(this.type).
then(function(translators) { return [translators] });
}, },
/** /**
@ -1139,8 +1113,8 @@ Zotero.Translate.Base.prototype = {
this._loadTranslator(this.translator[0], function() { me._translateTranslatorLoaded() }); this._loadTranslator(this.translator[0], function() { me._translateTranslatorLoaded() });
} else { } else {
// need to get translator first // need to get translator first
Zotero.Translators.get(this.translator[0], Zotero.Translators.get(this.translator[0]).
function(translator) { then(function(translator) {
me.translator[0] = translator; me.translator[0] = translator;
me._loadTranslator(translator, function() { me._translateTranslatorLoaded() }); me._loadTranslator(translator, function() { me._translateTranslatorLoaded() });
}); });
@ -1682,13 +1656,7 @@ Zotero.Translate.Web.prototype.setLocation = function(location) {
* Get potential web translators * Get potential web translators
*/ */
Zotero.Translate.Web.prototype._getTranslatorsGetPotentialTranslators = function() { Zotero.Translate.Web.prototype._getTranslatorsGetPotentialTranslators = function() {
var me = this; return Zotero.Translators.getWebTranslatorsForLocation(this.location);
Zotero.Translators.getWebTranslatorsForLocation(this.location,
function(data) {
// data[0] = list of translators
// data[1] = list of functions to convert proper URIs to proxied URIs
me._getTranslatorsTranslatorsReceived(data[0], data[1]);
});
} }
/** /**
@ -1920,13 +1888,10 @@ Zotero.Translate.Import.prototype.complete = function(returnValue, error) {
* Get all potential import translators, ordering translators with the right file extension first * Get all potential import translators, ordering translators with the right file extension first
*/ */
Zotero.Translate.Import.prototype._getTranslatorsGetPotentialTranslators = function() { Zotero.Translate.Import.prototype._getTranslatorsGetPotentialTranslators = function() {
if(this.location) { return (this.location ?
var me = this; Zotero.Translators.getImportTranslatorsForLocation(this.location) :
Zotero.Translators.getImportTranslatorsForLocation(this.location, Zotero.Translators.getAllForType(this.type)).
function(translators) { me._getTranslatorsTranslatorsReceived(translators) }); then(function(translators) { return [translators] });;
} else {
Zotero.Translate.Base.prototype._getTranslatorsGetPotentialTranslators.call(this);
}
} }
/** /**
@ -1938,12 +1903,13 @@ Zotero.Translate.Import.prototype.getTranslators = function() {
if(this._currentState === "detect") throw new Error("getTranslators: detection is already running"); if(this._currentState === "detect") throw new Error("getTranslators: detection is already running");
this._currentState = "detect"; this._currentState = "detect";
var me = this; var me = this;
Zotero.Translators.getAllForType(this.type, function(translators) { return Zotero.Translators.getAllForType(this.type).
then(function(translators) {
me._potentialTranslators = []; me._potentialTranslators = [];
me._foundTranslators = translators; me._foundTranslators = translators;
me.complete(true); me.complete(true);
return me._foundTranslators;
}); });
if(this._currentState === null) return this._foundTranslators;
} else { } else {
return Zotero.Translate.Base.prototype.getTranslators.call(this); return Zotero.Translate.Base.prototype.getTranslators.call(this);
} }
@ -2113,12 +2079,17 @@ Zotero.Translate.Export.prototype.complete = function(returnValue, error) {
* Overload {@link Zotero.Translate.Base#getTranslators} to return all translators immediately * Overload {@link Zotero.Translate.Base#getTranslators} to return all translators immediately
*/ */
Zotero.Translate.Export.prototype.getTranslators = function() { Zotero.Translate.Export.prototype.getTranslators = function() {
if(this._currentState === "detect") throw new Error("getTranslators: detection is already running"); if(this._currentState === "detect") {
this._currentState = "detect"; return Q.reject(new Error("getTranslators: detection is already running"));
this._foundTranslators = Zotero.Translators.getAllForType(this.type); }
this._potentialTranslators = []; var me = this;
this.complete(true); return Zotero.Translators.getAllForType(this.type).then(function(translators) {
return this._foundTranslators; me._currentState = "detect";
me._foundTranslators = translators;
me._potentialTranslators = [];
me.complete(true);
return me._foundTranslators;
});
} }
/** /**

View File

@ -37,9 +37,7 @@ Zotero.Translators = new function() {
/** /**
* Initializes translator cache, loading all relevant translators into memory * Initializes translator cache, loading all relevant translators into memory
*/ */
this.init = Q.async(function() { this.reinit = Q.async(function() {
_initialized = true;
var start = (new Date()).getTime(); var start = (new Date()).getTime();
var transactionStarted = false; var transactionStarted = false;
@ -136,6 +134,7 @@ Zotero.Translators = new function() {
Zotero.debug("Cached "+i+" translators in "+((new Date()).getTime() - start)+" ms"); Zotero.debug("Cached "+i+" translators in "+((new Date()).getTime() - start)+" ms");
}); });
this.init = Zotero.lazy(this.reinit);
/** /**
* Gets the translator that corresponds to a given ID * Gets the translator that corresponds to a given ID
@ -144,15 +143,10 @@ Zotero.Translators = new function() {
* retrieved. If no callback is specified, translators are * retrieved. If no callback is specified, translators are
* returned. * returned.
*/ */
this.get = function(id, callback) { this.get = function(id) {
if(!_initialized) this.init(); return this.init().then(function() {
var translator = _translators[id] ? _translators[id] : false; return _translators[id] ? _translators[id] : false
});
if(callback) {
callback(translator);
return true;
}
return translator;
} }
/** /**
@ -162,23 +156,19 @@ Zotero.Translators = new function() {
* retrieved. If no callback is specified, translators are * retrieved. If no callback is specified, translators are
* returned. * returned.
*/ */
this.getAllForType = function(type, callback) { this.getAllForType = function(type) {
if(!_initialized) this.init() return this.init().then(function() {
return _cache[type].slice();
var translators = _cache[type].slice(0); });
if(callback) {
callback(translators);
return true;
}
return translators;
} }
/** /**
* Gets all translators for a specific type of translation * Gets all translators for a specific type of translation
*/ */
this.getAll = function() { this.getAll = function() {
if(!_initialized) this.init(); return this.init().then(function() {
return [translator for each(translator in _translators)]; return [translator for each(translator in _translators)];
});
} }
/** /**
@ -191,7 +181,7 @@ Zotero.Translators = new function() {
* argument. * argument.
*/ */
this.getWebTranslatorsForLocation = function(uri, callback) { this.getWebTranslatorsForLocation = function(uri, callback) {
var allTranslators = this.getAllForType("web"); return this.getAllForType("web").then(function(allTranslators) {
var potentialTranslators = []; var potentialTranslators = [];
var properHosts = []; var properHosts = [];
@ -256,11 +246,8 @@ Zotero.Translators = new function() {
} }
} }
if(callback) { return [potentialTranslators, converterFunctions];
callback([potentialTranslators, converterFunctions]); });
return true;
}
return potentialTranslators;
} }
/** /**
@ -271,7 +258,7 @@ Zotero.Translators = new function() {
* returned. * returned.
*/ */
this.getImportTranslatorsForLocation = function(location, callback) { this.getImportTranslatorsForLocation = function(location, callback) {
var allTranslators = Zotero.Translators.getAllForType("import"); return Zotero.Translators.getAllForType("import").then(function(allTranslators) {
var tier1Translators = []; var tier1Translators = [];
var tier2Translators = []; var tier2Translators = [];
@ -289,6 +276,7 @@ Zotero.Translators = new function() {
return true; return true;
} }
return translators; return translators;
});
} }
/** /**