
When an item has a URL, turn Locate button into a menu and allow lookup via Wayback Machine Support for additional user-configurable providers is forthcoming
2146 lines
62 KiB
XML
2146 lines
62 KiB
XML
<?xml version="1.0"?>
|
|
<!--
|
|
***** BEGIN LICENSE BLOCK *****
|
|
|
|
Copyright (c) 2006 Center for History and New Media
|
|
George Mason University, Fairfax, Virginia, USA
|
|
http://chnm.gmu.edu
|
|
|
|
Licensed under the Educational Community License, Version 1.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.opensource.org/licenses/ecl1.php
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
***** END LICENSE BLOCK *****
|
|
-->
|
|
|
|
<!DOCTYPE bindings SYSTEM "chrome://zotero/locale/zotero.dtd">
|
|
<!-- <!DOCTYPE bindings SYSTEM "chrome://zotero/locale/itembox.dtd"> -->
|
|
|
|
<bindings xmlns="http://www.mozilla.org/xbl"
|
|
xmlns:xbl="http://www.mozilla.org/xbl"
|
|
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
|
|
<binding id="item-box">
|
|
<resources>
|
|
<stylesheet src="chrome://zotero/skin/bindings/itembox.css"/>
|
|
<stylesheet src="chrome://zotero-platform/content/itembox.css"/>
|
|
</resources>
|
|
|
|
<implementation>
|
|
<!--
|
|
Public properties
|
|
-->
|
|
<field name="clickable">false</field>
|
|
<field name="editable">false</field>
|
|
<field name="saveOnEdit">false</field>
|
|
<field name="displayGoButtons">false</field>
|
|
<field name="showTypeMenu">false</field>
|
|
<field name="hideEmptyFields">false</field>
|
|
<field name="clickByRow">false</field> <!-- Click entire row rather than just field value -->
|
|
<field name="clickByItem">false</field>
|
|
|
|
<field name="clickHandler"/>
|
|
<field name="blurHandler"/>
|
|
|
|
<!-- Modes are predefined settings groups for particular tasks -->
|
|
<field name="_mode">"view"</field>
|
|
<property name="mode" onget="return this._mode;">
|
|
<setter>
|
|
<![CDATA[
|
|
this.clickable = false;
|
|
this.editable = false;
|
|
this.saveOnEdit = false;
|
|
this.displayGoButtons = false;
|
|
this.showTypeMenu = false;
|
|
this.hideEmptyFields = false;
|
|
this.clickByRow = false;
|
|
this.clickByItem = false;
|
|
|
|
switch (val) {
|
|
case 'view':
|
|
break;
|
|
|
|
case 'edit':
|
|
this.clickable = true;
|
|
this.editable = true;
|
|
this.saveOnEdit = true
|
|
this.displayGoButtons = true;
|
|
this.showTypeMenu = true;
|
|
this.clickHandler = this.showEditor;
|
|
this.blurHandler = this.hideEditor;
|
|
break;
|
|
|
|
case 'merge':
|
|
//this.hideEmptyFields = true;
|
|
this.clickByItem = true;
|
|
break;
|
|
|
|
case 'mergeedit':
|
|
this.clickable = true;
|
|
this.editable = true;
|
|
this.saveOnEdit = false;
|
|
this.displayGoButtons = false;
|
|
this.showTypeMenu = true;
|
|
this.clickHandler = this.showEditor;
|
|
this.blurHandler = this.hideEditor;
|
|
break;
|
|
|
|
default:
|
|
throw ("Invalid mode '" + val + "' in itembox.xml");
|
|
}
|
|
|
|
this._mode = val;
|
|
document.getAnonymousNodes(this)[0].setAttribute('mode', val);
|
|
]]>
|
|
</setter>
|
|
</property>
|
|
|
|
<field name="_item"/>
|
|
<property name="item"
|
|
onget="return this._item;"
|
|
onset="this._item = val; this.refresh();">
|
|
</property>
|
|
|
|
<!-- .ref is an alias for .item -->
|
|
<property name="ref"
|
|
onget="return this._item;"
|
|
onset="this._item = val; this.refresh();">
|
|
</property>
|
|
|
|
|
|
<!--
|
|
An array of field names that should be shown
|
|
even if they're empty and hideEmptyFields is set
|
|
-->
|
|
<field name="_visibleFields">[]</field>
|
|
<property name="visibleFields">
|
|
<setter>
|
|
<![CDATA[
|
|
if (val.constructor.name != 'Array') {
|
|
throw ('visibleFields must be an array in <itembox>.visibleFields');
|
|
}
|
|
|
|
this._visibleFields = val;
|
|
]]>
|
|
</setter>
|
|
</property>
|
|
|
|
<!--
|
|
An array of field names that should be clickable
|
|
even if this.clickable is false
|
|
-->
|
|
<field name="_clickableFields">[]</field>
|
|
<property name="clickableFields">
|
|
<setter>
|
|
<![CDATA[
|
|
if (val.constructor.name != 'Array') {
|
|
throw ('clickableFields must be an array in <itembox>.clickableFields');
|
|
}
|
|
|
|
this._clickableFields = val;
|
|
]]>
|
|
</setter>
|
|
</property>
|
|
|
|
<!--
|
|
An array of field names that should be editable
|
|
even if this.editable is false
|
|
-->
|
|
<field name="_editableFields">[]</field>
|
|
<property name="editableFields">
|
|
<setter>
|
|
<![CDATA[
|
|
if (val.constructor.name != 'Array') {
|
|
throw ('editableFields must be an array in <itembox>.editableFields');
|
|
}
|
|
|
|
this._editableFields = val;
|
|
]]>
|
|
</setter>
|
|
</property>
|
|
|
|
|
|
<!--
|
|
An array of field names in the order they should appear
|
|
in the list; empty spaces can be created with null
|
|
-->
|
|
<field name="_fieldOrder">[]</field>
|
|
<property name="fieldOrder">
|
|
<setter>
|
|
<![CDATA[
|
|
if (val.constructor.name != 'Array') {
|
|
throw ('fieldOrder must be an array in <itembox>.fieldOrder');
|
|
}
|
|
|
|
this._fieldOrder = val;
|
|
]]>
|
|
</setter>
|
|
</property>
|
|
|
|
|
|
<!-- Private properties -->
|
|
<property name="_dynamicFields" onget="return this._id('dynamic-fields')"/>
|
|
<property name="_itemTypeMenu" onget="return this._id('item-type-menu')"/>
|
|
<property name="_creatorTypeMenu" onget="return this._id('creator-type-menu')"/>
|
|
|
|
<field name="_selectField"/>
|
|
<field name="_beforeRow"/>
|
|
<field name="_activeScrollbox"/>
|
|
<field name="_addCreatorRow"/>
|
|
<field name="_creatorCount"/>
|
|
|
|
<field name="_lastTabIndex"/>
|
|
<field name="_tabDirection"/>
|
|
<field name="_tabIndexMinCreators" readonly="true">10</field>
|
|
<field name="_tabIndexMaxCreators" readonly="true">0</field>
|
|
<field name="_tabIndexMinFields" readonly="true">1000</field>
|
|
<field name="_tabIndexMaxInfoFields" readonly="true">0</field>
|
|
<field name="_tabIndexMaxTagsFields" readonly="true">0</field>
|
|
|
|
<property name="_defaultFirstName"
|
|
onget="return '(' + Zotero.getString('pane.item.defaultFirstName') + ')'"/>
|
|
<property name="_defaultLastName"
|
|
onget="return '(' + Zotero.getString('pane.item.defaultLastName') + ')'"/>
|
|
<property name="_defaultFullName"
|
|
onget="return '(' + Zotero.getString('pane.item.defaultFullName') + ')'"/>
|
|
|
|
<method name="refresh">
|
|
<body>
|
|
<![CDATA[
|
|
Zotero.debug('Refreshing item box');
|
|
|
|
if (this.clickByItem) {
|
|
var itemBox = document.getAnonymousNodes(this)[0];
|
|
itemBox.setAttribute('onclick',
|
|
'document.getBindingParent(this).clickHandler(this)');
|
|
}
|
|
|
|
if (this.displayGoButtons) {
|
|
// Enable/disable "View =>" button
|
|
testView: try {
|
|
var viewButton = document.getElementById('view-button');
|
|
|
|
viewButton.removeAttribute('viewSnapshot');
|
|
viewButton.removeAttribute('viewURL');
|
|
viewButton.setAttribute('label',
|
|
Zotero.getString('pane.item.goToURL.online.label'));
|
|
viewButton.setAttribute('tooltiptext',
|
|
Zotero.getString('pane.item.goToURL.online.tooltip'));
|
|
|
|
var spec = false, validURI = false;
|
|
|
|
var uri = Components.classes["@mozilla.org/network/standard-url;1"].
|
|
createInstance(Components.interfaces.nsIURI);
|
|
|
|
// First try to find a snapshot matching the item's URL field
|
|
var snapID = this.item.getBestSnapshot();
|
|
if (snapID) {
|
|
spec = Zotero.Items.get(snapID).getLocalFileURL();
|
|
uri.spec = spec;
|
|
if (!uri.scheme || uri.scheme != 'file') {
|
|
snapID = false;
|
|
spec = false;
|
|
}
|
|
}
|
|
|
|
// If that fails, try the URL field itself
|
|
if (!spec) {
|
|
spec = this.item.getField('url');
|
|
uri.spec = spec;
|
|
if (!(uri.scheme && (uri.host || uri.scheme == 'file'))) {
|
|
spec = false;
|
|
}
|
|
}
|
|
|
|
if (!spec) {
|
|
break testView;
|
|
}
|
|
|
|
validURI = true;
|
|
|
|
if (snapID) {
|
|
viewButton.setAttribute('label',
|
|
Zotero.getString('pane.item.goToURL.snapshot.label'));
|
|
viewButton.setAttribute('tooltiptext',
|
|
Zotero.getString('pane.item.goToURL.snapshot.tooltip'));
|
|
viewButton.setAttribute('viewSnapshot', snapID);
|
|
}
|
|
else {
|
|
viewButton.setAttribute('viewURL', spec);
|
|
}
|
|
}
|
|
catch (e) {
|
|
Zotero.debug(e);
|
|
}
|
|
viewButton.setAttribute('disabled', !validURI);
|
|
|
|
// Enable/disable "Locate =>" button
|
|
switch (this.item.itemTypeID) {
|
|
// DEBUG: handle descendents of these types as well?
|
|
case Zotero.ItemTypes.getID('book'):
|
|
case Zotero.ItemTypes.getID('bookSection'):
|
|
case Zotero.ItemTypes.getID('journalArticle'):
|
|
case Zotero.ItemTypes.getID('thesis'):
|
|
var openURL = true;
|
|
break;
|
|
|
|
default:
|
|
var openURL = false;
|
|
}
|
|
|
|
var locateButton = document.getElementById('locate-button');
|
|
|
|
// TODO: move Locate service logic to separate interface
|
|
var wayback = this._itemHasURL();
|
|
if (wayback) {
|
|
locateButton.setAttribute('type', 'menu');
|
|
locateButton.setAttribute('disabled', false);
|
|
document.getElementById('locate-service-openurl').disabled = !openURL;
|
|
}
|
|
else {
|
|
locateButton.removeAttribute('type');
|
|
locateButton.disabled = !openURL;
|
|
}
|
|
|
|
this._id('go-buttons').hidden = false;
|
|
}
|
|
else {
|
|
this._id('go-buttons').hidden = true;
|
|
}
|
|
|
|
// Item type menu
|
|
if (this.showTypeMenu) {
|
|
// Build item type menu if it hasn't been built yet
|
|
if (!this._itemTypeMenu.firstChild.hasChildNodes()) {
|
|
var itemTypes = Zotero.ItemTypes.getTypes();
|
|
for (var i=0; i<itemTypes.length; i++) {
|
|
var name = itemTypes[i].name;
|
|
if (name != 'attachment' && name != 'note') {
|
|
this._itemTypeMenu.appendItem(Zotero.getString("itemTypes." + name), itemTypes[i].id);
|
|
}
|
|
}
|
|
}
|
|
|
|
var listitems = this._itemTypeMenu.firstChild.childNodes;
|
|
for (var i=0, len=listitems.length; i < len; i++) {
|
|
if (listitems[i].getAttribute('value') == this.item.itemTypeID) {
|
|
this._itemTypeMenu.selectedIndex = i;
|
|
}
|
|
}
|
|
|
|
this._itemTypeMenu.parentNode.hidden = false;
|
|
}
|
|
else {
|
|
this._itemTypeMenu.parentNode.hidden = true;
|
|
}
|
|
|
|
|
|
//
|
|
// Clear and rebuild metadata fields
|
|
//
|
|
while (this._dynamicFields.hasChildNodes()) {
|
|
this._dynamicFields.removeChild(this._dynamicFields.firstChild);
|
|
}
|
|
|
|
var fieldNames = [];
|
|
|
|
// Manual field order
|
|
if (this._fieldOrder.length) {
|
|
for each(var field in this._fieldOrder) {
|
|
fieldNames.push(field);
|
|
}
|
|
}
|
|
// Get field order from database
|
|
else {
|
|
if (!this.showTypeMenu) {
|
|
fieldNames.push("itemType");
|
|
}
|
|
|
|
var fields = Zotero.ItemFields.getItemTypeFields(this.item.getField("itemTypeID"));
|
|
|
|
for (var i=0; i<fields.length; i++) {
|
|
fieldNames.push(Zotero.ItemFields.getName(fields[i]));
|
|
}
|
|
|
|
fieldNames.push("dateAdded", "dateModified");
|
|
}
|
|
|
|
for (var i=0; i<fieldNames.length; i++) {
|
|
var fieldName = fieldNames[i];
|
|
var val = '';
|
|
|
|
if (fieldName) {
|
|
var fieldID = Zotero.ItemFields.getID(fieldName);
|
|
if (fieldID && !Zotero.ItemFields.isValidForType(fieldID, this.item.itemTypeID)) {
|
|
fieldName = null;
|
|
}
|
|
}
|
|
|
|
if (fieldName) {
|
|
// createValueElement() adds the itemTypeID as an attribute
|
|
// and converts it to a localized string for display
|
|
if (fieldName == 'itemType') {
|
|
val = this.item.getField('itemTypeID');
|
|
}
|
|
else {
|
|
val = this.item.getField(fieldName);
|
|
}
|
|
|
|
var fieldIsClickable = this._fieldIsClickable(fieldName);
|
|
|
|
if (!val && this.hideEmptyFields
|
|
&& this._visibleFields.indexOf(fieldName) == -1) {
|
|
continue;
|
|
}
|
|
|
|
// Start tabindex at 1000 after creators
|
|
var tabindex = fieldIsClickable
|
|
? (i>0 ? this._tabIndexMinFields + i : 1) : 0;
|
|
this._tabIndexMaxInfoFields = Math.max(this._tabIndexMaxInfoFields, tabindex);
|
|
|
|
if (fieldIsClickable &&
|
|
!this.item.isPrimaryField(fieldName) &&
|
|
Zotero.ItemFields.isFieldOfBase(Zotero.ItemFields.getID(fieldName), 'date')) {
|
|
this.addDateRow(fieldNames[i], this.item.getField(fieldName, true), tabindex);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
var valueElement = this.createValueElement(
|
|
val, fieldName, tabindex
|
|
);
|
|
|
|
var label = document.createElement("label");
|
|
label.setAttribute('fieldname', fieldName);
|
|
|
|
var prefix = '';
|
|
// Add '(...)' before 'Abstract:' for collapsed abstracts
|
|
if (fieldName == 'abstractNote') {
|
|
if (val && !Zotero.Prefs.get('lastAbstractExpand')) {
|
|
prefix = '(...) ';
|
|
}
|
|
}
|
|
|
|
if (fieldName) {
|
|
label.setAttribute("value", prefix +
|
|
Zotero.ItemFields.getLocalizedString(this.item.itemTypeID, fieldName) + ":");
|
|
}
|
|
|
|
if (fieldName == 'url' && val) {
|
|
label.setAttribute("isButton", true);
|
|
// TODO: make getFieldValue non-private and use below instead
|
|
label.setAttribute("onclick", "ZoteroPane.loadURI(this.nextSibling.firstChild ? this.nextSibling.firstChild.nodeValue : this.nextSibling.value, event)");
|
|
label.setAttribute("tooltiptext", Zotero.getString('pane.item.goToURL.online.tooltip'));
|
|
}
|
|
else if (fieldName == 'abstractNote') {
|
|
label.setAttribute("onclick",
|
|
"if (this.nextSibling.inputField) { this.nextSibling.inputField.blur(); } "
|
|
+ "else { document.getBindingParent(this).toggleAbstractExpand(this); }");
|
|
}
|
|
else {
|
|
label.setAttribute("onclick",
|
|
"if (this.nextSibling.inputField) { this.nextSibling.inputField.blur(); }");
|
|
}
|
|
|
|
this.addDynamicRow(label, valueElement);
|
|
|
|
if (fieldName && this._selectField == fieldName) {
|
|
this.showEditor(valueElement);
|
|
}
|
|
}
|
|
this._selectField = false;
|
|
|
|
//
|
|
// Creators
|
|
//
|
|
|
|
// Creator type menu
|
|
if (this.editable) {
|
|
while (this._creatorTypeMenu.hasChildNodes()) {
|
|
this._creatorTypeMenu.removeChild(this._creatorTypeMenu.firstChild);
|
|
}
|
|
|
|
var creatorTypes = Zotero.CreatorTypes.getTypesForItemType(this.item.itemTypeID);
|
|
var localized = {};
|
|
for (var i=0; i<creatorTypes.length; i++) {
|
|
localized[creatorTypes[i]['name']]
|
|
= Zotero.getString('creatorTypes.' + creatorTypes[i]['name']);
|
|
}
|
|
|
|
for (var i in localized) {
|
|
var menuitem = document.createElement("menuitem");
|
|
menuitem.setAttribute("label", localized[i]);
|
|
menuitem.setAttribute("typeid", Zotero.CreatorTypes.getID(i));
|
|
this._creatorTypeMenu.appendChild(menuitem);
|
|
}
|
|
}
|
|
|
|
// Creator rows
|
|
|
|
// Place, in order of preference, after title, after type,
|
|
// or at beginning
|
|
var field = this._dynamicFields.getElementsByAttribute('fieldname', 'title').item(0);
|
|
if (!field) {
|
|
var field = this._dynamicFields.getElementsByAttribute('fieldname', 'itemType').item(0);
|
|
}
|
|
if (field) {
|
|
this._beforeRow = field.parentNode.nextSibling;
|
|
}
|
|
else {
|
|
this._beforeRow = this._dynamicFields.firstChild;
|
|
}
|
|
|
|
this._creatorCount = 0;
|
|
if (this.item.numCreators() > 0) {
|
|
for (var i = 0, len=this.item.numCreators(); i<len; i++) {
|
|
this.addCreatorRow(this.item.getCreator(i).ref,
|
|
this.item.getCreator(i).creatorTypeID);
|
|
}
|
|
|
|
if (this._addCreatorRow) {
|
|
this.addCreatorRow(false, false, true);
|
|
this._addCreatorRow = false;
|
|
}
|
|
}
|
|
else if (this.editable) {
|
|
// Add default row
|
|
this.addCreatorRow(false, false, true, true);
|
|
}
|
|
|
|
|
|
// Move to next or previous field if (shift-)tab was pressed
|
|
if (this._lastTabIndex && this._tabDirection)
|
|
{
|
|
this._focusNextField('info', this._dynamicFields, this._lastTabIndex, this._tabDirection == -1);
|
|
}
|
|
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="_itemHasURL">
|
|
<body>
|
|
<![CDATA[
|
|
var url = this.item.getField('url');
|
|
return url && !url.match(/^file:|^zotero:/);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="addDynamicRow">
|
|
<parameter name="label"/>
|
|
<parameter name="value"/>
|
|
<parameter name="beforeElement"/>
|
|
<body>
|
|
<![CDATA[
|
|
var row = document.createElement("row");
|
|
|
|
// Add click event to row
|
|
if (this._rowIsClickable(value.getAttribute('fieldname'))) {
|
|
row.className = 'zotero-clicky';
|
|
row.addEventListener('click', function (event) {
|
|
document.getBindingParent(this).clickHandler(this);
|
|
}, false);
|
|
}
|
|
|
|
row.appendChild(label);
|
|
row.appendChild(value);
|
|
if (beforeElement) {
|
|
this._dynamicFields.insertBefore(row, this._beforeRow);
|
|
}
|
|
else {
|
|
this._dynamicFields.appendChild(row);
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="addCreatorRow">
|
|
<parameter name="creator"/>
|
|
<parameter name="creatorTypeID"/>
|
|
<parameter name="unsaved"/>
|
|
<parameter name="defaultRow"/>
|
|
<body>
|
|
<![CDATA[
|
|
// getCreatorFields(), switchCreatorMode() and handleCreatorAutoCompleteSelect()
|
|
// may need need to be adjusted if this DOM structure changes
|
|
|
|
if (!creator) {
|
|
creator = {
|
|
firstName: '',
|
|
lastName: '',
|
|
fieldMode: Zotero.Prefs.get('lastCreatorFieldMode')
|
|
};
|
|
}
|
|
|
|
// Disable the "+" button on previous rows
|
|
var elems = this._dynamicFields.getElementsByAttribute('value', '+');
|
|
if (elems.length) {
|
|
this.disableButton(elems[elems.length-1]);
|
|
}
|
|
|
|
if (creator.fieldMode == 1) {
|
|
var firstName = '';
|
|
var lastName = creator.lastName ? creator.lastName : this._defaultFullName;
|
|
}
|
|
else {
|
|
var firstName = creator.firstName ? creator.firstName : this._defaultFirstName;
|
|
var lastName = creator.lastName ? creator.lastName : this._defaultLastName;
|
|
}
|
|
|
|
// Use the first entry in the drop-down for the default type if none specified
|
|
var typeID = creatorTypeID ?
|
|
creatorTypeID : this._creatorTypeMenu.childNodes[0].getAttribute('typeid');
|
|
|
|
var typeBox = document.createElement("hbox");
|
|
typeBox.setAttribute("typeid", typeID);
|
|
typeBox.setAttribute("popup", "creator-type-menu");
|
|
typeBox.setAttribute("fieldname", 'creator-' + this._creatorCount + '-typeID');
|
|
typeBox.className = 'creator-type-label zotero-clicky';
|
|
|
|
var img = document.createElement('image');
|
|
img.setAttribute('src', 'chrome://zotero/skin/arrow-down.gif');
|
|
typeBox.appendChild(img);
|
|
|
|
var label = document.createElement("label");
|
|
label.setAttribute('value',
|
|
Zotero.getString('creatorTypes.'+Zotero.CreatorTypes.getName(typeID)) + ":")
|
|
typeBox.appendChild(label);
|
|
|
|
var hbox = document.createElement("hbox");
|
|
|
|
// Name
|
|
var firstlast = document.createElement("hbox");
|
|
firstlast.className = 'creator-name-box';
|
|
firstlast.setAttribute("flex","1");
|
|
var tabindex = this._tabIndexMinCreators + (this._creatorCount * 2);
|
|
var fieldName = 'creator-' + this._creatorCount + '-lastName';
|
|
var lastNameLabel = firstlast.appendChild(
|
|
this.createValueElement(
|
|
lastName,
|
|
fieldName,
|
|
tabindex
|
|
)
|
|
);
|
|
|
|
// Comma
|
|
var comma = document.createElement('label');
|
|
comma.setAttribute('value', ',');
|
|
comma.className = 'comma';
|
|
firstlast.appendChild(comma);
|
|
|
|
var fieldName = 'creator-' + this._creatorCount + '-firstName';
|
|
firstlast.appendChild(
|
|
this.createValueElement(
|
|
firstName,
|
|
fieldName,
|
|
tabindex + 1
|
|
)
|
|
);
|
|
if (creator.fieldMode) {
|
|
firstlast.lastChild.setAttribute('hidden', true);
|
|
}
|
|
this._tabIndexMaxCreators = Math.max(this._tabIndexMaxCreators, tabindex);
|
|
|
|
hbox.appendChild(firstlast);
|
|
|
|
// Single/double field toggle
|
|
var toggleButton = document.createElement('toolbarbutton');
|
|
toggleButton.setAttribute('fieldname',
|
|
'creator-' + this._creatorCount + '-fieldMode');
|
|
toggleButton.className = 'zotero-clicky';
|
|
hbox.appendChild(toggleButton);
|
|
|
|
// Minus (-) button
|
|
var removeButton = document.createElement('label');
|
|
removeButton.setAttribute("value","-");
|
|
// If default first row, don't let user remove it
|
|
if (defaultRow) {
|
|
this.disableButton(removeButton);
|
|
}
|
|
else {
|
|
removeButton.setAttribute("class","zotero-clicky");
|
|
removeButton.setAttribute("onclick",
|
|
"document.getBindingParent(this).removeCreator("
|
|
+ this._creatorCount
|
|
+ ", this.parentNode.parentNode)");
|
|
}
|
|
hbox.appendChild(removeButton);
|
|
|
|
// Plus (+) button
|
|
var addButton = document.createElement('label');
|
|
addButton.setAttribute("value","+");
|
|
addButton.setAttribute("class", "zotero-clicky");
|
|
// If row isn't saved, don't let user add more
|
|
if (unsaved) {
|
|
this.disableButton(addButton);
|
|
}
|
|
else {
|
|
this._enablePlusButton(addButton, typeID, creator.fieldMode);
|
|
}
|
|
hbox.appendChild(addButton);
|
|
|
|
this._creatorCount++;
|
|
|
|
if (!this.editable) {
|
|
toggleButton.hidden = true;
|
|
removeButton.hidden = true;
|
|
addButton.hidden = true;
|
|
}
|
|
|
|
this.addDynamicRow(typeBox, hbox, true);
|
|
|
|
// Set single/double field toggle mode
|
|
if (creator.fieldMode) {
|
|
this.switchCreatorMode(hbox.parentNode, 1, true);
|
|
}
|
|
else {
|
|
this.switchCreatorMode(hbox.parentNode, 0, true);
|
|
}
|
|
|
|
// Focus new rows
|
|
if (unsaved && !defaultRow){
|
|
lastNameLabel.click();
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="addDateRow">
|
|
<parameter name="field"/>
|
|
<parameter name="value"/>
|
|
<parameter name="tabindex"/>
|
|
<body>
|
|
<![CDATA[
|
|
var label = document.createElement("label");
|
|
label.setAttribute("value", Zotero.getString("itemFields." + field) + ':');
|
|
label.setAttribute("fieldname", field);
|
|
label.setAttribute("onclick", "this.nextSibling.firstChild.blur()");
|
|
|
|
var hbox = document.createElement("hbox");
|
|
var elem = this.createValueElement(
|
|
Zotero.Date.multipartToStr(value),
|
|
field,
|
|
tabindex
|
|
);
|
|
|
|
// y-m-d status indicator
|
|
var datebox = document.createElement('hbox');
|
|
datebox.className = 'zotero-date-field-status';
|
|
var year = document.createElement('label');
|
|
var month = document.createElement('label');
|
|
var day = document.createElement('label');
|
|
year.setAttribute('value', Zotero.getString('date.abbreviation.year'));
|
|
month.setAttribute('value', Zotero.getString('date.abbreviation.month'));
|
|
day.setAttribute('value', Zotero.getString('date.abbreviation.day'));
|
|
|
|
// Display the date parts we have and hide the others
|
|
var sqldate = Zotero.Date.multipartToSQL(value);
|
|
year.setAttribute('hidden', !Zotero.Date.sqlHasYear(sqldate));
|
|
month.setAttribute('hidden', !Zotero.Date.sqlHasMonth(sqldate));
|
|
day.setAttribute('hidden', !Zotero.Date.sqlHasDay(sqldate));
|
|
|
|
datebox.appendChild(year);
|
|
datebox.appendChild(month);
|
|
datebox.appendChild(day);
|
|
|
|
var hbox = document.createElement('hbox');
|
|
hbox.setAttribute('flex', 1);
|
|
hbox.appendChild(elem);
|
|
hbox.appendChild(datebox);
|
|
|
|
this.addDynamicRow(label, hbox);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="switchCreatorMode">
|
|
<parameter name="row"/>
|
|
<parameter name="fieldMode"/>
|
|
<parameter name="initial"/>
|
|
<body>
|
|
<![CDATA[
|
|
// Change if button position changes
|
|
// row->hbox->label->label->toolbarbutton
|
|
var button = row.lastChild.lastChild.previousSibling.previousSibling;
|
|
var hbox = button.previousSibling;
|
|
var lastName = hbox.firstChild;
|
|
var comma = hbox.firstChild.nextSibling;
|
|
var firstName = hbox.lastChild;
|
|
|
|
// Switch to single-field mode
|
|
if (fieldMode == 1) {
|
|
button.setAttribute('image', 'chrome://zotero/skin/textfield-dual.png');
|
|
button.setAttribute('tooltiptext', Zotero.getString('pane.item.switchFieldMode.two'));
|
|
lastName.setAttribute('fieldMode', '1');
|
|
button.setAttribute('onclick', "document.getBindingParent(this).switchCreatorMode(Zotero.getAncestorByTagName(this, 'row'), 0)");
|
|
lastName.setAttribute('flex', '1');
|
|
|
|
// Remove firstname field from tabindex
|
|
var tab = parseInt(firstName.getAttribute('ztabindex'));
|
|
firstName.setAttribute('ztabindex', -1);
|
|
if (this._tabIndexMaxCreators == tab) {
|
|
this._tabIndexMaxCreators--;
|
|
}
|
|
|
|
// Hide first name field and prepend to last name field
|
|
firstName.setAttribute('hidden', true);
|
|
comma.setAttribute('hidden', true);
|
|
|
|
if (!initial) {
|
|
var first = this._getFieldValue(firstName);
|
|
if (first && first != this._defaultFirstName) {
|
|
var last = this._getFieldValue(lastName);
|
|
this._setFieldValue(lastName, first + ' ' + last);
|
|
}
|
|
}
|
|
|
|
if (this._getFieldValue(lastName) == this._defaultLastName) {
|
|
this._setFieldValue(lastName, this._defaultFullName);
|
|
}
|
|
}
|
|
// Switch to two-field mode
|
|
else {
|
|
button.setAttribute('image', 'chrome://zotero/skin/textfield-single.png');
|
|
button.setAttribute('tooltiptext', Zotero.getString('pane.item.switchFieldMode.one'));
|
|
lastName.setAttribute('fieldMode', '0');
|
|
button.setAttribute('onclick', "document.getBindingParent(this).switchCreatorMode(Zotero.getAncestorByTagName(this, 'row'), 1)");
|
|
lastName.setAttribute('flex', '0');
|
|
|
|
// Add firstname field to tabindex
|
|
var tab = parseInt(lastName.getAttribute('ztabindex'));
|
|
firstName.setAttribute('ztabindex', tab + 1);
|
|
if (this._tabIndexMaxCreators == tab)
|
|
{
|
|
this._tabIndexMaxCreators++;
|
|
}
|
|
|
|
if (!initial) {
|
|
// Move all but last word to first name field and show it
|
|
var last = this._getFieldValue(lastName);
|
|
if (last && last != this._defaultFullName) {
|
|
var lastNameRE = /(.*?)[ ]*([^ ]+[ ]*)$/;
|
|
var parts = lastNameRE.exec(last);
|
|
if (parts[2] && parts[2] != last)
|
|
{
|
|
this._setFieldValue(lastName, parts[2]);
|
|
this._setFieldValue(firstName, parts[1]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!this._getFieldValue(firstName)) {
|
|
this._setFieldValue(firstName, this._defaultFirstName);
|
|
}
|
|
|
|
if (this._getFieldValue(lastName) == this._defaultFullName) {
|
|
this._setFieldValue(lastName, this._defaultLastName);
|
|
}
|
|
|
|
firstName.setAttribute('hidden', false);
|
|
comma.setAttribute('hidden', false);
|
|
}
|
|
|
|
// Save the last-used field mode
|
|
Zotero.debug("Switching lastCreatorFieldMode to " + fieldMode);
|
|
Zotero.Prefs.set('lastCreatorFieldMode', fieldMode);
|
|
|
|
if (!initial)
|
|
{
|
|
var index = button.getAttribute('fieldname').split('-')[1];
|
|
var fields = this.getCreatorFields(row);
|
|
fields.fieldMode = fieldMode;
|
|
this.modifyCreator(index, fields);
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="scrollToTop">
|
|
<body>
|
|
<![CDATA[
|
|
if (!this._activeScrollbox) {
|
|
return;
|
|
}
|
|
var sbo = this._activeScrollbox.boxObject;
|
|
sbo.QueryInterface(Components.interfaces.nsIScrollBoxObject);
|
|
sbo.scrollTo(0,0);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="ensureElementIsVisible">
|
|
<parameter name="elem"/>
|
|
<body>
|
|
<![CDATA[
|
|
if (!this._activeScrollbox) {
|
|
return;
|
|
}
|
|
var sbo = this._activeScrollbox.boxObject;
|
|
sbo.QueryInterface(Components.interfaces.nsIScrollBoxObject);
|
|
sbo.ensureElementIsVisible(elem);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="changeTypeTo">
|
|
<parameter name="itemTypeID"/>
|
|
<parameter name="menu"/>
|
|
<body>
|
|
<![CDATA[
|
|
if (itemTypeID == this.item.itemTypeID) {
|
|
return true;
|
|
}
|
|
|
|
var fieldsToDelete = this.item.getFieldsNotInType(itemTypeID, true);
|
|
|
|
// Generate list of localized field names for display in pop-up
|
|
if (fieldsToDelete) {
|
|
var fieldNames = "";
|
|
for (var i=0; i<fieldsToDelete.length; i++) {
|
|
fieldNames += "\n - " +
|
|
Zotero.ItemFields.getLocalizedString(this.item.itemTypeID, fieldsToDelete[i]);
|
|
}
|
|
|
|
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
|
.getService(Components.interfaces.nsIPromptService);
|
|
}
|
|
|
|
if (!fieldsToDelete ||
|
|
promptService.confirm(null,
|
|
Zotero.getString('pane.item.changeType.title'),
|
|
Zotero.getString('pane.item.changeType.text') + "\n" + fieldNames)) {
|
|
this.item.setType(itemTypeID);
|
|
|
|
if (this.saveOnEdit) {
|
|
this.item.save();
|
|
}
|
|
else {
|
|
this.refresh();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Revert the menu (which changes before the pop-up)
|
|
if (menu) {
|
|
menu.value = this.item.itemTypeID;
|
|
}
|
|
|
|
return false;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="onViewClick">
|
|
<parameter name="button"/>
|
|
<parameter name="event"/>
|
|
<body>
|
|
<![CDATA[
|
|
if (button.getAttribute('viewURL')) {
|
|
ZoteroPane.loadURI(button.getAttribute('viewURL'), event);
|
|
}
|
|
else if (button.getAttribute('viewSnapshot')) {
|
|
ZoteroPane.viewAttachment(button.getAttribute('viewSnapshot'), event);
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="onLocateClick">
|
|
<parameter name="event"/>
|
|
<body>
|
|
<![CDATA[
|
|
// Default OpenURL button
|
|
if (event.originalTarget.id == 'locate-button') {
|
|
var url = Zotero.OpenURL.resolve(this.item);
|
|
if (url) {
|
|
ZoteroPane.loadURI(url, event);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Menu options
|
|
switch (event.originalTarget.id) {
|
|
case 'locate-service-openurl':
|
|
var url = Zotero.OpenURL.resolve(this.item);
|
|
if (url) {
|
|
ZoteroPane.loadURI(url, event);
|
|
}
|
|
break;
|
|
|
|
case 'locate-service-wayback':
|
|
var prefix = "http://web.archive.org/web/*/";
|
|
var url = this.item.getField('url');
|
|
url = prefix + url;
|
|
ZoteroPane.loadURI(url, event);
|
|
break;
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="toggleAbstractExpand">
|
|
<parameter name="label"/>
|
|
<body>
|
|
<![CDATA[
|
|
var cur = Zotero.Prefs.get('lastAbstractExpand');
|
|
Zotero.Prefs.set('lastAbstractExpand', !cur);
|
|
|
|
var ab = label.nextSibling;
|
|
var valueText = this.item.getField('abstractNote');
|
|
var tabindex = ab.getAttribute('ztabindex');
|
|
var elem = this.createValueElement(
|
|
valueText,
|
|
'abstractNote',
|
|
tabindex
|
|
);
|
|
ab.parentNode.replaceChild(elem, ab);
|
|
|
|
var text = Zotero.ItemFields.getLocalizedString(this.item.itemTypeID, 'abstractNote') + ':';
|
|
// Add '(...)' before "Abstract:" for collapsed abstracts
|
|
if (valueText && cur) {
|
|
text = '(...) ' + text;
|
|
}
|
|
label.setAttribute('value', text);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="disableButton">
|
|
<parameter name="button"/>
|
|
<body>
|
|
<![CDATA[
|
|
button.setAttribute('disabled', true);
|
|
button.setAttribute('onclick', false);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="_enablePlusButton">
|
|
<parameter name="button"/>
|
|
<parameter name="creatorTypeID"/>
|
|
<parameter name="fieldMode"/>
|
|
<body>
|
|
<![CDATA[
|
|
button.setAttribute('disabled', false);
|
|
button.setAttribute("onclick",
|
|
"document.getBindingParent(this).disableButton(this); "
|
|
+ "var creator = new Zotero.Creator; "
|
|
+ "creator.fieldMode = " + (fieldMode ? fieldMode : 0) + "; "
|
|
+ "document.getBindingParent(this).addCreatorRow(creator, "
|
|
+ (creatorTypeID ? creatorTypeID : 'false') + ", true);");
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<method name="createValueElement">
|
|
<parameter name="valueText"/>
|
|
<parameter name="fieldName"/>
|
|
<parameter name="tabindex"/>
|
|
<body>
|
|
<![CDATA[
|
|
valueText = valueText + '';
|
|
|
|
if (fieldName) {
|
|
var fieldID = Zotero.ItemFields.getID(fieldName);
|
|
}
|
|
|
|
// If an abstract, check last expand state
|
|
var abstractAsVbox = (fieldName == 'abstractNote') &&
|
|
Zotero.Prefs.get('lastAbstractExpand');
|
|
|
|
if (fieldName == 'extra' || abstractAsVbox) {
|
|
var valueElement = document.createElement("vbox");
|
|
}
|
|
else {
|
|
var valueElement = document.createElement("label");
|
|
}
|
|
|
|
valueElement.setAttribute('fieldname', fieldName);
|
|
valueElement.setAttribute('flex', 1);
|
|
|
|
if (this._fieldIsClickable(fieldName)) {
|
|
valueElement.setAttribute('ztabindex', tabindex);
|
|
valueElement.addEventListener('click', function (event) {
|
|
/* Skip right-click on Windows */
|
|
if (event.button) {
|
|
return;
|
|
}
|
|
document.getBindingParent(this).clickHandler(this);
|
|
}, false);
|
|
valueElement.className = 'zotero-clicky';
|
|
}
|
|
|
|
switch (fieldName) {
|
|
case 'itemType':
|
|
valueElement.setAttribute('itemTypeID', valueText);
|
|
valueText = Zotero.ItemTypes.getLocalizedString(valueText);
|
|
break;
|
|
|
|
case 'tag':
|
|
this._tabIndexMaxTagsFields = Math.max(this._tabIndexMaxTagsFields, tabindex);
|
|
break;
|
|
|
|
// Convert dates from UTC
|
|
case 'dateAdded':
|
|
case 'dateModified':
|
|
case 'accessDate':
|
|
if (valueText) {
|
|
var date = Zotero.Date.sqlToDate(valueText, true);
|
|
valueText = date ? date.toLocaleString() : '';
|
|
|
|
// Don't show time for access date if none
|
|
if (fieldName == 'accessDate') {
|
|
valueText = valueText.replace('00:00:00 ', '');
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (fieldID) {
|
|
// Display the SQL date as a tooltip for date fields
|
|
if (Zotero.ItemFields.isFieldOfBase(fieldID, 'date')) {
|
|
valueElement.setAttribute('tooltiptext',
|
|
Zotero.Date.multipartToSQL(this.item.getField(fieldName, true)));
|
|
}
|
|
|
|
// Display a context menu for certain fields
|
|
if (fieldName == 'seriesTitle' || fieldName == 'shortTitle' ||
|
|
Zotero.ItemFields.isFieldOfBase(fieldID, 'title') ||
|
|
Zotero.ItemFields.isFieldOfBase(fieldID, 'publicationTitle')) {
|
|
valueElement.setAttribute('contextmenu', 'field-menu');
|
|
}
|
|
}
|
|
|
|
|
|
if (fieldName && fieldName.indexOf('firstName') != -1) {
|
|
valueElement.setAttribute('flex', '1');
|
|
}
|
|
|
|
var firstSpace = valueText.indexOf(" ");
|
|
|
|
// To support newlines in 'extra' fields, we use multiple
|
|
// <description> elements inside a vbox
|
|
if (fieldName == 'extra' || abstractAsVbox) {
|
|
var lines = valueText.split("\n");
|
|
for (var i = 0; i < lines.length; i++) {
|
|
var descriptionNode = document.createElement("description");
|
|
var linetext = document.createTextNode(lines[i]);
|
|
descriptionNode.appendChild(linetext);
|
|
valueElement.appendChild(descriptionNode);
|
|
}
|
|
}
|
|
// 29 == arbitrary length at which to chop uninterrupted text
|
|
else if ((firstSpace == -1 && valueText.length > 29 ) || firstSpace > 29
|
|
|| (fieldName &&
|
|
(fieldName.substr(0, 7) == 'creator') || fieldName == 'abstractNote')) {
|
|
if (fieldName == 'abstractNote') {
|
|
valueText = valueText.replace(/[\t\n]/g, ' ');
|
|
}
|
|
valueElement.setAttribute('crop', 'end');
|
|
valueElement.setAttribute('value',valueText);
|
|
}
|
|
else {
|
|
// Wrap to multiple lines
|
|
valueElement.appendChild(document.createTextNode(valueText));
|
|
}
|
|
|
|
return valueElement;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="removeCreator">
|
|
<parameter name="index"/>
|
|
<parameter name="labelToDelete"/>
|
|
<body>
|
|
<![CDATA[
|
|
// If unsaved row, just remove element
|
|
if (!this.item.hasCreatorAt(index)) {
|
|
labelToDelete.parentNode.removeChild(labelToDelete);
|
|
|
|
// Enable the "+" button on the previous row
|
|
var elems = this._dynamicFields.getElementsByAttribute('value', '+');
|
|
var button = elems[elems.length-1];
|
|
var creatorFields = this.getCreatorFields(Zotero.getAncestorByTagName(button, 'row'));
|
|
this._enablePlusButton(button, creatorFields.typeID, creatorFields.fieldMode);
|
|
|
|
this._creatorCount--;
|
|
return;
|
|
}
|
|
this.item.removeCreator(index);
|
|
this.item.save();
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="showEditor">
|
|
<parameter name="elem"/>
|
|
<body>
|
|
<![CDATA[
|
|
// Blur any active fields
|
|
if (this._dynamicFields) {
|
|
this._dynamicFields.focus();
|
|
}
|
|
|
|
Zotero.debug('Showing editor');
|
|
|
|
var fieldName = elem.getAttribute('fieldname');
|
|
var tabindex = elem.getAttribute('ztabindex');
|
|
|
|
var [field, creatorIndex, creatorField] = fieldName.split('-');
|
|
if (field == 'creator') {
|
|
var c = this.item.getCreator(creatorIndex);
|
|
var value = c ? c.ref[creatorField] : '';
|
|
var itemID = this.item.id;
|
|
}
|
|
else if (fieldName=='tag') {
|
|
var tagID = elem.parentNode.getAttribute('id').split('-')[1];
|
|
var value = tagID ? Zotero.Tags.getName(tagID) : '';
|
|
var itemID = Zotero.getAncestorByTagName(elem, 'tagsbox').item.id;
|
|
}
|
|
else {
|
|
var value = this.item.getField(fieldName);
|
|
var itemID = this.item.id;
|
|
|
|
// Access date needs to be converted from UTC
|
|
if (fieldName=='accessDate' && value!='') {
|
|
var localDate = Zotero.Date.sqlToDate(value, true);
|
|
var value = Zotero.Date.dateToSQL(localDate);
|
|
}
|
|
}
|
|
|
|
var t = document.createElement("textbox");
|
|
t.setAttribute('value', value);
|
|
t.setAttribute('fieldname', fieldName);
|
|
t.setAttribute('ztabindex', tabindex);
|
|
t.setAttribute('flex', '1');
|
|
|
|
if (creatorField=='lastName') {
|
|
t.setAttribute('fieldMode', elem.getAttribute('fieldMode'));
|
|
}
|
|
|
|
if (['title', 'abstractNote', 'extra'].indexOf(fieldName) != -1) {
|
|
t.setAttribute('multiline', true);
|
|
t.setAttribute('rows', 8);
|
|
}
|
|
else {
|
|
var autoCompleteFields = [
|
|
'creator',
|
|
'journalAbbreviation',
|
|
'seriesTitle',
|
|
'seriesText',
|
|
'repository',
|
|
'callNumber',
|
|
'archiveLocation',
|
|
'language',
|
|
'rights',
|
|
'tag'
|
|
];
|
|
|
|
// Add the type-specific versions of these base fields
|
|
var baseACFields = ['publisher', 'publicationTitle', 'type',
|
|
'medium', 'place'];
|
|
autoCompleteFields = autoCompleteFields.concat(baseACFields);
|
|
|
|
for (var i=0; i<baseACFields.length; i++) {
|
|
var add = Zotero.ItemFields.getTypeFieldsFromBase(baseACFields[i], true)
|
|
autoCompleteFields = autoCompleteFields.concat(add);
|
|
}
|
|
|
|
// Add auto-complete for certain fields
|
|
if (autoCompleteFields.indexOf(field) != -1) {
|
|
t.setAttribute('type', 'autocomplete');
|
|
t.setAttribute('autocompletesearch', 'zotero');
|
|
var suffix = itemID ? itemID : '';
|
|
if (field=='creator') {
|
|
suffix = elem.getAttribute('fieldMode') + '-' + suffix;
|
|
}
|
|
t.setAttribute('autocompletesearchparam', fieldName + '/' + suffix);
|
|
t.setAttribute('ontextentered',
|
|
'document.getBindingParent(this).handleCreatorAutoCompleteSelect(this)');
|
|
}
|
|
}
|
|
var box = elem.parentNode;
|
|
box.replaceChild(t, elem);
|
|
|
|
// Prevent error when clicking between a changed field
|
|
// and another -- there's probably a better way
|
|
if (!t.select) {
|
|
return;
|
|
}
|
|
|
|
t.select();
|
|
|
|
t.addEventListener('blur', function () {
|
|
document.getBindingParent(this).blurHandler(this);
|
|
}, false);
|
|
t.setAttribute('onkeypress', "return document.getBindingParent(this).handleKeyPress(event)");
|
|
|
|
this._tabDirection = false;
|
|
this._lastTabIndex = tabindex;
|
|
|
|
return t;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<!--
|
|
Save a multiple-field selection for the creator autocomplete
|
|
(e.g. "Shakespeare, William")
|
|
-->
|
|
<method name="handleCreatorAutoCompleteSelect">
|
|
<parameter name="textbox"/>
|
|
<body>
|
|
<![CDATA[
|
|
var comment = Zotero.Utilities.AutoComplete.getResultComment(textbox);
|
|
if (!comment)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var [creatorID, numFields] = comment.split('-');
|
|
|
|
// If result uses two fields, save both
|
|
if (numFields==2)
|
|
{
|
|
// Manually clear autocomplete controller's reference to
|
|
// textbox to prevent error next time around
|
|
textbox.mController.input = null;
|
|
|
|
var [field, creatorIndex, creatorField] =
|
|
textbox.getAttribute('fieldname').split('-');
|
|
|
|
// Stay focused
|
|
this._lastTabIndex = parseInt(textbox.getAttribute('ztabindex')) - 1;
|
|
this._tabDirection = 1;
|
|
|
|
var creator = Zotero.Creators.get(creatorID);
|
|
|
|
var otherField = creatorField == 'lastName' ? 'firstName' : 'lastName';
|
|
|
|
// Update this textbox
|
|
textbox.setAttribute('value', creator[creatorField]);
|
|
textbox.value = creator[creatorField];
|
|
|
|
// Update the other label
|
|
if (otherField=='firstName'){
|
|
var label = textbox.nextSibling.nextSibling;
|
|
}
|
|
else if (otherField=='lastName'){
|
|
var label = textbox.previousSibling.previousSibling;
|
|
}
|
|
|
|
//this._setFieldValue(label, creator[otherField]);
|
|
if (label.firstChild){
|
|
label.firstChild.nodeValue = creator[otherField];
|
|
}
|
|
else {
|
|
label.value = creator[otherField];
|
|
}
|
|
|
|
var row = Zotero.getAncestorByTagName(textbox, 'row');
|
|
|
|
var fields = this.getCreatorFields(row);
|
|
fields[creatorField] = creator[creatorField];
|
|
fields[otherField] = creator[otherField];
|
|
this.modifyCreator(creatorIndex, fields);
|
|
}
|
|
|
|
// Otherwise let the autocomplete popup handle matters
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="handleKeyPress">
|
|
<parameter name="event"/>
|
|
<body>
|
|
<![CDATA[
|
|
var target = event.target;
|
|
var focused = document.commandDispatcher.focusedElement;
|
|
|
|
switch (event.keyCode)
|
|
{
|
|
case event.DOM_VK_RETURN:
|
|
var fieldname = target.getAttribute('fieldname');
|
|
// Use shift-enter as the save action for the larger fields
|
|
if ((fieldname == 'abstractNote' || fieldname == 'extra')
|
|
&& !event.shiftKey)
|
|
{
|
|
break;
|
|
}
|
|
|
|
|
|
// Prevent blur on containing textbox
|
|
// DEBUG: what happens if this isn't present?
|
|
event.preventDefault();
|
|
|
|
if (fieldname == 'tag')
|
|
{
|
|
// If last tag row, create new one
|
|
var row = target.parentNode.parentNode;
|
|
if (row == row.parentNode.lastChild)
|
|
{
|
|
this._tabDirection = 1;
|
|
var lastTag = true;
|
|
}
|
|
}
|
|
// Shift-enter adds new creator row
|
|
else if (fieldname.indexOf('creator-') == 0 && event.shiftKey) {
|
|
// Value hasn't changed
|
|
if (target.getAttribute('value') == target.value) {
|
|
Zotero.debug("Value hasn't changed");
|
|
// If + button is disabled, just focus next creator row
|
|
if (Zotero.getAncestorByTagName(target, 'row').lastChild.lastChild.disabled) {
|
|
this._focusNextField('info', this._dynamicFields, this._lastTabIndex, false);
|
|
}
|
|
else {
|
|
// TODO: should use current creator type
|
|
this.addCreatorRow(false, false, true);
|
|
}
|
|
}
|
|
// Value has changed
|
|
else {
|
|
this._tabDirection = 1;
|
|
this._addCreatorRow = true;
|
|
focused.blur();
|
|
}
|
|
return false;
|
|
}
|
|
focused.blur();
|
|
|
|
// Return focus to items pane
|
|
if (!lastTag) {
|
|
var tree = document.getElementById('zotero-items-tree');
|
|
if (tree) {
|
|
tree.focus();
|
|
}
|
|
}
|
|
|
|
return false;
|
|
|
|
case event.DOM_VK_ESCAPE:
|
|
// Reset field to original value
|
|
target.value = target.getAttribute('value');
|
|
|
|
var tagsbox = Zotero.getAncestorByTagName(focused, 'tagsbox');
|
|
|
|
focused.blur();
|
|
|
|
if (tagsbox) {
|
|
tagsbox.closePopup();
|
|
}
|
|
|
|
// Return focus to items pane
|
|
var tree = document.getElementById('zotero-items-tree');
|
|
if (tree) {
|
|
tree.focus();
|
|
}
|
|
|
|
return false;
|
|
|
|
case event.DOM_VK_TAB:
|
|
this._tabDirection = event.shiftKey ? -1 : 1;
|
|
// Blur the old manually -- not sure why this is necessary,
|
|
// but it prevents an immediate blur() on the next tag
|
|
focused.blur();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="hideEditor">
|
|
<parameter name="textbox"/>
|
|
<body>
|
|
<![CDATA[
|
|
Zotero.debug('Hiding editor');
|
|
/*
|
|
var textbox = Zotero.getAncestorByTagName(t, 'textbox');
|
|
if (!textbox){
|
|
Zotero.debug('Textbox not found in hideEditor');
|
|
return;
|
|
}
|
|
*/
|
|
|
|
// TODO: get rid of this?
|
|
var saveChanges = this.saveOnEdit;
|
|
|
|
// Prevent autocomplete breakage in Firefox 3
|
|
if (textbox.mController) {
|
|
textbox.mController.input = null;
|
|
}
|
|
|
|
var fieldName = textbox.getAttribute('fieldname');
|
|
var tabindex = textbox.getAttribute('ztabindex');
|
|
|
|
//var value = t.value;
|
|
var value = textbox.value;
|
|
|
|
var elem;
|
|
var [field, creatorIndex, creatorField] = fieldName.split('-');
|
|
|
|
// Creator fields
|
|
if (field == 'creator') {
|
|
var row = Zotero.getAncestorByTagName(textbox, 'row');
|
|
|
|
var otherFields = this.getCreatorFields(row);
|
|
otherFields[creatorField] = value;
|
|
|
|
this.modifyCreator(creatorIndex, otherFields);
|
|
|
|
var val = this.item.getCreator(creatorIndex);
|
|
val = val ? val.ref[creatorField] : null;
|
|
|
|
if (!val) {
|
|
// Reset to '(first)'/'(last)'/'(name)'
|
|
if (creatorField == 'lastName') {
|
|
val = otherFields.fieldMode
|
|
? this._defaultFullName : this._defaultLastName;
|
|
}
|
|
else if (creatorField == 'firstName') {
|
|
val = this._defaultFirstName;
|
|
}
|
|
}
|
|
|
|
elem = this.createValueElement(
|
|
val,
|
|
fieldName,
|
|
tabindex
|
|
);
|
|
|
|
// Reset creator mode settings
|
|
if (otherFields.fieldMode) {
|
|
this.switchCreatorMode(row, 1, true);
|
|
}
|
|
else {
|
|
this.switchCreatorMode(row, 0, true);
|
|
}
|
|
}
|
|
|
|
// Tags
|
|
else if (fieldName=='tag') {
|
|
var tagsbox = Zotero.getAncestorByTagName(textbox, 'tagsbox');
|
|
if (!tagsbox)
|
|
{
|
|
Zotero.debug('Tagsbox not found', 1);
|
|
return;
|
|
}
|
|
|
|
var row = textbox.parentNode;
|
|
var rows = row.parentNode;
|
|
|
|
// Tag id encoded as 'tag-1234'
|
|
var id = row.getAttribute('id').split('-')[1];
|
|
|
|
if (saveChanges) {
|
|
if (id) {
|
|
if (value) {
|
|
// If trying to replace with another existing tag
|
|
// (which causes a delete of the row),
|
|
// clear the tab direction so we don't advance
|
|
// when the notifier kicks in
|
|
var existing = Zotero.Tags.getID(value, 0);
|
|
if (existing && id != existing)
|
|
{
|
|
this._tabDirection = false;
|
|
}
|
|
var changed = tagsbox.replace(id, value);
|
|
if (changed)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
tagsbox.remove(id);
|
|
return;
|
|
}
|
|
}
|
|
// New tag
|
|
else {
|
|
// If this is an existing automatic tag, it's going to be
|
|
// deleted and the number of rows will stay the same,
|
|
// so we have to compensate
|
|
var existingTypes = Zotero.Tags.getTypes(value);
|
|
if (existingTypes && existingTypes.indexOf(1) != -1) {
|
|
this._lastTabIndex--;
|
|
}
|
|
var id = tagsbox.add(value);
|
|
}
|
|
}
|
|
|
|
if (id) {
|
|
elem = this.createValueElement(
|
|
value,
|
|
'tag',
|
|
tabindex
|
|
);
|
|
}
|
|
else {
|
|
// Just remove the row
|
|
//
|
|
// If there's an open popup, this throws NODE CANNOT BE FOUND
|
|
try {
|
|
var row = rows.removeChild(row);
|
|
}
|
|
catch (e) {}
|
|
tagsbox.fixPopup();
|
|
tagsbox.closePopup();
|
|
|
|
this._tabDirection = false;
|
|
return;
|
|
}
|
|
|
|
var focusMode = 'tags';
|
|
var focusBox = tagsbox;
|
|
}
|
|
|
|
// Fields
|
|
else {
|
|
// Access date needs to be parsed and converted to UTC
|
|
if (fieldName=='accessDate' && value!='') {
|
|
if (Zotero.Date.isSQLDate(value) || Zotero.Date.isSQLDateTime(value)) {
|
|
var localDate = Zotero.Date.sqlToDate(value);
|
|
value = Zotero.Date.dateToSQL(localDate, true);
|
|
}
|
|
else {
|
|
var d = Zotero.Date.strToDate(value);
|
|
value = null;
|
|
if (d.year && d.month != undefined && d.day) {
|
|
d = new Date(d.year, d.month, d.day);
|
|
value = Zotero.Date.dateToSQL(d, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
this._modifyField(fieldName, value, this.saveOnEdit);
|
|
|
|
elem = this.createValueElement(
|
|
this.item.getField(fieldName),
|
|
fieldName,
|
|
tabindex
|
|
);
|
|
}
|
|
|
|
var box = textbox.parentNode;
|
|
box.replaceChild(elem,textbox);
|
|
|
|
if (this._tabDirection) {
|
|
if (!focusMode) {
|
|
var focusMode = 'info';
|
|
var focusBox = this._dynamicFields;
|
|
}
|
|
this._focusNextField(focusMode, focusBox, this._lastTabIndex, this._tabDirection == -1);
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="_rowIsClickable">
|
|
<parameter name="fieldName"/>
|
|
<body>
|
|
<![CDATA[
|
|
return this.clickByRow &&
|
|
(this.clickable ||
|
|
this._clickableFields.indexOf(fieldName) != -1);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="_fieldIsClickable">
|
|
<parameter name="fieldName"/>
|
|
<body>
|
|
<![CDATA[
|
|
return !this.clickByRow &&
|
|
((this.clickable && !this.item.isPrimaryField(fieldName))
|
|
|| this._clickableFields.indexOf(fieldName) != -1);
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="_modifyField">
|
|
<parameter name="field"/>
|
|
<parameter name="value"/>
|
|
<parameter name="save"/>
|
|
<body>
|
|
<![CDATA[
|
|
this.item.setField(field,value);
|
|
if (save) {
|
|
this.item.save();
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="_getFieldValue">
|
|
<parameter name="label"/>
|
|
<body>
|
|
<![CDATA[
|
|
return label.firstChild
|
|
? label.firstChild.nodeValue : label.value;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="_setFieldValue">
|
|
<parameter name="label"/>
|
|
<parameter name="value"/>
|
|
<body>
|
|
<![CDATA[
|
|
if (label.firstChild) {
|
|
label.firstChild.nodeValue = value;
|
|
}
|
|
else {
|
|
label.value = value;
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<!-- TODO: work with textboxes too -->
|
|
<method name="textTransform">
|
|
<parameter name="label"/>
|
|
<parameter name="mode"/>
|
|
<body>
|
|
<![CDATA[
|
|
var val = this._getFieldValue(label);
|
|
switch (mode) {
|
|
case 'lower':
|
|
var newVal = val.toLowerCase();
|
|
break;
|
|
case 'title':
|
|
var utils = new Zotero.Utilities();
|
|
var newVal = utils.capitalizeTitle(val.toLowerCase(), true);
|
|
break;
|
|
default:
|
|
throw ("Invalid transform mode '" + mode + "' in zoteroitembox.textTransform()");
|
|
}
|
|
this._setFieldValue(label, newVal);
|
|
this._modifyField(label.getAttribute('fieldname'), newVal, this.saveOnEdit);
|
|
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="getCreatorFields">
|
|
<parameter name="row"/>
|
|
<body>
|
|
<![CDATA[
|
|
var typeID = row.getElementsByClassName('creator-type-label')[0].getAttribute('typeid');
|
|
var label1 = row.getElementsByClassName('creator-name-box')[0].firstChild;
|
|
var label2 = label1.parentNode.lastChild;
|
|
|
|
var fields = {
|
|
lastName: label1.firstChild ? label1.firstChild.nodeValue
|
|
: label1.value,
|
|
firstName: label2.firstChild ? label2.firstChild.nodeValue
|
|
: label2.value,
|
|
fieldMode: label1.getAttribute('fieldMode')
|
|
? parseInt(label1.getAttribute('fieldMode')) : 0,
|
|
creatorTypeID: parseInt(typeID),
|
|
};
|
|
|
|
// Ignore '(first)'
|
|
if (fields.fieldMode == 1 || fields.firstName == this._defaultFirstName) {
|
|
fields.firstName = '';
|
|
}
|
|
// Ignore '(last)' or '(name)'
|
|
if (fields.lastName == this._defaultFullName
|
|
|| fields.lastName == this._defaultLastName) {
|
|
fields.lastName = '';
|
|
}
|
|
|
|
return fields;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<method name="modifyCreator">
|
|
<parameter name="index"/>
|
|
<parameter name="fields"/>
|
|
<parameter name="changeGlobally"/>
|
|
<body>
|
|
<![CDATA[
|
|
var firstName = fields.firstName;
|
|
var lastName = fields.lastName;
|
|
//var shortName = fields.shortName;
|
|
var fieldMode = fields.fieldMode;
|
|
var creatorTypeID = fields.creatorTypeID;
|
|
|
|
var oldCreator = this.item.getCreator(index);
|
|
|
|
// Don't save empty creators
|
|
if (!firstName && !lastName){
|
|
if (!oldCreator) {
|
|
return;
|
|
}
|
|
this.item.removeCreator(index);
|
|
this.item.save();
|
|
return;
|
|
}
|
|
|
|
Zotero.DB.beginTransaction();
|
|
|
|
var newCreator = new Zotero.Creator;
|
|
newCreator.setFields(fields);
|
|
|
|
var newLinkedCreators = [];
|
|
var creatorDataID = Zotero.Creators.getDataID(fields);
|
|
if (creatorDataID) {
|
|
newLinkedCreators = Zotero.Creators.getCreatorsWithData(creatorDataID);
|
|
}
|
|
|
|
if (oldCreator) {
|
|
if (oldCreator.ref.equals(newCreator)) {
|
|
if (oldCreator.creatorTypeID == creatorTypeID) {
|
|
Zotero.debug("Creator " + oldCreator.ref.id + " hasn't changed");
|
|
}
|
|
// Just change creatorTypeID
|
|
else {
|
|
this.item.setCreator(index, oldCreator.ref, creatorTypeID);
|
|
if (this.saveOnEdit) {
|
|
this.item.save();
|
|
}
|
|
}
|
|
Zotero.DB.commitTransaction();
|
|
return;
|
|
}
|
|
|
|
oldCreator = oldCreator.ref;
|
|
}
|
|
|
|
var creator;
|
|
var creatorID;
|
|
|
|
if (oldCreator) {
|
|
var numLinkedItems = oldCreator.countLinkedItems();
|
|
// Creator is linked only to the current item
|
|
if (numLinkedItems == 1) {
|
|
if (newLinkedCreators.length) {
|
|
// Use the first creator found with this data
|
|
// TODO: support choosing among options
|
|
creatorID = newLinkedCreators[0];
|
|
creator = Zotero.Creators.get(creatorID);
|
|
}
|
|
else {
|
|
oldCreator.setFields(fields);
|
|
//creatorID = oldCreator.save();
|
|
creator = oldCreator;
|
|
}
|
|
}
|
|
// Creator is linked to multiple items with changeGlobally off
|
|
else if (!changeGlobally) {
|
|
if (newLinkedCreators.length) {
|
|
// Use the first creator found with this data
|
|
// TODO: support choosing among options
|
|
creatorID = newLinkedCreators[0];
|
|
creator = Zotero.Creators.get(creatorID);
|
|
}
|
|
else {
|
|
//creatorID = newCreator.save();
|
|
creator = newCreator;
|
|
}
|
|
}
|
|
// Creator is linked to multiple items with changeGlobally on
|
|
else {
|
|
throw ('changeGlobally unimplemented');
|
|
if (newLinkedCreators.length) {
|
|
// Use the first creator found with this data
|
|
// TODO: support choosing among options
|
|
creatorID = newLinkedCreators[0];
|
|
|
|
// TODO: switch all linked items to this creator
|
|
}
|
|
else {
|
|
creatorID = newCreator.save();
|
|
|
|
// TODO: switch all linked items to new creatorID
|
|
}
|
|
}
|
|
}
|
|
// No existing creator
|
|
else {
|
|
if (newLinkedCreators.length) {
|
|
creatorID = newLinkedCreators[0];
|
|
creator = Zotero.Creators.get(creatorID);
|
|
}
|
|
else {
|
|
//creatorID = newCreator.save();
|
|
creator = newCreator;
|
|
}
|
|
}
|
|
|
|
this.item.setCreator(index, creator, creatorTypeID);
|
|
if (this.saveOnEdit) {
|
|
this.item.save();
|
|
}
|
|
|
|
Zotero.DB.commitTransaction();
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<!--
|
|
/*
|
|
function modifyCreatorByID(index, creatorID, creatorTypeID) {
|
|
throw ('Unimplemented');
|
|
var oldCreator = _itemBeingEdited.getCreator(index);
|
|
if (creator) {
|
|
oldCreator = creator.ref;
|
|
var oldCreatorID = oldCreator.creatorID;
|
|
}
|
|
|
|
Zotero.debug("Old creatorID is " + oldCreatorID);
|
|
|
|
_itemBeingEdited.setCreator(index, firstName, lastName, typeID, fieldMode);
|
|
_itemBeingEdited.save();
|
|
}
|
|
*/
|
|
-->
|
|
|
|
|
|
<method name="focusFirstField">
|
|
<parameter name="mode"/>
|
|
<body>
|
|
<![CDATA[
|
|
switch (mode) {
|
|
case 'info':
|
|
this._focusNextField('info', this._dynamicFields, 0, false);
|
|
break;
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
|
|
<!--
|
|
Advance the field focus forward or backward
|
|
|
|
Note: We're basically replicating the built-in tabindex functionality,
|
|
which doesn't work well with the weird label/textbox stuff we're doing.
|
|
(The textbox being tabbed away from is deleted before the blur()
|
|
completes, so it doesn't know where it's supposed to go next.)
|
|
-->
|
|
<method name="_focusNextField">
|
|
<parameter name="mode"/>
|
|
<parameter name="box"/>
|
|
<parameter name="tabindex"/>
|
|
<parameter name="back"/>
|
|
<body>
|
|
<![CDATA[
|
|
tabindex = parseInt(tabindex);
|
|
if (back)
|
|
{
|
|
if (mode=='info')
|
|
{
|
|
switch (tabindex)
|
|
{
|
|
case 1:
|
|
//Zotero.debug('At beginning');
|
|
document.getElementById('item-type-menu').focus();
|
|
return false;
|
|
|
|
case this._tabIndexMinCreators:
|
|
var nextIndex = 1;
|
|
break;
|
|
|
|
case this._tabIndexMinFields:
|
|
var nextIndex = this._tabIndexMaxCreators;
|
|
break;
|
|
|
|
default:
|
|
var nextIndex = tabindex - 1;
|
|
}
|
|
}
|
|
else if (mode=='tags')
|
|
{
|
|
switch (tabindex)
|
|
{
|
|
case 1:
|
|
return false;
|
|
|
|
default:
|
|
var nextIndex = tabindex - 1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (mode=='info')
|
|
{
|
|
switch (tabindex)
|
|
{
|
|
case 1:
|
|
var nextIndex = this._tabIndexMinCreators;
|
|
break;
|
|
|
|
case this._tabIndexMaxCreators:
|
|
var nextIndex = this._tabIndexMinFields;
|
|
break;
|
|
|
|
case this._tabIndexMaxInfoFields:
|
|
//Zotero.debug('At end');
|
|
return false;
|
|
|
|
default:
|
|
var nextIndex = tabindex + 1;
|
|
}
|
|
}
|
|
else if (mode=='tags')
|
|
{
|
|
switch (tabindex)
|
|
{
|
|
case this._tabIndexMaxTagsFields:
|
|
// In tags box, keep going to create new row
|
|
var nextIndex = tabindex + 1;
|
|
break;
|
|
|
|
default:
|
|
var nextIndex = tabindex + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
Zotero.debug('Looking for tabindex ' + nextIndex, 4);
|
|
switch (mode)
|
|
{
|
|
case 'info':
|
|
var next = box.getElementsByAttribute('ztabindex', nextIndex);
|
|
if (!next[0])
|
|
{
|
|
//Zotero.debug("Next field not found");
|
|
return this._focusNextField(mode, box, nextIndex, back);
|
|
}
|
|
break;
|
|
|
|
// Tags pane
|
|
case 'tags':
|
|
var next = document.getAnonymousNodes(box)[0].
|
|
getElementsByAttribute('ztabindex', nextIndex);
|
|
if (!next[0]) {
|
|
next[0] = box.addDynamicRow();
|
|
}
|
|
break;
|
|
}
|
|
|
|
next[0].click();
|
|
this.ensureElementIsVisible(next[0]);
|
|
return true;
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="_id">
|
|
<parameter name="id"/>
|
|
<body>
|
|
<![CDATA[
|
|
return document.getAnonymousNodes(this)[0].getElementsByAttribute('id', id)[0];
|
|
]]>
|
|
</body>
|
|
</method>
|
|
</implementation>
|
|
|
|
<content>
|
|
<scrollbox id="item-box" flex="1" orient="vertical"
|
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
<popupset>
|
|
<popup id="creator-type-menu" position="after_start"
|
|
oncommand="var typeBox = document.popupNode.localName == 'hbox'
|
|
? document.popupNode : document.popupNode.parentNode;
|
|
var row = typeBox.parentNode;
|
|
var typeID = event.explicitOriginalTarget.getAttribute('typeid');
|
|
var fields = document.getBindingParent(this).getCreatorFields(row);
|
|
fields.creatorTypeID = typeID;
|
|
typeBox.getElementsByTagName('label')[0].setAttribute(
|
|
'value',
|
|
Zotero.getString(
|
|
'creatorTypes.' + Zotero.CreatorTypes.getName(typeID)
|
|
) + ':'
|
|
);
|
|
typeBox.setAttribute('typeid', typeID);
|
|
var index = typeBox.getAttribute('fieldname').split('-')[1];
|
|
document.getBindingParent(this).modifyCreator(index, fields)"/>
|
|
<popup id="field-menu">
|
|
<menu label="&zotero.item.textTransform;">
|
|
<menupopup>
|
|
<menuitem label="&zotero.item.textTransform.lowercase;" class="menuitem-non-iconic"
|
|
oncommand="document.getBindingParent(this).textTransform(document.popupNode, 'lower')"/>
|
|
<menuitem label="&zotero.item.textTransform.titlecase;" class="menuitem-non-iconic"
|
|
oncommand="document.getBindingParent(this).textTransform(document.popupNode, 'title')"/>
|
|
</menupopup>
|
|
</menu>
|
|
</popup>
|
|
</popupset>
|
|
<hbox id="go-buttons" align="center" hidden="true">
|
|
<button id="view-button"
|
|
onfocus="document.getBindingParent(this).ensureElementIsVisible(this)"
|
|
oncommand="document.getBindingParent(this).onViewClick(this, event)" disabled="false"/>
|
|
<button id="locate-button" label="&zotero.toolbar.openURL.label;"
|
|
onfocus="document.getBindingParent(this).ensureElementIsVisible(this)"
|
|
type="menu"
|
|
oncommand="document.getBindingParent(this).onLocateClick(event)">
|
|
<menupopup>
|
|
<menuitem id="locate-service-openurl" label="Library Lookup" tooltiptext="&zotero.toolbar.openURL.tooltip;"/>
|
|
<menuitem id="locate-service-wayback" label="Wayback Machine"/>
|
|
</menupopup>
|
|
</button>
|
|
</hbox>
|
|
<hbox align="center" hidden="true">
|
|
<menulist id="item-type-menu" oncommand="document.getBindingParent(this).changeTypeTo(this.value, this)" flex="1"
|
|
onfocus="document.getBindingParent(this).ensureElementIsVisible(this)"
|
|
onkeypress="if (event.keyCode == event.DOM_VK_TAB){ if (!event.shiftKey) { document.getBindingParent(this).focusFirstField('info'); event.preventDefault(); } }">
|
|
<menupopup/>
|
|
</menulist>
|
|
</hbox>
|
|
<grid flex="1">
|
|
<columns>
|
|
<column/>
|
|
<column flex="1"/>
|
|
</columns>
|
|
<rows id="dynamic-fields" flex="1"/>
|
|
</grid>
|
|
</scrollbox>
|
|
</content>
|
|
</binding>
|
|
</bindings>
|