I went exactly by the instructions for integrating google sign-in:
https://developers.google.com/identity/sign-in/web/sign-in#specify_your_apps_client_id
sign-in works, but sign-out gives a javascript error in the line:
var auth2 = gapi.auth2.getAuthInstance();
The error is:
gapi.auth2 undefined
I include the google platform library as instructed:
<script type='text/javascript' src='https://apis.google.com/js/platform.js' async defer></script>
Why does it not work?
Are signIn and signOut used on the same page?
Div g-signin2 loads and inits gapi.auth2 so it should work as long as those are on the same page.
In case signOut is on separate page, you should manually load and init gapi.auth2 library.
Full example (you have to replace YOUR_CLIENT_ID with your actual client_id):
<html>
<head>
<meta name="google-signin-client_id" content="YOUR_CLIENT_ID">
</head>
<body>
<script>
function signOut() {
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
});
}
function onLoad() {
gapi.load('auth2', function() {
gapi.auth2.init();
});
}
</script>
Sign out
<script src="https://apis.google.com/js/platform.js?onload=onLoad" async defer></script>
</body>
</html>
Related
Following documentation described here, I have account linking set up with implicit grants and find that it works well when testing with the browser / actions console, and also with the Google Home app for Android. Unfortunately on the iphone version of the app, user auth hangs most of the time. Feedback from actions on google support is that the problem is that google sign in flow is implemented in separate browser tab (window). On iphone you can't open 2 windows in SfariViewController, thus they are re-writing address of the first page and can’t finish sign in flow. This is known issue and they are not planning to change this. The solution is to implement sign in flow all in one browser window. I'm unclear how to do this and am looking for someone to share code behind the authorization URL you set up that works consistently on iphone. Below is the core of what I am using:
.html snippet:
<!DOCTYPE html>
<html>
<head>
<title>Authorization Page</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="google-signin-client_id" content="948762963734-2kbegoe3i9ieqc6vjmabh0rqqkmxxxxx.apps.googleusercontent.com">
<!-- <meta name="google-signin-ux_mode" content="redirect"> INCLUDING THIS META TAG BREAKS THE AUTH FLOW -->
<script src="js/googleAuth.js"></script>
<script src="https://apis.google.com/js/platform.js" async defer></script>
<link rel="stylesheet" href="css/googleAuth.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<header class="bgimg-1 w3-display-container w3-grayscale-min" id="loginScreen">
<div class="w3-display-topleft w3-padding-xxlarge w3-text-yellow" style="top:5px">
<span class="w3-text-white">Google Sign In</span><br>
<span class="w3-large">Sign in with your Google account</span><br><br>
<div class="g-signin2" data-onsuccess="onSignIn"></div><br><br>
</div>
</header>
</body>
</html>
.js code snippet:
function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
var id = profile.getId()
var name = profile.getName()
var email = profile.getEmail()
var token = googleUser.getAuthResponse().id_token;
var client_id = getQueryVariable('client_id')
// vital-code-16xxx1 is the project ID of the google app
var redirect_uri = 'https://oauth-redirect.googleusercontent.com/r/vital-code-16xxx1'
var state = getQueryVariable('state')
var response_type = getQueryVariable('response_type')
// store the user's name, ID and access token and then sign out
storeOwnerID (email, name, id, token, function() {
// sign out
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('signed out')
});
// if this page was loaded by Actions On Google, redirect to complete authorization flow
typeof redirect_uri != 'undefined' ? window.location = redirectURL : void 0
})
}
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
console.log('Query variable %s not found', variable);
}
#dana Have you tried adding meta tag?
<meta name="google-signin-ux_mode" content="redirect">
With help from Google support & engineering, this is now resolved:
As noted above, I had to include this meta tag: <meta name="google-signin-ux_mode" content="redirect">
I needed to have https://my-auth-endpoint.com/ in my project's authorized redirect URI. It is not enough to have it only in Authorized javascript origins. The other key thing is to include the trailing slash, I hadn't originally and it will not work without it.
Below is the simple code foundation you can use to get a working version of an authorization endpoint for actions on google account linking:
.html:
<!DOCTYPE html>
<html>
<head>
<title>Authorization Page</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="google-signin-client_id" content="948762963734-2kbegoe3i9ieqc6vjmabh0rqqkmxxxxx.apps.googleusercontent.com">
<meta name="google-signin-ux_mode" content="redirect">
<script src="js/googleAuth.js"></script>
<script src="https://apis.google.com/js/platform.js" async defer></script>
<link rel="stylesheet" href="css/googleAuth.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script>
sessionStorage['jsonData'] == null ? storeQueryVariables() : void 0
</script>
</head>
<body>
<header class="bgimg-1 w3-display-container w3-grayscale-min" id="loginScreen">
<div class="w3-display-topleft w3-padding-xxlarge w3-text-yellow" style="top:5px">
<span class="w3-text-white">Google Sign In</span><br>
<span class="w3-large">Sign in with your Google account</span><br><br>
<div class="g-signin2" data-onsuccess="onSignIn"></div><br><br>
</div>
</header>
</body>
</html>
.js:
// Retrieve user data, store to DynamoDB and complete the redirect process to finish account linking
function onSignIn(googleUser) {
let profile = googleUser.getBasicProfile(),
id = profile.getId(),
name = profile.getName(),
email = profile.getEmail(),
token = googleUser.getAuthResponse().id_token,
redirect_uri = 'https://oauth-redirect.googleusercontent.com/r/vital-code-16xxxx',
jsonData = JSON.parse(sessionStorage['jsonData']),
redirectURL = redirect_uri + '#access_token=' + token + '&token_type=bearer&state=' + jsonData.state
// store the user's name, ID and access token
storeUserData(email, name, id, token, function() {
// sign out of google for this app
let auth2 = gapi.auth2.getAuthInstance();
auth2.signOut()
// if this page was loaded by Actions On Google, redirect to complete authorization flow
typeof redirect_uri != 'undefined' ? window.location = redirectURL : void 0
})
}
// Store the user data to db
function storeUserData (email, name, id, token, callback) {
// removed for simplicity
}
// Store URI query variable 'state' to browser cache
function storeQueryVariables() {
let qvar = {
'state': getQueryVariable('state')
}
storeLocally(qvar)
}
// Get any variable from incoming URI
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
console.log('Query variable %s not found', variable);
}
// Store JSON object input to local browser cache
function storeLocally (jsonData) {
if (typeof(Storage) !== 'undefined') {
sessionStorage['jsonData'] = JSON.stringify(jsonData)
} else {
console.log('Problem: local web storage not available')
}
}
I have a problem while loading views using ui-router in cordova ios build. I'm using cordova angular in my application. The ui-router working fine in android build but while i'm running the app using cordova emulate ios the views not getting loaded.
here is my code looks like,
index.html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Awesome material design app</title>
<link rel="stylesheet" href="node_modules/angular-material/angular-material.css">
<link rel="stylesheet" href="lib/ionic/css/ionicons.min.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/ngPercentDisplay.css">
<script src="node_modules/angular/angular.js"></script>
<script src="lib/angular-ui-router.min.js"></script>
<script src="node_modules/angular-aria/angular-aria.js"></script>
<script src="node_modules/angular-animate/angular-animate.js"> </script>
<script src="node_modules/angular-material/angular-material.js"></script>
<script src="node_modules/angular-local-storage/dist/angular-local-storage.js"></script>
<script src="lib/angular-touch.min.js"></script>
<script src="js/ng-cordova.min.js"></script>
<script src="cordova.js"></script>
<script src="js/index.js"></script>
<script src="js/controller.js"></script>
<script src="js/router.js"></script>
</head>
<body ng-app="YourApp">
<div layout="column">
<ng-include src="'templates/partials/sidebar.html'" style="top:0px" ng-if ="lang =='ENGLISH'"></ng-include>
<ng-include src="'templates/partials/sidebar-right.html'" style="top:0px" ng-if ="lang =='ARABIC'"></ng-include>
<div ui-view></div>
</div>
</body>
</html>
The router.js file looks like below
app.config(['$urlRouterProvider', '$stateProvider','$compileProvider', function($urlRouterProvider, $stateProvider,$compileProvider) {
$urlRouterProvider.otherwise('/signup');
$stateProvider.state('signup', {
url:'/signup',
templateUrl: 'templates/sign-up.html',
controller: 'signupCtrl'
});
}]);
The index.js file looks like
var app = {
// Application Constructor
initialize: function() {
this.bindEvents();
},
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// 'load', 'deviceready', 'offline', and 'online'.
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
// deviceready Event Handler
//
// The scope of 'this' is the event. In order to call the 'receivedEvent'
// function, we must explicitly call 'app.receivedEvent(...);'
onDeviceReady: function() {
app.receivedEvent('deviceready');
},
// Update DOM on a Received Event
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
}
};
app.initialize();
controller.js looks like below,
'use strict';
var app = angular.module( 'YourApp', [ 'ngMaterial','ui.router']);
app.controller('myCtrl',['$scope',function ($scope) {
$scope.detail={};
$scope.detail.name="MyApp";
$scope.detail.desc="welcome to my app!";
}]);
Please help me if any one knows about this issue. Thanks in advance.
I am trying to use video.js(gitHub link - https://github.com/videojs/video.js ) plugin in my jquery mobile project to get custom video player, I followed all the documentation from this site (http://videojs.com/), but due to some reasons I am getting following errors -
The element or ID supplied is not valid. (videojs).
this[a] is not a function.
My code -
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="Js/jquery.js"></script>
<script src="Js/jquery.signalR-2.1.2.min.js"></script>
<script src="Js/jquery.mobile-1.4.5.js"></script>
<link href="mcss/jquery.mobile-1.4.5.css" rel="stylesheet" />
<link href="http://vjs.zencdn.net/4.12/video-js.css" rel="stylesheet">
<script src="http://vjs.zencdn.net/4.12/video.js"></script>
<script type="text/javascript">
videojs("Mobile_VIDEO_1").ready(function () {
var vid = this;
vid.on("ended", function () {
alert("is");
$("#videoListXYZ").css("display", "block");
});
});
</script>
</head>
<body>
<div data-role="page" id="p-forget-password">
<div data-role="main" class="ui-content ui-body-cf ui-responsive">
<!-- inserted dyanamically using handlebars template "http://handlebarsjs.com"/ -->
<video id="Mobile_VIDEO_1" class="video-js vjs-default-skin" controls data-id="{{VideoId}}" data-setup='{ "plugins" : { "resolutionSelector" : { "default_res" : "360" } } }' autoplay="autoplay" width="340" height="250">
<source src="{{Path}}" type="video/mp4" data-res="360" />
</video>
</div>
</div>
</body>
Please help me to find out what I am doing wrong.
-I tried using putting videojs(xyx).ready(....) inside document.ready
- I also tried sending my script at the bottom of my page as suggested by (http://help.videojs.com/discussions/problems/985-api-ready-call-fails), but it still not working
After many hit and trial, I realized that my event is firing much before the DOM initialization, so I searched for how to check when the whole page is fully loaded and I come across this document (https://css-tricks.com/snippets/jquery/run-javascript-only-after-entire-page-has-loaded/) from this link I used this
$(window).bind("load", function() {
// code here
});
to check if my page is fully loaded or not . my final solution is mentioned below , if any of you come across a better solution then please share that to help others.
$(window).bind("load", function () {
var videoPath = $('#sv1').attr('src'); //to get the path of video
if (videoPath != "" && videoPath != null) { //checking for non-empty path
console.log(videoPath);
videojs('MY_VIDEO_1', { "plugins": { "resolutionSelector": { "default_res": "360" } } }, function () {
console.log('Good to go!');
this.play();
this.on('ended', function () {
console.log('awww...over so soon?');
$("#videoList").css("display", "block");
});
});
$("#replay").click(function () {
var myPlayer = videojs("MY_VIDEO_1");
myPlayer.play();
});
}
});
I am developing an Phonegap (3.3.0) + Jquery Mobile (1.4) app.
I get an infinite loading page (white page with ui-loader icon). This is erratic and sometimes the app starts well.
I see a very strange bug: none of the first "console.logs" I use in my js file are displayed in the Phonegap Build Weinre debug console.
Only after a certain line (which contain by the way the first asynchronous function) the console.log are displayed in the Weinre console.
So I guess I have a binding order problem related to Jquery Mobile and Phonegap, but I can't find what's wrong in my initialization.
Can I be also due to the order in which I call js files in my index.html ?
I followed this post to register Phonegap and JQM : Correct way of using JQuery-Mobile/Phonegap together?
recommended here : jQuery Mobile : What is the order of page events triggering?
by #Gajotres.
Can you help ?
Thanks
HTML:
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<!-- SPLASH PAGE -->
<div id="splash-page" data-role="page">
<div class='toastenjs' style='display:none'></div>
<center id="splashLogoCenter">
<img src="images/splash.png" width="200" />
</center>
</div>
<!-- WELCOME PAGE -->
<div id="welcome-page" data-role="page">
...
</div>
<script src="js/jquery-1.9.1.js"></script>
<script src="js/jquery.jsonp-2.4.0.min.js"></script>
<script src="js/functions.js"></script>
<script src="js/functionCUgly.js"></script>
<script src="js/boardDims.js"></script>
<script src="phonegap.js"></script>
<script src="js/jquery.mobile.config.js"></script>
<script src="js/jquery.mobile-1.4.3.min.js"></script>
<!--POUCHDB -->
<script src="js/pouchdb-2.2.3.min.js"></script>
<!-- Flexslider-->
<!-- <script src="js/flexslider-v2.js"></script>--> <!-- v2.2 doesn't work, maybe because we're not using last versions of jquery and jqm -->
<script src="js/flexsliderV2.3.js"></script>
<!-- iScroll-->
<script type="application/javascript" src="js/iscroll.js"></script>
<script type="application/javascript" src="js/jquery.mobile.iscrollview.js"></script>
<!-- Add2home : create a shortcut icon of the wep app on the phone homescreen -->
<script type="application/javascript" src="js/add2home.js"></script>
<script src="js/GoogleLogin.js"></script> <!--Phonegap module by eric valenzia https://github.com/valenzia10/PhonegapGoogleLogin-->
<script src="js/jquery.ddslick.min.js"></script>
<script src="js/jquery-geturlvar.js"></script>
<script src="js/html2canvas.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
if (typeof(google) != 'undefined'){
google.load('visualization', '1.0', {'packages':['corechart']});
}
</script>
JS file:
var deviceReadyDeferred = $.Deferred();
var jqmReadyDeferred = $.Deferred();
$(document).one("mobileinit", function () {
console.log('mobileinit just fired'); //this one is not displayed in the weinre console
jqmReadyDeferred.resolve();
});
if ( isPhoneGap() ) {
document.addEventListener("deviceReady", onDeviceReady, false);
function onDeviceReady() {
deviceReadyDeferred.resolve();
}
$.when(deviceReadyDeferred, jqmReadyDeferred).then( EVERYTHING() ); // !!!!! normalement il faut virer ces parenthèses pour respecter le $.when....mais ça fait tout bugger !!!!!!!!!
} else {
console.log("NOT Running on PhoneGap!");
$.when(jqmReadyDeferred).then( EVERYTHING );
}
function EVERYTHING() {
console.log("on est entré dans EVERYTHING()"); //not displayed in the weinre console
insideEVERYTHING = 1;
console.log("jqmReadyDeferred is "+jqmReadyDeferred.state()); //not displayed in the weinre console
console.log("deviceReadyDeferred is "+deviceReadyDeferred.state()); //not displayed in the weinre console
//FOR EVERY PAGE
$(document).on('pagecontainershow', function (e, ui) {
//...
});
$(document).on('pagecontainershow', function (e, ui) {
//...
});
// --------------- SPLASH PAGE ---------------------
//$(document).on('pagecreate','#splash-page', function(){
$(document).on('pagecontainershow', function (e, ui) {
var activePageId = $(':mobile-pagecontainer').pagecontainer('getActivePage').attr('id');
if (activePageId === 'splash-page') {
console.log("we are in splash-page");
if (typeof debugOptionUseLocalDB != 'undefined' && debugOptionUseLocalDB) {
fallbackToLocalDBfile();
console.log('on yess');
}else{
if(connectionStatus == 'online'){
console.log("launching getJsonpFile...");
//DEBUG TIMER
var time=[];
var dummy;
dummy = new Date().getTime();
time.push(dummy);
getJsonpFile(dbUrl())
.done(function(data) {
console.log("...getJsonpFile done.");
if(localStorage) {
if ( isPhoneGap() || !isIOS() ) { //BUG iOS safari doesn't work with this (Cf. Philippe's ipad), si on est sur phonegap ok, si on n'est pas sur phonegap et pas sur iOS ok
localStorage.setItem("proDB", JSON.stringify(data)); //write to localStorage
}
}
//...JQM bindings are continued below
The best registration is the following :
var isPhoneGap;
var deviceReadyDeferred = $.Deferred();
var jqmReadyDeferred = $.Deferred();
isPhoneGap = checkIfPhoneGap();
if ( isPhoneGap ) {
$.when(deviceReadyDeferred, jqmReadyDeferred).done( Everything );
} else {
console.log("NOT Running on PhoneGap!");
$.when(jqmReadyDeferred).done( Everything );
}
$(document).on("mobileinit", function () {
//alert('mobileinit just fired');
//popShortToast("mobileinit just fired");
jqmReadyDeferred.resolve();
});
document.addEventListener("deviceReady", onDeviceReady, false);
function onDeviceReady() {
//popShortToast("deviceReady just fired");
deviceReadyDeferred.resolve();
}
function checkIfPhoneGap() {
var app = document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1; // && document.URL.indexOf( 'file://' );
if ( app ) {
return true;
} else {
return false;
}
}
function Everything() {
//enter your JQM bindings here, and use Phonegap's features
}
I currently have a mobile site I am building and I am having trouble with integrating a custom JQuery widget. For some reason the the pageshow event is firing twice for whichever page is loaded first.
For ease of understanding I have created two HTML pages
Page 1
<!doctype html>
<head>
<meta charset="utf-8">
<title>One</title>
<link rel="stylesheet" href="https://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.min.css" />
<script type="text/javascript" src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
$(document).on("mobileinit", function () {
$.mobile.changePage.defaults.reloadPage = true;
});
</script>
<script type="text/javascript" src="https://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.js"></script>
</head>
<body id="default">
<div data-role="page" id="content-one">
<div role="main" class="ui-content" id="one-content">
One<br/>
back to two
</div>
<script type="text/javascript">
(function($, undefined) {
$.widget("test.stuff", {
_create : function() {
console.log("create");
},
_init : function() {
console.log("_init");
},
destroy: function () {
this.element.empty();
$.Widget.prototype.destroy.call(this);
}
});
})(jQuery);
</script>
<script type="text/javascript">
$(document).on("pageshow", "#content-one", function () {
console.log("pageshow1");
$("#content-one").stuff({});
});
$(document).on("pagebeforeshow", "#content-one", function () {
console.log("pagebeforeshow1");
});
</script>
</div>
</body>
</html>
Page 2
<!doctype html>
<head>
<meta charset="utf-8">
<title>Two</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.10.2.min.js"> </script>
<script type="text/javascript">
$(document).on("mobileinit", function () {
$.mobile.changePage.defaults.reloadPage = true;
});
</script>
<script type="text/javascript" src="https://code.jquery.com/mobile/1.4.0/jquery.mobile-1.4.0.js"></script>
</head>
<body id="default">
<div data-role="page" id="content-two">
<div role="main" class="ui-content">
Two<br/>
back to one
</div>
<script type="text/javascript">
$(document).on("pageshow", "#content-two", function () {
console.log("pageshow2");
});
$(document).on("pagebeforeshow", "#content-two", function () {
console.log("pagebeforeshow2");
});
</script>
</div>
</body>
</html>
To recreate load page one first, navigate to page two using link, then navigate to page one using link.
When page one is loaded again the pageshow event is fired twice. I have the reloadPage set to true as I have dynamic content for my pages and I cannot serve cached pages.
I very well could be using the events incorrectly.
Try substituting your $(document).on("pageshow",...) with $(document).one("pageshow", ...), which restricts the event to one call http://api.jquery.com/one/.
The problem is that using on in the inline script creates a new event each time the page is loaded. So the first time you load the page, the inline script is executed and the pageshow event is triggered. The second time a new event is triggered again, but the first one is still listening to content-one pageshow. In fact, if you repeat the process you'll see the log three, four, ... times.
Another option could be to create a script in the head section which sets up all required triggers in $(document).on("pageshow", "#content-one", ...), $(document).on("pageshow", "#content-two", ...). In this case, the script will only be initialized once, so it will work.
Wasted about 2 hours trying to do all the fixes on here and other sites. I gave up and put an if statement in their to prevent it from firing again
var hasDownload = false;
$(document).on("pageinit", "#mypage",function(event){
if (hasDownload === false) {
hasDownload = true;
// do some work
}
);
Try to remove the page on hide event, like so :
$(document).on("mobileinit", function () {
$.mobile.changePage.defaults.reloadPage = true;
$(docuement).on('pagehide', function (event, ui) {
$(event.target).remove();
});
});
Remenber that if you don't disable ajax, all request will be with AJAX