closes #214, add footnote support to word integration
closes #215, allow user to select desired citation style and change citation styles on the fly
This commit is contained in:
parent
0515e4cb9e
commit
10f4b28c63
BIN
Zotero.dot.dmg
BIN
Zotero.dot.dmg
Binary file not shown.
|
@ -265,7 +265,9 @@ var Scholar_File_Interface = new function() {
|
|||
}
|
||||
|
||||
// generate bibliography
|
||||
var bibliography = Scholar.Cite.getBibliography(io.style, items, format);
|
||||
var csl = Scholar.Cite.getStyle(io.style);
|
||||
csl.preprocessItems(items);
|
||||
var bibliography = csl.createBibliography(items, format);
|
||||
|
||||
if(io.output == "print") {
|
||||
// printable bibliography, using a hidden browser
|
||||
|
@ -343,7 +345,7 @@ var Scholar_File_Interface = new function() {
|
|||
transferable.addDataFlavor("text/html");
|
||||
transferable.setTransferData("text/html", str, bibliography.length*2);
|
||||
// add text
|
||||
var bibliography = Scholar.Cite.getBibliography(io.style, items, "Text");
|
||||
var bibliography = csl.createBibliography(items, "Text");
|
||||
var str = Components.classes["@mozilla.org/supports-string;1"].
|
||||
createInstance(Components.interfaces.nsISupportsString);
|
||||
str.data = bibliography;
|
||||
|
|
|
@ -10,9 +10,7 @@ Scholar.Cite = new function() {
|
|||
var _lastStyle = null;
|
||||
|
||||
this.getStyles = getStyles;
|
||||
this.getStyleClass = getStyleClass;
|
||||
this.getBibliography = getBibliography;
|
||||
this.getCitation = getCitation;
|
||||
this.getStyle = getStyle;
|
||||
|
||||
/*
|
||||
* returns an associative array of cslID => styleName pairs
|
||||
|
@ -30,46 +28,11 @@ Scholar.Cite = new function() {
|
|||
|
||||
return stylesObject;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the class of a given style
|
||||
*/
|
||||
function getStyleClass(cslID) {
|
||||
var csl = _getCSL(cslID);
|
||||
return csl.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* generates a bibliography
|
||||
*/
|
||||
function getBibliography(cslID, items, format) {
|
||||
var csl = _getCSL(cslID);
|
||||
|
||||
// set items
|
||||
csl.setItems(items);
|
||||
|
||||
// generate bibliography
|
||||
return csl.createBibliography(format);
|
||||
}
|
||||
|
||||
/*
|
||||
* generates a bibliography
|
||||
*/
|
||||
function getCitation(cslID, item, items, format) {
|
||||
var csl = _getCSL(cslID);
|
||||
|
||||
// set items
|
||||
csl.setItems(items);
|
||||
|
||||
// generate bibliography
|
||||
return csl.createCitation(item, format);
|
||||
}
|
||||
|
||||
/*
|
||||
* gets CSL from the database, or, if it's the most recently used style,
|
||||
* from the cache
|
||||
*/
|
||||
function _getCSL(cslID) {
|
||||
function getStyle(cslID) {
|
||||
if(_lastStyle != cslID || Scholar.Prefs.get("cacheTranslatorData") == false) {
|
||||
// get style
|
||||
var sql = "SELECT csl FROM csl WHERE cslID = ?";
|
||||
|
@ -111,64 +74,135 @@ CSL = function(csl) {
|
|||
}
|
||||
// load defaults from CSL
|
||||
this._parseFieldDefaults(this._csl.defaults);
|
||||
// parse bibliography options, since these will be necessary for
|
||||
// disambiguation purposes even for citations
|
||||
// parse bibliography and citation options
|
||||
this._parseBibliographyOptions();
|
||||
this._parseCitationOptions();
|
||||
// if no bibliography exists, parse citation element as bibliography
|
||||
if(!this._bib) {
|
||||
Scholar.debug("CSL: using citation element");
|
||||
if(!this._cit) {
|
||||
this._parseCitationOptions();
|
||||
}
|
||||
Scholar.debug("CSL: using citation element for bibliography");
|
||||
this._bib = this._cit;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* set items - convert to array and pre-process
|
||||
* preprocess items, separating authors, editors, and translators arrays into
|
||||
* separate properties
|
||||
*
|
||||
* must be called prior to generating citations or bibliography with a new set
|
||||
* of items
|
||||
*/
|
||||
CSL.prototype.setItems = function(items) {
|
||||
// create a serialized string of all of the unique items
|
||||
var serializedItemString = "";
|
||||
CSL.prototype.preprocessItems = function(items) {
|
||||
Scholar.debug("CSL: preprocessing items");
|
||||
|
||||
this._items = items;
|
||||
this._uniqueItems = new Array();
|
||||
var existingItems = new Object();
|
||||
for each(var item in items) {
|
||||
var itemID = item.getID();
|
||||
if(!existingItems[itemID]) {
|
||||
existingItems[itemID] = true;
|
||||
this._uniqueItems.push(item);
|
||||
serializedItemString += itemID+",";
|
||||
// get data necessary to generate citations before sorting
|
||||
for(var i in items) {
|
||||
var item = items[i];
|
||||
var dateModified = item.getField("dateModified");
|
||||
|
||||
if(!item._csl || item._csl.dateModified != dateModified) {
|
||||
// namespace everything in item._csl so there's no chance of overlap
|
||||
item._csl = new Object();
|
||||
item._csl.ignore = new Array();
|
||||
item._csl.dateModified = dateModified;
|
||||
|
||||
// separate item into authors, editors, translators
|
||||
var creators = this._separateItemCreators(item);
|
||||
item._csl.authors = creators[0];
|
||||
item._csl.editors = creators[1];
|
||||
item._csl.translators = creators[2];
|
||||
|
||||
// parse date
|
||||
item._csl.date = CSL.prototype._processDate(item.getField("date"));
|
||||
} else {
|
||||
// clear disambiguation and subsequent author substitute
|
||||
if(item._csl.disambiguation) item._csl.date.disambiguation = undefined;
|
||||
if(item._csl.subsequentAuthorSubstitute) item._csl.subsequentAuthorSubstitute = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
Scholar.debug("CSL: items set to "+serializedItemString);
|
||||
// sort by sort order
|
||||
if(this._bib.sortOrder) {
|
||||
Scholar.debug("CSL: sorting items");
|
||||
var me = this;
|
||||
items.sort(function(a, b) {
|
||||
return me._compareItem(a, b);
|
||||
});
|
||||
}
|
||||
|
||||
//if(serializedItemString != this._serializedItemString) {
|
||||
// only re-process if there are new items
|
||||
this._serializedItemString = serializedItemString;
|
||||
this._preprocessItems();
|
||||
//}
|
||||
// disambiguate items after preprocessing and sorting
|
||||
var usedCitations = new Array();
|
||||
var lastAuthor;
|
||||
|
||||
for(var i in items) {
|
||||
var item = items[i];
|
||||
|
||||
var author = this._getFieldValue("author",
|
||||
this._getFieldDefaults("author"),
|
||||
item, "disambiguate", this._bib);
|
||||
|
||||
// handle (2006a) disambiguation for author-date styles
|
||||
if(this.class == "author-date") {
|
||||
var citation = author+" "+this._getFieldValue("date",
|
||||
this._getFieldDefaults("date"),
|
||||
item, "disambiguate", this._bib);
|
||||
|
||||
if(usedCitations[citation]) {
|
||||
if(!usedCitations[citation]._csl.date.disambiguation) {
|
||||
usedCitations[citation]._csl.date.disambiguation = "a";
|
||||
item._csl.date.disambiguation = "b";
|
||||
} else {
|
||||
// get all but last character
|
||||
var oldLetter = usedCitations[citation]._csl.date.disambiguation;
|
||||
if(oldLetter.length > 1) {
|
||||
item._csl.date.disambiguation = oldLetter.substr(0, oldLetter.length-1);
|
||||
} else {
|
||||
item._csl.date.disambiguation = "";
|
||||
}
|
||||
|
||||
var charCode = oldLetter.charCodeAt(oldLetter.length-1);
|
||||
if(charCode == 122) {
|
||||
// item is z; add another letter
|
||||
item._csl.date.disambiguation += "za";
|
||||
} else {
|
||||
// next lowercase letter
|
||||
item._csl.date.disambiguation += String.fromCharCode(charCode+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usedCitations[citation] = item;
|
||||
}
|
||||
|
||||
// add numbers to each
|
||||
item._csl.number = i;
|
||||
|
||||
// handle subsequent author substitutes
|
||||
if(this._bib.subsequentAuthorSubstitute && lastAuthor == author) {
|
||||
item._csl.subsequentAuthorSubstitute = true;
|
||||
}
|
||||
lastAuthor = author;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* create a citation (in-text or footnote)
|
||||
*/
|
||||
CSL.prototype.createCitation = function(items, format) {
|
||||
CSL.prototype.createCitation = function(items, types, format) {
|
||||
Scholar.debug("CSL: creating citation for item "+items[0].getID());
|
||||
if(!this._cit) {
|
||||
this._parseCitationOptions();
|
||||
}
|
||||
|
||||
var string = "";
|
||||
for(var i in items) {
|
||||
if(this._cit.format && this._cit.format.delimiter && string) {
|
||||
// add delimiter if one exists, and this isn't the first element
|
||||
// with content
|
||||
string += this._cit.format.delimiter;
|
||||
if(types == 2) {
|
||||
var string = this._getTerm("ibid", (items.length > 1 ? true : false));
|
||||
string = string[0].toUpperCase()+string.substr(1);
|
||||
} else {
|
||||
var string = "";
|
||||
for(var i in items) {
|
||||
if(this._cit.format && this._cit.format.delimiter && string) {
|
||||
// add delimiter if one exists, and this isn't the first element
|
||||
// with content
|
||||
string += this._cit.format.delimiter;
|
||||
}
|
||||
string += this._getCitation(items[i], (types[i] == 1 ? "first" : "subsequent"), format, this._cit);
|
||||
}
|
||||
string += this._getCitation(items[i], format, this._cit);
|
||||
}
|
||||
|
||||
// add format
|
||||
|
@ -189,11 +223,7 @@ CSL.prototype.createCitation = function(items, format) {
|
|||
* create a bibliography
|
||||
* (items is expected to be an array of items)
|
||||
*/
|
||||
CSL.prototype.createBibliography = function(format) {
|
||||
// preprocess this._items
|
||||
Scholar.debug("CSL: preprocessing items");
|
||||
this._preprocessItems();
|
||||
|
||||
CSL.prototype.createBibliography = function(items, format) {
|
||||
// process this._items
|
||||
var output = "";
|
||||
|
||||
|
@ -212,10 +242,10 @@ CSL.prototype.createBibliography = function(format) {
|
|||
output += "\r\n";
|
||||
}
|
||||
|
||||
for(var i in this._uniqueItems) {
|
||||
var item = this._uniqueItems[i];
|
||||
for(var i in items) {
|
||||
var item = items[i];
|
||||
|
||||
var string = this._getCitation(item, format, this._bib);
|
||||
var string = this._getCitation(item, "first", format, this._bib);
|
||||
|
||||
// add format
|
||||
if(this._bib.format) {
|
||||
|
@ -516,7 +546,7 @@ CSL.prototype._parseFieldDefaults = function(ref) {
|
|||
/*
|
||||
* parses a list of fields into an array of objects
|
||||
*/
|
||||
CSL.prototype._parseFields = function(ref, type, bibCitElement, inheritFormat) {
|
||||
CSL.prototype._parseFields = function(ref, position, type, bibCitElement, inheritFormat) {
|
||||
var typeDesc = new Array();
|
||||
for each(var element in ref) {
|
||||
if(element.namespace() == CSL.ns) { // ignore elements in other namespaces
|
||||
|
@ -535,7 +565,7 @@ CSL.prototype._parseFields = function(ref, type, bibCitElement, inheritFormat) {
|
|||
itemDesc._serialized = this._serializeElement(itemDesc.name, itemDesc);
|
||||
// add to serialization for type
|
||||
if(bibCitElement) {
|
||||
bibCitElement._serializations[type][itemDesc._serialized] = itemDesc;
|
||||
bibCitElement._serializations[position][type][itemDesc._serialized] = itemDesc;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -546,7 +576,7 @@ CSL.prototype._parseFields = function(ref, type, bibCitElement, inheritFormat) {
|
|||
|
||||
var children = element.children();
|
||||
if(children.length()) {
|
||||
itemDesc.children = this._parseFields(children, type, bibCitElement);
|
||||
itemDesc.children = this._parseFields(children, position, type, bibCitElement);
|
||||
}
|
||||
} else {
|
||||
// parse attributes on this field
|
||||
|
@ -640,7 +670,7 @@ CSL.prototype._parseBibliographyOptions = function() {
|
|||
this._bib.sortOrder[0].name = "cited";
|
||||
}
|
||||
} else {
|
||||
this._bib.sortOrder = this._parseFields(bibliography.sort, false, this._bib);
|
||||
this._bib.sortOrder = this._parseFields(bibliography.sort, "first", false, this._bib);
|
||||
}
|
||||
|
||||
// parse et al
|
||||
|
@ -683,22 +713,32 @@ CSL.prototype._parseTypes = function(itemElements, bibCitElement) {
|
|||
|
||||
// find the type item without position="subsequent"
|
||||
for each(var itemElement in itemElements) {
|
||||
if(itemElement.@position.toString() == "subsequent") {
|
||||
// bind subsequent element to position 1
|
||||
bibCitElement._types[1] = itemElement;
|
||||
bibCitElement._serializations[1] = new Object();
|
||||
} else {
|
||||
// create an associative array of available types
|
||||
if(itemElement.choose.length()) {
|
||||
for each(var type in itemElement.choose.type) {
|
||||
bibCitElement._types[type.@name] = type;
|
||||
bibCitElement._serializations[type.@name] = new Object();
|
||||
}
|
||||
} else {
|
||||
// if there's only one type, bind it to index 0
|
||||
bibCitElement._types[0] = itemElement;
|
||||
bibCitElement._serializations[0] = new Object();
|
||||
var position = itemElement.@position.toString();
|
||||
if(position) {
|
||||
// handle ibids
|
||||
if(position == "subsequent" &&
|
||||
itemElement.@ibid.toString() == "true") {
|
||||
this.ibid = true;
|
||||
}
|
||||
} else {
|
||||
position = "first";
|
||||
}
|
||||
|
||||
if(!bibCitElement._types[position]) {
|
||||
bibCitElement._types[position] = new Object();
|
||||
bibCitElement._serializations[position] = new Object();
|
||||
}
|
||||
|
||||
// create an associative array of available types
|
||||
if(itemElement.choose.length()) {
|
||||
for each(var type in itemElement.choose.type) {
|
||||
bibCitElement._types[position][type.@name] = type;
|
||||
bibCitElement._serializations[position][type.@name] = new Object();
|
||||
}
|
||||
} else {
|
||||
// if there's only one type, bind it to index 0
|
||||
bibCitElement._types[position][0] = itemElement;
|
||||
bibCitElement._serializations[position][0] = new Object();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -706,21 +746,22 @@ CSL.prototype._parseTypes = function(itemElements, bibCitElement) {
|
|||
/*
|
||||
* convert reference types to native structures for speed
|
||||
*/
|
||||
CSL.prototype._getTypeObject = function(reftype, bibCitElement) {
|
||||
if(!bibCitElement._types[reftype]) {
|
||||
CSL.prototype._getTypeObject = function(position, reftype, bibCitElement) {
|
||||
if(!bibCitElement._types[position][reftype]) {
|
||||
// no type available
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse type if necessary
|
||||
if(typeof(bibCitElement._types[reftype]) == "xml") {
|
||||
if(typeof(bibCitElement._types[position][reftype]) == "xml") {
|
||||
Scholar.debug("CSL: parsing XML for "+reftype);
|
||||
bibCitElement._types[reftype] = this._parseFields(bibCitElement._types[reftype].children(),
|
||||
reftype, bibCitElement, true);
|
||||
bibCitElement._types[position][reftype] = this._parseFields(
|
||||
bibCitElement._types[position][reftype].children(),
|
||||
position, reftype, bibCitElement, true);
|
||||
}
|
||||
|
||||
Scholar.debug("CSL: got object for "+reftype);
|
||||
return bibCitElement._types[reftype];
|
||||
return bibCitElement._types[position][reftype];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1008,101 +1049,6 @@ CSL.prototype._lpad = function(string, pad, length) {
|
|||
return string;
|
||||
}
|
||||
|
||||
/*
|
||||
* preprocess items, separating authors, editors, and translators arrays into
|
||||
* separate properties
|
||||
*/
|
||||
CSL.prototype._preprocessItems = function() {
|
||||
// get data necessary to generate citations before sorting
|
||||
for(var i in this._uniqueItems) {
|
||||
var item = this._uniqueItems[i];
|
||||
var dateModified = item.getField("dateModified");
|
||||
|
||||
if(!item._csl || item._csl.dateModified != dateModified) {
|
||||
// namespace everything in item._csl so there's no chance of overlap
|
||||
item._csl = new Object();
|
||||
item._csl.ignore = new Array();
|
||||
item._csl.dateModified = dateModified;
|
||||
|
||||
// separate item into authors, editors, translators
|
||||
var creators = this._separateItemCreators(item);
|
||||
item._csl.authors = creators[0];
|
||||
item._csl.editors = creators[1];
|
||||
item._csl.translators = creators[2];
|
||||
|
||||
// parse date
|
||||
item._csl.date = CSL.prototype._processDate(item.getField("date"));
|
||||
} else {
|
||||
// clear disambiguation and subsequent author substitute
|
||||
if(item._csl.disambiguation) item._csl.disambiguation = undefined;
|
||||
if(item._csl.subsequentAuthorSubstitute) item._csl.subsequentAuthorSubstitute = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// sort by sort order
|
||||
if(this._bib.sortOrder) {
|
||||
Scholar.debug("CSL: sorting items");
|
||||
var me = this;
|
||||
this._uniqueItems.sort(function(a, b) {
|
||||
return me._compareItem(a, b);
|
||||
});
|
||||
}
|
||||
|
||||
// disambiguate items after preprocessing and sorting
|
||||
var usedCitations = new Array();
|
||||
var lastAuthor;
|
||||
|
||||
for(var i in this._uniqueItems) {
|
||||
var item = this._uniqueItems[i];
|
||||
|
||||
var author = this._getFieldValue("author",
|
||||
this._getFieldDefaults("author"),
|
||||
item, "disambiguate", this._bib);
|
||||
|
||||
// handle (2006a) disambiguation for author-date styles
|
||||
if(this.class == "author-date") {
|
||||
var citation = author+" "+this._getFieldValue("date",
|
||||
this._getFieldDefaults("date"),
|
||||
item, "disambiguate", this._bib);
|
||||
|
||||
if(usedCitations[citation]) {
|
||||
if(!usedCitations[citation]._csl.date.disambiguation) {
|
||||
usedCitations[citation]._csl.date.disambiguation = "a";
|
||||
item._csl.date.disambiguation = "b";
|
||||
} else {
|
||||
// get all but last character
|
||||
var oldLetter = usedCitations[citation]._csl.date.disambiguation;
|
||||
if(oldLetter.length > 1) {
|
||||
item._csl.date.disambiguation = oldLetter.substr(0, oldLetter.length-1);
|
||||
} else {
|
||||
item._csl.date.disambiguation = "";
|
||||
}
|
||||
|
||||
var charCode = oldLetter.charCodeAt(oldLetter.length-1);
|
||||
if(charCode == 122) {
|
||||
// item is z; add another letter
|
||||
item._csl.date.disambiguation += "za";
|
||||
} else {
|
||||
// next lowercase letter
|
||||
item._csl.date.disambiguation += String.fromCharCode(charCode+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usedCitations[citation] = item;
|
||||
}
|
||||
|
||||
// add numbers to each
|
||||
item._csl.number = i;
|
||||
|
||||
// handle subsequent author substitutes
|
||||
if(this._bib.subsequentAuthorSubstitute && lastAuthor == author) {
|
||||
item._csl.subsequentAuthorSubstitute = true;
|
||||
}
|
||||
lastAuthor = author;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* handles sorting of items
|
||||
*/
|
||||
|
@ -1209,11 +1155,10 @@ CSL.prototype._processCreators = function(type, element, creators, format, bibCi
|
|||
authorStrings[maxCreators-1] = and+" "+authorStrings[maxCreators-1];
|
||||
// skip the comma if there are only two creators and no
|
||||
// et al, and name as sort is no
|
||||
if(maxCreators == 2 &&
|
||||
(!element["name-as-sort-order"]
|
||||
|| (element["name-as-sort-order"] != "first"
|
||||
&& element["name-as-sort-order"] != "all"))) {
|
||||
joinString = " ";
|
||||
if((maxCreators == 2 && child["delimiter-precedes-last"] != "always") ||
|
||||
(maxCreators > 2 && child["delimiter-precedes-last"] == "never")) {
|
||||
var lastString = authorStrings.pop();
|
||||
authorStrings[maxCreators-2] = authorStrings[maxCreators-2]+" "+lastString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1237,18 +1182,22 @@ CSL.prototype._processCreators = function(type, element, creators, format, bibCi
|
|||
/*
|
||||
* get a citation, given an item and bibCitElement
|
||||
*/
|
||||
CSL.prototype._getCitation = function(item, format, bibCitElement) {
|
||||
CSL.prototype._getCitation = function(item, position, format, bibCitElement) {
|
||||
Scholar.debug("CSL: generating citation for item "+item.getID());
|
||||
|
||||
if(!bibCitElement._types[position]) {
|
||||
position = "first";
|
||||
}
|
||||
|
||||
// determine mapping
|
||||
if(bibCitElement._types[0]) {
|
||||
if(bibCitElement._types[position][0]) {
|
||||
// only one element
|
||||
var typeName = 0;
|
||||
var type = this._getTypeObject(typeName, bibCitElement);
|
||||
var type = this._getTypeObject(position, typeName, bibCitElement);
|
||||
} else {
|
||||
var typeNames = this._getTypeFromItem(item);
|
||||
for each(var typeName in typeNames) {
|
||||
var type = this._getTypeObject(typeName, bibCitElement);
|
||||
var type = this._getTypeObject(position, typeName, bibCitElement);
|
||||
if(type) {
|
||||
break;
|
||||
}
|
||||
|
@ -1263,7 +1212,7 @@ CSL.prototype._getCitation = function(item, format, bibCitElement) {
|
|||
var string = "";
|
||||
for(var j in type) {
|
||||
var value = this._getFieldValue(type[j].name, type[j], item, format,
|
||||
bibCitElement, typeName);
|
||||
bibCitElement, position, typeName);
|
||||
string += value;
|
||||
}
|
||||
|
||||
|
@ -1273,7 +1222,7 @@ CSL.prototype._getCitation = function(item, format, bibCitElement) {
|
|||
/*
|
||||
* processes an element from a (pre-processed) item into text
|
||||
*/
|
||||
CSL.prototype._getFieldValue = function(name, element, item, format, bibCitElement, typeName) {
|
||||
CSL.prototype._getFieldValue = function(name, element, item, format, bibCitElement, position, typeName) {
|
||||
var data = "";
|
||||
|
||||
if(element._serialized && item._csl.ignore[element._serialized]) {
|
||||
|
@ -1389,7 +1338,8 @@ CSL.prototype._getFieldValue = function(name, element, item, format, bibCitEleme
|
|||
var child = element.children[i];
|
||||
|
||||
var string = this._getFieldValue(child.name, child, item,
|
||||
format, typeName, bibCitElement);
|
||||
format, bibCitElement, position,
|
||||
typeName);
|
||||
if(string) {
|
||||
childData.push(string);
|
||||
}
|
||||
|
@ -1427,9 +1377,10 @@ CSL.prototype._getFieldValue = function(name, element, item, format, bibCitEleme
|
|||
inheritElement = element;
|
||||
} else {
|
||||
// search for elements with the same serialization
|
||||
if(typeName != undefined && bibCitElement._serializations[typeName]
|
||||
&& bibCitElement._serializations[typeName][serialization]) {
|
||||
inheritElement = bibCitElement._serializations[typeName][serialization];
|
||||
if(typeName != undefined && bibCitElement._serializations[position]
|
||||
&& bibCitElement._serializations[position][typeName]
|
||||
&& bibCitElement._serializations[position][typeName][serialization]) {
|
||||
inheritElement = bibCitElement._serializations[position][typeName][serialization];
|
||||
} else {
|
||||
// otherwise, use defaults
|
||||
inheritElement = this._getFieldDefaults(substituteElement.name);
|
||||
|
|
|
@ -51,8 +51,7 @@ Scholar.Integration = new function() {
|
|||
* handles a SOAP envelope
|
||||
*/
|
||||
function handleEnvelope(envelope) {
|
||||
Scholar.debug("Integration: got SOAP envelope");
|
||||
Scholar.debug(envelope);
|
||||
Scholar.debug("Integration: SOAP Request\n"+envelope);
|
||||
envelope = envelope.replace(_XMLRe, "");
|
||||
|
||||
var env = new Namespace("http://schemas.xmlsoap.org/soap/envelope/");
|
||||
|
@ -116,9 +115,12 @@ Scholar.Integration = new function() {
|
|||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>;
|
||||
|
||||
var response = responseEnvelope.toXMLString();
|
||||
Scholar.debug("Integration: SOAP Response\n"+response);
|
||||
|
||||
// return OK
|
||||
return _generateResponse("200 OK", 'text/xml; charset="utf-8"',
|
||||
responseEnvelope.toXMLString());
|
||||
response);
|
||||
} else {
|
||||
Scholar.debug("Integration: SOAP method not supported");
|
||||
}
|
||||
|
@ -294,10 +296,11 @@ Scholar.Integration.DataListener.prototype._requestFinished = function(response)
|
|||
|
||||
Scholar.Integration.SOAP = new function() {
|
||||
this.init = init;
|
||||
this.getCitation = getCitation;
|
||||
this.getBibliography = getBibliography;
|
||||
this.update = update;
|
||||
this.restoreSession = restoreSession;
|
||||
this.setDocPrefs = setDocPrefs;
|
||||
|
||||
var _sessions = new Array();
|
||||
var window;
|
||||
|
||||
function init() {
|
||||
|
@ -308,76 +311,304 @@ Scholar.Integration.SOAP = new function() {
|
|||
|
||||
/*
|
||||
* generates a new citation for a given item
|
||||
* ACCEPTS: style[, itemString, newItemIndex]
|
||||
* RETURNS: (newItem, citation)
|
||||
* ACCEPTS: sessionID, bibliographyMode, citationMode(, fieldIndex, fieldName)+
|
||||
* RETURNS: bibliography(, fieldIndex, fieldRename, fieldContent)+
|
||||
*/
|
||||
function getCitation(vars) {
|
||||
// get items
|
||||
var io = {dataIn: null, dataOut: null};
|
||||
window.openDialog('chrome://scholar/content/selectItemsDialog.xul','',
|
||||
'chrome,popup,modal,centerscreen',io);
|
||||
|
||||
if(io.dataOut) { // cancel was not pressed
|
||||
var selectedItemIDs = io.dataOut;
|
||||
var selectedItems = Scholar.Items.get(selectedItemIDs);
|
||||
|
||||
var style = vars[0];
|
||||
if(vars[1]) { // some items already exist in the document
|
||||
var itemString = vars[1]; // underscore-delimited string
|
||||
|
||||
var newItemIndex = parseInt(vars[2]); // index at which the
|
||||
// item belongs in
|
||||
// itemString
|
||||
|
||||
// splice in the new item ID
|
||||
if(newItemIndex == -1) { // at beginning
|
||||
var items = selectedItems.concat(Scholar.Items.get(itemString.split("_")));
|
||||
} else { // at newItemIndex
|
||||
var items = Scholar.Items.get(itemString.substr(0, newItemIndex).split("_")).
|
||||
concat(selectedItems);
|
||||
|
||||
if(newItemIndex != itemString.length) { // not at the end
|
||||
items = items.concat(Scholar.Items.get(itemString.substr(newItemIndex+1).split("_")))
|
||||
}
|
||||
}
|
||||
} else { // this is the first item and the only item to worry
|
||||
// about
|
||||
var items = selectedItems;
|
||||
}
|
||||
|
||||
var citation = Scholar.Cite.getCitation(style, selectedItems, items, "Integration");
|
||||
|
||||
return [selectedItemIDs.join("_"), citation];
|
||||
function update(vars) {
|
||||
if(!_sessions[vars[0]]) {
|
||||
return "ERROR:sessionExpired";
|
||||
}
|
||||
var session = _sessions[vars[0]];
|
||||
var returnString = "";
|
||||
|
||||
var bibliographyMode = vars[1];
|
||||
var citationMode = vars[2];
|
||||
|
||||
var style = Scholar.Cite.getStyle(session.styleID);
|
||||
|
||||
var encounteredItem = new Object();
|
||||
var newField = new Object();
|
||||
var regenerate = new Object();
|
||||
|
||||
var newFieldArrayIndex = vars.indexOf("X", 2);
|
||||
if(newFieldArrayIndex != -1) {
|
||||
var newFieldIndex = vars[newFieldArrayIndex-1];
|
||||
|
||||
// get items
|
||||
var io = {dataIn: null, dataOut: null};
|
||||
window.openDialog('chrome://scholar/content/selectItemsDialog.xul','',
|
||||
'chrome,popup,modal,centerscreen',io);
|
||||
|
||||
if(io.dataOut) { // cancel was not pressed
|
||||
var field = (io.dataOut.join(","))+"_"+Scholar.randomString();
|
||||
|
||||
// set so that itemID works
|
||||
vars[newFieldArrayIndex] = field;
|
||||
// set so that field name will get changed
|
||||
newField[newFieldIndex] = field;
|
||||
} else {
|
||||
vars[newFieldArrayIndex] = "!";
|
||||
newField[newFieldIndex] = "!";
|
||||
}
|
||||
}
|
||||
|
||||
var regenerateItemList = _inspectCitationPairs(vars, 3, session, style,
|
||||
encounteredItem, newField, regenerate,
|
||||
(citationMode == "all"));
|
||||
|
||||
if(!regenerateItemList) {
|
||||
// if we're not already regenerating the item list, ensure no
|
||||
// citations have been deleted
|
||||
for(var i in session.encounteredItem) {
|
||||
if(!encounteredItem[i]) {
|
||||
regenerateItemList = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var output = new Array();
|
||||
|
||||
if(regenerateItemList || bibliographyMode == "true") {
|
||||
Scholar.debug("Integration: Regenerating Item List");
|
||||
|
||||
// need to re-process items
|
||||
var items = new Array();
|
||||
for(var i in encounteredItem) {
|
||||
items.push(Scholar.Items.get(i));
|
||||
}
|
||||
style.preprocessItems(items);
|
||||
|
||||
// EBNF: bibliography-data
|
||||
if(bibliographyMode != "false") {
|
||||
output.push(style.createBibliography(items, "Integration"));
|
||||
} else {
|
||||
output.push("!");
|
||||
}
|
||||
} else {
|
||||
// EBNF: bibliography-data
|
||||
output.push("!");
|
||||
}
|
||||
|
||||
// state which citations to update
|
||||
// EBNF: citation-output-triple
|
||||
for(var i in regenerate) {
|
||||
// EBNF: citation-index
|
||||
output.push(i);
|
||||
|
||||
if(regenerate[i] === false) {
|
||||
// if marked for deletion, delete
|
||||
output.push("!");
|
||||
output.push("!");
|
||||
} else if(regenerate[i] === true) {
|
||||
// if marked for name change, change name
|
||||
output.push(newField[i]);
|
||||
output.push("!");
|
||||
} else {
|
||||
// EBNF: citation-field
|
||||
if(newField[i]) {
|
||||
output.push(newField[i]);
|
||||
} else {
|
||||
output.push("!");
|
||||
}
|
||||
|
||||
// EBNF: citation-data
|
||||
var items = Scholar.Items.get(regenerate[i][0]);
|
||||
output.push(style.createCitation(items, regenerate[i][1], "Integration"));
|
||||
}
|
||||
}
|
||||
|
||||
session.encounteredItem = encounteredItem;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/*
|
||||
* gets a bibliography
|
||||
* ACCEPTS: style, itemString
|
||||
* RETURNS: bibliography
|
||||
* restores a session, given all citations
|
||||
* ACCEPTS: styleID(, fieldIndex, fieldName)+
|
||||
* RETURNS: sessionID
|
||||
*/
|
||||
function getBibliography(vars) {
|
||||
// get items
|
||||
var itemIDs = vars[1].split("_");
|
||||
var items = Scholar.Items.get(itemIDs);
|
||||
function restoreSession(vars) {
|
||||
var sessionID = Scholar.randomString();
|
||||
var session = _generateSession(sessionID);
|
||||
session.styleID = vars[0];
|
||||
|
||||
return Scholar.Cite.getBibliography(vars[0], items, "Integration");
|
||||
var style = Scholar.Cite.getStyle(session.styleID);
|
||||
|
||||
var encounteredItem = new Object();
|
||||
var newField = new Object();
|
||||
var regenerate = new Object();
|
||||
|
||||
_inspectCitationPairs(vars, 1, session, style);
|
||||
|
||||
return [sessionID];
|
||||
}
|
||||
|
||||
/*
|
||||
* sets document preferences
|
||||
* ACCEPTS: [currentStyle]
|
||||
* RETURNS: (style, styleClass)
|
||||
* ACCEPTS: (sessionID)?
|
||||
* RETURNS: sessionID, styleID, style-class
|
||||
*/
|
||||
function setDocPrefs(vars) {
|
||||
var io = new Object();
|
||||
if(vars && vars[0]) {
|
||||
io.style = vars[0];
|
||||
|
||||
if(!vars || vars[0] == "!") {
|
||||
// no session ID; generate a new one
|
||||
var sessionID = Scholar.randomString();
|
||||
var session = _generateSession(sessionID);
|
||||
} else {
|
||||
// session ID exists
|
||||
var sessionID = vars[0];
|
||||
var session = _sessions[sessionID];
|
||||
var originalStyle = session.styleID;
|
||||
io.style = originalStyle;
|
||||
}
|
||||
|
||||
window.openDialog('chrome://scholar/content/integrationDocPrefs.xul','',
|
||||
'chrome,popup,modal,centerscreen',io);
|
||||
var styleClass = Scholar.Cite.getStyleClass(io.style);
|
||||
return [io.style, styleClass];
|
||||
session.styleID = io.style;
|
||||
var style = Scholar.Cite.getStyle(io.style);
|
||||
|
||||
return [sessionID, io.style, style.class];
|
||||
}
|
||||
|
||||
/*
|
||||
* inspects citation pairs to determine which are in need of an update
|
||||
*
|
||||
* vars - the set of variables
|
||||
*
|
||||
* startIndex - the place in the set of variables at which the citations
|
||||
* begin
|
||||
*
|
||||
* session - the session variable (see _generateSession())
|
||||
*
|
||||
* encounteredItem - an object representing whether a given item ID has been
|
||||
* encountered, in the format itemID => true
|
||||
*
|
||||
* newField - an object representing whether a given field needs to be
|
||||
* renamed, in the format fieldIndex => newFieldName
|
||||
*
|
||||
* regenerate - an object representing whether the contents of a given field
|
||||
* need to be modified, in the format:
|
||||
* index => [[itemID1, itemID2], ([format1, format2] | "2")]
|
||||
* formats are as follows:
|
||||
* 1 => first occurance of a given item. use full citation.
|
||||
* 2 => item occurred directly previously. use ibid. (never
|
||||
* used as an array, only a single item)
|
||||
* 3 => subsequent entry.
|
||||
*/
|
||||
|
||||
function _inspectCitationPairs(vars, startIndex, session, style, encounteredItem, newField, regenerate, regenerateAll) {
|
||||
var newItemFound = false;
|
||||
var encounteredField = new Object();// keep track of field names, to see
|
||||
// if there are duplicates
|
||||
|
||||
if(!encounteredItem) {
|
||||
encounteredItem = new Object();
|
||||
}
|
||||
|
||||
var lastItemIDString = null;
|
||||
var index, field, lastItemID, itemIDs, itemID, itemSetValue;
|
||||
for(var i=startIndex; i<vars.length; i+=2) {
|
||||
index = vars[i];
|
||||
field = vars[i+1];
|
||||
if(regenerate && field == "!") {
|
||||
// mark for deletion if necessary
|
||||
Scholar.debug("Integration: Marking "+index+" for deletion");
|
||||
regenerate[index] = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
itemIDString = field.substr(0, field.indexOf("_"));
|
||||
itemIDs = itemIDString.split(",");
|
||||
|
||||
itemSetValue = null;
|
||||
if(itemIDString == lastItemIDString && style.ibid) {
|
||||
// use ibid if possible
|
||||
itemSetValue = 2;
|
||||
} else {
|
||||
// loop through to see which are first citations
|
||||
itemSetValue = new Array();
|
||||
for each(itemID in itemIDs) {
|
||||
if(!encounteredItem[itemID]) {
|
||||
encounteredItem[itemID] = true;
|
||||
itemSetValue.push(1);
|
||||
|
||||
if(!session.encounteredItem[itemID]) {
|
||||
newItemFound = true;
|
||||
}
|
||||
} else {
|
||||
itemSetValue.push(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(regenerateAll) {
|
||||
// regenerate all citations if requested
|
||||
var update = true;
|
||||
} else {
|
||||
// test to see if this itemSetValue is different from the
|
||||
// version stored in the session
|
||||
var update = false;
|
||||
if(typeof(itemSetValue) == "object" &&
|
||||
typeof(session.itemSet[field]) == "object") {
|
||||
// loop through, looking for differences
|
||||
for(var j in itemSetValue) {
|
||||
if(itemSetValue[j] != session.itemSet[field][j]) {
|
||||
update = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(itemSetValue != session.itemSet[field]) {
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(update) {
|
||||
Scholar.debug("Integration: field "+field+" at index "+index+" was "+(session.itemSet[field] ? session.itemSet[field].toSource() : "undefined")+" but is now "+itemSetValue.toSource());
|
||||
// positioning has changed
|
||||
if(encounteredField[field]) {
|
||||
if(regenerate) {
|
||||
// someone copy and pasted a citation from this document,
|
||||
// since this field appears twice. and we have to change it.
|
||||
newField[index] = itemIDString+"_"+Scholar.randomString();
|
||||
session.itemSet[newField[index]] = itemSetValue;
|
||||
}
|
||||
} else {
|
||||
session.itemSet[field] = itemSetValue;
|
||||
}
|
||||
|
||||
if(regenerate) {
|
||||
// regenerate citation
|
||||
regenerate[index] = [itemIDs, itemSetValue];
|
||||
}
|
||||
} else if(encounteredField[field]) {
|
||||
// someone copy and pasted a citation from this document,
|
||||
// since this field appears twice. we don't have to change it,
|
||||
// but we do need to change its name
|
||||
session.itemSet[newField[index]] = itemSetValue;
|
||||
|
||||
if(regenerate) {
|
||||
newField[index] = itemIDString+"_"+Scholar.randomString();
|
||||
regenerate[index] = true; // true means name change without
|
||||
// field value change
|
||||
}
|
||||
}
|
||||
|
||||
encounteredField[field] = true;
|
||||
lastItemIDString = itemIDString;
|
||||
}
|
||||
|
||||
return newItemFound;
|
||||
}
|
||||
|
||||
/*
|
||||
* generates, stores, and returns a new session object
|
||||
*/
|
||||
function _generateSession(sessionID) {
|
||||
var session = _sessions[sessionID] = new Object();
|
||||
session.encounteredItem = new Object();
|
||||
session.itemSet = new Object();
|
||||
|
||||
return session;
|
||||
}
|
||||
}
|
|
@ -5969,7 +5969,7 @@ REPLACE INTO "csl" VALUES('http://purl.org/net/xbiblio/csl/styles/apa.csl', '200
|
|||
<access>
|
||||
<text term-name="retrieved" text-transform="capitalize"/>
|
||||
<date suffix=", ">
|
||||
<month/>
|
||||
<month suffix=" "/>
|
||||
<day suffix=", "/>
|
||||
<year/>
|
||||
</date>
|
||||
|
|
Loading…
Reference in New Issue
Block a user