Fix post-save textbox focusing bugs in right-hand pane

Fix a couple cases of lost text field focus after an edit, including
focusing of the Title field after using New Item when a field is already
being edited and has a changed value.

Also, in tests, select My Library and wait for items to load when using
the loadZoteroPane() support function. We could add a parameter to skip
that or move it to a separate function, but the code to detect it is a
bit convoluted and it's a prerequisite for many tests, so it's handy to
have a function for it.
This commit is contained in:
Dan Stillman 2015-05-04 02:00:52 -04:00
parent 590649fd49
commit 8fec5ace3a
7 changed files with 103 additions and 63 deletions

View File

@ -1682,8 +1682,6 @@
<parameter name="textbox"/>
<body><![CDATA[
return Zotero.spawn(function* () {
if (textbox.localName == 'textarea') return;
Zotero.debug('Hiding editor');
// Prevent autocomplete breakage in Firefox 3
@ -1785,11 +1783,7 @@
}
}
elem = this.createValueElement(
val,
fieldName,
tabindex
);
var newVal = val;
}
// Fields
@ -1854,18 +1848,23 @@
}
}
this._modifyField(fieldName, value, this.saveOnEdit);
yield this._modifyField(fieldName, value, this.saveOnEdit);
var newVal = this.item.getField(fieldName);
}
// If box is still open (due to field not being modified and there not being
// a refresh), close it manually
if (textbox && textbox.parentNode) {
elem = this.createValueElement(
this.item.getField(fieldName),
fieldName,
tabindex
);
var box = textbox.parentNode;
box.replaceChild(elem,textbox);
}
var box = textbox.parentNode;
box.replaceChild(elem,textbox);
if(field === 'creator') {
// Reset creator mode settings here so that flex attribute gets reset
this.switchCreatorMode(row, (otherFields.fieldMode ? 1 : 0), true);
@ -1912,14 +1911,14 @@
<parameter name="field"/>
<parameter name="value"/>
<parameter name="save"/>
<body>
<![CDATA[
this.item.setField(field,value);
if (save) {
this.item.save();
}
]]>
</body>
<body><![CDATA[
return Zotero.spawn(function* () {
this.item.setField(field, value);
if (save) {
yield this.item.save();
}
}, this);
]]></body>
</method>
@ -1973,8 +1972,7 @@
throw ("Invalid transform mode '" + mode + "' in zoteroitembox.textTransform()");
}
this._setFieldValue(label, newVal);
this._modifyField(label.getAttribute('fieldname'), newVal, this.saveOnEdit);
this._modifyField(label.getAttribute('fieldname'), newVal, this.saveOnEdit).done();
]]>
</body>
</method>
@ -2204,7 +2202,7 @@
return Zotero.spawn(function* () {
var textboxes = document.getAnonymousNodes(this)[0].getElementsByTagName('textbox');
if (textboxes && textboxes.length) {
yield this.blurHandler(textboxes[0].inputField);
yield this.blurHandler(textboxes[0]);
}
}, this);
]]></body>

View File

@ -153,6 +153,23 @@ var ZoteroItemPane = new function() {
});
this.blurOpenField = Zotero.Promise.coroutine(function* () {
var tabBox = document.getElementById('zotero-view-tabbox');
switch (tabBox.selectedIndex) {
case 0:
var box = _itemBox;
break;
case 2:
var box = _tagsBox;
break;
}
if (box) {
yield box.blurOpenField();
}
});
this.addNote = function (popup) {
ZoteroPane_Local.newNote(popup, _lastItem.key);
}

View File

@ -751,6 +751,8 @@ var ZoteroPane = new function()
}
}
yield ZoteroItemPane.blurOpenField();
if (row !== undefined && row !== null) {
var collectionTreeRow = this.collectionsView.getRow(row);
var libraryID = collectionTreeRow.ref.libraryID;

View File

@ -32,20 +32,30 @@ function loadBrowserWindow() {
}
/**
* Loads a Zotero pane in a new window. Returns the containing window.
* Loads a Zotero pane in a new window and selects My Library. Returns the containing window.
*/
function loadZoteroPane() {
return loadBrowserWindow().then(function(win) {
win.ZoteroOverlay.toggleDisplay(true);
// Hack to wait for pane load to finish. This is the same hack
// we use in ZoteroPane.js, so either it's not good enough
// there or it should be good enough here.
return Zotero.Promise.delay(52).then(function() {
return win;
});
});
}
var loadZoteroPane = Zotero.Promise.coroutine(function* () {
var win = yield loadBrowserWindow();
win.ZoteroOverlay.toggleDisplay(true);
// Hack to wait for pane load to finish. This is the same hack
// we use in ZoteroPane.js, so either it's not good enough
// there or it should be good enough here.
yield Zotero.Promise.delay(52);
var zp = win.ZoteroPane;
var cv = zp.collectionsView;
var resolve1, resolve2;
var promise1 = new Zotero.Promise(() => resolve1 = arguments[0]);
var promise2 = new Zotero.Promise(() => resolve2 = arguments[0]);
cv.addEventListener('load', () => resolve1())
yield promise1;
cv.selection.select(0);
zp.addEventListener('itemsLoaded', () => resolve2());
yield promise2;
return win;
});
/**
* Waits for a window with a specific URL to open. Returns a promise for the window.

View File

@ -4,22 +4,10 @@ describe("Zotero.CollectionTreeView", function() {
// Load Zotero pane and select library
before(function* () {
win = yield loadZoteroPane();
var zp = win.ZoteroPane;
var cv = zp.collectionsView;
var resolve1, resolve2;
var promise1 = new Zotero.Promise(() => resolve1 = arguments[0]);
var promise2 = new Zotero.Promise(() => resolve2 = arguments[0]);
cv.addEventListener('load', () => resolve1())
yield promise1;
cv.selection.select(0);
zp.addEventListener('itemsLoaded', () => resolve2());
yield promise2;
collectionsView = zp.collectionsView;
collectionsView = win.ZoteroPane.collectionsView;
});
after(function () {
if (win) {
win.close();
}
win.close();
});
// Select library

View File

@ -4,25 +4,13 @@ describe("Zotero.ItemTreeView", function() {
// Load Zotero pane and select library
before(function* () {
win = yield loadZoteroPane();
var zp = win.ZoteroPane;
var cv = zp.collectionsView;
var resolve1, resolve2;
var promise1 = new Zotero.Promise(() => resolve1 = arguments[0]);
var promise2 = new Zotero.Promise(() => resolve2 = arguments[0]);
cv.addEventListener('load', () => resolve1())
yield promise1;
cv.selection.select(0);
zp.addEventListener('itemsLoaded', () => resolve2());
yield promise2;
itemsView = zp.itemsView;
itemsView = win.ZoteroPane.itemsView;
var item = new Zotero.Item('book');
existingItemID = yield item.save();
});
after(function () {
if (win) {
win.close();
}
win.close();
});
describe("#selectItem()", function () {

View File

@ -0,0 +1,37 @@
describe("ZoteroPane", function() {
var win, doc, zp;
// Load Zotero pane and select library
before(function* () {
win = yield loadZoteroPane();
doc = win.document;
zp = win.ZoteroPane;
});
after(function () {
win.close();
});
describe("#newItem", function () {
it("should create an item and focus the title field", function* () {
yield zp.newItem(Zotero.ItemTypes.getID('book'), {}, null, true);
var itemBox = doc.getElementById('zotero-editpane-item-box');
var textboxes = doc.getAnonymousNodes(itemBox)[0].getElementsByTagName('textbox');
assert.lengthOf(textboxes, 1);
assert.equal(textboxes[0].getAttribute('fieldname'), 'title');
textboxes[0].blur();
yield Zotero.Promise.delay(1);
})
it("should save an entered value when New Item is used", function* () {
var value = "Test";
var item = yield zp.newItem(Zotero.ItemTypes.getID('book'), {}, null, true);
var itemBox = doc.getElementById('zotero-editpane-item-box');
var textbox = doc.getAnonymousNodes(itemBox)[0].getElementsByTagName('textbox')[0];
textbox.value = value;
yield itemBox.blurOpenField();
item = yield Zotero.Items.getAsync(item.id);
assert.equal(item.getField('title'), value);
})
});
})