<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5200826704807962631</id><updated>2011-04-22T00:28:35.791+02:00</updated><category term='scrollTo'/><category term='ancestors'/><category term='syntaxe'/><category term='compatibilité'/><category term='documentation'/><category term='internet explorer'/><category term='ajax'/><category term='highlight'/><category term='tutorial'/><category term='reset'/><category term='souce code'/><category term='Blogger'/><category term='degradable'/><category term='tutoriel'/><category term='historique'/><category term='firefox'/><category term='coloration'/><category term='favoris'/><category term='css'/><category term='trick'/><category term='ie; ff'/><category term='reset.css'/><category term='scroll'/><category term='debuter'/><category term='extjs'/><category term='prototype'/><category term='référencement'/><title type='text'>Astuces CSS, Javascript, PHP ou Ajax par RapotOR</title><subtitle type='html'>Astuces, Développement Web, XHTML, CSS, PHP, MySQL, Ajax, Web 2.0!</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://rapotor.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://rapotor.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>RapotOR</name><uri>http://www.blogger.com/profile/09981627114003941351</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://1.bp.blogspot.com/_Aa55wEAWQr4/SXIAKrtirNI/AAAAAAAAAAM/jSN-9jD_E78/S220/ced.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5200826704807962631.post-3596318000681940632</id><published>2009-03-10T10:31:00.010+01:00</published><updated>2009-03-10T20:55:12.814+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scroll'/><category scheme='http://www.blogger.com/atom/ns#' term='scrollTo'/><category scheme='http://www.blogger.com/atom/ns#' term='prototype'/><category scheme='http://www.blogger.com/atom/ns#' term='ancestors'/><title type='text'>Scroll d'un element jusqu'a un autre element</title><content type='html'>Bonjour,&lt;br /&gt;&lt;br /&gt;Un petit post assez court pour vous exposez ce petit problème qui me chatouillait.&lt;br /&gt;Dans mon application web, j'avais besoin d'utiliser le fameux "&lt;span style="font-style:italic;"&gt;scrollTo()&lt;/span&gt;". Seulement, petit hic, cette fonction fonctionne sur le document. Dans mon cas, le &lt;span style="font-style:italic;"&gt;scroll&lt;/span&gt; se situait sur une DIV parente a l'élément que je voulais atteindre.&lt;br /&gt;&lt;br /&gt;La fonction suivante permet donc de réaliser un scroll sur le premier élément parent qui possède une scrollbar.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;Element.addMethods({&lt;br /&gt;  scrollFirstAncestorTo: function(element) {&lt;br /&gt;    var firstAncestor = null;&lt;br /&gt;    //boucle pour recuperer le premier parent qui possede un scroll.&lt;br /&gt;    element.ancestors().each(function(el,index){&lt;br /&gt;      var previousScrollTop = el.scrollTop;&lt;br /&gt;      el.scrollTop = el.scrollHeight;&lt;br /&gt;      // si le scroll est &amp;gt; 0, il y a un scroll possible.&lt;br /&gt;      if (el.scrollTop &amp;gt; 0){&lt;br /&gt;        firstAncestor = el;&lt;br /&gt;        el.scrollTop = previousScrollTop;&lt;br /&gt;        // on sort de la boucle vu qu'on a notre parent.&lt;br /&gt;        throw $break;&lt;br /&gt;      }&lt;br /&gt;    });&lt;br /&gt;    &lt;br /&gt;    if (typeof firstAncestor == &amp;quot;object&amp;quot; &amp;amp;&amp;amp; firstAncestor !== null){&lt;br /&gt;      var valueT = 0, valueL = 0;&lt;br /&gt;      // on somme les offsets jusqu'a notre element&lt;br /&gt;      // la fonction est similaire a cumulativeOffset&lt;br /&gt;      do {&lt;br /&gt;        valueT += element.offsetTop  || 0;&lt;br /&gt;        valueL += element.offsetLeft || 0;&lt;br /&gt;        element = element.offsetParent;&lt;br /&gt;      } while (element &amp;amp;&amp;amp; element!=firstAncestor);&lt;br /&gt;      // on applique le scroll calcul&amp;eacute;&lt;br /&gt;      firstAncestor.scrollTop = valueT;&lt;br /&gt;      firstAncestor.scrollLeft = valueT;&lt;br /&gt;      return firstAncestor;&lt;br /&gt;    }else{&lt;br /&gt;      return false;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;  }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Si vous avez des questions ou des remarques, n'hésitez pas.&lt;br /&gt;&lt;br /&gt;Cédric&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5200826704807962631-3596318000681940632?l=rapotor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rapotor.blogspot.com/feeds/3596318000681940632/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://rapotor.blogspot.com/2009/03/scroll-dun-element-jusqua-un-autre.html#comment-form' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/3596318000681940632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/3596318000681940632'/><link rel='alternate' type='text/html' href='http://rapotor.blogspot.com/2009/03/scroll-dun-element-jusqua-un-autre.html' title='Scroll d&apos;un element jusqu&apos;a un autre element'/><author><name>RapotOR</name><uri>http://www.blogger.com/profile/09981627114003941351</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://1.bp.blogspot.com/_Aa55wEAWQr4/SXIAKrtirNI/AAAAAAAAAAM/jSN-9jD_E78/S220/ced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5200826704807962631.post-5750354891092998659</id><published>2009-02-16T18:52:00.010+01:00</published><updated>2009-02-20T17:57:47.930+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='favoris'/><category scheme='http://www.blogger.com/atom/ns#' term='degradable'/><category scheme='http://www.blogger.com/atom/ns#' term='référencement'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='historique'/><category scheme='http://www.blogger.com/atom/ns#' term='prototype'/><title type='text'>Site ajax, referencement, historique et favoris (PART 2)</title><content type='html'>&lt;span style="font-style:italic;"&gt;La lecture de cette partie nécessite la compréhension de la partie 1.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Bonjour,&lt;br /&gt;&lt;br /&gt;Nous avions vu comment gérer la navigation Ajax en respectant les utilisateurs sans JS (ou le bot Google). La classe créée était relativement basique. La deuxième partie de l'article va nous permettre d'améliorer son fonctionnement.&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Dégradation des formulaires&lt;/h1&gt;&lt;br /&gt;La solution est quasiment identique a celle utilisée sur les liens. On utilise l'action &lt;span style="font-style:italic;"&gt;onSubmit&lt;/span&gt;. Les valeurs du formulaire sont ajoutées au paramètres généraux par le biais de &lt;span style="font-style:italic;"&gt;Serialize&lt;/span&gt;.&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;//...&lt;br /&gt;var forms = el.getElementsByTagName(&amp;quot;form&amp;quot;);&lt;br /&gt;&lt;br /&gt;$A(forms).each(function(form){&lt;br /&gt;&lt;br /&gt;  form.onsubmit = function(){&lt;br /&gt;    var anchor = form.action;&lt;br /&gt;    &lt;br /&gt;    if (anchor.length==0)&lt;br /&gt;      return false;&lt;br /&gt;    &lt;br /&gt;    var formOptions = { &amp;quot;ajaxtype&amp;quot;: &amp;quot;form&amp;quot;, &lt;br /&gt;                        &amp;quot;curl&amp;quot;: this.stripBaseUrl(window.location.href), &lt;br /&gt;                        &amp;quot;formid&amp;quot;: form.id, &lt;br /&gt;                        &amp;quot;hash&amp;quot;: anchor };&lt;br /&gt;&lt;br /&gt;    Object.extend( formOptions , Form.serialize( form , true) || { });&lt;br /&gt;    &lt;br /&gt;    this.triggerCallback( formOptions );&lt;br /&gt;&lt;br /&gt;    return false;&lt;br /&gt;  }.bind(this);&lt;br /&gt;}.bind(this));&lt;br /&gt;//...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h1&gt;Éviter l'écrasement de l'action &lt;span style="font-style:italic;"&gt;onClick &lt;/span&gt;&lt;/h1&gt;&lt;br /&gt;La solution est assez simple. Avant l'ecrasement de la fonction onClick du lien, il nous suffit de sauver la fonction originale tel que montré ci-dessous:&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;var links = el.getElementsByTagName(&amp;quot;a&amp;quot;);&lt;br /&gt;$A(links).each(function(link){&lt;br /&gt;    link._onclick = link.onclick || Prototype.emptyFunction;&lt;br /&gt;    link.onclick = function(){&lt;br /&gt;        link._onclick();&lt;br /&gt;        // code présent dans la PART 1 de l'acticle.&lt;br /&gt;        return false;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;On fait exactement la meme manipulation avec le onSubmit.&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Gestion de sous-répertoire&lt;/h1&gt;&lt;br /&gt;Lorsque l'on veut utiliser l'URL rewriting, on a besoin de placer une balise BASE pour indiquer quel est le répertoire réel. C'est précisément cette balise que je vais utiliser pour nettoyer l'URL et récupérer l'adresse réelle tel que:&lt;br /&gt;http://www.monsite.com/site2/news/2/toto-est-un-heros.html deviendra news/2/toto-est-un-heros.html&lt;br /&gt;Dans un premier temps, nous allons sauvegarder la base (&lt;span style="font-style:italic;"&gt;http://www.monsite.com/site2/&lt;/span&gt;) dans une variable. Celle-ci servira a une fonction &lt;span style="font-style:italic;"&gt;stripBaseUrl&lt;/span&gt;.&lt;br /&gt;Je me permet de sauvegarder également l'index qui sera en fait la page d'arrivée (cela nous servira plus tard).&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;var baseObj = document.getElementsByTagName(&amp;quot;base&amp;quot;);&lt;br /&gt;if ( baseObj.length == 1 ){&lt;br /&gt;  this.options.baseUrl  = baseObj[0].href;&lt;br /&gt;  this.options.indexUrl = this.stripBaseUrl(window.location.href);&lt;br /&gt;}&lt;br /&gt;//...&lt;br /&gt;stripBaseUrl: function(url){&lt;br /&gt;  if ( url.substring( 0 , this.options.baseUrl.length ) == this.options.baseUrl ){&lt;br /&gt;    return url.substring( this.options.baseUrl.length , url.length );&lt;br /&gt;  }else{&lt;br /&gt;    return url;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h1&gt;Gestion du bouton &lt;span style="font-style:italic;"&gt;Précédent&lt;/span&gt; et de l'historique&lt;/h1&gt;&lt;br /&gt;A ce moment, les choses sérieuses commencent! Il faut savoir que le changement d'ancre fait réagir différemment les navigateurs. Firefox crée un point d'historique alors que IE n'en crée pas. Sous Firefox, même si je me rend a la page précédente, le navigateur ne relancera pas de nouvelles requête Ajax en vue de recharger son contenu (le contraire aurait été surprenant).&lt;br /&gt;En attendant la création d'une action &lt;span style="font-style:italic;"&gt;onHashChange&lt;/span&gt; (et puis même si elle arrive, il faudra toujours satisfaire les couillons qui ont un vieux navigateur), nous devons ruser pour gérer a la fois IE et Firefox.&lt;br /&gt;&lt;h2&gt;Firefox&lt;/h2&gt;&lt;br /&gt;Pour Firefox, j'utilise un timer qui va vérifier en permanence l'ancre du navigateur. Si jamais il change, il va relancer la requête Ajax. dans le cas ou il n'y a pas d ancre, je fais une requête avec l'index comme ancre.&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;this.interval = setInterval(function(){&lt;br /&gt;  if ( this.anchor != this.getHash() ){&lt;br /&gt;    this.anchor = this.getHash() ;&lt;br /&gt;    var formOptions = { &amp;quot;ajaxtype&amp;quot;: &amp;quot;link&amp;quot;, &lt;br /&gt;                        &amp;quot;curl&amp;quot;: this.stripBaseUrl(window.location.href) , &lt;br /&gt;                        &amp;quot;hash&amp;quot;: ( (this.anchor.length&amp;gt;0) ? this.anchor : this.options.indexUrl) };&lt;br /&gt;    this.triggerCallback(formOptions);      &lt;br /&gt;  }&lt;br /&gt;}.bind(this), this.options.interval);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Internet Explorer&lt;/h2&gt;&lt;br /&gt;Pour IE, le changement d'ancre ne cree pas de point d'historique. Il faut ruser. L'astuce est de creer une iframe. Le changement d'adresse dans l'iframe permettra alors la creation du point d'historique.&lt;br /&gt;Ce n'est pas tout! Il faut encore detecter le changement d'ancre. Pour cela, c'est le contenu de l'iframe qui déclenchera la requête Ajax. Un exemple vaut mieux que de grandes paroles.&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;initialize: function(options){&lt;br /&gt;  //...&lt;br /&gt;  if (Prototype.Browser.IE){&lt;br /&gt;    this.iframe(document.body, this.getHash() );&lt;br /&gt;  }&lt;br /&gt;  //...&lt;br /&gt;}&lt;br /&gt;//...&lt;br /&gt;iframe: function(parentElement,anchor){&lt;br /&gt;  if ( this.el.historyFrame == null ){&lt;br /&gt;&lt;br /&gt;    this.el.historyFrame = new Element( 'iframe' );&lt;br /&gt;    this.el.historyFrame.style.display = 'none';&lt;br /&gt;    this.el.historyFrame.style.position ='absolute';&lt;br /&gt;    this.el.historyFrame.style.top ='200px';&lt;br /&gt;    this.el.historyFrame.style.border ='solid 1px #000';&lt;br /&gt;    this.el.historyFrame.style.right ='50px';&lt;br /&gt;    this.el.historyFrame.style.zIndex = '1000';&lt;br /&gt;    this.el.historyFrame.style.backgroundColor ='#FFFFFF';&lt;br /&gt;    &lt;br /&gt;    this.el.historyFrame.src = this.options.baseUrl+'nav.php?hash='+ anchor;&lt;br /&gt;&lt;br /&gt;    parentElement.appendChild(this.el.historyFrame);&lt;br /&gt;&lt;br /&gt;  }else{&lt;br /&gt;  &lt;br /&gt;    this.el.historyFrame.src = this.options.baseUrl+'nav.php?hash='+ anchor;&lt;br /&gt;  &lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;//...&lt;br /&gt;setHash: function(anchor){&lt;br /&gt;  this.anchor = anchor;&lt;br /&gt;  window.location.hash = anchor;&lt;br /&gt;  if (Prototype.Browser.IE){&lt;br /&gt;    this.iframe(this.el.historyDiv,anchor);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;//...&lt;br /&gt;goLink: function(anchor, options, hashChange){   &lt;br /&gt;  if ( anchor != this.getHash() ){&lt;br /&gt;    if (hashChange == undefined)&lt;br /&gt;      hashChange = true;&lt;br /&gt;    &lt;br /&gt;    var formOptions = { &amp;quot;ajaxtype&amp;quot;: &amp;quot;link&amp;quot;, &lt;br /&gt;                        &amp;quot;curl&amp;quot;: this.stripBaseUrl(window.location.href), &lt;br /&gt;                        &amp;quot;hash&amp;quot;: anchor };&lt;br /&gt;    Object.extend( formOptions , options || { });&lt;br /&gt;    &lt;br /&gt;    if (hashChange)&lt;br /&gt;      this.setHash(anchor);&lt;br /&gt;    &lt;br /&gt;    this.triggerCallback( formOptions );  &lt;br /&gt;  }                      &lt;br /&gt;}&lt;br /&gt;//...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Explications :&lt;/span&gt;&lt;br /&gt;* Si &lt;span style="font-style:italic;"&gt;historyFrame &lt;/span&gt; est nulle, c'est le premier appel de la fonction et il faut créer l'iframe.&lt;br /&gt;* Lorsqu'on change d'ancre, on change également l'adresse de l'iframe.&lt;br /&gt;* La fonction &lt;span style="font-style:italic;"&gt;goLink&lt;/span&gt; est equivalente au code executé par un lien. Il sera appelé par l'iframe.&lt;br /&gt;* Lors de l'appel d'une page précédente, c'est le code de la page &lt;span style="font-style:italic;"&gt;nav.php&lt;/span&gt; qui relancera la requête Ajax par le biais de la fonction &lt;span style="font-style:italic;"&gt;goLink&lt;/span&gt;. Pour connaitre l'URL a appeler, l'ancre est tout simplement écrite dans la propriété &lt;span style="font-style:italic;"&gt;TITLE&lt;/span&gt; de la page.&lt;br /&gt;&lt;pre name="code" class="php"&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;&lt;br /&gt;  header( &amp;quot;Expires: Mon, 20 Dec 1998 01:00:00 GMT&amp;quot; );&lt;br /&gt;  header( &amp;quot;Last-Modified: &amp;quot; . gmdate(&amp;quot;D, d M Y H:i:s&amp;quot;) . &amp;quot; GMT&amp;quot; );&lt;br /&gt;  header( &amp;quot;Cache-Control: no-cache, must-revalidate&amp;quot; );&lt;br /&gt;  header( &amp;quot;Pragma: no-cache&amp;quot; );&lt;br /&gt;  &lt;br /&gt;  $hash = 'index.html';&lt;br /&gt;  if (isset($_GET['hash'])){&lt;br /&gt;    $hash = stripslashes($_GET['hash']);&lt;br /&gt;  }  &lt;br /&gt;  &lt;br /&gt;?&amp;gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;  &amp;lt;head&amp;gt;&lt;br /&gt;    &amp;lt;title&amp;gt;&amp;lt;?php echo $hash; ?&amp;gt;&amp;lt;/title&amp;gt;&lt;br /&gt;    &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://127.0.0.1/Intranet/js/prototype/prototype.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;      document.observe(&amp;quot;dom:loaded&amp;quot;, function() {&lt;br /&gt;        if (window.parent.location.hash != document.title){&lt;br /&gt;          window.parent.AjaxNav.goLink( document.title );&lt;br /&gt;        }&lt;br /&gt;      });&lt;br /&gt;    &amp;lt;/script&amp;gt;&lt;br /&gt;  &amp;lt;/head&amp;gt;&lt;br /&gt;  &amp;lt;body&amp;gt;&amp;lt;?php echo $hash; ?&amp;gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Gestion des favoris.&lt;/h1&gt;&lt;br /&gt;Lorsqu'on met une page en favoris, la page désirée sera indiquée dans l'ancre. Il suffit donc au chargement de la page de vérifier si une ancre est présente. Dans l'affirmative, on redirige vers celle-ci.&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;document.observe(&amp;quot;dom:loaded&amp;quot;, function() {&lt;br /&gt;  //...&lt;br /&gt;  if (window.location.hash.length &amp;gt; 0){&lt;br /&gt;    var baseObj = document.getElementsByTagName(&amp;quot;base&amp;quot;);&lt;br /&gt;    if ( baseObj.length == 1 ){&lt;br /&gt;      window.location.href = baseObj[0].href+window.location.hash.split('#')[1];&lt;br /&gt;    }else{&lt;br /&gt;      window.location.href = window.location.hash.split('#')[1];&lt;br /&gt;    }&lt;br /&gt;    return;&lt;br /&gt;  }&lt;br /&gt;  //...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Crypter les mots de passe.&lt;/h1&gt;&lt;br /&gt;Cette dernière amélioration peut être superflue pour certain. Elle consiste en le cryptage (MD5 dans l'exemple) des champs &lt;span style="font-style:italic;"&gt;PASSWORD&lt;/span&gt; avant de soumettre le formulaire. Pour effectuer cela, il faut tout d'abord récupérer le fichier &lt;a href="http://pajhome.org.uk/crypt/md5" target="_blank"&gt;MD5.js&lt;/a&gt; qui fera la conversion des mots de passe. Le code est le suivant. Il est relativement simple.&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;//...&lt;br /&gt;Object.extend( formOptions , Form.serialize( form , true) || { });&lt;br /&gt;&lt;br /&gt;if (this.options.pwdToMd5){&lt;br /&gt;  var pwdOnly = Form.serializeElements( form.getInputs('password') , true );&lt;br /&gt;  for (var property in pwdOnly)&lt;br /&gt;    pwdOnly[property] = hex_md5(pwdOnly[property]);&lt;br /&gt;  &lt;br /&gt;  Object.extend( formOptions , pwdOnly || { });&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;this.triggerCallback( formOptions );&lt;br /&gt;//...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h1&gt;Appel d'une page SANS changement d'ancre.&lt;/h1&gt;&lt;br /&gt;Cela peut paraitre bizarre mais cela devient vite utile. En effet, cela permet d'effectuer des actions qui ne sont pas réellement une page. Dans une version de site sans Ajax, cela équivaut a une page du type "Les modifications ont été effectuées. Redirection en cours...". En Ajax, on a évidement pas besoin de changer la page pour cela! J'espère que cela vous parle!&lt;br /&gt;Pour réaliser cela, j'utilise l'attribut TARGET avec la valeur "_self". Cela permet de ne pas avoir de problème pour les utilisateurs sans JS.&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;if ( !link.target || link.target != &amp;quot;_self&amp;quot; )&lt;br /&gt;  this.setHash(anchor);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;On recolle tous les bouts&lt;/h1&gt;&lt;br /&gt;Il est maintenant temps de rassembler les différents bouts de code en une classe pleinement fonctionnelle.&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;/*  Ajax Navigator &lt;br /&gt; *  (c) 2008-2009 Cedric Lahouste&lt;br /&gt; * &lt;br /&gt; *  Educative version, my final version will be posted in a next article.&lt;br /&gt; *  Version dans un but educatif, ma version finale sera postee dans un prochain article&lt;br /&gt; *  &lt;br /&gt; *  Ajax Navigator is freely distributable under the terms of an MIT-style license.&lt;br /&gt; *&lt;br /&gt; *  Prototype needed.&lt;br /&gt; *&lt;br /&gt; *---------------------------------------------------------------------------------*/&lt;br /&gt;&lt;br /&gt;var AjaxNavigator = Class.create({&lt;br /&gt; &lt;br /&gt; options: {&lt;br /&gt;  url: 'index.php',&lt;br /&gt;  indexUrl : 'index.html',&lt;br /&gt;  baseUrl  : '',&lt;br /&gt;  interval : 250, // in millisecond&lt;br /&gt;  pwdToMd5 : true,&lt;br /&gt;  callback : Prototype.emptyFunction  &lt;br /&gt; },&lt;br /&gt;&lt;br /&gt;  // elements&lt;br /&gt;  el: {&lt;br /&gt;    historyFrame : null&lt;br /&gt;  },&lt;br /&gt;  &lt;br /&gt;  // initialize: gogogo!&lt;br /&gt; initialize: function(options){&lt;br /&gt;  &lt;br /&gt;  Object.extend(this.options, options || { });&lt;br /&gt; &lt;br /&gt;  this.applyOn(document);&lt;br /&gt;  &lt;br /&gt;  var baseObj = document.getElementsByTagName(&amp;quot;base&amp;quot;);&lt;br /&gt;  if ( baseObj.length == 1 ){&lt;br /&gt;   this.options.baseUrl  = baseObj[0].href;&lt;br /&gt;   this.options.indexUrl = this.stripBaseUrl(window.location.href);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  if (Prototype.Browser.IE){&lt;br /&gt;      // no setInterval needed for ie. hash change detected directly by the iframe!&lt;br /&gt;      this.iframe(document.body, this.getHash() );&lt;br /&gt;  }else{&lt;br /&gt;      // with firefox, actually no way found. if iframe used, 2 history points are created (1 by iframe and 1 by hash)&lt;br /&gt;      // and there is a problem. the iframe content doesn't change.&lt;br /&gt;      this.anchor = this.getHash();&lt;br /&gt;      this.interval = setInterval(function(){&lt;br /&gt;        if ( this.anchor != this.getHash() ){&lt;br /&gt;          this.anchor = this.getHash() ;&lt;br /&gt;          var formOptions = { &amp;quot;ajaxtype&amp;quot;: &amp;quot;link&amp;quot;, &lt;br /&gt;                              &amp;quot;curl&amp;quot;: this.stripBaseUrl(window.location.href) , &lt;br /&gt;                              &amp;quot;hash&amp;quot;: ( (this.anchor.length&amp;gt;0) ? this.anchor : this.options.indexUrl) };&lt;br /&gt;          this.triggerCallback(formOptions);      &lt;br /&gt;        }&lt;br /&gt;      }.bind(this), this.options.interval);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; iframe: function(parentElement,anchor){&lt;br /&gt;    if ( this.el.historyFrame == null ){&lt;br /&gt;&lt;br /&gt;      this.el.historyFrame = new Element( 'iframe' );&lt;br /&gt;      this.el.historyFrame.style.display = 'none';&lt;br /&gt;      this.el.historyFrame.style.position ='absolute';&lt;br /&gt;      this.el.historyFrame.style.top ='200px';&lt;br /&gt;      this.el.historyFrame.style.border ='solid 1px #000';&lt;br /&gt;      this.el.historyFrame.style.right ='50px';&lt;br /&gt;      this.el.historyFrame.style.zIndex = '1000';&lt;br /&gt;      this.el.historyFrame.style.backgroundColor ='#FFFFFF';&lt;br /&gt;      &lt;br /&gt;      this.el.historyFrame.src = this.options.baseUrl+'nav.php?hash='+ anchor;&lt;br /&gt;&lt;br /&gt;      parentElement.appendChild(this.el.historyFrame);&lt;br /&gt;&lt;br /&gt;    }else{&lt;br /&gt;    &lt;br /&gt;      this.el.historyFrame.src = this.options.baseUrl+'nav.php?hash='+ anchor;&lt;br /&gt;    &lt;br /&gt;    }&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; // get the url without the base... http://127.0.0.1/toto.html becomes toto.html&lt;br /&gt; stripBaseUrl: function(url){&lt;br /&gt;  if ( url.substring( 0 , this.options.baseUrl.length ) == this.options.baseUrl ){&lt;br /&gt;   return url.substring( this.options.baseUrl.length , url.length );&lt;br /&gt;  }else{&lt;br /&gt;   return url;&lt;br /&gt;  }&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; // getHash... get the anchor and if no anchor, get the url!&lt;br /&gt; getHash: function(){&lt;br /&gt;    return ( this.stripBaseUrl(window.location.href).split('#')[1] || this.stripBaseUrl(window.location.href) );&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; // use for changing url without request&lt;br /&gt; setHash: function(anchor){&lt;br /&gt;  this.anchor = anchor;&lt;br /&gt;  window.location.hash = anchor;&lt;br /&gt;  if (Prototype.Browser.IE){&lt;br /&gt;   this.iframe(this.el.historyDiv,anchor);&lt;br /&gt;  }&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; // use for action by button&lt;br /&gt; goLink: function(anchor, options, hashChange){   &lt;br /&gt;    if ( anchor != this.getHash() ){&lt;br /&gt;      if (hashChange == undefined)&lt;br /&gt;        hashChange = true;&lt;br /&gt;      &lt;br /&gt;      var formOptions = { &amp;quot;ajaxtype&amp;quot;: &amp;quot;link&amp;quot;, &lt;br /&gt;                          &amp;quot;curl&amp;quot;: this.stripBaseUrl(window.location.href), &lt;br /&gt;                          &amp;quot;hash&amp;quot;: anchor };&lt;br /&gt;      Object.extend( formOptions , options || { });&lt;br /&gt;      &lt;br /&gt;      if (hashChange)&lt;br /&gt;        this.setHash(anchor);&lt;br /&gt;      &lt;br /&gt;      this.triggerCallback( formOptions );  &lt;br /&gt;    }                      &lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; // apply on a element. Because can be called by a function getting new html code&lt;br /&gt; applyOn: function(el){&lt;br /&gt;    &lt;br /&gt;    if (typeof el == 'string')&lt;br /&gt;      el = $(el);&lt;br /&gt;    &lt;br /&gt;  // links&lt;br /&gt;  var links = el.getElementsByTagName(&amp;quot;a&amp;quot;);&lt;br /&gt; &lt;br /&gt;  $A(links).each(function(link){&lt;br /&gt;      // Don't make change the onclick value IF:&lt;br /&gt;      // * It's already script&lt;br /&gt;      // * The target is '_blank' =&gt; will open in an other window&lt;br /&gt;      // * The target is 'file:' (local files)&lt;br /&gt;      if ( link.href.substring(0,11) != 'javascript:' &amp;amp;&amp;amp; link.href.substring(0,5) != 'file:' &amp;amp;&amp;amp; link.target != &amp;quot;_blank&amp;quot;){&lt;br /&gt;        link._onclick = link.onclick || Prototype.emptyFunction;&lt;br /&gt;        link.onclick = function(){&lt;br /&gt;          var anchor = this.stripBaseUrl( link.href );&lt;br /&gt;          if (anchor.length==0)&lt;br /&gt;            return false;&lt;br /&gt;          var linkOptions = { &amp;quot;ajaxtype&amp;quot;: &amp;quot;link&amp;quot;, &lt;br /&gt;                              &amp;quot;curl&amp;quot;: this.stripBaseUrl(window.location.href), &lt;br /&gt;                              &amp;quot;hash&amp;quot;: anchor };&lt;br /&gt;&lt;br /&gt;          // if the target is '_self', we did page actions without anchor change.&lt;br /&gt;          if ( !link.target || link.target != &amp;quot;_self&amp;quot; )&lt;br /&gt;            this.setHash(anchor);&lt;br /&gt;          &lt;br /&gt;          this.triggerCallback( linkOptions );&lt;br /&gt;          &lt;br /&gt;          // Fire original function&lt;br /&gt;          link._onclick();&lt;br /&gt;          &lt;br /&gt;          return false;&lt;br /&gt;        }.bind(this);&lt;br /&gt;   }&lt;br /&gt;  }.bind(this));&lt;br /&gt;  &lt;br /&gt;  // forms &lt;br /&gt;  var forms = el.getElementsByTagName(&amp;quot;form&amp;quot;);&lt;br /&gt;&lt;br /&gt;  var pwdOnly = {toto:'toto'};&lt;br /&gt;  &lt;br /&gt;  $A(forms).each(function(form){&lt;br /&gt;   &lt;br /&gt;   form._onsubmit = form.onsubmit || Prototype.emptyFunction;&lt;br /&gt;&lt;br /&gt;   form.onsubmit = function(){&lt;br /&gt;    var anchor = this.stripBaseUrl(form.action);&lt;br /&gt;    &lt;br /&gt;    if (anchor.length==0)&lt;br /&gt;     return false;&lt;br /&gt;        &lt;br /&gt;        // Fire the original function&lt;br /&gt;        form._onsubmit();    &lt;br /&gt;    &lt;br /&gt;    var formOptions = { &amp;quot;ajaxtype&amp;quot;: &amp;quot;form&amp;quot;, &lt;br /&gt;              &amp;quot;curl&amp;quot;: this.stripBaseUrl(window.location.href), &lt;br /&gt;              &amp;quot;formid&amp;quot;: form.id, &lt;br /&gt;              &amp;quot;hash&amp;quot;: anchor };&lt;br /&gt; &lt;br /&gt;    Object.extend( formOptions , Form.serialize( form , true) || { });&lt;br /&gt; &lt;br /&gt;    if (this.options.pwdToMd5){&lt;br /&gt;     // we convert all password input's values with md5 function.&lt;br /&gt;     var pwdOnly = Form.serializeElements( form.getInputs('password') , true );&lt;br /&gt;     for (var property in pwdOnly)&lt;br /&gt;      pwdOnly[property] = hex_md5(pwdOnly[property]);&lt;br /&gt;     &lt;br /&gt;     Object.extend( formOptions , pwdOnly || { });&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    this.triggerCallback( formOptions );&lt;br /&gt;&lt;br /&gt;    return false;&lt;br /&gt;   }.bind(this);&lt;br /&gt;  }.bind(this));&lt;br /&gt;  &lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; // the callback, for submitting &amp;amp; requesting url&lt;br /&gt; triggerCallback: function(vars){&lt;br /&gt;  if ('function' == typeof this.options.callback) {&lt;br /&gt;   this.options.callback(vars);&lt;br /&gt;  }&lt;br /&gt;  return false;&lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; // submit &amp;amp; get actions to do!&lt;br /&gt; submit: function(formOptions){&lt;br /&gt; &lt;br /&gt;  var ajaxOptions = {&lt;br /&gt;   method: 'post',&lt;br /&gt;   postBody: $H(formOptions).toQueryString(),&lt;br /&gt;   onSuccess: function(xhr){&lt;br /&gt;    &lt;br /&gt;    if ( xhr.status==200 &amp;amp;&amp;amp; xhr.responseText.length &amp;gt; 0){&lt;br /&gt;     if ( xhr.responseText.isJSON() ){&lt;br /&gt;      this.evaluateResponse( xhr.responseText.evalJSON() );&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;   }.bind(this),&lt;br /&gt;   onFailure: Prototype.emptyFunction&lt;br /&gt;  };&lt;br /&gt;  &lt;br /&gt;  //***********************************************&lt;br /&gt;  new Ajax.Request(this.options.url,ajaxOptions);&lt;br /&gt;  //***********************************************&lt;br /&gt;  &lt;br /&gt;  return false;&lt;br /&gt;  &lt;br /&gt; },&lt;br /&gt; &lt;br /&gt; // evalutation actions received&lt;br /&gt; evaluateResponse: function(xhrObj){&lt;br /&gt; &lt;br /&gt;          // Do something here&lt;br /&gt;          // Evaluation de la chaine ici.&lt;br /&gt;          // Ce sera le sujet de la partie 3 de cet article.&lt;br /&gt; &lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Ouf...&lt;/h1&gt;&lt;br /&gt;Voici la fin de la deuxième partie de cet article. Nous avons effectué toutes les améliorations nécessaires. Notre classe est maintenant fonctionnelle pour la navigation Ajax.&lt;br /&gt;&lt;br /&gt;Dans la troisième partie de l'article, je vous exposerai une manière d'effectuer diverses actions en évaluant le retour de la requête. On pourra ainsi créer une automatisation d'actions complexes.&lt;br /&gt;&lt;br /&gt;Vos commentaires et remarques sont les bienvenus. J'y répondrai volontiers.&lt;br /&gt;A bientôt&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5200826704807962631-5750354891092998659?l=rapotor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rapotor.blogspot.com/feeds/5750354891092998659/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://rapotor.blogspot.com/2009/02/site-ajax-referencement-historique-et_16.html#comment-form' title='2 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/5750354891092998659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/5750354891092998659'/><link rel='alternate' type='text/html' href='http://rapotor.blogspot.com/2009/02/site-ajax-referencement-historique-et_16.html' title='Site ajax, referencement, historique et favoris (PART 2)'/><author><name>RapotOR</name><uri>http://www.blogger.com/profile/09981627114003941351</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://1.bp.blogspot.com/_Aa55wEAWQr4/SXIAKrtirNI/AAAAAAAAAAM/jSN-9jD_E78/S220/ced.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5200826704807962631.post-280306865984801658</id><published>2009-02-13T09:16:00.012+01:00</published><updated>2009-02-20T17:58:07.432+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='favoris'/><category scheme='http://www.blogger.com/atom/ns#' term='degradable'/><category scheme='http://www.blogger.com/atom/ns#' term='référencement'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='historique'/><category scheme='http://www.blogger.com/atom/ns#' term='prototype'/><title type='text'>Site ajax, referencement, historique et favoris (PART 1)</title><content type='html'>Bonjour,&lt;br /&gt;&lt;br /&gt;Ajax, c'est chouette, c'est beau et en plus cela permet de diminuer les requêtes vers le serveur... Mais lorsqu'on désactive Javascript ou qu'on est un bot de référencement, le contenu peut rapidement nous échapper...&lt;br /&gt;Les autres problèmes concernent la gestion des historiques (bouton précédent) et la mise en favoris. Ces points seront développés dans les parties suivantes de cet article.&lt;br /&gt;&lt;br /&gt;Dans cette première partie, je vais vous développer une méthode qui permet la lisibilité totale de vos pages par les robots des moteurs tels que Google et par les personnes qui n'ont pas activé Javascript (oui cela arrive!!).&lt;br /&gt;Lorsque j'ai débuté avec Ajax, un bon nombre d'articles sur le sujet pourrissaient ce système vu qu'il était limité a une part des utilisateurs. Avec le temps, j'ai accru mes connaissances et j'ai fini par trouver des débuts de solutions.&lt;br /&gt;&lt;br /&gt;Oui je parle beaucoup et peu d'actions donc je propose un truc: commençons.&lt;br /&gt;&lt;br /&gt;Pour que la navigation s'opère normalement pour un utilisateur sans JS, il faut que les liens soient tout a fait conventionnels. Donc, le code HTML doit rester du type:&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;a href=&amp;quot;mapage.html&amp;quot;&amp;gt;Go to my page!&amp;lt;/a&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Par contre, lorsque notre visiteur a activé JS, ces mêmes liens doivent faire une requête sans rafraichir la page entière. La solution est ce qu'on appelle la dégradation de tous liens. Pour cela, je crée un objet qui gèrera la navigation générale de notre site basé sur &lt;span style="font-style:italic;"&gt;Prototype&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;La solution consiste a utilise l'action &lt;span style="font-style:italic;"&gt;OnClick&lt;/span&gt;, de realiser la requete et de renvoyer &lt;span style="font-style:italic;"&gt;false&lt;/span&gt; a la fonction pour que le navigateur ne se rende évidement pas a l'adresse!&lt;br /&gt;&lt;br /&gt;La partie du code intéressant pour faire cela est la suivante:&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;var links = document.getElementsByTagName(&amp;quot;a&amp;quot;); // NOTE 1&lt;br /&gt;$A(links).each(function(link){ // NOTE 2&lt;br /&gt;  link.onclick = function(){&lt;br /&gt;    var anchor = link.href; // NOTE 3&lt;br /&gt;    if (anchor.length==0)&lt;br /&gt;      return false;&lt;br /&gt;    &lt;br /&gt;    // NOTE 4&lt;br /&gt;    var linkOptions = { &amp;quot;ajaxtype&amp;quot;: &amp;quot;link&amp;quot;, &lt;br /&gt;                        &amp;quot;curl&amp;quot;: window.location.href, &lt;br /&gt;                        &amp;quot;hash&amp;quot;: anchor };&lt;br /&gt;&lt;br /&gt;    submitAjax(linkOptions); // NOTE 5&lt;br /&gt;    return false; // NOTE 6&lt;br /&gt;  };&lt;br /&gt;};&lt;br /&gt;    &lt;br /&gt;function submitAjax(linkOptions){&lt;br /&gt;  var ajaxOptions = {&lt;br /&gt;    method: 'post',&lt;br /&gt;    postBody: $H(linkOptions).toQueryString(), // NOTE 7&lt;br /&gt;    onSuccess: function(xhr){&lt;br /&gt;      if ( xhr.status==200 &amp;amp;&amp;amp; xhr.responseText.length &amp;gt; 0){&lt;br /&gt;        // NOTE 9&lt;br /&gt;      }&lt;br /&gt;    }.bind(this),&lt;br /&gt;    onFailure: Prototype.emptyFunction&lt;br /&gt;  };&lt;br /&gt; &lt;br /&gt;  new Ajax.Request(&amp;quot;index.php&amp;quot;,ajaxOptions); // NOTE 8&lt;br /&gt;  return false;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Explications&lt;/span&gt;&lt;br /&gt;1) On commence récupérer tous les liens du document.&lt;br /&gt;2) On parcoure tous les liens.&lt;br /&gt;3) On récupère l'adresse du lien en cours.&lt;br /&gt;4) On prépare les infos (notamment l'adresse) a transmettre&lt;br /&gt;5) On effectue la requete&lt;br /&gt;6) On renvoi &lt;span style="font-style:italic;"&gt;FALSE &lt;/span&gt;pour eviter le changement de page.&lt;br /&gt;7) On ajoute les infos aux paramètres généraux de la requête.&lt;br /&gt;8) On lance la requête&lt;br /&gt;9) Si la requête est un succès, il reste a réaliser quelque chose avec le résultat!&lt;br /&gt;&lt;br /&gt;Incluons maintenant cela dans une classe. A partir de ce code très primaire, il faut prévoir la dégradation d'autres éléments que document. Dans la classe, il faut donc que la fonction soit applicable a n'importe quel élément.&lt;br /&gt;&lt;br /&gt;Version fonctionnelle reprenant les différentes parties:&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;/*  Ajax Navigator &lt;br /&gt; *  (c) 2008-2009 Cedric Lahouste&lt;br /&gt; * &lt;br /&gt; *  Educative version, my final version will be posted in a next article.&lt;br /&gt; *  Version dans un but educatif, ma version finale sera postee dans un prochain article&lt;br /&gt; *  &lt;br /&gt; *  Ajax Navigator is freely distributable under the terms of an MIT-style license.&lt;br /&gt; *&lt;br /&gt; *  Prototype needed.&lt;br /&gt; *&lt;br /&gt; *---------------------------------------------------------------------------------*/&lt;br /&gt;var AjaxNavigator = Class.create({&lt;br /&gt;&lt;br /&gt;  options: {&lt;br /&gt;    url: 'index.php',&lt;br /&gt;    callback : Prototype.emptyFunction  &lt;br /&gt;  },&lt;br /&gt;&lt;br /&gt;  // initialize: gogogo!&lt;br /&gt;  initialize: function(options){&lt;br /&gt;  &lt;br /&gt;    Object.extend(this.options, options || { });&lt;br /&gt;  &lt;br /&gt;    this.applyOn(document);&lt;br /&gt;&lt;br /&gt;  },&lt;br /&gt;&lt;br /&gt;  getHash: function(){&lt;br /&gt;    return ( this.stripBaseUrl(window.location.href).split('#')[1] || this.stripBaseUrl(window.location.href) );&lt;br /&gt;  },&lt;br /&gt;&lt;br /&gt;  // apply on a element. Because can be called by a function getting new html code&lt;br /&gt;  applyOn: function(el){  &lt;br /&gt;    if (typeof el == 'string')&lt;br /&gt;      el = $(el);&lt;br /&gt;   &lt;br /&gt;    var links = el.getElementsByTagName(&amp;quot;a&amp;quot;);&lt;br /&gt;    &lt;br /&gt;    $A(links).each(function(link){&lt;br /&gt;      link.onclick = function(){&lt;br /&gt;        var anchor = link.href;&lt;br /&gt;        if (anchor.length==0)&lt;br /&gt;          return false;&lt;br /&gt;        &lt;br /&gt;        var linkOptions = { &amp;quot;ajaxtype&amp;quot;: &amp;quot;link&amp;quot;, &lt;br /&gt;                            &amp;quot;curl&amp;quot;: window.location.href, &lt;br /&gt;                            &amp;quot;hash&amp;quot;: anchor };&lt;br /&gt;        this.triggerCallback( linkOptions );&lt;br /&gt;&lt;br /&gt;        return false;&lt;br /&gt;      }.bind(this);&lt;br /&gt;    }.bind(this);&lt;br /&gt;    &lt;br /&gt;  },&lt;br /&gt;  &lt;br /&gt;  // the callback, for submitting &amp;amp; requesting url&lt;br /&gt;  triggerCallback: function(vars){&lt;br /&gt;    if ('function' == typeof this.options.callback) {&lt;br /&gt;      this.options.callback(vars);&lt;br /&gt;     }&lt;br /&gt;     return false;&lt;br /&gt;  },&lt;br /&gt;&lt;br /&gt;  // submit &amp;amp; get actions to do!&lt;br /&gt;  submit: function(linkOptions){&lt;br /&gt;&lt;br /&gt;    var ajaxOptions = {&lt;br /&gt;      method: 'post',&lt;br /&gt;      postBody: $H(linkOptions).toQueryString(),&lt;br /&gt;      onSuccess: function(xhr){&lt;br /&gt;        if ( xhr.status==200 &amp;amp;&amp;amp; xhr.responseText.length &amp;gt; 0){&lt;br /&gt;          /*&lt;br /&gt;          next step will be to do something with the response...&lt;br /&gt;          if ( xhr.responseText.isJSON() ){&lt;br /&gt;            this.evaluateResponse( xhr.responseText.evalJSON() );&lt;br /&gt;          }&lt;br /&gt;          */&lt;br /&gt;        }&lt;br /&gt;      }.bind(this),&lt;br /&gt;      onFailure: Prototype.emptyFunction&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    new Ajax.Request(this.options.url,ajaxOptions);&lt;br /&gt;  &lt;br /&gt;    return false;&lt;br /&gt;  &lt;br /&gt;  },&lt;br /&gt;&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;AjaxNav = new AjaxNavigator({&lt;br /&gt;  callback:function(options){&lt;br /&gt;    AjaxNav.submit(options);&lt;br /&gt;  }&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ouf! Maintenant, si JS est activé, chaque clic sur un lien nous permettra de faire la requête Ajax.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Améliorations?&lt;/span&gt;&lt;br /&gt;Les améliorations que nous aborderont dans les articles suivants sont les suivantes:&lt;br /&gt;&lt;br /&gt;* Dégradation des formulaires... On utilise l'action &lt;span style="font-style:italic;"&gt;onSubmit&lt;/span&gt;.&lt;br /&gt;* Éviter l'écrasement de l'action &lt;span style="font-style:italic;"&gt;onClick &lt;/span&gt;(&lt;span style="font-style:italic;"&gt;onSubmit&lt;/span&gt;) si elle est déjà présente sur un lien.&lt;br /&gt;* Gestion de sous-répertoire du type http://www.monsite.com/secondsite ou de sites bases sur l'url rewriting. Pour cela, nous utiliserons la balise &lt;span style="font-style:italic;"&gt;BASE&lt;/span&gt;.&lt;br /&gt;* Gestion du bouton &lt;span style="font-style:italic;"&gt;Précédent&lt;/span&gt;.&lt;br /&gt;Sous firefox, le changement d'ancre crée un point d'historique mais la requête n'est pas rappelée pour changer la page.&lt;br /&gt;Sous IE, un changement d'ancre ne suffit pas a créer un point d'historique.&lt;br /&gt;* Gestion des favoris. La réponse est quasi déjà dévoilée. On utilise les ancres pour indiquer la page en cours.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Un dernier mot&lt;/span&gt;&lt;br /&gt;Cette classe est une version très très épurée de ma version finale. A terme, Ajax Navigator permet d'effectuer des actions très poussée a partir de ce qui est reçu du serveur. Une classe PHP y est associée. Pour la version finale, voici quelques exemples de commandes PHP que nous pourrons faire:&lt;br /&gt;&lt;pre name="code" class="php"&gt;&lt;br /&gt;// Changement d'attributs d'un element&lt;br /&gt;$ajaxNav-&amp;gt;writeAttributes( &amp;quot;ID_ELEMENT&amp;quot; , array('value' =&amp;gt; &amp;quot;&amp;quot; ));&lt;br /&gt;&lt;br /&gt;// redirection ajax (donc sans rafraichissement)&lt;br /&gt;$ajaxNav-&amp;gt;ajaxlocation(&amp;quot;toto.html&amp;quot;);&lt;br /&gt;&lt;br /&gt;// creer une alerte.&lt;br /&gt;$ajaxNav-&amp;gt;alert(&amp;quot;La forme?&amp;quot;);&lt;br /&gt;&lt;br /&gt;/* ajout, suppression de classes.&lt;br /&gt;   &amp;lt;div class=&amp;quot;red&amp;quot;&amp;gt;Coucou toi!&amp;lt;/div&amp;gt;  devient &amp;lt;div class=&amp;quot;red isselected&amp;quot;&amp;gt;Coucou toi!&amp;lt;/div&amp;gt;&lt;br /&gt;*/&lt;br /&gt;$ajaxNav-&amp;gt;addclass(&amp;quot;ID_ELEMENT&amp;quot;,&amp;quot;isselected&amp;quot;);&lt;br /&gt;&lt;br /&gt;// changer le contenu d'une div.&lt;br /&gt;$ajaxNav-&amp;gt;html(&amp;quot;ID_ELEMENT&amp;quot;,&amp;quot;&amp;lt;b&amp;gt;hello&amp;lt;/b&amp;gt;&amp;quot;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Si vous êtes impatient et que vous ne voulez pas attendre la publication des différentes parties de l'article, laissez un message sur ce post avec des infos de contacts.&lt;br /&gt;Pour les autres, rendez-vous sur la PART 2.&lt;br /&gt;&lt;br /&gt;A bientôt.&lt;br /&gt;Cedric&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5200826704807962631-280306865984801658?l=rapotor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rapotor.blogspot.com/feeds/280306865984801658/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://rapotor.blogspot.com/2009/02/site-ajax-referencement-historique-et.html#comment-form' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/280306865984801658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/280306865984801658'/><link rel='alternate' type='text/html' href='http://rapotor.blogspot.com/2009/02/site-ajax-referencement-historique-et.html' title='Site ajax, referencement, historique et favoris (PART 1)'/><author><name>RapotOR</name><uri>http://www.blogger.com/profile/09981627114003941351</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://1.bp.blogspot.com/_Aa55wEAWQr4/SXIAKrtirNI/AAAAAAAAAAM/jSN-9jD_E78/S220/ced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5200826704807962631.post-6677528368612388980</id><published>2009-01-26T20:52:00.004+01:00</published><updated>2009-01-26T21:01:14.715+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='reset.css'/><category scheme='http://www.blogger.com/atom/ns#' term='reset'/><category scheme='http://www.blogger.com/atom/ns#' term='compatibilité'/><category scheme='http://www.blogger.com/atom/ns#' term='ie; ff'/><category scheme='http://www.blogger.com/atom/ns#' term='trick'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>Bien démarrer avec reset.css</title><content type='html'>Hello!&lt;br /&gt;&lt;br /&gt;Voici un petit bout de code pour tenter de mettre les différents navigateurs à égalité avant de démarrer. Vous le mettez dans un fichier &lt;span style="font-style:italic;"&gt;reset.css&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Important:&lt;/span&gt;&lt;br /&gt;Évidement, ce n'est en aucun cas LE produit miracle. Ce bout de code permet juste de mettre les valeurs par défaut identiques. Par contre, les propriétés assimilées différemment continueront à vous hanter...&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="css"&gt;&lt;br /&gt;html, body, div, span, applet, object, iframe,&lt;br /&gt;h1, h2, h3, h4, h5, h6, p, blockquote, pre,&lt;br /&gt;a, abbr, acronym, address, big, cite, code,&lt;br /&gt;del, dfn, em, font, img, ins, kbd, q, s, samp,&lt;br /&gt;small, strike, strong, sub, sup, tt, var,&lt;br /&gt;b, u, i, center,&lt;br /&gt;dl, dt, dd, ol, ul, li,&lt;br /&gt;fieldset, form, label, legend,&lt;br /&gt;table, caption, tbody, tfoot, thead, tr, th, td {&lt;br /&gt;  margin: 0;&lt;br /&gt;  padding: 0;&lt;br /&gt;  border: 0;&lt;br /&gt;  outline: 0;&lt;br /&gt;  font-size: 100%;&lt;br /&gt;  vertical-align: baseline;&lt;br /&gt;  background: transparent;&lt;br /&gt;}&lt;br /&gt;body {&lt;br /&gt;  line-height: 1;&lt;br /&gt;}&lt;br /&gt;ol, ul {&lt;br /&gt;  list-style: none;&lt;br /&gt;}&lt;br /&gt;blockquote, q {&lt;br /&gt;  quotes: none;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* remember to define focus styles! */&lt;br /&gt;:focus {&lt;br /&gt;  outline: 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* remember to highlight inserts somehow! */&lt;br /&gt;ins {&lt;br /&gt;  text-decoration: none;&lt;br /&gt;}&lt;br /&gt;del {&lt;br /&gt;  text-decoration: line-through;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* tables still need 'cellspacing=&amp;quot;0&amp;quot;' in the markup */&lt;br /&gt;table {&lt;br /&gt;  border-collapse: collapse;&lt;br /&gt;  border-spacing: 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A bientôt!&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Source:&lt;/span&gt; &lt;a href="http://meyerweb.com/eric/thoughts/2008/01/15/resetting-again/"&gt;http://meyerweb.com/eric/thoughts/2008/01/15/resetting-again/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5200826704807962631-6677528368612388980?l=rapotor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rapotor.blogspot.com/feeds/6677528368612388980/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://rapotor.blogspot.com/2009/01/bien-dmarrer-avec-resetcss.html#comment-form' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/6677528368612388980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/6677528368612388980'/><link rel='alternate' type='text/html' href='http://rapotor.blogspot.com/2009/01/bien-dmarrer-avec-resetcss.html' title='Bien démarrer avec reset.css'/><author><name>RapotOR</name><uri>http://www.blogger.com/profile/09981627114003941351</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://1.bp.blogspot.com/_Aa55wEAWQr4/SXIAKrtirNI/AAAAAAAAAAM/jSN-9jD_E78/S220/ced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5200826704807962631.post-4864293191258927904</id><published>2009-01-18T12:04:00.011+01:00</published><updated>2009-01-18T12:25:58.971+01:00</updated><title type='text'>Mise en forme du code pour SyntaxHighlighter</title><content type='html'>Voici un petit code PHP pour convertir vos codes source et les afficher dans un article Blogger. Cet article est le complément du premier.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="php"&gt;&lt;br /&gt;$textareaValue = &amp;quot;&amp;quot;;&lt;br /&gt;&lt;br /&gt;echo &amp;quot;&amp;lt;html&amp;gt;&amp;quot;;&lt;br /&gt;echo &amp;quot;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Htmlentities&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;quot;;&lt;br /&gt;echo &amp;quot;&amp;lt;body&amp;gt;&amp;quot;;&lt;br /&gt;&lt;br /&gt;echo &amp;quot;&amp;lt;form method=\&amp;quot;post\&amp;quot; action=\&amp;quot;\&amp;quot;&amp;gt;&amp;quot;;   &lt;br /&gt;&lt;br /&gt;if (isset($_POST[&amp;quot;code&amp;quot;])){&lt;br /&gt; echo &amp;quot;&amp;lt;a href=\&amp;quot;javascript:history.back(1);\&amp;quot;&amp;gt;Previous&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;&amp;quot;;&lt;br /&gt; &lt;br /&gt; if (get_magic_quotes_gpc())&lt;br /&gt;  $textareaValue = stripslashes($_POST[&amp;quot;code&amp;quot;]);&lt;br /&gt; &lt;br /&gt; $textareaValue = &amp;quot;&amp;lt;pre name=\&amp;quot;code\&amp;quot; class=\&amp;quot;&amp;quot;.$_POST[&amp;quot;codetype&amp;quot;].&amp;quot;\&amp;quot;&amp;gt;&amp;quot;.chr(13).htmlentities($textareaValue).chr(13).&amp;quot;&amp;lt;/pre&amp;gt;&amp;quot;;&lt;br /&gt;&lt;br /&gt;}else{&lt;br /&gt; echo &amp;quot;&amp;lt;input type=\&amp;quot;submit\&amp;quot; name=\&amp;quot;Convert\&amp;quot; /&amp;gt;&amp;quot;;&lt;br /&gt; echo &amp;quot;&amp;lt;select name=\&amp;quot;codetype\&amp;quot;&amp;gt;&amp;quot;;&lt;br /&gt; echo &amp;quot;&amp;lt;option value=\&amp;quot;php\&amp;quot;&amp;gt;PHP&amp;lt;/option&amp;gt;&amp;quot;;&lt;br /&gt; echo &amp;quot;&amp;lt;option value=\&amp;quot;xhtml\&amp;quot;&amp;gt;XHTML&amp;lt;/option&amp;gt;&amp;quot;;&lt;br /&gt; echo &amp;quot;&amp;lt;option value=\&amp;quot;js\&amp;quot;&amp;gt;Javascript&amp;lt;/option&amp;gt;&amp;quot;;&lt;br /&gt; echo &amp;quot;&amp;lt;option value=\&amp;quot;css\&amp;quot;&amp;gt;CSS&amp;lt;/option&amp;gt;&amp;quot;;&lt;br /&gt; echo &amp;quot;&amp;lt;/select&amp;gt;&amp;lt;br/&amp;gt;&amp;quot;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;echo &amp;quot;&amp;lt;textarea name=\&amp;quot;code\&amp;quot; cols=\&amp;quot;100\&amp;quot; rows=\&amp;quot;30\&amp;quot;&amp;gt;&amp;quot;.htmlentities($textareaValue).&amp;quot;&amp;lt;/textarea&amp;gt;&amp;lt;br/&amp;gt;&amp;quot;;   &lt;br /&gt;&lt;br /&gt;echo &amp;quot;&amp;lt;/form&amp;gt;&amp;quot;;&lt;br /&gt;&lt;br /&gt;echo &amp;quot;&amp;lt;/body&amp;gt;&amp;quot;;&lt;br /&gt;echo &amp;quot;&amp;lt;/html&amp;gt;&amp;quot;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Cédric&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5200826704807962631-4864293191258927904?l=rapotor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rapotor.blogspot.com/feeds/4864293191258927904/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://rapotor.blogspot.com/2009/01/mise-en-forme-du-code-pour.html#comment-form' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/4864293191258927904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/4864293191258927904'/><link rel='alternate' type='text/html' href='http://rapotor.blogspot.com/2009/01/mise-en-forme-du-code-pour.html' title='Mise en forme du code pour SyntaxHighlighter'/><author><name>RapotOR</name><uri>http://www.blogger.com/profile/09981627114003941351</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://1.bp.blogspot.com/_Aa55wEAWQr4/SXIAKrtirNI/AAAAAAAAAAM/jSN-9jD_E78/S220/ced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5200826704807962631.post-8227729486550101967</id><published>2009-01-17T16:28:00.004+01:00</published><updated>2009-02-13T14:37:44.014+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='documentation'/><category scheme='http://www.blogger.com/atom/ns#' term='debuter'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='extjs'/><category scheme='http://www.blogger.com/atom/ns#' term='tutoriel'/><title type='text'>Quelques exemples de base pour ExtJS</title><content type='html'>J'avais écrit un article sur librairie javascript &lt;a href="http://extjs.com"&gt;ExtJS&lt;/a&gt;.&lt;br /&gt;Celui-ci comporte diverses astuces qu'un débutant rencontre à coup sûr lorsqu'il débute avec &lt;a href="http://extjs.com"&gt;ExtJS&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Je vous invite à lire:&lt;br /&gt;La version en anglais: &lt;a href="http://extjs.com/learn/Tutorial:Some_Usefull_examples"&gt;http://extjs.com/learn/Tutorial:Some_Usefull_examples&lt;/a&gt; &lt;br /&gt;ou&lt;br /&gt;La version en français: &lt;a href="http://extjs.com/learn/Tutorial:Quelques_exemples_utiles"&gt;http://extjs.com/learn/Tutorial:Quelques_exemples_utiles&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;La documentation officielle est également &lt;a href="http://extjs.com/deploy/dev/docs/"&gt;à consulter&lt;/a&gt;. Elle est très bien faite!&lt;br /&gt;&lt;br /&gt;Contenu du tutoriel en français:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Introduction&lt;/h3&gt;&lt;br /&gt;J'ai réalisé une application personnelle. A mes débuts avec ExtJs, pas mal de problèmes sont venu bloquer ma progression et j'ai voulu les rassembler dans ce tutoriel pour aider les personnes qui débutent.&lt;br /&gt;Mes recherches dans la doc et les forums a été assez importante. J'espère que la votre sera beaucoup plus petite grâce à ce tutoriel.&lt;br /&gt;&lt;br /&gt;Enfin, je voudrais préciser que ma connaissance de ExtJs n'est pas encore parfaite; il y a donc certainement des améliorations possibles au code. Donc, désolé pour d'éventuelles conneries... Je veux juste vous aider :)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Programmation Orientée Object&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;J'avais réalisé ma première version de mon application sans PPO mais c'était une erreur pour une grosse application... Je pense. PPO est beaucoup plus simple d'utilisation.&lt;br /&gt;Voici une adresse : http://extjs.com/learn/Manual:Basic_Application_Design&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;s.gif sur internet?? Non!!!&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;C'est déjà présent dans d'autres tutoriels mais une fois de plus vaut mieux qu'une fois de moins.&lt;br /&gt;&lt;br /&gt;Ajoutez cette ligne pour que ExtJs utilise l'image locale:&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;Ext.BLANK_IMAGE_URL = 'ext/resources/images/default/s.gif';  // 2.0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Selection de la première ligne&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;C'est toujours utile de pouvoir selectionner la première ligne d'un combo ou d'une grid.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Les Combo&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;2 Solutions:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Première:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Votre 'store' est déjà créé et charger dans votre application (orientée object).&lt;br /&gt;Effectivement, j'ai personnellement changé mes stores petits et souvent utilisés dans ma classe.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;var MyCombo = new Ext.form.ComboBox({&lt;br /&gt; displayField:'field1',&lt;br /&gt; store: store1,                          &lt;br /&gt; valueField: 'id',&lt;br /&gt; editable: false,&lt;br /&gt; typeAhead: true,&lt;br /&gt; mode: 'local',&lt;br /&gt; triggerAction: 'all',&lt;br /&gt; emptyText:'Choose...',&lt;br /&gt; selectOnFocus:true,&lt;br /&gt; forceSelection : true,&lt;br /&gt; anchor:'95%',&lt;br /&gt; listeners: {&lt;br /&gt;   beforerender: function(combo){&lt;br /&gt;     MyCombo.setValue(MyCombo.store.getAt(0).data.id); // Ligne finale&lt;br /&gt;     // MyCombo.setValue(MyCombo.store.collect('id', true)[0]); //pas assez rapide&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;La ligne finale est la ligne correspondant à la selection de la première ligne.&lt;br /&gt;Le champ 'id' correspond au champ 'valueField'.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Deuxième: &lt;/span&gt;&lt;br /&gt;La deuxième solution envisage le cas ou il faut également créer le store avec le combo.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;var MyCombo = new Ext.form.ComboBox({&lt;br /&gt; displayField:'field1',&lt;br /&gt; store: new Ext.data.store({&lt;br /&gt;   url: 'getdata.php',&lt;br /&gt;   autoLoad: true,&lt;br /&gt;   listeners: {&lt;br /&gt;     load: function(){&lt;br /&gt;       MyCombo.setValue(MyCombo.store.getAt(0).data.id); // Ligne finale&lt;br /&gt;       // MyCombo.setValue(MyCombo.store.collect('id', true)[0]);  // pas assez rapide&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   reader: new Ext.data.JsonReader({&lt;br /&gt;     root: 'data'  // le champ 'root' des données; à enlever si nécessaire&lt;br /&gt;   }, ['id','field1', 'field2'])&lt;br /&gt; }),                          &lt;br /&gt; valueField: 'id',&lt;br /&gt; editable: false,&lt;br /&gt; typeAhead: true,&lt;br /&gt; mode: 'local',&lt;br /&gt; triggerAction: 'all',&lt;br /&gt; emptyText:'Choose...',&lt;br /&gt; selectOnFocus:true,&lt;br /&gt; forceSelection : true,&lt;br /&gt; anchor:'95%'&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Les Grid&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Pour les grids, c'est le meme système à part qu'on utilise comme ligne finale celle ci :&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;MyGrid.getSelectionModel().selectRow(0);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Examples avec Combo&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Alors ici, c'est une petit code pour montre plusieurs champs dans le combo.&lt;br /&gt;On utilise un template : tpl.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;var myCombo = new Ext.form.ComboBox({&lt;br /&gt; // use tpl !!!&lt;br /&gt; tpl: '&amp;lt;tpl for=&amp;quot;.&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;x-combo-list-item&amp;quot;&amp;gt;{id} &amp;gt; {field1}&amp;lt;/div&amp;gt;&amp;lt;/tpl&amp;gt;',&lt;br /&gt; valueField: 'id',&lt;br /&gt; store: myStore,&lt;br /&gt; allowBlank: true,&lt;br /&gt; typeAhead: true,&lt;br /&gt; mode: 'local',&lt;br /&gt; triggerAction: 'all'&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Examples et astuces pour Grid&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Différents affichages de colonnes&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Voici quelques exemples d'affichage de différentes données pour vous donner des idées. Vous pouvez envisage tout et n'importe quoi.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;// donc on cr&amp;eacute;e un objet 'ColumnModel'&lt;br /&gt;var cmLIST = new Ext.grid.ColumnModel([&lt;br /&gt;{&lt;br /&gt;  // ajouter un peu de text &amp;agrave; la value du champ&lt;br /&gt;  header: &amp;quot;ID&amp;quot;,&lt;br /&gt;  dataIndex: 'id',&lt;br /&gt;  sortable: true,&lt;br /&gt;  renderer: function(v,params,record){&lt;br /&gt;    return 'TOTO-'+v;&lt;br /&gt;  },&lt;br /&gt;  width: 30         &lt;br /&gt;},{&lt;br /&gt;  // On peut meme ajouter de l'HTML&lt;br /&gt;  header: &amp;quot;Field 1&amp;quot;,&lt;br /&gt;  dataIndex: 'field1',&lt;br /&gt;  sortable: true,&lt;br /&gt;  renderer: function(v,params,record){&lt;br /&gt;    return '&amp;lt;b&amp;gt;'+v+'&amp;lt;/b&amp;gt;';&lt;br /&gt;  },&lt;br /&gt;  width: 50     &lt;br /&gt;},{&lt;br /&gt;  // Utiliser un autre champ dans celui en cours; ajouter de la couleur...&lt;br /&gt;  // par exemple, ici, j'utilise le field3 pour afficher le field2.&lt;br /&gt;  header: &amp;quot;Field 2&amp;quot;,&lt;br /&gt;  dataIndex: 'field2',&lt;br /&gt;  sortable: true,&lt;br /&gt;  renderer: function(v,params,record){&lt;br /&gt;    if (record.data.field3 == 1){&lt;br /&gt;      // imagine that 'field2' is an other field in store&lt;br /&gt;      return v+':&amp;lt;font color=&amp;quot;#00FF00&amp;quot;&amp;gt;'+record.data.field3+'&amp;lt;/font&amp;gt;';&lt;br /&gt;    }else{&lt;br /&gt;      return v+':&amp;lt;font color=&amp;quot;#FF0000&amp;quot;&amp;gt;'+record.data.field3+'&amp;lt;/font&amp;gt;';&lt;br /&gt;    }&lt;br /&gt;  },&lt;br /&gt;  width: 50&lt;br /&gt;},{&lt;br /&gt;  // afficher une date. :)&lt;br /&gt;  // perso j'utilise tjs le temps unix... un petit format et hop!&lt;br /&gt;  header: &amp;quot;Date&amp;quot;,&lt;br /&gt;  dataIndex: 'fielddate',&lt;br /&gt;  sortable: true,     &lt;br /&gt;  renderer: function(v,params,record){&lt;br /&gt;   return Ext.util.Format.date(v,'d-m-Y');  // change the mask if you want..&lt;br /&gt;  },    &lt;br /&gt;  width: 50&lt;br /&gt;},{&lt;br /&gt;  // On peut meme ajouter un champ imaginaire calcul&amp;eacute; &amp;agrave; partir d'existants&lt;br /&gt;  header: &amp;quot;Cost&amp;quot;,&lt;br /&gt;  width: 60,&lt;br /&gt;  renderer: function(v, params, record){&lt;br /&gt;    return (record.data.pricebyunit * record.data.quantity);&lt;br /&gt;  },&lt;br /&gt;  sortable: true&lt;br /&gt;}&lt;br /&gt;]);&lt;br /&gt;&lt;br /&gt;var myGrid= new Ext.grid.GridPanel({&lt;br /&gt;  id: 'myGrid',&lt;br /&gt;  anchor: '100% 100%',&lt;br /&gt;  store: myStore,  // ici un store d&amp;eacute;j&amp;agrave; cr&amp;eacute;&amp;eacute; avant. avec les diff&amp;eacute;rents champs&lt;br /&gt;  cm: cmLIST,  // et ici on d&amp;eacute;finit l'utilisation de notre ColumnModel&lt;br /&gt;  ...&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Colonne à partir d'un store&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Dans la plus part des cas, avec la configuration des bases de données, on utilise des ID pour faire un lien avec une autre table. alors évidement, on récupère des numéros dans certains champs et pas une valeur texte ou autre. Pour ca, la ligne suivante permet la récupération dans un autre store que celui de la grid du texte correspondant à un ID.&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;...&lt;br /&gt;  // Dans un champ du ColumnModel&lt;br /&gt;  renderer: function(v, params, record){ &lt;br /&gt;     return store2.getAt(stores2.find('id',v)).get('field1');      &lt;br /&gt;  },  &lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Affichage d'une ligne&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Dans le GridPanel, vous pouvez utiliser la fonction 'getRowClass' dans la propriété 'view' pour changer la css de la ligne.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;...&lt;br /&gt;  view: new Ext.grid.GridView({&lt;br /&gt;     getRowClass: function(row, index) {&lt;br /&gt;         var cls = '';&lt;br /&gt;         var data = row.data;&lt;br /&gt;         &lt;br /&gt;         // ici un petit test pour changer ou pas la css... changez par le votre!&lt;br /&gt;         if ( data.field1 &amp;lt; 0  ) {&lt;br /&gt;            cls = 'row-invalid'; // on assigne le nom d'une classe css!&lt;br /&gt;         }else{&lt;br /&gt;            cls = '';&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;         return cls; // on retource la valeur...&lt;br /&gt;     }&lt;br /&gt;  }),&lt;br /&gt;... &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="css"&gt;&lt;br /&gt;// ici ma classe css qui rendra rouge la ligne si on l'utilise... bien s&amp;ucirc;r!&lt;br /&gt;.row-invalid { &lt;br /&gt;    background-color: red !important;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Selectionner une seule ligne&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;La propriété singleselect... bien sur!&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;...&lt;br /&gt;  sm: new Ext.grid.RowSelectionModel({singleSelect:true}),&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Examples et astuces avec EditorGrid&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Colonne Date&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Ici on doit pouvoir afficher la date correctement et en même temps l'éditer !! wow!!&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;...&lt;br /&gt;// dans le ColumnModel&lt;br /&gt;{&lt;br /&gt;  header: &amp;quot;Date&amp;quot;,&lt;br /&gt;  dataIndex: 'datefield',&lt;br /&gt;  sortable: true,     &lt;br /&gt;  renderer: Ext.util.Format.dateRenderer('d-m-Y'), &lt;br /&gt;  width: 80,&lt;br /&gt;  editor: new Ext.form.DateField({&lt;br /&gt;    format: 'd-m-Y'&lt;br /&gt;  })&lt;br /&gt;} &lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Colonne avec combo&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;...&lt;br /&gt;// dans le ColumnModel&lt;br /&gt;{&lt;br /&gt;  header: &amp;quot;Suppliers&amp;quot;,&lt;br /&gt;  dataIndex: 'supplierid',&lt;br /&gt;  sortable: true,     &lt;br /&gt;  width: 80,&lt;br /&gt;  renderer: function(v, params, record){ &lt;br /&gt;   // ici on affiche la value &amp;agrave; partir du store comme d&amp;eacute;j&amp;agrave; montr&amp;eacute; dans la section grid&lt;br /&gt;   return storeSuppliers.getAt(storeSuppliers.find('id',v)).get('name');      &lt;br /&gt;  }, &lt;br /&gt;  // et on cr&amp;eacute;e notre combo qui va chercher dans le meme store&lt;br /&gt;  // ainsi la valeur du champ est tjs l'ID et pas le texte! &lt;br /&gt;  editor: new Ext.form.ComboBox({&lt;br /&gt;    store: storeSuppliers,&lt;br /&gt;    triggerAction: 'all',&lt;br /&gt;    emptyText:'',&lt;br /&gt;    selectOnFocus: true,&lt;br /&gt;    valueField: 'id',&lt;br /&gt;    displayField: 'name'&lt;br /&gt;  }),&lt;br /&gt;  width: 200 &lt;br /&gt;}&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Editeur dynamique&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Peut être que vous devriez avoir besoin de changer l'éditeur en fonction des données.&lt;br /&gt;Pour cet exemple, je vais utiliser parfois un textfield ou parfois un combo!&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;// a store&lt;br /&gt;var storeField = new Ext.data.Store({&lt;br /&gt;   url: 'getdata.php',&lt;br /&gt;   reader: new Ext.data.JsonReader({&lt;br /&gt;      root: 'enreg'&lt;br /&gt;   }, ['id','field1', 'field2'])&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;// un combo         &lt;br /&gt;var editorCombo = new Ext.form.ComboBox({&lt;br /&gt;   valueField: 'id',&lt;br /&gt;   displayField: 'field1',&lt;br /&gt;   store: storeField,&lt;br /&gt;   allowBlank: true,&lt;br /&gt;   typeAhead: true,&lt;br /&gt;   mode: 'local',&lt;br /&gt;   triggerAction: 'all',&lt;br /&gt;   emptyText:'Choose...',&lt;br /&gt;   selectOnFocus: true,&lt;br /&gt;   forceSelection : true,&lt;br /&gt;   editable: true&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;// ici on cr&amp;eacute;e l'&amp;eacute;diteur en fonction du combo        &lt;br /&gt;var objEditorCombo = new Ext.grid.GridEditor(editorCombo);&lt;br /&gt;&lt;br /&gt;// un textfield&lt;br /&gt;var editorText = new Ext.form.TextField({ allowBlank: false });    &lt;br /&gt;&lt;br /&gt;// ici on cr&amp;eacute;e l'&amp;eacute;diteur en fonction du textfield&lt;br /&gt;var objEditorText = new Ext.grid.GridEditor(editorText);&lt;br /&gt;         &lt;br /&gt;var cmLIST = new Ext.grid.ColumnModel([&lt;br /&gt;//...&lt;br /&gt;{&lt;br /&gt;  header: &amp;quot;Field 1&amp;quot;,&lt;br /&gt;  dataIndex: 'field1',&lt;br /&gt;  sortable: true,   &lt;br /&gt;  width: 400,  &lt;br /&gt;  editor: objEditorCombo  // on assigne un des 2 &amp;eacute;diteurs.&lt;br /&gt;}&lt;br /&gt;//.... &lt;br /&gt;]); &lt;br /&gt;&lt;br /&gt;var myGrid = new Ext.grid.EditorGridPanel({&lt;br /&gt;  store: myStore,&lt;br /&gt;  // ... ici, n'importe quelle propri&amp;eacute;t&amp;eacute;s..&lt;br /&gt;  cm: cmLIST,  // my column model&lt;br /&gt;  listeners:{&lt;br /&gt;      // au moment du double click on va changer l'&amp;eacute;diteur&lt;br /&gt;      celldblclick: function(grid, rowIndex, columnIndex, e){&lt;br /&gt;                    &lt;br /&gt;          // mais seulement pour le champ 'field1'...&lt;br /&gt;          // faudrait pas le changer pour un autre ;)&lt;br /&gt;          if (grid.getColumnModel().getDataIndex(columnIndex) == &amp;quot;field1&amp;quot;){&lt;br /&gt;             // ici un test exemple... &amp;agrave; changer par le votre&lt;br /&gt;             if (grid.store.getAt(rowIndex).get('field2') == 0){&lt;br /&gt;                 // on assigne dans ce cas le textfield&lt;br /&gt;                 grid.getColumnModel().setEditor(columnIndex,objEditorText);&lt;br /&gt;             }else{&lt;br /&gt;                 // et dans l'autre le combo&lt;br /&gt;                 grid.getColumnModel().setEditor(columnIndex,objEditorCombo);&lt;br /&gt;             }&lt;br /&gt;          }&lt;br /&gt;                    &lt;br /&gt;      },&lt;br /&gt;      afteredit: function(e){&lt;br /&gt;        // apr&amp;egrave;s l'&amp;eacute;dition, dans le cas ou l'&amp;eacute;diteur &amp;eacute;tait le combo,&lt;br /&gt;        // il se pourrait qu'il faille changer en m&amp;ecirc;me temps d'autres colonnes&lt;br /&gt;        // qui sont li&amp;eacute;es.        &lt;br /&gt;        if (e.field == 'field1' &amp;amp;&amp;amp; e.record.get('field2') == 0){&lt;br /&gt;e.record.set('field2',storeField.getAt(storeField.find('id',e.value)).get('field2'));           &lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;      }  &lt;br /&gt;  }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Eviter des pertes de mémoire&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Il y a pas mal de topics qui parlent de pertes de mémoires. Qu'est ce que c'est? Avec l'utilisation de certains composants, certaines DIV ne sont pas détruites avec l'utilisation de l'application et la mémoire augmente sans cesse...&lt;br /&gt;J'ai remarqué cela avec msg, modal windows, grid pour l'instant.&lt;br /&gt;Vous vérifier cela, utilisez l'extension FIREBUG sous FIREFOX.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Ext.msg&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Ce n'est en fait pas vraiment un problème. A chaque fois qu'une fenêtre apparaît, les 'shadow' (masque, ombres sous les fenêtres etc...) DIV ne sont pas créées à chaque fois; elles sont réutilisées à nouveau à chaque fenêtre ('show'). Donc ce n'est pas nécessaire de les supprimer.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Modal window&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Argh! Pas très bon!&lt;br /&gt;C'est la fenêtre avec l'option d'un masque qui cache l'application en arrière.&lt;br /&gt;J'ai créé une petite extend de Ext.Window avec un listener qui supprimer les mask, shadow correspondants&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;Ext.ModalWindow = Ext.extend(Ext.Window, {&lt;br /&gt;  &lt;br /&gt;  initComponent : function(){&lt;br /&gt;    Ext.Window.superclass.initComponent.call(this);&lt;br /&gt;  },&lt;br /&gt;  &lt;br /&gt;  modal: true,&lt;br /&gt;  &lt;br /&gt;  closable: true,&lt;br /&gt;        &lt;br /&gt;  modal: true,&lt;br /&gt;  &lt;br /&gt;  shadow: false,&lt;br /&gt;  &lt;br /&gt;  minimizable: false,&lt;br /&gt;  &lt;br /&gt;  draggable: false,&lt;br /&gt;  &lt;br /&gt;  resizable: false,&lt;br /&gt;  &lt;br /&gt;  width: 500,&lt;br /&gt;  &lt;br /&gt;  height: 'auto',&lt;br /&gt;        &lt;br /&gt;  layout: 'anchor',&lt;br /&gt;&lt;br /&gt;  plain: true, &lt;br /&gt;  &lt;br /&gt;  listeners: {&lt;br /&gt;  &lt;br /&gt;    beforedestroy: function(w){&lt;br /&gt;    &lt;br /&gt;      if (w.mask){Ext.destroy(w.mask);}&lt;br /&gt;      if (w.proxy){Ext.destroy(w.proxy);}&lt;br /&gt;      if (w.plain){Ext.destroy(w.plain);}&lt;br /&gt;      &lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;// et son utilisation :&lt;br /&gt;&lt;br /&gt;var modalWin = new Ext.ModalWindow({&lt;br /&gt;      &lt;br /&gt;  id: 'modalWin',&lt;br /&gt;        &lt;br /&gt;  title: 'Intranet Logon.',&lt;br /&gt;        &lt;br /&gt;  width: 360,&lt;br /&gt;        &lt;br /&gt;  buttons: [&lt;br /&gt;  {&lt;br /&gt;    text: 'Quit',&lt;br /&gt;    handler: function(){&lt;br /&gt;       modalWin.destroy();&lt;br /&gt;    }&lt;br /&gt;  }]&lt;br /&gt;&lt;br /&gt;});        &lt;br /&gt;      &lt;br /&gt;modalWin.show();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Vider un panel&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;Dans ce cas, j'avais quelques grids dans un panel et certaines DIV n'était pas supprimées. Du coup, à chaque fois, j'avais des DIV qui s'amoncelait... et la mémoire qui augmentait...&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;div id=&amp;quot;ext-gen728&amp;quot; class=&amp;quot;x-dd-drag-proxy x-dd-drop-nodrop x-grid3-col-dd&amp;quot; style=&amp;quot;position: absolute; z-index: 15000; visibility: hidden; left: -10000px; top: -10000px;&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;div class=&amp;quot;x-dd-drop-icon&amp;quot;/&amp;gt;&lt;br /&gt;&amp;lt;div id=&amp;quot;ext-gen730&amp;quot; class=&amp;quot;x-dd-drag-ghost&amp;quot;/&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;div id=&amp;quot;ext-gen733&amp;quot; class=&amp;quot;col-move-top&amp;quot;/&amp;gt;&lt;br /&gt;&amp;lt;div id=&amp;quot;ext-gen734&amp;quot; class=&amp;quot;col-move-bottom&amp;quot;/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;La meilleure solution pour moi était :&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt; myPanel.items.each(function(item, index, len){&lt;br /&gt;   item.purgeListeners();&lt;br /&gt;   myPanel.remove(item,true); &lt;br /&gt;   // le 'true' , cest pour l'option destroy.&lt;br /&gt;   // &amp;agrave; noter que le '.destroy', ca marchait pas des masses pour &amp;eacute;viter les DIV restantes.&lt;br /&gt; });&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Form avec grid&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Comme pas mal de personnes sur le forum, j'ai voulu mettre une grid dans un formpanel... mais evidement, ce ne fut pas si facile au moment du submit ... :D&lt;br /&gt;Ici, c'est ma méthode. Peut être il y en a d'autres.&lt;br /&gt;( Une extend du formpanel avec grid serait peut être mieux... )&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Changement des données&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt; Ext.Ajax.request({&lt;br /&gt;    url: 'getdata.php?type=da&amp;idv='+PR_ID,&lt;br /&gt;    callback: function(options,success,response){&lt;br /&gt;               &lt;br /&gt;       var myResponse = Ext.util.JSON.decode(response.responseText);&lt;br /&gt;                  &lt;br /&gt;       myForm.form.setValues(myResponse);&lt;br /&gt;                  &lt;br /&gt;       // mettre les données dans la grid à partir du champ grid1&lt;br /&gt;       var myGrid = Ext.getCmp('myGrid');&lt;br /&gt;       myGrid.store.loadData(myResponse.grid1);&lt;br /&gt;                  &lt;br /&gt;     }&lt;br /&gt; });&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Savegarde des données&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="js"&gt;&lt;br /&gt;var myForm = new Ext.form.FormPanel({&lt;br /&gt;  ...&lt;br /&gt;  items: [&lt;br /&gt;  {&lt;br /&gt;    xtype: 'textfield',&lt;br /&gt;    name: 'field1',&lt;br /&gt;    fieldLabel: 'Field 1'&lt;br /&gt;  },{&lt;br /&gt;    xtype: 'textfield',&lt;br /&gt;    name: 'field2',&lt;br /&gt;    fieldLabel: 'Field 2'&lt;br /&gt;  },{&lt;br /&gt;    xtype: 'grid',&lt;br /&gt;    // ... d'autres propri&amp;eacute;t&amp;eacute;s ici&lt;br /&gt;  }&lt;br /&gt;  ]&lt;br /&gt;  bbar: [     &lt;br /&gt;  {&lt;br /&gt;     xtype: 'button', // c'est le m&amp;ecirc;me que d'utiliser &amp;quot;new Ext.Button()&amp;quot; (voir doc)&lt;br /&gt;     text: 'Save' ,&lt;br /&gt;     iconCls: 'save', &lt;br /&gt;     handler : function() {&lt;br /&gt;&lt;br /&gt;       var storeValue=[];&lt;br /&gt;       var myGrid = Ext.getCmp('myGrid');&lt;br /&gt;       var allRecords = myGrid.store.getRange(0);&lt;br /&gt;       &lt;br /&gt;       // je mets les donn&amp;eacute;es dans une variable storeValue&lt;br /&gt;       for (i=0;i &amp;lt; allRecords.length;i++)&lt;br /&gt;       {&lt;br /&gt;         storeValue[i] = allRecords[i].data;&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       // je r&amp;eacute;cup les donn&amp;eacute;es de la form&lt;br /&gt;       var dataForm = generalInfos.getForm().getValues();&lt;br /&gt;&lt;br /&gt;       // j'envoi la requete ajax avec les donn&amp;eacute;es compl&amp;egrave;tes.&lt;br /&gt;       Ext.Ajax.request({&lt;br /&gt;                           &lt;br /&gt;         url: 'submitdata.php',&lt;br /&gt;         &lt;br /&gt;         // je param&amp;egrave;tre la requ&amp;ecirc;te                      &lt;br /&gt;         params: {&lt;br /&gt;            param1: 'toto',&lt;br /&gt;            param2: 'titi',&lt;br /&gt;            field1: dataForm.field1,&lt;br /&gt;            field2: dataForm.field2,&lt;br /&gt;            grid1: Ext.encode(storeValue)  // Donn&amp;eacute;es de la grid au format JSON...&lt;br /&gt;         },&lt;br /&gt;                               &lt;br /&gt;         callback: function(options,success,response){&lt;br /&gt;                               &lt;br /&gt;            alert('SUBMIT!');&lt;br /&gt;                                  &lt;br /&gt;         }&lt;br /&gt;                               &lt;br /&gt;       }); &lt;br /&gt;     }&lt;br /&gt;  }&lt;br /&gt;  ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Merci et à bientôt.&lt;br /&gt;&lt;br /&gt;Cédric&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5200826704807962631-8227729486550101967?l=rapotor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rapotor.blogspot.com/feeds/8227729486550101967/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://rapotor.blogspot.com/2009/01/quelques-exemples-de-base-pour-extjs.html#comment-form' title='1 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/8227729486550101967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/8227729486550101967'/><link rel='alternate' type='text/html' href='http://rapotor.blogspot.com/2009/01/quelques-exemples-de-base-pour-extjs.html' title='Quelques exemples de base pour ExtJS'/><author><name>RapotOR</name><uri>http://www.blogger.com/profile/09981627114003941351</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://1.bp.blogspot.com/_Aa55wEAWQr4/SXIAKrtirNI/AAAAAAAAAAM/jSN-9jD_E78/S220/ced.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5200826704807962631.post-4331354576511342560</id><published>2009-01-17T15:13:00.008+01:00</published><updated>2009-01-18T12:34:08.250+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='coloration'/><category scheme='http://www.blogger.com/atom/ns#' term='highlight'/><category scheme='http://www.blogger.com/atom/ns#' term='Blogger'/><category scheme='http://www.blogger.com/atom/ns#' term='souce code'/><category scheme='http://www.blogger.com/atom/ns#' term='syntaxe'/><category scheme='http://www.blogger.com/atom/ns#' term='tutoriel'/><title type='text'>Coloration syntaxique de code source sur Blogger.</title><content type='html'>Premier post! Et l'aventure commence!&lt;br /&gt;Celui-ci concerne la coloration syntaxique de code source dans un article Blogger.&lt;br /&gt;Demo:&lt;br /&gt;&lt;pre name="code" class="php"&gt;&lt;br /&gt;echo "Ceci est une démo";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Comment faire? &lt;br /&gt;Lorsque j'ai cherché pour cette astuce, je suis tombé presque directement sur &lt;a href="http://code.google.com/p/syntaxhighlighter/"&gt;SyntaxHighlighter&lt;/a&gt;. Il me semble le meilleur et c'est celui-là qu'on utilisera dans ce tutoriel.&lt;br /&gt;Premier problème que j'ai rencontré dans une paire de tutos, c'est qu'il fallait uploader sur un hébergement. Perso, cela ne me bottait pas trop... si on a un blog sans hébergement c'est pas pour devoir encore héberger quelque chose.&lt;br /&gt;Astuce: il faut utiliser les fichiers directement sur le serveur google et le tour est joué!&lt;br /&gt;&lt;br /&gt;Etape 1: Se rendre dans "Mise en page" (template) et se rendre dans "Modifier le code HTML". (Pas trop dur ;) )&lt;br /&gt;&lt;br /&gt;Etape 2: Coller le code suivant juste en dessous de &lt;span style="font-weight:bold;"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="html"&gt;&lt;br /&gt;&amp;lt;link href='http://syntaxhighlighter.googlecode.com/svn/trunk/Styles/SyntaxHighlighter.css' rel='stylesheet' type='text/css'/&amp;gt;  &lt;br /&gt;&amp;lt;script language='javascript' src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shCore.js'/&amp;gt;   &lt;br /&gt;&amp;lt;script language='javascript' src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/clipboard.swf'/&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Etape 3: Choisir les languages à vouloir afficher. J'ai choisi php, sql, css, html. Vous vous rendez sur &lt;a href="http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/"&gt;cette page&lt;/a&gt;. Vous choisissez les fichiers correspondants: &lt;span style="font-style:italic;"&gt;shBrushPhp.js&lt;/span&gt; pour &lt;span style="font-weight:bold;"&gt;PHP&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;shBrushCss.js&lt;/span&gt; pour &lt;span style="font-weight:bold;"&gt;CSS&lt;/span&gt;, etc...&lt;br /&gt;A la suite des premières lignes de code collées, il faut donc ajouter une ligne par language à supporter. Voici la ligne pour &lt;span style="font-weight:bold;"&gt;PHP&lt;/span&gt;:&lt;br /&gt;Important: Le &lt;span style="font-weight:bold;"&gt;HTML&lt;/span&gt; se trouve dans &lt;span style="font-style:italic;"&gt;shBrushXml.js&lt;/span&gt;!&lt;br /&gt;&lt;pre name="code" class="html"&gt;&lt;br /&gt;&amp;lt;script language='javascript' src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushPhp.js'/&amp;gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Etape 4: Coller la suite juste avant &lt;span style="font-weight:bold;"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;. Cela sert à initialiser le script de mise en page de vos codes. &lt;br /&gt;Petit détail tout de même! Le script est un peu différent de l'original. Effectivement, Blogger n'aime pas trop les &amp;lt;br/&amp;gt;; ils sont remplacés par un retour à la ligne. Le code ci-dessous permet de contourner le problème. &lt;a href="http://yehhou.blogspot.com/2007/06/blogger-dpsyntaxhighlighter.html"&gt;Merci les chinois&lt;/a&gt;.&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;script class='javascript'&amp;gt;&lt;br /&gt;//&amp;lt;![CDATA[&lt;br /&gt;  function FindTagsByName(container, name, Tag)&lt;br /&gt;  {&lt;br /&gt;      var elements = document.getElementsByTagName(Tag);&lt;br /&gt;      for (var i = 0; i &amp;lt; elements.length; i++)&lt;br /&gt;      {&lt;br /&gt;          if (elements[i].getAttribute(&amp;quot;name&amp;quot;) == name)&lt;br /&gt;          {&lt;br /&gt;              container.push(elements[i]);&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;  var elements = [];&lt;br /&gt;  FindTagsByName(elements, &amp;quot;code&amp;quot;, &amp;quot;pre&amp;quot;);&lt;br /&gt;  FindTagsByName(elements, &amp;quot;code&amp;quot;, &amp;quot;textarea&amp;quot;);&lt;br /&gt;&lt;br /&gt;for(var i=0; i &amp;lt; elements.length; i++) {&lt;br /&gt;if(elements[i].nodeName.toUpperCase() == &amp;quot;TEXTAREA&amp;quot;) {&lt;br /&gt; var childNode = elements[i].childNodes[0];&lt;br /&gt; var newNode = document.createTextNode(childNode.nodeValue.replace(/&amp;lt;br\s*\/?&amp;gt;/gi,'\n'));&lt;br /&gt; elements[i].replaceChild(newNode, childNode);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;else if(elements[i].nodeName.toUpperCase() == &amp;quot;PRE&amp;quot;) {&lt;br /&gt; brs = elements[i].getElementsByTagName(&amp;quot;br&amp;quot;);&lt;br /&gt; for(var j = 0, brLength = brs.length; j &amp;lt; brLength; j++) {&lt;br /&gt;  var newNode = document.createTextNode(&amp;quot;\n&amp;quot;);&lt;br /&gt;  elements[i].replaceChild(newNode, brs[0]);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;dp.SyntaxHighlighter.HighlightAll(&amp;quot;code&amp;quot;);&lt;br /&gt;//]]&amp;gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Etape 5: Etape importante... qui rend fou si elle nous échape. En haut de la page, il faut supprimer le DOCTYPE (c'est la ligne tout en haut qui contient DOCTYPE ;) ). C'est en contradiction avec celui situé sur google. Du coup, ça s'affiche pas bien!&lt;br /&gt;&lt;br /&gt;Etape 6: On appuie sur "Enregistrer le modèle". Oula! C'est dur cette étape-ci!&lt;br /&gt;&lt;br /&gt;Etape 7 : Allez courage! Pour terminer... On insère notre code source! Après tout c'est le but non? &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Comment Faire cela? &lt;/span&gt;&lt;br /&gt;Sur la page de rédaction du message, il faut passer en mode HTML "Modifier le code HTML".&lt;br /&gt;&lt;br /&gt;Etape 8: Il faut convertir le code que l'on veut afficher. Soit vous vous créer un script en &lt;span style="font-weight:bold;"&gt;PHP&lt;/span&gt; &lt;a href="http://rapotor.blogspot.com/2009/01/mise-en-forme-du-code-pour.html"&gt;qui effectue un htmlentities&lt;/a&gt;; Soit vous vous rendez sur &lt;a href="http://www.manoli.net/csharpformat/format.aspx"&gt;ce site&lt;/a&gt;. Cela remplacera par exemple &amp;lt; par &amp;amp;lt;.&lt;br /&gt;Vous entourez le code par le code HTML comme ceci:&lt;br /&gt;&lt;pre name="code" class="php"&gt;&lt;br /&gt;&amp;lt;pre name="code" class="php"&amp;gt;&lt;br /&gt;// mon code ici&lt;br /&gt;&amp;lt;/pre&amp;gt;&lt;/pre&gt;&lt;br /&gt;La valeur de la classe indique le language. La liste est &lt;a href="http://code.google.com/p/syntaxhighlighter/wiki/Languages"&gt;ici&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Etape 9: Je publie le message! Ouf!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Je vous remercie pour la lecture de ce premier post. Vos commentaires sont les bienvenus.&lt;br /&gt;&lt;br /&gt;Cédric.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5200826704807962631-4331354576511342560?l=rapotor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rapotor.blogspot.com/feeds/4331354576511342560/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://rapotor.blogspot.com/2009/01/coloration-syntaxique-de-code-source.html#comment-form' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/4331354576511342560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/4331354576511342560'/><link rel='alternate' type='text/html' href='http://rapotor.blogspot.com/2009/01/coloration-syntaxique-de-code-source.html' title='Coloration syntaxique de code source sur Blogger.'/><author><name>RapotOR</name><uri>http://www.blogger.com/profile/09981627114003941351</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://1.bp.blogspot.com/_Aa55wEAWQr4/SXIAKrtirNI/AAAAAAAAAAM/jSN-9jD_E78/S220/ced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5200826704807962631.post-8699744554030667890</id><published>2009-01-16T17:12:00.010+01:00</published><updated>2009-01-17T17:10:56.408+01:00</updated><title type='text'>Bonjour</title><content type='html'>Bonjour à tous,&lt;br /&gt;&lt;br /&gt;Je lance ce blog pour vous partager astuces, méthodes et diverses choses que j'ai découvertes au cours des mes développements. Je me fais une joie de vous les partager.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="php"&gt;&lt;br /&gt;echo "Hello world!";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Il sera l'objet de tutoriels portant le javascript, l'ajax ou encore le PHP.&lt;br /&gt;Les articles à venir porteront plus précisément sur:&lt;br /&gt;- La coloration syntaxique de codes sur Blogger.&lt;br /&gt;- Des astuces diverses sur le framework ExtJS.&lt;br /&gt;- Astuces de navigation ajax par ancres.&lt;br /&gt;et bien plus encore...&lt;br /&gt;&lt;br /&gt;Cédric&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5200826704807962631-8699744554030667890?l=rapotor.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rapotor.blogspot.com/feeds/8699744554030667890/comments/default' title='Publier les commentaires'/><link rel='replies' type='text/html' href='http://rapotor.blogspot.com/2009/01/bonjour.html#comment-form' title='0 commentaires'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/8699744554030667890'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5200826704807962631/posts/default/8699744554030667890'/><link rel='alternate' type='text/html' href='http://rapotor.blogspot.com/2009/01/bonjour.html' title='Bonjour'/><author><name>RapotOR</name><uri>http://www.blogger.com/profile/09981627114003941351</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://1.bp.blogspot.com/_Aa55wEAWQr4/SXIAKrtirNI/AAAAAAAAAAM/jSN-9jD_E78/S220/ced.jpg'/></author><thr:total>0</thr:total></entry></feed>
