Pages

samedi 31 décembre 2011

Stop aux liens qui s'ouvrent grâce à javascript !

Il n'y a rien de plus énervant pour moi qu'un lien qui s'ouvre en java-script. J'ai pour habitude en lisant un article ou certains sites d'annonces d'ouvrir les liens potentiellement intéressants dans un nouvel onglet.
Ceux s'ouvrant en java-script sont une vraie plaie ! Ils ouvrent une page blanche et quelle horreur de constater qu'après un quart d'heure de recherche, toutes mes annonces dûment sélectionnées sont ouvertes sur le néant. Obligé de tout recommencer, ça fait vraiment ch**r -_-.
Et c'est un vrai parcours du combattant pour l'ouvrir dans un onglet :
  1. ouvrir le lien
  2. copier l'url (Ctrl+L, Ctrl+C)
  3. retour en arrière (Ctrl+gauche ou Alt+gauche)
  4. ouvrir un nouvel onglet (Ctrl+T)
  5. aller sur la page copier (Ctrl+Shift+V ou Ctrl+V, Entrée)
  6. revenir sur les annonces (Ctrl+Tab, ou Ctrl+Shift+Tab)
6 étapes pour un pauvre onglet en arrière-plan…

Alors par pitié, mettez un vrai lien, pas un bout de javascript.

mercredi 28 décembre 2011

Charger des pages avec ajax sans gêner les utilisateurs n'ayant pas javascript

Le but d'un site chargeant ces pages avec ajax est de diminuer la charge du serveur en ne demandant que le contenu principal (pas de menu, footer et autres contenus inchangés). Ceci pour une navigation plus rapide.
Le problème apparaît quelquefois au niveau de l'historique et si ce n'est pas pensé, impossible d'accéder à une page via son url. Quant à ceux n'ayant pas java-script ‑moteur de recherche compris‑ il est totalement impossible de visiter le site.

Le premier problème peut se corriger avec history.pushState ou la lib history.js qui permet de normaliser d'un navigateur à l'autre et utilise des ancres pour les vieux navigateurs (ceux ne supportant pas HTML5).

Le second problème est tout simple, il suffit d'indiquer une page complète et ajouter un paramètre dans l'url pour les utilisateurs ayant java-script. Si ce paramètre existe la page ne renvoie que le contenu principal, il ne reste plus qu'à remplacer l'ancien par le nouveau.

Par exemple avec un lien sur ma_page.php qui retourne une page complète.
On intercepte l'événement click. On ajoute un paramètre, par exemple 'ajax', ce qui donne ma_page.php?ajax puis on charge cette page. Le serveur ne renvoie que le contenu, on ajoute ma_page.php dans l'historique et on remplace l'ancien contenu par le nouveau.
De plus, il serait de bon ton d'indiquer le chargement quelque part, c'est perturbant de ne rien voir :).

vendredi 23 décembre 2011

int[2] comment_retourner_un_tableau();

Vous est-il déjà arrivé de vouloir retourner un tableau de n valeur ?
Un prototype du genre int[2] f(); ?
Et là, c'est le drame, un expected unqualified-id before ‘[’ token empêche de compiler.

La meilleure solution est de retourner un objet. Le plus simple étant std::array du C++0x ou boost::array. Un std::vector fera aussi l'affaire ;).

Une autre solution est de retourner un pointeur. Niveau typage c'est pas le top : on perd l'information sur la taille. Mais pourquoi pas.
Attention quand même ! Regardez bien l'exemple suivant :
int* f()
{
 int a[] = {0,1,2,3,4};
 return a;
}

int main()
{
 int* a = f();
 std::cout << a[2] << ',';
 a[2] = 0;
 int* a2 = new int[5];
 std::cout << a[2] << std::endl;
 return 0;
}
À première vue, rien de bien dangereux. Cependant le compilo nous dit warning: address of local variable ‘a’ returned. Étrange erreur, c'est pourtant ce que l'on veut…
En exécutant le binaire celui-ci affiche quelque chose comme : 3,12812616681
Pourquoi ? Tout simplement parce que 'a' pointe sur une mémoire non allouée, ou pour être plus précis dés-allouée. Bah oui, 'a' en sortant de la fonction f est détruit, mais cela n'empêche pas de retourner son pointeur… vers un espace mémoire libre. Le compilateur nous avait prévenu ;).

En réalité f devrait ressembler à
int* f()
{
 int* a = new int[5];
 a[0] = 0;
 a[1] = 1;
 a[2] = 2;
 a[3] = 3;
 a[4] = 4;
 return a;
}
Mais pour éviter les fuites mémoires, ne pas oublier delete[]. Si on veut retourner un pointeur il sera peut-être préférable de retourner un pointeur intelligent, au moins le delete sera automatique.
On revient à la phrase du début, le plus simple reste le retour d'un objet.

std::array<5, int> f()
{
 return {{0,1,2,3,4}};
}

jeudi 22 décembre 2011

jQuery(context).find(expr) vs jQuery(expr, context)

Saviez-vous que $(this).find(".truc") est l'équivalent de $(".truc", this) ?
Mais saviez-vous que le second exemple appelle le premier ;) ?
Maintenant oui ! Alors préférer le premier, ça ne sera que plus performant.

mercredi 30 novembre 2011

falcon: un ensemble de fonctions et classes basé sur le nouveau standard du C++

J'attends avec impatience que les standards du C++0x et C++11 soient introduits dans les compilateurs. Les nouveautés sont très intéressantes et permettent des choses qui étaient alors impossibles.
Il y a quelques semaines une mise à jour des dépôts m'a fait passer à g++4.6.1. Même si tout n'est pas encore terminé ‑comme le support du nouveau mot clef constexp ou certaines fonctions comme tuple::tie‑ la mise à jour apporte quand même le support de nullptr et la nouvelle syntaxe du for :
exemple
std::forward_list<int> l({0,1,2,3,4});
for(auto& v: l)
  ++v;
std::endl(std::cout);
for(auto v: l)
  std::cout << v << ',';

Il y a sûrement eu d'autres améliorations mais je n'ai pas vraiment regardé. Hélas, l'IDE que j'utilise (KDevelop) ne supporte pas de faire des fonctions lambda ou certaines autres améliorations syntaxiques (mais quel IDE le supporte ?)
exemple d'utilisation d'une fonction lambda
std::for_each<>(l.begin(), l.end(), [](int& i){
  std::cout << v << ',';
});

Pour combler ce problème et ne pas avoir un nombre trop conséquent d'erreurs qui ralentissent inutilement l'interpréteur j'ai fait un ensemble de macros.
Bien sûr certaines macros sont totalement incompatibles avec C++99 (celles du dossier c++0x). Mais dans ce cas un joli message va l'indiquer (honteusement repris d'un header de la std).
Falcon est composé d'un peu plus de cent fichiers divisés en plusieurs ensembles, en voici quelques-uns:
  • sfinae: qui permet de vérifier l'existence d'un type, d'un nom de fonction, si cette fonction est appelable avec tel ou tel paramètre, ainsi que la vérification d'un retour convertible en un autre type.
  • lambda: qui se comporte comme boost::lambda mais sans l'erreur de la rvalue référence.
  • algorithm: qui permet d'appeler les algorithmes de la std en donnant un container (donc pas besoin de faire begin() et end()). Fonctionne aussi avec les tableaux.
  • iterator: un ensemble itérateur plus ou moins étrange comme un itérateur infini ou un faux itérateur.
  • arg: qui permet de faire joujou avec les paramètres varialen pour, par exemple récupérer le type ou la valeur d'un paramètre positionné à une place n.
Il y en a bien d'autres mais autant télécharger les sources. Tout n'est pas fini pour autant et il y aura sûrement des ajouts… quand j'aurai de nouvelles idées :).

dl falcon. Le fichier Doxygen permet de générer une documentation, je vous conseille de générer la doc avec et sans la macro __GXX_EXPERIMENTAL_CXX0X__. Doxygen ne supportant pas encore bien c++0x les résultats sont catastrophiques sur certaines parties.

Switch-viewer pour KDevelop


Switch-viewer est un plugin conçu pour KDevelop suite au manque de fonctionnalités au niveau de la vue. Les vues correspondent au cadre contenant les fichiers, mais aucun moyen de se déplacer d'une vue à l'autre simplement. La seule façon de faire est de sélectionner le fichier (trier par ordre d'activation), seul problème, comment savoir quel fichier appartient à la vue s'il est ouvert plusieurs fois ?

Switch-viwer permet de résoudre ce problème et ajoute quelques fonctionnalités au niveau des vues :

Le passage d'une vue à l'autre se fait en boucle, la vue qui suit la dernière est la première et celle qui précède la première est la dernière.
  • Allez à la vue suivante (ALT+V).
  • Allez à la vue précédente (ALT+SHIFT+V).
Le déplacement d'un fichier d'une vue à l'autre la scinde si elle ne l'est pas déjà.
  • Déplacer le fichier courant dans la vue suivante (CTRL+ALT+V).
  • Déplacer le fichier courant dans la vue précédente (CTRL+ALT+SHIFT+V).
  • Supprimer les vues déjà présentes dans d'autres groupes.
  • Supprimer les vues du groupe présentes dans d'autres groupes.

mardi 12 juillet 2011

Plugin qui sauvegarde la position de curseurs dans un document

Ces derniers jours j'ai codé un petit plugin pour les logiciels katepart. Cette fois, c'est du C++/Kde, ça permet beaucoup plus de choses et de toute manière pour ce que je voulais, c'est un peu obligé.

Le plugin permet d'avoir plusieurs curseurs en ajoutant ou supprimant des curseurs virtuels dans un document. Tous les textes écrits ou supprimés seront répétés sur chacun des curseurs virtuels.

Plusieurs options sont disponibles:
  • Synchroniser le déplacement du curseur avec les curseurs virtuels.
  • Se déplacer entre les curseurs 
  • Désactiver les curseurs sans les supprimer
  • Supprimer tous les curseurs ou ceux se situant sur la ligne 
Si une sélection est présente:
  • Ajouter un curseur le fait pour toutes les lignes de la sélection
  • Supprime tous les curseurs ne prend effet que dans la sélection
Le dépôt se trouve sur google code à cette adresse: https://code.google.com/p/ktexteditor-mcursors/

J'en est profité pour mettre à jour mes commandes js en supprimant les fonctions cadd, cremove, cmove, ccopy qui reposent sur le même principe mais avec quelques lacunes liées à l'api js. J'ai aussi ajouté une nouvelle commande: une transposition avancée de caractère, plus poussée que celle par défaut et accessible avec Ctrl+Alt+T.

jeudi 9 juin 2011

90 commandes pour Katepart

Étant un fervent utilisateur de kde et de ces logiciels, je me suis dit qu'il était de bon ton d'ajouter des fonctionnalités à certains: kwrite, kate et kdevelop.
Ces 3 logiciels ainsi que quelques autres reposent sur le composant Katepart qui est en quelque sorte la base de l'éditeur de texte. Katepart possède la faculté d'être étendu via des commandes et des plugins. Les plugins sont codés en C++/Qt et les scripts en java-script.
Comme je ne voulais rajouter que quelques commandes simples, je me suis naturellement tourné vers l'api javascript. Au final le nombre de commande ajouté est assez conséquent (90) et quelques-une seraient plus appropriées en tant que plugin (un jour peut-être quand j'en aurai vraiment besoin).

Les sources js à mettre dans /home/utilisateur/.kde/share/apps/katepart/script/ ainsi qu'une documentation en xml/xsl se trouvent ici.
PS : Le fichier xml s'affiche bien sur un navigateur récent.


Voici le nom des 90 commandes ajoutées :  duplicate, insert, insertLeft, detach, detachLeft, set-namespace-tag, set-always-write-namespace, tag, repeat, repeatLine, replace, replaceLine, change, changeLine, cursor, join2, echap, interval, rgxinterval, call, apply, kill, filename, extension, url, mimeType, encoding, highlightingMode, highlightingModeCursor, cadd, cremove, cmove, ccopy, diffSelection, reverseLine, reverseWord, reverse, sort2, natsort2, usort, rsort, rnatsort, rusort, tr, mv, mvLine, slice, length, align, outer, outerLine, wrap, wrapLine, unouter, unouterLine, unwrap, unwrapLine, explode, cut, countChar, countLine, countWord, countLongWord, countRgx, count, set-call-interpret-string, swap, rewindSelection, selectBlock, uniq2, romanNumeral, encodeuri, decodeuri, rmLinesWithOnly, rmText, rmTextOf, rmNCharacter, rmNCharacterLeft, nreplace, nreplaceLeft, select, between, createFunction, alias, execFunction, eval, printEval, insertEval, range, random.