Comme tout le monde le sait probablement maintenant, il n'y a pas de moyen facile de le faire. J'ai cependant trouvé une sorte d'astuce programmatique. Et quand je dis "kludge", je le pense vraiment ! Je ne pense pas que ce programme soit prêt pour le grand public, mais quelqu'un pourrait aimer bricoler avec ce concept et essayer de trouver quelque chose de réalisable.
L'idée est que, bien que vous ne puissiez pas lire la largeur du contenu de l'iframe, vous pouvez passer en boucle une série de largeurs pour l'iframe lui-même jusqu'à ce que vous trouviez celle qui empêche tout juste le texte à l'intérieur de s'enrouler. À ce moment-là, le texte doit toucher le côté droit de l'iframe. En d'autres termes, nous voulons définir la largeur de l'iframe à 1px de plus que la largeur qui ferait que le texte s'enroule.
Détecter si le texte est enveloppant est en principe assez facile : vous définissez la largeur de l'iframe, vous attendez que le code FB ajuste le contenu, puis vous lisez la hauteur. Si tout tient sur une seule ligne, la hauteur doit être d'environ 25px. Plus que cela signifie que le texte est enveloppé.
La difficulté vient de la partie "attendre que le code FB ajuste le contenu". J'ai l'impression qu'il doit y avoir un moyen de forcer un "redessin" de l'iframe, mais je ne l'ai pas encore trouvé. Appeler FB.XFBML.parse() est évident, mais cela ne semble pas fonctionner. C'est la partie où je suis coincé. Je force l'iframe à se recharger en définissant son attribut src, ce qui fait l'affaire mais à un prix horrible en termes de vitesse. Il ne s'agit que d'une "preuve de concept" à ce stade. Un moyen simple de savoir quand un redessin est terminé serait presque aussi bon ; je pense que cela devrait être possible, mais mon cerveau s'est enlisé avant que je trouve quelque chose de simple.
Quoi qu'il en soit, voici un code de test si vous voulez l'essayer. Cela prend une éternité pour que le bouton soit en position, mais cela fonctionne au moins. J'ai laissé tout visible pendant le processus de chargement pour que vous puissiez voir ce qu'il fait, sur une vraie page il serait mieux de garder les choses cachées jusqu'à ce que tout soit prêt. Notez également que l'alignement peut être légèrement décalé parce que j'ajuste la largeur 5px à la fois. Si les choses pouvaient être faites plus rapidement, il serait facile d'utiliser 1px à la place. Il serait encore mieux d'effectuer un ajustement grossier pour se rapprocher, puis un ajustement fin pour obtenir un résultat parfait. Il y a évidemment beaucoup d'expériences à faire, pour ceux qui voudraient s'y mettre.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type='text/javascript'>
var likediv, likeframe;
function loadcode(d, s, id)
{
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}
function init()
{
loadcode(document, 'script', 'facebook-jssdk');
likediv=document.getElementById('d2');
setTimeout(initx, 10);
}
function initx()
{
likeframe=likediv.getElementsByTagName('iframe')[0];
if (!likeframe) { setTimeout(initx, 10); return; }
likeframe.style.width='225px';
setTimeout(shrink, 10);
}
function shrink()
{
likeframe=likediv.getElementsByTagName('iframe')[0];
var currwidth=parseInt(likeframe.style.width);
if (currwidth>=500) return;
newwidth=currwidth+5;
likeframe.style.width=newwidth+'px';
likeframe.style.height='0';
likeframe.src=likeframe.src;
setTimeout(checkframe, 10);
}
function checkframe()
{
var h=parseInt(likeframe.offsetHeight);
if (h==0) setTimeout(checkframe, 10);
else if (h>25) shrink();
//else we are done; make the frame visible if we hid it earlier
}
</script>
</head>
<body onload='init()' style='margin:10px 50px'>
<div id="fb-root"></div>
<div style='text-align:right'>Here is some right-aligned text to compare to.</div>
<div id='d2' style='float:right;height:25px;overflow:hidden;border:1px dotted red'>
<div class="fb-like" data-send="false" data-width="225" data-show-faces="false" data-action="recommend"></div>
</div>
</body>
</html>
EDIT : J'ai fait un peu plus d'expériences, toujours une solution de contournement maladroite mais plus rapide qu'avant :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type='text/javascript'>
var likediv, likeframe, targwidth;
function loadcode(d, s, id)
{
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}
function init()
{
loadcode(document, 'script', 'facebook-jssdk');
likediv=document.getElementById('d2');
setTimeout(initx, 10);
}
function initx()
{
likeframe=likediv.getElementsByTagName('iframe')[0];
if (!likeframe) { setTimeout(initx, 10); return; }
likeframe.style.width='225px';
setTimeout(shrink, 10);
}
function shrink()
{
likeframe=likediv.getElementsByTagName('iframe')[0];
var currwidth=parseInt(likeframe.style.width);
if (currwidth>=500) return;
targwidth=currwidth+5;
likeframe.style.width='10px';
likeframe.style.height='0';
setTimeout(checkframe, 10);
}
function checkframe()
{
var h=parseInt(likeframe.offsetHeight);
if (h==0) { setTimeout(checkframe, 10); return; }
likeframe.style.width=targwidth+'px';
likeframe.style.height='0';
setTimeout(checkframe2, 10);
}
function checkframe2()
{
var h=parseInt(likeframe.offsetHeight);
if (h==0) setTimeout(checkframe2, 10);
else if (h>25) shrink();
//else we are done; make the frame visible if we hid it earlier
}
</script>
</head>
<body onload='init()' style='margin:10px 50px'>
<div id="fb-root"></div>
<div style='text-align:right'>Here is some right-aligned text to compare to.</div>
<div id='d2' style='float:right;height:25px;overflow:hidden;border:1px dotted red'>
<div class="fb-like" data-send="false" data-width="225" data-show-faces="false" data-action="recommend"></div>
</div>
</body>
</html>
FINAL EDIT : Je pense que cette méthode n'a jamais été aussi efficace ; le code pourrait certainement être modifié, mais il faudra toujours plusieurs secondes pour tester toutes les largeurs afin de trouver ce qui fonctionne. Mais c'est maintenant suffisamment rapide (environ 5 secondes) pour être utilisable. J'ajoute chaque nouvelle version du code plutôt que de remplacer les anciennes parce que je n'ai pas fait beaucoup de tests inter-navigateurs de ce code et il est possible que les versions plus rapides ne fonctionnent pas pour quelqu'un. Puisqu'il s'agit d'un code expérimental, je pense qu'il est préférable d'avoir les différentes versions disponibles pour une solution de repli.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type='text/javascript'>
var minwidth=225, maxwidth=500, finished=false, last_was_good=null;
var likediv, likeframe, targwidth, boundlow, boundhigh;
function loadcode(d, s, id)
{
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}
function init()
{
loadcode(document, 'script', 'facebook-jssdk');
likediv=document.getElementById('d2');
setTimeout(initx, 10);
}
function initx()
{
likeframe=likediv.getElementsByTagName('iframe')[0];
if (!likeframe) { setTimeout(initx, 10); return; }
likeframe.style.width=minwidth+'px';
setTimeout(trynewwidth, 1);
}
function trynewwidth()
{
if (last_was_good==null) { boundlow=minwidth; boundhigh=maxwidth; }
else if (last_was_good) boundhigh=targwidth;
else boundlow=targwidth;
finished=((boundhigh-boundlow)<2);
if (finished && last_was_good) { done(); return; }
if (finished && !last_was_good) targwidth=boundhigh;
else targwidth=parseInt((boundlow+boundhigh)/2);
setTimeout(setwidth, 1);
}
function done()
{
//All finished, if we were hiding the div make it visible now
}
function setwidth()
{
likeframe=likediv.getElementsByTagName('iframe')[0];
likeframe.style.width='10px';
likeframe.style.height='0';
setTimeout(checkframe, 10);
}
function checkframe()
{
var h=parseInt(likeframe.offsetHeight);
if (h==0) { setTimeout(checkframe, 10); return; }
likeframe.style.width=targwidth+'px';
likeframe.style.height='0';
setTimeout(checkframe2, 10);
}
function checkframe2()
{
var h=parseInt(likeframe.offsetHeight);
if (h==0) { setTimeout(checkframe2, 10); return; }
if (finished) { done(); return; }
last_was_good=(h<26);
setTimeout(trynewwidth, 1);
}
</script>
</head>
<body onload='init()' style='margin:10px 50px'>
<div id="fb-root"></div>
<div style='text-align:right'>Here is some right-aligned text to compare to.</div>
<div id='d2' style='float:right;height:25px;overflow:hidden;border:1px dotted red'>
<div class="fb-like" data-send="false" data-width="225" data-show-faces="false" data-action="recommend"></div>
</div>
</body>
</html>