Can websites view Ios device name? [duplicate] - device

Is there a way to get the name of a mobile device (e.g. "John's iPhone" ) using javascript?
Maybe I wasn't very clear... what I meant is not whether it's an iPhone, iPad etc. but the "device name" - for example it can be "John's iPhone".

You can't do this through javascript for a web app running in a native browser - javascript generally doesn't have access to this personal identifying data.
One possible way is to use a framework like PhoneGap which may have an API to access the device name. But then, you can only deploy your web site via an app store, so this could be very limiting based on your use case.

Your best bet is to use the user agent:
e.g.
const ua = navigator.userAgent
const device = {
iPad: /iPad/.test(ua),
iPhone: /iPhone/.test(ua),
Android4: /Android 4/.test(ua)
}
The object will allow you to write nice conditional logic such as if(device.iPad) { /* do stuff */ }

I'm working with mobile device with embedded scanner. To be able to use some the JavaScript library of different devices and to avoid conflict with those libraries of different manufacturer (Zebra, Honeywell, Datalogic, iOs ect...) I need to come up with a way to identify each devices so I can load the proper library and this is what I came up with. Enjoy
getDeviceName: function () {
var deviceName = '';
var isMobile = {
Android: function() {
return navigator.userAgent.match(/Android/i);
},
Datalogic: function() {
return navigator.userAgent.match(/DL-AXIS/i);
},
Bluebird: function() {
return navigator.userAgent.match(/EF500/i);
},
Honeywell: function() {
return navigator.userAgent.match(/CT50/i);
},
Zebra: function() {
return navigator.userAgent.match(/TC70|TC55/i);
},
BlackBerry: function() {
return navigator.userAgent.match(/BlackBerry/i);
},
iOS: function() {
return navigator.userAgent.match(/iPhone|iPad|iPod/i);
},
Windows: function() {
return navigator.userAgent.match(/IEMobile/i);
},
any: function() {
return (isMobile.Datalogic() || isMobile.Bluebird() || isMobile.Honeywell() || isMobile.Zebra() || isMobile.BlackBerry() || isMobile.Android() || isMobile.iOS() || isMobile.Windows());
}
};
if (isMobile.Datalogic())
deviceName = 'Datalogic';
else if (isMobile.Bluebird())
deviceName = 'Bluebird';
else if (isMobile.Honeywell())
deviceName = 'Honeywell';
else if (isMobile.Zebra())
deviceName = 'Zebra';
else if (isMobile.BlackBerry())
deviceName = 'BlackBerry';
else if (isMobile.iOS())
deviceName = 'iOS';
else if ((deviceName == '') && (isMobile.Android()))
deviceName = 'Android';
else if ((deviceName == '') && (isMobile.Windows()))
deviceName = 'Windows';
if (deviceName != '') {
consoleLog('Devices information deviceName = ' + deviceName);
consoleLog('Devices information any = ' + isMobile.any());
consoleLog('navigator.userAgent = ' + navigator.userAgent);
}
return deviceName;
},
and this is an example of how it can be used:
initializeHandheldScanners: function () {
if (DeviceCtrl.getDeviceName() == 'Zebra')
DeviceCtrl.initializeSymbolScanner();
if (DeviceCtrl.getDeviceName() == 'Honeywell')
DeviceCtrl.initializeHoneywellScanner();
if (DeviceCtrl.getDeviceName() == 'Datalogic')
DeviceCtrl.initializeDatalogicScanner();
},
You can say thanks to Cory LaViska. I did this based on his work. Here is the link if you want to know more
https://www.abeautifulsite.net/detecting-mobile-devices-with-javascript

You can use this snippet:
const getUA = () => {
let device = "Unknown";
const ua = {
"Generic Linux": /Linux/i,
"Android": /Android/i,
"BlackBerry": /BlackBerry/i,
"Bluebird": /EF500/i,
"Chrome OS": /CrOS/i,
"Datalogic": /DL-AXIS/i,
"Honeywell": /CT50/i,
"iPad": /iPad/i,
"iPhone": /iPhone/i,
"iPod": /iPod/i,
"macOS": /Macintosh/i,
"Windows": /IEMobile|Windows/i,
"Zebra": /TC70|TC55/i,
}
Object.keys(ua).map(v => navigator.userAgent.match(ua[v]) && (device = v));
return device;
}
console.log(getUA());

Related

Alexa Custom skill in AWS lambda not recognizing Alexa.getSupportedInterfaces[Error handled: Alexa.getSupportedInterfaces is not a function]

Trying to use Alexa presentation Language features in AWS hosted custom lambda function. Intent handler are firing but when I add the
Alexa.getSupportedInterfaces it is failing .
Message is "Error handled: Alexa.getSupportedInterfaces is not a function"
// 1. Intent Handlers =============================================
const LaunchRequest_Handler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'LaunchRequest';
},
handle(handlerInput) {
let responseBuilder = handlerInput.responseBuilder;
let speakOutput = 'Welcome to test Bot. ';
// let skillTitle = capitalize(invocationName);
// Add APL directive to response
if (Alexa1.getSupportedInterfaces(handlerInput.requestEnvelope)['Alexa.Presentation.APL']) {
// Add the RenderDocument directive to the responseBuilder
responseBuilder.addDirective({
type: 'Alexa.Presentation.APL.RenderDocument',
token: Echo_Token,
document: Customer
});
// Tailor the speech for a device with a screen.
speakOutput += " You should now also see my greeting on the screen."
} else {
// User's device does not support APL, so tailor the speech to this situation
speakOutput += " This example would be more interesting on a device with a screen, such as an Echo Show or Fire TV.";
}
return responseBuilder
.speak(speakOutput)
.withShouldEndSession(false)
.reprompt('try again, ' + speakOutput)
.withSimpleCard("CustomerSupport!", "CustomerSupport)")
// .reprompt('add a reprompt if you want to keep the session open for the user to respond')
//.withStandardCard('Welcome!',
// 'Hello!\nThis is a card for your skill, ' + skillTitle,
// welcomeCardImg.smallImageUrl, welcomeCardImg.largeImageUrl)
.getResponse();
},
};
Instead of using the below condition:
Alexa1.getSupportedInterfaces(handlerInput.requestEnvelope['Alexa.Presentation.APL]
you can use, below condition to check if the device supports APL:
if (supportsAPL(handlerInput))
Make sure you include below functions definition in your index file:
function supportsAPL(handlerInput) {
const supportedInterfaces = handlerInput.requestEnvelope.context.System.device.supportedInterfaces;
const aplInterface = supportedInterfaces['Alexa.Presentation.APL'];
return aplInterface != null && aplInterface != undefined;
}
function supportsAPLT(handlerInput) {
const supportedInterfaces = handlerInput.requestEnvelope.context.System.device.supportedInterfaces;
const aplInterface = supportedInterfaces['Alexa.Presentation.APLT'];
return aplInterface != null && aplInterface != undefined;
}
Hope that helps as it worked for me.

Trouble w/ Meteor Sorting

I'm trying to add a simple drop down control above a list such that I can sort it by "created" or "title".
The list template is called posts_list.html. In it's helper .js file I have:
posts: function () {
var sortCriteria = Session.get("sortCriteria") || {};
return Posts.find({},{sort: {sortCriteria: 1}});
}
Then, I have abstracted the list into another template. From here I have the following click event tracker in the helper.js
"click": function () {
// console.log(document.activeElement.id);
Session.set("sortCriteria", document.activeElement.id);
// Router.go('history');
Router.render('profile');
}
Here I can confirm that the right Sort criteria is written to the session. However, I can't make the page refresh. The collection on the visible page never re-sorts.
Frustrating. Any thoughts?
Thanks!
You can't use variables as keys in an object literal. Give this a try:
posts: function() {
var sortCriteria = Session.get('sortCriteria');
var options = {};
if (sortCriteria) {
options.sort = {};
options.sort[sortCriteria] = 1;
}
return Posts.find({}, options);
}
Also see the "Variables as keys" section of common mistakes.
thanks so much for that. Note I've left commented out code below to show what I pulled out. If I required a truly dynamic option, versus the simply binary below, I would have stuck w/ the "var options" approach. What I ended up going with was:
Template.postList.helpers({
posts: function () {
//var options = {};
if (Session.get("post-list-sort")) {
/*options.sort = {};
if (Session.get("post-list-sort") == "Asc") {
options.sort['created'] = 1;
} else {
options.sort['created'] = -1;
}*/
//return hunts.find({}, options);}
console.log(Session.get("hunt-list-sort"));
if (Session.get("hunt-list-sort") == "Asc") {
return Hunts.find({}, {sort: {title: 1}});
}
else {
return Hunts.find({}, {sort: {title: -1}});
};
}
}
});

Tracking with Java Script if Ajax request is going on in a webpage or Intercept XMLHttpRequest through Selenium Web driver

I am using Selenium WebDriver for crawling a web site(only for example, I will be crawling other web sites too!) which has infinite scroll.
Problem statement:
Scroll down the infinite scroll page till the content stops loading using Selenium web driver.
My Approach:
Currently I am doing this-
Step 1: Scroll to the page bottom
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("javascript:window.onload=toBottom();"+
"function toBottom(){" +
"window.scrollTo(0,Math.max(document.documentElement.scrollHeight," +
"document.body.scrollHeight,document.documentElement.clientHeight));" +
"}");
Then I wait for some time to let the Ajax Request complete like this-
Step 2: Explicitly wait for Ajax request to be over
Thread.sleep(1000);
Then I give another java script to check if the page is scrollable
Step 3:Check if the page is scrollable
//Alternative to document.height is to be used which is document.body.clientHeight
//refer to https://developer.mozilla.org/en-US/docs/DOM/document.height
if((Long)js.executeScript("return " +
"(document.body.clientHeight-(window.pageYOffset + window.innerHeight))")>0)
If the above condition is true then I repeat the from Step 1 - 3, till condition in Step 3 is false.
The Problem:
I do not want to give the Thread.sleep(1000); in step 2, rather I would like to check using Java Script if the background Ajax request is over and then scroll down further if the condition in Step 3 is true .
PS: I am not the developer of the page so I do not have access to the code running the page, I can just inject java scripts(as in Step 1 and 3) in the web page. And, I have to write a generic logic for any web site with Ajax requests during infinite scroll.
I will be grateful to some one could spare some time here!
EDIT : Ok, after struggling for 2 days, I have figured out that the pages which I am crawling through the Selenium WebDriver can have any of these JavaScript libraries and I will have to pool according to the different Library, for example, In case of the web application using jQuery api, I may be waiting for
(Long)((JavascriptExecutor)driver).executeScript("return jQuery.active")
to return a zero.
Likewise if the web application is using the Prototype JavaScript library I will have to wait for
(Long)((JavascriptExecutor)driver).executeScript("return Ajax.activeRequestCount")
to return a zero.
Now, the problem is how do I write a generic code which could handle most the JavaScript libraries available?
Problem I am facing in implementing this-
1. How do I find which JavaScript Library is being used in the Web Application(using Selenium WebDriver in Java), such that I can then write the corresponding wait methods?
Currently, I am using this
Code
2. This way I will have to write as many as 77 methods for separate JavaScript library so, I need a better way to handle this scenario as well.
In short, I need to figure out if the browser is making any call(Ajax or simple) with or without any JavaScript library through Selenium Web Driver's java implementation
PS: there are Add ons for Chorme's JavaScript Lib detector and Firefox's JavaScript Library detector which detect the JavaScript library being used.
For web pages with Ajax Response during the infinite scroll and using jQuery API(or other actions), before starting to opening the web page.
//Inject the pooling status variable
js.executeScript("window.status = 'fail';");
//Attach the Ajax call back method
js.executeScript( "$(document).ajaxComplete(function() {" +
"status = 'success';});");
Step 1: will remain the same as in the original question
Step 2 Pooling the following script(This is the one which removes the need of Thread.Sleep() and makes the logic more dynamic)
String aStatus = (String)js.executeScript("return status;");
if(aStatus!=null && aStatus.equalsIgnoreCase("success")){
js.executeScript("status = 'fail';");
break poolingLoop;
}
Step 3: No need now!
Conclusion: No need to give blunt Thread.sleep(); again and again while using Selenium WebDriver!!
This approach works good only if there's jQuery api being used in the web application.
EDIT:
As per the the link given by #jayati i injected the javascript-
Javascript one:
//XMLHttpRequest instrumentation/wrapping
var startTracing = function (onnew) {
var OldXHR = window.XMLHttpRequest;
// create a wrapper object that has the same interfaces as a regular XMLHttpRequest object
// see http://www.xulplanet.com/references/objref/XMLHttpRequest.html for reference on XHR object
var NewXHR = function() {
var self = this;
var actualXHR = new OldXHR();
// private callbacks (for UI):
// onopen, onsend, onsetrequestheader, onupdate, ...
this.requestHeaders = "";
this.requestBody = "";
// emulate methods from regular XMLHttpRequest object
this.open = function(a, b, c, d, e) {
self.openMethod = a.toUpperCase();
self.openURL = b;
ajaxRequestStarted = 'open';
if (self.onopen != null && typeof(self.onopen) == "function") {
self.onopen(a,b,c,d,e); }
return actualXHR.open(a,b,c,d,e);
}
this.send = function(a) {
ajaxRequestStarted = 'send';
if (self.onsend != null && typeof(this.onsend) == "function") {
self.onsend(a); }
self.requestBody += a;
return actualXHR.send(a);
}
this.setRequestHeader = function(a, b) {
if (self.onsetrequestheader != null && typeof(self.onsetrequestheader) == "function") { self.onsetrequestheader(a, b); }
self.requestHeaders += a + ":" + b + "\r\n";
return actualXHR.setRequestHeader(a, b);
}
this.getRequestHeader = function() {
return actualXHR.getRequestHeader();
}
this.getResponseHeader = function(a) { return actualXHR.getResponseHeader(a); }
this.getAllResponseHeaders = function() { return actualXHR.getAllResponseHeaders(); }
this.abort = function() { return actualXHR.abort(); }
this.addEventListener = function(a, b, c) { return actualXHR.addEventListener(a, b, c); }
this.dispatchEvent = function(e) { return actualXHR.dispatchEvent(e); }
this.openRequest = function(a, b, c, d, e) { return actualXHR.openRequest(a, b, c, d, e); }
this.overrideMimeType = function(e) { return actualXHR.overrideMimeType(e); }
this.removeEventListener = function(a, b, c) { return actualXHR.removeEventListener(a, b, c); }
// copy the values from actualXHR back onto self
function copyState() {
// copy properties back from the actual XHR to the wrapper
try {
self.readyState = actualXHR.readyState;
} catch (e) {}
try {
self.status = actualXHR.status;
} catch (e) {}
try {
self.responseText = actualXHR.responseText;
} catch (e) {}
try {
self.statusText = actualXHR.statusText;
} catch (e) {}
try {
self.responseXML = actualXHR.responseXML;
} catch (e) {}
}
// emulate callbacks from regular XMLHttpRequest object
actualXHR.onreadystatechange = function() {
copyState();
try {
if (self.onupdate != null && typeof(self.onupdate) == "function") { self.onupdate(); }
} catch (e) {}
// onreadystatechange callback
if (self.onreadystatechange != null && typeof(self.onreadystatechange) == "function") { return self.onreadystatechange(); }
}
actualXHR.onerror = function(e) {
ajaxRequestComplete = 'err';
copyState();
try {
if (self.onupdate != null && typeof(self.onupdate) == "function") { self.onupdate(); }
} catch (e) {}
if (self.onerror != null && typeof(self.onerror) == "function") {
return self.onerror(e);
} else if (self.onreadystatechange != null && typeof(self.onreadystatechange) == "function") {
return self.onreadystatechange();
}
}
actualXHR.onload = function(e) {
ajaxRequestComplete = 'loaded';
copyState();
try {
if (self.onupdate != null && typeof(self.onupdate) == "function") { self.onupdate(); }
} catch (e) {}
if (self.onload != null && typeof(self.onload) == "function") {
return self.onload(e);
} else if (self.onreadystatechange != null && typeof(self.onreadystatechange) == "function") {
return self.onreadystatechange();
}
}
actualXHR.onprogress = function(e) {
copyState();
try {
if (self.onupdate != null && typeof(self.onupdate) == "function") { self.onupdate(); }
} catch (e) {}
if (self.onprogress != null && typeof(self.onprogress) == "function") {
return self.onprogress(e);
} else if (self.onreadystatechange != null && typeof(self.onreadystatechange) == "function") {
return self.onreadystatechange();
}
}
if (onnew && typeof(onnew) == "function") { onnew(this); }
}
window.XMLHttpRequest = NewXHR;
}
window.ajaxRequestComplete = 'no';//Make as a global javascript variable
window.ajaxRequestStarted = 'no';
startTracing();
Or Javascript Two:
var startTracing = function (onnew) {
window.ajaxRequestComplete = 'no';//Make as a global javascript variable
window.ajaxRequestStarted = 'no';
XMLHttpRequest.prototype.uniqueID = function() {
if (!this.uniqueIDMemo) {
this.uniqueIDMemo = Math.floor(Math.random() * 1000);
}
return this.uniqueIDMemo;
}
XMLHttpRequest.prototype.oldOpen = XMLHttpRequest.prototype.open;
var newOpen = function(method, url, async, user, password) {
ajaxRequestStarted = 'open';
/*alert(ajaxRequestStarted);*/
this.oldOpen(method, url, async, user, password);
}
XMLHttpRequest.prototype.open = newOpen;
XMLHttpRequest.prototype.oldSend = XMLHttpRequest.prototype.send;
var newSend = function(a) {
var xhr = this;
var onload = function() {
ajaxRequestComplete = 'loaded';
/*alert(ajaxRequestComplete);*/
};
var onerror = function( ) {
ajaxRequestComplete = 'Err';
/*alert(ajaxRequestComplete);*/
};
xhr.addEventListener("load", onload, false);
xhr.addEventListener("error", onerror, false);
xhr.oldSend(a);
}
XMLHttpRequest.prototype.send = newSend;
}
startTracing();
And checking the status of the status vars ajaxRequestStarted, ajaxRequestComplete in the java code, one can determine if the ajax was started or completed.
Now I have a way to wait till an Ajax is complete, I can also find if the Ajax was triggered on some action
Approach 1:
Your approach is good, just a few changes would do the trick:
Step 1: Improve this step to call the toBottom function at regular interval using window.setInterval. At (c >= totalcount) call window.clearInterval
Setp 2: Instead of checking the page is yet scrollable, check if (c >= totalcount). And this condition every 200ms until (c >= totalcount) returns true.
FYI: If the Step 1 doesn't work in all the browsers then probably, you can refer to line 5210 of Tata-Nano-Reviews-925076578.js and call this with cvariable checking.
Approach 2:
Go to jQuery API and type "ajax". You can find some callback handlers which could be used for ajax requests.
Probably, set a variable before the request is been sent and after it is been received appropriately.
And in between use your original method of scrolling to bottom at regular interval, unless you can no more scroll. At this point clear the interval variable.
Now, regularly check if that interval variable is null or not. Null would mean that you have reached the bottom.
We had to solve the same problem, and managed using a long Javascript function. Just need to add checks to see which library is not undefined.
PS Thanks for giving me an easy answer for how to check for in progress Prototype requests!
eg. Handle JQuery and XHR/Prototype
var jsExecutor = /*Get your WebDriverInstance*/ as IJavaScriptExecutor;
while(/*your required timeout here*/)
{
var ajaxComplete =
jsExecutor.ExecuteScript("return ((typeof Ajax === 'undefined') ||
Ajax.activeRequestCount == 0) && ((typeof jQuery === 'undefined') || $.active == 0)");
if (ajaxIsComplete)
return
}

Less CSS and local storage issue

I'm using LESS CSS (more exactly less.js) which seems to exploit LocalStorage under the hood. I had never seen such an error like this before while running my app locally, but now I get "Persistent storage maximum size reached" at every page display, just above the link the unique .less file of my app.
This only happens with Firefox 12.0 so far.
Is there any way to solve this?
P.S.: mainly inspired by Calculating usage of localStorage space, this is what I ended up doing (this is based on Prototype and depends on a custom trivial Logger class, but this should be easily adapted in your context):
"use strict";
var LocalStorageChecker = Class.create({
testDummyKey: "__DUMMY_DATA_KEY__",
maxIterations: 100,
logger: new Logger("LocalStorageChecker"),
analyzeStorage: function() {
var result = false;
if (Modernizr.localstorage && this._isLimitReached()) {
this._clear();
}
return result;
},
_isLimitReached: function() {
var localStorage = window.localStorage;
var count = 0;
var limitIsReached = false;
do {
try {
var previousEntry = localStorage.getItem(this.testDummyKey);
var entry = (previousEntry == null ? "" : previousEntry) + "m";
localStorage.setItem(this.testDummyKey, entry);
}
catch(e) {
this.logger.debug("Limit exceeded after " + count + " iteration(s)");
limitIsReached = true;
}
}
while(!limitIsReached && count++ < this.maxIterations);
localStorage.removeItem(this.testDummyKey);
return limitIsReached;
},
_clear: function() {
try {
var localStorage = window.localStorage;
localStorage.clear();
this.logger.debug("Storage clear successfully performed");
}
catch(e) {
this.logger.error("An error occurred during storage clear: ");
this.logger.error(e);
}
}
});
document.observe("dom:loaded",function() {
var checker = new LocalStorageChecker();
checker.analyzeStorage();
});
P.P.S.: I didn't measure the performance impact on the UI yet, but a decorator could be created and perform the storage test only every X minutes (with the last timestamp of execution in the local storage for instance).
Here is a good resource for the error you are running into.
http://www.sitepoint.com/building-web-pages-with-local-storage/#fbid=5fFWRXrnKjZ
Gives some insight that localstorage only has so much room and you can max it out in each browser. Look into removing some data from localstorage to resolve your problem.
Less.js persistently caches content that is #imported. You can use this script to clear content that is cached. Using the script below you can call the function destroyLessCache('/path/to/css/') and it will clear your localStorage of css files that have been cached.
function destroyLessCache(pathToCss) { // e.g. '/css/' or '/stylesheets/'
if (!window.localStorage || !less || less.env !== 'development') {
return;
}
var host = window.location.host;
var protocol = window.location.protocol;
var keyPrefix = protocol + '//' + host + pathToCss;
for (var key in window.localStorage) {
if (key.indexOf(keyPrefix) === 0) {
delete window.localStorage[key];
}
}
}

Why don't InfoCards work in IE8?

What changed in IE8 that makes detecting InfoCard Selector support in javascript stop working unless IE8 is put in Compatibility Mode?
And more to the point, what is the new JavaScript code to detect the presence of InfoCard support?
Here is the script that worked up through IE7, including FireFox with a plug-in in some cases:
function AreCardsSupported() {
var IEVer = -1;
if (navigator.appName == 'Microsoft Internet Explorer') {
if (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) {
IEVer = parseFloat(RegExp.$1);
}
}
// Look for IE 7+.
if (IEVer >= 7) {
var embed = document.createElement("object");
embed.setAttribute("type", "application/x-informationcard");
return "" + embed.issuerPolicy != "undefined" && embed.isInstalled;
}
// not IE (any version)
if (IEVer < 0 && navigator.mimeTypes && navigator.mimeTypes.length) {
// check to see if there is a mimeType handler.
x = navigator.mimeTypes['application/x-informationcard'];
if (x && x.enabledPlugin) {
return true;
}
// check for the IdentitySelector event handler is there.
if (document.addEventListener) {
var event = document.createEvent("Events");
event.initEvent("IdentitySelectorAvailable", true, true);
top.dispatchEvent(event);
if (top.IdentitySelectorAvailable == true) {
return true;
}
}
}
return false;
}
I got an answer out of band from the IE8 team:
Change
embed.setAttribute("type", "application/x-informationcard");
to
embed.type = "application/x-informationcard";

Resources