deviceorientation event not called on ios safari - javascript

<button onclick="test()">click here</button>
<script>
function test(){
DeviceOrientationEvent.requestPermission()
.then(response => {
if (response == 'granted') {
console.log("granted good");
window.addEventListener('deviceorientation', (e) => {
// do something with e
console.log("device orientation changed ", e);
})
}
}).catch(err => {
console.log("Err ", err);
})
}
</script>
I have this code. It seems like ios safari asks me for permission which then i grant it. So it logs granted good as shown in the if statement. The problem is if I change device orientation, event doesn't get called so no logs appear.
Any idea why ? I am using https: protocol. So not sure anymore what's going on.

Related

javascript ndefREADER doesn't load automatically

First of all, I have to say this is my first question on stack ;)
I am trying to implement a reading via NFC on my test web, but i dunno why, the ndefReader doesn't works on startup, i have to press any field on the web to get it loaded (or asked for permission).
BUT, if i wrote some alerts to check why it doen't reach the function on startup, it works!!! (of course, it show alerts before). I don't know if when I accept the alert, I am interacting with the web and that's why it works, but anyways, I dunno why this happens (I need to click anywhere before starting).
function iniciar() {
document.getElementById("input1").focus();
//alert("test before"); <--- IF i remove this, it doesnt works
document.getElementById("input1").addEventListener("blur", async () => {
try{
const ndef = new NDEFReader();
alert("before wait");
await ndef.scan();
alert("after wait");
ndef.addEventListener("readingerror", () => {
alert("Argh! Cannot read data from the NFC tag. Try another one?");
});
ndef.addEventListener("reading", ({ message, serialNumber }) => {
alert(`> Serial Number: ${serialNumber}`);
alert(`> Records: (${message.records.length})`);
});
} catch (error) {
alert("Argh! " + error);
}
},false);
To scan and write to NFC tags, you must first request the "nfc" permission while handling a user gesture (e.g a button click, or in your case the "alert" call). Once handled, the NDEFReader scan() and write() methods trigger a user prompt, if access was not previously granted.
Check out https://web.dev/nfc/#security-and-permissions to learn more.
Hopefully https://googlechrome.github.io/samples/web-nfc/ samples should help you as well.
scanButton.addEventListener("click", async () => {
console.log("User clicked scan button");
try {
const ndef = new NDEFReader();
await ndef.scan();
console.log("> Scan started");
ndef.addEventListener("readingerror", () => {
console.log("Argh! Cannot read data from the NFC tag. Try another one?");
});
ndef.addEventListener("reading", ({ message, serialNumber }) => {
console.log(`> Serial Number: ${serialNumber}`);
console.log(`> Records: (${message.records.length})`);
});
} catch (error) {
console.log("Argh! " + error);
}
});

How to show custom page loading error when "No Internet Available"?

I want to generate a custom error page when there's No internet available in a website just like https://m.apkpure.com and page will load again on refresh when internet is available. I know we can use the following code to check "ONLINE" or "OFFLINE"
window.addEventListener("online", function() {
alert("You're ONLINE!");
});
window.addEventListener("offline", function() {
alert("You're OFFLINE!");
});
// OR
if (navigator.onLine) {
console.log("You are online");
} else {
console.log("You are offline");
}
But I dont think that the https://m.apkpure.com use the above kind of code to detect ONLINE or OFFLINE. If there's any other way to do so please let me know.
After a little digging through the source code...
In sw.js on the website you were talking about(https://m.apkpure.com):
self.addEventListener('fetch', (event) => {
if (!self.navigator.onLine) {
event.respondWith(
caches.match(event.request).then((response) => {
return caches.match('/offline.html')
})
)
}
})
So yeah, they do use navigator.onLine.

How do I get DeviceOrientationEvent and DeviceMotionEvent to work on Safari?

I'm trying to implement DeviceOrientationEvent and DeviceMotionEvent on my website for a 3D effect. However, the console doesn't log any info and apparently iOS 13 requires a user set permission to start doing this. I can't seem to figure out how to set it up properly.
I've done some research and this is what I found: https://github.com/w3c/deviceorientation/issues/57#issuecomment-498417027
All other methods provided online are not usable anymore sadly.
window.addEventListener('deviceorientation', function(event) {
console.log(event.alpha + ' : ' + event.beta + ' : ' + event.gamma);
});
I get the following error message:
[Warning] No device motion or orientation events will be fired until permission has been requested and granted.
As of iOS 13 beta 2, you need to call DeviceOrientationEvent.requestPermission() to access to gyroscope or accelerometer. This will present a permission dialog prompting the user to allow motion and orientation access for this site.
Note that this will not work if you try to call it automatically when the page loads. The user needs to take some action (like tapping a button) to be able to display the dialog.
Also, the current implementation seems to require that the site have https enabled.
For more information, see this page
if ( location.protocol != "https:" ) {
location.href = "https:" + window.location.href.substring( window.location.protocol.length );
}
function permission () {
if ( typeof( DeviceMotionEvent ) !== "undefined" && typeof( DeviceMotionEvent.requestPermission ) === "function" ) {
// (optional) Do something before API request prompt.
DeviceMotionEvent.requestPermission()
.then( response => {
// (optional) Do something after API prompt dismissed.
if ( response == "granted" ) {
window.addEventListener( "devicemotion", (e) => {
// do something for 'e' here.
})
}
})
.catch( console.error )
} else {
alert( "DeviceMotionEvent is not defined" );
}
}
const btn = document.getElementById( "request" );
btn.addEventListener( "click", permission );
Use an element on your page to use as the event trigger and give it an id of "request".
This will check for https and change it if required before requesting API authorization.
Found this yesterday but do not remember the URL.
You need a click or a user gesture to call the requestPermission().
Like this :
<script type="text/javascript">
function requestOrientationPermission(){
DeviceOrientationEvent.requestPermission()
.then(response => {
if (response == 'granted') {
window.addEventListener('deviceorientation', (e) => {
// do something with e
})
}
})
.catch(console.error)
}
</script>
<button onclick='requestOrientationPermission();'>Request orientation permission</button>
Note : if you click on cancel on the permission prompt and want to test it again, you will need to quit Safari and launch it back for the prompt to come back.
On Xamarin iOS (Xamarin.Forms) you can inject the permission request script with the EvaluateJavaScript method on the WkWebView when it is ready:
webView.EvaluateJavaScript("DeviceMotionEvent.requestPermission().then(response => { if (response == 'granted') {window.addEventListener('devicemotion', (e) => {})}}).catch(console.error)");
If using a custom WkWebView renderer (must implement IWKUIDelegate if this bug is still around https://bugs.webkit.org/show_bug.cgi?id=203287) the script can be injected when setting the webView control in OnElementChanged
Example:
// do this when setting up the webview control in OnElementChanged
//enable device motion sensors permission script:
//https://medium.com/flawless-app-stories/how-to-request-device-motion-and-orientation-permission-in-ios-13-74fc9d6cd140
var source =
"function requestSensorPermission() {" +
" if (typeof(DeviceMotionEvent) !== 'undefined' && typeof(DeviceMotionEvent.requestPermission) === 'function') {" +
" DeviceMotionEvent.requestPermission() .then(response => {" +
" if (response == 'granted') { " +
" window.addEventListener('devicemotion', (e) => { })" +
" }" +
" }).catch(console.error)" +
" }" +
"}";
var script = new WKUserScript(new NSString(source), WKUserScriptInjectionTime.AtDocumentEnd, true);
wkWebView.Configuration.UserContentController.AddUserScript(script);
Then you can call yourCustomWebView.EvaluateJavaScript("requestSensorPermission()") in your code behind when yourCustomWebView is ready.
EvaluateJavaScript:
https://learn.microsoft.com/en-us/dotnet/api/webkit.wkwebview.evaluatejavascript?view=xamarin-ios-sdk-12
Custom WkWebView Renderer: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/hybridwebview#create-the-custom-renderer-on-ios
This is not really an answer, but something to consider if using DeviceMotion on WKWebView.
On Xcode 13 you can use this new WKUIDelegate. You'll still need to request the permission as the other answers mention, but it will not prompt the user for the permission, will directly grant it.
#available(iOS 15, *)
func webView(_ webView: WKWebView,
requestDeviceOrientationAndMotionPermissionFor origin: WKSecurityOrigin,
initiatedByFrame frame: WKFrameInfo,
decisionHandler: #escaping (WKPermissionDecision) -> Void) {
decisionHandler(.grant)
}

jQuery on Button Click in mobile devices

I have a Button
d3.select("#updatebutton").on("click", function(e) {
try{
$.get('any url', function(data) {
alert('Any Alert Message');
window.location.href = window.location.href;
});
}
catch (e) {
alert('Error: ' + e);
}
}
where i want to do certain actions on the button click event:
app.get('any url', function(req, res, next) {
try{
anyfunction();
}
catch(e) {
alert('Error');
}
});
It is working fine on normal web browser, however if I open my webpage on a mobile device, it seems that the click event is never called and nothing happens. Is this a jQuery Problem or am I missing something?
The Code is running on a node.js Server.
Hope anyone can help.
UPDATE:
I'm using jade as rendering-engine for HTML. My Button looks like the following:
div#updatebutton
i.fa.fa-repeat.fa-lg
| 'some description'
Try with touchstart event.
UPDATE
Please check.
var myButton = d3.select("#updatebutton");
myButton.on("touchstart", onDown);
function onDown() {
alert("Work");
try{
$.get('any url', function(data) {
alert('Any Alert Message');
window.location.href = window.location.href;
});
}
catch (e) {
alert('Error: ' + e);
}
}
You can detect user device using navigator object. Refer this
If device is touch enabled then use touchstart/touchend events or use click events for desktops(click events should work in mobile browsers too, can not guess the reason by going through the provided code)
Try this:
function is_touch_device() {
return (('ontouchstart' in window) || (navigator.MaxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0));
}
var myButton = d3.select("#updatebutton");
var myEvent = is_touch_device() ? 'touchend' : 'click';
myButton.on(myEvent, onDown);
function onDown() {
$.get('any url', function(data) {
alert('Any Alert Message');
window.location.reload(); //better way to reload the page
}).fail(function(error) {
console.log(error);
});
}

Check if user has webcam or not using JavaScript only?

Is it possible to figure out whether a user has a webcam or not using only JavaScript? I don't want to use any plugin for this.
You don't necessarily need to get the permission to know if the user has a webcam, you can check it with enumerateDevices:
function detectWebcam(callback) {
let md = navigator.mediaDevices;
if (!md || !md.enumerateDevices) return callback(false);
md.enumerateDevices().then(devices => {
callback(devices.some(device => 'videoinput' === device.kind));
})
}
detectWebcam(function(hasWebcam) {
console.log('Webcam: ' + (hasWebcam ? 'yes' : 'no'));
})
You can use a new HTML5 API to check if they give you permission to use the webcam. After all, if they deny permission, they might as well not have a webcam, from the code's perspective.
See navigator.getUserMedia().
EDIT:
navigator.getMedia = ( navigator.getUserMedia || // use the proper vendor prefix
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
navigator.getMedia({video: true}, function() {
// webcam is available
}, function() {
// webcam is not available
});
You can check if the user has a webcam using this plugin: http://www.xarg.org/project/jquery-webcam-plugin/
if(webcam.getCameraList().length == 0){
alert('You don\'t have a web camera');
}
Taken from here: How can I check if user has a webcam or not?
Edit: I see you updated your question to say that you don't want to use a plugin. In this case, you could try using the getUserMedia API:
function success(stream){
// The success function receives an argument which points to the webcam stream
document.getElementById('myVideo').src = stream;
}
function error(){
alert("No webcam for you, matey!");
}
if (navigator.getUserMedia) {
navigator.getUserMedia({video:true, audio:false}, success, error);
} else {
error();
}
Source: http://www.iandevlin.com/blog/2012/06/html5/filtering-a-webcam-using-getusermedia-and-html5-canvas
There is NO way you can read current browser settings.
the only thing we can do is try to access the webcam/microphone and see if we are able to access that device like...
navigator.getMedia({video: true}, function() {
// webcam is available
}, function() {
// webcam is not available
});
BUT **** One important thing to note here, if you follow this approach then be aware that ....
Also please note that, you have to use HTTPS to use webcam/microphone and it will prompt you the browser specific permission popup with allow and block buttons ONLY ONCE, you will NOT see this permission popup again as HTTPS save the permission.
The only way to get this permission popup again is to:
Clear your cache and
Reset the browser settings
Open a new instance of the browser.
FYI ... You cannot manipulate browser specific setting using JavaScript
So don't event go that way, unless you have time to kill
Navigator.getUserMedia() is being depreciated as of 2019. To access webcam, use MediaDevices.getUserMedia() instead.
Note that navigator.mediaDevices will return undefined if the current document isn't loaded securely. URLs served from localhost are usually OK.
Sample code to test for and access webcam:
const constraints = {
audio: false,
video: { width: 1280, height: 720 },
};
if (!navigator.mediaDevices) {
console.log("Document not secure. Unable to capture WebCam.");
} else {
navigator.mediaDevices
.getUserMedia(constraints)
.then(function(stream) {
//show webcam stream
let videoIn = document.createElement("video");
videoIn.autoplay = true;
document.body.appendChild(videoIn);
videoIn.srcObject = stream;
})
.catch(function(err) {
console.log("Unable to capture WebCam.", err);
});
}
While here, and inspired by other answers, as part of an implementation I'm working on I am using the following function to return a boolean checking for an active stream.
The project is a little old, hence jQuery and ES5, though hope this can prove useful to someone:
function() {
var deferred = $.Deferred();
navigator.mediaDevices.getUserMedia(VIDEO_CONSTRAINTS)
.then(function(stream) { deferred.resolve(stream.active); })
.catch(function() { deferred.resolve(false) })
return deferred.promise()
}
This can then be used as follows:
checkStreamActive()
.then(function(activeStream) {
if(activeStream) {
// do something
} else {
// do something else
}
})
async function detectWebcam() {
try {
var md = navigator.mediaDevices;
var results = false;
if (!md || !md.enumerateDevices) results = false;
const devices = await md.enumerateDevices();
results = devices.some(device => 'videoinput' === device.kind);
return results;
} catch (error) { return false; }
}
strong textTry this code to check whether the device has webcam or not by javascript alertcheck this image
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
webcam_check_func();
});
function webcam_check_func() {
var hasWebcam = false;
var device = [];
if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
navigator.enumerateDevices = function (callback) {
navigator.mediaDevices.enumerateDevices().then(callback);
};
navigator.enumerateDevices(function (devices) {
devices.forEach(function (my_device) {
if (my_device.kind === 'videoinput') {
debugger;
hasWebcam = true;
}
}
);
alert("Has Web Camera -->" + hasWebcam);
});
}
}
</script>
</head>
<body>
</body>
</html>

Categories