045780d9ac
MODS uses the encoding as specified in the <?xml tag, or else UTF-8 RIS uses IBM850, since the spec says "IBM Extended Character Set" and it's the only code page Mozilla supports. (should I do this? or just use unicode?) MARC uses UTF-8, since I don't think there's any way to get full MARC-8 support, and UTF-8 is now the preferred encoding anyway
440 lines
14 KiB
JavaScript
440 lines
14 KiB
JavaScript
var Scholar_File_Interface = new function() {
|
|
var _unresponsiveScriptPreference, _importCollection, _notifyItem, _notifyCollection;
|
|
|
|
this.exportFile = exportFile;
|
|
this.exportCollection = exportCollection;
|
|
this.exportItems = exportItems;
|
|
this.importFile = importFile;
|
|
this.bibliographyFromCollection = bibliographyFromCollection;
|
|
this.bibliographyFromItems = bibliographyFromItems;
|
|
|
|
/*
|
|
* Creates Scholar.Translate instance and shows file picker for file export
|
|
*/
|
|
function exportFile(name, items) {
|
|
var translation = new Scholar.Translate("export");
|
|
var translators = translation.getTranslators();
|
|
|
|
// present options dialog
|
|
var io = {translators:translators}
|
|
window.openDialog("chrome://scholar/content/exportOptions.xul",
|
|
"_blank", "chrome,modal,centerscreen", io);
|
|
if(!io.selectedTranslator) {
|
|
return false;
|
|
}
|
|
|
|
const nsIFilePicker = Components.interfaces.nsIFilePicker;
|
|
var fp = Components.classes["@mozilla.org/filepicker;1"]
|
|
.createInstance(nsIFilePicker);
|
|
|
|
fp.init(window, Scholar.getString("fileInterface.export"), nsIFilePicker.modeSave);
|
|
|
|
// set file name and extension
|
|
name = (name ? name : Scholar.getString("pane.collections.library"));
|
|
fp.defaultString = name+"."+io.selectedTranslator.target;
|
|
fp.appendFilter(io.selectedTranslator.label, "*."+io.selectedTranslator.target);
|
|
|
|
var rv = fp.show();
|
|
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
|
|
if(items) {
|
|
translation.setItems(items);
|
|
}
|
|
translation.setLocation(fp.file);
|
|
translation.setTranslator(io.selectedTranslator);
|
|
translation.setHandler("done", _exportDone);
|
|
_disableUnresponsive();
|
|
Scholar_File_Interface.Progress.show(
|
|
Scholar.getString("fileInterface.itemsExported"),
|
|
function() {
|
|
translation.translate();
|
|
});
|
|
}
|
|
}
|
|
|
|
/*
|
|
* exports a collection or saved search
|
|
*/
|
|
function exportCollection() {
|
|
var collection = ScholarPane.getSelectedCollection();
|
|
if (collection)
|
|
{
|
|
exportFile(collection.getName(), Scholar.getItems(collection.getID()));
|
|
return;
|
|
}
|
|
|
|
var searchRef = ScholarPane.getSelectedSavedSearch();
|
|
if (searchRef)
|
|
{
|
|
var search = new Scholar.Search();
|
|
search.load(searchRef['id']);
|
|
exportFile(search.getName(), Scholar.Items.get(search.search()));
|
|
return;
|
|
}
|
|
|
|
throw ("No collection or saved search currently selected");
|
|
}
|
|
|
|
|
|
/*
|
|
* exports items
|
|
*/
|
|
function exportItems() {
|
|
var items = ScholarPane.getSelectedItems();
|
|
if(!items || !items.length) throw("no items currently selected");
|
|
|
|
exportFile(Scholar.getString("fileInterface.exportedItems"), items);
|
|
}
|
|
|
|
/*
|
|
* closes items exported indicator
|
|
*/
|
|
function _exportDone(obj, worked) {
|
|
Scholar_File_Interface.Progress.close();
|
|
_restoreUnresponsive();
|
|
|
|
if(!worked) {
|
|
window.alert(Scholar.getString("fileInterface.exportError"));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Creates Scholar.Translate instance and shows file picker for file import
|
|
*/
|
|
function importFile() {
|
|
var translation = new Scholar.Translate("import");
|
|
var translators = translation.getTranslators();
|
|
|
|
const nsIFilePicker = Components.interfaces.nsIFilePicker;
|
|
var fp = Components.classes["@mozilla.org/filepicker;1"]
|
|
.createInstance(nsIFilePicker);
|
|
fp.init(window, Scholar.getString("fileInterface.import"), nsIFilePicker.modeOpen);
|
|
|
|
fp.appendFilters(nsIFilePicker.filterAll);
|
|
for(var i in translators) {
|
|
fp.appendFilter(translators[i].label, "*."+translators[i].target);
|
|
}
|
|
|
|
var rv = fp.show();
|
|
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
|
|
translation.setLocation(fp.file);
|
|
// get translators again, bc now we can check against the file
|
|
translators = translation.getTranslators();
|
|
if(translators.length) {
|
|
// create a new collection to take in imported items
|
|
var date = new Date();
|
|
_importCollection = Scholar.Collections.add(Scholar.getString("fileInterface.imported")+" "+date.toLocaleString());
|
|
|
|
// import items
|
|
translation.setTranslator(translators[0]);
|
|
translation.setHandler("collectionDone", _importCollectionDone);
|
|
translation.setHandler("done", _importDone);
|
|
_disableUnresponsive();
|
|
|
|
// disable notifier
|
|
Scholar.Notifier.disable();
|
|
|
|
// show progress indicator
|
|
Scholar_File_Interface.Progress.show(
|
|
Scholar.getString("fileInterface.itemsImported"),
|
|
function() {
|
|
translation.translate();
|
|
});
|
|
} else {
|
|
window.alert(Scholar.getString("fileInterface.fileFormatUnsupported"));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Saves collections after they've been imported. Input item is of the type
|
|
* outputted by Scholar.Collection.toArray(); only receives top-level
|
|
* collections
|
|
*/
|
|
function _importCollectionDone(obj, collection) {
|
|
Scholar.Notifier.enable();
|
|
Scholar.Notifier.trigger("add", "collection", collection.getID());
|
|
collection.changeParent(_importCollection.getID());
|
|
Scholar.Notifier.disable();
|
|
}
|
|
|
|
/*
|
|
* closes items imported indicator
|
|
*/
|
|
function _importDone(obj, worked) {
|
|
// add items to import collection
|
|
for each(var itemID in obj.newItems) {
|
|
_importCollection.addItem(itemID);
|
|
}
|
|
|
|
// run notify
|
|
Scholar.Notifier.enable();
|
|
if(obj.newItems.length) {
|
|
Scholar.Notifier.trigger("add", "item", obj.newItems);
|
|
Scholar.Notifier.trigger("modify", "collection", _importCollection.getID());
|
|
}
|
|
|
|
Scholar_File_Interface.Progress.close();
|
|
_restoreUnresponsive();
|
|
|
|
if(!worked) {
|
|
window.alert(Scholar.getString("fileInterface.importError"));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* disables the "unresponsive script" warning; necessary for import and
|
|
* export, which can take quite a while to execute
|
|
*/
|
|
function _disableUnresponsive() {
|
|
var prefService = Components.classes["@mozilla.org/preferences-service;1"].
|
|
getService(Components.interfaces.nsIPrefBranch);
|
|
_unresponsiveScriptPreference = prefService.getIntPref("dom.max_script_run_time");
|
|
prefService.setIntPref("dom.max_script_run_time", 0);
|
|
}
|
|
|
|
/*
|
|
* restores the "unresponsive script" warning
|
|
*/
|
|
function _restoreUnresponsive() {
|
|
var prefService = Components.classes["@mozilla.org/preferences-service;1"].
|
|
getService(Components.interfaces.nsIPrefBranch);
|
|
prefService.setIntPref("dom.max_script_run_time", _unresponsiveScriptPreference);
|
|
}
|
|
|
|
/*
|
|
* Creates a bibliography from a collection or saved search
|
|
*/
|
|
function bibliographyFromCollection() {
|
|
var collection = ScholarPane.getSelectedCollection();
|
|
if (collection)
|
|
{
|
|
_doBibliographyOptions(collection.getName(), Scholar.getItems(collection.getID()));
|
|
return;
|
|
}
|
|
|
|
var searchRef = ScholarPane.getSelectedSavedSearch();
|
|
if (searchRef)
|
|
{
|
|
var search = new Scholar.Search();
|
|
search.load(searchRef['id']);
|
|
_doBibliographyOptions(search.getName(), Scholar.Items.get(search.search()));
|
|
return;
|
|
}
|
|
|
|
throw ("No collection or saved search currently selected");
|
|
}
|
|
|
|
/*
|
|
* Creates a bibliography from a items
|
|
*/
|
|
function bibliographyFromItems() {
|
|
var items = ScholarPane.getSelectedItems();
|
|
if(!items || !items.length) throw("no items currently selected");
|
|
|
|
_doBibliographyOptions(Scholar.getString("fileInterface.untitledBibliography"), items);
|
|
}
|
|
|
|
/*
|
|
* Shows bibliography options and creates a bibliography
|
|
*/
|
|
function _doBibliographyOptions(name, items) {
|
|
// make sure at least one item is not a standalone note or attachment
|
|
var haveNonNote = false;
|
|
for(var i in items) {
|
|
var type = Scholar.ItemTypes.getName(items[i].getType());
|
|
if(type != "note" && type != "attachment") {
|
|
haveNonNote = true;
|
|
break;
|
|
}
|
|
}
|
|
if(!haveNonNote) {
|
|
window.alert(Scholar.getString("fileInterface.noReferencesError"));
|
|
return;
|
|
}
|
|
|
|
var io = new Object();
|
|
var newDialog = window.openDialog("chrome://scholar/content/bibliography.xul",
|
|
"_blank","chrome,modal,centerscreen", io);
|
|
|
|
// determine output format
|
|
var format = "HTML";
|
|
if(io.output == "save-as-rtf") {
|
|
format = "RTF";
|
|
}
|
|
|
|
// generate bibliography
|
|
try {
|
|
var csl = Scholar.Cite.getStyle(io.style);
|
|
csl.preprocessItems(items);
|
|
var bibliography = csl.createBibliography(items, format);
|
|
} catch(e) {
|
|
window.alert(Scholar.getString("fileInterface.bibliographyGenerationError"));
|
|
throw(e);
|
|
return;
|
|
}
|
|
|
|
if(io.output == "print") {
|
|
// printable bibliography, using a hidden browser
|
|
var browser = Scholar.Browser.createHiddenBrowser(window);
|
|
browser.contentDocument.write(bibliography);
|
|
|
|
// this is kinda nasty, but we have to temporarily modify the user's
|
|
// settings to eliminate the header and footer. the other way to do
|
|
// this would be to attempt to print with an embedded browser, but
|
|
// it's not even clear how to attempt to create one
|
|
var prefService = Components.classes["@mozilla.org/preferences-service;1"].
|
|
getService(Components.interfaces.nsIPrefBranch);
|
|
var prefsToClear = ["print.print_headerleft", "print.print_headercenter",
|
|
"print.print_headerright", "print.print_footerleft",
|
|
"print.print_footercenter", "print.print_footerright"];
|
|
var oldPrefs = new Array();
|
|
for(var i in prefsToClear) {
|
|
oldPrefs[i] = prefService.getCharPref(prefsToClear[i]);
|
|
prefService.setCharPref(prefsToClear[i], "");
|
|
}
|
|
|
|
// print
|
|
browser.contentWindow.print();
|
|
|
|
// set the prefs back
|
|
for(var i in prefsToClear) {
|
|
prefService.setCharPref(prefsToClear[i], oldPrefs[i]);
|
|
}
|
|
|
|
Scholar.Browser.deleteHiddenBrowser(browser);
|
|
} else if(io.output == "save-as-html") {
|
|
var fStream = _saveBibliography(name, "HTML");
|
|
|
|
if(fStream !== false) {
|
|
var html = "";
|
|
html +='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n';
|
|
html +='<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\n';
|
|
html +='<head>\n';
|
|
html +='<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>\n';
|
|
html +='<title>'+Scholar.getString("fileInterface.bibliographyHTMLTitle")+'</title>\n';
|
|
html +='</head>\n';
|
|
html +='<body>\n';
|
|
html += bibliography;
|
|
html +='</body>\n';
|
|
html +='</html>\n';
|
|
|
|
// create UTF-8 output stream
|
|
var os = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
|
|
createInstance(Components.interfaces.nsIConverterOutputStream);
|
|
os.init(fStream, "UTF-8", 0, "?".charCodeAt(0));
|
|
|
|
os.writeString(html);
|
|
|
|
os.close();
|
|
fStream.close();
|
|
}
|
|
} else if(io.output == "save-as-rtf") {
|
|
var fStream = _saveBibliography(name, "RTF");
|
|
if(fStream !== false) {
|
|
fStream.write(bibliography, bibliography.length);
|
|
fStream.close();
|
|
}
|
|
} else if(io.output == "copy-to-clipboard") {
|
|
// copy to clipboard
|
|
var transferable = Components.classes["@mozilla.org/widget/transferable;1"].
|
|
createInstance(Components.interfaces.nsITransferable);
|
|
var clipboardService = Components.classes["@mozilla.org/widget/clipboard;1"].
|
|
getService(Components.interfaces.nsIClipboard);
|
|
|
|
// add HTML
|
|
var str = Components.classes["@mozilla.org/supports-string;1"].
|
|
createInstance(Components.interfaces.nsISupportsString);
|
|
str.data = bibliography;
|
|
transferable.addDataFlavor("text/html");
|
|
transferable.setTransferData("text/html", str, bibliography.length*2);
|
|
// add text
|
|
var bibliography = csl.createBibliography(items, "Text");
|
|
var str = Components.classes["@mozilla.org/supports-string;1"].
|
|
createInstance(Components.interfaces.nsISupportsString);
|
|
str.data = bibliography;
|
|
transferable.addDataFlavor("text/unicode");
|
|
transferable.setTransferData("text/unicode", str, bibliography.length*2);
|
|
|
|
clipboardService.setData(transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
|
|
}
|
|
}
|
|
|
|
function _saveBibliography(name, format) {
|
|
// savable bibliography, using a file stream
|
|
const nsIFilePicker = Components.interfaces.nsIFilePicker;
|
|
var fp = Components.classes["@mozilla.org/filepicker;1"]
|
|
.createInstance(nsIFilePicker);
|
|
fp.init(window, "Save Bibliography", nsIFilePicker.modeSave);
|
|
|
|
if(format == "RTF") {
|
|
var extension = "rtf";
|
|
fp.appendFilter("RTF", "*.rtf");
|
|
} else {
|
|
var extension = "html";
|
|
fp.appendFilters(nsIFilePicker.filterHTML);
|
|
}
|
|
|
|
fp.defaultString = name+"."+extension;
|
|
|
|
var rv = fp.show();
|
|
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
|
|
// open file
|
|
var fStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
|
|
createInstance(Components.interfaces.nsIFileOutputStream);
|
|
fStream.init(fp.file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
|
|
return fStream;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handles the display of a progress indicator
|
|
Scholar_File_Interface.Progress = new function() {
|
|
var _windowLoaded = false;
|
|
var _windowLoading = false;
|
|
var _progressWindow;
|
|
// keep track of all of these things in case they're called before we're
|
|
// done loading the progress window
|
|
var _loadHeadline, _loadNumber, _outOf, _callback;
|
|
|
|
this.show = show;
|
|
this.close = close;
|
|
|
|
function show(headline, callback) {
|
|
if(_windowLoading || _windowLoaded) { // already loading or loaded
|
|
_progressWindow.focus();
|
|
return false;
|
|
}
|
|
_windowLoading = true;
|
|
|
|
_loadHeadline = headline;
|
|
_loadNumber = 0;
|
|
_outOf = 0;
|
|
_callback = callback;
|
|
|
|
_progressWindow = window.openDialog("chrome://scholar/chrome/fileProgress.xul", "", "chrome,resizable=no,close=no,dependent,dialog,centerscreen");
|
|
_progressWindow.addEventListener("pageshow", _onWindowLoaded, false);
|
|
|
|
return true;
|
|
}
|
|
|
|
function close() {
|
|
_windowLoaded = false;
|
|
try {
|
|
_progressWindow.close();
|
|
} catch(ex) {}
|
|
}
|
|
|
|
function _onWindowLoaded() {
|
|
_windowLoading = false;
|
|
_windowLoaded = true;
|
|
|
|
// do things we delayed because the winodw was loading
|
|
_progressWindow.document.getElementById("progress-label").value = _loadHeadline;
|
|
|
|
if(_callback) {
|
|
window.setTimeout(_callback, 1500);
|
|
}
|
|
}
|
|
}
|