I use this function to detect iOS
export function isiOS() {
return navigator.userAgent.match(/ipad|iphone/i);
}
is there any way to make it detected iOS13+? thanks
Why do I need it? usually, iOS safari can't download files therefore to make image downloadable I should render it as
<img src={qrImage} alt="creating qr-key..." />
however on Android/PC and pretty much everywhere else it's possible to do it directly via
<a href={qrImage} download="filename.png">
<img src={qrImage} alt="qr code" />
</a>
so user just press image and download it. Turned on on iOS13 now second option works while first one doesn't anymore.
I would like to advice you against detecting operating system or browser from user agent, since they are susceptible to change more than an API for that does, till a reliable stable standard API lands. I have no idea about when this second part will happen.
However, I can suggest to detect feature instead if in this case it is applicable to you.
You can check if the anchor html element supports download attribute:
"download" in document.createElement("a") // true in supporting browsers false otherwise
That way you can display the appropriate html markup depending on the output for each case.
Something like that may help:
function doesAnchorSupportDownload() {
return "download" in document.createElement("a")
}
// or in a more generalized way:
function doesSupport(element, attribute) {
return attribute in document.createElement(element)
}
document.addEventListener("DOMContentLoaded", event => {
if (doesAnchorSupportDownload()) {
anchor.setAttribute("display", "inline"); // your anchor with download element. originally display was none. can also be set to another value other than none.
} else {
image.setAttribute("display", "inline"); // your alone image element. originally display was none. can also be set to another value other than none.
}
});
For example, I use following to detect if I am on an ar quick look supporting browser on iOS:
function doesSupportAnchorRelAR() {
return document.createElement("a").relList.supports("ar");
}
You can also use techniques documented below:
http://diveinto.html5doctor.com/detect.html#techniques
See this Link .
$(document).ready(function() {
function iOSversion() {
if (/iP(hone|od|ad)/.test(navigator.platform)) {
var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)];
}
}
ver = iOSversion();
if (ver[0] >= 13) {
alert('This is running iOS '+ver);
}
});
You can detect iOS 13 on iPhone but in iPad OS 13 navigator.platform comes as MacIntel. So it is not possible to get iPad identified using below code, but it works perfectly on iPhone.
if (/iP(hone|od|ad)/.test(navigator.platform)) {
var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
var version = [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)];
}
When user asks for mobile website using the browser navigator.platform returns as iPad and works perfectly.
Related
I am using GoogleSheets to print a png/image file using HTMLService. I created a temporary Iframe element with an img tag in the modalDialog and call IFrame element's contentWindow.print() function after IFrame element and its image are loaded. (I have not set visibility:hidden attribute of IFrame element to check if image is getting loaded.)
However, I only see the printer dialog without any print preview. I am testing on Firefox. Am I missing anything?
[Updated] - I am using Googles Apps script. performPrint() is in printJsSource.html and openUrl() is in Code.gs.
Inside printJsSource.html
function performPrint(iframeElement, params) {
try {
iframeElement.focus()
// If Edge or IE, try catch with execCommand
if (Browser.isEdge() || Browser.isIE()) {
try {
iframeElement.contentWindow.document.execCommand('print', false, null)
} catch (e) {
iframeElement.contentWindow.print()
}
} else {
// Other browsers
iframeElement.contentWindow.print() // as I am using Firefox, it is coming here
}
} catch (error) {
params.onError(error)
} finally {
//cleanUp(params)
}
}
Inside Code.gs
function openUrl() {
var html = HtmlService.createHtmlOutputFromFile("printJsSource");
html.setWidth(500).setHeight(500);
var ui = SpreadsheetApp.getUi().showModalDialog(html, "Opening ..." );
}
I think there is some general confusion about the concept
First of all, function performPrint() seems to be a client-side Javascript funciton, while function openUrl() is a server-side Apps Script function.
While you did not specify either you use Google Apps Script - if you do so, function openUrl()belongs into the code.gs file and function performPrint() into printJsSource.html file
function openUrl() allows you to open a modal dialog which can show some data on the UI, e.g. your image
Do not confuse this behavior with actual printing (preview)!
It is NOT possible to trigger the opening of a Google Sheets printing preview programamticaly!
The Javascript method you are using iframeElement.contentWindow.print() might trigger the printing of the whole content of a browser window (different from the Google Sheets printing dialog, also depends on the browser), but if you try to incorporate it into the client-side coe of an Apps Script project, you will most likely run into restrictions due to the scopes of modal diloags and usage of iframes.
While from your code it is hard to say either you implemented the funcitons in the correct files of the Apps Script project, keep in mind that to work with iframes you need to specify in function openUrl()
html.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
I am developing a Hybrid App for iOS and Android using PhoneGap.Is it possible to add buttons and control its event to toolbar of inappbrowser using javascript.I know how to add it through ios native side but i cant use that process.I need to control the button event through a javascript method.
You have two options to do that.
The first option is, obviously, to patch the native plugin code, and that's it. Here you can find an example made for iOS, you will have to do the same to your Android Java code and for every other platform you want to support.
Another option is to hide the native toolbar and inject HTML and CSS to create a new one when the page is loaded.
Something like this:
// starting inappbrowser...
inAppWindow = window.open(URL_TO_LOAD, '_blank', 'location=no');
// Listen to the events, we need to know when the page is completely loaded
inAppWindow.addEventListener('loadstop', function () {
code = CustomHeader.html();
// Inject your JS code!
inAppWindow.executeScript({
code: code
}, function () {
console.log("injected (callback).");
});
// Inject CSS!
inAppWindow.insertCSS({
code: CustomHeader.css
}, function () {
console.log("CSS inserted!");
});
And you will have obviously to define the CustomHeader object, something like this:
var CustomHeader = {
css: '#customheader { your css here }',
html: function() {
var code = 'var div = document.createElement("div");\
div.id = "customheader";\
// Insert it just after the body tag
if (document.body.firstChild){ document.body.insertBefore(div, document.body.firstChild); } \
else { document.body.appendChild(div); }';
return code;
}
};
I had experience with this problem.
For my case, the second option was enough, not a critical task. Sometimes it takes a lot for the loadstop event to fire, and so you don't see the injected bar for >= 5 seconds.
And you have to pay attention even on the CSS of the loaded page, because obviously you can affect the original CSS, or the original CSS can affect the style of your toolbar.
I'm using Jquery Mobile to develop an web app for Android and iPhone. I want to handle the event when the users change their value in the input text field.
Initially, I use .on("keyup change") and everything seem to work ok. However, when the users paste some text on the text field (by holding and tap on the "Paste"), my event handler is not called.
Please help me if you know how to solve this problem.
Thank you all.
Works on all browsers but not on FireFox.
Demo
$('input').on('paste', function (e) {
if (e.originalEvent.clipboardData) {
var text = e.originalEvent.clipboardData.getData("text/plain");
$('p').empty();
$('p').append(text);
}
});
Credit goes to: jQuery Detect Paste Event Anywhere on Page and "Redirect" it to Textarea
For Android add a timeout as it is in this example http://ajax911.com/numbers-numeric-field-jquery/
For iPad add event 'change' together with paste, worked on iphone
Here is what worked for me on mobile Safari and Chrome.
if (document.getElementById('search_input')) {
document.querySelector('#search_input').addEventListener('paste', (e) => {
let pasteData = (e.clipboardData || window.clipboardData).getData('text');
pasteData = pasteData.replace(/[^\x20-\xFF]/gi, '');
window.setTimeout(() => {
//do stuff
});
});
}
I'm building an app to launch across Android, iOS, and desktop simultaneously. The app includes a login that is attached to a vBulletin system and I've run into a significant issue (that the client is adamant must be fixed). On iOS, if you are typing in a TextInput that has its displayAsPassword set to true, it will show plain text while typing. Once you click out of the TextInput, it displays properly.
Here is the code I am using within Flex
<s:TextInput id="inputField" width="100%" styleName="loginFields" text="Password" focusAlpha="0" focusEnabled="false" autoCorrect="false" />
I then attach focus events to the input field that run these functions.
private var defaultText:String = 'Password';
private var passwordDisplay:Boolean = true;
private function focusIn (e:FocusEvent = null):void {
if (this.inputField.text == this.defaultText){
this.inputField.text = '';
}
if (this.passwordDisplay){
this.inputField.displayAsPassword = true;
}
}
private function focusOut (e:FocusEvent = null):void {
if (this.inputField.text == ''){
this.inputField.text = this.defaultText;
if (this.passwordDisplay){
this.inputField.displayAsPassword = false;
}
}
}
There's a lot more code in the file, but this is the only relevant. Basically, on focus in, it checks if the text == the default text. If it does, it empties the field. It then sets displayAsPassword to true. On focus out, it checks if the field is empty. If it is, it resets the field to default and displayAsPassword to false. I know the default text is built in, but I needed more functionality than it offered.
Now, this issue (password displaying as plaintext while focus is on field) is present in iOS only and it doesn't occur in the emulator. It works perfectly and as expected on Android and desktop. I've tried recreating the functionality manually (possible but not ideal because caretIndex is not a TextInput property), I've tried hiding the TextInput and overlaying a field of '•' that match the length of the input (not possible because TextInput is StageText). I'm not sure what else I can try here. Any ideas?
Thanks in advance for any help here.
Specs:
Built and compiled using FlashBuilder 4.6 (but I also have 4.5.1 available to me)
Using Air 3.1
Compiled on OS X Lion
Tested on both 1st and 3rd gen iPads
Using Flex SDK 4.6.0
I am having a problem with my jqm form not working properly in mobile browsers (iPad 1 Safari, Android Dolphin) but working as expected in desktop browsers (Chrome, Firefox, Safari & IE9 on Win7).
The form starts by asking the user how they would like to be contacted (email, sms, and/or post), then updates fields to be required based on this selection (validation is via the validationEngine.js plugin).
An example of the form can be seen here.
The logic of the script is that it checks to see if the checkbox is selected (or de-selected), then adds (or removes) a class to make it required as shown below.
$('body').delegate('#byEmail_label', 'click tap', (function(event) {
if (!$("#byEmail").is(":checked"))
{
$('#req_email').addClass('reqField');
$('#email').addClass("validate[required,custom[email]]");
}
else
{
$('#req_email').removeClass('reqField');
$('#email').removeClass("validate[required,custom[email]]").validationEngine('hide');
}
})
);
I had this working 100% without the .delegate(), but then I could not have the form load via ajax - after adding .delegate it all works well, except in mobile browsers.
Has anyone experienced something similar, or have any idea how I can get this working?
Thanks
Finally fixed my own problem by moving all my jquery outside the
$(document).ready(function () {...
and into
$('*').delegate('body','pagecreate', function(){...
ie:
$('*').delegate('body','pagecreate', function(){
$('#byEmail_label').tap(function(event) {
if ($("#byEmail").is(":checked"))
{
$('#req_email').addClass('reqField');
$('#email').addClass("validate[required,custom[email]]");
}
else
{
$('#req_email').removeClass('reqField');
$('#email').removeClass("validate[required,custom[email]]").validationEngine('hide');
}
});
});
Now my head feels better... no more banging it on the desk...
I also had troubles with checkboxes and radios, this is what I used. Might help to check for the value instead of if it's checked.
alert($('input[name=byEmail]:checked').val());
or
var cb_val = $('input[name=byEmail]:checked').val() == true;
or
var cb_val = ($('input[name=byEmail]:checked').val() == 'blah') ? true:false;
Maybe something like this
var addValidation = ($('input[name=byEmail]:checked').val() != '') ? true:false;
if(addValidation) {
$('#req_email').addClass('reqField');
$('#email').addClass("validate[required,custom[email]]");
} else {
$('#req_email').removeClass('reqField');
$('#email').removeClass("validate[required,custom[email]]").validationEngine('hide');
}