PowerBI Tile issue IOS - javascript

I'm using PowerBI REST to make an iOS App. Image below shows the result. When I click on any of the tiles I get no response, while if I click ON the red border (added in photoshop) Page respond to the click only if the tile includes a map, other tiles still no response.
Running the same page in a browser on Mac everything works, but on an iOS device it doesn't.
HTML Code:
<html>
<head>
<meta name="viewport" content="initial-scale=1.0" />
<script type="text/javascript">
// listen for message to receive tile click messages.
if (window.addEventListener) {
window.addEventListener("message", receiveMessage, false);
} else {
window.attachEvent("onmessage", receiveMessage);
}
//The embedded tile posts messages for clicks to parent window. Listen and handle as appropriate
function receiveMessage(event) {
messageData = JSON.parse(event.data);
if (messageData.event == "tileClicked"){
window.webkit.messageHandlers.callbackHandler.postMessage(messageData.navigationUrl.toString());
}
}
function updateEmbedReport() {
var w = window.innerWidth - 25;
var h = window.innerHeight;
// check if the embed url was selected
var embedUrl = "";
var iframe = document.getElementById('iframe1');
iframe.src = embedUrl;
iframe.onload = postActionLoadReport;
iframe.height = h;
iframe.width = w;
}
function postActionLoadReport() {
// get the access token.
accessToken = ;
var w = window.innerWidth - 25;
var h = window.innerHeight;
// construct the post message structure
var m = { action: "loadTile", accessToken: accessToken, height: h, width: w};
message = JSON.stringify(m);
// push the message.
iframe = document.getElementById('iframe1');
iframe.contentWindow.postMessage(message, "*");
iframe.height = h;
iframe.width = w;
}
</script>
</head>
<body onload="updateEmbedReport()">
<iframe id="iframe1" width="250px" frameBorder="0" name="iframe1" height="250px" style="cursor:pointer"/>
</body>
</html>
Swift code (which I use to make the app respond to tile click)
private var mWebView: WKWebView?
override func awakeFromNib() {
super.awakeFromNib()
let mWebViewConfig: WKWebViewConfiguration = WKWebViewConfiguration()
mWebViewConfig.userContentController.addScriptMessageHandler(self, name: "callbackHandler")
mWebViewConfig.preferences.javaScriptEnabled = true
mWebViewConfig.preferences.javaScriptCanOpenWindowsAutomatically = true
self.mWebView = WKWebView(frame: self.frame, configuration: mWebViewConfig)
//self.mWebView!.scrollView.scrollEnabled = false
self.addSubview(self.mWebView!)
}
func setData(url: String, tileClick: ITileClick){
self.mTileClick = tileClick
let page: String = (InstanceReferences.mPowerBIHandler?.GetPage(InstanceReferences.mAuthenticationToken!, EmbedURL: url, ReportPage: false))!
self.mWebView?.loadHTMLString(page, baseURL: NSURL(string: url)!)
}
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
print("iniside")
if message.name == "callbackHandler" {
self.mTileClick?.OnTilePageClick("\(message.body)")
} }
Note: Used the same HTML page in android app and everything is working without issues.
Any help would be great.

Have you been able to use any of the drill down options using the Power BI App on iphone?

There seems to be a bug in the embedded page which prevents it from detecting iOS taps. I believe you won't be able to solve this on your end due to cross-domain restrictions.
You can workaround this problem by saving the navigation URL provided to you by the tileLoaded event (fired on tile load), and detecting taps in iOS (Using a gesture recognizer on the WKWebView).

Related

How to manage Activex events in JS without Object tag

Hi im developing activex control to manage webcam in IE, everything works but i need to refresh the image when a new frame is captures, up to now i display images on click, but i want to listen "Captured frame event" in JS to refresh my html view.
I have seen a lot of samples but all of these are using Object tag in html
<object id="Control" classid="CLSID:id"/>
<script for="Control" event="myEvent()">
alert("hello");
</script>
is there a way to listen activex events using pure JS? using :
Ob = new ActivexObject('PROG.ID');
No, it's not working in purly JavaScript you can only use JScript.
JScript only works in Internet Explorer and there it only works, if the user confirms to execute the scripts, ussualy you use it in an .hta Hyper Text (Markup Language) Application
Example:
<script language="JScript">
"use strict";
function openFile(strFileName) {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f = fso.OpenTextFile(strFileName, 1);
if (f.AtEndOfStream) {
return;
}
var file = f.ReadAll();
f.close();
return file;
}
function writeFile(filename, content) {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f = fso.OpenTextFile(filename, 2, true);
f.Write(content);
f.Close();
}
</script>
<script language="javascript">
"use strict";
var native_db;
function init() {
var file = openFile("./Natives.json");
native_db = JSON.parse(file);
displayNamespaces();
};
I also would have as alternate an example how it works in modern Browsers, if it helps you out there:
<video id="webcam"></video>
<input type="button" value="activate webcam" onclick="test()">
<script>
function test() {
navigator.mediaDevices.getUserMedia({video: true, audio: true}).then((stream) => { // get access to webcam
const videoElement = document.getElementById('webcam');
videoElement.srcObject = stream; // set our stream, to the video element
videoElement.play();
// This creates a Screenshot on click, as you mentioned
videoElement.addEventListener('click', function(event) {
const canvas = document.createElement('canvas');
canvas.width = videoElement.videoWidth;
canvas.height = videoElement.videoHeight;
const context = canvas.getContext('2d');
context.drawImage(videoElement, 0, 0, videoElement.videoWidth, videoElement.videoHeight);
// you could just do this, to display the canvas:
// document.body.appendChild(canvas);
canvas.toBlob(function (blob) { // we automatlicly download the screenshot
const a = document.createElement('a');
a.href = URL.createObjectURL(blob); // creates a Datastream Handle Link in your Browser
a.download = 'screenshot.png'; // the name we have to define here now, since it will not use the url name
document.body.appendChild(a); // some Browsers don't like operating with Events of Objects which aren't on DOM
setTimeout(function() { // so we timeout a ms
a.click(); // trigger the download
URL.revokeObjectURL(a.href); // release the Handle
document.body.removeChild(a); // remove the element again
}, 1);
});
});
}).catch(console.error);
}
</script>
I ended up using timer, when i click enable button in the view i call the method startRecord, in this method i read Activex value every 70 ms, I would rather not use timer but it works.
private async startRecord() {
while (this.banCapturing) {
await new Promise(res => setTimeout(res, 70)); //14 ~ 15 fps
this.foto = this.Ob.imageBase64; //Read Activex Value, DLL is updating imageBase64 on camera event.
}
}

Iframe fetching the full screen method from iframe source

I try to create a one liner iframe that users can add in their sites and this iframe adress is my site.
My problem is that if i want it to be able to become full screen i need to supply them with js code and i don't want it i want it to fetch the js code from my site.
The js that i use to make full screen when needed is :
<script>
window.addEventListener('message', receiveMessage, false);
function receiveMessage(evt) {
if (evt.origin === 'site src') {
//if (isNaN(evt.data)) return;
var iframe = document.getElementById('someId');
if (event.data.height !== 0) {
iframe.height = 100 + "%";
iframe.width = 100 + "%";
iframe.style.position = 'fixed';
iframe.style.top = '2%';
iframe.style.left = '2%';
}
else {
iframe.height = 110 + "px";
iframe.width = 300 + "px";
iframe.style.position = 'relative';
}
}
}
</script>
This script currently written at the client the one that use the iframe.
The iframe looks like.
<iframe id="expertips_iframe" src="my site adress" width="300px" height="110px" frameBorder="0" scrolling="no"></iframe>
I want the iframe line to fetch the js code from my site and inject it to the user/client that use the iframe, or any other way as long as i do it (the iframe and the js) in one line.
Hope it is clear enough and thank you.

How to resize Webview height based on HTML content in Windows 10 UWP?

I am currently working on Windows 10 UWP App and facing an issue with WebView that when I have less HTML content, I am getting more height in javascript. My Code is as follows
WebView webView = new WebView() { IsHitTestVisible = true };
string notifyJS = #"<script type='text/javascript' language='javascript'>
function setupBrowser(){
document.touchmove=function(){return false;};;
document.onmousemove=function(){return false;};
document.onselectstart=function(){return false;};
document.ondragstart=function(){return false;}
window.external.notify('ContentHeight:'+document.body.firstChild.offsetHeight);
//window.external.notify('ContentHeight:'+document.getElementById('pageWrapper').offsetHeight);
var links = document.getElementsByTagName('a');
for(var i=0;i<links.length;i++) {
links[i].onclick = function() {
window.external.notify(this.href);
return false;
}
}
}
</script>";
string htmlContent;
if (hexcolor != null)
{
htmlContent = string.Format("<html><head>{0}</head>" +
"<body onLoad=\"setupBrowser()\" style=\"margin:0px;padding:0px;background-color:{2};\">" +
"<div id=\"pageWrapper\" style=\"width:100%;word-wrap:break-word;padding:0px 25px 0px 25px\">{1}</div></body></html>",
notifyJS,
formItem.I_DEFAULT_VALUE,
hexcolor);
}
Here formItem.I_DEFAULT_VALUE is
HTML without html,head and body tags and its value is
<p>
<span style="font-size: 14px;">To help us investigate your query please can you make a sheet using the following </span>document<span style="font-size: 14px;">.</span></p>
<p>
<strong><span style="font-size: 14px;">Testing WebView Height</span></strong></p>
HexColor is background color that needs to be applied.
And my script_notify method is as follows:
webView.ScriptNotify += async (sender, e) =>
{
if (e.Value.StartsWith("ContentHeight"))
{
(sender as WebView).Height = Convert.ToDouble(e.Value.Split(':')[1]);
return;
}
if (!string.IsNullOrEmpty(e.Value))
{
string href = e.Value.ToLower();
if (href.StartsWith("mailto:"))
{
LauncherOptions options = new LauncherOptions();
options.DisplayApplicationPicker = true;
options.TreatAsUntrusted = true;
var success = await Launcher.LaunchUriAsync(new Uri(e.Value), options);
}
else if (href.StartsWith("tel:"))
{
LauncherOptions options = new LauncherOptions();
options.DisplayApplicationPicker = true;
options.TreatAsUntrusted = true;
var success = await Launcher.LaunchUriAsync(new Uri(e.Value), options);
}
else
{
LauncherOptions options = new LauncherOptions();
options.DisplayApplicationPicker = true;
options.TreatAsUntrusted = true;
var success = await Launcher.LaunchUriAsync(new Uri(e.Value), options);
}
}
};
Can someone suggest why I am getting very large height even if content is small?
you could try to parse the string "document.body.scrollHeight.toString()" after your content loads in order to set a new height for your webview.
Here's an example with NavigationCompleted but you could use a custom event
public static class WebViewExtensions
{
public static void ResizeToContent(this WebView webView)
{
var heightString = webView.InvokeScript("eval", new[] {"document.body.scrollHeight.toString()" });
int height;
if (int.TryParse(heightString, out height))
{
webView.Height = height;
}
}
}
public Page()
{
MyWebView.NavigationCompleted += (sender, args) => sender.ResizeToContent();
MyWebView.Navigate(new Uri("index.html"));
}
I'm not sure why you are getting a value that is too high, I faced a slightly different issue: the height of the document I got was too small (the height did seemingly not account for images). I have tried multiple events (NavigationFinished, LoadCompleted, ...) but in none of these events I was able to get an accurate height.
What finally worked for me was waiting for a short period until I send back the height of the document. Not exactly a great solution, I hope I will be able to simplify this at some point. Perhaps this also works for your issue.
I inject a script that waits for 100 miliseconds and then sends it back. Even if the image wasn't fully loaded yet, the content size was accurate for me.
window.setTimeout(function () {
var height = document.body.scrollHeight.toString();
window.external.notify("ContentHeight:" + height);
}, 100);

how to save a picture taken with window.getusermedia in js

Currently i am working on a open webapp camera, right now i have implemented the camera setup(live stream as viewport, take picture button, capture, display taken picture in corner... etc) but now i am running into the issue of how to save that picture for the user to their device or computer, this app is currently being designed for mobile b2g primarily. I know most people are gonna tell me security issues!!! i dont mean tell the device exactly where to put it. I mean something like
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script type="text/javascript">
window.onload = function () {
var img = document.getElementById('embedImage');
var button = document.getElementById('saveImage');
img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA'+
'AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO'+
'9TXL0Y4OHwAAAABJRU5ErkJggg==';
img.onload = function () {
button.removeAttribute('disabled');
};
button.onclick = function () {
window.location.href = img.src.replace('image/png', 'image/octet-stream');
};
};
</script>
</head>
<body>
<img id="embedImage" alt="Red dot"/>
<input id="saveImage" type="button" value="save image" disabled="disabled"/>
</body>
</html>
that specific code executed on mobile triggers the file to automatically be saved on click of the button. now what i want to do is use that to take my picture from its var its in and save it as that file, for example that will be in downloads folder.
this is what my code is currently https://github.com/1Jamie/1Jamie.github.io
any help would be appreciated and this is the current running implementation if you want to take a working look http://1Jamie.github.io
This worked for me when I was playing around with getUserMedia - I did notice that you did not have the name of the method in the proper case and it is a method of the navigator.mediaDevices interface - not a method of the window directly...
References:
[Navigator for mozilla]https://developer.mozilla.org/en-US/docs/Mozilla/B2G_OS/API/Navigator
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices
[mediaDevices for chrome and android]https://developers.google.com/web/updates/2015/10/media-devices?hl=en
var video = document.getElementById('monitor');
var canvas1 = document.getElementById('photo1');
var img1 = document.getElementById('canvasImg');
navigator.mediaDevices.getUserMedia({
video: true
}).then(function (stream) {
video.srcObject = stream;
video.onloadedmetadata = function () {
canvas1.width = video.videoWidth;
canvas1.height = video.videoHeight;
document.getElementById('splash').hidden = true;
document.getElementById('app').hidden = false;
};
}).catch(function (reason) {
document.getElementById('errorMessage').textContent = 'No camera available.';
});
function snapshot1() {
canvas1.getContext('2d').drawImage(video, 0, 0);
}
"save_snap" is the id of a button - Disclaimer I am using jQuery- but you should easily see where this corresponds to your code:
$("#save_snap").click(function (event){
// save canvas image as data url (png format by default)
var dataURL = canvas2.toDataURL();
// set canvasImg image src to dataURL
// so it can be saved as an image
$('#canvasImg').attr("src" , dataURL);
$('#downloader').attr("download" , "download.png");
$('#downloader').attr("href" , dataURL);
//* trying to force download - jQuery trigger does not apply
//Use CustomEvent Vanilla js: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent
// In particular
var event1 = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': true
});
//NOW we are effectively clicking the element with the href attribute:
//Could use jQuery selector but then we would have to unwrap it
// to expose it to the native js function...
document.getElementById('downloader').dispatchEvent(event1);
});

Canvas not displaying on mobile devices

HTML5 canvas (only using the drawImage function) is not showing up on mobile devices, but is on my laptop.
You can see here : mmhudson.com/index.html (reload once)
I get no errors or anything, but it doesn't display in chrome on iOS or the default browser on android..
EDIT:
This problem only occurs when the following meta tag is included in the document:
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
Your init() function is called by imgLoad(), but you're loading images only when the window width is greater than or equal to 480px:
window.onload = function(){
s.dL = true;
s.width = window.innerWidth;
s.height = window.innerHeight;
if(s.width < 320){
//too small
}
else if(s.width >= 320 && s.width < 480){
s.scWidth = 296;
}
else{
s.scWidth = 456;
b_border.src = "res/480/b_border.png";
r_border.src = "res/480/r_border.png";
l_border.src = "res/480/l_border.png";
t_border.src = "res/480/t_border.png";
br_corner.src = "res/480/br_corner.png";
tr_corner.src = "res/480/tr_corner.png";
bl_corner.src = "res/480/bl_corner.png";
tl_corner.src = "res/480/tl_corner.png";
h_wall.src = "res/480/h_wall.png";
v_wall.src = "res/480/v_wall.png";
box.src = "res/480/box.png";
crosshair.src = "res/480/crosshair.png";
player1.src = "res/480/player1.png";
player2.src = "res/480/player2.png";
}
}
When you omit the meta viewport tag, the browser assumes a page / window width of 980px, and so your code runs normally.
When you include a meta viewport tag with width=device-width, the browser sets the page / window width to the width of the screen (e.g. 320px on iPhone), and so imgLoad() and init() is never called.
It looks like you are trying to draw the images before they have loaded. I'm not sure why the mobile browsers would fail more often, possibly they are slower to load them all in?
In fact, when i open your page on my desktop, sometimes the canvas does not draw, but if I open the console and enter draw() it appears (because by then the images have loaded).
If you were dealing with just a single image, the simplified code would be:
var img = new Image();
img.onload = function(){
// drawing code goes here
}
img.src = 'myfile.png';
But because of the large number of images you have here, I would look into a resource loading library of some sort.

Categories

Resources