Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
bwiernik committed Nov 29, 2017
0 parents commit c562f7d
Show file tree
Hide file tree
Showing 15 changed files with 767 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.project
373 changes: 373 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Zotero Short DOI Lookup

This is an add-on for Zotero, a research source management tool. The add-on can look up Short DOI codes using http://shortdoi.org and store them for Zotero items.

Please report any bugs, questions, or feature requests on the Zotero forums.

Code for this extension is based heavily on [Zotero Google Scholar Citations](https://github.com/beloglazov/zotero-scholar-citations) by Anton Beloglazov

# License

Copyright (C) 2017 Brenton M. Wiernik

Distributed under the Mozilla Public License (MPL).
5 changes: 5 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh

version=0.1.0
rm builds/zotero-shortdoi-${version}-fx.xpi
zip -r builds/zotero-shortdoi-${version}-fx.xpi chrome/* chrome.manifest install.rdf options.xul
Binary file added builds/zotero-shortdoi-0.1.0-fx.xpi
Binary file not shown.
5 changes: 5 additions & 0 deletions chrome.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
content zoteroshortdoi chrome/content/

overlay chrome://zotero/content/zoteroPane.xul chrome://zoteroshortdoi/content/overlay.xul

locale zoteroshortdoi en-US chrome/locale/en-US/
34 changes: 34 additions & 0 deletions chrome/content/overlay.xul
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0"?>

<!DOCTYPE overlay SYSTEM "chrome://zoteroshortdoi/locale/overlay.dtd">

<overlay
id="zoteroshortdoi"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

<script
type="application/x-javascript"
src="chrome://zoteroshortdoi/content/scripts/zoteroshortdoi.js"/>

<stringbundleset id="stringbundleset">
<stringbundle
id="zoteroshortdoi-bundle"
src="chrome://zoteroshortdoi/locale/zoteroshortdoi.properties"/>
</stringbundleset>

<popup id="zotero-collectionmenu">
<menuitem
id="zotero-collectionmenu-zoteroshortdoi"
label="&zotero.zoteroshortdoi.update.label;"
oncommand="Zotero.ShortDOI.updateSelectedEntity()"/>
</popup>

<popup
id="zotero-itemmenu"
onpopupshowing="ZoteroPane.buildItemContextMenu();">
<menuitem
id="zotero-itemmenu-zoteroshortdoi"
label="&zotero.zoteroshortdoi.update.label;"
oncommand="Zotero.ShortDOI.updateSelectedItems()"/>
</popup>
</overlay>
273 changes: 273 additions & 0 deletions chrome/content/scripts/zoteroshortdoi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm");

if (typeof Zotero === 'undefined') {
Zotero = {};
}
Zotero.ShortDOI = {};

const PREF_BRANCH = 'extensions.shortdoi.';
const PREFS = {
savelong: true
};

function getPref(key) {
// Cache the prefbranch after first use
if (getPref.branch == null)
getPref.branch = Services.prefs.getBranch(PREF_BRANCH);

// Figure out what type of pref to fetch
switch (typeof PREFS[key]) {
case "boolean":
return getPref.branch.getBoolPref(key);
case "number":
return getPref.branch.getIntPref(key);
case "string":
return getPref.branch.getCharPref(key);
}
}

function setDefaultPrefs() {
let branch = Services.prefs.getDefaultBranch(PREF_BRANCH);
for (let [key, val] in Iterator(PREFS)) {
switch (typeof val) {
case "boolean":
branch.setBoolPref(key, val);
break;
case "number":
branch.setIntPref(key, val);
break;
case "string":
branch.setCharPref(key, val);
break;
}
}
}

var prefObserver = {
register: function() {
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);

this.branch = prefService.getBranch(PREF_BRANCH);

// Now we queue the interface called nsIPrefBranch2. This interface is described as:
// "nsIPrefBranch2 allows clients to observe changes to pref values."
// This is only necessary prior to Gecko 13
if (!("addObserver" in this.branch))
this.branch.QueryInterface(Components.interfaces.nsIPrefBranch2);

// Finally add the observer.
this.branch.addObserver("", this, false);
},

unregister: function() {
this.branch.removeObserver("", this);
},

observe: function(aSubject, aTopic, aData) {
switch (aData) {
case "savelong":
Zotero.ShortDOI.savelong = getPref("savelong")
break;
}
}
}

Zotero.ShortDOI.init = function() {
setDefaultPrefs();
Zotero.ShortDOI.resetState();

stringBundle = document.getElementById('zoteroshortdoi-bundle');
Zotero.ShortDOI.DOInotfoundString = 'DOI not found. taking you to http://shortdoi.org to view the error.';
if (stringBundle != null) {
Zotero.ShortDOI.DOInotfoundString = stringBundle.getString('DOInotfoundString');
}

// Register the callback in Zotero as an item observer
var notifierID = Zotero.Notifier.registerObserver(
Zotero.ShortDOI.notifierCallback, ['item']);
prefObserver.register();

Zotero.ShortDOI.savelong = getPref("savelong")

// Unregister callback when the window closes (important to avoid a memory leak)
window.addEventListener('unload', function(e) {
Zotero.Notifier.unregisterObserver(notifierID);
prefObserver.unregister();
}, false);

};

Zotero.ShortDOI.notifierCallback = {
notify: function(event, type, ids, extraData) {
if (event == 'add') {
Zotero.ShortDOI.updateItems(Zotero.Items.get(ids));
}
}
};

Zotero.ShortDOI.resetState = function() {
Zotero.ShortDOI.current = -1;
Zotero.ShortDOI.toUpdate = 0;
Zotero.ShortDOI.itemsToUpdate = null;
Zotero.ShortDOI.numberOfUpdatedItems = 0;
};

Zotero.ShortDOI.updateSelectedEntity = function(libraryId) {
if (!ZoteroPane.canEdit()) {
ZoteroPane.displayCannotEditLibraryMessage();
return;
}

var collection = ZoteroPane.getSelectedCollection();
var group = ZoteroPane.getSelectedGroup();

if (collection) {
var items = [];
collection.getChildItems(false).forEach(function (item) {
items.push(Zotero.Items.get(item.id));
});
Zotero.ShortDOI.updateItems(items);
} else if (group) {
if (!group.editable) {
alert("This group is not editable!");
return;
}
var items = [];
group.getCollections().forEach(function(collection) {
collection.getChildItems(false).forEach(function(item) {
items.push(Zotero.Items.get(item.id));
})
});
Zotero.ShortDOI.updateItems(items);
} else {
Zotero.ShortDOI.resetState();
return;
}
};

Zotero.ShortDOI.updateSelectedItems = function() {
Zotero.ShortDOI.updateItems(ZoteroPane.getSelectedItems());
};

Zotero.ShortDOI.updateItems = function(items) {
if (items.length == 0 ||
Zotero.ShortDOI.numberOfUpdatedItems < Zotero.ShortDOI.toUpdate) {
return;
}

Zotero.ShortDOI.resetState();
Zotero.ShortDOI.toUpdate = items.length;
Zotero.ShortDOI.itemsToUpdate = items;
Zotero.ShortDOI.updateNextItem();
};

Zotero.ShortDOI.updateNextItem = function() {
Zotero.ShortDOI.numberOfUpdatedItems++;

if (Zotero.ShortDOI.current == Zotero.ShortDOI.toUpdate - 1) {
Zotero.ShortDOI.resetState();
return;
}

Zotero.ShortDOI.current++;
Zotero.ShortDOI.updateItem(
Zotero.ShortDOI.itemsToUpdate[Zotero.ShortDOI.current]);
};

Zotero.ShortDOI.generateItemUrl = function(item, attempt) {
var baseURL = 'http://shortdoi.org/';
var doi = item.getField('DOI');
if(doi && typeof doi === "string") {
doi = Zotero.Utilities.cleanDOI(doi);
if(doi) {
if(!!doi.match(/10\/[^\s]*[^\s\.,]/)) {
return false;
}
if(attempt === "initial") {
var url = baseURL + encodeURIComponent(doi) + '?format=json';
} else {
var url = baseURL + encodeURIComponent(doi);
}

return url;
}
}

return false;
};

Zotero.ShortDOI.updateItem = function(item) {
var req = new XMLHttpRequest();
var url = Zotero.ShortDOI.generateItemUrl(item, "initial");
req.open('GET', url, true);

req.onreadystatechange = function() {
if (req.readyState == 4) {
if (req.status == 200 && req.responseText !== '') {
if (item.isRegularItem() && !item.isCollection()) {
var doiResponse = JSON.parse(req.responseText);
var shortDOI = doiResponse.ShortDOI;
if(Zotero.ShortDOI.savelong) {
var longDOI = doiResponse.DOI;
var longDOIstring = 'Long DOI: ' + longDOI + ' '
try {
var old = item.getField('extra')
if (old.length == 0 || old.search(/^Long DOI: *[^\s]+$/) != -1) {//If empty or just Long DOI:
item.setField('extra', longDOIstring);
} else if (old.search(/^Long DOI: *[^\s]+/) != -1) {//If the field starts with Long DOI:
item.setField(
'extra',
old.replace(/^Long DOI: *[^\s]+ ?/, longDOIstring));
} else if (old.search(/\nLong DOI: *[^\s]+/) != -1) { //If there are citations and somthing else on same line
item.setField(
'extra',
old.replace(/\nLong DOI: *[^\s]+ ?/, ' \n' + longDOIstring));
} else {
item.setField('extra', old + ' \n' + longDOIstring);
}
item.setField('DOI', shortDOI);
item.saveTx();
} catch (e) {}
} else {
item.setField('DOI', shortDOI);
item.saveTx();
}
}
Zotero.ShortDOI.updateNextItem();
} else if (req.status == 200 ||
req.status == 403 ||
req.status == 503) {
alert(Zotero.ShortDOI.DOInotfoundString);
var url2 = Zotero.ShortDOI.generateItemUrl(item, "notfound");
req2 = new XMLHttpRequest();
req2.open('GET', url2, true);
req2.onreadystatechange = function() {
if (req2.readyState == 4) {
if (typeof Zotero.launchURL !== 'undefined') {
Zotero.launchURL(url);
} else if (typeof Zotero.openInViewer !== 'undefined') {
Zotero.openInViewer(url);
} else if (typeof ZoteroStandalone !== 'undefined') {
ZoteroStandalone.openInViewer(url);
} else {
window.gBrowser.loadOneTab(
url, {inBackground: false});
}
Zotero.ShortDOI.resetState();
}
}
req2.send(null);
}
}
};

req.send(null);
};

if (typeof window !== 'undefined') {
window.addEventListener('load', function(e) {
Zotero.ShortDOI.init();
}, false);
}
1 change: 1 addition & 0 deletions chrome/locale/en-US/overlay.dtd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!ENTITY zotero.zoteroshortdoi.update.label "Get Short DOIs">
1 change: 1 addition & 0 deletions chrome/locale/en-US/zoteroshortdoi.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DOInotfoundString=DOI not found. taking you to http://shortdoi.org to view the error.
1 change: 1 addition & 0 deletions defaults/preferences/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pref("extensions.shortdoi.savelong", true);
31 changes: 31 additions & 0 deletions install.rdf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0"?>
<RDF:RDF
xmlns:em="http://www.mozilla.org/2004/em-rdf#"
xmlns:NC="http://home.netscape.com/NC-rdf#"
xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<RDF:Description
RDF:about="rdf:#$x61SL3"
em:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
em:minVersion="2.0"
em:maxVersion="20.*"/>
<RDF:Description
RDF:about="urn:mozilla:install-manifest"
em:id="zoteroshortdoi@wiernik.org"
em:name="Zotero Short DOI Lookup"
em:version="0.1.0"
em:type="2"
em:creator="Brenton M. Wiernik"
em:description="Zotero plugin for auto-fetching Short DOI names"
em:homepageURL="http://wiernik.org/software"
em:updateURL="https://raw.githubusercontent.com/bwiernik/zotero-shortdoi/master/update.rdf">
<em:type>2</em:type>
<em:targetApplication RDF:resource="rdf:#$x61SL3"/>
<em:targetApplication>
<Description>
<em:id>zotero@chnm.gmu.edu</em:id>
<em:minVersion>3.0b1</em:minVersion>
<em:maxVersion>5.0.*</em:maxVersion>
</Description>
</em:targetApplication>
</RDF:Description>
</RDF:RDF>
4 changes: 4 additions & 0 deletions options.xul
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" ?>
<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<setting pref="extensions.shortdoi.savelong" title="Save Long DOI in Extra" type="bool"/>
</vbox>
Loading

0 comments on commit c562f7d

Please sign in to comment.