From f81f0d714322648deb480e0fda95a0ff6d8f267b Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Mon, 19 Dec 2011 03:38:58 -0500 Subject: [PATCH] Allow citing embedded items and editing citations containing embedded items --- .../content/zotero/integration/quickFormat.js | 28 ++- chrome/content/zotero/xpcom/cite.js | 29 +++ chrome/content/zotero/xpcom/data/item.js | 14 +- chrome/content/zotero/xpcom/integration.js | 215 ++++++++++-------- chrome/content/zotero/xpcom/utilities.js | 113 ++++++++- 5 files changed, 288 insertions(+), 111 deletions(-) diff --git a/chrome/content/zotero/integration/quickFormat.js b/chrome/content/zotero/integration/quickFormat.js index 4058362a6e..08779ea864 100644 --- a/chrome/content/zotero/integration/quickFormat.js +++ b/chrome/content/zotero/integration/quickFormat.js @@ -254,13 +254,19 @@ var Zotero_QuickFormat = new function () { break; } } - if(!mismatch) return; + if(!mismatch) { + _resize(); + return; + } } curIDs = searchResultIDs; // Check to see which search results match items already in the document - var citedItems, completed = false, preserveSelection = false; + var citedItems, completed = false, isAsync = false; io.getItems(function(citedItems) { + // Don't do anything if panel is already closed + if(isAsync && referencePanel.state !== "open" && referencePanel.state !== "showing") return; + completed = true; if(str.toLowerCase() === Zotero.getString("integration.ibid").toLowerCase()) { @@ -290,14 +296,14 @@ var Zotero_QuickFormat = new function () { Zotero.debug("Searched cited items"); } - _updateItemList(citedItemsMatchingSearch, searchResultIDs, preserveSelection); + _updateItemList(citedItemsMatchingSearch, searchResultIDs, isAsync); }); if(!completed) { // We are going to have to wait until items have been retrieved from the document. // Until then, show item list without cited items. _updateItemList(false, searchResultIDs); - preserveSelection = true; + isAsync = true; } } else { // No search conditions, so just clear the box @@ -378,7 +384,7 @@ var Zotero_QuickFormat = new function () { referenceBox.appendChild(_buildListItem(item)); previousLibrary = libraryID; - if(preserveSelection && item.id === previousItemID) { + if(preserveSelection && (item.cslItemID ? item.cslItemID : item.id) === previousItemID) { selectedIndex = referenceBox.childNodes.length-1; } } @@ -390,7 +396,6 @@ var Zotero_QuickFormat = new function () { referenceBox.ensureIndexIsVisible(selectedIndex); } } - /** * Builds a string describing an item. We avoid CSL here for speed. @@ -480,7 +485,7 @@ var Zotero_QuickFormat = new function () { rll.setAttribute("orient", "vertical"); rll.setAttribute("flex", "1"); rll.setAttribute("class", "quick-format-item"); - rll.setAttribute("zotero-item", item.id); + rll.setAttribute("zotero-item", item.cslItemID ? item.cslItemID : item.id); rll.appendChild(titleNode); rll.appendChild(infoNode); rll.addEventListener("click", _bubbleizeSelected, false); @@ -515,7 +520,7 @@ var Zotero_QuickFormat = new function () { * Builds the string to go inside a bubble */ function _buildBubbleString(citationItem) { - var item = Zotero.Items.get(citationItem.id); + var item = Zotero.Cite.getItem(citationItem.id); // create text for bubble var title, delimiter; var str = item.getField("firstCreator"); @@ -577,6 +582,11 @@ var Zotero_QuickFormat = new function () { if(!referenceBox.hasChildNodes() || !referenceBox.selectedItem) return false; var citationItem = {"id":referenceBox.selectedItem.getAttribute("zotero-item")}; + if(typeof citationItem.id === "string" && citationItem.id.indexOf("/") !== -1) { + var item = Zotero.Cite.getItem(citationItem.id); + citationItem.uris = item.cslURIs; + citationItem.itemData = item.cslItemData; + } if(curLocator) { citationItem["locator"] = curLocator; if(curLocatorLabel) { @@ -781,7 +791,7 @@ var Zotero_QuickFormat = new function () { locator.value = target.citationItem["locator"] ? target.citationItem["locator"] : ""; suppressAuthor.checked = !!target.citationItem["suppress-author"]; - var item = Zotero.Items.get(target.citationItem.id); + var item = Zotero.Cite.getItem(target.citationItem.id); document.getElementById("citation-properties-title").textContent = item.getDisplayTitle(); while(info.hasChildNodes()) info.removeChild(info.firstChild); _buildItemDescription(item, info); diff --git a/chrome/content/zotero/xpcom/cite.js b/chrome/content/zotero/xpcom/cite.js index da3ddbf580..c7d6b811df 100644 --- a/chrome/content/zotero/xpcom/cite.js +++ b/chrome/content/zotero/xpcom/cite.js @@ -390,6 +390,35 @@ Zotero.Cite.makeFormattedBibliography = function(cslEngine, format) { } } +/** + * Get an item by ID, either by retrieving it from the library or looking for the document it + * belongs to. + * @param {String|Number|Array} id + */ +Zotero.Cite.getItem = function(id) { + var slashIndex; + + if(id instanceof Array) { + return [Zotero.Cite.getItem(anId) for each(anId in id)]; + } else if(typeof id === "string" && (slashIndex = id.indexOf("/")) !== -1) { + var sessionID = id.substr(0, slashIndex), + session = Zotero.Integration.sessions[sessionID], + item; + if(session) { + item = session.embeddedZoteroItems[id.substr(slashIndex+1)]; + } + + if(!item) { + item = new Zotero.Item("document"); + item.setField("title", "Missing Item"); + Zotero.log("CSL item "+id+" not found"); + } + return item; + } else { + return Zotero.Items.get(id); + } +} + Zotero.Cite.labels = ["page", "book", "chapter", "column", "figure", "folio", "issue", "line", "note", "opus", "paragraph", "part", "section", "sub verbo", "volume", "verse"]; \ No newline at end of file diff --git a/chrome/content/zotero/xpcom/data/item.js b/chrome/content/zotero/xpcom/data/item.js index 5523683ec5..f2beb679a2 100644 --- a/chrome/content/zotero/xpcom/data/item.js +++ b/chrome/content/zotero/xpcom/data/item.js @@ -183,7 +183,19 @@ Zotero.Item.prototype.getField = function(field, unformatted, includeBaseMapped) this.loadPrimaryData(true); } - if (field == 'id' || Zotero.Items.isPrimaryField(field)) { + if (field === 'firstCreator' && !this.id) { + // Hack to get a firstCreator for an unsaved item + var creators = this.getCreators(); + if(creators.length === 0) { + return ""; + } else if(creators.length === 1) { + return creators[0].ref.lastName; + } else if(creators.length === 2) { + return creators[0].ref.lastName+" "+Zotero.getString('general.and')+" "+creators[1].ref.lastName; + } else if(creators.length > 3) { + return creators[0].ref.lastName+" et al." + } + } else if (field === 'id' || Zotero.Items.isPrimaryField(field)) { var privField = '_' + field; //Zotero.debug('Returning ' + (this[privField] ? this[privField] : '') + ' (typeof ' + typeof this[privField] + ')'); return this[privField]; diff --git a/chrome/content/zotero/xpcom/integration.js b/chrome/content/zotero/xpcom/integration.js index bb989e9b1f..d146015f93 100644 --- a/chrome/content/zotero/xpcom/integration.js +++ b/chrome/content/zotero/xpcom/integration.js @@ -1274,7 +1274,7 @@ Zotero.Integration.Fields.prototype._updateDocument = function(forceCitations, f * Brings up the addCitationDialog, prepopulated if a citation is provided */ Zotero.Integration.Fields.prototype.addEditCitation = function(field, callback) { - var newField, citation, fieldIndex, session = this._session, me = this; + var newField, citation, fieldIndex, session = this._session, me = this, loadFirst; // if there's already a citation, make sure we have item IDs in addition to keys if(field) { @@ -1285,18 +1285,13 @@ Zotero.Integration.Fields.prototype.addEditCitation = function(field, callback) } citation = session.unserializeCitation(content); - - var zoteroItem; - for each(var citationItem in citation.citationItems) { - var item = false; - if(!citationItem.id) { - zoteroItem = false; - if(citationItem.uris) { - [zoteroItem, ] = session.uriMap.getZoteroItemForURIs(citationItem.uris); - } else if(citationItem.key) { - zoteroItem = Zotero.Items.getByKey(citationItem.key); - } - if(zoteroItem) citationItem.id = zoteroItem.id; + try { + session.lookupItems(citation); + } catch(e) { + if(e instanceof MissingItemException) { + citation.citationItems = []; + } else { + throw e; } } @@ -1471,9 +1466,8 @@ Zotero.Integration.CitationEditInterface.prototype = { * has already been updated if it should be. */ "_getItems":function(itemsCallback) { - // TODO handle items not in library var citationsByItemID = this._session.citationsByItemID; - var items = [itemID for(itemID in citationsByItemID) + var ids = [itemID for(itemID in citationsByItemID) if(citationsByItemID[itemID] && citationsByItemID[itemID].length // Exclude this item && (citationsByItemID[itemID].length > 1 @@ -1481,7 +1475,7 @@ Zotero.Integration.CitationEditInterface.prototype = { // Sort all previously cited items at top, and all items cited later at bottom var fieldIndex = this._fieldIndex; - items.sort(function(a, b) { + ids.sort(function(a, b) { var indexA = citationsByItemID[a][0].properties.zoteroIndex, indexB = citationsByItemID[b][0].properties.zoteroIndex; @@ -1494,7 +1488,7 @@ Zotero.Integration.CitationEditInterface.prototype = { return indexB - indexA; }); - itemsCallback(Zotero.Items.get(items)); + itemsCallback(Zotero.Cite.getItem(ids)); } } @@ -1506,6 +1500,7 @@ Zotero.Integration.Session = function(doc) { this.uncitedItems = {}; this.omittedItems = {}; this.embeddedItems = {}; + this.embeddedZoteroItems = {}; this.embeddedItemsByURI = {}; this.customBibliographyText = {}; this.reselectedItems = {}; @@ -1779,89 +1774,7 @@ Zotero.Integration.Session.prototype.addCitation = function(index, noteIndex, ar } // get items - for(var i=0, n=citation.citationItems.length; i