Facebook FB sharer with jQuery- "FB is not defined" error - facebook-javascript-sdk

I am implementing facebook share. However I get error Uncaught ReferenceError: FB is not defined. However, if I put code inside getScript function (in code below) then it works, but only at page load.
Viewed lots of answers like this, but was not able to get the solution.
<div id="fb-root"></div>
<script>
jQuery(document).ready(function() {
jQuery.ajaxSetup({ cache: true });
jQuery.getScript('//connect.facebook.net/en_UK/all.js', function(){
window.FB.init({
appId: 'XXX',
});
jQuery('#loginbutton,#feedbutton').removeAttr('disabled');
});
FB.ui(
{
method: 'feed',
name: 'Facebook Dialogs',
link: 'http://XXX.website',
picture: 'http://XXX.website/logoroundTR.gif',
caption: 'MyCaption',
description: 'MyDescription'
},
function(response) {
if (response) {
alert('Post was published.');
} else {
alert('Post was not published.');
}
}
);
});
</script>
<button><fb:like href="http://XXX.website/" layout="button_count" action="like" show_faces="true" share="true"></fb:like></button>
p.s.: Second question: How do I link the button to FB.ui function. Any easy way?

Ok found a workable solution. Slight Hack.
Removed FB.ui and put it in the button onclick and it works great.
So for custom title, caption, image and description for facebook javascript sdk, one can do following:
<div id="fb-root"></div>
<script>
jQuery(document).ready(function() {
jQuery.ajaxSetup({ cache: true });
jQuery.getScript('//connect.facebook.net/en_UK/all.js', function(){
window.FB.init({
appId: 'appID',
});
jQuery('#loginbutton,#feedbutton').removeAttr('disabled');
});
});
</script>
<button onclick="javascript:FB.ui({method: 'feed',name: 'Facebook Dialogs',link: 'http://xxxY.com',picture: 'http://xxxy.com/wp-content/img/logoroundTR.gif',caption: 'SandeepCaption',description: 'SandeepDescription'});"> Click Here </button>

Related

How can I add a click event to a class in Vue **without** changing the html? [duplicate]

Is there a way to add a click handler inside a Vue instance without writing on the markup? I'm loading an SVG via ajax, and I'd like to use Vue click events on it.
My Vue file looks like this:
<template>
<div>
<div class="map" v-html="map"></div>
</div>
</template>
<script>
export default{
data : function(){
return {
map : 'Loading'
};
},
methods : {
getMap : function(){
var thisMap = this;
axios.get('/img/world-map.svg').then(function (response) {
thisMap.map = response.data;
thisMap.loading = false;
}).catch(function (error) {
thisMap.loading = false;
console.log(error);
});
},
},
mounted : function(){
console.log('WorldMap mounted');
this.getMap();
}
}
</script>
The issue is that I'm loading a rather large SVG straight into the page. In a perfect world I would just do something like this:
<template>
<div>
<div class="map" >
<svg>
<g #click="groupClicked" class="asia" id="asia" xmlns:svg="http://www.w3.org/2000/svg">
<path stroke="#FFFFFF" d="M715.817,47.266c-4.45,1.25-8.903,2.497-13.357,3.739c-1.074,0.327-8.403,1.757-5.678,3.204
c-1.922,2.104-2.993,1.568-5.547,1.536c-1.547,1.333,0.981,1.22-0.558,2.421c-0.976,0.761-0.946,1.257-2.106,0.827
c-0.368-0.136-2.223-0.261-1.543,0.759c2.082,1.3,0.231,3.046-1.466,4.011c-1.831-0.38-3.271-1.611-5.245-1.293
c-1.229,0.196-2.104,0.763-3.176-0.205c-1.265-1.143,0.371-1.409,1.378-2.177c1.529-1.168,5.473-0.2,2.834-2.668
c1.061-0.979,2.07-0.946,3.206-1.736c-0.297-0.416-0.649-0.773-1.067-1.068c1.047-1.075,1.679-3.036,3.497-2.725
c1.441,0.249,2.046-1.318,3.182-2.137c1.121-0.811,2.4-1.266,3.771-1.402c1.656-0.165,3.271,0.134,4.347-1.427
c0.921-1.334,1.921-1.218,3.468-0.757c1.687,0.504,2.808-0.159,4.442-0.698c2.313-0.118,4.489-0.946,6.812-1.068
c1.043-1.941,2.354-2.07,4.375-2.331c0.653-0.085,6.433-0.678,4.774,1.792C721.041,46.198,718.024,46.605,715.817,47.266
C711.364,48.516,718.356,46.505,715.817,47.266z"/>
</g>
</svg>
</div>
</div>
</template>
However the SVG I'm loading is about 300kb big and I don't want to be carrying that around with all my JavaScript on every page load.
Any comments or solutions welcome.
Edit
Since asking I've actually got quite far with this approach, which isn't perfect but at the moment it seems pretty good.
var vueBus = new Vue({});
$('body').on('click', 'svg g', function(){
var name = $(this).attr('data-name');
vueBus.$emit('svgGroupClicked', name);
});
and then adding a listener in my .vue file
mounted() : function(){
vueBus.$on('svgGroupClicked', function(){ ... });
}
You can just add a click event via plain javascript after the GET request succeeds:
axios.get('/img/world-map.svg').then(function (response) {
thisMap.map = response.data;
thisMap.addClickHandler();
thisMap.loading = false;
})
Your addClickHandler method would look something like this:
methods: {
addClickHandler: function() {
var gEl = this.$el.getElementsByTagName('g')[0];
gEl.addEventListener('click', function() {
alert('I got clicked');
});
},
}
Or, if you're using jQuery:
methods: {
addClickHandler: function() {
$(this.$el).find('g')[0].click(function() {
alert('I got clicked');
});
},
}

Nuxt: Page crashing on page reload

Anyone know why a sub page crashes when user reloads the page? It is fine when you navigate to the page using nuxt-link from another page (using route params), but when the user reloads/refreshes the page, it will crash.
Here is my sandbox where you can test it out: Codesandbox
Code from nuxt link:
<nuxt-link :to="{name: 'photos-id-title', params: { id: photo.id, title: photo.title }}">
Code from photo details page:
<template>
<section>
<!-- <template v-if="photo"> -->
<img
:id="photo.filename"
:src="photo.url"
class="img-fluid thumbnail rounded"
:alt="photo.title"
/>
<h1 class="h3">{{ photo.title }}</h1>
</section>
</template>
<script>
import { Annotorious } from '#recogito/annotorious'
export default {
data() {
return {
photo: {},
anno: {},
title: this.$route.params.title
}
},
async mounted() {
await this.getPhotoDoc()
this.anno = await new Annotorious({ image: this.photo.filename })
},
methods: {
async getPhotoDoc() {
const docRef = await this.$fireStore
.collection('photos')
.doc(this.$route.params.id)
.get()
try {
if (docRef.exists) {
// data() returns all data about the doc
console.log('got the doc: ', docRef.data())
this.photo = docRef.data()
} else {
console.log('no docs exist')
}
} catch (error) {
console.log('Error getting document:', error)
}
}
},
head() {
return {
title: this.photo.title,
meta: [
{
hid: 'description',
name: 'description',
content: this.photo.description
}
]
}
}
}
</script>
User journey: Click PHOTOS from navbar, select any photo on the page. You shall see a "photo detail" page. Loads fine. Try to refresh the page -- it will crash.
Note: I also have this scaffolded in a regular/plain vue app using Vue-cli and have NO issues. Only seems to be a problem with Nuxt. Must be SSR related?
Thanks for any help...
If you think this is SSR related and the Annotorious plugin might cause the problem try this:
nuxt.config.js add the plugin with mode client
plugins: [
{ src: '~/plugins/client-only.js', mode: 'client' }, // only on client side
]
You can find more information in the nuxtjs docs here

Stripe is not defined in Nuxt

I want to add stripe elements to my nuxt js page However, I got an error
Stripe is not defined
I have inserted the <script src="https://js.stripe.com/v3/"></script> on my nuxt.config.js
Here's the code
head: {
title: process.env.npm_package_name || "",
script: [{ src: "https://js.stripe.com/v3/" }],
link: [
{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" },
]
},
My payment page
<template>
<div>
<div ref="card"></div>
<button v-on:click="purchase">Purchase</button>
</div>
</template>
<script>
let stripe = Stripe("Key"),
elements = stripe.elements(),
card = undefined;
export default {
mounted: function() {
card = elements.create("card");
card.mount(this.$refs.card);
},
methods: {
async purchase() {
let result = await stripe.createToken(card);
}
}
};
</script>
I followed this tutorial and still can't fix it
https://alligator.io/vuejs/stripe-elements-vue-integration/
You are including stripe for into scripts, so it will be loaded in browser. But nuxt is SSR. And the code in your script section will be also executed on server. And on server there no stripe, so it wont work. You need to execute all your code that create Stripe in mounted hook, which is only executed on client

VueJS - trigger Modal from materializecss

I am trying to trigger a modal from the materializecss framework within a VueJS-instance.
Both, VueJS and Materializecss, are implemented correct. On their own both frameworks work fine.
Clicking the open-button results in an error:
Uncaught TypeError: data[option] is not a function
at HTMLDivElement. (adminarea.js:24562)
at Function.each (adminarea.js:10567)
at jQuery.fn.init.each (adminarea.js:10356)
at jQuery.fn.init.Plugin [as modal] (adminarea.js:24556)
at Vue$3.showLoader (adminarea.js:21396)
at boundFn (adminarea.js:54956)
at HTMLButtonElement.invoker (adminarea.js:56467)
This is my Vue-Instance:
const app = new Vue({
el: '#app',
data: {
activeUser: {
username: '',
email: ''
},
},
methods: {
showLoader(){
$('#loaderModal').modal('open');
},
closeLoader(){
$('#loaderModal').modal('close');
}
},
mounted() {
// Get current User
axios.get('/api/currentUser')
.then(response => {
this.activeUser.username = response.data.username;
this.activeUser.email = response.data.email;
});
},
components: {
Admindashboard
}
});
And here is the part of my html-file with the modal structure:
<!-- Modal Structure -->
<div id="loaderModal" class="modal">
<div class="modal-content">
<h4>Fetching data..</h4>
<div class="progress">
<div class="indeterminate"></div>
</div>
</div>
</div>
<button class="btn cyan waves-effect waves-cyan" v-on:click="showLoader">Open</button>
Any ideas? Thanks!
It seems I found an solution:
Nice to know for Laravel-users: for my current project I use Laravel 5.5 with Materializecss, VueJS and VueRouter but I think the solution is universal. Materializecss was installed via npm and has to be included into your application. I've required the css-framework within my ressources/assets/js/bootstrap.js:
...// more code
try {
window.$ = window.jQuery = require('jquery');
window.materialize = require('materialize-css');
} catch (e) {
console.log(e);
}
...// more code
Now you have to initialize the Modal-function on the mounted-event of your wrapping Vue-instance:
const app = new Vue({
router,
data: {
...
},
methods: {
testClick: function(){
console.log('Testklick-Call');
$('#modal1').modal('open');
}
},
mounted: function(){
console.log('Instance mounted');
$('.modal').modal();
}
}).$mount('#app');
The code above is placed within my ressources/assets/js/app.js and is packed by default by Laravel Mix but I think this is universal and also usable without Laravel Mix/Webpack etc.
Now you can call every modal programmatically from where ever you want. I've tested it in my main instance on a click-event. Function is placed in my Vue-instance (see above). HTML-Code see below:
<button v-on:click="testClick">Open Modal</button>
But you can also make use of the modal within a mounted-function or any other function of any component:
<template>
<div>
<p>I am an component!</p>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted!');
$('#modal1').modal('open');
}
}
</script>
This also works, if the component becomes only visible after clicked on a link (using VueRouter).
Hopefully this helps someone except me :)
As suggested here, you need to add following code in the mounted block:
mounted() {
$('#loaderModal').modal(); //New line to be added
// Get current User
axios.get('/api/currentUser')
.then(response => {
this.activeUser.username = response.data.username;
this.activeUser.email = response.data.email;
});
},

Magnific-popup: how to get image url from <img src="...">?

Is it possible to force magnific-popup to get image url from 'src' attribute of img tag? This way there would be no need to wrap img with a tags.
I tried the code below, but it doesn't work. Returned error is 'undefined' url.
<script type="text/javascript">
$(document).ready(function(){
$('div.gallery').magnificPopup({delegate: 'img'.attr('src') , type: 'image', gallery:{enabled:true}
});
});
</script>
Anyways, is there any option to do with 'img' only, without 'a' tags?
Thanks!
<script type="text/javascript">
$(document).ready(function(){
$('div.gallery').magnificPopup({delegate: 'img' , type: 'image', gallery:{enabled:true},
callbacks: {
elementParse: function() { this.item.src = this.item.el.attr('src'); }
}
});
});
</script>
elementParse http://dimsemenov.com/plugins/magnific-popup/documentation.html#api
I actually have not worked, and I found how to do .
Now the script when clicking pictures increases and creates a gallery of them .
<script type="text/javascript">
$(document).ready(function() {
$('#text').magnificPopup({
delegate: 'img',
type: 'image',
gallery: {
enabled: true
},
callbacks: {
elementParse: function(qw) {
qw.src = qw.el.attr('src');
}
}
});
});
</script>
With magnificPopup 1.1.0
now you have to do like this if you want it to work.
$(document).ready(function() {
$('.myClass').magnificPopup({
type: 'image',
callbacks: {
elementParse: function(item) {
item.src = item.el.attr('src');
}
}
});
});
The accepted answer didn't work for me, either. I ended up using the data-mfp-src attribute, which overrides the value in the href one (as mentioned here: http://dimsemenov.com/plugins/magnific-popup/documentation.html#content-types).
Instead of adding the attribute manually (duplicating the src of the image), I just copied the src value in data-mfp-src attributes for all images before the magnificPopup call. Something like this:
var popupImages = $('div.withPopups img');
popupImages.each(function(){
$(this).attr('data-mfp-src', $(this).attr('src'));
});
popupImages.magnificPopup({type: 'image'});