Skip navigation.

digital-nation

Blog-note d'un informaticien procrastinate...

Posts tagged with "javascript"

Rendre le menu Dock (Fisheyes) accessible

, , , ...

J’ai récemment pu télécharger un menu très sympathique, rappelant celui de Mac… Son utilisation est des plus simplistes, vu que le travail nous a été maché.

Malheureusement, lorsque nous regardons le code, ce n’est pas très propre (oui cela valide, mais on peut faire mieux !) :
<div class="dock-container" id="dock-contener">
  <a class="dock-item" href="../index.php" tabindex="1" accesskey="1"><img src="../images/menu/accueil.png" alt="Accueil"><span>Accueil</span></a> 
  <a class="dock-item" href="../contact.php" tabindex="2" accesskey="2"><img src="../images/menu/contact.png" alt="Contact"><span>contactez-nous</span></a> 
  <a class="dock-item" href="../photographies" tabindex="3" accesskey="3"><img src="../images/menu/les-photos.png" alt="Photos"><span>Les photos</span></a>
  <a class="dock-item" href="../ceremonie_civile.php" tabindex="4" accesskey="4"><img src="../images/menu/ceremonie-civile.png" alt="cécrémonie civile"><span>La cérémonie civile</span></a> 
  <a class="dock-item" href="../ceremonie_laique.php" tabindex="5" accesskey="5"><img src="../images/menu/ceremonie-laique.png" alt="cécrémonie laïque"><span>La cérémonie laïque</span></a> 
  <a class="dock-item" href="../nos_fiancailles.php" tabindex="6" accesskey="6"><img src="../images/menu/nos-fiancailles.png" alt="fiançailles"><span>Nos fiançailles</span></a> 
  <a class="dock-item" href="../le_mariage.php" tabindex="7" accesskey="7"><img src="../images/menu/mariage.png" alt="mariage"><span>Le mariage</span></a> 
  <a class="dock-item" href="../le_voyage_de_noce.php" tabindex="8" accesskey="8"><img src="../images/menu/voyage-de-noces.png" alt="voyage de noces"><span>Le voyage de noces</span></a>
</div>

Comme vous pouvez le constater, ici il s’agit d’une succession d’ancre située dans un conteneur… Ces ancres, ce conteneur et ces « span » sont mis en forme par du CSS que voici :
.dock { margin-left: 150px; float: left; width: 400px; position: relative; height: 50px;  text-align: center; padding-left: 20px; }
.dock-container { top: 0px; height: 50px; }
a.dock-item { display: block; width: 40px; color: #A50021; position: absolute; top: 0px; text-align: center; text-decoration: none;
font: bold 12px Verdana, "Lucida Grande", Lucida, Tahoma, "Trebuchet MS", Arial, Geneva, Helvetica, sans-serif; }
li.dock-item a { color: #A50021; font: font: bold 12px Verdana, "Lucida Grande", Lucida, Tahoma, "Trebuchet MS", Arial, Geneva, Helvetica, sans-serif; }
.dock-item img { border: none; margin: 5px 10px 0px; width: 100%; }
.dock-item span { display: none; padding-left: 20px; }

Ce qui donne un bel effet de mise en page, grâce à la librairie Jquery ainsi qu’un petit complément appelé Interface.
Malheureusement lorsqu’on navigue sans le javascript activé, cela n’a pas l’effet escompté… Et la mise en page ne se charge pas comme nous le désirions, et rend donc la navigation impossible (en gros tout est superposé).
Il est vrai qu’il n’est pas recommandé de baser sa navigation principale sur le javascript ou un complément quelconque… Toutefois si nous regardons le code, ce n’est pas le cas principal ici : c’est du HTML mis en forme par du CSS sur lequel on passe une couche de javascript pour donner un effet. Ouf mais cela ne résoud pas notre problème !
Tentons d’abord quelques petites modification basique pour rendre ce code plus propres :
a)modifions le HTML comme suis :
<div class="dock" id="dock">
<ul class="dock-container" id="dock-contener">
  <li class="dock-item"><a href="../index.php" tabindex="1" accesskey="1"><img src="../images/menu/accueil.png" alt="Accueil"><span>Accueil</span></a> </li>
  <li class="dock-item"><a href="../contact.php" tabindex="2" accesskey="2"><img src="../images/menu/contact.png" alt="Contact"><span>contactez-nous</span></a> </li>
  <li class="dock-item"><a href="../photographies" tabindex="3" accesskey="3"><img src="../images/menu/les-photos.png" alt="Photos"><span>Les photos</span></a></li>
  <li class="dock-item"><a href="../ceremonie_civile.php" tabindex="4" accesskey="4"><img src="../images/menu/ceremonie-civile.png" alt="cécrémonie civile"><span>La cérémonie civile</span></a></li> 
  <li class="dock-item"><a href="../ceremonie_laique.php" tabindex="5" accesskey="5"><img src="../images/menu/ceremonie-laique.png" alt="cécrémonie laïque"><span>La cérémonie laïque</span></a> </li>
  <li class="dock-item"><a href="../nos_fiancailles.php" tabindex="6" accesskey="6"><img src="../images/menu/nos-fiancailles.png" alt="fiançailles"><span>Nos fiançailles</span></a> </li>
  <li class="dock-item"><a href="../le_mariage.php" tabindex="7" accesskey="7"><img src="../images/menu/mariage.png" alt="mariage"><span>Le mariage</span></a> 
  <li class="dock-item"><a href="../le_voyage_de_noce.php" tabindex="8" accesskey="8"><img src="../images/menu/voyage-de-noces.png" alt="voyage de noces"><span>Le voyage de noces</span></a></li>
</ul>
</div>

(en résumé j’ai ajouté un LI devant les A, et remplacé le DIV nommé DOCK-CONTENER par un appel de liste uniforme UL)
b)modifier le javascript
Mais si on recharge la page, cela ne fonctionne plus. Eh non, car dans les paramètres de Interface il faut modifier aussi du javascript. Comme suis :
$(document).ready(
function()
{
$('#dock').Fisheye(
{
maxWidth: 50,
//items: 'a',// test accessibilite
items: 'li',
itemsText: 'span',
container: '.dock-container',
itemWidth: 40,
proximity: 90,
halign : 'center'
}
)
}
);

(en résumé : j’ai changé l’interaction sur les éléments de liste en place d’un élément d’ancre)
Et là tout refonctionne à merveille…
Mais lorsque nous naviguons sans javascript, cela ne va toujours pas !
Bon ne paniquons pas… Que se passe-t-il ? La mise en page est scabreuse. Remodifions donc la mise en page pour le cas où le visiteur n’a pas le javascript d’activé !
c)petit hack entre amis
Pour cela, déterminons un emplacement dans l’entête qui va appeler une feuille de style (CSS) en cas où le javascript n’est pas actif. En effet, ici ce n’est plus un problème d’accessibilité, mais de mise en page.
Nous savons aussi que le dernier élément appelé d’une CSS est celui dont la mise en page sera appliquée. Parfais. Maintenant que nous savons cela, nous avons la solution !
Modifions le HTML comme suis, et rajoutons :
<!-- HACK pour JQUERY INTERFACE si Javascript desactive --> 
<noscript>
<link href="../css/noscript.css" rel="stylesheet" type="text/css">
</noscript>
<!-- FIN HACK pour JQUERY INTERFACE si javascript desactive -->

Ceci doit être placé en fin de la balise HEAD.
Créons maintenant une CSS appelée noscript.css qui sera appelée comme déterminé plus haut et remettons la mise en page correcte !
/* 
CSS Hack pour JQUERY INTERFACE
Rôle : réadapte le menu si le javascript n'est pas actif
Auteur :  X Brusselaers
Licence : GNU GPL v2
*/
.dock { margin-left: 150px; float: left; width: 400px; position: relative; height: 150px; padding-left: 20px; }/* augmenter la hauteur pour repousser les éléments du bas
réorganisation selon une liste classique */
.dock-container { height: 100%; }/* modification simple => 100% */
li.dock-item { display: block; width: 400px; color: #A50021; position: relative; text-align: left; /* remise en ordre des éléments du menu  */
text-decoration: none; 
font: bold 12px Verdana, "Lucida Grande", Lucida, Tahoma, "Trebuchet MS", Arial, Geneva, Helvetica, sans-serif;}
.dock-item img { display: none; }/* je cache les images, car je ne veux plus naviguer avec */ 
.dock-item span { display: block; }/* display en block, pour annuler le display none */

Maintenant lorsqu’on navigue sans javascript, nous avons un menu qui s’affiche comme une liste.

[[ EDIT ]]
Et zut, cela ne valide pas ! Mais au moins c'est accessible... Je recherche encore une solution pour cette "unique" erreur...

Coloration syntaxique

, , , ...

Alors que je recherchais quelques petites fonctions en javascript (que j'aurais mieux fait de faire moi-même) je suis tombé sur un script sympathique de coloration syntaxique multiple (prenant en compte autant le Javascript, le CSS, etc...).

Comment utiliser cette "librairie" ? Tout simplement en insérant le code suivant dans l'en-tête :
<link type="text/css" rel="stylesheet" href="css/SyntaxHighlighter.css"></link>
<script language="javascript" src="js/nom_du_langage.js"></script>
<!-- nom_du_language.js doit être remplacé par un élément existant et correspondant au language désirée, 
exemple pour le CSS : shBrushCss.js -->


Par la suite il suffit de nommer le conteneur du code avec le nom code (name="code") et d'indiquer dans la classe de l'élement conteneur le style de language (class="css") et c'est tout !
Donnant en résumé ceci :
<pre name="code" class="c-sharp">
 // Début du code... etc...
</pre>


Simple non ?

Il existe en plus de nombreuses options et une évolution certaine !
Du point de vue accessibilité, cela ne pose aucun problème. Que demander de plus ?

Ce qu'il faut lire

, , , ...

Quelques billets...

Read more...

Twitter, validation de code

, , , ...

Dans la suite de ce billet, je découvre de plus en plus les services de Twitter et j'ai difficile à m'en passer au quotidien.

Cela permet en plus de mettre facilement un petit contenu en ligne, de maintenir un site un peu "up to date" par ce que l'on fait, ce que l'on peut lire, etc.

Malheureusement, il y a quelques défaut. Si vous insérez le code fournis (tant Adobe Flash que Javascript), vous n'aurez aucune validation par le W3C.

Alors pourquoi ne pas faire quelques modifications simples pour ceux qui désirent utiliser cela via le web :

  <!-- debut de Twitter -->
  <div id="twitter">
      <p>Le Groumphy en direct <a href="http://twitter.com/statuses/friends_timeline/6611282.rss"><img src="images/flux_rss.gif" alt="Flux RSS Twitter de Groumphy" class="img_rss"></a></p>
    <object id="flash_twitter_perso"
type="application/x-shockwave-flash" data="http://twitter.com/flash/twitter_badge.swf">
      <param name="movie" value="http://twitter.com/flash/twitter_badge.swf">
      <param name="FlashVars" value="color1=10066329&type=user&id=6611282">
      <param name="allowScriptAccess" value="always">
      <param name="wmode" value="transparent">
  <!-- debut alternatif 1 badge Twitter -->
<ul>
<li id="my_twitter_status"></li>
<li id="my_twitter_status_time"></li>
</ul>
<script type="text/javascript" src="http://www.twitter.com/statuses/user_timeline/6611282.json?callback=_twitterCallback&count=1"></script>
<!-- fin alternatif 1 badge Twitter -->
<!-- debut alternatif 2 badge twitter -->
    <p>Le Groumphy en direct <a href="http://twitter.com/statuses/user_timeline/6611282.rss"><img src="images/flux_rss.gif" alt="Flux RSS Twitter de Groumphy" class="img_rss"></a></p>
<!-- fin alternatif 2 badge twitter -->
</object>
    <p>Le Groumphy en direct et ceux qu'il lit <a href="http://twitter.com/statuses/friends_timeline/6611282.rss"><img src="images/flux_rss.gif" alt="Flux RSS Twitter de Groumphy" class="img_rss"></a></p>
    <object id="flash_twitter" type="application/x-shockwave-flash" data="http://static.twitter.com/flash/twitter_timeline_badge.swf">
      <param name="movie" value="http://static.twitter.com/flash/twitter_timeline_badge.swf">
      <param name="FlashVars" value="user_id=6611282&color1=0x999999&color2=0x999999&textColor1=0x5E5E5E&textColor2=0x0&backgroundColor=0xCCCCCC&textSize=12">
      <param name="allowScriptAccess" value="always">
      <param name="wmode" value="transparent">
      <!-- debut de Twitter (alternatif 1) -->
      <div id="twitter_txt">
        <ul id="twitter_list">
          <li id="texte_twitter">
          <li>
          <li id="temps_passe"></li>
        </ul>
        <script type="text/javascript" src="http://www.twitter.com/statuses/user_timeline/6611282.json?callback=twitterCallback&count=1"></script>
        <p><a href="http://twitter.com/statuses/friends_timeline/6611282.rss">Suivez ce que fais le Groumphy et ceux qu'il lit (RSS)</a></p>
      </div>
      <!-- fin de Twitter (alternatif 1)-->
      <!-- debut de Twitter (alternatif 2) -->
      <noscript>
      <p> <a href="http://twitter.com/statuses/friends_timeline/6611282.rss">Suivez ce que fais le Groumphy et ceux qu'il lit (RSS)</a> </p>
      </noscript>
      <!-- fin de Twitter (alternatif 2) -->
      <!-- debut de Twitter (alternatif 3) -->
      <p><a href="http://twitter.com/Groumphy">Suivez les aventures de Groumphy</a><p>
        <!-- fin de Twitter (alternatif 3) -->
    </object>
  </div>
  <!-- fin de Twitter -->


Vous n'aurez qu'à personnaliser votre ID dans les URI et le tour est joué. Un simple copier-collé vous fera j'espère gagner du temps.

Pour le javascript, j'ai préféré doubler une fonction en place de les rassembler dans l'éventualité où vous ne désireriez qu'une partie du code Twitter.

Voici donc le javascript :

function relative_time(time_value) {
    var values = time_value.split(" ");
    time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
    var parsed_date = Date.parse(time_value);
    var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
    var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
    delta = delta + (relative_to.getTimezoneOffset() * 60);
    if (delta < 60) { return '(moins d\'une minute)'; } 
else if(delta < 120) { return '(il y \à une minute)'; } 
else if(delta < (45*60)) { return '(Il y \à' + (parseInt(delta / 60)).toString() + ' minutes)'; } 
else if(delta < (90*60)) { return '(Il y \à une heure)'; } 
else if(delta < (24*60*60)) { return '(plus de ' + (parseInt(delta / 3600)).toString() + ' heures)'; } 
else if(delta < (48*60*60)) { return '(Il y \à un jour)'; } 
else { return '(Il y \à ' + (parseInt(delta / 86400)).toString() + ' jours'; } }  
function twitterCallback(obj) {
var id = obj[0].user.id;
document.getElementById('texte_twitter').innerHTML = obj[0].text;
document.getElementById('temps_passe').innerHTML = relative_time(obj[0].created_at); }
function _twitterCallback(obj) {
var id = obj[0].user.id;
document.getElementById('my_twitter_status').innerHTML = obj[0].text;
document.getElementById('my_twitter_status_time').innerHTML = relative_time(obj[0].created_at);
}


En espérant à nouveau plein de découverte...

Microbloging, Twitter et Google Reader

, , , ...

Suite à un horaire léger, j’ai pu consacrer un peu de temps à l’article d’hier sur le microblogging.
J’ai pu donc tester légèrement l’application de Twitter… J’ai pu en tirer les conclusions qu’il est simple d’utilisation, que ce que je vous ai dis hier n’étais pas que des « conneries » et autres de ce style… Mais en plus il procure un certain amusement à être complété.

Mais je n’ai pas fais que cela, j’ai aussi récupéré les données de Google Reader qui étaient partagé afin de remodifier la fonction. La modifier est un bien grand mot, je dirais plutôt l’éclaircir, et la rendre compréhensible.

Au fil de la journée, je suis arrivé à un résultat assez pertinent, qui semble valider, et accessible malgré les technologies utilisées : Adobe Flash, Javascript, etc.
Disons qu’il faudrais séparer les deux : l’un est accessible, l’autre pas ?

Afin de partager cela, je vous cite ci-dessous le code source :

HTML :
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Twitter Party Badge</title>
<script type="text/javascript" src="groumphy.js"></script>
</head>
<body>
<!-- 
Service Twitter et Google Reader (Shared)
Auteur : Google Inc., Twitter
Modification : Groumphy
Copyright : respectif aux scripts 
Version : 1.0.0 alpha
--> 
<div id="twitter_and_googlereader">
<!-- debut de Twitter --> 
<div>
<object 
type="application/x-shockwave-flash" data="http://static.twitter.com/flash/twitter_timeline_badge.swf" 
width="250" 
height="600">
<param name="movie" value="http://static.twitter.com/flash/twitter_timeline_badge.swf">
<param name="FlashVars" value="user_id=6611282&color1=0x999999&color2=0x999999&textColor1=0x5E5E5E&textColor2=0x0&backgroundColor=0xCCCCCC&textSize=12">
<param name="allowScriptAccess" value="always">
<param name="wmode" value="transparent">
<!-- debut de Twitter (alternatif 1) --> 
<div id="twitter">
<ul id="twitter_list">
<li id="texte_twitter"><li>
<li id="temps_passe"></li>
</ul>
<script type="text/javascript" src="http://www.twitter.com/statuses/user_timeline/6611282.json?callback=twitterCallback&count=1"></script>
<p><a href="http://twitter.com/statuses/friends_timeline/6611282.rss">Suivez ce que fais le Groumphy (RSS)</a></p>
</div>
<!-- fin de Twitter (alternatif 1)-->
<!-- debut de Twitter (alternatif 2) -->
<noscript>
<p>
<a href="http://twitter.com/statuses/friends_timeline/6611282.rss">Suivez ce que fais le Groumphy (RSS)</a>
</p>
</noscript>
<!-- fin de Twitter (alternatif 3) -->
<!-- debut de Twitter (alternatif 4) -->
<p><a href="http://twitter.com/Groumphy">Suivez les aventures de Groumphy</a><p>
<!-- fin de Twitter (alternatif 4) -->
</object>
<p><a href="http://twitter.com/statuses/friends_timeline/6611282.rss">Suivez ce que fais le Groumphy (RSS)</a></p>
</div>
<!-- fin de Twitter --> 
<!-- debut de Google Reader --> 
<div id="google_reader">
<script type="text/javascript" src="http://www.google.com/reader/public/javascript/user/15343427923727093981/state/com.google/broadcast?n=10&callback=GRC_p(%7Bc%3A%22gray%22%2Ct%3A%22Je%20lis%20en%20ce%20moment%22%2Cs%3A%22true%22%7D)%3Bnew%20GRC"></script>
<noscript><p><a href="http://www.google.com/reader/public/atom/user/15343427923727093981/state/com.google/broadcast">Lisez ce que lis le Groumphy(RSS)</a></p></noscript>
<p><a href="http://www.google.com/reader/public/atom/user/15343427923727093981/state/com.google/broadcast">Lisez ce que lis le Groumphy(RSS)</a></p>
</div>
<!-- fin de Google Reader --> 
</div> 
</body>
</html>


En Javascript, cela donne :
// ---------------------------------------------------------------
// Script de partage de flux de Google Reader (labs)
// Auteur : Google Inc. (c) 2006
// Modification : Groumphy.net (c) 2007
// Information : v.Labs 1.0
// ---------------------------------------------------------------
(function (){
var z = "/reader/shared/";;;
var G = G || { }, 
H = this;
if(!Function.prototype.apply){
Function.prototype.apply = function(a,b){
var c = [],
d,
g;
if(!a) a = H;
if(!b) b = [];
for(var e = 0; e < b.length; e++){ 
c[e] = "args[" + e + "]" }
g = "oScope.__applyTemp__.peek().(" + c.join(",") + ");";
if(!a.__applyTemp__){ 
a.__applyTemp__ = [] } 
a.__applyTemp__.push(this);
d = eval(g);
a.__applyTemp__.pop();
return d } };
if(!Array.prototype.push){
Array.prototype.push = function(){
for(var a = 0; a < arguments.length; a++){ 
this[this.length] = arguments[a] }
return this.length } }
if(!Array.prototype.pop){ 
Array.prototype.pop= function(){ 
var a;
if(this.length){
a = this[this.length-1];
this.length--}
return a } }
Array.prototype.peek = function(){ 
return this[this.length-1] };
if(!Array.prototype.shift){
Array.prototype.shift = function(){
var a;
if(this.length){
a = this[0];
for( var b = 0; b < this.length-1; b++){ 
this[b] = this[b+1] }
this.length-- }
return a } }
if(!Array.prototype.unshift){ 
Array.prototype.unshift = function(){ 
var a = arguments.length;
for(var b = this.length-1; b >= 0; b--){ 
this[b+a] = this[b] }
for(var c = 0; c < a; c++){ 
this[c] = arguments[c] } 
return this.length } } 
var I = function(a){ return/^\s*$/.test(a) }, 
J = function(a){ return I(K(a)) }, 
K = function(a){ return a == null ? "":String(a) }, 
x = new p;
function p(){ 
if(document.all){ this.r = true } 
else { this.r = false } 
this.O = "pop" in Array.prototype;
this.z = "contains" in document;
this.M = "implementation" in document && "createDocument" in document.implementation;
this.L = "compatMode" in document; 
this.N = "XMLHttpRequest" in window; 
vara = navigator.userAgent, 
b = /\(.*\) AppleWebKit\/(.*) \((.*)/.exec(a);
if(b){ this.B = true; this.Q = parseInt(b[1],10) } 
else{ this.B = false } 
this.A = window.opera;
this.P = a.indexOf("Wii")!= -1 }
p.prototype.n = function(){
return this.r && !this.z && !this.o() };
p.prototype.o = function(){ 
return this.A };
function v(a,b){ 
var c = b || document; 
return c.getElementById(a) }
function i(a,b,c){ 
var d = c || document, g = d.createElement(a);
if(b){ for(var e in b){
var h = b[e];
if(x.n() && e == "class"){ 
e = "className" }
g.setAttribute(e,h) } }
return g }
function j(a){ 
return document.createTextNode(a) } 
var C = function(a){ 
if(!a) return "";
var b = /<[^>]*>/gi; 
return a.replace(b,"") };
function D(a,b){
if(a.length <= b){ return a}
var c = a.split(/\s+/);
a = [];
for(var d = 0; d < c.length && a.join(" ").length <= b; d++){
a.push(c[d]) } 
a = a.join(" ");
if(d != c.length){ a += "..."} 
return a}
var m = {}, 
y = { blue: {f:"#fff", 
e:"#bccceb", 
k:"#090992", 
j:"#bccceb", 
i:"#1010c8", 
d:"#7a7ee0", 
h:"#e5ecf9", 
b:"#898de9" },
green: {f:"#fff", 
e:"#d8dbbc", 
k:"#2d8509", 
j:"#d8dbbc", 
i:"#58bf2f", 
d:"#97e07a", 
h:"#f5fbeb", 
b:"#adb094" },
slate: {f:"#123", 
e:"#345", 
k:"#5e805e", 
j:"#5e6f80", 
i:"#abc", 
d:"#5e6f80", 
h:"#152939", 
b:"#abc" },
gray:{ f:"#fff", 
e:"#ccc", 
k:"#666", 
j:"#ccc", 
i:"#999", 
d:"#ccc", 
h:"#eee", 
b:"#aaa" },
khaki:{f:"#f2e9ca", 
e:"#8e7c6a", 
k:"#d52", 
j:"#cba", 
i:"#543", 
d:"#ba9", 
h:"#eae0c6", 
b:"#987" },
pink:{ f:"#fff", 
e:"#aaa", 
k:"#d69", 
j:"#ddd", 
i:"#e684ad", 
d:"#ebc", 
h:"#fcf0f7", 
b:"#a88" },
black:{f:"#000", 
e:"#aaa", 
k:"#ccc", 
j:"#d8dbbc", 
i:"#d52", 
d:"#7a2b0e", 
h:"#111", 
b:"#999" } },
u = {margin:0, 
padding:0, 
background:"transparent none", 
border:"none", 
textAlign:"left", 
textIndent:"0",
textDecoration:"none", 
fontWeight:"normal" };
function k(a,b){ 
//this.l = "readerpublishermodule" + this.p();
this.l = "id_div_googlereader" + this.p();
this.g = a; 
this.u = m["c"];
this.v = m["t"];
this.K = m["s"] == "true";
if(b){ 
b.innerHTML = ""; 
b.id = this.l; 
this.m(v(this.l)) } 
else{
document.write('<div id="' + this.l + '" class="reader-publisher-module"></div>');
var c = this;
window.setTimeout( function(){ c.m(v(c.l)) }, 0) } }
k.prototype.p = function(){ 
if(!("GRC_c" in window)){ window["GRC_c"] = 0 }
return window["GRC_c"]++ };
function A(a){ m =a }
k.prototype.m = function(a){ 
function b(F){ 
return F }
var c = this.q(); 
this.a(c.J, a);
if(this.v){ 
var d = i("h3");
this.a(c.I, d);
d.appendChild(j(this.v));
a.appendChild(d) }
var g = i("ul");
this.a(c.H, g);
for( var e = 0, h; h = this.g.items[e]; e++){ 
if(!h.alternate){ continue }
var o = i("li");
this.a(c.G, o); 
var t = i("a",{href:b(h.alternate.href), 
title:h.title, 
"class":"i" });
this.a(c.C, t);
var f = C(h.title);
if(!J(f)){ f = D(f,48) }
t.appendChild(j(f));
o.appendChild(t);
if(this.K && h.origin.title){ 
var q = h.origin, 
l = i("div", { 
"class":"s" });
this.a(c.F, l);
o.appendChild(l);
l.appendChild(j(" from "));
var f = q.title;
if(f.length > 48){ 
f = f.substring(0,48) }
if(q.htmlUrl){ var r = i("a", { 
href:b(q.htmlUrl), 
title:f });
this.a(c.D,r);
r.appendChild(j(f));
l.appendChild(r) } 
else{ l.appendChild(j(f)) } }
g.appendChild(o) }
a.appendChild(g);
var s = i("div", {
"class":"f"});
this.a(c.w, s);
if(this.g.id){ 
var w = this.g.id.indexOf("feed/") == 0, 
E = this.g.alternate && this.g.alternate.href;
if(!w || E){ 
var n = i("a"); 
this.a(c.b, n); 
//n.href = w ? this.g.alternate.href:"http://www.google.com" + z + this.g.id;
n.href = w ? this.g.alternate.href:"http://my.opera.com/groumphy";
n.appendChild(j("Lire plus..."));
s.appendChild(n) } }
a.appendChild(s)};
k.prototype.q = function(){ 
if(this.u == "-"){ 
return{ } }
var a = y[this.u];
return{
J:{ fontFamily:"arial, sans-serif", 
fontSize:"10pt", 
MozBorderRadius:"8px", 
background:a.f,
border:"solid 4px " +a.e,
margin:"0.5em" },
I:{ padding:"0.2em 0",
margin:"0 0.5em",
MozBorderRadius:"8px 8px 0 0",
borderBottom:"solid 1px " + a.j,
color:a.k },
H:{ padding:"0.2em", 
margin:"0 0.5em", 
overflow:"hidden" },
G:{ listStyleType:"none",
padding:"0.4em 0 0.4em 0" },
C:{ color:a.i, 
borderBottom:"solid 1px " + a.d },
F:{ paddingLeft:"0.5em", 
color:a.d },
D:{ color:a.d },
w:{textAlign:"right",
borderTop:"solid 1px " +a.e,
background:a.h,
MozBorderRadius:"0 0 4px 4px",
padding:"0.2em 8px", 
fontSize:"small",
whiteSpace:"nowrap" },
b:{ color:a.b,
textDecoration:"underline" } } };
k.prototype.a = function(a,b){ 
if(!a) return;
B(b);
for(var c in a){ 
b.style[c] = a[c] } };
function B(a){ 
for(var b in u){ 
a.style[b] = u[b] } }
window["GRC_p"] = A;
window["GRC"] = k; })();

// ---------------------------------------------------------------
// Script de boite Twitter, pour le microblogging
// Auteur : Twitter (c) 2007
// Modification : Groumphy.net (c) 2007
// Information : 1.0.1modification par Groumphy 06.06.2007
//1.0 version originale
// ---------------------------------------------------------------
function relative_time(time_value) {
    var values = time_value.split(" ");
    time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
    var parsed_date = Date.parse(time_value);
    var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
    var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
    delta = delta + (relative_to.getTimezoneOffset() * 60);
    if (delta < 60) { return '(moins d\'une minute)'; } 
else if(delta < 120) { return '(il y \à une minute)'; } 
else if(delta < (45*60)) { return '(Il y \à' + (parseInt(delta / 60)).toString() + ' minutes)'; } 
else if(delta < (90*60)) { return '(Il y \à une heure)'; } 
else if(delta < (24*60*60)) { return '(plus de ' + (parseInt(delta / 3600)).toString() + ' heures)'; } 
else if(delta < (48*60*60)) { return '(Il y \à un jour)'; } 
else { return '(Il y \à ' + (parseInt(delta / 86400)).toString() + ' jours'; } }  
function twitterCallback(obj) {
var id = obj[0].user.id;
document.getElementById('texte_twitter').innerHTML = obj[0].text;
document.getElementById('temps_passe').innerHTML = relative_time(obj[0].created_at); }

Intéressé ? Simple, modifier quelques variables, et le tour est joué !
Pour voir le résultat opérationnel encore en test, rendez-vous sur Groumphy.net !
Mais je me pose encore quelques questions… Faut-il faire un rafraichissement de la page toutes les X minutes (afin de garder le contenu à jour pour le visiteur) ? N’y a-t-il pas déjà un service qui offre cela (tout combiné dans la même plateforme) ? Etc.

Information : pour le code, l'indentation n'est pas présente.

Javascript non intrusif

, , , ...

Utiliser la puissance du DOM pour ses scripts

Read more...

Widgetize! Personnalisation d'une automatisation

, , , ...

Me revoici dans l'idée de faire un fil de l'information avec le journal Le Soir.
Après les récents articles sur l'automatisation d'un widget et plus particulièrement sur la manière de l'extérioriser, je me suis dit qu'il était temps de passer à la pratique.

Je vous avais récement montré en plus comment faire un widget, donc nous pouvons ici combiner les deux.
Alors en premier temps il nous faut récupérer le widget que nous avons créé pour notre blog, et qui est dans le répertoir Widget de Opera dans vos paramètres locaux (comme dit précédement il s'agit d'une simple archive à décompresser).

Une foix que cela est fait, nous obtenons la structure suivante :

  1. dossier JS
  2. dossier SKIN
  3. fichier CONFIG.XML
  4. fichier INDEX.HTML
  5. fichier CONFIG.JS


Récupérons maintenant le fil de l'information du journal Le Soir ( http://www.lesoir.be/services/rss/le_fil_Info/index.xml ). Pour ce faire, il suffit d'éditer la source du site et de récupérer la ligne qui vous intéresse dans les RSS... Cela s'identifie par un simple lien (balise HTML LINK) avec le type

RSS+XML (attribut de la balise LINK sur TYPE="APPLICATION/RSS+XML").

Maintenant il nous faut configurer le widget. Comme vous vous en douter, le fichier CONFIG.JS est là pour cela !
Donc éditons le dans le bloc-note et remplacons les données comme suit :

var skeletonConfig = {
feedURL : "http://www.lesoir.be/services/rss/le_fil_Info/index.xml",
feedTitle : "Journal Le Soir : le fil de l'info",
feedVersion : "generic",
maxItems : 10
};


Théoriquement votre widget est pret à l'emploi ! Vous enregistrer le tout, vous remettez au format archive et vous faite une lecture du fichier config.xml par Opera et le widget est lisible.

Mais comme vous vous en douter, il n'est pas parfais ! De nombreux anglicisme sont encore présent dans le widget. Normal me direz-vous car Opera Software,

l'éditeur maitre du widget que nous modifions, n'est pas du tout orienté vers le français !
Alors continuons à personnaliser le widget :

Ouvrons le fichier CONFIG.XML :

Et comme vous le voyez, nous pouvons donc le personnaliser :
  • La balise <widgetname> représente le nom du widget, changeons le par Le Soir,
  • La balise <description> elle représente la description du widget, placer y ce que vous y désirez comme description sans faire dans la longueur,
  • Par la suite, ce qui est entre les balise d'identification (<id>), représente l'identification du widget, le HOST représente l'hôte d'hébergement du widget,


Le NAME est le nom et REVISED est la dernière revision du widget... Jusque là que du connus que nous avons déjà passé en revue lors de la création du premier Widget.
Vous pouvez maintenant déterminer la hauteur et la largeur (balise WIDTH et HEIGHT) en pixel.
La suite reste tout aussi connue par les auteurs (nom, liens, organisation...) !

Ceci devrait donner cela :

<?xml version="1.0"?>
<widget>
  <widgetname>Le Soir.be</widgetname>
  <description>Le fil de l'information</description>
  <id>
     <host>localhost</host>
     <name>Lecteur RSS</name>
     <revised>2006-08-12</revised>
  </id>
  <width>400</width>
  <height>250</height>
  <author>
    <name>Opera widgets</name>
    <link>http://widgets.opera.com/</link>
    <organization>Opera Software ASA</organization>
  </author>
</widget>


Passons maintenant à la suite, le plus amusant, franciser l'interface...
Pour ce faire, très simplement éditons le fichier INDEX.HTML comme il se doit :
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!--
/**
 * Copyright (c) 2006, Opera Software ASA
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Opera Software ASA nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY OPERA SOFTWARE ASA AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL OPERA SOFTWARE ASA AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
-->
<!-- 
Auteur : Opera Software ASA - version d'origine
Groumphy (http://users.skynet.be/digital-nation/blog/) - modification 
Licence : (c) Opera Software ASA 2006 All rights reserved
Changelog : francisation
personnalisation du widget
Version : 1.0.0- version d'origine
1.0.1- version modifiée par Groumphy
-->
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Lecteur RSS</title>
<link rel="stylesheet" type="text/css" href="skin/base.css">
<link rel="stylesheet" type="text/css" href="skin/skin-specific.css">
<script type="text/javascript" src="config.js"></script>
<script type="text/javascript" src="js/date.js"></script>
<script type="text/javascript" src="js/general.js"></script>
<script type="text/javascript" src="js/animation.js"></script>
<script type="text/javascript" src="js/Feed.js"></script>
<script type="text/javascript" src="js/Tooltip.js"></script>
<script type="text/javascript" src="js/parsers.js"></script>
<script type="text/javascript" src="js/script.js"></script>
</head>
<body>
<div id="wrapper">
<div id="header">
<div id="logo"></div>
<h1 id="widgetTitle">&nbsp;</h1>
<span id="unread" title="Unread items">0</span>
<button id="flip">Basculer</button>
<button id="close" onclick="window.close()">Fermer</button>
</div>
<div id="cbody">
<div id="content">
<ul id="itemList"></ul>
<div id="back">
<h2>Widgetize!</h2>
<p><a href="http://widgets.opera.com/widgetize/">Widgetize!</a> est un produit de Opera Software sur lequel vous 

pouvez créer vos propres 
                widget. (version modifiée par <a href="http://users.skynet.be/digital-nation/blog/">Groumphy</a>)</p>
<p class="downcenter"><input type="checkbox" id="disanim">Désactiver animations</p>
</div>
</div>
</div>
<div id="footer">
<button id="reload">Recharger</button>
<span id="lastUpdate">&nbsp;</span>
<button id="expandMinimize" class="minimize"></button>
</div>
</div>
</body>
</html>

Parfais... Maintenant il nous faut voir du coté Javascript. Cela fait un petit plus non négligeable d'avoir des dates à l'européenne et surtout que ce soit inscrit en français.
Alors éditons le fichier Date.js se trouvant dans le dossier JS et changer les deux premières variables par des contenus francisé :
var months = [
'Janvier',
'Fevrier',
'Mars',
'Avril',
'Mai',
'Juin',
'Juillet',
'Aout',
'Septembre',
'Octobre',
'Novembre',
'Decembre'
];
var tw = {
second : 'seconde',
seconds : 'secondes',
minute : 'minute',
minutes : 'minutes',
hour : 'heure',
hours : 'heures',
yesterday : 'Hier',
and : 'et',
ago : 'depuis',
today : 'Ce jour',
at : ', ',
future : 'dans le futur',
date : '%DATE% %MONTH%',
longdate : '%DATE% %MONTH%, %YEAR%'
}

Comme vous avez pu le remarquer, j'ai aussi adapté la date dans un ordre européen (voir variable date et longdate dans la zone mémoire tw)...

Vous avez aussi la possiblité de modifier la fonction de calcul de l'heure. En effet, la variable ago de la zone de mémoire tw se situe à la fin (dans la version anglaise), hors en français elle devrait se placer à l'avant...

Modifion alors l'appel de la fonction dans une variable de la manière suivante :
Date.prototype.toAge = function() {

var now = new Date();
var yesterday = new Date( now.getFullYear(), now.getMonth(), now.getDate() );

var delta = yesterday.getTime() - this.getTime();
var ticks = now.getTime() - this.getTime();

if ( delta > 0 || ticks < 0 ) {
// Yesterday or before
if ( delta < 1000 * 60 * 60 * 24 && ticks > 0 ) {
// Yesterday
return tw.yesterday;
} else {
// Long ago
var d = (now.getFullYear() != this.getFullYear()) ? tw.longdate.replace( '%YEAR%', this.getFullYear() ) : tw.date;
d = d.replace( '%MONTH%', months[this.getMonth()] ).replace( '%DATE%', this.getDate() );
if (ticks < 0) d += ' (' + tw.future + ')';
return d;
}
} else {
// Today

if (ticks < 0) {
return tw.future;
}
// Seconds
ticks = Math.floor( ticks / 1000 );
if (ticks < 60) {
//return ticks + ' ' + (ticks == 1 ? tw.second : tw.seconds) + ' ' + tw.ago;
return tw.ago + ' ' + ticks + ' ' + (ticks == 1 ? tw.second : tw.seconds);
}
// Less than, or an hour ago
ticks = Math.floor( ticks / 60 );
if (ticks <= 60) {
if (ticks < 60) {
//return ticks % 60 + ' ' + (ticks == 1 ? tw.minute : tw.minutes) + ' ' + tw.ago;
return tw.ago + ' ' + ticks % 60 + ' ' + (ticks == 1 ? tw.minute : tw.minutes);
} else {
return tw.ago + ' ' + '1 ' + tw.hour;
}
}
// Less than, or two hours ago
if (ticks <= 120) {
if (ticks < 120) {
return tw.ago + ' ' + '1 ' + tw.hours + ' ' + tw.and + ' ' + ticks % 60 + ' ' +
(ticks == 1 ? tw.minute : tw.minutes);
} else {
return tw.ago + ' ' + '2 ' + tw.hours;
}
}
// Otherwise, write out the time
else {
return tw.today + tw.at + ' ' + padZero(this.getHours()) + ':' + padZero(this.getMinutes());
}
}
};


Hum, voila qui est fait pour une grande partie et c'est bientôt terminé. Il ne nous reste plus que quelques petites modifications et le tour est joué !
Ouvrons maintenant SCRIPTS.JS et dans la changeons la fonction oneNewItemHandler comme ceci :
function onNewItemsHandler(noChange, err) {
/* Advanced - lastupdate */
    updateStatus(err);
    /* End advanced */

var container = document.getElementById('itemList');
var list = feed.getItemList();

   /* Advanced - modified for lastupdate */
if (err) {
        if (container.firstChild) {
    return;
    }

var li = document.createElement('li');
li.appendChild( document.createTextNode( '(Affichage RSS non possible)' ) );
container.insertBefore( li, container.firstChild );
li.id = 'noContent';
return;
}
   /* End advanced */

if (list.length == 0) {
container.innerHTML = '';
var li = document.createElement('li');
li.appendChild( document.createTextNode( '(Pas de News)' ) );
container.appendChild(li);
li.id = 'noContent';
return;
}

// Unchanged feed, leave it alone
    if (noChange) return;

// Display feed items
container.innerHTML = '';
var pointer = null, li = null, content = null;

for (var i = 0; pointer = list[i]; i++) {
li = document.createElement('li');
li.className = pointer.read ? 'read' : '';
li.guid = pointer.getGUID();
container.appendChild( li );

var tit = pointer.getTitle() || '(Pas de titre)';
if ( typeof tit == 'string' ) tit = document.createTextNode( tit );
var h2 = document.createElement('h2');
h2.className = 'postTitle';
h2.appendChild( tit );
li.appendChild( h2 );

var content = document.createElement('div');
var h3 = document.createElement('h3');
h3.className = 'dateTime';
/* Advanced - lastupdate */
var pub = pointer.getDate();
h3.appendChild( document.createTextNode( pub ? pub.toAge() : '(Pas de date)' ) );
h3.timestamp = pub ? pub.getTime() : 0;
/* End advanced */
        content.appendChild( h3 );
li.appendChild( content );
li.expander = content;

var desc = pointer.getDesc() || document.createTextNode( '(No text)' );
if ( typeof desc == 'string' ) desc = document.createTextNode( desc );
content.appendChild( desc );

var link, href = pointer.getLink();
if ( href ) {
link = document.createElement('a');
link.href = href;
link.appendChild( document.createTextNode( ' Voir ' ) );
} else {
link = document.createTextNode( '(Pas de lien)' );
}
link.className = 'morelink';
content.appendChild(link);

}

    updateUnread();

/* Advanced - fancy unread */
if (feed.getUnreadCount() > 0) {
document.getElementById('unread').style.visibility = 'visible';
var animation = document.getElementById('unread').createAnimation();
animation.style.opacity = 0;
animation.speed = 5;
animation.accelerationProfile = animation.constant;
animation.addAnimation('opacity', animation.style.opacity, '1').run();
}
/* End advanced */
}

En bref nous avons simplement traduit les commentaires données dans les structures conditionnelles.

Après ces quelques manipulations, il n'y a rien d'autres à faire.
Si vous recompiler le tout, et que vous proposer cela en téléchargement, il n'y a aucun soucis pour l'exécution du widget.

Ce dernier article devrait pouvoir vous aider sur pas mal de problème de lecteur RSS, en essayant que ce soit le cas.

filinfoLeSoir.zip

Créer son propre widget via l'automatisation

, , , ...

Comme vu dans le post précédent sur le générateur de widget, je me pose la question et la pose, pourquoi n'y a t'il pas directement moyen de télécharger ce widget ?

Actuellement si nous voulons faire un déploiement externe, nous sommes obligés d'aller la configuration de Opera (dossier utilisateur) et plus particulièrement le dossier widget et copier le widget correspondant que nous venons de créer pour le modifier à un endroit extérieur.

Parfais, mais maintenant y a t'il moyen de personnaliser ce widget pour le rendre compatible avec un site totalement externe de Opera ou encore ceux proposé par défaut sur le générateur ?
Là je dis à nouveau oui !

Lorsque nous analysons le widget, nous voyons qu'il a une configuration tout à fait classique :
  • un dossier JS : contenant les animations, les dates de mises à jour etc. en bref, le javascript qu'à besoin le widget pour fonctionner ;
  • un dossier SKIN : disposant des images, de la mise en forme générale et spécifique (via fichier CSS) ;
  • à la racine : le fichier CONFIG.XML, le fichier INDEX.HTML et un étrange fichier CONFIG.JS !

Ouvrons ce dernier dans notre éditeur de texte, nous obtenons simplement quelques renseignements complémentaires très utiles :
var skeletonConfig = {
feedURL : "http://my.opera.com/Groumphy/xml/atom/blog/",
feedTitle : "Carnet de Groumphy",
feedVersion : "generic",
maxItems : 9
};

Ainsi nous pouvons donc personnaliser le widget :
  1. feedURL est la variable déterminant le chemin vers le RSS,
  2. feedTitle est la variable permettant de gérer le titre du widget,
  3. feedVersion représente en terme de variable la forme qu'à le RSS ou ATOM,
  4. maxItems est simplement un nombre variable du nombre maximum d'item (entrée) générée par le widget.


Je n'ai pas encore essayé de le personnaliser, mais à première vue, toutes les autres fonctions contenues dans le dossier JS ne contiennent aucune variable personnalisable et font appels à ce fichier externe !

A suivre encore... Et encore !

Générateur de Widget

, , , ...

Faisant partie de la communauté de Opera, je ne vous présente plus les widgets, ces petits add-on que l'on déploie en deux et trois mouvements dans Opera à l'image de Firefox et ses extensions ou plugin.

Toutefois un lien que je tiens toutefois à donner avec grand plaisir est le générateur de Widget ! En effet, il est maintenant possible d'avoir un widget personnalisé au RSS de son site !

Il est implémenté directement dans toutes les pages de la communauté Opera (my.opera), mais maintenant il est possible de l'implémenter avec un générateur !

En 3 étapes vous avez votre widget permettant de lire votre flux RSS !
Le déploiement lui est un peu scabreux... Il se fait que par des liens via les serveurs Opéra.

Ce qui aurait été plus pratique aurait été un téléchargement du widget pour pouvoir avoir un déploiement externe et l'incorporer dans un site même externe.
Le widget n'aurais été téléchargeable que si le navigateur Opera était détecté... Mais avec une technologie client type javascript.

A suivre toutefois de prêt car certaines options sont encore masquées et permettraient d'avoir une certaine largesse d'esprit.

Barre de navigation en javascript

, , , ...

Dans la continuité du post précédent où je vous indiquais comment faire pour afficher le protocole, l'URL etc. via Javascript, je vous propose cette fois une barre de navigation mettant en pratique ce principe.

Ainsi nous pouvons simplement voir l'utilisation de indexOf, des zones de mémoire, de la location d'une adresse et tutti quanti.

function navURI() { 
var c = '';
var z = document.location.href; // capture de l'adresse
var s = z.split('/');// split de HREF représentant l'adresse
for (var i = 0; i < (s.length - 1); i++) { 
   // Je dépose la variable i qui est le compteur  pour faire le split
   // si on ne désire pas le protocole avec, inscrire la valeur de i à 1 en initial
   // etc... il suffit de règler les informations que l'on désire
var o;
      o = '<a href="*/">*</a>* | '; // dépose d'une variable conteneur :
o = o.split('*'); // je splitte la variable pour pouvoir obtenir mes informations
c+= o[0] + z.substring(0,z.indexOf(s[i]) + // ecriture du chemin
s[i].length) + o[1] + s[i] + o[2] + o[3]; }
document.writeln(c); } // ecriture dans la page



Assez simple, il suffit par la suite de faire appel à la fonction et l'affichage se fait.

Détecter le Protocole et l'URL en Javascript

, , , ...

Ce n'est pas vraiment un script, mais j'espère toutefois qu'il pourra être utile à tous : détecter via javascript le protocole utilisé ou encore l'URI sur laquelle on se trouve.

Pratique à utiliser avec un indexOf car cela permet d'analyser en "profondeur" l'URL sur laquelle on se trouve et de cibler par exemple des destinations ou des publicités selon le domaine, sous-domaine dans lequel on se trouve !

<!DOCTYPE HTML PUBLIC "-// W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<head>
<title>Test</title>
<script language="javascript1.4" type="text/javascript">
<!-- 
function uri() { var p, h, u; 
p = location.protocol; h = location.hostname; u = location.href; 
document.write('<p>Protocole: ' + p + ' <br> ' + ' Host: ' + h + ' <br> ' + ' URL: ' + u + '</p>');} 
/-> 
</script> 
</head>
<body> 
<script language="javascript1.4" type="text/javascript"> 
uri(); </script> 
</body></html>


Je ne pense pas qu'il y aie besoin de commentaire sur une telle "fonction".

Edit : apparament il semble y avoir plusieurs problèmes lors de l'édition. Désolé.

Insertion d'élément Flash dans une page (x)HTML

, , , ...

L'inclusion d'un élément nécessitant le plugin Adobe (ex Macromédia) Flash n'est pas une mince affaire.

Dans le meilleur des cas, vous aurez peut-être l'occasion de voir votre plugin s'afficher sous un navigateur, parfois sous deux... Dans le pire, vous ne verrez rien !

Bien entendu, beaucoup se sont penché sur la question et de nombreuses solution sont parues. Certaines plus faciles que d'autres.

Passons en revues quelques-unes de ces solutions.

La solution "écrire en dur"

Ici point de petite astuce, point de renvois au site de téléchargement ou autre... Ce qui se passe, nous écrivons en "dur" (insertion directe du code) dans la page.
Pour ce faire, nous travaillons par la balise OBJECT. Celle-ci est gerée via une autre balise PARAM... Qui comporte donc la paramétrisation de la première.

Lorsque nous utilisons un éditeur de page en WYSIWYG, nous avons bien souvent un code de ce style :
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" 
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0" width="200" 
height="20" title="play it !" bgcolor="#999999">
  <param name="movie" value="monflash.swf">
  <param name="quality" value="high">
<param name="bgcolor" value="#999999">
  <embed src="monflash.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" 
type="application/x-shockwave-flash" width="200" height="20"></embed>
</object>


Hors lorsque nous validons notre page HTML par le W3C, nous obtenons une dizaine d'erreur facilement. Mais alors comment faire.

Lorsque nous consultons différents sites (qui nous renseigne sur une méthode plus "valide"), nous obtenons le code suivant :
<object type="application/x-shockwave-flash" data="fichierflash.swf" width="600" height="20">
<param name="movie" value="fichierflash.swf" />
<param name="wmode" value="transparent" />
<p>Image ou texte alternatif</p>
</object>

Cf. Css.AlsaCreations.com
Cette dernière méthode est compatible par tous les navigateurs. Parfais me direz-vous, nous gérons tout aussi le contenu réel (le Flash) que le contenu alternatif (via un texte ou une image).

Mais cela serait beaucoup trop simple si... Il n'y avait pas incompatibilité de version de Flash (sur les éléments avancés).
De fait, d'autres personnes se sont à nouveau penchées sur le problème et ont sortis quelques JavaScript des plus sympathiques.
Je citerais donc deux méthodes qui m'ont particulièrement séduites : la méthode Satay, la méthode du FlashObject...
Toutes deux inclues un système de détection, de redirection etc. permettant d'avoir la version souhaitée ainsi que la visualisation correcte.

De véritable petites merveilles... Mais un peu (voir beaucoup) trop complèxe pour moi.

Alors je me suis "amusé" à pouvoir combiner les deux... Mais sans aucuns systèmes de redirection ou téléchargement. J'utilise très simplement du Javascript pour écrire l'OBJECT Flash et s'il n'est pas affiché, je puis donc utiliser le dernier paramètre pour un contenu alternatif.
Les méthodes Satay et FlashObject intègrent bien entendu cela.

Cependant, j'ai décidé de continuer l'originalité par l'utilisation de la balise NoScript définie identiquement à la manière du contenu alternatif de la balise OBJECT.
De fait, peut importe que le navigateur gère Flash ou non, Javascript ou non, il y aura l'affichage du contenu alternatif.

Nous pourrions aussi afficher dans la balise NoScript le Flash en soi... Une idée comme une autre.
Passons en revue maintenant le code :
En javascript
// Auteur : Groumphy
// Version : v1.0.1
// Licence : CreativeCommons Partage à l'identique BE
// SWF = le fichier Flash
// S_SWF = largeur du Flash
// H_SWF = hauteur du Flash
// ALT_IMG = image alternative
// ALT_TXT = texte alternatif 
function _gFlash(swf, w_swf, h_swf, alt_img, alt_txt) {
document.write('<object type="application/x-shockwave-flash" data="' +
 swf + '" width="' + w_swf + '" height="' + h_swf + '">');
    document.write('<param name="movie" value="' + swf + '">');
document.write('<param name="wmode" value="transparent">');
if ((alt_img != '') || (alt_img != ' ')) { 
document.write('<img src="' + alt_img + '" width="' + w_swf + '" height="' 
+ h_swf + '" alt="">'); }
if ((alt_txt != '') || (alt_txt != ' ')) { 
document.write('<p>' + alt_txt + '</p>'); }
document.write('</object>'); }


En HTML :
<script language="javascript1.1" type="text/javascript">
_gFlashHtml('monflash.swf', '400', '300', '', '');
</script>
<noscript>
<object type="application/x-shockwave-flash" data="monflash.swf" width="600" height="20">
<param name="movie" value="fichierflash.swf" />
<param name="wmode" value="transparent" />
<p>Image ou texte alternatif</p>
</object>
</noscript>


J'ai effectué les tests sous différents navigateurs et systèmes d'exploitation, mais je n'ai pas constaté de problèmes majeurs (excepté ceux que je cite si souvent relatif à l'utilisation du Javascript et des plugins... En rapport aux utilisateurs [visiteur] les plus pointus au niveau des langages clients etc.).

Que pensez-vous d'une méthode pareille ?
Quels serait les avantages ou inconvéniants...

Changer la taille de la police (ou texte) par Javascript

, , , ...

Comme vu (encore) précédement, il existait de très beau script pouvant faire changer de feuille de style par javascript.

Passons maintenant à une autre méthode : le changement de la taille de la police ou du texte par un Javascript.

Malheureusement, ce n'est pas directement possible avec une quelconque manière de le faire (nativement). De fait, une personne nommée Dustin Diaz a créé une nouvelle fonctionnalité : getElementsByClass().
Cette fonctionnalité permet de travailler sur une classe précise et uniquement celle-ci. Ce qui est plutôt pratique car si nous disposons d'une mise en page précise et que nous ne souhaitons pas voir déformée par un agrandissement global de la page (nous augmenterons donc que la taille de la police d'un conteneur spécifique par exemple).

// Création : Dustin Diaz
//Site : http://www.dustindiaz.com/getelementsbyclass
function getElementsByClass(searchClass, node, tag) { 
var classElements = new Array(); 
if ( node == null ) 
node = document; 
if ( tag == null ) 
tag = '*'; 
var els = node.getElementsByTagName(tag); 
var elsLen = els.length; 
var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)"); 
for (i = 0, j = 0; i < elsLen; i++) { 
if ( pattern.test(els[i].className) ) { 
classElements[j] = els[i]; 
j++; 
} 
} 
return classElements; 
} 


Encore une fois, si vous êtes un lecteur fidèle sur les articles concernant le Javascript, j'insiste pour dire que le Javascript est un langage interprété par le navigateur. L'internaute a le choix ou non d'utiliser cette technologie. A utiliser avec parcimonie donc.
Pour l'accessibilité directe, rien ne vaut de passer par l'interface du navigateur (le plus souvent Ctrl + Molette de la souris ou Menu Affichage et choisir les différentes tailles...).


Il est bien entendu possible (et plus aisé) d'agrandir la police de toute une page... Cela peut se faire tout aussi bien par Javascript. Point besoin d'utiliser la fonction décrite ci-dessus mais utilisons simplement une autre feuille de style (Cf. article précédent) ou une ligne de Javascript (utilisation de document.getElementByTag sur la balise Body par exemple).

Mais pourquoi faire simple lorsqu'il est plus aisé de faire complèxe.
Complèxe ne serait pas le bon mot vu que quelques personnes se sont déjà penchées sur le sujet et qu'il ne nous reste plus qu'à utiliser simplement et de manière pratique ce qu'elles ont développé. Nous pouvons même l'améliorer.

Une méthode que j'apprécie plus particulièrement et qui utilise justement getElementsByClass() est celle faite par Le Journal du Developpeur (Xavier Borderie).
Elle permet de fait à spécifier une classe sur laquelle est portée la fonction ainsi que la taille.
        // Xavier Borderie
function tailleFonte(classe, taille) { 
cibles = getElementsByClass(classe); 
for (i = 0; i < cibles.length; i++) { 
        cibles[i].style.fontSize = taille; 
        } 
    } 


Maintenant que nous avons nos deux fonctions, il ne nous reste plus qu'a faire le (x)HTML et la CSS...

Du coté CSS :
  h1 {
font-family: "Times New Roman", Times, serif;
font-size: medium;
font-weight: bold;
font-variant: small-caps;
color: #0099FF;
background-color: #CCCCCC;
width: 100%;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #FFFFFF;
}
  #conteneur {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: small;
color: #FFFFFF;
background-color: #0099FF;
width: 100%;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #0033FF;
  }
  #conteneur #entete {
  
  }
  
  #conteneur #corps {
font-size: x-small;
  }
  #conteneur #corps #zonetest {
font-size: small;
  }
  .serif {
font-family: serif; 
font-size: x-small; }
  li {
display: inline;
  }
  li:before { 
content: "|";
  }
  li:after {
content: "|";
  }


Du coté HTML :
<div id="conteneur">

<div id="entete">
<h1>Changer la taille de police par Javascript</h1>
</div>

<div id="corps">
<p>Augmenter ou diminuer la taille de la police</p>
<ul>
<li><a href="javascript:tailleFonte('serif', 'small');">Augmenter la taille</a></li>
<li><a href="javascript:tailleFonte('serif', 'x-small');">Diminuer la taille</a></li>
</ul>
<div id="zonetest">
<p id="nickname" title="monnickname" class="serif">Mon nickname est Groumphy</p>
</div>

</div>

</div>


Evidence même... Une classe, une taille avec les inconvéniants et avantages que j'ai cité ci-dessus.

Création de cookies en javascript

, , , ...

Dans un post précédent je vous indiquais comment changer le style "à la volée" grâce à un styleswitcher (en javascript).
Je vous informais aussi que pour avoir une valeur permanente, il nous fallais enregistrer le choix dans un cookies.

De fait, voyons comment créer un cookies dans ce post.

La création d'un cookies se fait aisément par document.cookies.
Pour la création il nous faut aussi quelques paramètres. Ces paramètres sont :
  1. Name : permet de donner un nom (un identifiant unique), sa valeur est une chaine de caractère (string) ;
  2. Contenu : le contenu à inscrire dans le cookies ;
  3. Expires : détermine via l'objet Date une date d'expiration du cookies ;
  4. Path : indique le répertoire où le cookies est valide, c'est à dire que toute page se trouvant dans le répertoire et ayant une fonction de lecture du cookies sera prise en compte ;
  5. Domaine : indique le nom d'hote dans lequel le cookies est valide ;
  6. Secure : informe que le cookies ne sera lu que sur un protocole HTTPS ;


Passons maintenant à une petite fonction simple :

function monCookie(nomCookies, valeurCookies, dateCookies) {
  document.cookie = nomCookies + "=" + 
      escape(valeurCookies) + (( dateCookies == null) ? "" : ("; dateCookies = " + 
      dateCookies.toGMTString())); }


Petite explication :
  • toGMTString() : transforme la chaine de caractère date en valeur date au format GMT ;
  • dateCookies == null : vérifie que la date du cookies est renseigné, à défaut, ne renseigne pas de date d'expiration ;
  • escape(valeurCookies) : transforme la valeur du cookies en valeur ASCII, son contraire est unescape(valeurCookies) et cette fonction sera utilisée dans la lecture du cookies ;
  • document.cookie : crée le cookies ;


Comme annoncé précédement, vu que nous utilisons ici la fonction escape(), nous devons évidement utiliser une fonction unescape(). Le principe est simple, nous trouvons le cookies, nous lisons le contenu du cookies et nous "décryptons" le cookies.

Faisons le point :

function decryptCookies(valeurDecrypt){
  var chaineCookies = document.cookie.indexOf (";", valeurDecrypt);
  if (chaineCookies == -1)  { chaineCookies = document.cookie.length; }
  return unescape(document.cookie.substring(valeurDecrypt, chaineCookies));  }


Que se passe t'il ici ?
Simplement que par un transfers d'une valeur dans la fonction (par la variable valeurDecrypt), je demande que l'on sépare à chaque ";" du contenu de la variable valeurDecrypt en une sous-chaine de caractère lisible (donc "décrypté" par unescape()).

Ceci n'est que pour décoder le contenu du cookies. Maintenant il nous faut accéder à ce cookies, et cela se fait via une autre petite fonction en Javascript (que nous baptiserons pourquoi pas : lireCookies).
Identiquement, à la création du cookies, cette fonction doit comporter un nombre certain de paramètre toutefois beaucoup plus restreint car je ne dois connaitre que le nom. Le restant des informations étant lu, je n'ai qu'à les extraires.

function lireCookies(nomCookies) {
  var argumentCookies = nomCookies + "=";
  var argumentLongeur = argumentCookies.length;
  var cookiesLongueur = document.cookie.length;
  var i = 0;
  while (i < cookiesLongueur){
    var j = i + argumentLongueur;
    if (document.cookie.substring(i, j) == argumentCookies) { 
        return decryptCookies(j); i = document.cookie.indexOf(" ",i) + 1; }
    if (i == 0) { break; } } return null;  }


A nouveau passons en détail la fonction :
  • nomCookies : est le nom du cookies que je dois lire... C'est la seule chose que l'on doit vraiment connaitre ;
  • cookiesLongueur : est le nombre de sous-structure que comporte le contenu du cookies, c'est la valeur structurée en zone de mémoire que nous devrons "décrypter" via la fonction decryptCookies ;
  • i : est la variable d'initialisation du compteur pour une boucle ;
  • while (i < cookiesLongueur) : est la boucle informant que tant que la valeur de i est plus petite que le nombre maximum de la zone mémoire, il doit y avoir instruction contenu dans la boucle de la fonction de décryptage du cookies (via la fonction decryptCookies(valeur_a_decrypter) qui est ici j (le nombre de la zone mémoire à décrypter) ;


Ces 3 fonctions sont dissociable en 2 parties : écriture, lecture + décryptage.

Lorsque ces 3 fonctions sont connues, maitrisée et "installée", nous pouvons donc les utiliser dans de très simples appels javascript :

dateExpiration = new Date();
dateExpiration.setDate(dateExpiration.getDay() + 15); // expire dans quinze jour
monCookies("nomDuCookies", "valeurDuCookies", dateExpiration);


Identiquement pour lire le cookie, j'emploierais donc la syntaxe suivante :

var o;
o = lireCookies('nomDuCookies');


N'oublions pas que le Javascript (je ne le répèterais jamais assez) est un langage client, donc pas obligatoirement exécuté par le logiciel du visiteur et même si ce langage est interprété par l'internaute, ce dernier peut avoir configuré le navigateur pour qu'il n'accepte pas les cookies.
Ce type de fonction est donc à interpréter avec parcimonie.

Source des codes : fr.selfhtml.org, Conseil-Creations.com, CommentCaMarche.com, etc. ; remanié par Groumphy.

StyleSwitcher : changer le css à la volée via un javascript

, , , ...

Bien souvent les solutions pour adapter les styles sont composée de PHP, ASP etc. Heureusement, il a été développé il y a quelques temps une solution en JavaScript.

Excepté erreur de ma part, le premier à avoir tenté l'expérience fut l'excellent site A List Apart. Il a donc donné un article précis et conci. Passons le en revue.

Pour changer le style, il faut que le navigateur du client puisse interpréter les fonctions. Evidement il faudra que le Javascript soit activé. De fait, l'utilisation de la balise NoScript n'est pas à oublier.

En second temps, il faut lier les feuilles de styles de la manière suivante :
<link title="css1" rel="stylesheet" type="text/css" href="css1.css" media="screen">
<link title="css2" rel="alternate stylesheet" href="css2.css" type="text/css" media="screen">


Que se passe t'il ici ?
Nous donnons simplement une feuille de style générale et par défaut (la css1.css). Nous attribuons aussi un style secondaire (la css2.css) ; et c'est tout !

Dans la continuité, il nous faut créer une fonction en Javascript. La fonction sera principalement orientée vers la reconnaissance des balises en Javascript via getElementByTagName.
Bien entendu cette reconnaissance sera liée avec l'élément Link que nous utilisons pour lier les feuilles de styles.

Voici donc LA fonction (oui oui, vous avez bien lu la majuscule) qui a été bien concue :
function setActiveStyleSheet(title) {
   var i, a, main;
   for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
     if(a.getAttribute("rel").indexOf("style") != -1
        && a.getAttribute("title")) {
       a.disabled = true;
       if(a.getAttribute("title") == title) a.disabled = false;
     }
   }
}


Le plus dur est fait.
Il nous faut simplement maintenant voir pour lancer la fonction sur un simple appel.
Le site A List Apart donne l'exemple de faire l'appel de la fonction setActiveStyleSheet sur un élément onClick.

D'un avis personnel, je préfère l'appel de la fonction via "un bon vieux lien" dans lequel on précise un appel Javascript.
Faisons le point sur cela :
<a href="javascript:setActiveStyleSheet('css1')">Style 1</a>
<a href="javascript:setActiveStyleSheet('css2')">Style 2</a>


il nous suffit maintenant d'inclure ces liens dans une liste non ordonnée que nous placerons par exemple en Inline pour le Display.
Dans la continuité, nous pouvons bien entendu utiliser des pseudo-classes :before et :after pour agrémenter une présentation (par exemple avec un Content: " | "; ).

Par la suite, il faut simplement stocker le choix de l'utilisateur courant dans un cookies et le tour est joué ; en effet, la fonction ici n'est pas "permanente", elle n'a pas d'élément pour lire une information qu'elle a déjà été exécutée ou autre et ne sait pas le style choisis a la prochaine visite de la page.

La Les questions que l'on pourrais se poser est la sont les suivantes :

Est-ce que ce genre de fonction existe aussi pour des feuilles de styles implémentées en dur dans la page ?
Est-ce qu'il existe un moyen de faire varier la balise utilisée, par exemple sur un Import ?



J'essayerais de trouver une fonction similaire dans les prochains jours afin de vérifier cela... A défaut, je ferais quelques tests pour vérifier en changeant principalement le getElementByTagName etc.

A suivre donc...
November 2009
M T W T F S S
October 2009December 2009
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30