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:
parent
590649fd49
commit
8fec5ace3a
|
@ -1682,8 +1682,6 @@
|
||||||
<parameter name="textbox"/>
|
<parameter name="textbox"/>
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
return Zotero.spawn(function* () {
|
return Zotero.spawn(function* () {
|
||||||
if (textbox.localName == 'textarea') return;
|
|
||||||
|
|
||||||
Zotero.debug('Hiding editor');
|
Zotero.debug('Hiding editor');
|
||||||
|
|
||||||
// Prevent autocomplete breakage in Firefox 3
|
// Prevent autocomplete breakage in Firefox 3
|
||||||
|
@ -1785,11 +1783,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
elem = this.createValueElement(
|
var newVal = val;
|
||||||
val,
|
|
||||||
fieldName,
|
|
||||||
tabindex
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fields
|
// 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(
|
elem = this.createValueElement(
|
||||||
this.item.getField(fieldName),
|
this.item.getField(fieldName),
|
||||||
fieldName,
|
fieldName,
|
||||||
tabindex
|
tabindex
|
||||||
);
|
);
|
||||||
|
var box = textbox.parentNode;
|
||||||
|
box.replaceChild(elem,textbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
var box = textbox.parentNode;
|
|
||||||
box.replaceChild(elem,textbox);
|
|
||||||
|
|
||||||
if(field === 'creator') {
|
if(field === 'creator') {
|
||||||
// Reset creator mode settings here so that flex attribute gets reset
|
// Reset creator mode settings here so that flex attribute gets reset
|
||||||
this.switchCreatorMode(row, (otherFields.fieldMode ? 1 : 0), true);
|
this.switchCreatorMode(row, (otherFields.fieldMode ? 1 : 0), true);
|
||||||
|
@ -1912,14 +1911,14 @@
|
||||||
<parameter name="field"/>
|
<parameter name="field"/>
|
||||||
<parameter name="value"/>
|
<parameter name="value"/>
|
||||||
<parameter name="save"/>
|
<parameter name="save"/>
|
||||||
<body>
|
<body><![CDATA[
|
||||||
<![CDATA[
|
return Zotero.spawn(function* () {
|
||||||
this.item.setField(field,value);
|
this.item.setField(field, value);
|
||||||
if (save) {
|
if (save) {
|
||||||
this.item.save();
|
yield this.item.save();
|
||||||
}
|
}
|
||||||
]]>
|
}, this);
|
||||||
</body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1973,8 +1972,7 @@
|
||||||
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);
|
this._modifyField(label.getAttribute('fieldname'), newVal, this.saveOnEdit).done();
|
||||||
|
|
||||||
]]>
|
]]>
|
||||||
</body>
|
</body>
|
||||||
</method>
|
</method>
|
||||||
|
@ -2204,7 +2202,7 @@
|
||||||
return Zotero.spawn(function* () {
|
return Zotero.spawn(function* () {
|
||||||
var textboxes = document.getAnonymousNodes(this)[0].getElementsByTagName('textbox');
|
var textboxes = document.getAnonymousNodes(this)[0].getElementsByTagName('textbox');
|
||||||
if (textboxes && textboxes.length) {
|
if (textboxes && textboxes.length) {
|
||||||
yield this.blurHandler(textboxes[0].inputField);
|
yield this.blurHandler(textboxes[0]);
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
]]></body>
|
]]></body>
|
||||||
|
|
|
@ -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) {
|
this.addNote = function (popup) {
|
||||||
ZoteroPane_Local.newNote(popup, _lastItem.key);
|
ZoteroPane_Local.newNote(popup, _lastItem.key);
|
||||||
}
|
}
|
||||||
|
|
|
@ -751,6 +751,8 @@ var ZoteroPane = new function()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yield ZoteroItemPane.blurOpenField();
|
||||||
|
|
||||||
if (row !== undefined && row !== null) {
|
if (row !== undefined && row !== null) {
|
||||||
var collectionTreeRow = this.collectionsView.getRow(row);
|
var collectionTreeRow = this.collectionsView.getRow(row);
|
||||||
var libraryID = collectionTreeRow.ref.libraryID;
|
var libraryID = collectionTreeRow.ref.libraryID;
|
||||||
|
|
|
@ -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() {
|
var loadZoteroPane = Zotero.Promise.coroutine(function* () {
|
||||||
return loadBrowserWindow().then(function(win) {
|
var win = yield loadBrowserWindow();
|
||||||
win.ZoteroOverlay.toggleDisplay(true);
|
win.ZoteroOverlay.toggleDisplay(true);
|
||||||
|
|
||||||
// Hack to wait for pane load to finish. This is the same hack
|
// 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
|
// we use in ZoteroPane.js, so either it's not good enough
|
||||||
// there or it should be good enough here.
|
// there or it should be good enough here.
|
||||||
return Zotero.Promise.delay(52).then(function() {
|
yield Zotero.Promise.delay(52);
|
||||||
return win;
|
|
||||||
});
|
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.
|
* Waits for a window with a specific URL to open. Returns a promise for the window.
|
||||||
|
|
|
@ -4,22 +4,10 @@ describe("Zotero.CollectionTreeView", function() {
|
||||||
// Load Zotero pane and select library
|
// Load Zotero pane and select library
|
||||||
before(function* () {
|
before(function* () {
|
||||||
win = yield loadZoteroPane();
|
win = yield loadZoteroPane();
|
||||||
var zp = win.ZoteroPane;
|
collectionsView = win.ZoteroPane.collectionsView;
|
||||||
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;
|
|
||||||
});
|
});
|
||||||
after(function () {
|
after(function () {
|
||||||
if (win) {
|
win.close();
|
||||||
win.close();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Select library
|
// Select library
|
||||||
|
|
|
@ -4,25 +4,13 @@ describe("Zotero.ItemTreeView", function() {
|
||||||
// Load Zotero pane and select library
|
// Load Zotero pane and select library
|
||||||
before(function* () {
|
before(function* () {
|
||||||
win = yield loadZoteroPane();
|
win = yield loadZoteroPane();
|
||||||
var zp = win.ZoteroPane;
|
itemsView = win.ZoteroPane.itemsView;
|
||||||
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;
|
|
||||||
|
|
||||||
var item = new Zotero.Item('book');
|
var item = new Zotero.Item('book');
|
||||||
existingItemID = yield item.save();
|
existingItemID = yield item.save();
|
||||||
});
|
});
|
||||||
after(function () {
|
after(function () {
|
||||||
if (win) {
|
win.close();
|
||||||
win.close();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#selectItem()", function () {
|
describe("#selectItem()", function () {
|
||||||
|
|
37
test/tests/zoteroPaneTest.js
Normal file
37
test/tests/zoteroPaneTest.js
Normal 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);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user