zotero/chrome/content/zotero/integration/addCitationDialog.js
Simon Kornblith 4556ea3f10 fixes #1668, Items added in multiple mode not recognized unless visible (twice)
fix Accept button issue by using getAttribute() rather than id property, but also scroll to newly inserted citation, since it's probably the desirable behavior
2010-06-18 18:19:52 +00:00

605 lines
18 KiB
JavaScript

/*
***** 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 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
var Zotero_Citation_Dialog = new function () {
var _preserveData = {
"prefix":"value",
"suffix":"value",
"label":"selectedIndex",
"locator":"value",
"suppress-author":"checked"
};
var _itemData = new Object();
var _multipleSourcesOn = false;
var _lastSelected = null;
var _previewShown = false;
var _suppressNextTreeSelect = false;
var _suppressNextListSelect = false;
var _locatorIndexArray = {};
var _locatorNameArray = {};
var _autoRegeneratePref;
var _acceptButton;
var _sortCheckbox;
var _citationList;
var _originalHTML;
var io;
this.load = load;
this.toggleMultipleSources = toggleMultipleSources;
this.toggleEditor = toggleEditor;
this.treeItemSelected = treeItemSelected;
this.listItemSelected = listItemSelected;
this.up = up;
this.down = down;
this.add = add;
this.remove = remove;
this.sortCitation = sortCitation;
this.confirmRegenerate = confirmRegenerate;
this.accept = accept;
this.cancel = cancel;
/*
* initialize add citation dialog
*/
function load() {
document.documentElement.getButton("extra1").label = Zotero.getString("citation.multipleSources");
document.documentElement.getButton("extra2").label = Zotero.getString("citation.showEditor");
io = window.arguments[0].wrappedJSObject;
// find accept button
_acceptButton = document.getElementById("zotero-add-citation-dialog").getButton("accept");
_autoRegeneratePref = Zotero.Prefs.get("integration.autoRegenerate");
_citationList = document.getElementById("citation-list");
// if a style with sortable citations, present checkbox
if(io.sortable) {
_sortCheckbox = document.getElementById("keepSorted");
_sortCheckbox.hidden = false;
_sortCheckbox.checked = !io.citation.properties.unsorted;
}
// load locators
var locators = Zotero.Cite.labels;
var menu = document.getElementById("label");
var popup = document.getElementById("locator-type-popup");
var i = 0;
for(var value in locators) {
var locator = locators[value];
var locatorLabel = locator[0].toUpperCase()+locator.substr(1);
// add to popup
var child = document.createElement("menuitem");
child.setAttribute("value", value);
child.setAttribute("label", locatorLabel);
popup.appendChild(child);
// add to array
_locatorIndexArray[locator] = i;
_locatorNameArray[i] = locator;
i++;
}
menu.selectedIndex = 0;
// load (from selectItemsDialog.js)
doLoad();
// if we already have a citation, load data from it
document.getElementById('editor').format = "RTF";
if(io.citation.citationItems.length) {
if(io.citation.citationItems.length == 1) {
// single citation
_suppressNextTreeSelect = true;
itemsView.selectItem(io.citation.citationItems[0].id); // treeview from selectItemsDialog.js
for(var property in _preserveData) {
if(io.citation.citationItems[0][property]) {
if(property == "label") {
document.getElementById(property)[_preserveData[property]] = _locatorIndexArray[io.citation.citationItems[0][property]];
} else {
document.getElementById(property)[_preserveData[property]] = io.citation.citationItems[0][property];
}
}
}
} else {
// multiple citations
toggleMultipleSources();
for(var i=0; i<io.citation.citationItems.length; i++) {
var item = Zotero.Items.get(io.citation.citationItems[i].id);
if(item) {
_addItem(item);
_itemData[io.citation.citationItems[i].id] = io.citation.citationItems[i];
}
}
}
// show user-editable edited citation
if(io.citation.properties.custom) {
toggleEditor(io.citation.properties.custom);
delete io.citation.properties.custom;
}
_updateAccept();
}
}
/*
* turn on/off multiple sources item list
*/
function toggleMultipleSources() {
_multipleSourcesOn = !_multipleSourcesOn;
if(_multipleSourcesOn) {
var items = itemsView.getSelectedItems(true);
var itemID = (items.length ? items[0] : false);
// var itemDataID = itemID+"::"+0;
document.getElementById("multiple-sources").hidden = undefined;
document.getElementById("zotero-add-citation-dialog").width = "750";
document.documentElement.getButton("extra1").label = Zotero.getString("citation.singleSource");
// move user field content to multiple before adding XXXXX
if (itemID) {
// _itemData[itemDataID] = new Object();
_itemData[itemID] = new Object();
var element;
for (var box in _preserveData) {
element = document.getElementById(box);
// _itemData[itemDataID][box] = element[_preserveData[box]];
_itemData[itemID][box] = element[_preserveData[box]];
}
}
treeItemSelected();
// disable adding info until citation added
_itemSelected(false);
// add current selection
if (itemID) {
this.add();
} else {
_updateAccept();
_updatePreview();
}
} else {
document.getElementById("multiple-sources").hidden = true;
document.getElementById("zotero-add-citation-dialog").width = "600";
document.documentElement.getButton("extra1").label = Zotero.getString("citation.multipleSources");
// enable all fields
for(var i in _preserveData) {
document.getElementById(i).disabled = false;
}
// delete item list
_itemData = new Object();
// delete all items
_clearCitationList();
_updateAccept();
_updatePreview();
}
}
/*
* called when an item in the item selection tree is clicked
*/
function treeItemSelected() {
if(_suppressNextTreeSelect) {
_suppressNextTreeSelect = false;
_updateAccept();
return;
}
var items = itemsView.getSelectedItems(true); // treeview from selectItemsDialog.js
var itemID = (items.length ? items[0] : false);
if(_multipleSourcesOn) {
// if item is also on right side, show info
var hasBeenAdded = itemID && _itemData[itemID] !== undefined;
// disable boxes if item not added; otherwise, enable
_itemSelected(hasBeenAdded ? itemID : false);
// turn off highlight in selected item list
_suppressNextListSelect = true;
document.getElementById("citation-list").selectedIndex = -1;
// disable adding nothing, or things already added
document.getElementById("add").disabled = !itemID || hasBeenAdded;
document.getElementById("remove").disabled = true;
document.getElementById("up").disabled = true;
document.getElementById("down").disabled = true;
} else {
_updateAccept();
_updatePreview();
}
}
/*
* called when an item in the selected items list is clicked
*/
function listItemSelected() {
if(_suppressNextListSelect) {
_suppressNextListSelect = false;
_updateAccept();
return;
}
var selectedListItem = _citationList.getSelectedItem(0);
var selectedListIndex = _citationList.selectedIndex;
var itemID = (selectedListItem ? selectedListItem.value : false);
_itemSelected(itemID);
// turn off highlight in item tree
_suppressNextTreeSelect = true;
document.getElementById("zotero-items-tree").view.selection.clearSelection();
document.getElementById("remove").disabled = !itemID;
document.getElementById("add").disabled = true;
_configListPosition(!itemID, selectedListIndex);
}
function _configListPosition(flag, selectedListIndex) {
if (selectedListIndex > 0) {
document.getElementById("up").disabled = flag;
} else {
document.getElementById("up").disabled = true;
}
if (-1 < selectedListIndex && selectedListIndex < (_citationList.getRowCount() - 1)) {
document.getElementById("down").disabled = flag;
} else {
document.getElementById("down").disabled = true;
}
}
function _move(direction) {
// automatically uncheck sorted checkbox if user is rearranging citation
if(_sortCheckbox && _sortCheckbox.checked) {
_sortCheckbox.checked = false;
sortCitation();
}
var insertBeforeItem;
var selectedListItem = _citationList.getSelectedItem(0);
var selectedListIndex = _citationList.selectedIndex;
var itemID = selectedListItem.value;
if (direction === -1) {
insertBeforeItem = selectedListItem.previousSibling;
} else {
insertBeforeItem = selectedListItem.nextSibling.nextSibling;
}
var listItem = _citationList.removeChild(selectedListItem);
_citationList.insertBefore(listItem, insertBeforeItem);
_citationList.selectedIndex = (selectedListIndex + direction);
_itemSelected(itemID);
_updatePreview();
_configListPosition(false, (selectedListIndex + direction));
}
function up() {
_move(-1);
}
function down() {
_move(1);
}
/*
* Adds a citation to the multipleSources list
*/
function add() {
var item = itemsView.getSelectedItems()[0]; // treeview from selectItemsDialog.js
_itemSelected(item.id);
_citationList.ensureElementIsVisible(_addItem(item));
// don't let someone select it again
document.getElementById("add").disabled = true;
// allow user to press OK
_updateAccept();
_updatePreview();
sortCitation(item.id);
}
/*
* Deletes a citation from the multipleSources list
*/
function remove() {
var selectedListItem = _citationList.getSelectedItem(0);
var selectedListIndex = _citationList.selectedIndex;
var itemID = selectedListItem.value;
// remove from _itemData
delete _itemData[itemID];
_itemData[itemID] = undefined;
_lastSelected = null;
// remove from list
_citationList.removeChild(selectedListItem);
if (selectedListIndex >= _citationList.getRowCount()) {
selectedListIndex = _citationList.getRowCount() - 1;
}
_citationList.selectedIndex = selectedListIndex;
_updateAccept();
_updatePreview();
}
/*
* Sorts the list of citations
*/
function sortCitation(scrollToItemID) {
if(!_sortCheckbox) return;
if(!_sortCheckbox.checked) {
io.citation.properties.unsorted = true;
return;
}
var selectedItemID = (_citationList.selectedItem ? _citationList.selectedItem.value : null);
Zotero.debug("item "+selectedItemID+" selected");
_getCitation();
// delete all existing items from list
_clearCitationList();
// run preview function to re-sort, if it hasn't already been
// run
io.previewFunction();
// add items back to list
var scrollTo = null;
for(var i=0; i<io.citation.sortedItems.length; i++) {
var itemID = io.citation.sortedItems[i][0].id;
var item = Zotero.Items.get(itemID);
var itemNode = _addItem(item);
if(itemID == selectedItemID) _citationList.selectedIndex = i;
if(scrollToItemID && itemID == scrollToItemID) scrollTo = itemNode;
}
if(scrollTo) _citationList.ensureElementIsVisible(scrollTo);
}
/*
* Ask whether to modfiy the preview
*/
function confirmRegenerate(focusShifted) {
if(document.getElementById('editor').value == _originalHTML || _originalHTML === undefined) {
// no changes; just update without asking
_updatePreview();
return;
}
if(_autoRegeneratePref == -1) {
if(focusShifted) { // only ask after onchange event; oninput is too
// frequent for this to be worthwhile
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var saveBehavior = { value: false };
var regenerate = promptService.confirmEx(
this.window,
Zotero.getString('integration.regenerate.title'),
Zotero.getString('integration.regenerate.body'),
promptService.STD_YES_NO_BUTTONS,
null, null, null,
Zotero.getString('integration.regenerate.saveBehavior'),
saveBehavior
);
if(saveBehavior.value) {
_autoRegeneratePref = (regenerate == 0 ? 1 : 0);
Zotero.Prefs.set("integration.autoRegenerate", _autoRegeneratePref);
}
if(regenerate == 0) {
_updatePreview();
}
}
} else if(_autoRegeneratePref == 1) {
_updatePreview();
}
}
/*
* Shows the edit pane
*/
function toggleEditor(text) {
var warning = document.getElementById('zotero-editor-warning');
var editor = document.getElementById('editor');
warning.hidden = _previewShown;
editor.hidden = _previewShown;
_previewShown = !_previewShown;
if(_previewShown) {
document.documentElement.getButton("extra2").label = Zotero.getString("citation.hideEditor");
if(text) {
editor.value = text;
} else {
_updatePreview();
}
} else {
document.documentElement.getButton("extra2").label = Zotero.getString("citation.showEditor");
}
}
/*
* called when accept button is clicked
*/
function accept() {
Zotero.debug("Trying to accept");
_getCitation();
Zotero.debug("got citation");
var isCustom = _previewShown && io.citation.citationItems.length // if a citation is selected
&& document.getElementById('editor').value != _originalHTML // and citation has been edited
if(isCustom) {
var citation = document.getElementById('editor').value;
} else {
var citation = (io.citation.citationItems.length ? io.previewFunction() : "");
}
Zotero.debug("verified not custom");
if(Zotero.Utilities.prototype.trim(citation) == "") {
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var insert = promptService.confirm(window,
Zotero.getString("integration.emptyCitationWarning.title"),
Zotero.getString("integration.emptyCitationWarning.body"));
if(!insert) return false;
}
Zotero.debug("verified not empty");
if(isCustom) io.citation.properties.custom = citation;
return true;
}
/*
* called when cancel button is clicked
*/
function cancel() {
io.citation.citationItems = new Array();
}
/*
* Updates the contents of the preview pane
*/
function _updatePreview() {
if(_previewShown) {
var editor = document.getElementById('editor');
_getCitation();
editor.readonly = !io.citation.citationItems.length;
editor.value = (io.citation.citationItems.length ? io.previewFunction() : "");
_originalHTML = editor.value;
}
}
/*
* Controls whether the accept (OK) button should be enabled
*/
function _updateAccept(status) {
if(_multipleSourcesOn) {
_acceptButton.disabled = !_citationList.getRowCount();
} else {
_acceptButton.disabled = !itemsView.getSelectedItems().length; // treeview from selectItemsDialog.js
}
}
/*
* called when an item is selected; if itemID is false, disables fields; if
* itemID is undefined, only updates _itemData array
*/
function _itemSelected(itemID) {
if(_lastSelected && !_itemData[_lastSelected]) {
_itemData[_lastSelected] = new Object();
}
for(var box in _preserveData) {
var domBox = document.getElementById(box);
var property = _preserveData[box];
// save property
if(_lastSelected) {
if(property == "label") {
_itemData[_lastSelected][box] = _locatorNameArray[domBox.selectedIndex];
} else {
_itemData[_lastSelected][box] = domBox[property];
}
}
// restore previous property
if(itemID) {
domBox.disabled = false;
if(_itemData[itemID] && _itemData[itemID][box] !== undefined) {
if(property == "label") {
domBox[property] = _locatorIndexArray[_itemData[itemID][box]];
} else {
domBox[property] = _itemData[itemID][box];
}
}
} else if(itemID !== undefined) {
domBox.disabled = true;
domBox[property] = "";
}
}
if(itemID !== undefined) _lastSelected = itemID;
}
/*
* updates io.citation to reflect selected items
*/
function _getCitation() {
io.citation.citationItems = new Array();
// use to map selectedIndexes back to page/paragraph/line
var locatorTypeElements = document.getElementById("label").getElementsByTagName("menuitem");
if(_multipleSourcesOn) {
_itemSelected(); // store locator info
var listLength = _citationList.getRowCount();
var citationItems = new Array();
if(listLength) {
// generate citationItems
for(var i=0; i<listLength; i++) {
var itemID = _citationList.getItemAtIndex(i).getAttribute("value");
var citationItem = _itemData[itemID];
citationItem.id = itemID;
io.citation.citationItems.push(citationItem);
}
}
} else {
var items = itemsView.getSelectedItems(true); // treeview from selectItemsDialog.js
if(items.length) {
var citationItem = {};
citationItem.id = items[0];
for(var property in _preserveData) {
if(property == "label") {
citationItem[property] = _locatorNameArray[document.getElementById(property).selectedIndex];
} else {
citationItem[property] = document.getElementById(property)[_preserveData[property]];
}
}
if(citationItem["locator"] == "") {
citationItem["locator"] = citationItem["label"] = undefined;
}
io.citation.citationItems = [citationItem];
} else {
io.citation.citationItems = [];
}
}
}
/*
* Add an item to the item list (multiple sources only)
*/
function _addItem(item) {
var itemNode = document.createElement("listitem");
itemNode.setAttribute("value", item.id);
itemNode.setAttribute("label", item.getField("title"));
itemNode.setAttribute("class", "listitem-iconic");
itemNode.setAttribute("image", item.getImageSrc());
_citationList.appendChild(itemNode);
return itemNode;
}
/*
* Removes all items from the multiple sources list
*/
function _clearCitationList() {
while(_citationList.firstChild) _citationList.removeChild(_citationList.firstChild);
}
}