2017-10-03 14 views
0

J'ai un composant qui enveloppe un Wicket TextField qui, lors de la mise à jour, je valide son contenu via une autre classe externe responsable de la validation du modèle.Wicket 6: la position du curseur TextField se déplace lorsque le composant est mis à jour

Si le contenu n'est pas valide, je mets à jour le composant wrapper pour afficher une erreur.

Cela a pour effet de mettre à jour le TextField encapsulé.

Le problème est que lorsque cette mise à jour se produit le curseur dans le champ de texte passe à la position 0.

Par « mise à jour », je veux dire que je suis d'ajouter le composant TextField (ou d'un composant de conteneur parent/Panel) à un AjaxRequestTarget pour la mise à jour.

Y a-t-il un moyen [sympa] d'empêcher ce saut de curseur de se produire et de le laisser juste où il est?

+0

peut vous envoyer le code aussi? – soorapadman

+0

Quel événement JavaScript initie la validation? – svenmeier

+0

Pour clarifier, si le curseur dans le champ de texte est dit, à mi-chemin entre le texte, puis pour une raison quelconque j'ajoute ce composant TextField à un AjaxRequestTarget pour la mise à jour, le curseur saute alors à la position 0 dans le texte. @svenmeier - Javascript ne lance pas la validation - une capture du comportement FormComponentUpdate fait (onUpdate) –

Répondre

1

On dirait que je ne cherchais pas autour assez dur - je peux pointer vers une solution trouvée ici:

http://apache-wicket.1842946.n4.nabble.com/TextField-cursor-reset-mid-editing-td4668582.html

Plus précisément, le poste plus par:

ChambreNoire 4 décembre 2014 ; 4:19 pm Re: FIXED: TextField curseur reset mi-édition

Cela a fonctionné pour moi bien, mais juste pour noter que vous ne devez pas forcer une mise à jour du composant si le contenu du texte du modèle TextField n'a pas changé, Sinon, lorsque vous sélectionnez un texte par la méthode du clavier (touches de déplacement + flèches, etc.), la sélection échouera et le curseur reviendra à la position qui était la sienne avant la sélection.

En fait, étant donné que les messages du forum ont tendance à disparaître, voici le texte du message ci-dessous:

OK so this is what I have. Disclaimer: I'm no javascript/jQuery expert so this is mostly cobbled together from things I have found online and tested in my particular situation. Any optimisations are more than welcome! 

So first the script 

(function($) { 
$.fn.getCaretPosition = function() { 
    var input = this.get(0); 
    if (!input) return; // No (input) element found 
    if ('selectionStart' in input) { 
     // Standard-compliant browsers 
     return input.selectionStart; 
    } else if (document.selection) { 
     // IE 
     input.focus(); 
     var sel = document.selection.createRange(); 
     var selLen = document.selection.createRange().text.length; 
     sel.moveStart('character', -input.value.length); 
     return sel.text.length - selLen; 
    } 
}; 
$.fn.setCaretPosition = function(position) { 
    var input = this.get(0); 
    if (!input) return false; // No (input) element found 

    input.value = input.value; 
    //^this is used to not only get "focus", but 
    // to make sure we don't have it everything -selected- 
    // (it causes an issue in chrome, and having it doesn't hurt any other browser) 

    if (input.createTextRange) { 
     var range = input.createTextRange(); 
     range.move('character', position); 
     range.select(); 
     return true; 
    } else { 
     // (input.selectionStart === 0 added for Firefox bug) 
     if (input.selectionStart || input.selectionStart === 0) { 
      input.focus(); 
      input.setSelectionRange(position, position); 
      return true; 
     } else { // fail city, fortunately this never happens (as far as I've tested) :) 
      input.focus(); 
      return false; 
     } 
    } 
} 
})(jQuery); 

Then I add the following behavior to my TextField : 

add(new AjaxFormComponentUpdatingBehavior("onkeyup") { 

@Override 
protected void onUpdate(AjaxRequestTarget target) { 

    String id = getComponent().getMarkupId(); 

    String caret = id + "_caretPosition"; 
    String selector = "$('#" + id + "')"; 

    target.prependJavaScript("var $s = " + selector + ";if($s[0]===document.activeElement){" + 
      "jQuery.data(document,'" + caret + "'," + selector + ".getCaretPosition());}"); 

    onFieldUpdate(getFormComponent(), target); 

    target.appendJavaScript("var $p = jQuery.data(document,'" + caret + "');" + 
      "if($p!=undefined){" + selector + ".setCaretPosition($p);" + 
      "jQuery.removeData(document,'" + caret + "');}"); 
} 

@Override 
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) { 
    super.updateAjaxAttributes(attributes); 

    String id = getFormComponent().getMarkupId() + "_onkeyup"; 

    attributes.setThrottlingSettings(new ThrottlingSettings(id, seconds(1), true)); 
} 
}); 

So this gets round the 'zapping focus back to the original field after hitting tab' issue I experienced as the behavior will be called a bit after I hit tab due to the throttle settings but that won't affect whether the field is focused or not (it won't regain focus). So I can check this and bypass the whole thing if the field isn't focused simply by not storing the caret position and consequently not re-setting it. 

You'll notice I'm storing the caretPosition in 'document' using jQuery.data(). There's probably a more 'js/jquery best practices' way to do this. I should also be clearing the position once I set it (thinking out loud) so I'll add that above. 

CN