Pour un script de tooltip développé rapidement sur un gros projet en cours, j'ai utilisé le plugin position de jQuery UI.
Cette fonction permet de positionner exactement comme on veut un élément par rapport à un autre. La fonction utlime pour une infobulle.
Et ce plugin vient même avec une détection de collision avec la fenêtre. Autrement dit, si l'élément positionné dépasse de la fenêtre, alors on le positionne de l'autre côté. Un must !
Le seul problème est qu'il n'existe actuellement aucune possibilité de détecter lorsque cela arrive.
En lisant le code de ce plugin, il existe en réalité un moyen très simple pour détecter cette collision et ajouter une classe à l'élément positionné. Dans mon cas, cela me permet de modifier l'affichage de l'infobulle de façon à avoir la flèche du bon côté.
Le code en question :
var currentlyPositionning,
initPos;
$.ui.position.custom = {
left: function(position, data) {
initPos = position.left;
$.ui.position.flip.left(position, data);
if (initPos != position.left) {
currentlyPositionning.addClass('tooltipFlip');
}
},
top: function(position, data) {
initPos = position.top;
$.ui.position.flip.top(position, data);
if (initPos != position.top) {
currentlyPositionning.addClass('tooltipFlip');
}
}
};
En réalité, on ajoute simplement une option custom au plugin position. Pour chacune des propriétés top ou left pour lesquels le plugin détecte une collision, on vérifie si la propriété a été modifié par la fonction de détection originelle du plugin. Et si oui, dans mon cas, j'ajoute une classe à l'élément.
Vous avez sans doute remarqué la variable currentlyPositionning ; Elle doit correspondre à l'élément sur lequel on applique actuellement la position. En effet, aucune information dans l'objet data ne permet de remonter jusqu'à cet élément.
Enfin, pour utiliser cette nouvelle fonctionnalité, il suffit d'appeler le plugin position comme suit :
currentlyPositionning = elem;
elem.position({
of: me,
my: 'left bottom',
at: 'right top',
offset: '15px',
collision: 'custom'
});
Et voilà, le tour est joué.