31 votes

Comment faire en sorte que la largeur du bouton "J'aime" de Facebook soit automatiquement redimensionnée ?

Je mets en œuvre le Bouton "J'aime" de Facebook mais j'ai des problèmes avec la largeur. J'utilise l'implémentation JavaScript SDK, pas le iframe direct.

Selon la documentation, la largeur par défaut est 450 . C'est très bien, et je comprends que la largeur peut être modifiée par le biais de la fonction width de l'attribut <fb:like> tag. Cependant, mon problème est que je ne peux vraiment pas spécifier une largeur fixe. En raison de la nature du bouton, la largeur n'est pas constante dans tous les états. Par exemple, si personne n'a encore aimé la page, il affiche "Soyez le premier de vos amis à aimer ceci" ; si quelqu'un l'a fait, il affiche "XXX personnes aiment ceci. Soyez le premier de vos amis" ; et encore si vous ont aimé, il affiche "Vous aimez ça". ou "Vous et XXX personnes aiment ça." En d'autres termes, il existe de nombreux états du bouton, dont aucun ne partage une largeur constante.

Ce ne serait pas un gros problème si ce n'était que je veux afficher le bouton de manière flottante sur le côté droit d'une fenêtre <div> . Pour être plus clair, voici ce que je suis en train de faire :

<div id="wrapper">
    <span class="fb-like"><fb:like show_faces="false" width="450" font="lucida grande""></fb:like></span>
    ...
</div>
<style type="text/css">
.fblike {
    display: inline-block;
    padding: 0.5em;
    position: absolute;
    right: 0;
    top: 0;
}
#wrapper {
    position: relative;
}
</style>

Cela fonctionne bien, mais le problème est que l'iframe a maintenant une largeur constante de 450 pixels. Comme l'iframe est aligné à gauche, lorsque le texte est plus court, il y a un espace supplémentaire à droite. J'ai essayé plusieurs applications de text-align: right en vain. Et le problème est encore aggravé par le fait qu'il s'agit en fait d'un balisage fantaisiste pour une iframe ajoutée par le SDK de FB. Je ne peux donc pas modifier son contenu avec CSS ou JavaScript.

J'ai besoin d'une solution qui permette soit (a) de conserver la largeur de la zone des boutons de manière dynamique (c'est-à-dire qu'elle change en fonction du contenu), soit (b) d'aligner à droite tout ce qui se trouve dans la zone des boutons.

Merci pour toute aide que vous pourrez m'apporter !

12voto

andriuspl Points 109
#fblike iframe {
    width: 95px !important;
}

#fblike .fb_edge_comment_widget iframe {
    width: 330px !important;
}

Et

<div id="fblike"><fb:like show-faces="false" layout="button_count"></fb:like></div>

De cette façon, les iframes des boutons "commentaire" et "j'aime" ont une largeur fixe. Pas d'effets bizarres. J'espère que cela vous aidera.

5voto

Pascal Points 1257

Si vous utilisez la version XFBML du bouton J'aime, ainsi que le kit SDK Javascript de Facebook, vous pouvez vous abonner à l'événement "xfbml.render" et, une fois cet événement déclenché, vous pouvez définir la largeur de l'iframe du bouton J'aime à une petite valeur. (J'utilise 50px.) La iframe ajustera ensuite automatiquement sa largeur en fonction des besoins pour afficher le bouton, le nombre de "like" et tout autre élément, selon votre configuration.

https://developers.facebook.com/docs/reference/javascript/

Le plus gros obstacle à cette solution est que vous aurez besoin d'un Facebook App ID. Vous pouvez obtenir un App ID en créant une application ici : https://developers.facebook.com/apps/

5voto

Floyd Wilburn Points 1762

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>

2voto

Jacob Thomason Points 319

J'utilise personnellement ce qui suit...

#fbook-like {
    width: 50px !important; /*width of just the button*/
    overflow: visible; /*so there is no cut off*/
    vertical-align: top; /*bc all other like buttons align top*/
}

Ce que j'ai fait ici, c'est de placer le bouton fb à l'extrême droite, de façon à ce qu'il s'aligne avec mon bord, et que seuls les commentaires ajoutés (dynamiques en largeur) apparaissent au-delà du bord. J'ai pu conserver un bon design tout en affichant les commentaires, quelle que soit leur longueur.

2voto

Tym3k Points 11

Correction CSS

.fb-like, 
.fb-like > span,
.fb-like > span iframe {
    max-width:273px;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X