www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

commit fb149764990541723c7d9501e60b84dc866f9698
parent 3ac5a6db09e06798b28ce44e6e3cc2d6480cd8d9
Author: Simon Kornblith <simon@simonster.com>
Date:   Tue,  3 Jan 2012 15:26:52 -0500

Merge branch '3.0'

Diffstat:
Mchrome/content/zotero/about.xul | 32++++++++++++++++----------------
Mchrome/content/zotero/integration/quickFormat.js | 463++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mchrome/content/zotero/integration/quickFormat.xul | 25+++++++++++++++++--------
Mchrome/content/zotero/recognizePDF.js | 10+++++-----
Mchrome/content/zotero/xpcom/citeproc.js | 138++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Mchrome/content/zotero/xpcom/integration.js | 137+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mchrome/content/zotero/xpcom/translation/translate.js | 5+++--
Mchrome/content/zotero/xpcom/utilities.js | 12++++++++----
Mchrome/content/zotero/zoteroPane.js | 3+++
9 files changed, 495 insertions(+), 330 deletions(-)

diff --git a/chrome/content/zotero/about.xul b/chrome/content/zotero/about.xul @@ -240,7 +240,7 @@ <vbox id="aboutcontent"> <label id="name" value="Zotero"/> <hbox> - <label class="text-link" href="http://zotero.org" value="http://zotero.org"/> + <label class="zotero-text-link" href="http://zotero.org" value="http://zotero.org"/> </hbox> <label id="version" value="&zotero.version; "/> <script> @@ -250,7 +250,7 @@ <vbox id="column1"> <label class="subhead" value="&zotero.createdby;"/> <vbox class="subcontent"> - <label class="text-link" href="http://chnm.gmu.edu" value="Center for History and New Media"/> + <label class="zotero-text-link" href="http://chnm.gmu.edu" value="Center for History and New Media"/> <label value="George Mason University"/> <label value="Fairfax, VA, USA"/> </vbox> @@ -268,30 +268,30 @@ <vbox class="subcontent"> <vbox id="zotero-translators-list"/> </vbox> - <label class="text-link" href="http://www.zotero.org/support/credits_and_acknowledgments" value="&zotero.moreCreditsAndAcknowledgements;"/> + <label class="zotero-text-link" href="http://www.zotero.org/support/credits_and_acknowledgments" value="&zotero.moreCreditsAndAcknowledgements;"/> </vbox> <vbox id="column2"> <label class="subhead" value="Citation &amp; Bibliography Processing"/> <vbox class="subcontent"> - <label class="text-link" href="http://citationstyles.org/" value="Citation Style Language"/> - <label class="text-link" href="http://bitbucket.org/fbennett/citeproc-js/" value="citeproc-js (Frank Bennett)"/> + <label class="zotero-text-link" href="http://citationstyles.org/" value="Citation Style Language"/> + <label class="zotero-text-link" href="http://bitbucket.org/fbennett/citeproc-js/" value="citeproc-js (Frank Bennett)"/> </vbox> <label class="subhead" value="&zotero.about.additionalSoftware;"/> <vbox class="subcontent"> - <label class="text-link" href="http://www.famfamfam.com/lab/icons/silk/" value="famfamfam (small icons)"/> - <label class="text-link" href="http://appscript.sourceforge.net/py-appscript/" value="py-appscript (MacWord plug-in IPC)"/> - <label class="text-link" href="http://simile.mit.edu/timeline/" value="SIMILE Project (Timeline)"/> - <label class="text-link" href="http://www.w3.org/2005/ajar/tab" value="Tabulator (RDF parser)"/> - <label class="text-link" href="http://tango.freedesktop.org/Tango_Desktop_Project" value="Tango Desktop Project (pref icons)"/> - <label class="text-link" href="http://tinymce.moxiecode.com/" value="TinyMCE (rich-text editing)"/> - <label class="text-link" href="http://www.dbai.tuwien.ac.at/user/pollak/webpagedump/" value="WebPageDump (snapshot code)"/> - <label class="text-link" href="http://www.foolabs.com/xpdf/" value="Xpdf (pdftotext)"/> + <label class="zotero-text-link" href="http://www.famfamfam.com/lab/icons/silk/" value="famfamfam (small icons)"/> + <label class="zotero-text-link" href="http://appscript.sourceforge.net/py-appscript/" value="py-appscript (MacWord plug-in IPC)"/> + <label class="zotero-text-link" href="http://simile.mit.edu/timeline/" value="SIMILE Project (Timeline)"/> + <label class="zotero-text-link" href="http://www.w3.org/2005/ajar/tab" value="Tabulator (RDF parser)"/> + <label class="zotero-text-link" href="http://tango.freedesktop.org/Tango_Desktop_Project" value="Tango Desktop Project (pref icons)"/> + <label class="zotero-text-link" href="http://tinymce.moxiecode.com/" value="TinyMCE (rich-text editing)"/> + <label class="zotero-text-link" href="http://www.dbai.tuwien.ac.at/user/pollak/webpagedump/" value="WebPageDump (snapshot code)"/> + <label class="zotero-text-link" href="http://www.foolabs.com/xpdf/" value="Xpdf (pdftotext)"/> </vbox> <label class="subhead" value="&zotero.thanks;"/> <vbox class="subcontent"> - <label class="text-link" href="http://www.mellon.org/" value="Andrew W. Mellon Foundation"/> - <label class="text-link" href="http://www.imls.gov/" value="Institute of Museum and Library Services"/> - <label class="text-link" href="http://www.sloan.org/" value="Alfred P. Sloan Foundation"/> + <label class="zotero-text-link" href="http://www.mellon.org/" value="Andrew W. Mellon Foundation"/> + <label class="zotero-text-link" href="http://www.imls.gov/" value="Institute of Museum and Library Services"/> + <label class="zotero-text-link" href="http://www.sloan.org/" value="Alfred P. Sloan Foundation"/> </vbox> </vbox> </hbox> diff --git a/chrome/content/zotero/integration/quickFormat.js b/chrome/content/zotero/integration/quickFormat.js @@ -24,9 +24,11 @@ */ var Zotero_QuickFormat = new function () { - var io, qfs, qfi, qfiWindow, qfiDocument, qfe, qfb, qfbHeight, keepSorted, showEditor, - referencePanel, referenceBox, referenceHeight, separatorHeight, dragX, dragY, curLocator, - curLocatorLabel, curIDs = [], curResizer, dragging; + var initialized, io, qfs, qfi, qfiWindow, qfiDocument, qfe, qfb, qfbHeight, keepSorted, + showEditor, referencePanel, referenceBox, referenceHeight = 0, separatorHeight = 0, + currentLocator, currentLocatorLabel, currentSearchTime, dragging, panel, + panelPrefix, panelSuffix, panelSuppressAuthor, panelLocatorLabel, panelLocator, panelInfo, + panelRefersToBubble; // A variable that contains the timeout object for the latest onKeyPress event var eventTimeout = null; @@ -36,61 +38,75 @@ var Zotero_QuickFormat = new function () { /** * Pre-initialization, when the dialog has loaded but has not yet appeared */ - this.onDOMContentLoaded = function() { - io = window.arguments[0].wrappedJSObject; - - // Only hide chrome on Windows or Mac - if(Zotero.isMac || Zotero.isWin) { - document.documentElement.setAttribute("hidechrome", true); - } - - qfs = document.getElementById("quick-format-search"); - qfi = document.getElementById("quick-format-iframe"); - qfb = document.getElementById("quick-format-entry"); - qfbHeight = qfb.scrollHeight; - referencePanel = document.getElementById("quick-format-reference-panel"); - referenceBox = document.getElementById("quick-format-reference-list"); - qfiWindow = qfi.contentWindow; - qfiDocument = qfi.contentDocument; - qfb.addEventListener("keypress", _onQuickSearchKeyPress, false); - qfe = qfiDocument.getElementById("quick-format-editor"); - - if(Zotero.isWin && Zotero.Prefs.get('integration.keepAddCitationDialogRaised')) { - qfb.setAttribute("square", "true"); - } - - // add labels to popup - var locators = Zotero.Cite.labels; - var menu = document.getElementById("locator-label"); - var labelList = document.getElementById("locator-label-popup"); - for each(var locator in locators) { - // TODO localize - var locatorLabel = locator[0].toUpperCase()+locator.substr(1); + this.onDOMContentLoaded = function(event) { + if(event.target === document) { + initialized = true; + io = window.arguments[0].wrappedJSObject; - // add to list of labels - var child = document.createElement("menuitem"); - child.setAttribute("value", locator); - child.setAttribute("label", locatorLabel); - labelList.appendChild(child); - } - menu.selectedIndex = 0; - - keepSorted = document.getElementById("keep-sorted"); - showEditor = document.getElementById("show-editor"); - if(io.sortable) { - keepSorted.hidden = false; - if(!io.citation.properties.unsorted) { - keepSorted.setAttribute("checked", "true"); + // Only hide chrome on Windows or Mac + if(Zotero.isMac || Zotero.isWin) { + document.documentElement.setAttribute("hidechrome", true); + } + + qfs = document.getElementById("quick-format-search"); + qfi = document.getElementById("quick-format-iframe"); + qfb = document.getElementById("quick-format-entry"); + qfbHeight = qfb.scrollHeight; + referencePanel = document.getElementById("quick-format-reference-panel"); + referenceBox = document.getElementById("quick-format-reference-list"); + + if(Zotero.isWin && Zotero.Prefs.get('integration.keepAddCitationDialogRaised')) { + qfb.setAttribute("square", "true"); + } + + // add labels to popup + var locators = Zotero.Cite.labels; + var menu = document.getElementById("locator-label"); + var labelList = document.getElementById("locator-label-popup"); + for each(var locator in locators) { + // TODO localize + var locatorLabel = locator[0].toUpperCase()+locator.substr(1); + + // add to list of labels + var child = document.createElement("menuitem"); + child.setAttribute("value", locator); + child.setAttribute("label", locatorLabel); + labelList.appendChild(child); + } + menu.selectedIndex = 0; + + keepSorted = document.getElementById("keep-sorted"); + showEditor = document.getElementById("show-editor"); + if(io.sortable) { + keepSorted.hidden = false; + if(!io.citation.properties.unsorted) { + keepSorted.setAttribute("checked", "true"); + } } + + window.sizeToContent(); + + // Nodes for citation properties panel + panel = document.getElementById("citation-properties"); + panelPrefix = document.getElementById("prefix"); + panelSuffix = document.getElementById("suffix"); + panelSuppressAuthor = document.getElementById("suppress-author"); + panelLocatorLabel = document.getElementById("locator-label"); + panelLocator = document.getElementById("locator"); + panelInfo = document.getElementById("citation-properties-info"); + } else if(event.target === qfi.contentDocument) { + qfiWindow = qfi.contentWindow; + qfiDocument = qfi.contentDocument; + qfb.addEventListener("keypress", _onQuickSearchKeyPress, false); + qfe = qfiDocument.getElementById("quick-format-editor"); } - - window.sizeToContent(); } /** * Initialize add citation dialog */ - this.onLoad = function() { + this.onLoad = function(event) { + if(event.target !== document) return; // make sure we are visible window.setTimeout(function() { var screenX = window.screenX; @@ -174,8 +190,8 @@ var Zotero_QuickFormat = new function () { isBC = false, dateID = false; - curLocator = false; - curLocatorLabel = false; + currentLocator = false; + currentLocatorLabel = false; // check for adding a number onto a previous page number if(numRe.test(str)) { @@ -209,7 +225,7 @@ var Zotero_QuickFormat = new function () { } // TODO support types other than page - curLocator = m[2]; + currentLocator = m[2]; str = str.substring(0, m.index); } @@ -221,11 +237,11 @@ var Zotero_QuickFormat = new function () { if(m[3]) { isBC = true; } - if(!curLocator && m[4]) { - curLocator = m[4]; + if(!currentLocator && m[4]) { + currentLocator = m[4]; } } else { - curLocator = m[1]; + currentLocator = m[1]; } str = str.substr(0, m.index)+str.substring(m.index+m[0].length); @@ -245,27 +261,16 @@ var Zotero_QuickFormat = new function () { if(haveConditions) { var searchResultIDs = (haveConditions ? s.search() : []); - // No need to refresh anything if box hasn't changed - if(searchResultIDs.length === curIDs.length) { - var mismatch = false; - for(var i=0; i<searchResultIDs.length; i++) { - if(curIDs[i] !== searchResultIDs[i]) { - mismatch = true; - break; - } - } - if(!mismatch) { - _resize(); - return; - } - } - curIDs = searchResultIDs; - // Check to see which search results match items already in the document var citedItems, completed = false, isAsync = false; + // Save current search so that when we get items, we know whether it's too late to + // process them or not + var lastSearchTime = currentSearchTime = Date.now(); io.getItems(function(citedItems) { // Don't do anything if panel is already closed - if(isAsync && referencePanel.state !== "open" && referencePanel.state !== "showing") return; + if(isAsync && + ((referencePanel.state !== "open" && referencePanel.state !== "showing") + || lastSearchTime !== currentSearchTime)) return; completed = true; @@ -302,8 +307,11 @@ var Zotero_QuickFormat = new function () { 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. + Zotero.debug("Getting cited items asynchronously"); _updateItemList(false, searchResultIDs); isAsync = true; + } else { + Zotero.debug("Got cited items synchronously"); } } else { // No search conditions, so just clear the box @@ -312,43 +320,19 @@ var Zotero_QuickFormat = new function () { } /** - * Sorts items - */ - function _itemSort(a, b) { - // Sort by library ID - var libA = a.libraryID, libB = b.libraryID; - if(libA !== libB) { - return libA - libB; - } - - // Sort by last name of first author - var creatorsA = a.getCreators(), creatorsB = b.getCreators(), - caExists = creatorsA.length ? 1 : 0, cbExists = creatorsB.length ? 1 : 0; - if(caExists !== cbExists) { - return cbExists-caExists; - } else if(caExists) { - return creatorsA[0].ref.lastName.localeCompare(creatorsB[0].ref.lastName); - } - - // Sort by date - var yearA = a.getField("date", true, true).substr(0, 4), - yearB = b.getField("date", true, true).substr(0, 4); - return yearA - yearB; - } - - /** * Updates the item list */ function _updateItemList(citedItems, searchResultIDs, preserveSelection) { var selectedIndex = 1, previousItemID; // Do this so we can preserve the selected item after cited items have been loaded - if(preserveSelection && referenceBox.selectedIndex !== 2) { + if(preserveSelection && referenceBox.selectedIndex !== -1 && referenceBox.selectedIndex !== 2) { previousItemID = parseInt(referenceBox.selectedItem.getAttribute("zotero-item"), 10); } while(referenceBox.hasChildNodes()) referenceBox.removeChild(referenceBox.firstChild); + var nCitedItemsFromLibrary = {}; if(!citedItems) { // We don't know whether or not we have cited items, because we are waiting for document // data @@ -358,21 +342,76 @@ var Zotero_QuickFormat = new function () { // We have cited items referenceBox.appendChild(_buildListSeparator(Zotero.getString("integration.cited"))); for(var i=0, n=citedItems.length; i<n; i++) { - referenceBox.appendChild(_buildListItem(citedItems[i])); + var citedItem = citedItems[i]; + if(i < 50) { + referenceBox.appendChild(_buildListItem(citedItem)); + } + + // Tabulate number of items in document for each library + if(!citedItem.cslItemID) { + var libraryID = citedItem.libraryID ? citedItem.libraryID : 0; + if(libraryID in nCitedItemsFromLibrary) { + nCitedItemsFromLibrary[libraryID]++; + } else { + nCitedItemsFromLibrary[libraryID] = 1; + } + } + } + } + + // Also take into account items cited in this citation. This means that the sorting isn't + // exactly by # of items cited from each library, but maybe it's better this way. + _updateCitationObject(); + for each(var citationItem in io.citation.citationItems) { + var citedItem = Zotero.Cite.getItem(citationItem.id); + if(!citedItem.cslItemID) { + var libraryID = citedItem.libraryID ? citedItem.libraryID : 0; + if(libraryID in nCitedItemsFromLibrary) { + nCitedItemsFromLibrary[libraryID]++; + } else { + nCitedItemsFromLibrary[libraryID] = 1; + } } } if(searchResultIDs.length && (!citedItems || citedItems.length < 50)) { - // Don't handle more than 50 results - if(searchResultIDs.length > 50-citedItems.length) { - searchResultIDs = searchResultIDs.slice(0, 50-citedItems.length); - } - var items = Zotero.Items.get(searchResultIDs); - items.sort(_itemSort); + + items.sort(function _itemSort(a, b) { + var libA = a.libraryID ? a.libraryID : 0, libB = b.libraryID ? b.libraryID : 0; + if(libA !== libB) { + // Sort by number of cites for library + if(nCitedItemsFromLibrary[libA] && !nCitedItemsFromLibrary[libB]) { + return -1; + } + if(!nCitedItemsFromLibrary[libA] && nCitedItemsFromLibrary[libB]) { + return 1; + } + if(nCitedItemsFromLibrary[libA] !== nCitedItemsFromLibrary[libB]) { + return nCitedItemsFromLibrary[libB] - nCitedItemsFromLibrary[libA]; + } + + // Sort by ID even if number of cites is equal + return libA - libB; + } + + // Sort by last name of first author + var creatorsA = a.getCreators(), creatorsB = b.getCreators(), + caExists = creatorsA.length ? 1 : 0, cbExists = creatorsB.length ? 1 : 0; + if(caExists !== cbExists) { + return cbExists-caExists; + } else if(caExists) { + return creatorsA[0].ref.lastName.localeCompare(creatorsB[0].ref.lastName); + } + + // Sort by date + var yearA = a.getField("date", true, true).substr(0, 4), + yearB = b.getField("date", true, true).substr(0, 4); + return yearA - yearB; + }); var previousLibrary = -1; - for(var i=0, n=items.length; i<n; i++) { + for(var i=0, n=Math.min(items.length, citedItems ? 50-citedItems.length : 50); i<n; i++) { var item = items[i], libraryID = item.libraryID; if(previousLibrary != libraryID) { @@ -483,7 +522,6 @@ var Zotero_QuickFormat = new function () { // add to rich list item var rll = document.createElement("richlistitem"); rll.setAttribute("orient", "vertical"); - rll.setAttribute("flex", "1"); rll.setAttribute("class", "quick-format-item"); rll.setAttribute("zotero-item", item.cslItemID ? item.cslItemID : item.id); rll.appendChild(titleNode); @@ -506,7 +544,6 @@ var Zotero_QuickFormat = new function () { // add to rich list item var rll = document.createElement("richlistitem"); rll.setAttribute("orient", "vertical"); - rll.setAttribute("flex", "1"); rll.setAttribute("disabled", true); rll.setAttribute("class", loading ? "quick-format-loading" : "quick-format-separator"); rll.appendChild(titleNode); @@ -522,20 +559,48 @@ var Zotero_QuickFormat = new function () { function _buildBubbleString(citationItem) { var item = Zotero.Cite.getItem(citationItem.id); // create text for bubble + + // Creator var title, delimiter; var str = item.getField("firstCreator"); + + // Title, if no creator if(!str) { // TODO localize quotes str = '"'+item.getField("title")+'"'; } + // Date var date = item.getField("date", true); if(date && (date = date.substr(0, 4)) !== "0000") { str += ", "+date; } + // Locator if(citationItem.locator) { - str += ", "+(citationItem.locator.indexOf("-") !== -1 || citationItem.locator.indexOf("–") !== -1 ? "pp" : "p")+". "+citationItem.locator; + if(citationItem.label) { + // TODO localize and use short forms + var label = citationItem.label; + } else if(/[\-–,]/.test(citationItem.locator)) { + var label = "pp."; + } else { + var label = "p." + } + + str += ", "+label+" "+citationItem.locator; + } + + // Prefix + if(citationItem.prefix && Zotero.CiteProc.CSL.ENDSWITH_ROMANESQUE_REGEXP) { + str = citationItem.prefix + +(Zotero.CiteProc.CSL.ENDSWITH_ROMANESQUE_REGEXP.test(citationItem.prefix) ? " " : "") + +str; + } + + // Suffix + if(citationItem.suffix && Zotero.CiteProc.CSL.STARTSWITH_ROMANESQUE_REGEXP) { + str += (Zotero.CiteProc.CSL.STARTSWITH_ROMANESQUE_REGEXP.test(citationItem.suffix) ? " " : "") + +citationItem.suffix; } return str; @@ -587,10 +652,10 @@ var Zotero_QuickFormat = new function () { citationItem.uris = item.cslURIs; citationItem.itemData = item.cslItemData; } - if(curLocator) { - citationItem["locator"] = curLocator; - if(curLocatorLabel) { - citationItem["label"] = curLocatorLabel; + if(currentLocator) { + citationItem["locator"] = currentLocator; + if(currentLocatorLabel) { + citationItem["label"] = currentLocatorLabel; } } @@ -617,12 +682,8 @@ var Zotero_QuickFormat = new function () { * Resizes window to fit content */ function _resize() { - var childNodes = referenceBox.childNodes, - numReferences = 0, - numSeparators = 0, - firstReference, - firstSeparator, - height; + var childNodes = referenceBox.childNodes, numReferences = 0, numSeparators = 0, + firstReference, firstSeparator, height; for(var i=0, n=childNodes.length; i<n && numReferences < SHOWN_REFERENCES; i++) { if(childNodes[i].className === "quick-format-item") { numReferences++; @@ -638,10 +699,7 @@ var Zotero_QuickFormat = new function () { if(qfeHeight > 30) { qfe.setAttribute("multiline", true); qfs.setAttribute("multiline", true); - qfeHeight = qfe.scrollHeight; - var height = 4+qfeHeight; - - qfs.style.height = height+"px"; + qfs.style.height = (4+qfeHeight)+"px"; window.sizeToContent(); } else { delete qfs.style.height; @@ -652,32 +710,30 @@ var Zotero_QuickFormat = new function () { var panelShowing = referencePanel.state === "open" || referencePanel.state === "showing"; - if(numReferences) { - var height = referenceHeight ? - Math.min(numReferences*referenceHeight+1+numSeparators*separatorHeight) : 39; - - if(panelShowing && height !== referencePanel.clientHeight) { - referencePanel.sizeTo((window.outerWidth-30), height); - /*if(curResizer) curResizer.stop(); - curResizer = new Resizer(referencePanel, null, height, 30, 1000); - curResizer.animate();*/ - } else { - referencePanel.sizeTo((window.outerWidth-30), height); - referencePanel.openPopup(document.documentElement, "after_start", 15, null, - false, false, null); - - if(!referenceHeight) { - separatorHeight = firstSeparator.scrollHeight; - referenceHeight = firstReference.scrollHeight; - height = Math.min(numReferences*referenceHeight+1+numSeparators*separatorHeight); - referencePanel.sizeTo((window.outerWidth-30), height); - } + if(numReferences || numSeparators) { + if(!referenceHeight && firstReference) { + if(!panelShowing) referencePanel.openPopup(document.documentElement, "after_start", 15, + null, false, false, null); + panelShowing = true; + referenceHeight = firstReference.scrollHeight; + if(firstReference === referenceBox.lastChild) referenceHeight += 1; } - } else { - if(panelShowing) { - referencePanel.hidePopup(); - referencePanel.sizeTo(referencePanel.clientWidth, 0); + + if(!separatorHeight && firstSeparator) { + if(!panelShowing) referencePanel.openPopup(document.documentElement, "after_start", 15, + null, false, false, null); + panelShowing = true; + separatorHeight = firstSeparator.scrollHeight; + if(firstSeparator === referenceBox.lastChild) separatorHeight += 1; } + + referencePanel.sizeTo(window.outerWidth-30, + numReferences*referenceHeight+1+numSeparators*separatorHeight-1); + if(!panelShowing) referencePanel.openPopup(document.documentElement, "after_start", 15, + null, false, false, null); + } else if(panelShowing) { + referencePanel.hidePopup(); + referencePanel.sizeTo(window.outerWidth-30, 0); } } @@ -768,71 +824,31 @@ var Zotero_QuickFormat = new function () { * Shows the citation properties panel for a given bubble */ function _showCitationProperties(target) { - var panel = document.getElementById("citation-properties"); - var prefix = document.getElementById("prefix"); - var suffix = document.getElementById("suffix"); - var suppressAuthor = document.getElementById("suppress-author"); - var locatorLabel = document.getElementById("locator-label"); - var locator = document.getElementById("locator"); - var info = document.getElementById("citation-properties-info"); - - prefix.value = target.citationItem["prefix"] ? target.citationItem["prefix"] : ""; - suffix.value = target.citationItem["suffix"] ? target.citationItem["suffix"] : ""; + panelRefersToBubble = target; + panelPrefix.value = target.citationItem["prefix"] ? target.citationItem["prefix"] : ""; + panelSuffix.value = target.citationItem["suffix"] ? target.citationItem["suffix"] : ""; if(target.citationItem["label"]) { - var option = locatorLabel.getElementsByAttribute("value", target.citationItem["label"]); + var option = panelLocatorLabel.getElementsByAttribute("value", target.citationItem["label"]); if(option.length) { - locatorLabel.selectedItem = option[0]; + panelLocatorLabel.selectedItem = option[0]; } else { - locatorLabel.selectedIndex = 0; + panelLocatorLabel.selectedIndex = 0; } } else { - locatorLabel.selectedIndex = 0; + panelLocatorLabel.selectedIndex = 0; } - locator.value = target.citationItem["locator"] ? target.citationItem["locator"] : ""; - suppressAuthor.checked = !!target.citationItem["suppress-author"]; + panelLocator.value = target.citationItem["locator"] ? target.citationItem["locator"] : ""; + panelSuppressAuthor.checked = !!target.citationItem["suppress-author"]; 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); + while(panelInfo.hasChildNodes()) panelInfo.removeChild(panelInfo.firstChild); + _buildItemDescription(item, panelInfo); target.setAttribute("selected", "true"); panel.openPopup(target, "after_start", target.clientWidth/2, 0, false, false, null); - locator.focus(); - - var closeListener = function(event) { - panel.removeEventListener("popuphidden", closeListener, false); - target.removeAttribute("selected"); - if(prefix.value) { - target.citationItem["prefix"] = prefix.value; - } else { - delete target.citationItem["prefix"]; - } - if(suffix.value) { - target.citationItem["suffix"] = suffix.value; - } else { - delete target.citationItem["suffix"]; - } - if(locatorLabel.selectedIndex !== 0) { - target.citationItem["label"] = locatorLabel.selectedItem.value; - } else { - delete target.citationItem["label"]; - } - if(locator.value) { - target.citationItem["locator"] = locator.value; - } else { - delete target.citationItem["locator"]; - } - if(suppressAuthor.checked) { - target.citationItem["suppress-author"] = true; - } else { - delete target.citationItem["suppress-author"]; - } - target.value = _buildBubbleString(target.citationItem); - _moveCursorToEnd(); - } - panel.addEventListener("popuphidden", closeListener, false); + panelLocator.focus(); } /** @@ -1008,6 +1024,47 @@ var Zotero_QuickFormat = new function () { } /** + * Handle changes to citation properties + */ + this.onCitationPropertiesChanged = function(event) { + if(panelPrefix.value) { + panelRefersToBubble.citationItem["prefix"] = panelPrefix.value; + } else { + delete panelRefersToBubble.citationItem["prefix"]; + } + if(panelSuffix.value) { + panelRefersToBubble.citationItem["suffix"] = panelSuffix.value; + } else { + delete panelRefersToBubble.citationItem["suffix"]; + } + if(panelLocatorLabel.selectedIndex !== 0) { + panelRefersToBubble.citationItem["label"] = panelLocatorLabel.selectedItem.value; + } else { + delete panelRefersToBubble.citationItem["label"]; + } + if(panelLocator.value) { + panelRefersToBubble.citationItem["locator"] = panelLocator.value; + } else { + delete panelRefersToBubble.citationItem["locator"]; + } + if(panelSuppressAuthor.checked) { + panelRefersToBubble.citationItem["suppress-author"] = true; + } else { + delete panelRefersToBubble.citationItem["suppress-author"]; + } + panelRefersToBubble.value = _buildBubbleString(panelRefersToBubble.citationItem); + }; + + /** + * Handle closing citation properties panel + */ + this.onCitationPropertiesClosed = function(event) { + panelRefersToBubble.removeAttribute("selected"); + Zotero_QuickFormat.onCitationPropertiesChanged(); + _moveCursorToEnd(); + } + + /** * Makes "Enter" work in the panel */ this.onPanelKeyPress = function(event) { @@ -1025,12 +1082,6 @@ var Zotero_QuickFormat = new function () { }; /** - * Handle checking/unchecking "Show Editor" - */ - this.onShowEditorCommand = function(event) { - }; - - /** * Open classic Add Citation window */ this.onClassicViewCommand = function(event) { diff --git a/chrome/content/zotero/integration/quickFormat.xul b/chrome/content/zotero/integration/quickFormat.xul @@ -65,10 +65,12 @@ <progressmeter id="quick-format-progress-meter" mode="undetermined" value="0" flex="1"/> </deck> </windowdragbox> - <panel id="quick-format-reference-panel" noautofocus="true" norestorefocus="true" noautohide="true"> + <panel id="quick-format-reference-panel" noautofocus="true" norestorefocus="true" noautohide="true" height="0"> <richlistbox id="quick-format-reference-list" flex="1"/> </panel> - <panel id="citation-properties" type="arrow" orient="vertical" onkeypress="Zotero_QuickFormat.onPanelKeyPress(event)"> + <panel id="citation-properties" type="arrow" orient="vertical" + onkeypress="Zotero_QuickFormat.onPanelKeyPress(event)" + onpopuphidden="Zotero_QuickFormat.onCitationPropertiesClosed(event)"> <vbox flex="1"> <description id="citation-properties-title"/> <hbox id="citation-properties-info"/> @@ -80,22 +82,29 @@ </columns> <rows> <row align="center"> - <menulist id="locator-label" sizetopopup="none"> + <menulist id="locator-label" sizetopopup="none" + oncommand="Zotero_QuickFormat.onCitationPropertiesChanged(event)"> <menupopup id="locator-label-popup"/> </menulist> - <textbox id="locator" flex="1"/> + <textbox id="locator" flex="1" + oninput="window.setTimeout(Zotero_QuickFormat.onCitationPropertiesChanged, 0)"/> </row> <row align="center"> <label value="&zotero.citation.prefix.label;"/> - <textbox class="citation-textbox" id="prefix" flex="1"/> + <textbox class="citation-textbox" id="prefix" flex="1" + oninput="window.setTimeout(Zotero_QuickFormat.onCitationPropertiesChanged, 0)"/> </row> <row align="center"> <label value="&zotero.citation.suffix.label;"/> - <textbox class="citation-textbox" id="suffix" flex="1"/> + <textbox class="citation-textbox" id="suffix" flex="1" + oninput="window.setTimeout(Zotero_QuickFormat.onCitationPropertiesChanged, 0)"/> </row> <html:div> - <html:input type="checkbox" id="suppress-author"/> - <html:label for="suppress-author">&zotero.citation.suppressAuthor.label;</html:label> + <html:input type="checkbox" id="suppress-author" + onchange="Zotero_QuickFormat.onCitationPropertiesChanged(event)"/> + <html:label for="suppress-author"> + &zotero.citation.suppressAuthor.label; + </html:label> </html:div> </rows> </grid> diff --git a/chrome/content/zotero/recognizePDF.js b/chrome/content/zotero/recognizePDF.js @@ -310,7 +310,8 @@ Zotero_RecognizePDF.Recognizer.prototype.recognize = function(file, libraryID, c // get (not quite) median length var lineLengthsLength = lineLengths.length; - if(lineLengthsLength < 20) { + if(lineLengthsLength < 20 + || lines[0] === "This is a digital copy of a book that was preserved for generations on library shelves before it was carefully scanned by Google as part of a project") { this._callback(false, "recognizePDF.noOCR"); } else { var sortedLengths = lineLengths.sort(); @@ -329,9 +330,6 @@ Zotero_RecognizePDF.Recognizer.prototype.recognize = function(file, libraryID, c } this._startLine = this._iteration = 0; - } - - if(lineLengthsLength >= 20) { this._queryGoogle(); } } @@ -403,16 +401,18 @@ Zotero_RecognizePDF.Recognizer.prototype._queryGoogle = function() { } var translate = new Zotero.Translate("web"); + var savedItem = false; translate.setTranslator("57a00950-f0d1-4b41-b6ba-44ff0fc30289"); translate.setHandler("itemDone", function(translate, item) { Zotero.Browser.deleteHiddenBrowser(me._hiddenBrowser); + savedItem = true; me._callback(item); }); translate.setHandler("select", function(translate, items, callback) { me._selectItems(translate, items, callback); }); translate.setHandler("done", function(translate, success) { - if(!success) me._queryGoogle(); + if(!success || !savedItem) me._queryGoogle(); }); this._hiddenBrowser.addEventListener("pageshow", function() { me._scrape(translate) }, true); diff --git a/chrome/content/zotero/xpcom/citeproc.js b/chrome/content/zotero/xpcom/citeproc.js @@ -419,6 +419,23 @@ var CSL = { "\u06E5": "\u0648", "\u06E6": "\u064A" }, + LOCATOR_LABELS_REGEXP: new RegExp("^((ch|col|fig|no|l|n|op|p|para|pt|sec|sv|vrs|vol)\\.)\\s+(.*)"), + LOCATOR_LABELS_MAP: { + "ch": "chapter", + "col": "column", + "fig": "figure", + "no": "issue", + "l": "line", + "n": "note", + "op": "opus", + "p": "page", + "para": "para", + "pt": "part", + "sec": "section", + "sv": "sub-verbo", + "vrs": "verse", + "vol": "volume" + }, SUPERSCRIPTS_REGEXP: new RegExp("[\u00AA\u00B2\u00B3\u00B9\u00BA\u02B0\u02B1\u02B2\u02B3\u02B4\u02B5\u02B6\u02B7\u02B8\u02E0\u02E1\u02E2\u02E3\u02E4\u1D2C\u1D2D\u1D2E\u1D30\u1D31\u1D32\u1D33\u1D34\u1D35\u1D36\u1D37\u1D38\u1D39\u1D3A\u1D3C\u1D3D\u1D3E\u1D3F\u1D40\u1D41\u1D42\u1D43\u1D44\u1D45\u1D46\u1D47\u1D48\u1D49\u1D4A\u1D4B\u1D4C\u1D4D\u1D4F\u1D50\u1D51\u1D52\u1D53\u1D54\u1D55\u1D56\u1D57\u1D58\u1D59\u1D5A\u1D5B\u1D5C\u1D5D\u1D5E\u1D5F\u1D60\u1D61\u2070\u2071\u2074\u2075\u2076\u2077\u2078\u2079\u207A\u207B\u207C\u207D\u207E\u207F\u2120\u2122\u3192\u3193\u3194\u3195\u3196\u3197\u3198\u3199\u319A\u319B\u319C\u319D\u319E\u319F\u02C0\u02C1\u06E5\u06E6]", "g"), locale: {}, locale_opts: {}, @@ -800,7 +817,7 @@ CSL.Output.Queue.prototype.closeLevel = function (name) { } this.current.pop(); }; -CSL.Output.Queue.prototype.append = function (str, tokname, notSerious) { +CSL.Output.Queue.prototype.append = function (str, tokname, notSerious, ignorePredecessor) { var token, blob, curr; var useblob = true; if (this.state.tmp["doing-macro-with-date"]) { @@ -843,7 +860,9 @@ CSL.Output.Queue.prototype.append = function (str, tokname, notSerious) { str = str.replace(/ ([:;?!\u00bb])/g, "\u202f$1").replace(/\u00ab /g, "\u00ab\u202f"); this.last_char_rendered = str.slice(-1); str = str.replace(/\s+'/g, " \'").replace(/^'/g, " \'"); - this.state.tmp.term_predecessor = true; + if (!ignorePredecessor) { + this.state.tmp.term_predecessor = true; + } } blob = new CSL.Blob(str, token); curr = this.current.value(); @@ -855,7 +874,9 @@ CSL.Output.Queue.prototype.append = function (str, tokname, notSerious) { if (this.state.tmp.strip_periods) { blob.blobs = blob.blobs.replace(/\./g, ""); } - this.state.tmp.term_predecessor = true; + if (!ignorePredecessor) { + this.state.tmp.term_predecessor = true; + } } if (!notSerious) { this.state.parallel.AppendBlobPointer(curr); @@ -1942,7 +1963,7 @@ CSL.DateParser = function () { }; CSL.Engine = function (sys, style, lang, forceLang) { var attrs, langspec, localexml, locale; - this.processor_version = "1.0.250"; + this.processor_version = "1.0.252"; this.csl_version = "1.0"; this.sys = sys; this.sys.xml = new CSL.System.Xml.Parsing(); @@ -2495,6 +2516,7 @@ CSL.Engine.Opt = function () { this.development_extensions.field_hack = true; this.development_extensions.locator_date_and_revision = true; this.development_extensions.locator_parsing_for_plurals = true; + this.development_extensions.locator_label_parse = true; this.development_extensions.raw_date_parsing = true; this.development_extensions.clean_up_csl_flaws = true; this.gender = {}; @@ -3128,6 +3150,15 @@ CSL.Engine.prototype.processCitationCluster = function (citation, citationsPre, } } } + if (this.opt.development_extensions.locator_label_parse) { + if (item.locator && (!item.label || item.label === 'page')) { + var m = CSL.LOCATOR_LABELS_REGEXP.exec(item.locator); + if (m) { + item.label = CSL.LOCATOR_LABELS_MAP[m[2]]; + item.locator = m[3]; + } + } + } Item = this.retrieveItem("" + item.id); var newitem = [Item, item]; sortedItems.push(newitem); @@ -3800,8 +3831,8 @@ CSL.localeResolve = function (langstr) { langlst = langstr.split(/[\-_]/); ret.base = CSL.LANG_BASES[langlst[0]]; if ("undefined" === typeof ret.base) { - CSL.debug("Warning: unknown locale "+langstr+", setting to en-US"); - return {base:"en-US", best:"en-US", bare:"en"}; + CSL.debug("Warning: unknown locale "+langstr+", setting fallback to en-US"); + return {base:"en-US", best:langstr, bare:"en"}; } if (langlst.length === 1 || langlst[1] === "x") { ret.best = ret.base.replace("_", "-"); @@ -4261,7 +4292,7 @@ CSL.Node["date-part"] = { if (state.registry.registry[Item.id] && state.registry.registry[Item.id].disambig.year_suffix !== false && !state.tmp.has_done_year_suffix) { state.tmp.has_done_year_suffix = true; num = parseInt(state.registry.registry[Item.id].disambig.year_suffix, 10); - number = new CSL.NumericBlob(num, this); + number = new CSL.NumericBlob(num, this, Item.id); this.successor_prefix = state[state.build.area].opt.layout_delimiter; this.splice_prefix = state[state.build.area].opt.layout_delimiter; formatter = new CSL.Util.Suffixator(CSL.SUFFIX_CHARS); @@ -4762,10 +4793,18 @@ CSL.Node.layout = { var sp; if (item && item.prefix) { sp = ""; - if (item.prefix.match(CSL.ENDSWITH_ROMANESQUE_REGEXP)) { + var prefix = item.prefix.replace(/<[^>]+>/g, "").replace(/\s+$/, "").replace(/^\s+/, ""); + if (prefix.match(CSL.ENDSWITH_ROMANESQUE_REGEXP)) { sp = " "; } - state.output.append((item.prefix + sp), this); + var ignorePredecessor = false; + if (CSL.TERMINAL_PUNCTUATION.slice(0,-1).indexOf(prefix.slice(-1)) > -1 + && prefix[0] != prefix[0].toLowerCase()) { + state.tmp.term_predecessor = false; + ignorePredecessor = true; + } + prefix = (item.prefix + sp).replace(/\s+/g, " ") + state.output.append(prefix, this, false, ignorePredecessor); } }; prefix_token.execs.push(func); @@ -6321,7 +6360,7 @@ CSL.NameOutput.prototype._splitInstitution = function (value, v, i) { splitInstitution = splitInstitution.split("|"); if (this.institution.strings.form === "short" && this.state.sys.getAbbreviation) { var jurisdiction = this.Item.jurisdiction; - for (var j = splitInstitution.length; j > 1; j += -1) { + for (var j = splitInstitution.length; j > 0; j += -1) { var str = splitInstitution.slice(0, j).join("|"); var jurisdiction = this.state.transform.loadAbbreviation(jurisdiction, "institution-entire", str); if (this.state.transform.abbrevs[jurisdiction]["institution-entire"][str]) { @@ -6912,19 +6951,21 @@ CSL.Node.number = { } var values = state.tmp.shadow_numbers[varname].values; var blob; + var newstr = "" if (state.opt["page-range-format"] && !this.strings.prefix && !this.strings.suffix && !this.strings.form) { - var newstr = "" for (var i = 0, ilen = values.length; i < ilen; i += 1) { newstr += values[i][1]; } newstr = state.fun.page_mangler(newstr); + } + if (newstr && !newstr.match(/^[0-9]+$/)) { state.output.append(newstr, this); } else { state.output.openLevel("empty"); for (var i = 0, ilen = values.length; i < ilen; i += 1) { - var blob = new CSL[values[i][0]](values[i][1], values[i][2]); + var blob = new CSL[values[i][0]](values[i][1], values[i][2], Item.id); if (i > 0) { blob.strings.prefix = blob.strings.prefix.replace(/^\s*/, ""); } @@ -7033,7 +7074,7 @@ CSL.Node.text = { if (state.opt.citation_number_slug) { state.output.append(state.opt.citation_number_slug, this); } else { - number = new CSL.NumericBlob(num, this); + number = new CSL.NumericBlob(num, this, Item.id); state.output.append(number, "literal"); } } @@ -7051,7 +7092,7 @@ CSL.Node.text = { func = function (state, Item) { if (state.registry.registry[Item.id] && state.registry.registry[Item.id].disambig.year_suffix !== false && !state.tmp.just_looking) { num = parseInt(state.registry.registry[Item.id].disambig.year_suffix, 10); - number = new CSL.NumericBlob(num, this); + number = new CSL.NumericBlob(num, this, Item.id); formatter = new CSL.Util.Suffixator(CSL.SUFFIX_CHARS); number.setFormatter(formatter); state.output.append(number, "literal"); @@ -7103,16 +7144,7 @@ CSL.Node.text = { if (!state.tmp.term_predecessor) { myterm = CSL.Output.Formatters["capitalize-first"](state, term); } else { - if (item && item.prefix) { - var prefix = item.prefix.replace(/\s+$/, ""); - if (CSL.TERMINAL_PUNCTUATION.slice(0,-1).indexOf(prefix.slice(-1)) > -1) { - myterm = CSL.Output.Formatters["capitalize-first"](state, term); - } else { - myterm = term; - } - } else { - myterm = term; - } + myterm = term; } if (state.tmp.strip_periods) { myterm = myterm.replace(/\./g, ""); @@ -7251,6 +7283,54 @@ CSL.Node.text = { } }; CSL.Attributes = {}; +CSL.Attributes["@has-year-only"] = function (state, arg) { + trydates = arg.split(/\s+/); + func = function (state, Item, item) { + var ret = []; + for (var i = 0, ilen = trydates.length; i < ilen; i += 1) { + var trydate = Item[trydates[i]]; + if (!trydate || trydate.month || trydate.season) { + ret.push(false) + } else { + ret.push(true) + } + } + return ret; + }; + this.tests.push(func); +} +CSL.Attributes["@has-month-or-season-only"] = function (state, arg) { + trydates = arg.split(/\s+/); + func = function (state, Item, item) { + var ret = []; + for (var i = 0, ilen = trydates.length; i < ilen; i += 1) { + var trydate = Item[trydates[i]]; + if (!trydate || (!trydate.month && !trydate.season) || trydate.day) { + ret.push(false) + } else { + ret.push(true) + } + } + return ret; + }; + this.tests.push(func); +} +CSL.Attributes["@has-day-only"] = function (state, arg) { + trydates = arg.split(/\s+/); + func = function (state, Item, item) { + var ret = []; + for (var i = 0, ilen = trydates.length; i < ilen; i += 1) { + var trydate = Item[trydates[i]]; + if (!trydate || !trydate.day) { + ret.push(false) + } else { + ret.push(true) + } + } + return ret; + }; + this.tests.push(func); +} CSL.Attributes["@part-separator"] = function (state, arg) { this.strings["part-separator"] = arg; } @@ -8229,6 +8309,9 @@ CSL.Transform = function (state) { jurisdiction = "default"; } if (!orig) { + if (!this.abbrevs[jurisdiction]) { + this.abbrevs[jurisdiction] = new CSL.AbbreviationSegments(); + } return jurisdiction; } if (state.sys.getAbbreviation) { @@ -8847,7 +8930,8 @@ CSL.Blob.prototype.push = function (blob) { this.blobs.push(blob); } }; -CSL.NumericBlob = function (num, mother_token) { +CSL.NumericBlob = function (num, mother_token, id) { + this.id = id; this.alldecor = []; this.num = num; this.blobs = num.toString(); @@ -8888,7 +8972,9 @@ CSL.Output.DefaultFormatter.prototype.format = function (num) { return num.toString(); }; CSL.NumericBlob.prototype.checkNext = function (next) { - if (! next || !next.num || this.type !== next.type || next.num !== (this.num + 1)) { + if (next && this.id == next.id) { + this.status = CSL.START; + } else if (! next || !next.num || this.type !== next.type || next.num !== (this.num + 1)) { if (this.status === CSL.SUCCESSOR_OF_SUCCESSOR) { this.status = CSL.END; } diff --git a/chrome/content/zotero/xpcom/integration.js b/chrome/content/zotero/xpcom/integration.js @@ -1010,16 +1010,18 @@ Zotero.Integration.Fields.prototype.updateSession = function(callback) { if(me._session.reload) { //this._session.restoreProcessorState(); TODO doesn't appear to be working properly me._session.updateUpdateIndices(); - var deleteCitations = me._session.updateCitations(); - me._deleteFields = me._deleteFields.concat([i for(i in deleteCitations)]); - me._session.updateIndices = {}; - me._session.updateItemIDs = {}; - me._session.citationText = {}; - me._session.bibliographyHasChanged = false; - delete me._session.reload; + Zotero.pumpGenerator(me._session.updateCitations(function(deleteCitations) { + me._deleteFields = me._deleteFields.concat([i for(i in deleteCitations)]); + me._session.updateIndices = {}; + me._session.updateItemIDs = {}; + me._session.citationText = {}; + me._session.bibliographyHasChanged = false; + delete me._session.reload; + if(callback) callback(me._session); + })); + } else { + if(callback) callback(this._session); } - - if(callback) callback(this._session); }); }); } @@ -1109,7 +1111,13 @@ Zotero.Integration.Fields.prototype._processFields = function(fields, callback, */ Zotero.Integration.Fields.prototype.updateDocument = function(forceCitations, forceBibliography, ignoreCitationChanges, callback) { - Zotero.pumpGenerator(this._updateDocument(forceCitations, forceBibliography, ignoreCitationChanges, callback)); + // update citations + this._session.updateUpdateIndices(forceCitations); + var me = this; + var deleteCitations = Zotero.pumpGenerator(this._session.updateCitations(function(deleteCitations) { + Zotero.pumpGenerator(me._updateDocument(forceCitations, forceBibliography, + ignoreCitationChanges, deleteCitations, callback)); + })); } /** @@ -1120,11 +1128,9 @@ Zotero.Integration.Fields.prototype.updateDocument = function(forceCitations, fo * modified since they were created, instead of showing a warning */ Zotero.Integration.Fields.prototype._updateDocument = function(forceCitations, forceBibliography, - ignoreCitationChanges, callback) { + ignoreCitationChanges, deleteCitations, callback) { try { // update citations - this._session.updateUpdateIndices(forceCitations); - var deleteCitations = this._session.updateCitations(); this._deleteFields = this._deleteFields.concat([i for(i in deleteCitations)]); if(this.progressCallback) { @@ -2159,64 +2165,69 @@ Zotero.Integration.Session.prototype.formatCitation = function(index, citation) /** * Updates the list of citations to be serialized to the document */ -Zotero.Integration.Session.prototype.updateCitations = function() { - /*var allUpdatesForced = false; - var forcedUpdates = {}; - if(force) { - allUpdatesForced = true; - // make sure at least one citation gets updated - updateLoop: for each(var indexList in [this.newIndices, this.updateIndices]) { - for(var i in indexList) { - if(!this.citationsByIndex[i].properties.delete) { - allUpdatesForced = false; - break updateLoop; +Zotero.Integration.Session.prototype.updateCitations = function(callback) { + try { + /*var allUpdatesForced = false; + var forcedUpdates = {}; + if(force) { + allUpdatesForced = true; + // make sure at least one citation gets updated + updateLoop: for each(var indexList in [this.newIndices, this.updateIndices]) { + for(var i in indexList) { + if(!this.citationsByIndex[i].properties.delete) { + allUpdatesForced = false; + break updateLoop; + } } } - } - - if(allUpdatesForced) { - for(i in this.citationsByIndex) { - if(this.citationsByIndex[i] && !this.citationsByIndex[i].properties.delete) { - forcedUpdates[i] = true; - break; + + if(allUpdatesForced) { + for(i in this.citationsByIndex) { + if(this.citationsByIndex[i] && !this.citationsByIndex[i].properties.delete) { + forcedUpdates[i] = true; + break; + } } } + }*/ + + if(Zotero.Debug.enabled) { + Zotero.debug("Integration: Indices of new citations"); + Zotero.debug([key for(key in this.newIndices)]); + Zotero.debug("Integration: Indices of updated citations"); + Zotero.debug([key for(key in this.updateIndices)]); } - }*/ - - if(Zotero.Debug.enabled) { - Zotero.debug("Integration: Indices of new citations"); - Zotero.debug([key for(key in this.newIndices)]); - Zotero.debug("Integration: Indices of updated citations"); - Zotero.debug([key for(key in this.updateIndices)]); - } - - var deleteCitations = {}; - for each(var indexList in [this.newIndices, this.updateIndices]) { - for(var index in indexList) { - index = parseInt(index); - - var citation = this.citationsByIndex[index]; - if(citation.properties.delete) { - deleteCitations[index] = true; - continue; - } - if(this.formatCitation(index, citation)) { - this.bibliographyHasChanged = true; - } - if(!this.citationIDs[citation.citationID]) { - this.citationIDs[citation.citationID] = citation; + + var deleteCitations = {}; + for each(var indexList in [this.newIndices, this.updateIndices]) { + for(var index in indexList) { + index = parseInt(index); + + var citation = this.citationsByIndex[index]; + if(citation.properties.delete) { + deleteCitations[index] = true; + continue; + } + if(this.formatCitation(index, citation)) { + this.bibliographyHasChanged = true; + } + if(!this.citationIDs[citation.citationID]) { + this.citationIDs[citation.citationID] = citation; + } + delete this.newIndices[index]; + yield true; } - delete this.newIndices[index]; } + + /*if(allUpdatesForced) { + this.newIndices = {}; + this.updateIndices = {}; + }*/ + + callback(deleteCitations); + } catch(e) { + Zotero.Integration.handleError(e, this._doc); } - - /*if(allUpdatesForced) { - this.newIndices = {}; - this.updateIndices = {}; - }*/ - - return deleteCitations; } /** diff --git a/chrome/content/zotero/xpcom/translation/translate.js b/chrome/content/zotero/xpcom/translation/translate.js @@ -849,10 +849,11 @@ Zotero.Translate.Base.prototype = { args.push(arguments[i]); } - for(var i=0, n=this._handlers[type].length; i<n; i++) { + var handlers = this._handlers[type].slice(); + for(var i=0, n=handlers.length; i<n; i++) { Zotero.debug("Translate: Running handler "+i+" for "+type, 5); try { - returnValue = this._handlers[type][i].apply(null, args); + returnValue = handlers[i].apply(null, args); } catch(e) { if(this._parentTranslator) { // throw handler errors if they occur when a translator is diff --git a/chrome/content/zotero/xpcom/utilities.js b/chrome/content/zotero/xpcom/utilities.js @@ -1329,8 +1329,10 @@ Zotero.Utilities = { // map text fields for(var variable in CSL_TEXT_MAPPINGS) { if(variable in cslItem) { - for each(var field in CSL_TEXT_MAPPINGS[variable]) { - var fieldID = Zotero.ItemFields.getID(field); + var textMappings = CSL_TEXT_MAPPINGS[variable]; + for(var i in textMappings) { + var field = textMappings[i], + fieldID = Zotero.ItemFields.getID(field); if(Zotero.ItemFields.isBaseField(fieldID)) { var newFieldID = Zotero.ItemFields.getFieldIDFromTypeAndBase(itemTypeID, fieldID); if(newFieldID) fieldID = newFieldID; @@ -1355,8 +1357,10 @@ Zotero.Utilities = { creatorTypeID = Zotero.CreatorTypes.getPrimaryIDForType(itemTypeID); } - for each(var cslAuthor in cslItem[CSL_NAMES_MAPPINGS[field]]) { - var creator = isZoteroItem ? new Zotero.Creator() : {}; + var nameMappings = cslItem[CSL_NAMES_MAPPINGS[field]]; + for(var i in nameMappings) { + var cslAuthor = nameMappings[i], + creator = isZoteroItem ? new Zotero.Creator() : {}; if(cslAuthor.family || cslAuthor.given) { if(cslAuthor.family) creator.lastName = cslAuthor.family; if(cslAuthor.given) creator.firstName = cslAuthor.given; diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js @@ -1092,6 +1092,9 @@ var ZoteroPane = new function() this.getItemGroup = function () { + if (!this.collectionsView.selection) { + return false; + } return this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex); }