Closes #405, Pressing copy keystroke with item selected should copy citation to clipboard

Shortcut key defaults to "C"

Abstracted clipboard logic in Zotero_File_Interface._doBibliographyOptions() to separate function, Z_F_I.copyItemsToClipboard(items, style), which ZoteroPane.copySelectedItemsToClipboard() calls

Currently limited to citation styles, but there's no reason it couldn't support export formats, etc.
This commit is contained in:
Dan Stillman 2007-02-17 23:13:48 +00:00
parent 97d1e0b844
commit a076095400
9 changed files with 217 additions and 56 deletions

View File

@ -113,6 +113,7 @@ var Zotero_File_Interface = new function() {
this.importFile = importFile;
this.bibliographyFromCollection = bibliographyFromCollection;
this.bibliographyFromItems = bibliographyFromItems;
this.copyItemsToClipboard = copyItemsToClipboard;
/*
* Creates Zotero.Translate instance and shows file picker for file export
@ -278,20 +279,55 @@ var Zotero_File_Interface = new function() {
_doBibliographyOptions(Zotero.getString("fileInterface.untitledBibliography"), items);
}
/*
* Copies HTML and text bibliography entries for passed items in given style
*
* Does not check that items are actual references (and not notes or attachments)
*/
function copyItemsToClipboard(items, style) {
// copy to clipboard
var transferable = Components.classes["@mozilla.org/widget/transferable;1"].
createInstance(Components.interfaces.nsITransferable);
var clipboardService = Components.classes["@mozilla.org/widget/clipboard;1"].
getService(Components.interfaces.nsIClipboard);
var csl = Zotero.Cite.getStyle(style);
csl.preprocessItems(items);
// add HTML
var bibliography = csl.createBibliography(items, "HTML");
var str = Components.classes["@mozilla.org/supports-string;1"].
createInstance(Components.interfaces.nsISupportsString);
str.data = bibliography;
transferable.addDataFlavor("text/html");
transferable.setTransferData("text/html", str, bibliography.length*2);
// add text
var bibliography = csl.createBibliography(items, "Text");
var str = Components.classes["@mozilla.org/supports-string;1"].
createInstance(Components.interfaces.nsISupportsString);
str.data = bibliography;
transferable.addDataFlavor("text/unicode");
transferable.setTransferData("text/unicode", str, bibliography.length*2);
clipboardService.setData(transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
}
/*
* Shows bibliography options and creates a bibliography
*/
function _doBibliographyOptions(name, items) {
// make sure at least one item is not a standalone note or attachment
var haveNonNote = false;
for(var i in items) {
var type = Zotero.ItemTypes.getName(items[i].getType());
if(type != "note" && type != "attachment") {
haveNonNote = true;
var haveRegularItem = false;
for each(var item in items) {
if (item.isRegularItem()) {
haveRegularItem = true;
break;
}
}
if(!haveNonNote) {
if (!haveRegularItem) {
window.alert(Zotero.getString("fileInterface.noReferencesError"));
return;
}
@ -310,13 +346,18 @@ var Zotero_File_Interface = new function() {
// generate bibliography
try {
var csl = Zotero.Cite.getStyle(io.style);
csl.preprocessItems(items);
var bibliography = csl.createBibliography(items, format);
if (io.output == 'clipboard') {
this.copyItemsToClipboard(items, io.style);
return;
}
else {
var csl = Zotero.Cite.getStyle(io.style);
csl.preprocessItems(items);
var bibliography = csl.createBibliography(items, format);
}
} catch(e) {
window.alert(Zotero.getString("fileInterface.bibliographyGenerationError"));
throw(e);
return;
}
if(io.output == "print") {
@ -380,31 +421,10 @@ var Zotero_File_Interface = new function() {
fStream.write(bibliography, bibliography.length);
fStream.close();
}
} else if(io.output == "copy-to-clipboard") {
// copy to clipboard
var transferable = Components.classes["@mozilla.org/widget/transferable;1"].
createInstance(Components.interfaces.nsITransferable);
var clipboardService = Components.classes["@mozilla.org/widget/clipboard;1"].
getService(Components.interfaces.nsIClipboard);
// add HTML
var str = Components.classes["@mozilla.org/supports-string;1"].
createInstance(Components.interfaces.nsISupportsString);
str.data = bibliography;
transferable.addDataFlavor("text/html");
transferable.setTransferData("text/html", str, bibliography.length*2);
// add text
var bibliography = csl.createBibliography(items, "Text");
var str = Components.classes["@mozilla.org/supports-string;1"].
createInstance(Components.interfaces.nsISupportsString);
str.data = bibliography;
transferable.addDataFlavor("text/unicode");
transferable.setTransferData("text/unicode", str, bibliography.length*2);
clipboardService.setData(transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
}
}
function _saveBibliography(name, format) {
// savable bibliography, using a file stream
const nsIFilePicker = Components.interfaces.nsIFilePicker;

View File

@ -49,6 +49,7 @@ var ZoteroPane = new function()
this.deleteSelectedItem = deleteSelectedItem;
this.deleteSelectedCollection = deleteSelectedCollection;
this.editSelectedCollection = editSelectedCollection;
this.copySelectedItemsToClipboard = copySelectedItemsToClipboard;
this.clearQuicksearch = clearQuicksearch;
this.handleSearchKeypress = handleSearchKeypress;
this.handleSearchInput = handleSearchInput;
@ -286,6 +287,9 @@ var ZoteroPane = new function()
case 'toggleFullscreen':
ZoteroPane.fullScreen();
break;
case 'copySelectedItemsToClipboard':
ZoteroPane.copySelectedItemsToClipboard();
break;
default:
throw ('Command "' + command + '" not found in ZoteroPane.handleKeyDown()');
}
@ -789,6 +793,34 @@ var ZoteroPane = new function()
}
function copySelectedItemsToClipboard() {
var items = this.getSelectedItems();
if (!items.length) {
return;
}
// Make sure at least one item is not a standalone note or attachment
var haveRegularItem = false;
for each(var item in items) {
if (item.isRegularItem()) {
haveRegularItem = true;
break;
}
}
if (!haveRegularItem) {
window.alert(Zotero.getString("fileInterface.noReferencesError"));
return;
}
// TODO: we only support bibliography output at the moment
var mode = Zotero.Prefs.get("export.quickCopy.mode");
if (mode == 'bibliography') {
var style = Zotero.Prefs.get("export.quickCopy.setting");
Zotero_File_Interface.copyItemsToClipboard(items, style);
}
}
function clearQuicksearch() {
document.getElementById('zotero-tb-search').value = "";
document.getElementById('zotero-tb-search').doCommand('cmd_zotero_search');
@ -904,24 +936,6 @@ var ZoteroPane = new function()
return this.itemsView.getSelectedItems(asIDs);
}
return [];
if (this.itemsView) {
var items = new Array();
var start = new Object();
var end = new Object();
for (var i=0, len=this.itemsView.selection.getRangeCount(); i<len; i++) {
this.itemsView.selection.getRangeAt(i,start,end);
for (var j=start.value; j<=end.value; j++) {
if (asIDs) {
items.push(this.itemsView._getItemAtRow(j).ref.getID());
}
else {
items.push(this.itemsView._getItemAtRow(j).ref);
}
}
}
}
return items;
}

View File

@ -30,6 +30,9 @@ function init()
for (var i=0; i<rows.length; i++) {
rows[i].firstChild.nextSibling.value = Zotero.isMac ? 'Cmd+Shift+' : 'Ctrl+Alt+';
}
populateQuickCopyList();
updateQuickCopyInstructions();
}
@ -61,6 +64,47 @@ function populateOpenURLResolvers() {
}
function populateQuickCopyList() {
var formatMenu = document.getElementById("quickCopy-menu");
var listbox = formatMenu.firstChild;
var styles = Zotero.Cite.getStyles();
var format = Zotero.Prefs.get("export.quickCopy.setting");
// add styles to list
for (i in styles) {
var itemNode = document.createElement("menuitem");
itemNode.setAttribute("value", i);
itemNode.setAttribute("label", styles[i]);
listbox.appendChild(itemNode);
if (i == format) {
formatMenu.selectedItem = itemNode;
}
}
formatMenu.setAttribute('preference', "pref-quickCopy-setting");
}
function updateQuickCopyInstructions() {
if (Zotero.isMac) {
document.getElementById('quickCopy-macWarning').setAttribute('hidden', false);
}
var prefix = Zotero.isMac ? 'Cmd+Shift+' : 'Ctrl+Alt+';
var key = Zotero.Prefs.get('keys.copySelectedItemsToClipboard');
var instr = document.getElementById('quickCopy-instructions');
var str = Zotero.getString('zotero.preferences.export.quickCopy.instructions', prefix + key);
while (instr.hasChildNodes()) {
instr.removeChild(instr.firstChild);
}
instr.appendChild(document.createTextNode(str));
}
function onOpenURLSelected()
{
var openURLMenu = document.getElementById('openURLMenu');

View File

@ -148,6 +148,24 @@ To add a new preference:
</groupbox>
</prefpane>
<prefpane id="zotero-prefpane-export" label="&zotero.preferences.prefpane.export;">
<preferences>
<preference id="pref-quickCopy-setting" name="extensions.zotero.export.quickCopy.setting" type="string"/>
</preferences>
<groupbox>
<caption label="&zotero.preferences.quickCopy.caption;"/>
<label value="&zotero.preferences.quickCopy.outputFormat;" control="quickCopy-menu"/>
<menulist id="quickCopy-menu">
<menupopup/>
</menulist>
<label id="quickCopy-instructions"/>
<label id="quickCopy-macWarning" hidden="true" value="&zotero.preferences.quickCopy.macWarning;"/>
</groupbox>
</prefpane>
<prefpane id="zotero-prefpane-keys" label="&zotero.preferences.prefpane.keys;">
<preferences>
<preference id="pref-keys-openZotero" name="extensions.zotero.keys.openZotero" type="string"/>
@ -157,6 +175,7 @@ To add a new preference:
<preference id="pref-keys-newItem" name="extensions.zotero.keys.newItem" type="string"/>
<preference id="pref-keys-newNote" name="extensions.zotero.keys.newNote" type="string"/>
<preference id="pref-keys-toggleTagSelector" name="extensions.zotero.keys.toggleTagSelector" type="string"/>
<preference id="pref-keys-copySelectedItemsToClipboard" name="extensions.zotero.keys.copySelectedItemsToClipboard" type="string"/>
<preference id="pref-keys-overrideGlobal" name="extensions.zotero.keys.overrideGlobal" type="bool"/>
</preferences>
@ -209,6 +228,13 @@ To add a new preference:
<label/>
<textbox id="textbox-toggleTagSelector" maxlength="1" size="1" preference="pref-keys-toggleTagSelector"/>
</row>
<row>
<label value="&zotero.preferences.keys.copySelectedItemsToClipboard;" control="textbox-copySelectedItemsToClipboard"/>
<label/>
<textbox id="textbox-copySelectedItemsToClipboard" maxlength="1" size="1" preference="pref-keys-copySelectedItemsToClipboard" onchange="updateQuickCopyInstructions()"/>
</row>
</rows>
</grid>

View File

@ -117,10 +117,8 @@ var Zotero = new function(){
// Load in the localization stringbundle for use by getString(name)
var src = 'chrome://zotero/locale/zotero.properties';
var localeService =
Components.classes["@mozilla.org/intl/nslocaleservice;1"]
.getService(Components.interfaces.nsILocaleService);
var appLocale = localeService.getApplicationLocale();
var stringBundleService =
Components.classes["@mozilla.org/intl/stringbundle;1"]
.getService(Components.interfaces.nsIStringBundleService);
@ -630,7 +628,7 @@ Zotero.Keys = new function() {
this.getCommand = getCommand;
_actions = ['library', 'quicksearch', 'newItem', 'newNote', 'toggleTagSelector',
'toggleFullscreen'];
'toggleFullscreen', 'copySelectedItemsToClipboard'];
_keys = {};

View File

@ -23,6 +23,11 @@
<!ENTITY zotero.preferences.openurl.server "Resolver:">
<!ENTITY zotero.preferences.openurl.version "Version:">
<!ENTITY zotero.preferences.prefpane.export "Export">
<!ENTITY zotero.preferences.quickCopy.caption "Quick Copy">
<!ENTITY zotero.preferences.quickCopy.outputFormat "Output Format:">
<!ENTITY zotero.preferences.quickCopy.macWarning "Note that some formatting may be lost on Mac OS X.">
<!ENTITY zotero.preferences.prefpane.keys "Shortcut Keys">
<!ENTITY zotero.preferences.keys.openZotero "Open/Close Zotero Pane">
<!ENTITY zotero.preferences.keys.toggleFullscreen "Toggle Fullscreen Mode">
@ -31,5 +36,6 @@
<!ENTITY zotero.preferences.keys.newItem "Create a new item">
<!ENTITY zotero.preferences.keys.newNote "Create a new note">
<!ENTITY zotero.preferences.keys.toggleTagSelector "Toggle Tag Selector">
<!ENTITY zotero.preferences.keys.copySelectedItemsToClipboard "Copy Selected Items to Clipboard">
<!ENTITY zotero.preferences.keys.overrideGlobal "Try to override conflicting shortcuts">
<!ENTITY zotero.preferences.keys.changesTakeEffect "Changes take effect in new windows only">

View File

@ -267,6 +267,7 @@ zotero.preferences.update.error = Error
zotero.preferences.openurl.resolversFound.zero = %S resolvers found
zotero.preferences.openurl.resolversFound.singular = %S resolver found
zotero.preferences.openurl.resolversFound.plural = %S resolvers found
zotero.preferences.export.quickCopy.instructions = Select one or more references and press the shortcut key (%S) to copy the references to the clipboard.
fileInterface.itemsImported = Importing items...
fileInterface.itemsExported = Exporting items...

View File

@ -3,6 +3,15 @@ prefwindow .chromeclass-toolbar
display: -moz-box !important; /* Ignore toolbar collapse button on OS X */
}
radio[pane]
{
width: 48px;
height: 48px;
-moz-box-align: center;
-moz-box-pack: end;
}
/* General pane icon */
radio[pane=zotero-prefpane-general]
{
-moz-image-region: rect(0px, 32px, 32px, 0px);
@ -14,7 +23,26 @@ radio[pane=zotero-prefpane-general][selected="true"]
-moz-image-region: rect(32px, 32px, 64px, 0px);
}
/* Use the Gear icon until we find a keyboard icon */
/*
* Export pane icon
*/
radio[pane=zotero-prefpane-export]
{
list-style-image: url("chrome://browser/skin/Toolbar.png");
-moz-image-region: rect(0px, 312px, 24px, 288px);
}
radio[pane=zotero-prefpane-export]:hover,
radio[pane=zotero-prefpane-export]:active,
radio[pane=zotero-prefpane-export][selected="true"]
{
-moz-image-region: rect(24px, 312px, 48px, 288px);
}
/*
* Shortcut Keys pane icon
*
* Use the Gear icon until we find a keyboard icon
*/
radio[pane=zotero-prefpane-keys]
{
-moz-image-region: rect(0px, 224px, 32px, 192px);
@ -70,6 +98,26 @@ grid row hbox:first-child
color: red;
}
/* Export pane */
#quickCopy-menu
{
margin-top: .4em;
margin-bottom: .6em;
}
#quickCopy-instructions, #quickCopy-macWarning
{
font-size: .85em;
}
#quickCopy-macWarning
{
margin-top: .5em;
margin-bottom: 1em;
}
/* Shortcut Keys pane */
#zotero-prefpane-keys row
{
@ -89,5 +137,5 @@ grid row hbox:first-child
.statusLine
{
margin: .75em 0;
font-size: 10px;
font-size: .85em;
}

View File

@ -29,6 +29,7 @@ pref("extensions.zotero.keys.quicksearch", 'K');
pref("extensions.zotero.keys.newItem", 'N');
pref("extensions.zotero.keys.newNote", 'O');
pref("extensions.zotero.keys.toggleTagSelector", 'T');
pref("extensions.zotero.keys.copySelectedItemsToClipboard", 'C');
// Export and citation settings
pref("extensions.zotero.export.lastTranslator", '14763d24-8ba0-45df-8f52-b8d1108e7ac9');
@ -36,4 +37,7 @@ pref("extensions.zotero.export.translatorSettings", 'true,false');
pref("extensions.zotero.export.lastStyle", 'http://purl.org/net/xbiblio/csl/styles/apa.csl');
pref("extensions.zotero.export.bibliographySettings", 'save-as-rtf');
pref("extensions.zotero.export.quickCopy.mode", 'bibliography');
pref("extensions.zotero.export.quickCopy.setting", 'http://purl.org/net/xbiblio/csl/styles/apa.csl');
pref("extensions.zotero.annotations.warnOnClose", true);