Hyperlinks in Bing Maps infobox breaks Windows 8 App Navigation State - windows-8

I have Bing Maps on a page in my WinJS Windows 8 Application.
The Map has a few pins each with its own Infobox. When clicking on the pin it displays the infobox correctly with its content. The content contains a hyperlink that links to a different page in the Windows 8 Application. The app navigates to this page correctly, however the back button stops working and the App Bar can't be accessed either. (Navigating to the page normally works fine)
I think something goes wrong with how the page navigates and how the navigator records the state. I am new to this so it might also just be a stupid question.
Here is the code in the page's .js file:
// For an introduction to the Page Control template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232511
(function () {
"use strict";
WinJS.UI.Pages.define("/pages/testBing/testBing.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
// TODO: Initialize the page here.
Microsoft.Maps.loadModule('Microsoft.Maps.Map', { callback: initMap });
}
});
})();
var pinInfobox = null;
function initMap() {
try {
var mapOptions =
{
credentials: "credentials",
center: new Microsoft.Maps.Location(-33.961176, 22.420985),
mapTypeId: Microsoft.Maps.MapTypeId.road,
zoom: 5
};
var mapDiv = document.querySelector("#mapdiv");
map = new Microsoft.Maps.Map(mapDiv, mapOptions);
centerPosition();
}
catch (e) {
var md = new Windows.UI.Popups.MessageDialog(e.message);
md.showAsync();
}
}
function addPushPin(location) {
map.entities.clear();
var pushpin = new Microsoft.Maps.Pushpin(location, null);
pinInfobox = new Microsoft.Maps.Infobox(new Microsoft.Maps.Location(0, 0), { title: 'My Pushpin', visible: true, description: "<a href='/pages/player/player.html'>Profile</a>" });
Microsoft.Maps.Events.addHandler(pushpin, 'click', displayInfobox);
Microsoft.Maps.Events.addHandler(map, 'viewchange', hideInfobox);
map.entities.push(pushpin);
map.entities.push(pinInfobox);
}
function hideInfobox(e) {
pinInfobox.setOptions({ visible: false });
}
function centerPosition() {
var geolocator = new Windows.Devices.Geolocation.Geolocator();
geolocator.getGeopositionAsync().then(function (loc) {
var mapCenter = map.getCenter();
mapCenter.latitude = loc.coordinate.latitude;
mapCenter.longitude = loc.coordinate.longitude;
map.setView({ center: mapCenter, zoom: 15 });
addPushPin(mapCenter);
});
}
function displayInfobox(e) {
pinInfobox.setOptions({ title: e.target.Title, innerHTML: e.target.Description, visible: true, offset: new Microsoft.Maps.Point(0, 25) });
pinInfobox.setLocation(e.target.getLocation());
}
The HTML just has the following
<!-- WinJS references -->
<link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
<script src="//Microsoft.WinJS.1.0/js/base.js"></script>
<script src="//Microsoft.WinJS.1.0/js/ui.js"></script>
<!--Bing Mapps Reference -->
<script type="text/javascript" src="ms-appx:///Bing.Maps.JavaScript//js/veapicore.js"></script>
<link href="testBing.css" rel="stylesheet" />
<script src="testBing.js"></script>
</head>
<body>
<div class="testBing fragment">
<header aria-label="Header content" role="banner">
<button class="win-backbutton" aria-label="Back" disabled type="button"></button>
<h1 class="titlearea win-type-ellipsis">
<span class="pagetitle">Welcome to testBing</span>
</h1>
</header>
<section aria-label="Main content" role="main">
<div id="mapdiv"></div>
</section>
</div>
</body>
</html>

The comment by Dominic Hopton is correct: foo.html gets loaded as the whole page instead of as part of your app's navigation process. If the links are supposed to do an app navigation (as opposed to open in an external web browser), you can add this code to your page's ready function to convert the link click into a navigation event.
WinJS.Utilities.query("a").listen("click", function (e) {
e.preventDefault();
nav.navigate(e.target.href);
});
If you have some links that should navigate and some that should open in a browser, you can modify the query. For example, if can can add a CSS class to links that should open in a web browser, you could change the query to:
WinJS.Utilities.query("a:not(.defaultClick)")
You might also be able to modify the query to examine the href attribute of the link to check for "http" like so:
WinJS.Utilities.query("a:not([href^=http])")
I have not tested this last example yet, but if it works as I suspect it would, it would have a links that start with "http" (so including "https") behave normally, while all links that have a relative URL or a package URL will be converted to navigation events.
I don't recommend that you do this blindly, but depending on your app, this simple shortcut might change the behavior to match your expectations.

Related

Teams Message Extension: Embedding Content from Tab App into Task Module with Authentication

I have created a Tab App in Teams. Now I want to make a dialog from one tab accessible via a Message Extension App. This works partially now through embedding the contentUrl of the specific tab as an iFrame in the Task Module of the Message Extension like here: https://learn.microsoft.com/en-us/microsoftteams/platform/messaging-extensions/how-to/action-commands/create-task-module?tabs=dotnet#create-a-task-module-with-an-embedded-web-view
. The issue is the authentication. Api Calls won't work and the dialog is not able to retreive or send data.
In the manifest.json of the Tab App are the contentUrls of the tabs in the "staticTabs" section:
"staticTabs": [
{
"entityId": "dashboard",
"name": "Dashboard",
"contentUrl": "https://cdne-stcsfeedbackuidev.azureedge.net/tabs/dashboard.html?app.locale={locale}&page.subPageId={subEntityId}&app.theme={theme}",
"scopes": [
"personal"
]
}
],
I gave the dialog a specific Route via React Router so that you can access the dialog via subPageId. This works fine.
The Problem is, if you access the contentUrl, you won't be authenticated and API calls to the Graph API and own API won't work. This issue does not go away if I embed the tab via contentUrl in a Task Module for the Message Extension to give it a Teams Context:
public async handleTeamsMessagingExtensionFetchTask(
context: any,
action: any
): Promise<any> {
return {
task: {
type: 'continue',
value: {
width: 925,
height: 925,
title: 'Feedback Dialog',
url: "https://2e70-37-201-241-91.ngrok.io/feedbackDialog.html",
fallbackUrl: "https://cdne-stcsfeedbackuidev.azureedge.net/tabs/dashboard.html?page.subPageId=feedbackDialog"
}
}
};
}
Directly embedding the url like in "fallbackUrl" will result in an empty Task Module so I embedded the Url in a like this in feedbackDialog.html:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello World Feedback!</title>
</head>
<body>
<script src="https://statics.teams.microsoft.com/sdk/v1.7.0/js/MicrosoftTeams.min.js"></script>
<script>
microsoftTeams.initialize();
microsoftTeams.getContext((context) => {
console.log(context);
microsoftTeams.authentication.getAuthToken({
successCallback: (token) => {
console.log(token);
},
failureCallback: (reason) => {
console.error(reason);
}
});
});
</script>
<div style="padding:50px;">
<iframe id="feedbackDialog" width="800" height="800", frameBorder="0"
src="https://cdne-stcsfeedbackuidev.azureedge.net/tabs/dashboard.html?page.subPageId=feedbackDialog"></iframe>
</div>
</body>
</html>
The dialog gets displayed in the Task Module this way like if I open the contentUrl in the browser directly. But the Authentication does not work. The Teams context can be retreived but all API calls return with the Error: "Error: SDK initialization timed out".
Is there a simple way for me to authenticate the user here because this runs in Teams as a MessageExtension App and the embedded content in the Task Module comes from a Teams Tab App. Or do I need to manually implement something using MSAL?

Show custom error message on passwordless Auth0 page

I would like to only allow certain phone numbers when patients sign up to my application through a passwordless Auth0 page.
For this I added a custom Auth0 action to the Pre User Registration flow.
My custom action checks the phone prefix:
/**
* Handler that will be called during the execution of a PreUserRegistration flow.
*
* #param {Event} event - Details about the context and user that is attempting to register.
* #param {PreUserRegistrationAPI} api - Interface whose methods can be used to change the behavior of the signup.
*/
exports.onExecutePreUserRegistration = async (event, api) => {
if (!isAllowedPhoneNumber(event.user.phone_number)) {
api.access.deny('my_custom_identifier', 'My Custom Message');
}
};
const allowedPhonePrefixes = ["+43", "+32", "+420", "+45"];
const isAllowedPhoneNumber = (phoneNumber) =>
allowedPhonePrefixes.some((prefix) => phoneNumber.startsWith(prefix));
However, "My Custom Message" doesn't show up when I try a phone number outside those allowed. Instead, I see the default "We're sorry, something went wrong".
I then tried to edit the HTML code of my custom Auth0 login page adding this:
languageDictionary = {
...languageDictionary,
passwordless: {
"lock.fallback": "My Custom Message",
"no_signups_from_outside_schengen_area": "My Custom Message 2",
}
};
So the HTML code of my page now looks like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Sign In with Auth0</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<!--[if IE 8]>
<script src="//cdnjs.cloudflare.com/ajax/libs/ie8/0.2.5/ie8.js"></script>
<![endif]-->
<!--[if lte IE 9]>
<script src="https://cdn.auth0.com/js/base64.js"></script>
<script src="https://cdn.auth0.com/js/es5-shim.min.js"></script>
<![endif]-->
<script src="https://cdn.auth0.com/js/lock/11.30/lock.min.js"></script>
<script>
// Decode utf8 characters properly
var config = JSON.parse(decodeURIComponent(escape(window.atob('##config##'))));
config.extraParams = config.extraParams || {};
var connection = config.connection;
var prompt = config.prompt;
var languageDictionary;
var language;
if (config.dict && config.dict.signin && config.dict.signin.title) {
languageDictionary = { title: config.dict.signin.title };
} else if (typeof config.dict === 'string') {
language = config.dict;
}
var loginHint = config.extraParams.login_hint;
languageDictionary = {
...languageDictionary,
passwordless: {
"lock.fallback": "My Custom Message",
"no_signups_from_outside_schengen_area": "My Custom Message 2",
}
};
var lock = new Auth0LockPasswordless(config.clientID, config.auth0Domain, {
auth: {
redirectUrl: config.callbackURL,
responseType: (config.internalOptions || {}).response_type ||
(config.callbackOnLocationHash ? 'token' : 'code'),
params: config.internalOptions
},
configurationBaseUrl: config.clientConfigurationBaseUrl,
overrides: {
__tenant: config.auth0Tenant,
__token_issuer: config.authorizationServer.issuer
},
assetsUrl: config.assetsUrl,
allowedConnections: connection ? [connection] : null,
rememberLastLogin: !prompt,
language: language,
languageBaseUrl: config.languageBaseUrl,
languageDictionary: languageDictionary,
theme: {
logo: 'https://link-to-my-logo.something',
primaryColor: '#429db3'
},
closable: false,
showTerms: false
});
lock.show();
</script>
</body>
</html>
... but still neither "My Custom Message" nor "My Custom Message 2" show up. I still see "We're sorry, something went wrong".
How can I show a custom error message to users who enter a phone number from outside the list of allowed countries?
Note: I am pretty sure that the custom Auth0 action works, as I am able to prevent sign-ups for certain phone prefixes. What is probably wrong is the way I'm changing the code of the HTML page shown above, I suppose.
There is a partial solution that allows to show a custom message for all extensibility errors. (I haven't found a way to show different custom messages for different extensibility errors.)
This partial solution involves changing the structure in which the languageDictorionary variable above is structured:
languageDictionary = {
...languageDictionary,
error: {
passwordless: {
extensibility_error: "My Custom Message for all extensibility errors"
}
}
};
This way, any call to api.access.deny in the Pre User Registration flow will show "My Custom Message for all extensibility errors", no matter what identifier or message is passed to api.access.deny.

Google Maps API Grey background

I have problem with Google Maps on my site.
Maps and code works locally but when i publish map it shows only gray background.
I have Joomla site.
Please could someone help me.
This is my code:
<head>
<script src='http://code.jquery.com/jquery.min.js' type='text/javascript'></script>
</head>
<body>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script src="/maps/westcampus.js"></script>
<script>
var infowindow;
function initialize() {
var map = new google.maps.Map(document.getElementById('map_canvas'), {
center: new google.maps.LatLng(37.42362457157549, -122.0921247138165),
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoom: 10
});
for (var x in westcampus) {
var building = westcampus[x];
var location = new google.maps.LatLng(building.lat,building.lng);
addMarker(map, building.name, location);
}
}
var bounds = new google.maps.LatLngBounds ();
function addMarker(map, name, location) {
var marker= new google.maps.Marker({
position: location,
map: map
});
bounds.extend (location);
google.maps.event.addListener(marker, 'click', function() {
if (typeof infowindow != 'undefined') infowindow.close();
infowindow = new google.maps.InfoWindow({
content: name
});
infowindow.open(map,marker);
});
map.fitBounds (bounds);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<div id="map_canvas" style="width: 100%; height: 400px;"></div>
</body>
</html>
and DB
var westcampus = [{'name':'Google West Campus 1','lat':37.423901,'lng':-122.091497,'ost': "Ostatak!"},
{'name':'Google West Campus 2','lat':37.424194,'lng':-122.092699,'ost': "Ostatak!"},
{'name':'Google West Campus 3','lat':37.423901,'lng':-122.092456,'ost': "Ostatak!"}];
thanks
There seems to be nothing wrong with the code you're using.
So the problem is with the server, and where it's requesting the map from.
Are you running SSL, and trying to request the JavaScript via HTTP ? Maybe remote to the server and see if you can run the page locally there. Investigate the network with chrome of fiddler. Might be returning 403 somewhere or something along those lines.
Or a load timing issue. Sometimes google maps need the resize event called once the map triggers the idle event. So it recalculates the bounds of the map tiles.
Can't really suggest anything else. Good luck.

Google SignIn State

I'm trying to build a Google signin button into my website. I'm trying to avoid using their built-in button. The code below works to sign in a user, but I can't figure out how to make my webpage remember that they're signed in when the user refreshes the page, or leaves the site and comes back.
Using Chrome's developer tools, I can see that there's an entry for https://accounts.google.com under both Local Storage and Session Storage. They seem to more or less contain the same information, including the user's validated token.
What I don't understand is how to get the gapi.auth2.init() function to recognize and use this token. The documentation doesn't seem to cover it.
<html>
<head>
<title>Login Test</title>
<script src="http://code.jquery.com/jquery-2.1.4.js"></script>
<script src="https://apis.google.com/js/platform.js?onload=renderButton" async defer></script>
</head>
<script>
var googleUser = {};
function renderButton() {
gapi.load('auth2', function(){
auth2 = gapi.auth2.init({
client_id: 'MY_CREDENTIALS.apps.googleusercontent.com',
});
attachSignin(document.getElementById('customBtn'));
});
};
function attachSignin(element) {
auth2.attachClickHandler(element, {},
function(googleUser) {
document.getElementById('name').innerText = "Signed in: " +
googleUser.getBasicProfile().getName();
}, function(error) {
alert(JSON.stringify(error, undefined, 2));
}
);
}
</script>
<body>
<div id="gSignInWrapper">
<span class="label">Sign in with:</span>
<input type="button" id="customBtn" value="Google"></input>
</div>
<p id="name"></p>
</body>
</html>
You can use listeners. This is the relevant part:
// Listen for sign-in state changes.
auth2.isSignedIn.listen(signinChanged);
// Listen for changes to current user.
auth2.currentUser.listen(userChanged);
You can also get up to date values by
var isSignedIn = auth2.isSignedIn.get();
var currentUser = auth2.currentUser.get();
To strictly detect returning users only you can do:
var auth2 = gapi.auth2.init(CONFIG);
auth2.then(function() {
// at this point initial authentication is done.
var currentUser = auth2.currentUser.get();
});
When it comes to your code I would do:
auth2 = gapi.auth2.init(CONFIG);
auth2.currentUser.listen(onUserChange);
auth2.attachClickHandler(element, {});
This way all changes in sign-in state are passed to onUserChange (this includes returning users, new sign-ins from attachClickHandler, new sign-ins from different tab).

Can I make Custom FaceBook's Light Box of "Connect with Facebook to Continue" and "This site requires that you Connect with Facebook."?

can we change text in this lightbox
want to change "This site requires that you Connect with Facebook." and "Connect with Facebook to Continue"
Not sure about doing this with the JavaScript SDK, but I know you can do it with the PHP one.
You would have to create your box you want displayed in HTML and CSS. When you generate it in your page you have the server make the action of clicking on the button direct the user to the location provided by $facebook->getLoginUrl();
This would essentially do what you want. As i said i am unsure if the same thing is accomplish-able with the JavaScript SDK.
here what i am doing
in "facebooklogin.aspx" is first page for login after login and permissions user redirect to xxx.aspx page where i am fetching user details.
-- facebooklogin.aspx
<head runat="server">
<title>FaceBook Login</title>
<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US"
type="text/javascript"></script>
<script type="text/javascript">
function fblogin()
{
//<![CDATA[
//Replace API key with yours from Facebook
var api_key = 'XXX';
var channel_path = 'xd_receiver.htm';
FB_RequireFeatures(["XFBML"], function() {
// Create an ApiClient object, passing app's API key and
// a site relative URL to xd_receiver.htm
FB.Facebook.init(api_key, channel_path);
FB.ensureInit(function() {
FB.Connect.showPermissionDialog("email,user_birthday,user_location", function(perms) {
if (!perms) {
//alert("No");
} else {
//alert("yes");
window.location ="http://xxx.aspx"
}
});
});
});
//]]>
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div id="divbtnfb">
<a onclick="javascript:fblogin();">login</a>
</div>
</form>
</body>
--CODE BEHIND in XXX.aspx
protected void Page_Load(object sender, System.EventArgs e)
{
if (ConnectAuthentication.isConnected())
{
//Create instance of REST api using current authanticated session
Api api = new Api(CurrentSession);
//Display user data captured from the Facebook API.
try
{
Facebook.Schema.user user = api.Users.GetInfo();
firstName.Text = user.first_name;
lastName.Text = user.last_name;
//for email use client code
}
catch
{
Response.Redirect("facebooklogin.aspx");
}
}
else
{
Response.Redirect("facebooklogin.aspx");
}
}
-- In facebooklogin.aspx its checking for permission, if user is not loggedin to facebook this script shows this lightbox.
I want to change this lightbox