Save open field when selecting from an item pane context menu
If a field is open and the user right-clicks on another field (e.g., swap names, creator type, transform text), any changed value in the open field was lost. Also: - Don't show swap-names menu in single-field mode I can't quite get programmatic access to context menus to work correctly, so tests are disabled for now. (They work individually, but not together.)
This commit is contained in:
parent
2cce099928
commit
2a55e56f3f
|
@ -786,7 +786,7 @@
|
||||||
firstlast.lastChild.setAttribute('hidden', true);
|
firstlast.lastChild.setAttribute('hidden', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.editable) {
|
if (this.editable && fieldMode == 0) {
|
||||||
firstlast.setAttribute('contextmenu', 'zotero-creator-transform-menu');
|
firstlast.setAttribute('contextmenu', 'zotero-creator-transform-menu');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2021,28 +2021,32 @@
|
||||||
<method name="textTransform">
|
<method name="textTransform">
|
||||||
<parameter name="label"/>
|
<parameter name="label"/>
|
||||||
<parameter name="mode"/>
|
<parameter name="mode"/>
|
||||||
<body>
|
<body><![CDATA[
|
||||||
<![CDATA[
|
return Zotero.spawn(function* () {
|
||||||
var val = this._getFieldValue(label);
|
var val = this._getFieldValue(label);
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'title':
|
case 'title':
|
||||||
var newVal = Zotero.Utilities.capitalizeTitle(val.toLowerCase(), true);
|
var newVal = Zotero.Utilities.capitalizeTitle(val.toLowerCase(), true);
|
||||||
break;
|
break;
|
||||||
case 'sentence':
|
case 'sentence':
|
||||||
// capitalize the first letter, including after beginning punctuation
|
// capitalize the first letter, including after beginning punctuation
|
||||||
// capitalize after ?, ! and remove space(s) before those as well as colon analogous to capitalizeTitle function
|
// capitalize after ?, ! and remove space(s) before those as well as colon analogous to capitalizeTitle function
|
||||||
// also deal with initial punctuation here - open quotes and Spanish beginning punctuation marks
|
// also deal with initial punctuation here - open quotes and Spanish beginning punctuation marks
|
||||||
newVal = val.toLowerCase().replace(/\s*:/, ":");
|
newVal = val.toLowerCase().replace(/\s*:/, ":");
|
||||||
newVal = newVal.replace(/(([\?!]\s*|^)([\'\"¡¿“‘„«\s]+)?[^\s])/g, function (x) {
|
newVal = newVal.replace(/(([\?!]\s*|^)([\'\"¡¿“‘„«\s]+)?[^\s])/g, function (x) {
|
||||||
return x.replace(/\s+/m, " ").toUpperCase();});
|
return x.replace(/\s+/m, " ").toUpperCase();});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw ("Invalid transform mode '" + mode + "' in zoteroitembox.textTransform()");
|
throw ("Invalid transform mode '" + mode + "' in zoteroitembox.textTransform()");
|
||||||
}
|
}
|
||||||
this._setFieldValue(label, newVal);
|
this._setFieldValue(label, newVal);
|
||||||
this._modifyField(label.getAttribute('fieldname'), newVal, this.saveOnEdit).done();
|
if (this.saveOnEdit) {
|
||||||
]]>
|
// See note in modifyCreator()
|
||||||
</body>
|
yield this.blurOpenField();
|
||||||
|
}
|
||||||
|
return this._modifyField(label.getAttribute('fieldname'), newVal, this.saveOnEdit);
|
||||||
|
}, this);
|
||||||
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
|
||||||
|
@ -2083,7 +2087,7 @@
|
||||||
<parameter name="fields"/>
|
<parameter name="fields"/>
|
||||||
<parameter name="skipSave"/>
|
<parameter name="skipSave"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
return Zotero.Promise.try(function () {
|
return Zotero.spawn(function* () {
|
||||||
var libraryID = this.item.libraryID;
|
var libraryID = this.item.libraryID;
|
||||||
var firstName = fields.firstName;
|
var firstName = fields.firstName;
|
||||||
var lastName = fields.lastName;
|
var lastName = fields.lastName;
|
||||||
|
@ -2099,6 +2103,11 @@
|
||||||
}
|
}
|
||||||
this.item.removeCreator(index);
|
this.item.removeCreator(index);
|
||||||
if (this.saveOnEdit && !skipSave) {
|
if (this.saveOnEdit && !skipSave) {
|
||||||
|
// Make sure any open field is saved, since a blur() isn't otherwise
|
||||||
|
// triggered clicking directly to a popup menu. (If a field is open, the
|
||||||
|
// saveTx() below will become a no-op.)
|
||||||
|
yield this.blurOpenField();
|
||||||
|
|
||||||
return this.item.saveTx();
|
return this.item.saveTx();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -2106,9 +2115,12 @@
|
||||||
|
|
||||||
var changed = this.item.setCreator(index, fields);
|
var changed = this.item.setCreator(index, fields);
|
||||||
if (changed && this.saveOnEdit && !skipSave) {
|
if (changed && this.saveOnEdit && !skipSave) {
|
||||||
|
// See note above
|
||||||
|
yield this.blurOpenField();
|
||||||
|
|
||||||
return this.item.saveTx();
|
return this.item.saveTx();
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}, this);
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
@ -2117,6 +2129,7 @@
|
||||||
@return {Promise}
|
@return {Promise}
|
||||||
-->
|
-->
|
||||||
<method name="swapNames">
|
<method name="swapNames">
|
||||||
|
<parameter name="event"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
return Zotero.Promise.try(function () {
|
return Zotero.Promise.try(function () {
|
||||||
var row = Zotero.getAncestorByTagName(document.popupNode, 'row');
|
var row = Zotero.getAncestorByTagName(document.popupNode, 'row');
|
||||||
|
@ -2138,9 +2151,8 @@
|
||||||
<method name="moveCreator">
|
<method name="moveCreator">
|
||||||
<parameter name="index"/>
|
<parameter name="index"/>
|
||||||
<parameter name="moveUp"/>
|
<parameter name="moveUp"/>
|
||||||
<body>
|
<body><![CDATA[
|
||||||
<![CDATA[
|
return Zotero.spawn(function* () {
|
||||||
return Zotero.Promise.try(function () {
|
|
||||||
if (index == 0 && moveUp) {
|
if (index == 0 && moveUp) {
|
||||||
Zotero.debug("Can't move up creator 0");
|
Zotero.debug("Can't move up creator 0");
|
||||||
return;
|
return;
|
||||||
|
@ -2156,11 +2168,13 @@
|
||||||
this.item.setCreator(newIndex, a);
|
this.item.setCreator(newIndex, a);
|
||||||
this.item.setCreator(index, b);
|
this.item.setCreator(index, b);
|
||||||
if (this.saveOnEdit) {
|
if (this.saveOnEdit) {
|
||||||
|
// See note in modifyCreator()
|
||||||
|
yield this.blurOpenField();
|
||||||
|
|
||||||
return this.item.saveTx();
|
return this.item.saveTx();
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}, this);
|
||||||
]]>
|
]]></body>
|
||||||
</body>
|
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
|
||||||
|
@ -2394,7 +2408,7 @@
|
||||||
var hideTransforms = !exists || !!fieldMode;
|
var hideTransforms = !exists || !!fieldMode;
|
||||||
return !hideTransforms;">
|
return !hideTransforms;">
|
||||||
<menuitem label="&zotero.item.creatorTransform.nameSwap;"
|
<menuitem label="&zotero.item.creatorTransform.nameSwap;"
|
||||||
oncommand="document.getBindingParent(this).swapNames();"/>
|
oncommand="document.getBindingParent(this).swapNames(event);"/>
|
||||||
</menupopup>
|
</menupopup>
|
||||||
<menupopup id="zotero-doi-menu">
|
<menupopup id="zotero-doi-menu">
|
||||||
<menuitem id="zotero-doi-menu-view-online" label="&zotero.item.viewOnline;"/>
|
<menuitem id="zotero-doi-menu-view-online" label="&zotero.item.viewOnline;"/>
|
||||||
|
|
|
@ -27,6 +27,89 @@ describe("Item pane", function () {
|
||||||
|
|
||||||
yield Zotero.Items.erase(id);
|
yield Zotero.Items.erase(id);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
it.skip("should swap creator names", function* () {
|
||||||
|
var item = new Zotero.Item('book');
|
||||||
|
item.setCreators([
|
||||||
|
{
|
||||||
|
firstName: "First",
|
||||||
|
lastName: "Last",
|
||||||
|
creatorType: "author"
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
yield item.saveTx();
|
||||||
|
|
||||||
|
var itemBox = doc.getElementById('zotero-editpane-item-box');
|
||||||
|
var label = doc.getAnonymousNodes(itemBox)[0].getElementsByAttribute('fieldname', 'creator-0-lastName')[0];
|
||||||
|
var parent = label.parentNode;
|
||||||
|
assert.isTrue(parent.hasAttribute('contextmenu'));
|
||||||
|
|
||||||
|
var menupopup = doc.getAnonymousNodes(itemBox)[0]
|
||||||
|
.getElementsByAttribute('id', 'zotero-creator-transform-menu')[0];
|
||||||
|
// Fake a right-click
|
||||||
|
doc.popupNode = parent;
|
||||||
|
menupopup.openPopup(
|
||||||
|
parent, "after_start", 0, 0, true, false, new MouseEvent('click', { button: 2 })
|
||||||
|
);
|
||||||
|
var menuitem = menupopup.getElementsByTagName('menuitem')[0];
|
||||||
|
menuitem.click();
|
||||||
|
yield waitForItemEvent('modify');
|
||||||
|
|
||||||
|
var creator = item.getCreators()[0];
|
||||||
|
assert.propertyVal(creator, 'firstName', 'Last');
|
||||||
|
assert.propertyVal(creator, 'lastName', 'First');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it("shouldn't show Swap Names menu for single-field mode", function* () {
|
||||||
|
var item = new Zotero.Item('book');
|
||||||
|
item.setCreators([
|
||||||
|
{
|
||||||
|
name: "Name",
|
||||||
|
creatorType: "author"
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
yield item.saveTx();
|
||||||
|
|
||||||
|
var itemBox = doc.getElementById('zotero-editpane-item-box');
|
||||||
|
var label = doc.getAnonymousNodes(itemBox)[0].getElementsByAttribute('fieldname', 'creator-0-lastName')[0];
|
||||||
|
assert.isFalse(label.parentNode.hasAttribute('contextmenu'));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Note: This issue applies to all context menus in the item box (text transform, name swap),
|
||||||
|
// though the others aren't tested. This might go away with the XUL->HTML transition.
|
||||||
|
it.skip("should save open field after changing creator type", function* () {
|
||||||
|
var item = new Zotero.Item('book');
|
||||||
|
item.setCreators([
|
||||||
|
{
|
||||||
|
firstName: "First",
|
||||||
|
lastName: "Last",
|
||||||
|
creatorType: "author"
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
var id = yield item.saveTx();
|
||||||
|
|
||||||
|
var itemBox = doc.getElementById('zotero-editpane-item-box');
|
||||||
|
var label = doc.getAnonymousNodes(itemBox)[0].getElementsByAttribute('fieldname', 'place')[1];
|
||||||
|
label.click();
|
||||||
|
var textbox = doc.getAnonymousNodes(itemBox)[0].getElementsByAttribute('fieldname', 'place')[1];
|
||||||
|
textbox.value = "Place";
|
||||||
|
|
||||||
|
var menuLabel = doc.getAnonymousNodes(itemBox)[0].getElementsByAttribute('fieldname', 'creator-0-typeID')[0];
|
||||||
|
menuLabel.click();
|
||||||
|
var menupopup = itemBox._creatorTypeMenu;
|
||||||
|
var menuItems = menupopup.getElementsByTagName('menuitem');
|
||||||
|
menuItems[1].click();
|
||||||
|
yield waitForItemEvent('modify');
|
||||||
|
|
||||||
|
assert.equal(item.getField('place'), 'Place');
|
||||||
|
assert.equal(Zotero.CreatorTypes.getName(item.getCreators()[0].creatorTypeID), 'contributor');
|
||||||
|
|
||||||
|
// Wait for no-op saveTx()
|
||||||
|
yield Zotero.Promise.delay(1);
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("Attachment pane", function () {
|
describe("Attachment pane", function () {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user