Blog

Internet Explorer : javascript et <base>

1 août 2010

Posté dans : Javascript | Tags : , , | Aucune réponse

La balise HTML <base> permet de définir l’URL de base d’une page, tout URL relatif présent dans la page sera résolu selon cette base et non plus selon l’adresse de la page elle-même. Ce principe est valable pour les liens vers d’autres pages mais également les feuilles de style, les fichiers Javascript ou encore les images.

Les navigateurs modernes utilisent également cette base en Javascript. En définissant par exemple la base comme étant http://mon-site.com/fr/, le code suivant : window.location.ref = "contact/"; chargera la page http://mon-site.com/fr/contact/, quelque soit l’adresse à laquelle vous êtes. Malheureusement, le mauvais élève qu’est Internet Explorer (y compris la version 8) ignore totalement la base et vous serez renvoyé sur une page du genre http://monsite.com/fr/articles/2010/08/contact/ et vous obtiendrez une belle erreur 404.

Pour remédier au problème, voici une petite fonction jQuery toute simple qui force la prise en compte de la balise si elle est présente : function location(url) {
var base = $("base");
window.location.href = (base ? base.attr("href") : "")+url;
}

À noter que le problème est le même avec window.location.replace().

Adoucir le scroll des liens internes avec jQuery

23 avr 2010

Posté dans : Javascript | Tags : , , | Aucune réponse

De plus en plus de sites ajoutent un effet aux liens internes de leurs pages pour rendre le scroll plus attrayant, voici un petit bout de code pour reproduire cet effet grâce à jQuery : $(function() {
var scrollElement = $("html");
var scrollValue = scrollElement.scrollTop();
if (scrollElement.scrollTop(scrollValue + 1).scrollTop() == scrollValue) {
scrollElement = $("body");
}
else {
scrollElement.scrollTop(scrollValue);
}
$("a[href*=#]").click(function() {
if (location.hostname+location.pathname+location.search == this.hostname+this.pathname.replace(/^([^\/].*)/, "/$1")+this.search) {
var hash = "#"+$(this).attr("href").split("#")[1];
var target = $(hash == "#" ? body : hash);
if (target.length) {
var id = target.attr("id");
target.attr("id", "");
location.hash = hash;
target.attr("id", id);
var to = target.offset().top;
scrollElement.animate({ scrollTop: to }, {
duration: Math.abs($(window).scrollTop() - to) * 0.75,
complete: function() { target.focus(); }
});
return false;
}
}
});
});

Fonctionnement

  1. Lignes 2 à 9 : pour faire le scroll, il faudra animer la propriété scrollTop du noeud racine de la page. On pourrait se contenter d’utiliser le sélecteur « html,body » pour couvrir tous les navigateurs mais ça provoque un méchant bug sous Opera. On prend donc « html » par défaut ou « body » si ça ne fonctionne pas.
  2. Ligne 10 : le sélecteur « a[href*=#] » s’applique à tous les liens de la page dont l’attribut contient le caractère « # ».
  3. Ligne 11 : vérification que la cible est bien sur la page actuelle, dans le cas contraire il n’y a pas de scroll donc inutile d’aller plus loin.
  4. Lignes 15 à 18 : la fonction supprime le comportement par défaut du clic. On perd donc le scroll immédiat – comme souhaité – mais aussi la gestion de l’historique. Cette partie du code sert à rétablir cette dernière.
  5. Lignes 19 à 23 : création du scroll animé, il suffit de changer la valeur du paramètre duration pour changer la durée du scroll. Dans l’exemple ci-dessus la durée est calculée en fonction de la distance à parcourir.

Problèmes connus

A cause de la partie gérant l’historique, le navigateur ne connait plus la cible du lien le temps du clic. Si vous utilisez la pseudo-classe CSS3 :target, le style ne sera pas appliqué du tout dans le cas où l’utilisateur a cliqué sur le lien ; cela ne pose en revanche aucun problème dans le cas où l’ancre a été ajoutée manuellement à l’adresse par l’utilisateur.
Un autre bug moins gênant mais assez étrange : ce code ne marche pas sous Safari, Chrome ou Opera si la cible est « #top ». Là encore parce que le navigateur ne connait plus la cible au moment du clic : pour une raison que j’ignore, ces navigateurs considèrent que « #top » correspond au haut de page si aucun élément n’a cet identifiant ailleur dans la page. Du coup, au lieu de faire un joli scroll vers la cible, le navigateur se retrouve immédiatement en haut de page. Si vous avez la moindre explication sur ce comportement, n’hésitez pas à le faire savoir dans les commentaires où sur le thread que j’ai ouvert sur Alsacréations à ce sujet :)

Mise à jour le 24/05/2010 à 23:53

Lorsque la cible est en bas de page, il est fréquent que le scroll s’arrête avant par manque de place (cible plus petite que la fenêtre du navigateur). Cette modification permet de tenir compte de ce cas particulier, la fin du scroll reste fluide au lieu de s’arrêter brusquement sans pouvoir aller plus loin. Il suffit de mettre à jour la ligne 19 : $(function() {
var scrollElement = $("html");
var scrollValue = scrollElement.scrollTop();
if (scrollElement.scrollTop(scrollValue + 1).scrollTop() == scrollValue) {
scrollElement = $("body");
}
else {
scrollElement.scrollTop(scrollValue);
}
$("a[href*=#]").click(function() {
if (location.hostname+location.pathname+location.search == this.hostname+this.pathname.replace(/^([^\/].*)/, "/$1")+this.search) {
var hash = "#"+$(this).attr("href").split("#")[1];
var target = $(hash == "#" ? body : hash);
if (target.length) {
var id = target.attr("id");
target.attr("id", "");
location.hash = hash;
target.attr("id", id);
var to = Math.min(target.offset().top, $(document).height() - $(window).height());
scrollElement.animate({ scrollTop: to }, {
duration: Math.abs($(window).scrollTop() - to) * 0.75,
complete: function() { target.focus(); }
});
return false;
}
}
});
});

Intégrer WordPress à un site existant

10 mar 2010

Posté dans : PHP | Tags : , , | 8 réponses

WordPress a l’avantage de fonctionner entièrement en PHP y compris pour les thèmes, ce qui le rend assez flexible. C’est pourquoi il est relativement facile d’intégrer WordPress à un site existant, pour y apporter un moteur de blog efficace tout en gardant le design du site. Il suffit de créer un nouveau thème et de le bidouiller un peu.

Le thème WordPress

Si vous avez bien construit votre site, vous avez probablement des fichiers header et footer que vous incluez dans chacune de vos pages ou un système équivalent. WordPress fonctionne également de cette manière avec les fichiers header.php et footer.php du thème. Tout ce que vous avez à faire est de mettre dans ces templates les instructions pour récupérer vos propres fichiers.

header.php : require_once('chemin/vers/mon/fichier/header.php'); et footer.php : require_once('chemin/vers/mon/fichier/footer.php');

Dans votre propre header, vous faites sûrement appel à d’autres fichiers (configuration, textes, …). Si ces fichiers contiennent des variables que vous réutilisez un peu partout sur votre site — notamment les textes — celles-ci ne seront pas accessibles dans les fichiers de votre thème et la raison est simple : les variables globales ne sont par défaut pas accessibles à l’intérieur d’une fonction, le code exécuté par get_header() n’a donc pas accès à vos textes et autres variables utiles.

Lorsque vous ne pouvez pas utiliser get_header() dans votre thème, vous devez inclure manuellement les fichiers : // TEMPLATEPATH = chemin du thème
require_once(TEMPLATEPATH.'/header.php');

Le principe est le même pour tous les éléments de votre thème à une exception près : les commentaires. Ce template s’insère via la fonction comments_template(). Ici cette fonction est obligatoire car en plus de récupérer votre template, elle va initaliser la plupart des variables dont vous aurez besoin pour afficher les commentaires. Il va donc falloir bidouiller pour accéder à la fois aux variables des commentaires et à vos propres variables, en ajoutant au début de comments.php le code suivant : if (empty($do_comments_template))
{
return false;
}

Ainsi l’appel à comments_template() permettra d’initialiser les variables des commentaires sans afficher le template. Il ne reste plus qu’à placer le code suivant juste après l’appel : $do_comments_template = true;
require(TEMPLATEPATH.'/comments.php');

Rien ne vous empêche d’utiliser un autre nom de variable que $do_comments_template, l’important étant qu’elle soit initialisée entre la première et la seconde inclusion du template.

Vous devrez également adapter le template pour le formulaire de réponse. WordPress mémorise les informations des utilisateurs qui postent des commentaires pour remplir automatiquement le formulaire. Dans les thèmes classiques, ces informations sont stockées dans les variables $comment_author, $comment_author_email, $comment_author_url mais avec la méthode ci-dessous, elles sont perdues. Voici comment les retrouver : $commenter = wp_get_current_commenter();
$comment_author = $commenter['comment_author'];
$comment_author_email = $commenter['comment_author_email'];
$comment_author_url = $commenter['comment_author_url'];

Après ça il ne vous reste plus qu’à adapter le reste du thème à vos feuilles de style. Bien entendu le fichier style.css n’a plus aucune utilité à partir du moment où vous avez déjà votre propre feuille de style, si ce n’est éventuellement préciser les informations de votre thème.

Fonctions WordPress dans vos pages

Maintenant votre blog est stylé comme votre site mais il manque des éléments dans vos pages. Il faut au moins ajouter des informations dans le header — le ou les flux RSS par exemple — et pour cela vous aurez besoin des fonctions de WordPress : if (!$blog) // Cette page n'est pas une page WordPress (adapter à votre code)
{
$_post = $_POST;
$_get = $_GET;
}
require_once('chemin/vers/votre/installation/wordpress/wp-load.php');
if (isset($_get) && isset($_post))
{
$_POST = $_post;
$_GET = $_get;
}

Avec ça vous aurez accès aux fonctions telles que bloginfo() ou wp_head(). Ce code, en plus de charger WordPress, va empêcher que celui-ci ne modifie vos données GET ou POST avec son mécanisme Magic Quotes maison.

Les Magic Quotes sont une fonctionnalité dont l’utilisation est déconseillée (deprecated depuis PHP 5.3 et supprimée dans PHP 6). Toutefois, WordPress implémente son propre système en modifiant les données, notamment $_GET et $_POST. Cela fonctionne très bien pour le blog mais avec le code ci-dessus, ce système est appliqué à tout votre site, ce qui peut poser problème si vous avez des formulaires. C’est pourquoi lorsqu’on n’est pas sur une page WordPress on stocke les variables $_GET et $_POST originales pour les rétablir juste après avoir chargé WordPress.

URL Rewriting

Vous avez probablement installé WordPress dans un répertoire bien à lui. Si vous souhaitez que l’URL soit différente vous pouvez le faire via l’URL Rewriting. Il faut d’abord indiquer la nouvelle adresse dans les réglages généraux de WordPress. Le champ « Adresse web du blog » passe donc de http://monsite.com/wordpress à http://monsite.com/blog. Il ne reste plus qu’à mettre un .htaccess à la racine de votre site avec la ligne suivante :
RewriteRule ^blog(/?)(.*)$ wordpress/$2 [L,QSA]