fb:comment is setting wrong height (cuts comments in half) - gwt

I'm building a GWT application and am trying to dynamically add facebook comment boxes in certain places. This is working fine, except that the facebook SDK isn't calculating the height correctly. It always sets it at 160px.
This means that only half of the first comment is visible, even if there are multiple comments (i.e. it gets visibly cut in half). If I use the same code outside of GWT it works fine (i.e. the height is calculated correctly).
Does anybody know how the facebook SDK calculates the height of the box? Or what else I can try?
The details:
I initialise the facebook SDK as follows:
public static native void initFacebookSDK()
/*-{
window.fbAsyncInit = function() {
// init the FB JS SDK
FB.init({
appId : '<my-app-id>', // App ID from the App Dashboard
channelUrl : '//WWW.YOUR_DOMAIN.COM/channel.html', // Channel File for x-domain communication
status : true, // check the login status upon init?
cookie : true, // set sessions cookies to allow your server to access the session?
xfbml : true
// parse XFBML tags on this page?
});
// Additional initialization code such as adding Event Listeners goes here
};
// Load the SDK's source Asynchronously
(function(d, debug) {
var js, id = 'facebook-jssdk', ref = d
.getElementsByTagName('script')[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement('script');
js.id = id;
js.async = true;
js.src = "//connect.facebook.net/en_US/all"
+ (debug ? "/debug" : "") + ".js";
ref.parentNode.insertBefore(js, ref);
}(document, false));
}-*/;
I add the div as follows:
//_root is a vertical panel
_root.add(new HTML("<div id=\"mydiv\"></div>"));
and then I populate the div like this:
public static native void showComments(String currentUrl_)
/*-{
var mydiv = $doc.getElementById('mydiv');
mydiv.innerHTML = "<fb:comments href='" + currentUrl_
+ "' num_posts='5' width='422'></fb:comments>";
FB.XFBML.parse(mydiv);
}-*/;
The problem is that the facebook SDK always populates the div with the following:
<span style="height: 160px; width: 422px;">
<iframe ...>...</iframe>
</span>
whereas if I don't use GWT, the height parameter changes appropriately, e.g:
<span style="height: 1469px; width: 422px;">
<iframe ...>...</iframe>
</span>
Hope someone can help.

Worked it out.
In JSNI I should be using $doc and $wnd, instead of document and window, respectively. https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsJSNI#writing
In my defence I had tried this, but the missing ingredient was that I needed to reference the FB object as $wnd.FB, e.g:
$wnd.FB.init(...) and $wnd.FB.XFBML.parse(...)
Hope this helps someone.

Related

change facebook sdk lang code dynamically in vue (nuxt)

i am currently working on a simple like implementation in nuxt. when i change the language with 1i8n, i want to change the facebook sdk language accordingly, so the button renders in the given language code when i change the overall app language. my code looks like this:
import config from '#/config'
export default {
data() {
return {
FB_APP_ID: config.appname.FB_APP_ID
}
},
mounted() {
var langua;
if (this.$i18n.locale == 'en') {
langua = "en_US";
}
if (this.$i18n.locale == 'de') {
langua = "de_DE";
}
window.fbAsyncInit = () => {
FB.init({
appId: this.FB_APP_ID,
cookie: true,
xfbml: true,
version: 'v2.8'
})
}
(function(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/" + langua + "/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
}
}
it works but the dynamic change is not happening, do i miss something like async on the button sdk here ??? no idea, i am new to vue, help is appreciated thanks a lot.
That won’t work, the SDK can only be embedded and initialized once.
This is not entirely true: there is a workaround.
If you add a new script to the head, it will be executed once loaded. This is true for any script. If it doesn't, it means the script has a guard that prevents running the same code again most likely by checking if one of its variables is already defined.
In the case of Facebook SDK, it will check if FB is already defined globally so you simply need to delete it before adding your new sdk script with a different locale.
My code looks a bit different, but I'm also using Nuxt:
<template>
<div
:key="`fb-chat-${$i18n.locale}`"
class="fb-customerchat"
:page_id="pageId"
theme_color="#4586ff"
greeting_dialog_display="hide"
:logged_in_greeting="$t('greeting')"
:logged_out_greeting="$t('greeting')"
></div>
</template>
<script>
export default {
name: 'FacebookChat',
data() {
return {
pageId: process.env.FACEBOOK_PAGE_ID,
}
},
watch: {
'$i18n.locale': 'resetFacebookSdk',
},
mounted() {
this.initFacebookSdk()
},
methods: {
initFacebookSdk() {
if (!process.browser) return
const locale = this.$i18n.locale === 'de' ? 'de_DE' : 'en_US'
delete window.FB // needs to be undefined when inserting a second script with different locale
window.fbAsyncInit = function () {
window.FB.init({
appId: process.env.FACEBOOK_APP_ID,
autoLogAppEvents: true,
xfbml: true,
version: 'v10.0',
})
}
;(function (d, s, id) {
let js = d.getElementById(id),
fjs = d.getElementsByTagName(s)[0]
if (js) js.parentNode.removeChild(js) // remove script tag if exists
js = d.createElement(s)
js.id = id
js.src = `https://connect.facebook.net/${locale}/sdk/xfbml.customerchat.js`
fjs.parentNode.insertBefore(js, fjs)
})(document, 'script', `facebook-jssdk-${this.$i18n.locale}`)
},
resetFacebookSdk() {
const fbRoot = this.$el.closest('#fb-root')
if (!fbRoot) return
// Move fb-customerchat element outside of fb-root (created by Facebook SDK)
fbRoot.parentNode.insertBefore(this.$el, fbRoot)
// Delete fb-root to let Facebook SDK create it again
fbRoot.parentNode.removeChild(fbRoot)
this.initFacebookSdk()
},
},
}
</script>
What you should pay attention to:
The locale is part of the key attribute of my element to make it re-render on locale change in order to remove what the sdk has added (attributes, child elements)
There is a watcher to call resetFacebookSdk on locale change
I modified the sdk code snippet to remove the script tag if it was already present instead of doing nothing. This way, we can create it again.
The element .fb-customerchat is cleaned up with the key attribute, but the sdk has wrapped it with a new element #fb-root. The method resetFacebookSdk is taking care of moving .fb-customerchat outside of that wrapper and deleting it.
You can see it in action on our website (you can switch language in the footer).
Hope it helps. Let me know if something is not clear.
I solved it by using this.$router.go(0); on the button click of the language switch, i had hoped to use another way, but still could'nt find one, anyway, now the language changes when the page reloads and the sdk's lang code as well, if else uses the appropriate language. Maybe i ll find a more elegant solution someday 😊👍

FB app into Tab not getting more than 520px width

I'm testing an app and when not on a page's tab it's fine. I need it to be wider than 520px.
First of all, this is the html's code for setting the proper height.
window.fbAsyncInit = function () {
FB.init({
appId: '1428427990741852',
status: true,
cookie: true,
xfbml: true
});
FB.Canvas.setSize({ height: 1100 });
};
// Load the FB SDK Asynchronously
(function (d) {
var js, id = 'facebook-jssdk'; if (d.getElementById(id)) { return; }
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
d.getElementsByTagName('head')[0].appendChild(js);
} (document));
That's OK, the height is properly set as you can see is the app's iframe
<iframe class="smart_sizing_iframe noresize" frameborder="0" scrolling="yes" id="iframe_canvas" name="iframe_canvas_fb_https" src='javascript:""' height="1100" webkitallowfullscreen="" mozallowfullscreen="" oallowfullscreen="" msallowfullscreen="" allowfullscreen="" style="height: 1100px;"></iframe>
Now, if we check that same iframe after the app is loaded inside a page (as a tab), here's the result.
<iframe name="app_runner_fb_https53cc3ca1018792924747227" id="app_runner_fb_https53cc3ca1018792924747227" style="width: 520px; height: 1100px;" frameborder="0" src="https://s-static.ak.facebook.com/platform/page_proxy/hv09mZVdEP8.js#app_runner_fb_https53cc3ca1018792924747227" class="noresize"></iframe>
As you can see, there's the 520px width automatically set.
I have tried changing the Canvas Fixed Width property to YES so the app's width is set to 760px but I'm still getting a 520px width.
Also, I've tried forcing the width's px right in the code FB.Canvas.setSize({ width:760, height: 1100 }); but still, it's stucked in 520px.
Here you can see the app, alone by itself and as a tab.
Thanks.
TAB
Alone
PS. Not sure if this is of value but I'm using fbootstrap which has a 760/520px grid system but that I assume has nothing to do with fb's iframe itself.
Check the settings of the Page Tab in the App Settings, where you added it as "Platform" (https://developers.facebook.com/apps/[your-app-id]/settings/). There is a switch with the following text: "Wide Page Tab?" Switch that one to "YES" and your Tab should be 810px.

Facebook share with static og tags and no app

I'm trying to achieve a facebook share of a questionnaire results page.
I want the following items to be custom
1) The button, so I'm using an image
2) The Title, description and Image that appears in the Share box
3) The URL that is shared.
Here's the problem. The results are sent to a page called /results. This page changes depending on the visitors cookie (the results of their questionnaire is placed in this cookie so it displays the appropriate result).The OG tags for this page are also populated to get the right image, title and description to appear in the search box, but if Facebook were to scrape this page, it wouldn't be the same.
Here is the code I'm using
<script>
window.fbAsyncInit = function() {
FB.init({
appId : '<?=FB_APP_ID?>',
xfbml : true,
version : 'v2.0'
});
};
(function(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/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
<img src="images/icons/share-fb.png" alt="Share your Results on Facebook" class="share"/>
$('.share').click(function(){
FB.ui({
method: 'share',
href:'http://example.net/results',
}, function(response){});
});
Is it at all possible to
1) Do this without having a Facebook App? Under FBs new rules I'm unable to get an app approved without the need for Facebook login which I neither need nor have.
2) Set what is shared and not have it change in a user's feed whenever facebooks scrapes the result page and doesn't see the relevant OG tags?

How to get bigger images in News Feed when sharing a link

I have a page that uses the Facebook Feed and Share dialog. I read on this page of documentation that there is a way to get bigger images into the news feed, rather than the typical thumbnail. https://developers.facebook.com/docs/opengraph/howtos/maximizing-distribution-media-content/#images
I am not sure what I'm doing wrong but my image never appears to be in the larger format. Its always the tiny thumbnail. Here is the code I have. Not really sure what I'm doing wrong.
At first I thought my share.jpg image was too big (it was around 1900x1200) so I sized it down to the min specs that Facebook said to use (1200x630) and I still end up with the tiny thumbnail.
This is the FB.ui function that I have..
$(".facebook").bind("click", function(event){
event.preventDefault();
FB.ui({
method: 'feed',
//link: encodeURIComponent(shareURL),
link: shareURL,
caption: 'An example caption',
picture: 'http://www.example.com/beta/share.jpg'
}, function(response){});
});
Here's what I have on the page right after <body>
<script>
window.fbAsyncInit = function() {
// init the FB JS SDK
FB.init({
appId : 'XXXXXXXXXXXX', // App ID from the app dashboard
channelUrl : '//www.example.com/beta/channel.html', // Channel file for x-domain comms
status : true, // Check Facebook Login status
xfbml : true // Look for social plugins on the page
});
// Additional initialization code such as adding Event Listeners goes here
};
// Load the SDK asynchronously
(function(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";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
I think I may have figured it out. Looks like the bigger image only works on mobile and the new News Feed (which I still don't have.. WTF? LOL)

How to remove scrollbars from canvas on Firefox

Firefox is adding scrollbars to the canvas even with the body set to overflow:hidden and the execution of FB.Canvas.setAutoResize();. Every other browser hides the scrollbars. When I remove all content from the page the scrollbars persist.
Sample: https://apps.facebook.com/fbtestapppb/
With the introduction of Facebook Timeline the way to remove scroll bars and control page margins has changed. First (and most importantly) your body padding and margins MUST all be set to zero. This ensures all browsers process your canvas settings off absolute zero.
Depending on the 'Page Tab Width' (520px or 810px) option you set in your Apps/Page settings you will need to adjust the width in the following code. This block should be placed in the page Head:
<script type="text/javascript">
window.fbAsyncInit = function() {
FB.Canvas.setSize();
}
// Do things that will sometimes call sizeChangeCallback()
function sizeChangeCallback() {
FB.Canvas.setSize();
}
</script>
Just below the Body tag add the following code:
<div id="fb-root"></div>
<script src="http://connect.facebook.net/en_US/all.js"></script>
<script>
FB.init({appId: 'YOUR APP ID', status: true, cookie: true, xfbml: true});
window.fbAsyncInit = function() {
FB.Canvas.setSize({ width: 520, height: 1000 });
}
</script>
Remember to change 'YOUR APP ID'. Also width: should equal either 520 or 810. Set height: slightly larger than you require to allow overflow.
This solution has been tested in IE, FF, Safari and Chrome!
I added this to my css and it seemed to work:
body {
margin-top: -20px;
padding-top: 20px;
}
If you already have padding added to the top of your body, you will likely need to add 20px to it.
I assume it's because firefox measures the body height differently than other browsers.
Tested in ff8, chrome16 and ie9 with no negative repercussions.
I had solved this problem that way:
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
window.fbAsyncInit = function() {
FB.init({
appId : app_id, // App ID
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
var height_doc = $(document).height()+20;
FB.Canvas.setSize({height: height_doc});
};
It's works for me. I hope that help.
This is a known issue with canvas apps and page tabs, and has annoyingly been around for quite a while.
https://developers.facebook.com/bugs/309917422436936
Some people mention being able to use FB.Canvas.setSize({ width: 700, height: 800 }); or something like FB.Canvas.setAutoResize(500); and it gets around the issue.
Have you definitely set the iframe auto resize option in the apps control panel too?
Forget about body and html margins (I mean set them to zero).
Just place all your content (including header and footer) into a table with single cell.
At least all browsers will agree on how to calculate the height of the table...
like this:
<table id='m_table' width=100% align=left border=0 cellspacing=0 cellpadding=0>
<tr><td valign=top bgcolor=white align=center style='position:relative;'>
and do this :
setTimeout(function() {FB.Canvas.setSize({height:(document.getElementById('m_table').offsetHeight+40)})}, 1000);
works in IE,FireFox and Chrome/Safari...
Here is FB initialization code if you need it:
window.fbAsyncInit = function() {
FB.init({appId:'your_app_id',status:true,cookie:true,xfbml:true});fbApiInit = true;
}
function fbEnsureInit(callback)
{
if(!window.fbApiInit) setTimeout(function() {fbEnsureInit(callback);}, 50);
else if(callback) callback();
}
fbEnsureInit(function() {
FB.Canvas.scrollTo(0,0);
var h = document.getElementById('m_table').offsetHeight+40;
// console.log('setting size to '+h);
FB.Canvas.setSize({height:h});
setTimeout(function() {FB.Canvas.setSize({height:(document.getElementById('m_table').offsetHeight+40)})}, 1000);
});