After googling and analyzing DOM, i found out:
iframe dynamically replaces twitter's timeline a-link
jquery-ui effects force iframe to reload content
similar question
sample at jsfiddle
html
click here to start toggle
<div id="panel">
<a id="twitter-widget" class="twitter-timeline" href="https://twitter.com/search? q=%23Globallogic" data-widget-id="418408420543184896">#Globallogic</a>
</div>
css
#panel {
background:gray;
width:640px;
height:512px;
}
js
!function(d,s,id){var js,fjs=d.getElementsByTagName(s) [0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
$( window ).mousedown(function() {
$( "#panel" ).toggle( "slide", { direction: "left" }, 1000 );
});
Is it possible to configure jquery-ui to avoid iframe reload? and I'm appreciated for any other suggestions.
You can use the following code to reload the twitter widget's content:
twttr.widgets.load()
Be sure to run it after the widget has initially loaded as it will throw up an error otherwise.
I just encountered this issue and I resolved it by dynamically loading child elements to the panel
and ask twitter to load the widget. To do this , if below is you twitter div
then
<div id="panel">
<a id="twitter-widget" class="twitter-timeline" href="https://twitter.com/search?q=%23Globallogic"
data-widget-id="418408420543184896">#Globallogic</a>
</div>
Please place the below java script anywhere using the script tags.
window.twttr = (function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0],
t = window.twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s);
js.id = id;
js.src = "https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
t._e = [];
t.ready = function (f) {
t._e.push(f);
};return t;
}(document, "script", "twitter-wjs"));
Use setInterval() call the update function. In this function you can remove the existing twitter iframe ( created at the time of loading) , and replace it with your original link. after this is done simply call twttr.widgets.load() a standard event given by twitter
$(function(){
function updateStatus(){
var $twitter = $("#panel");
$twitter.append(" <a id='twitter-widget'
class='twitter-timeline' href='https://twitter.com/search?
q=%23Globallogic' data-widget- id='418408420543184896'>#Globallogic</a>");
twttr.widgets.load();
};
setInterval(function(){updateStatus()}, 1000);
});
Tweets that have images may take some time to load.
Related
Goal - Have share buttons for Facebook
I've had various problems, I've managed to solve most issues but never all at the same time.
ReferenceError: FB is not defined (error in the console)
"FB init function gives wrong version error" (error in the console)
My button does not render after transitioned to another route.
My button renders but there is no spacing around the button to adjacent stuff on the initial route
About that rendering issue (the - / hyphen is there to notice the spacing issue)
Rendering for the 1st time:
Rendering for the 2nd+ time:
What I've learned:
Facebook wants a <div id="fb-root"></div> as the first element inside your <body>
FB.XFBML.parse() can be called after didInsertElement to render a component after a transition
I made a JSBin boilerplate attempt, it's currently stuck at a undefined FB error.
http://emberjs.jsbin.com/fevoyuhiso/2/edit
Partial answer I'm also interested in:
Understanding how complex the solution at least must me to achieve a good result ("it must include an initializer, and a view/component!" or "you can solve this by just having ...")
Parts that may be of use
A post about "after FB.init()"
How to detect when facebook's FB.init is complete
An initializer
/* global FB */
export default {
name: 'facebook',
initialize: function() {
var fbAsyncInit = function() {
FB.init({
appId : 123,
xfbml : true,
version : 'v2.2'
});
};
(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'));
window.fbAsyncInit = fbAsyncInit;
}
};
A component
/* global FB */
import Ember from 'ember';
export default Ember.Component.extend({
tagName: 'div',
classNames: 'fb-like',
attributeBindings: [
'data-href',
'data-layout',
'data-action',
'data-show-faces',
'data-share'
],
onDidInsertElement: function() {
Ember.run.schedule('afterRender', FB.XFBML.parse);
}.on('didInsertElement'),
init: function() {
Ember.run.schedule('afterRender', FB.XFBML.parse);
}
});
A script tag
<script type="text/javascript" src="//connect.facebook.net/en_US/sdk.js#xfbml=1&appId=123&version=v2.2"></script>
The root div facebook asks for
<div id="fb-root"></div>
Loading Facebook SDK
import ENV from "my-app/config/environment";
import setupOfflineMode from "my-app/utils/offline-mode";
export function initialize(container, application) {
// offline mode stubs `FB`
if (ENV.offlineMode) { return setupOfflineMode(); }
// Wait for Facebook to load before allowing the application
// to fully boot. This prevents `ReferenceError: FB is not defined`
application.deferReadiness();
var fbAsyncInit = function() {
initFacebook(window.FB);
application.advanceReadiness();
};
loadFacebookSDK();
window.fbAsyncInit = fbAsyncInit;
}
function loadFacebookSDK() {
(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'));
}
function initFacebook(FB) {
FB.init({
appId: ENV.FB_APP_ID,
status: true,
cookie: true,
xfbml: true,
version: ENV.GRAPH_API_VERSION
});
}
export default {
name: 'facebook',
initialize: initialize
};
Share Links
I think this is all I needed to do; I hope I'm not forgetting something...
I didn't set up a component, so this is just a regular view, but it should work about the same.
<div class="fb-share-button" {{bind-attr data-href=link}} data-type="button"></div>
export default Ember.View.extend({
setupSocialNetworks: function() {
Ember.run.scheduleOnce('afterRender', this, function() {
FB.XFBML.parse();
});
}.on('didInsertElement')
});
UPDATE: Alternate solutions
I think which solution you use really depends on your needs. I'm focusing on a faster time-to-first-render, so I've changed my project to not deferReadiness for the Facebook SDK.
I've been playing with two solutions, again I think it totally depends on your needs.
Load the Facebook SDK in an initializer, but set a global promise for access.
This starts the loading on boot, but allows your application to continue booting without having to wait for Facebook. All calls to the Facebook API need to be accessed through the promise.
I'll share the details of this one if requested, but for now I'll just focus on the next solution:
Load the Facebook SDK only on demand in a service.
As before, all access to the Facebook API will need to go through a promise, but this time it is nicely encapsulated in a service and is only loaded on demand:
// app/services/facebook.js
import Ember from 'ember';
import ENV from "juniper/config/environment";
var computed = Ember.computed;
var RSVP = Ember.RSVP;
var _facebookSDKDeferrable = Ember.RSVP.defer();
var fbAsyncInit = function() {
_initFacebook(window.FB);
_facebookSDKDeferrable.resolve(window.FB);
};
window.fbAsyncInit = fbAsyncInit;
export default Ember.Service.extend({
// Resolves when the Facebook SDK is ready.
//
// Usage:
//
// facebook: Ember.inject.service(),
// foo: function() {
// this.get('facebook.SDK').then(function(FB) {
// // Facebook SDK is ready and FB is a reference to the SDK
// });
// }
SDK: computed.alias('FB'),
FB: computed(function() {
_loadFacebookSDK();
return _facebookSDKDeferrable.promise;
})
// I've also put promisified helpers for Facebook SDK
// methods here.
});
function _loadFacebookSDK() {
(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'));
}
function _initFacebook(FB) {
FB.init({
appId: ENV.FB_APP_ID,
status: true,
cookie: true,
xfbml: false,
version: ENV.GRAPH_API_VERSION
});
}
Note also that I've set xfbml to false in FB.init. If your share links have been rendered before the SDK gets loaded, FB.init({ xfbml: true }) will "parse" them, and your FB.XFBML.parse() call will do it again. By setting xfbml to false, you ensure that FB.XFBML.parse() will only get called once.
I want to add the Twitter widget into React, but I don't know where to start or how to do it. I am very new to React JS.
Here is the HTML version of the code:
<div class="Twitter">
<a class="twitter-timeline" href="https://twitter.com/<%= #artist.twitter %>" data-widget-id="424584924285239296" data-screen-name='<%= #artist.twitter %>'>Tweets by #<%= #artist.twitter %></a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
</div>
And here is what I have so far:
React.DOM.div
className: 'Twitter'
children: [
React.DOM.a
className: 'twitter-timeline'
href: "https://twitter.com/" + artist.twitter
'data-widget-id': "424584924285239296"
'data-screen-name': artist.twitter
children: 'Tweets by ' + artist.twitter
React.DOM.script
children: ...
]
I was planning to add the script where the dots (...) are, but that doesn't work. Thank you for your help.
First load Widget JS in your index.html(before your React scripts). Then in your component, simply do the following. The widget JS will rescan the DOM.
componentDidMount: function() {
twttr.widgets.load()
}
See: https://dev.twitter.com/web/javascript/initialization
This works for me!
Please note that I use React v0.14 and ECMAScript 2015 (aka ES6) with Babel.
index.html (after body tag):
<script>window.twttr = (function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0], t = window.twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s); js.id = id;
js.src = "https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
t._e = []; t.ready = function(f) {
t._e.push(f);
};
return t;
}(document, "script", "twitter-wjs"));
</script>
Twitter component:
const Twitter = () => (
<a href="https://twitter.com/your-twitter-page"
className="twitter-follow-button"
data-show-count="false"
data-show-screen-name="false"
>
</a>
);
Some React Component (that uses Twitter button):
class SomeReactComponent extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Twitter />
</div>
);
}
}
Or if you want to have a customized button, you can simply do this:
const Twitter = () => (
<a href="https://twitter.com/intent/tweet?via=twitterdev">
<i className="zmdi zmdi-twitter zmdi-hc-2x"></i>
</a>
);
It seems to be much easier to just use Twitter's widgets.js, more specifically createTimeline.
class TwitterTimeline extends Component {
componentDidMount() {
twttr.ready(() => {
twttr.widgets.createTimeline(widgetId, this.refs.container)
})
}
render() {
return <div ref="container" />
}
}
You can load the library directly from https://platform.twitter.com/widgets.js, but they recommend the following snippet:
<script>window.twttr = (function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0],
t = window.twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s);
js.id = id;
js.src = "https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
t._e = [];
t.ready = function(f) {
t._e.push(f);
};
return t;
}(document, "script", "twitter-wjs"));</script>
More information on setting up the library is here.
It's easy, all you need just use React's componentDidMount hook
{createClass, DOM:{a}} = require "react"
#TwitterWidget = createClass
componentDidMount: ->
link = do #refs.link.getDOMNode
unless #initialized
#initialized = yes
js = document.createElement "script"
js.id = "twitter-wjs"
js.src = "//platform.twitter.com/widgets.js"
link.parentNode.appendChild js
render: ->
{title, content, widget} = #props
a
ref: "link"
className: "twitter-timeline"
href: "https://twitter.com/#{widget.path}"
"data-widget-id": widget.id,
widget.title
TwitterWidget
widget:
id: "your-widget-id"
title: "Your Twitts"
path: "widget/path"
Try to install the react-twitter-embed by doing npm install react-twitter-embed. Once installed, the usage is pretty simple. Take a look at the screenshot below.
Code Sample:
import React from 'react';
import { TwitterTimelineEmbed } from 'react-twitter-embed';
const TwitterTimeLine = () => {
return (
<TwitterTimelineEmbed
sourceType="profile"
screenName="accimeesterlin" // change to your username
options={{height: 1200}}
/>
);
}
export default TwitterTimeLine;
They also have a list of other components that you can use as well.
List of available components
TwitterShareButton
TwitterFollowButton
TwitterHashtagButton
TwitterMentionButton
TwitterTweetEmbed
TwitterMomentShare
TwitterDMButton
TwitterVideoEmbed
TwitterOnAirButton
Here is a link to the npm package https://www.npmjs.com/package/react-twitter-embed
IMHO you should split it down in two.
A part of your code could be somehow rendered in a React component
/**
* #jsx React.DOM
*/
var React = require('react');
var twitterWidget = React.createClass({
render: function () {
return (
<div class="Twitter">
<a class="twitter-timeline"
href={this.props.link}
data-widget-id={this.props.widgetId}
data-screen-name={this.props.screenName} >
Tweets by {this.props.screenName}
</a>
</div>
);
}
});
React.renderComponent(<twitterWidget link="..." widgetId="..." />, document.getElementById('containerId');
Your script tag could be placed, as a separate React component or as normal HTML just above the closing body tag.
class TwitterShareButton extends React.Component {
render() {
return Tweet
}
componentDidMount() {
// scriptタグが埋め込まれた後にTwitterのaタグが置かれても機能が有効にならないので、すでにscriptタグが存在する場合は消す。
var scriptNode = document.getElementById('twitter-wjs')
if (scriptNode) {
scriptNode.parentNode.removeChild(scriptNode)
}
// ボタン機能の初期化(オフィシャルのボタン生成ページで生成されるものと同じもの)
!function(d,s,id){
var js,
fjs=d.getElementsByTagName(s)[0],
p=/^http:/.test(d.location)?'http':'https';
if(!d.getElementById(id)){
js=d.createElement(s);
js.id=id;
js.src=p+'://platform.twitter.com/widgets.js';
fjs.parentNode.insertBefore(js,fjs);
}
}(document, 'script', 'twitter-wjs');
}
http://qiita.com/h_demon/items/95e638666f6bd479b47b
You can use this React Social Embed Component.
Disclaimer: It is a component created by me.
Install by: npm i react-social-embed.
Usage:
import TweetEmbed from 'react-social-embed'
<TweetEmbed id='789107094247051264' />
/>
There are few interesting solutions out there, but all of those are injecting twitters code to website.
What would I suggest is to create another empty html file just for this widget. Eg. /twitter.html, where you can place all dirty JavaScripts and render widget.
Then when you include:
<iframe src="/twitter.html" />
It will work without any issues. Plus, you have separated external scripts - so it's good for security.
Just add some styling to make it look fine:
twitter.html
html,
body {
margin: 0;
padding: 0;
}
React's iframe
iframe {
border: none;
height: ???px;
}
I knows exactly where is the problem, first you need to understand how does react works.
React is frontend framework, works like all DOM is handled by react, if we directly integrate with DOM then sometimes it very difficult to code, cos React is also Updating that DOM.
As per the Twitter documentation, we cannot add twitter.js after init of web page.
https://dev.twitter.com/web/javascript/initialization
so it better to use some package, react-twitter-embed
Simple step
npm install --save react-twitter-embed
import { TwitterTimelineEmbed } from 'react-twitter-embed';
<TwitterTimelineEmbed
sourceType="profile"
userId={"1029587508445630465"}
options={{height: 400}}
/>
You can check other than timeline integration also using package.
https://romik-mk.medium.com/embed-twitter-timeline-widgets-reactjs-a27cafd7cfb6
I'm having a hard time trying to load fast the javascript Facebook SDK into my rails 4 application. Is there a good way to make it work correctly with turbolinks?
if i add this code on my JS application assets.
It's not working properly due to turbolinks:
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
// init the FB JS SDK
FB.init({
appId : 'YOUR_APP_ID', // App ID from the app dashboard
channelUrl : '//WWW.YOUR_DOMAIN.COM/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>
thanks
You will find the proper solution for integrating the Facebook SDK with Turbolinks here :
http://reed.github.io/turbolinks-compatibility/facebook.html
I was having a problem with the Like Box not loading when I navigate between pages using turbo links. My solution was to create a social.js.coffee in my assets/javascripts folder. In this file it simply has
$(document).on 'page:change', ->
FB.init({ status: true, cookie: true, xfbml: true });
I know its a lot to put in it's own file ;-), but the idea was that I know google analytics, twitter, and others will have the same conflicts and this will be a nice place to house those solutions as well.
Quoting this answer
If you prefer to use native Turbolinks 5 events, you can add this script to your Rails assets:
// FacebookSDK
// https://developers.facebook.com/docs/plugins/page-plugin/
(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/ja_JP/sdk.js#xfbml=1&version=v2.8";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk')); // Replace 'facebook-jssdk' with your page id.
// Compatibility with Turbolinks 5
(function($) {
var fbRoot;
function saveFacebookRoot() {
if ($('#fb-root').length) {
fbRoot = $('#fb-root').detach();
}
};
function restoreFacebookRoot() {
if (fbRoot != null) {
if ($('#fb-root').length) {
$('#fb-root').replaceWith(fbRoot);
} else {
$('body').append(fbRoot);
}
}
if (typeof FB !== "undefined" && FB !== null) { // Instance of FacebookSDK
FB.XFBML.parse();
}
};
document.addEventListener('turbolinks:request-start', saveFacebookRoot)
document.addEventListener('turbolinks:load', restoreFacebookRoot)
}(jQuery));
From: https://gist.github.com/6temes/52648dc6b3adbbf05da3942794b97a00
If you're putting your Facebook JS code at the end of your view, use flush in your controller action to ensure it's fully reloaded properly with Turbolinks:
def show
# ...
render :show, flush: true
end
Worked like a charm.
I followed the solution suggested by #gallonallen with some small modification. just created a file called turbo.js with following content:
$(document).on('turbolinks:load', function() {
FB.init({ status: true, cookie: true, xfbml: true });
});
And added //= require turbo in application.js before //= require query and it started working for me. I am using rails 4.2.6 and ruby 2.3.1 with turbo links 5. For me, prior to fix, turbo links was working on my local but not when deployed to staging or prod.
Im trying to load the twitter widget api in my ajax loaded page.
I have tryed to load the script in a couple of different ways and Im getting the alert to run each time but not the script itself.
So the first time I load the page, then the script is working, but if I go back to the menu and back to this page, then it doesnt load it?
This is the ajax loaded page.
<div id="twitterwid">
<a class="twitter-timeline" width="320" height="500" href="https://twitter.com/my account" data-widget-id="my widget id number">Loading tweets by #me</a>
<script>
alert("alert is working");
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
</script>
<div>
Any input appreciated, thanks.
All you have to do is: invoke a re-render of the widget tags on the page by calling:
twttr.widgets.load()
Similar question on Twitter Dev Channel
Note: inline script is not executed upon AJAX Load.
See: this SO Q&A for the solution to that.
Add first :
<script>window.twttr = (function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0],
t = window.twttr || {};
if (d.getElementById(id)) return t;
js = d.createElement(s);
js.id = id;
js.src = "https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
t._e = [];
t.ready = function(f) {
t._e.push(f);
};
return t;
}(document, "script", "twitter-wjs"));</script>
So you can use :
twttr.widgets.load()
I wrote like there: http://jqueryui.com/demos/tabs/#...follow_a_tab.27s_URL_instead_of_loading_its_content_via_ajax
<script type="text/javascript">
$(function(){
$("#tabs").tabs({
select: function(event, ui) {
var url = $.data(ui.tab, 'load.tabs');
if( url ) {
location.href = url;
return false;
}
return true;
}
});
});
</script>
<div id="tabs">
<ul>
<li>
Home
</li>
<li>
About
</li>
</ul>
</div>
Tabs are created, but initial list (div, ul, li) is visible as well. Another problem: when I hover over tab, I see URL kind of /default.htm#ui-tabs-1, /default.htm#ui-tabs-2 etc. But I want to see URL "/default.htm" over the 1st tab and URL "/about.htm" over the 2nd tab.
What could I do to solve my problem?
UPDATE
In version 1.9 there is powerful widget "menu".
You are miss interpreting the jQuery UI Tabs.
This Tabs are for having content hide/show and if using ajax pull the page info and show it on demand.
if you want those tabs to act as a menu ... then you need a menu, not the jQuery UI Tabs.
If your idea if to use this tabs but to fetch the /about.htm as a new content, then you can use the ajax example
http://jqueryui.com/demos/tabs/#ajax
keep in mind that it will fetch the entire content, so the /about.htm page should not have <html> neither <body> tags
I don't want to encourage you to do this, but the solution is currently available on jQuery UI's website: http://jqueryui.com/demos/tabs/#...follow_a_tab.27s_URL_instead_of_loading_its_content_via_ajax
You may extend it a bit to follow only certain URLs:
select: function(e, ui)
{
var tab = $(ui.tab);
var url = $.data(ui.tab, 'load.tabs');
if(url && tab.attr('data-ajax') == 'false')
{
location.href = url;
return false;
}
return true;
}
Then, when defining tabs:
<li>...</li>