Hit an issue with our mobile app (home screen safari app) in that it started reporting since iOS 13 that there was no html5 database support.
It tries to detect support for WebSQL with the following code:
function getDBType() {
if (typeof window.openDatabase == "function") {
return "WebSQL";
}
return "IndexedDB";
}
Unfortunately this is reporting that, despite WebSQL being removed from Safari 13, WebSQL is available, only to fall over with an exception later when it tries to call window.openDatabase().
On closer inspection it seems that something weird is happening:
(typeof window.openDatabase == "function") == true
(typeof window.openDatabase == "undefined") == true
(typeof window.openDatabase == "randomstring") == false
window.openDatabase == [object Function] /* not native function */
Test Page: http://locutus.sorcerer.co.uk/demo/safari-openDatabase.html
So the question is, how to properly test for WebSQL support that will work on safari 13?
One thought is to do the following to detect Safari 13's lack of support (with comment explaining the seeming pointless test)
if (typeof window.openDatabase == "function" && typeof window.openDatabase != "undefined") {
return "WebSQL";
}
Side Note: It is possible to enable WebSQL in Safari 13 on iOS is settings, Safari -> Advanced -> Experimental Features -> disable the 'Disable WebSQL' option. Only works in Safari app though, home screen safari apps still don't get WebSQL support.
Our code uses if (!window.openDatabase) throw 'No WebSQL support'; and that seems to be enough to detect the disabled setting on iOS13
Related
I am trying to detect if a client is an iPad, and to do that I'm trying to use window.navigator.platform and window.navigator.maxTouchPoints.
I'm trying to do this from Vue, by setting it as a computed property.
One device I have to test this with is an MDM-device, an iPad running the latest iOS and using Safari as the browser.
This is my computed property:
// ...
computed: {
isIpad() {
return navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 0;
}
}
And this is the view:
<div class="feature">
<div v-if="isIpad" class="feature-desktop">This feature is only available on desktops.</div>
</div>
In my vue-inspector on MacOS/Firefox the computed property is correct, returning false as expected. When I try to emulate an iPad through Firefox, it returns true, as expected. However, if I open the page using Safari on my MDM-enabled iPad, this property returns false.
Sadly, I cannot connect with developer tools as the iPad is locked down, but I can manually put javascript on the page to print out the result of both navigator.platform and navigator.maxTouchPoints, and they return the expected MacIntel platform and 5 touch points.
<script type="application/javascript">
document.getElementById('app').innerHTML = navigator.platform + ' ' + navigator.maxTouchPoints; // Prints MacIntel and 5
</script>
Does anyone have any experience with this sort of thing? I've yet to attempt setting a data-property with mounted().
Using the mounted event handler to set a data-property solved my problem.
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
createPopup(this);
}
else if (this.status == 404) {
alert("file not found from load");
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
Hi, I am learning about html and css and now javaScript with Dom.
I am trying to parse xml file and know that I have to use XMLHttpRequest to get the data.
To make exception handling such as "there is no file", "xml has fault(wrong xml)", I am trying to use the XMLHttpRequest's member variables "readyStatus", "status" to figure out what status of the result.
If there is another way to deal with this problem, let me know..
First, the chrome doesn't give the "status" value whereas the firefox give with same code. but it is limited to give status == 200 when the file exist regardless of file's status(wrong or not), do you know why?
Second, How can I see "status == 404" using status, could you tell me when it occur?
"Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/" ... This appear in the alert of the Chrome Console...I have the same problem...
I noticed cordovaInitCallback is called each time Worklight/Cordova is initialized in an Android app. In particular, it calls Cordova's "clearHistory" to wipe out the WebView history. This has been an issue when I try to make use of window.history in a multi-page app since the history is always reset during the initializtion from page to page.
Since the comment suggests that the purpose for this clearHistory call is to prevent going back to an old page in a direct update scenario, could the condition be strengthened over an Android environment check so that it is only called if a direct update has just taken place? One case, for example, I can think of is when connectOnStartup=false, then direct update would not occur.
wlclient.js:
var cordovaInitCallback = function(returnedData) {
onEnvInit(options);
if (WL.Client.getEnvironment() == WL.Env.ANDROID) {
if (returnedData !== null && returnedData !== "") {
WL.StaticAppProps.APP_VERSION = returnedData;
}
// In development mode, the application has a settings
// widget in which the user may alter
// the application's root url
// and here the application reads this url, and replaces the
// static prop
// WL.StaticAppProps.WORKLIGHT_ROOT_URL
// __setWLServerAddress for iOS is called within
// wlgap.ios.js's wlCheckReachability
// function because it is an asynchronous call.
// Only in Android we should clear the history of the
// WebView, otherwise when user will
// press the back button after upgrade he will return to the
// html page before the upgrade
if (**WL.Env.ANDROID == getEnv()**) {
cordova.exec(null, null, 'Utils', 'clearHistory', []);
}
}
I am currently using Worklight 5.0.5, and have checked this same condition exists in 5.0.5.1.
Thanks!
The architectural design of Worklight is SPA (Single Page Application).
cordovaInitCallback should be called only once in the life cycle of the application.
That said, you can, if you wish, override it.
Fancybox 2 uses this code
isTouch = document.createTouch !== undefined
to determine if the browser is a touch device. This seems to be a problem with QTWebKit because this function exists. Another way also fails because this attribute is null instead of undefined:
document.documentElement.ontouchstart
So I checked for both
isTouch = document.createTouch !== undefined && document.documentElement.ontouchstart != null
Or is there another solution?
I have been using
window.isTouch = !!('ontouchstart' in window && window.ontouchstart != null);
This works in QtWebkit and in Chrome's Webkit. I have not done further browser testing.
I'm sure I'm just overlooking this question but I cant seem to find how to check the device.
I want to check whether the device is either a phone, a tablet in landscape mode, a tablet in portrait mode or a other device (computer).
What I have is this:
if (Ext.platform.isPhone) {
console.log("phone");
}
if (Ext.platform.isTablet) {
console.log("tablet");
}
var x = Ext.platform;
But platform is undefined (probably because this is the way of Sencha Touch 1).
Does anyone know the correct place for me to access the device check?
Sencha Environment Detection offers a large spectrum through simple means.
Instead of Ext.os.is.Tablet, you can make life easier via Ext.os.deviceType which will return:
Phone
Tablet
Desktop
NB: this value can also be fudged by adding "?deviceType=" to the url.
http://localhost/mypage.html?deviceType=Tablet
Ext.os.name is the singleton returning:
iOS
Android
webOS
BlackBerry
RIMTablet
MacOS
Windows
Linux
Bada
Other
The usual ability of browser detection is available through Ext.browser.name.
Something I've only recently encountered, which I love is feature detection - allowing coding similar to Modernizr / YepNope based off ability of device. Ext.feature offers:
Ext.feature.has.Audio
Ext.feature.has.Canvas
Ext.feature.has.ClassList
Ext.feature.has.CreateContextualFragment
Ext.feature.has.Css3dTransforms
Ext.feature.has.CssAnimations
Ext.feature.has.CssTransforms
Ext.feature.has.CssTransitions
Ext.feature.has.DeviceMotion
Ext.feature.has.Geolocation
Ext.feature.has.History
Ext.feature.has.Orientation
Ext.feature.has.OrientationChange
Ext.feature.has.Range
Ext.feature.has.SqlDatabase
Ext.feature.has.Svg
Ext.feature.has.Touch
Ext.feature.has.Video
Ext.feature.has.Vml
Ext.feature.has.WebSockets
To detect fullscreen/app/homescreen browser mode on iOS:
window.navigator.standalone == true
Orientation Ext.device.Orientation and orientation change:
Ext.device.Orientation.on({
scope: this,
orientationchange: function(e) {
console.log('Alpha: ', e.alpha);
console.log('Beta: ', e.beta);
console.log('Gamma: ', e.gamma);
}
});
Orientation is based on Viewport. I usually add a listener which is more reliable:
onOrientationChange: function(viewport, orientation, width, height) {
// test trigger and values
console.log('o:' + orientation + ' w:' + width + ' h:' + height);
if (width > height) {
orientation = 'landscape';
} else {
orientation = 'portrait';
}
// add handlers here...
}
Use Ext.env.OS's is() method.
Note that only major component and simplified value of the version are
available via direct property checking. Supported values are: iOS,
iPad, iPhone, iPod, Android, WebOS, BlackBerry, Bada, MacOS, Windows,
Linux and Other
if (Ext.os.is('Android')) { ... }
if (Ext.os.is.Android2) { ... } // Equivalent to (Ext.os.is.Android && Ext.os.version.equals(2))
if (Ext.os.is.iOS32) { ... } // Equivalent to (Ext.os.is.iOS && Ext.os.version.equals(3.2))
Alternatively, you can also use PhoneGap Device API
I found the answer to it:
What seems to be the case is that Ext.os.is.(tablet/phone or something else) is true or undefined. If it is not the case it will be undefined.
I.a. Ext.os.is.Tablet is true when on a tablet and undefined when not.
So this is the answer I was looking for
if(Ext.os.is.Tablet){
this._bIsTablet = true;
}else if(Ext.os.is.Phone){
this._bIsPhone = true;
}else{
this._bIsOther = true;
}