fix(apk): le formulaire garde la vue 'detail', sinon chaque champ perdait le focus
Un gardien defocalise tout ce qui prend le focus hors de l'ecran courant, en comparant 'view' a l'identifiant de l'ecran. Le formulaire vit dans l'ecran 'detail' ; poser view='edit' le faisait donc blurer a chaque focusin - clavier ouvert, pas de curseur, rien ne rentrait. Un drapeau 'editing' dit desormais qu'on modifie, et 'view' continue de nommer l'ecran. Mesure au protocole DevTools sur le telephone : le champ etait bien atteignable et focalise, ce qui a elimine le DOM et le CSS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1076,6 +1076,7 @@ function renderDetail(d) {
|
|||||||
document.getElementById('kebab').hidden = false;
|
document.getElementById('kebab').hidden = false;
|
||||||
document.getElementById('pencil').hidden = false;
|
document.getElementById('pencil').hidden = false;
|
||||||
document.getElementById('dav').hidden = true;
|
document.getElementById('dav').hidden = true;
|
||||||
|
editing = false;
|
||||||
var html = '', i;
|
var html = '', i;
|
||||||
if (d.totp)
|
if (d.totp)
|
||||||
html += '<div class="field totp" id="totp"><div class="cap">2FA code</div>'
|
html += '<div class="field totp" id="totp"><div class="cap">2FA code</div>'
|
||||||
@@ -1398,6 +1399,7 @@ function openNewEntry() {
|
|||||||
// reutilise pour la creation, et son menu proposait Duplicate et Delete -
|
// reutilise pour la creation, et son menu proposait Duplicate et Delete -
|
||||||
// qui, cote Delphi, visent la derniere entree ouverte.
|
// qui, cote Delphi, visent la derniere entree ouverte.
|
||||||
closeMenu();
|
closeMenu();
|
||||||
|
editing = false;
|
||||||
document.getElementById('kebab').hidden = true;
|
document.getElementById('kebab').hidden = true;
|
||||||
document.getElementById('pencil').hidden = true;
|
document.getElementById('pencil').hidden = true;
|
||||||
document.getElementById('dav').hidden = true;
|
document.getElementById('dav').hidden = true;
|
||||||
@@ -1525,6 +1527,10 @@ function openMenu() {
|
|||||||
/// Ce que le formulaire porte a cet instant, par nom de champ. Sert a le
|
/// Ce que le formulaire porte a cet instant, par nom de champ. Sert a le
|
||||||
/// rouvrir tel quel apres une action d'icone, qui passe par un enregistrement.
|
/// rouvrir tel quel apres une action d'icone, qui passe par un enregistrement.
|
||||||
var editAgain = null;
|
var editAgain = null;
|
||||||
|
/// Le formulaire occupe l'ecran du detail : 'view' reste donc 'detail', et
|
||||||
|
/// c'est ce drapeau qui dit qu'on y modifie - la fleche et la touche retour
|
||||||
|
/// s'en servent pour refermer le formulaire avant de quitter l'entree.
|
||||||
|
var editing = false;
|
||||||
|
|
||||||
function collectEditValues() {
|
function collectEditValues() {
|
||||||
var ins = document.querySelectorAll('#fields [data-ef]'), m = {}, i;
|
var ins = document.querySelectorAll('#fields [data-ef]'), m = {}, i;
|
||||||
@@ -1558,13 +1564,12 @@ function openEditEntry() {
|
|||||||
+ (r.m ? ' wrap' : '') + '">'
|
+ (r.m ? ' wrap' : '') + '">'
|
||||||
+ (r.e === 'folder' ? folderSelect(r.v) : r.m
|
+ (r.e === 'folder' ? folderSelect(r.v) : r.m
|
||||||
? '<textarea class="field-in" data-ef="' + esc(r.e) + '" rows="5"'
|
? '<textarea class="field-in" data-ef="' + esc(r.e) + '" rows="5"'
|
||||||
+ ' autocorrect="off" spellcheck="false" style="' + FIELD_STYLE
|
+ ' enterkeyhint="enter" autocorrect="off" spellcheck="false"'
|
||||||
+ ';height:auto;resize:vertical">' + esc(r.v) + '</textarea>'
|
+ ' style="' + FIELD_STYLE + ';height:auto;resize:vertical"></textarea>'
|
||||||
: '<input class="field-in"' + (r.e === 'password' ? ' id="editpwd"' : '')
|
: '<input class="field-in"' + (r.e === 'password' ? ' id="editpwd"' : '')
|
||||||
+ ' data-ef="' + esc(r.e) + '" type="text"'
|
+ ' data-ef="' + esc(r.e) + '" type="text"'
|
||||||
+ ' autocomplete="off" autocorrect="off" autocapitalize="none"'
|
+ ' autocomplete="off" autocorrect="off" autocapitalize="none"'
|
||||||
+ ' spellcheck="false" style="' + FIELD_STYLE + '" value="'
|
+ ' spellcheck="false" style="' + FIELD_STYLE + '">')
|
||||||
+ esc(r.v) + '">')
|
|
||||||
+ (r.e === 'password' ? genButton('editpwd') : '')
|
+ (r.e === 'password' ? genButton('editpwd') : '')
|
||||||
+ '</div></div>';
|
+ '</div></div>';
|
||||||
}
|
}
|
||||||
@@ -1577,11 +1582,20 @@ function openEditEntry() {
|
|||||||
+ '<button class="btn main wide" id="eSave" style="flex:1">Save</button>'
|
+ '<button class="btn main wide" id="eSave" style="flex:1">Save</button>'
|
||||||
+ '</div>';
|
+ '</div>';
|
||||||
document.getElementById('fields').innerHTML = html;
|
document.getElementById('fields').innerHTML = html;
|
||||||
|
// Les valeurs APRES le rendu, jamais en attribut : c'est ainsi que
|
||||||
|
// procedait l'editeur d'une ligne, qui acceptait la frappe.
|
||||||
|
var fill = document.querySelectorAll('#fields [data-ef]'), fi, fe;
|
||||||
|
for (fi = 0; fi < fill.length; fi++) {
|
||||||
|
fe = fill[fi].getAttribute('data-ef');
|
||||||
|
for (var fk = 0; fk < detailRows.length; fk++)
|
||||||
|
if (detailRows[fk].e === fe && fill[fi].tagName !== 'SELECT')
|
||||||
|
fill[fi].value = detailRows[fk].v;
|
||||||
|
}
|
||||||
document.getElementById('eCancel').addEventListener('click', function () {
|
document.getElementById('eCancel').addEventListener('click', function () {
|
||||||
renderDetail(lastDetail);
|
renderDetail(lastDetail);
|
||||||
});
|
});
|
||||||
document.getElementById('eSave').addEventListener('click', saveEditEntry);
|
document.getElementById('eSave').addEventListener('click', saveEditEntry);
|
||||||
view = 'edit';
|
editing = true;
|
||||||
if (editAgain) {
|
if (editAgain) {
|
||||||
var ins = document.querySelectorAll('#fields [data-ef]'), i, f;
|
var ins = document.querySelectorAll('#fields [data-ef]'), i, f;
|
||||||
for (i = 0; i < ins.length; i++) {
|
for (i = 0; i < ins.length; i++) {
|
||||||
@@ -1590,7 +1604,9 @@ function openEditEntry() {
|
|||||||
}
|
}
|
||||||
editAgain = null;
|
editAgain = null;
|
||||||
}
|
}
|
||||||
send('touch');
|
// MEME SORTIE QUE LA CREATION, qui elle accepte la frappe : c'est le seul
|
||||||
|
// appel qui differait a l'ouverture du formulaire.
|
||||||
|
send('state?view=detail');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// UN SEUL ENVOI, ET SEULEMENT CE QUI A CHANGE : le reste du coffre n'a pas a
|
/// UN SEUL ENVOI, ET SEULEMENT CE QUI A CHANGE : le reste du coffre n'a pas a
|
||||||
@@ -1969,6 +1985,7 @@ function goList() {
|
|||||||
document.body.classList.remove('on-detail');
|
document.body.classList.remove('on-detail');
|
||||||
document.body.classList.add('on-list');
|
document.body.classList.add('on-list');
|
||||||
view = 'list';
|
view = 'list';
|
||||||
|
editing = false;
|
||||||
// Les valeurs en clair partent avec la vue, pas seulement de l'ecran.
|
// Les valeurs en clair partent avec la vue, pas seulement de l'ecran.
|
||||||
detailRows = [];
|
detailRows = [];
|
||||||
document.getElementById('fields').innerHTML = '';
|
document.getElementById('fields').innerHTML = '';
|
||||||
@@ -1977,7 +1994,7 @@ function goList() {
|
|||||||
// LA FLECHE REFERME D'ABORD LE FORMULAIRE. Elle ramenait a la liste, donc une
|
// LA FLECHE REFERME D'ABORD LE FORMULAIRE. Elle ramenait a la liste, donc une
|
||||||
// modification en cours disparaissait sans qu'on ait vu l'entree.
|
// modification en cours disparaissait sans qu'on ait vu l'entree.
|
||||||
document.getElementById('back').addEventListener('click', function () {
|
document.getElementById('back').addEventListener('click', function () {
|
||||||
if (view === 'edit') { renderDetail(lastDetail); return; }
|
if (editing) { renderDetail(lastDetail); return; }
|
||||||
goList();
|
goList();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2227,7 +2244,7 @@ var PM = {
|
|||||||
// Touche retour du telephone : le formulaire d'abord, la liste ensuite.
|
// Touche retour du telephone : le formulaire d'abord, la liste ensuite.
|
||||||
// Delphi ne connait que 'detail' - la page seule sait qu'elle edite.
|
// Delphi ne connait que 'detail' - la page seule sait qu'elle edite.
|
||||||
back: function () {
|
back: function () {
|
||||||
if (view === 'edit') { renderDetail(lastDetail); return; }
|
if (editing) { renderDetail(lastDetail); return; }
|
||||||
if (view === 'detail') goList();
|
if (view === 'detail') goList();
|
||||||
},
|
},
|
||||||
cancelEdit: function () { renderDetail(lastDetail); },
|
cancelEdit: function () { renderDetail(lastDetail); },
|
||||||
|
|||||||
Reference in New Issue
Block a user