From a66555e45b5e0a8cf958211d0a15fda6bf5669a5 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Fri, 29 Jul 2011 05:35:54 +0000 Subject: [PATCH] Orbtastic streamlined add citation dialog Does not currently support sorting or citation editor, and has not been tested on any platform but OS X, so off by default for now. Can be enabled with the hidden pref extensions.zotero.integration.quickFormat. --- .../content/zotero/integration/quickFormat.js | 649 ++++++++++++++++++ .../zotero/integration/quickFormat.xul | 81 +++ chrome/content/zotero/xpcom/integration.js | 6 +- chrome/skin/default/zotero/integration.css | 169 +++++ defaults/preferences/zotero.js | 1 + 5 files changed, 905 insertions(+), 1 deletion(-) create mode 100644 chrome/content/zotero/integration/quickFormat.js create mode 100644 chrome/content/zotero/integration/quickFormat.xul diff --git a/chrome/content/zotero/integration/quickFormat.js b/chrome/content/zotero/integration/quickFormat.js new file mode 100644 index 000000000..d4f5be640 --- /dev/null +++ b/chrome/content/zotero/integration/quickFormat.js @@ -0,0 +1,649 @@ +/* + ***** BEGIN LICENSE BLOCK ***** + + Copyright © 2009 Center for History and New Media + George Mason University, Fairfax, Virginia, USA + http://zotero.org + + This file is part of Zotero. + + Zotero is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Zotero is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with Zotero. If not, see . + + ***** END LICENSE BLOCK ***** +*/ + +var Zotero_QuickFormat = new function () { + var io, qft, qftWindow, qftDocument, qfe, + qfb, qfbHeight, + referenceBox, referenceHeight, + dragX, dragY, curLocator, curLocatorLabel, + curIDs = [], curResizer, dragging; + const SHOWN_REFERENCES = 7; + + /** + * Initialize add citation dialog + */ + this.onLoad = function() { + qft = document.getElementById("quick-format-search"); + qfb = document.getElementById("quick-format-entry"); + qfbHeight = qfb.scrollHeight; + referenceBox = document.getElementById("quick-format-reference-list"); + qftWindow = qft.contentWindow; + qftDocument = qft.contentDocument; + qfb.addEventListener("keypress", _onQuickSearchKeyPress, false); + qfe = qftDocument.getElementById("quick-format-editor"); + qfe.focus(); + + // 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; + + // load citation data + io = window.arguments[0].wrappedJSObject; + if(io.citation.citationItems.length) { + // hack to get spacing right + var evt = qftDocument.createEvent("KeyboardEvent"); + evt.initKeyEvent("keypress", true, true, qftWindow, + 0, 0, 0, 0, + 0, " ".charCodeAt(0)) + qfe.dispatchEvent(evt); + window.setTimeout(function() { + var node = qfe.firstChild; + node.nodeValue = ""; + + for(var i=0; i 50) ids = ids.slice(0, 50); + var items = Zotero.Items.get(ids); + for(var i=0, n=items.length; is + var elements = qfe.getElementsByTagName("br"); + for(var i=0, n=elements.length; i 20) { + qft.style.height = (22-16+qfeHeight+(qft.style.height == "22px" ? 2 : -2))+"px"; + qfe.style.lineHeight = "18px"; + qft.setAttribute("multiline", true); + } else { + qft.style.height = "22px"; + qfe.style.lineHeight = "16px"; + qft.removeAttribute("multiline"); + } + if(curResizer) curResizer.stop(); + curResizer = new Resizer(window, null, height, 10, 100); + curResizer.animate(); + } + + /** + * Accepts current selection and adds citation + */ + _accept = function() { + var nodes = qfe.childNodes; + io.citation.citationItems = []; + for(var i=0, n=nodes.length; i'); + event.stopPropagation(); + } + + /** + * Replaces the dummy element with a node to make dropping work + */ + function _onBubbleDrop(event) { + window.setTimeout(function() { + var el = qftDocument.getElementById("zotero-drag"); + if(el) { + _insertBubble(dragging, el); + Zotero.debug(dragging); + el.parentNode.removeChild(el); + } + }, 0); + } + + /** + * Handle a click on a bubble + */ + function _onBubbleClick(event) { + var target = event.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"); + + prefix.value = target.citationItem["prefix"] ? target.citationItem["prefix"] : ""; + suffix.value = target.citationItem["suffix"] ? target.citationItem["suffix"] : ""; + if(target.citationItem["label"]) { + var option = locatorLabel.getElementsByAttribute("value", target.citationItem["label"]); + if(option.length) { + locatorLabel.selectedItem = option[0]; + } else { + locatorLabel.selectedIndex = 0; + } + } else { + locatorLabel.selectedIndex = 0; + } + locator.value = target.citationItem["locator"] ? target.citationItem["locator"] : ""; + suppressAuthor.checked = !!target.citationItem["suppress-author"]; + + target.setAttribute("selected", "true"); + panel.openPopup(target, "after_start", + target.clientWidth/2, 0, false, false, event); + + 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); + } + panel.addEventListener("popuphidden", closeListener, false); + } + + /** + * Called when the user begins to drag the window + */ + this.onDragStart = function(el, event) { + dragX = event.clientX; + dragY = event.clientY; + window.addEventListener("mousemove", _onDrag, false); + window.addEventListener("mouseup", function() { window.removeEventListener("mousemove", _onDrag, false) }, false); + } + + /** + * Called during the window drag + */ + function _onDrag(event) { + window.moveTo(event.screenX-dragX, event.screenY-dragY); + } + + /** + * Makes "Enter" work in the panel + */ + this.onPanelKeyPress = function(event) { + if(keyCode === event.DOM_VK_RETURN || keyCode === event.DOM_VK_ENTER) { + event.target.hidePopup(); + } + }; + + /** + * Resizes windows + * @constructor + */ + var Resizer = function(window, targetWidth, targetHeight, steps, time) { + this.curWidth = window.innerWidth; + this.curHeight = window.innerHeight; + this.difX = (targetWidth ? targetWidth - this.curWidth : 0); + this.difY = (targetHeight ? targetHeight - this.curHeight : 0); + this.step = 0; + this.steps = steps; + this.timeout = time/steps; + + var me = this; + this._animateCallback = function() { me.animate() }; + }; + + /** + * Performs a step of the animation + */ + Resizer.prototype.animate = function() { + if(this.stopped) return; + this.step++; + window.resizeTo(this.curWidth+Math.round(this.step*this.difX/this.steps), + this.curHeight+Math.round(this.step*this.difY/this.steps)); + if(this.step !== this.steps) { + window.setTimeout(this._animateCallback, this.timeout); + } + }; + + /** + * Halts resizing + */ + Resizer.prototype.stop = function() { + this.stopped = true; + }; +} + +window.addEventListener("load", Zotero_QuickFormat.onLoad, false); \ No newline at end of file diff --git a/chrome/content/zotero/integration/quickFormat.xul b/chrome/content/zotero/integration/quickFormat.xul new file mode 100644 index 000000000..8f6b18f27 --- /dev/null +++ b/chrome/content/zotero/integration/quickFormat.xul @@ -0,0 +1,81 @@ + + + + + + + + + + + + +