Il s'agit de donner à la liste des villes le comportement suivant :
la méthode addSelector permet d'ajouter le contrôle clavier sur la liste : le code de touche 113 correspond à la touche F2, et permet l'édition d'une ville : voir http://tutorial.kobject.net/java/ajaxinclude/keyboard
{#func:this.addSelector(113)#}
{#func:this.setEditable(true)#}
{#mask:<td>{cp}</td><td>{ville}</td>#}
{#mask:<td>{cp}</td><td>{ville}</td>#}
{#set:this.ajaxIncludes=true#}
{#set:this.listContentUrl="villes.do"#}
{_ajx}
{_listContent}
{_page}
<div class="boxButtons">{_pageCounter}{_navBarre}</div>
{/_listContent}
| Action | Effet |
|---|---|
| F2 | Edition avec le formulaire de modification (il s'agit de la seule touche paramétrable) |
| Touches de direction Haut, bas, gauche, droite | Déplacement entre les villes |
| MAJ+Home | Atteindre la première page |
| MAJ+Fin | Atteindre la dernière page |
| MAJ+PageUp | Page précédente |
| MAJ+PageDown | Page suivante |
| Double clic | Déplacement sélection ligne |
{#func:this.addSelector(113)#}
{#func:this.setEditable(false)#}
...
Pour qu'un membre soit éditable, il faut qu'il appartienne à un élément DOM de la classe editable.
Nous allons ajouter un Display associé à la classe KVille pour modifier l'affichage des éléments de la liste :
La méthode showInList à surdéfinir gère l'affichage de chaque membre de la liste.
package net.display;
import net.ko.displays.KObjectDisplay;
import net.ko.kobject.KObject;
public class VilleDisplay extends KObjectDisplay {
@Override
public String showInList(KObject ko, String memberName) {
String result=super.showInList(ko, memberName);
//si le nom du membre est cp ou ville, on le met dans un span de classe css editable
if("cp".equals(memberName) || "ville".equals(memberName)){
result="<span class='editable' title='"+memberName+"'>"+result+"</span>";
}
return result;
}
}
... <class name="KVille" display="net.display.VilleDisplay"> <member max="5" name="cp" required="1" type="string" /> <member max="100" name="ville" required="1" type="string" transform="onlyFirstWordUpper"/> </class> ...
| Action | Effet |
|---|---|
| Double clic | Mode édition du membre |
| ESCAPE | Sortie de l'édition |
| ENTREE | Sortie avec possible validation |
| Perte du focus | Sortie de l'édition |
target correspond à l'élément DOM qui a reçu l'événement :
<ajax-includes>
...
<request requestURL="villes.do">
<js triggerSelector=".editable" triggerEvent="updated">
<updateOne virtualURL="updateVille.do" operation="update" kobjectShortClassName="KVille" targetId="info" method="POST">
<field name="{js:target.title}" value="{js:target.innerHTML}"/>
</updateOne>
</js>
</request>
...
<ajax-includes>
<mappings> ... <virtualMapping requestURL="updateVille.do" mappingFor="updateOne"/> ... </mappings>
Le champ supplémentaire devra afficher le nombre actuel d'entreprise(s) de la ville, dans un lien cliquable qui devra ensuite afficher la liste des entreprises de la ville.
...
public KVille() {
super();
hasMany(KEntreprise.class);
}
...
{#func:this.setEditable(false)#}
{#func:this.addSelector(113)#}
{#mask:<td>{cp}</td><td>{ville}</td><td>{btDetail}</td>#}
{#mask:<td>{cp}</td><td>{ville}</td><td>{btDetail}</td>#}
{#set:this.ajaxIncludes=true#}
{#set:this.listContentUrl="villes.do"#}
{_ajx}
{_listContent}
{_page}
<div class="boxButtons">{_pageCounter}{_navBarre}</div>
{/_listContent}
* Modifier le Display de la classe KVille, VilleDisplay, pour qu'il gère l'affichage de btDetail :
public class VilleDisplay extends KObjectDisplay {
@Override
public String showInList(KObject ko, String memberName) {
String result=super.showInList(ko, memberName);
if("cp".equals(memberName) || "ville".equals(memberName)){
result="<span class='editable' title='"+memberName+"'>"+result+"</span>";
}
if("btDetail".equals(memberName)){
KVille ville=(KVille) ko;
int nb=ville.getEntreprises().count();
if(nb>0)
result="<div><a id='alink-"+ville.getId()+"' class='default' title='Entreprises de "+ville.getVille()+"'>"+KString.pluriel(ville.getEntreprises().count(),"entreprise")+"</a></div>";
else
result="<div>"+KString.pluriel(ville.getEntreprises().count(),"entreprise")+"</div>";
}
return result;
}
}
{#func:this.setEditable(false)#}
{#func:this.addSelector(113)#}
{#mask:<td>{cp}</td><td>{ville}</td><td>{btDetail}</td>#}
{#mask:<td>{cp}</td><td>{ville}</td><td>{btDetail}</td>#}
{#set:this.ajaxIncludes=true#}
{#set:this.listContentUrl="villes.do"#}
{_ajx}
{_listContent}
{_page}
<div class="boxButtons">{_pageCounter}{_navBarre}</div>
{/_listContent}
<div id="divEntreprises"></div>
{#koDisplay:net.display.EntrepriseVilleDisplay#}
{#mask:<td>{rs}</td><td>{adresse}</td><td>{tel}</td>#}
{#mask:<td>{rs}</td><td>{adresse}</td><td>{tel}</td>#}
<fieldset>
<legend>%ville%</legend>
{_ajx}
{_listContent}
{_page}
{/_listContent}
</fieldset>
Le display va permettre de filtrer les entreprises de la liste, pour ne faire apparaître que les entreprises de la ville sélectionnée :
Surdéfinir la méthode beforeLoading de la façon suivante :
package net.display;
import javax.servlet.http.HttpServletRequest;
import net.ko.displays.KObjectDisplay;
import net.ko.http.objects.KRequest;
import net.ko.http.views.KPageList;
import net.ko.kobject.KObject;
public class EntrepriseVilleDisplay extends KObjectDisplay {
@Override
public void beforeLoading(Class<? extends KObject> clazz, KPageList list,
HttpServletRequest request) {
list.addWhere("idVille='"+KRequest.GET("idVille", request, "-1")+"'");
}
}
<mappings> ... <mapping requestURL="entrepParVille.do" responseURL="/WEB-INF/list/ville/entreprise.list"/> ... </mappings>
<ajax-includes>
...
<request requestURL="villes.do">
...
<js triggerSelector="a.default" triggerEvent="click">
<include targetURL="entrepParVille.do" targetParams="idVille={js:$vId(target.id)},ville={js:target.title}" targetId="divEntreprises"></include>
</js>
</request>
</ajax-includes>
<ajax-includes>
...
<request requestURL="villes.do">
...
<js triggerSelector="a.default">
<include targetURL="entrepParVille.do" targetParams="idVille={js:$vId(target.id)},ville={js:target.title}" targetId="divEntreprises" transition="skew">
<transition targetId="divEntreprises">
<oneTransition endValue="1" startValue="0" property="opacity" duration="2" timing="ease"/>
</transition>
</include>
</js>
</request>
...
</ajax-includes>