I want to provide users a facility to sign in with google. However, I want to use my image(only image, no css) as "sign in with google" button. I am using the following code:
<div id="mySignin"><img src="images/google.png" alt="google"/></div>
I am also using gapi.signin.render function as mentioned on google developer console. The code is:
<script src="https://apis.google.com/js/client:platform.js" type="text/javascript"></script>
<script>
function render(){
gapi.signin.render("mySignIn", {
// 'callback': 'signinCallback',
'clientid': 'xxxx.apps.googleusercontent.com',
'cookiepolicy': 'single_host_origin',
'requestvisibleactions': 'http://schema.org/AddAction',
'scope': 'profile'
});
}
The problem is that google signin popup is not opening and I cannot figure out how to solve it. Please suggest. Thanks in advance.
<script type="text/JavaScript">
/**
* Handler for the signin callback triggered after the user selects an account.
*/
function onSignInCallback(resp) {
gapi.client.load('plus', 'v1', apiClientLoaded);
}
/**
* Sets up an API call after the Google API client loads.
*/
function apiClientLoaded() {
gapi.client.plus.people.get({userId: 'me'}).execute(handleEmailResponse);
}
/**
* Response callback for when the API client receives a response.
*
* #param resp The API response object with the user email and profile information.
*/
function handleEmailResponse(resp) {
var primaryEmail;
var jsonobj=JSON.stringify(resp);alert(jsonobj);
var uid= jsonobj.id;
var user_name1= jsonobj.name;
for (var i=0; i < resp.emails.length; i++) {
if (resp.emails[i].type === 'account') primaryEmail = resp.emails[i].value;
}
/* document.getElementById('response').innerHTML = 'Primary email: ' +
primaryEmail + '<br/>id is: ' + uid; */
}
To use an image as your "Google Sign-in" button, you can use the GoogleAuth.attachClickHandler() function from the Google javascript SDK to attach a click handler to your image. Replace <YOUR-CLIENT-ID> with your app client id from your Google Developers Console.
HTML example:
<html>
<head>
<meta name="google-signin-client_id" content="<YOUR-CLIENT-ID>.apps.googleusercontent.com.apps.googleusercontent.com">
</head>
<body>
<image id="googleSignIn" src="img/your-icon.png"></image>
<script src="https://apis.google.com/js/platform.js?onload=onLoadGoogleCallback" async defer></script>
</body>
</html>
Javascript example:
function onLoadGoogleCallback(){
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: '<YOUR-CLIENT-ID>.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
scope: 'profile'
});
auth2.attachClickHandler(element, {},
function(googleUser) {
console.log('Signed in: ' + googleUser.getBasicProfile().getName());
}, function(error) {
console.log('Sign-in error', error);
}
);
});
element = document.getElementById('googleSignIn');
}
For those who come to here trying to get the button work out: The code below should do the trick.
It looks like the 'callback' method doesn't seem to work not sure if this is something to do with Vue as I am building it on Vue, or Google changed it as this was posted 5 years ago. Anyways, use the example below.
window.onload =() =>{
var GoogleUser = {}
gapi.load('auth2',() =>{
var auth2 = gapi.auth2.init({
client_id: '<client-unique>.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
scope: 'profile'
});
auth2.attachClickHandler(document.getElementById('googleSignup'), {},
(googleUser) =>{
console.log('Signed in: ' + googleUser.getBasicProfile().getName());
},(error) =>{
console.log('Sign-in error', error);
}
);
});
}
Change 'client_id' to your client id, and element id to your customized button id.
I hope this saves time for anyone!
Plus: I ended up using the code below, which is clearer:
window.onload = () => {
gapi.load('auth2', () => {
let auth2 = gapi.auth2.init({
client_id: '<client_id>.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
scope: 'profile email'
});
document.getElementById('googleSignup').addEventListener('click',() => {
auth2.signIn().then(() => {
let profile = auth2.currentUser.get().getBasicProfile();
... profile functions ...
}).catch((error) => {
console.error('Google Sign Up or Login Error: ', error)
});
});;
});
}
Related
Here's how I do it, after getting the signin's client file :
// HTML
<script type='text/javascript' src="https://apis.google.com/js/api:client.js" async defer></script>
I called gapi.load() function into a HTML button
// load the startApp function after the page loads
jQuery(function () {
$(window).load(function () {
startApp()
})
})
var startApp = function () {
gapi.load('auth2', function () {
// Retrieve the singleton for the GoogleAuth library and set up the client.
auth2 = gapi.auth2.init({
client_id: 'xxxxxxxx-xxxxxxxxxx.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
ux_mode: 'redirect', // I don't want it to display a pop-up
scope: 'profile email' // I just need to get user's name, profile picture and email address
});
// attach this function into a button element with id = "customBtn"
attachSignin(document.getElementById('customBtn'));
});
};
function attachSignin(element) {
auth2.attachClickHandler(element, {},
function (googleUser) {
// it never calls this block of code.
// this never runs
console.log(googleUser.getBasicProfile().getName())
var gProfile = googleUser.getBasicProfile();
var name = gProfile.getName();
var email = gProfile.getEmail();
var imgUrl = gProfile.getImageUrl();
}, function (error) {
return alert("Google Sign in error!")
});
}
It load the necessary functions into a button. If user click on that button, user will be redirected into Google's signin page. After user manages to sign in then Google will redirect the URL back into my website.
It should also send the user's profile info into my attachClickHandler() function within the attachSignin(). But it never happens since it reloads the page before the handler function gets called.
It only works if I change the ux_mode: 'redirect' into default' popup
The best I can do right now is just to get the email address from the token_id parameter that Google give in URL after signin. The id_token field from the URL is a jwt that can be decoded
http://localhost:3006/login#scope=email%20profile%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile%20openid&id_token=xxxxxxxxx&client_id=xxxxxxxxxxxx-xxxxxx.apps.googleusercontent.com
So How to get the user's profile information with ux_mode set to redirect ?
I modified your code so it works:
var startApp = function () {
gapi.load('auth2', function () {
// Retrieve the singleton for the GoogleAuth library and set up the client.
auth2 = gapi.auth2.init({
client_id: 'xxxxxxxx-xxxxxxxxxx.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
ux_mode: 'redirect', // I don't want it to display a pop-up
scope: 'profile email' // I just need to get user's name, profile picture and email address
});
// attach this function into a button element with id = "customBtn"
attachSignin(document.getElementById('customBtn'));
// START NEW CODE
auth2.currentUser.listen(function(googleUser) {
if (googleUser && (gProfile = googleUser.getBasicProfile())) {
var name = gProfile.getName();
var email = gProfile.getEmail();
var imgUrl = gProfile.getImageUrl();
console.log({name, email, imgUrl});
}
});
// END NEW CODE
});
};
// Can remove callbacks if not using pop-up
function attachSignin(element) {
auth2.attachClickHandler(element, {});
}
Explanation:
When using redirect instead of pop-up, listen on currentUser instead of the attachClickHandler() callbacks. The Google API will detect and consume the redirect parameters, firing the currentUser.listen handler.
Sources:
https://github.com/google/google-api-javascript-client/issues/477#issuecomment-430299619
https://developers.google.com/identity/sign-in/web/listeners
I am trying to stream some events in batches from a mobile web site to BigQuery, and I am trying to trigger a Google Cloud Function to do this via parameters.
I've reached the point to initilise de script, but how do I call a Google Cloud Function with param?
<script src="https://apis.google.com/js/api.js"></script>
<script>
function start() {
// 2. Initialize the JavaScript client library.
gapi.client.init({
'apiKey': 'YOUR_API_KEY',
// Your API key will be automatically added to the Discovery Document URLs.
'discoveryDocs': ['https://people.googleapis.com/$discovery/rest'],
// clientId and scope are optional if auth is not required.
'clientId': 'YOUR_WEB_CLIENT_ID.apps.googleusercontent.com',
'scope': 'profile',
}).then(function() {
// 3. Initialize and make the API request.
return gapi.client.people.people.get({
'resourceName': 'people/me',
'requestMask.includeField': 'person.names'
});
}).then(function(response) {
console.log(response.result);
}, function(reason) {
console.log('Error: ' + reason.result.error.message);
});
};
// 1. Load the JavaScript client library.
gapi.load('client', start);
</script>
I hope you found a solution for it... but I usually do:
var getPeople = gapi.client.people.people.get({
'resourceName': 'people/me',
'requestMask.includeField': 'person.names'
});
getPeople.execute(function(response) {
console.log(response.result);
}, function(reason) {
console.log('Error: ' + reason.result.error.message);
});
I'm using this script to sign in the user to my webapp.
<script src="https://apis.google.com/js/platform.js" async defer></script>
<script src="https://apis.google.com/js/api:client.js"></script>
<script>
var googleUser = {};
var startApp = function() {
gapi.load('auth2', function(){
auth2 = gapi.auth2.init({
client_id: '0000000000000-xxxx00000xxxx0000xxxx0000xxxx000.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
scope: 'profile',
});
attachSignin(document.getElementById('login-with-google'));
attachSignin(document.getElementById('register-with-google'));
});
};
function attachSignin(element) {
console.log(element.id);
auth2.attachClickHandler(element, {},
function(googleUser) {
onSignIn(googleUser);
},
function(error) {
console.log(JSON.stringify(error, undefined, 2));
if(error['error'] && error['error'] == 'IMMEDIATE_FAILED'){
auth2 = gapi.auth2.getAuthInstance();
auth2.signIn(
{
immediate: false
}
);
console.log('authorize--end');
}
});
}
</script>
After the user clicks on the button I am getting IMMEDIATE_FAILED
{
"type": "tokenFailed",
"idpId": "google",
"error": "IMMEDIATE_FAILED"
}
I saw some posts here on SO saying that if the user has never connected to my webapp, I have to call SignIn for a second time and the result is
{
error: "popup_closed_by_user"
}
Seriously, I don't know what I'm doing wrong, but clearly I'm doing something very stupid.
It was an error on JS API.
See more
https://github.com/google/google-api-javascript-client/issues/305
I have a blog that I want to make shareable via LinkedIn. The docs LinkedIn presents, while simply stated don't have enough detail for me to understand my use case. My use case requires me to dynamically put the picture and description in each blog post, which isn't being populated right now. This is an Angular project.
My current code:
post.html
<script>
delete IN;
$.getScript("https://platform.linkedin.com/in.js");
</script>
<script type="IN/Share" data-url={{webAddress}} data-counter="right"></script>
post.js
//I have all of my data in $scope variables in this area, which includes
// the picture and description I'd like to attach to the post.
Here is what the LinkedIn docs show as the right way to do this:
post.html
<script type="text/javascript" src="//platform.linkedin.com/in.js">
api_key: YOUR_API_KEY_HERE
authorize: true
onLoad: onLinkedInLoad
</script>
<script type="text/javascript">
// Setup an event listener to make an API call once auth is complete
function onLinkedInLoad() {
IN.Event.on(IN, "auth", shareContent);
}
// Handle the successful return from the API call
function onSuccess(data) {
console.log(data);
}
// Handle an error response from the API call
function onError(error) {
console.log(error);
}
// Use the API call wrapper to share content on LinkedIn
function shareContent() {
// Build the JSON payload containing the content to be shared
var payload = {
"comment": "Check out developer.linkedin.com! http://linkd.in/1FC2PyG",
"visibility": {
"code": "anyone"
}
};
IN.API.Raw("/people/~/shares?format=json")
.method("POST")
.body(JSON.stringify(payload))
.result(onSuccess)
.error(onError);
}
</script>
As I understand it, I need to populate the payload object with the right data/links. I have no clue how to do this based on what's in the docs.
Here are a few things I've tried/thought about along with where I'm currently stuck:
1) Get the data from post.js and put it in the payload object between the script tags in post.html. After doing some research, it is not possible to do this. Though I welcome being corrected if I'm wrong.
2) Bring the IN object into angular and populate the payload in post.js. This sounds really great but LinkedIn provides no html with which to call a function in post.js with Angular. Plus the LinkedIn code as presented takes care of formatting for the button and what comes after you click it.
3) Make an http call inside the script tags with JQuery. I rarely if ever use JQuery and have never used http for JQuery before. If this is even a feasible way to think of this problem, this is what I came up with:
<script type="IN/Share" data-url={{webAddress}} data-counter="right">
$.get( "https://public-api.wordpress.com/rest/v1.1/sites/myPost", function( response ) {
var post = _.first(_.filter(response.posts, function(n){return n.title.replace(/ /g,"-").replace(/[:]/g, "").toLowerCase() === $stateParams.id}));
var post1 = _.assign(post, {category: _.first(_.keys(post.categories)), pic: _.first(_.values(post.attachments)).URL, credit: _.first(_.values(post.attachments)).caption, linkCredit: _.first(_.values(post.attachments)).alt, fullStory: post.content.replace(/<(?!\s*\/?\s*p\b)[^>]*>/gi,'')});
**var image = post1.pic;**
**var title = post1.title;**
**var webAddress = window.location.href;**
function onLinkedInLoad() {
IN.Event.on(IN, "auth", shareContent);
}
function onSuccess(data) {
console.log(data);
}
function onError(error) {
console.log(error);
}
function shareContent(title, image, webAddress) {
var payload = {
"content": {
"title": title,
"submitted-image-url": image,
"submitted-url": webAddress
}
};
IN.API.Raw("/people/~/shares?format=json")
.method("POST")
.body(JSON.stringify(payload))
.result(onSuccess)
.error(onError);
}
});
</script>
This solution did not result in a solution either. Where to go from here, I have no ideas. I'm sure this simple but idiosyncratic enough that I need a little hand holding.
Unfortunately, I have not worked with linkedin API.
Perhaps not all will be right in my example. But I've got to use a variable IN in angular and write about the call API wrapper.
An example of the use of plugins, see page LinkedIn Plugins.
Live example on jsfiddle.
//CallBackHell
function LinkedInServiceFunc(callback) {
callback && IN.Event.onDOMReady(callback);
}
angular.module('ExampleApp', [])
.controller('ExampleController', function($scope, LinkedInService, ShareLinkedINService) {
console.log('ExampleController IN', IN);
console.log('ExampleController LinkedInService', LinkedInService);
LinkedInService.promise.then(function(LIN) {
console.log('Complete loading script for LinkedIn in ExampleController', LIN.Objects)
});
//Then you can interact with IN object as angular service. Like this
$scope.shareContent = function() { // Use the API call wrapper to share content on LinkedIn
// Build the JSON payload containing the content to be shared
var payload = {
"comment": $scope.comment,
"visibility": {
"code": 'anyone'
}
};
// Handle the successful return from the API call
function onSuccess(data) {
console.log(data);
}
// Handle an error response from the API call
function onError(error) {
console.log(error);
}
console.log('shareContent', payload);
LinkedInService.promise.then(function(LIN) {
LIN.API.Raw("/people/~/shares?format=json")
.method("POST")
.body(JSON.stringify(payload))
.result(onSuccess)
.error(onError);
});
}
$scope.shareContentService = function() {
//It's better way, i think
ShareLinkedINService.shareContent($scope.comment, 'anyone').then(function(data) {
console.log('success', data);
}).catch(function(data) {
console.err('error', data);
});
}
})
.service('LinkedInService', function($q) {
var defer = $q.defer();
LinkedInServiceFunc(function() {
defer.resolve(IN);
});
return {
promise: defer.promise
};
})
//You can create wrapper on IN API
.service('ShareLinkedINService', function(LinkedInService, $q) {
return {
shareContent: function(comment, visible) {
var defer = $q.defer();
var payload = {
"comment": comment,
"visibility": {
"code": visible
}
};
LinkedInService.promise.then(function(LIN) {
LIN.API.Raw("/people/~/shares?format=json")
.method("POST")
.body(JSON.stringify(payload))
.result(defer.resolve)
.error(defer.reject);
});
return defer.promise;
}
}
})
.directive('linkedInShareButton', function(LinkedInService) {
return {
restrict: "E",
replace: false,
scope: {
shareUrl: "#",
counter:"#"
},
link: function(scope, elem, attr) {
var script = document.createElement('script');
script.setAttribute('type', 'IN/Share');
script.setAttribute('data-url', scope.shareUrl);
script.setAttribute('data-counter', scope.counter);
elem.append(script);
},
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script type="text/javascript" src="//platform.linkedin.com/in.js">
authorize: false
onLoad: LinkedInServiceFunc
//I don't have api_key, because i delete it
// api_key: YOUR_API_KEY_HERE
// authorize: true
// onLoad: onLinkedInLoad
</script>
<body ng-app="ExampleApp">
<div>
<div ng-controller="ExampleController">
<input ng-model="comment">
<button ng-click="shareContent()">
shareContent
</button>
<button ng-click="shareContentService()">
shareContentService
</button>
<script type="IN/Share" data-url="www.mail.ru" data-counter="top"></script>
<linked-in-share-button share-url="www.mail.ru" counter="top"></linked-in-share-button>
</div>
</div>
</body>
I am a newbie to Pentaho and try to make an alert(some_msg_from_datasource) in the index.jsp of Pentaho. But I cannot figure out how to access the Pentaho variables from here. This is what I have
<head> ... <script type="text/javascript">
var Home = null;
pen.require(["home/home",
"common-ui/util/ContextProvider"], function(pentahoHome, ContextProvider) {
Home = pentahoHome;
// Define properties for loading context
var contextConfig = [{
path: "properties/config",
post: function(context, loadedMap) {
context.config = loadedMap;
}
}, {
path: "properties/messages",
post: function(context, loadedMap) {
context.i18n = loadedMap;
}
}];
// Define permissions
ContextProvider.addProperty("canCreateContent", <%=canCreateContent%>);
ContextProvider.addProperty("hasAnalyzerPlugin", <%=pluginIds.contains("analyzer")%>);
ContextProvider.addProperty("hasDataAccess", false); // default
// BISERVER-8631 - Manage datasources only available to roles/users with appropriate permissions
var serviceUrl = Home.getUrlBase() + "plugin/data-access/api/permissions/hasDataAccess";
Home.getContent(serviceUrl, function(result) {
ContextProvider.addProperty("hasDataAccess", result);
ContextProvider.get(Home.init, contextConfig); // initialize
}, function(error) {
console.log(error);
ContextProvider.get(Home.init, contextConfig); // log error and initialize anyway
});
});
</script> </head>
And for the body:
<body data-spy="scroll" data-target=".sidebar" onload="onBodyLoad()">
<script>
function onBodyLoad(){
alert("MOTD: " + the_motd_from_a_pentaho_var);
}
</script>
I assume I need the webcontext but I don't understand the head-scripts and how I can make it run. Tbh I don't even fully understand the syntax in the head. Please help :(