Log in/out button no longer maintaining state - iframe

My code was working fine until the past 24 hours. I did not change anything, but now the #fb-button is smaller and it no longer says "Log Out" when it should.
You can see this in action at Homewrd.
The following code is nested in BODY > ROOT:
<div id="fb-root"></div>
<script type="text/javascript">
// Load the SDK Asynchronously
(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));
// Init the SDK upon load
window.fbAsyncInit = function() {
FB.init({
appId:'271193286279763',
channelUrl:'//'+window.location.hostname+'/channel',
status:true,
cookie:true,
xfbml:true
});
// Conditional UI for landing page
if (landing) {
FB.getLoginStatus(function(response) {
if(response && response.status == 'connected') {
FB.api('/me', function(response) {
var heading = $('#goods h1').text().replace('Homewrd','Welcome '+response.first_name+'!');
$('#goods h1').text(heading);
});
}
});
}
// listen for and handle auth.statusChange events
FB.Event.subscribe('auth.statusChange', function(response) {
fbEventful = true;
if (response.authResponse) {
fbToken = response.authResponse.accessToken;
$('#fb-button').css({'display':'inline','float':'left'});
$('#toolbox').css({'display':'inline'});
$('#local-login').hide();
$('#local-logout').hide();
currentUser = {
fbid:response.authResponse.userID
}
displayPicture();
} else {
$.cookie('cuat', null);
$.ajax({
url:'/logout.json',
type:'delete',
success:function() {
ajaxOff();
renderLocal();
}
});
}
});
FB.Event.subscribe('auth.login',
function(response) {
FB.api('/me', function(me){
if (me.name) {
currentUser = {
fbid:me.id,
email:me.email,
first_name:me.first_name,
last_name:me.last_name
}
params = {
fbid: currentUser.fbid,
user: {
fbid:currentUser.fbid,
email:currentUser.email,
first_name:currentUser.first_name,
last_name:currentUser.last_name
}
}
$.ajax({
url:domain+'/user.json',
data:params,
dataType:'json',
type:'post',
success:function(e) {
cuat = e.user.auth_token;
$.cookie('cuat', cuat, {
path:'/',
expires:7
}
);
if (rurl) {
refreshSession();
}
if (storedProcedure!==null) {
storedProcedure();
}
}
});
}
});
}
);
$('#local-logout a').click(function(e) {
e.preventDefault();
var x = confirm('Are you sure that you want to logout?');
if (x===true) {
ajaxOn();
$.ajax({
url:'/logout.json',
type:'delete',
success:function() {
ajaxOff();
window.location.reload();
}
});
}
return false;
});
setTimeout(function() {
if (!fbEventful) {
renderLocal();
}
},1000);
}
</script>
<div id="header">
<div id="logo">
<h1>Logo Link</h1>
</div>
<div id="session">
<div id="fb-button" autologoutlink="true" class="fb-login-button" scope="publish_stream,email,user_about_me,user_birthday,user_hometown,offline_access"></div>
<div id="fb-picture"></div>
<div id="local-login"><p>local login link</p></div>
<div id="local-logout"><p>local logout link</p></div>
</div>
</div>

Related

MeteorJS project with redis-livedata package not returning object from redisCollection.hgetall as expected

The MeteorJS method "get.jade" is not returning jade object to client as expected. I'm using redis-livedata and manuel:reactivearray packages, and Redis is functioning locally correctly. I have put console.log in the code where there is a problem is returning server side data to client
jades.html
<template name="jades">
{{#if jadeslength}}
<div class="row">
<div class="user-card" id="swipe">
<img src="{{jade.img}}" style="width:100%">
<div class="card-container">
<h5>{{jade.name}}, {{jade.gender}}</h5>
</div>
</div>
</div>
<div class="row">
<div class="one-half column">
<button class="no" type="button">no</button>
</div>
<div class="one-half column">
<button class="button-primary yes" type="button">yes</button>
</div>
</div>
{{else}}
<div class="row">
<button class="button-primary search-jades" type="button" id="search">search</button>
</div>
{{/if}}
</template>
jades.js
import { Meteor } from 'meteor/meteor';
import { Session } from 'meteor/session';
import './jades.html';
Template.jades.onCreated(function () {
var jades = new ReactiveArray([]);
Session.set({'jadeId':""});
});
Template.jades.helpers({
jade: function() {
return jades.list();
},
jadeslength: function() {
var jades = jades.list();
return jades.length;
},
});
Template.jades.events({
...
'click .search-jades' () {
Template.instance.jades = [];
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var client_location = {"lat": position.coords.latitude, "lng": position.coords.longitude};
if (client_location) {
var lng = client_location.lng;
var lat = client_location.lat;
Meteor.call('client.profile', (error, result) => {
if (error) {
FlashMessages.sendError(error, 3000);
} else {
var user_profile = result;
Session.set({'user_profile': user_profile});
var prefer = user_profile.prefer;
switch (prefer) {
case "cis women":
Meteor.call('search.cw', lng, lat, (error, result) => {
if (error) {
FlashMessages.sendError(error, 3000);
return;
} else {
searched = result;
if (searched.length == 0) {
FlashMessages.sendWarning("no more providers found in your area", 3000);
} else {
for (var found of searched) {
var user_profile = Session.get('user_profile');
var right = user_profile.right;
if (!(found._id in right)) {
Template.instance.jades.push(found._id);
}
}
var jadeId = Template.instance.jades.pop();
console.log(jadeId); // returns ofQj98LBQWrSJ8gJs on client
if (jadeId) {
Meteor.call('get.jade', jadeId, (error, result) => {
if (error) {
FlashMessages.sendError(error, 3000);
} else {
Session.set({'jadeId': jadeId});
Session.set({'jade': result});
console.log(result); // returns undefined on client
}
});
} else {
FlashMessages.sendWarning("no more providers found in your area", 3000);
}
}
}
});
break;
case "trans women":
...
methods.js
'get.jade': function(jadeId) {
var redisCollection = new Meteor.RedisCollection("redis");
redisCollection.hgetall(jadeId, function(error, object) {
if (error) {
console.log(error);
} else {
console.log(object); // returns { name: 'alex', img: 'null', gender: 'cis woman' } on server
return object;
}
});
},
I solved this by changing the method as follows:
'get.jade': function(jadeId) {
var redisCollection = new Meteor.RedisCollection("redis");
return redisCollection.hgetall(jadeId)
},

Two recaptcha controls, one of them is not working

I have two reCaptcha V2 controls within two forms in one page, one is visible another is invisible. All is fine except the invisible one's data-callback callback - submitSendForm() did not get called. Once I removed the visible one, the invisible one starts working.
So the process is like once user completed the first visible challenge then the second form(within same page) will show with the invisible one, that's when the call back failed to be called.
It hasn't to be one visible and another invisible. But I found this to be easy when you want to have multiple controls.
Here is the code:
using (Html.BeginForm("Verify", "CertificateValidation", FormMethod.Post, new { id = "verifyForm" }))
{
<div class="form-group">
<div class="g-recaptcha" data-sitekey='site-key' data-callback="enableBtn"
style="transform: scale(0.66); transform-origin: 0 0;">
</div>
<div class="col-sm-3">
<button type="submit" id="verify" disabled>Verify</button>
</div>
</div>
}
using (Html.BeginForm("Send", "CertificateValidation", FormMethod.Post, new { id = "sendForm" }))
{
<div id='recaptcha1' class="g-recaptcha"
data-sitekey='site-key'
data-callback="submitSendForm"
data-size="invisible"></div>
<button type="submit">Send</button>
}
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<script type="text/javascript">
function submitSendForm() {
console.log('captcha completed.');
$('#sendForm').submit();
}
$('#sendForm').submit(function (event) {
console.log('form submitted.');
if (!grecaptcha.getResponse()) {
console.log('captcha not yet completed.');
event.preventDefault(); //prevent form submit
grecaptcha.execute();
} else {
console.log('form really submitted.');
}
});
var enableBtn = function (g_recaptcha_response) {
$('#verify').prop('disabled', false);
};
$(document).ready(function () {
$('#verify').click(function () {
$captcha = $('#recaptcha');
response = grecaptcha.getResponse();
if (response.length === 0) {
return false;
} else {
return true;
}
});
});
</script>
I got it figured out somehow:
var CaptchaCallback = function () {
grecaptcha.render('RecaptchaField1', { 'sitekey': 'site-key', 'callback': 'enableBtn' });
window.recaptchaField2Id = grecaptcha.render('RecaptchaField2', { 'sitekey': 'site-key', 'callback': 'submitSendForm', 'size': 'invisible' });
};
function submitSendForm() {
$('#sendForm').submit();
}
$('#sendForm').submit(function (event) {
if (!grecaptcha.getResponse(window.recaptchaField2Id)) {
event.preventDefault();
grecaptcha.execute(window.recaptchaField2Id);
}
});
using (Html.BeginForm("Verify", "CertificateValidation", FormMethod.Post, new { id = "verifyForm" }))
{
<div class="form-group">
<div style="transform: scale(0.66); transform-origin: 0 0;" id="RecaptchaField1"></div>
<div class="col-sm-3">
<button type="submit" id="verify" disabled>Verify</button>
</div>
</div>
}
using (Html.BeginForm("Send", "CertificateValidation", FormMethod.Post, new { id = "sendForm" }))
{
<div id="RecaptchaField2"></div>
<button type="submit">Send</button>
}
This one worked for me, clean and easy.
Javascript
var reCaptcha1;
var reCaptcha2;
function LoadCaptcha() {
reCaptcha1 = grecaptcha.render('Element_ID1', {
'sitekey': 'your_site_key'
});
reCaptcha2 = grecaptcha.render('Element_ID2', {
'sitekey': 'your_site_key'
});
};
function CheckCaptcha1() {
var response = grecaptcha.getResponse(reCaptcha1);
if (response.length == 0) {
return false; //visitor didn't do the check
};
};
function CheckCaptcha2() {
var response = grecaptcha.getResponse(reCaptcha2);
if (response.length == 0) {
return false; //visitor didn't do the check
};
};
HTML
<head>
<script src="https://www.google.com/recaptcha/api.js?onload=LoadCaptcha&render=explicit" async defer></script>
</head>
<body>
<div id="Element_ID1"></div>
<div id="Element_ID1"></div>
</body>

How do I track SignalR Connection State?

I was pointed to this GITHub sample code by David Fowler himself to track SignalR users and states. I have implemented all of it and it works great except I can't figure out the displaying of Hub connection state changes. I have this which doesn't seem to work. Does anyone know why?
!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style>
#state {
width: 20px;
height: 50px;
}
</style>
</head>
<body>
<h3 id="msg"></h3>
<div id="state"></div>
<script src="../Scripts/jquery-1.10.2.min.js"></script>
<script src="../Scripts/jquery.signalR-2.0.2.min.js"></script>
<script src="signalr/hubs"></script>
<script>
$(function () {
var userTracking = $.connection.alphaHub;
// Need at least one callback for events to be raised on the hub
userTracking.client.void = function () { };
$.connection.logging = true;
$.connection.hub.stateChanged(function (change) {
if (change.newState === $.signalR.connectionState.connected) {
$('#state').css('background-color', 'green');
} else if (change.newState === $.signalR.connectionState.reconnecting) {
$('#state').css('background-color', 'yellow');
} else if (change.newState === $.signalR.connectionState.disconnected) {
$('#state').css('background-color', 'red');
}
});
$.connection.hub.disconnected(function () {
setTimeout(function () {
$.connection.hub.start();
}, 1000);
});
});
</script>
</body>
</html>
My Hub is shown partially here:
public class AlphaHub : Hub
{
public override async Task OnConnected()
{
try
{
var name = Context.User.Identity.Name;
using (savitasEntities2 entities = new savitasEntities2())
{
var user = entities.SUsers
.Include(u => u.SConnections)
.SingleOrDefault(u => u.UserName == name);
if (user == null)
{
user = new SUser
{
UserName = name,
SConnections = new List<SConnection>()
};
entities.SUsers.Add(user);
}
user.SConnections.Add(new SConnection
{
ConnectionID = Context.ConnectionId,
UserAgent = Context.Request.Headers["User-Agent"],
LastActivity = DateTimeOffset.UtcNow
});
// entities.SaveChanges();
await entities.SaveChangesAsync();
}
}
public override async Task OnDisconnected()
{
try
{
using (savitasEntities2 db = new savitasEntities2())
{
var connection = await db.SConnections.FindAsync(Context.ConnectionId);
db.SConnections.Remove(connection);
await db.SaveChangesAsync();
}
}
catch (Exception ex)
{
c.LogError(ex.Message, "AlphaHub.cs" + " - " + this.GetType().FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name);
}
}
Looks like your hubs can't be found.
Change:
<script src="signalr/hubs"></script>
to:
<script src="~/signalr/hubs"></script>

YouTube API loadVideoById startSeconds not working

I created a chapter selector for some youtube videos I was embedding. This method used to work but has stopped recently. I can't figure out what's going on.
I'm using their recommended format but use loadVideoById to show each chapter
<div class="wrapper">
<div id="player"></div>
<script type="text/javascript">
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
width: '625',
videoId: 'FE5jN0rqMtM',
events: {
'onStateChange': onPlayerStateChange
},
playerVars:{
rel: 0,
wmode: "opaque"
}
});
}
function onPlayerStateChange(evt) {
if (evt.data == 0) {
$('#video_popup').removeClass('hide_pop');
$('#video_popup').addClass('display_pop');
}
else if (evt.data == -1) {
$('#video_popup').removeClass('display_pop');
$('#video_popup').addClass('hide_pop');
}
else {
$('#video_popup').removeClass('display_pop');
$('#video_popup').addClass('hide_pop');
}
}
function chapter1() {
player.loadVideoById({'videoId': 'FE5jN0rqMtM', 'startSeconds': 0});
}
function chapter2() {
player.loadVideoById({'videoId': 'FE5jN0rqMtM', 'startSeconds': 63});
}
function chapter3() {
player.loadVideoById({'videoId': 'FE5jN0rqMtM', 'startSeconds': 135});
}
</script>
<div id="video_popup" class="hide_pop">
<div class="video_layover">
<div class="promo">Thank you for watching!<br /><br /></div>
<div class="link">Replay Video</div>
</div>
</div>
<div style="margin: 0 auto 20px auto; width:625px; height:98px; text-align:center;">
<ul class="player">
<li>Chapter 1</li>
<li>Chapter 2</li>
<li>Chapter 3</li>
</ul>
</div>
I'm guessing it is a bug though I wasn't able to find it documented. You could report the bug if you want.
Regardless, I think cueVideoById is a better method which is working for me in all browsers:
Example: JS Bin
function chapter2() {
player.cueVideoById('FE5jN0rqMtM', 63); // BETTER WAY
player.playVideo();
}
If you experienced an error like "TypeError: ytPlayer.loadVideoById is not a function",
then I believe you have to wait for the onReady event to fire.
Here is the sample code (part of) I use:
var ytPlayer;
var ytPlayerIsReady = false;
// this methods only works if defined in the global scope !!
window.onYouTubeIframeAPIReady = function () {
ytPlayer = new YT.Player('ytplayer', {
playerVars: {
enablejsapi: 1,
controls: 0,
fs: 1,
autoplay: 1,
rel: 0,
showinfo: 0,
modestbranding: 1
},
events: {
onReady: onReady,
onError: onError,
onStateChange: onStateChange
}
});
};
// youtube code for calling the iframe api
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onError(event) {
console.log("error with code" + event.data);
}
function onStateChange(event) {
console.log("change state to " + event.data);
}
function onReady(event) {
ytPlayerIsReady = true;
console.log("I'm ready");
}
window.myVideoPlayer = {
init: function (options) {
// some arbitrary code...
// the trick is to fire options.callback,
// which contains all the logic needed
function timeout() {
setTimeout(function () {
if (false === ytPlayerIsReady) {
timeout();
}
else {
if (options.callback) {
options.callback();
}
}
}, 1000);
}
timeout();
}
};
myVideoPlayer.init({
callback: function(){
// now the youtube api is ready, you should be able to call
// loadVideoById without problems (at least it worked for me)
// ytPlayer.removeEventListener('onStateChange');
// ytPlayer.addEventListener('onStateChange', '_myYtPlayerOnChange');
// ytPlayer.loadVideoById({
// videoId: 'xxxx',
// startSeconds: 12
// });
}
});
You need to make sure var player is ready before calling loadVideoById
If(player != null)
{
loadVideoById ..
}

Breeze.js query does not update knockout view

I am querying data via breeze.js which works fine the first time. The second time the view isn't updated.
html
<a id="linkQDate">Order by Newest</a>
<a id="linkQScore">Order by Score</a>
<div id="questionWrapper">
<ul data-bind="foreach: results">
<li>
<strong><span data-bind="text: Score"></span></strong>
<span data-bind="text: Titel"></span>
</li>
</ul>
</DIV>
js
$(document).ready(function () {
var manager = new breeze.EntityManager('/breeze/dbentities');
var isApplied = false;
var dmodel;
$("#linkQDate").click(function () {
var query = breeze.EntityQuery.from("Questions").orderBy("Date");
manager.executeQuery(query).then(querySucceeded);
function querySucceeded(data) {
dmodel = data;
if (!isApplied) {
ko.applyBindings(dmodel, $("#questionWrapper")[0]);
isApplied = true;
}
}
});
$("#linkQScore").click(function () {
var query = breeze.EntityQuery.from("Questions").orderBy("Score");
manager.executeQuery(query).then(querySucceeded);
function querySucceeded(data) {
dmodel = data;
if (!isApplied) {
ko.applyBindings(dmodel, $("#questionWrapper")[0]);
isApplied = true;
}
}
});
});
If you just using plain JS objects it will not work. Because it does not know when underlying data changes. Use mapping plugin for this to work:
$(document).ready(function () {
var manager = new breeze.EntityManager('/breeze/dbentities');
var isApplied = false;
var dmodel;
function querySucceeded(data) {
if (!isApplied) {
dmodel = ko.mapping.fromJS(data);
ko.applyBindings(dmodel, $("#questionWrapper")[0]);
isApplied = true;
} else {
ko.mapping.fromJS(data, dmodel);
}
}
$("#linkQDate").click(function () {
var query = breeze.EntityQuery.from("Questions").orderBy("Date");
manager.executeQuery(query).then(querySucceeded);
});
$("#linkQScore").click(function () {
var query = breeze.EntityQuery.from("Questions").orderBy("Score");
});
});
Working code from Tomas without mappings. It is much faster:
$(document).ready(function () {
var manager = new breeze.EntityManager('/breeze/dbentities');
var isApplied = false;
var dmodel = { results: ko.observableArray() };
function queryFailed(data) {
console.log(data);
}
function querySucceeded(data) {
if (!isApplied) {
for (var i = 0; i < data.results.length; i++) {
dmodel.results.push(data.results[i]);
}
ko.applyBindings(dmodel, $("#questionWrapper")[0]);
isApplied = true;
} else {
dmodel.results.removeAll();
for (var i = 0; i < data.results.length; i++) {
dmodel.results.push(data.results[i]);
}
}
}
$("#linkQDate").click(function () {
var query = breeze.EntityQuery.from("Questions").orderBy("Date");
manager.executeQuery(query).then(querySucceeded).fail(queryFailed);;
});
$("#linkQScore").click(function () {
var query = breeze.EntityQuery.from("Questions").orderBy("Score");
manager.executeQuery(query).then(querySucceeded).fail(queryFailed);;
});
});

Resources