11548 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

J'ai créer un petit moteur de recherche pour un futur site à l'aide d'un script trouvé sur le net que j'ai un peu modifié. Il y a une fonction auto suggestion, en javascript, c'est à dire par exemple si je tappe la lettre "l", un div va s'afficher sous mon champ texte avec tout les mots clés commençant par "l".

Bref, j'aurais aimé savoir si mettre en gras le début des mots clé dans le div au fur et à mesure que l'on rajoute des lettres était possible et si oui, pouvez vous m'indiquez une piste pour le réaliser ?

Merci.

voici le script ( un peu long, je ne sais pas précisément quelle partie est utile ):


function metsEnPlace(valeur, liste){
  while(_completeDiv.childNodes.length>0) {
    _completeDiv.removeChild(_completeDiv.childNodes[0]);
  }
  // mise en place des suggestions
  for(var f=0; f<liste.length; ++f){
    var nouveauDiv=document.createElement("DIV");
    nouveauDiv.onmousedown=divOnMouseDown;
    nouveauDiv.onmouseover=divOnMouseOver;
    nouveauDiv.onmouseout=divOnMouseOut;
    setStylePourElement(nouveauDiv,"AutoCompleteDiv");
    var nouveauSpan=document.createElement("SPAN");
 // le texte de la suggestion en gras !!!   
    nouveauSpan.innerHTML=liste[f]; 
    nouveauDiv.appendChild(nouveauSpan);
    _completeDiv.appendChild(nouveauDiv)
  }
  PressAction();
  if(_completeDivRows>0) {
    _completeDiv.height=16*_completeDivRows+4;
  } else {
    hideCompleteDiv();
  }

}


Modifié par frdiard (17 Apr 2009 - 11:19)
Bon, je me repond tout seul :

j'ai remplacé dans la fonction metsEnPlace()


  nouveauSpan.innerHTML=liste[f]; 


Par


var indice = liste[f].indexOf(valeur);
nouveauSpan.innerHTML=liste[f].substring(0,indice);
nouveauSpan.innerHTML+="<span style='font-weight:bold;'>"+valeur+"</span>";
nouveauSpan.innerHTML+=liste[f].substring(indice+(valeur.length));

La fonction marche avec quelques petits soucis :

Maintenant, quand je tape un espace dans la zone de texte, il m'affiche "%20".

Si je tape "fes", il va afficher "festival"dans le div des propositions, mais si j'efface de la zone de texte et que je re-tape par exemple "ma", il m'affiche toujours "festival" dans le div.

Il ne surligne plus la réponse sélectionné : avant quand je tapais "fes", il affichait toutes la liste des mots clé commençant par "fes" avec la première proposition sélectionné par défaut, mais maintenant il se contente de mettre en gras et ne sélectionne plus.

Si quelqu'un a la réponse à l'un de mes problèmes.

Merci.

François
Bonjour,

Si j'ai bien compris, il y a déjà un bloc qui affiche des termes, et il s'agit de mettre en valeur ces termes en fonction d'une saisie de l'utilisateur?

Je ne l'ai jamais fait, mais j'imagine que je procèderais ainsi:

- M'arranger pour que tous les termes de la liste soient dans un élément SPAN (avec une classe quelconque si nécessaire).

- Construire un tableau de tous les termes, où chaque terme serait un objet avec comme propriétés le texte brut (string), et le noeud DOM correspondant au SPAN, voire éventuellement le noeud correspondant au contenu du SPAN (à voir...).

- Lors de la saisie ou de la modification de la saisie, lancer une fonction qui va bien (après un petit timeout, si la saisie n'est pas modifiée entre-temps).

- La fonction qui va bien compare la saisie à chaque texte de la liste des termes, et pour ceux qui correspondent on peut: a) appliquer une classe au SPAN pour lui donner une certaine mise en forme ou bien b) modifier le contenu du SPAN pour avoir d'abord la partie de texte à mettre en gras puis le reste (ça, c'est une deuxième fonction qui devrait le faire).

- Le truc chaud, c'est qu'à chaque modification (chaque appel de la fonction qui va bien), il faut soit remettre à zéro tous les termes (plein d'accès DOM, impact sur les performances...), soit remettre à zéro uniquement ceux qui ont été modifiés. Ou bien réécrire l'ensemble des termes d'un seul coup pour réduire les accès DOM (pas sûr que ça soit intéressant)?

Il y a peut-être moyen de simplifier, mais ton code actuel m'a l'air un peu limité pour ce que tu souhaites faire.
Je n'ai pris que la partie du code qui m'intéressait pour ce que je cherche à faire.

Je peux poster le script entier si besoin ?
J'imagine que les résultats sont retournés via ajax ou autre méthode asynchrone?
Dans ce cas, à mon avis, le plus simple c'est de gérer le problème coté serveur, avec un regex php qui remplace la valeur du champ par sa valeur entouré de <b></b>
Oui , pourrais tu m'expliquer un peu plus précisément ?

je vois pas trop comment faire.

merci
Modifié par frdiard (18 Apr 2009 - 00:40)
Un exemple :
La lettre tapée est
$input = "i";


Ta base de données retourne donc le tableau suivant:
$results = array(
  1 => "Igor",
  2 => "Isabelle",
  3 => "Irene"
);


Dans ton code php qui génère le xml tu rajoutes :
echo "<results>\n";
foreach ($results as $result){
  $text = preg_replace("/^($input)/i",'<b>$1</b>', $result);
  echo "   <result>".htmlspecialchars($text)."</result>\n";
}
echo "</results>\n"; 


Ici le résultat est retourné en xml avec php parce que c'est comme ça que je ferais, mais cela peut être en json avec python ou au format texte avec asp... C'est juste pour décrire la méthode.
Modifié par matmat (18 Apr 2009 - 02:26)
Je poste directement ma partie php : peux tu m'indiquer ou insérer ton code ?


<?php
header('Content-Type: text/xml;charset=utf-8');
echo(utf8_encode("<?xml version='1.0' encoding='UTF-8' ?><options>"));
if (isset($_GET['debut'])) {
    $debut = utf8_decode($_GET['debut']);
} else {
    $debut = "";
}
$debut = strtolower($debut);
mysql_connect("localhost","root","");
mysql_select_db("test");

/*//recupere les mot cle de tout les champs avec group_concat ( dans le cas d'une seule table tel que : titre, contenu, motcle
$reponse = mysql_query("SELECT group_concat(motcle) FROM recherche  ");

$liste = explode(',', mysql_result($reponse, 0));
$liste_unique = array_unique($liste); */

//ou par pertinence tel que : trois table : article, tag, article_tag

$reponse = mysql_query ("SELECT id_tag, nom, count(*) as combien FROM article_tag, tag 
where id_tag = id 
group by id_tag, nom 
order by combien desc, nom");
$liste = array();
while($row = mysql_fetch_assoc($reponse)) {
	$liste[] = $row['nom'];
}

function generateOptions($debut,$liste) {
    $MAX_RETURN = 10;
    $i = 0;
    foreach ($liste as $element) {
        if ($i<$MAX_RETURN && substr($element, 0, strlen($debut))==$debut) {
            echo(utf8_encode("<option>".$element."</option>"));
            $i++;
        }
    }
}

generateOptions($debut,$liste);

echo("</options>");


?>

Modifié par frdiard (18 Apr 2009 - 02:28)
à la place de:
echo(utf8_encode("<option>".$element."</option>"));


tu mets:
$debut = $_GET['debut'];
$element = preg_replace("/^($debut)/i",'<b>$1</b>', $element);
echo "<option>".htmlspecialchars($element)."</option>\n";
Merci cette méthode marche très bien, mais j'ai toujours les mêmes problèmes cité plus haut avec l'autre méthode:

c'est à dire :
a écrit :

Si je tape "fes", il va afficher "festival"dans le div des propositions, mais si j'efface de la zone de texte et que je re-tape par exemple "ma", il m'affiche toujours "festival" dans le div.

Il ne surligne plus la réponse sélectionné : avant quand je tapais "fes", il affichait toutes la liste des mots clé commençant par "fes" avec la première proposition sélectionné par défaut, mais maintenant il se contente de mettre en gras et ne sélectionne plus.


Merci en tout cas de m'accorder un peu de temps Smiley cligne
Modifié par frdiard (18 Apr 2009 - 02:45)
Dèja au debut de ton php il faut mettre en header qui évite la mise en cache:
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" ); 
header("Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" ); 
header("Cache-Control: no-cache, must-revalidate" ); 
header("Pragma: no-cache" );
header('Content-Type: text/xml; charset=UTF-8');


Et si pour effacer ton div au lieu de
while(_completeDiv.childNodes.length>0) {
    _completeDiv.removeChild(_completeDiv.childNodes[0]);
 }

tu fais un truc bien bourrin genre:
_completeDiv.innerHTML = "";

il se passe quoi?
Modifié par matmat (18 Apr 2009 - 02:56)
Toujours pareil :

On écrit 5 lettres qui sont bien mise en gras dans les suggestions, mais quand on efface toutes les lettres du champ texte, il n'efface qu'une lettre dans les suggestions pour finalement rester bloqué sur ces suggestions.

Il y a toujours ce problème de surlignage , je ne vois vrament pas d'où cela vient. Smiley decu

Je met un lien vers le .js entier si besoin : http://www.francoisdiard.free.fr/autosuggest.js

Merci beaucoup de votre aide ! Smiley cligne