Perhaps a typical and well-trodden question on first glance. But all other answers I've looked at (there are many) have consistently suggested (almost always) changing the user-agent of a WebView to a desktop string. Consistently, people have responded that this does not work for them. Myself included.
As a web design novice, from what digging I have done it seems that at some point in the last few years "responsive design" became the recommended and most widely used web design implementation philosophy of choice to determine how to deliver/display a site.
Which is why I believe changing a user-agent of a WebView is having no effect, as the site seems to be determining how to deliver content based on the meta tag "viewport", for example:
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
Has anyone else overcome this yet? Would my (layman) analysis of the issue be correct?
As far as my understanding, i think this seems like the below situation
Please look into this answer Showing the desktop version of a fully responsive website on tablets
So I think I may have found a solution, in part due to #hussnain-muavia answer, though there was slightly more I had to expand which I thought would warrant its own response.
WebView Settings
The WebView will need to be able to execute JavaScript:
WebSettings settings = _webView.getSettings();
settings.setJavaScriptEnabled(true);
In order for the site to be completely zoomed-out (i.e. displaying the full site and without scrollbars) additional settings will have to be applied to the WebView:
settings.setUseWideViewPort(true);
settings.setInitialScale(1);
settings.setLoadWithOverviewMode(true);
Achieving a Desktop Layout
Ultimately the thing that will result in a desktop view is the following JavaScript:
function desktopMode() {
var viewPort = document.getElementsByName("viewport");
if (viewPort != null) {
viewPort = viewPort[0];
}
else if ((viewPort = document.getElementById("viewport")) == null) {
return;
}
viewPort.setAttribute("content", "width=" + (screen.width + 1) + "; initial-scale=0.5");
}
As I mention in my question, I am a web design novice. Though one thing I notice is inconsistency (sorry web devs?) so I've intentionally built in a check by name and ID. We should expect only one tag, hence why name assumes the zeroth element.
Further to this solution I found I was getting a desktop layout but not quite the complete thing. So I modified the calculation thusly:
getViewport.setAttribute("content", "width=" + (screen.width * 4) + "; initial-scale=0.5");
I don't like it. But it works. My suspicion is there probably is some better calculation or constant for this.
It's probably worth mentioning, it's still worthwhile changing the user-agent string, in case the site does not use a responsive design. But this is an unrelated topic.
A major drawback of this solution is that it will result in some hideous UI, where the user can see the site being resized. As I put the JS in onPageStarted, but of course the functionality gets overridden. So I put it after the super onPageStarted call or in onPageFinished and this results in the same result of the user seeing the resize happening. Any ideas out there?
Related
I am experiencing a strange bug in PhoneGap on Android 4.4, for which I couldn't find any solution online. In my app, I am loading a lot of different images from a remote server, and as the user navigates back and forth, new images are loaded on each page (4 at a time, to be specific, through jQuery-generated html). After having navigated back and forth for a little while, some images will randomly not show up and instead show the typical "broken image" icon.
Now, here comes the strange part: I have been following the instructions at jQuery/JavaScript to replace broken images and done a few tests of my own. In conclusion, the naturalWidth and naturalHeight parameters report the right sizes of the images, and complete reports true for all images. Therefore, the solutions mentioned in the above SO thread don't work at all. Changing the image src doesn't help, either with or without a setTimeout (I tried adding the current timestamp as a parameter to the image path as well).
Did anyone else encounter this issue at all, or am I going crazy here? :)
EDIT: By the way, no error is ever reported. Therefore, no error handler is called when loading the image, making it useless to solve the problem with the already suggested methods (see the link above).
This is how i handle error images,
<img src="images/imageName.jpg" onError="onErrorFunc(this);" alt=" " />
function onErrorFunc(elem){
var imgUrl = "https://alternative-image";
elem.onerror = function (){
elem.src='images/noimage.jpg';
}
elem.src=imgUrl;
}
Hope it helps!
I am working on a horizontal scrolling site and to add to it it has a couple of CSS animations that totally crash all the browsers on the ipad i am testing on, so I am wondering if there is a way for the code to detect mobile devices (iOs, Android..) over and above screen sizes, to just disable animation for it?
Thanks for all your help in advance.
I haven't attached any code to it because, I really do not know what I would use to detect the Os, I am aware of using media queries but as I said window size is not what I am looking for its the Mobile OS that I want to target.
You can use the navigator.platform property to check the device type, then use some javascript to add the stylesheet containing your CSS animations if it's not one of the excluded platforms.
For example, to load the animations for all devices besides iPads, you could do:
if(navigator.platform != 'iPad')
{
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'animations.css';
document.getElementsByTagName('head')[0].appendChild(link);
}
For a list of platform values, refer here:
What is the list of possible values for navigator.platform as of today?
For more info on loading a stylesheet with JS, look here:
How to load up CSS files using Javascript?
I searched for weeks for a slide plugin that would work on a Phonegap app using knockout, bootstrap and jQuery. Unfortunately, nothing was fitting my needs. So, I built a custom slider. It seems to be working (I'm currently testing it on Android 2.3.4 - I'm starting with the lowest version we plan to support), but it doesn't always respond. The touchstart event seems to be rather sensitive. Does anyone have any ideas on how I can make the user experience more consistent and reactive to the touchstart event? I have researched on this for a few days, and it seems others have similar issues, but nothing exactly like mine. And none of the issues seem to have a definitive answer. Does Phonegap have issues with touch events?
Here is my knockout function:
performSlide: function() {
$('#sliderDiv').on({ 'touchstart' : function() {
$('div.slideArrow').animate({
left: "+=200"
}, 1000, function() {
shell.navigate('home', 'slide');
});
}
});
}
I'm using the event binder on a div to call the function.
<div class="linkHeader" id="sliderDiv" data-bind="event: { touchstart: performSlide }">
I have also ensured that the z-index of my div is set higher than the other elements. The position attribute is also set to relative.
Any advice offered would be much appreciated. I would love if this performed a little better... ok, a lot better. :-)
I have not received an answer, but I ended up figuring out what I needed to change. First, I needed to detect my event and capture it in a variable. Then, I also changed the databinding and .on function to detect the touchmove instead of the touchstart. It is working much better now.
I've seen/heard all about disabling text selection with the variations of user-select, but none of those are working for the problem I'm having. On Android (and I presume on iPhone), if you tap-and-hold on text, it highlights it and brings up little flags to drag and select text. I need to disable those (see image):
I've tried -webkit-touch-callout to no avail, and even tried things like $('body').on('select',function(e){e.preventDefault();return;}); to no avail. And the cheap tricks like ::selection:rgba(0,0,0,0); won't work either, as hiding these won't help - selection still happens and it disrupts the UI. Plus I'm guessing those flags would still be there.
Any thoughts would be great. Thanks!
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
-webkit-tap-highlight-color:rgba(0,0,0,0);
This will disable it for every browser going.
Reference:
jsFiddle Demo with Plugin
The above jsFiddle Demo I made uses a Plugin to allow you to prevent any block of text from being selected in Android or iOS devices (along with desktop browsers too).
It's easy to use and here is the sample markup once the jQuery plugin is installed.
Sample HTML:
<p class="notSelectable">This text is not selectable</p>
<p> This text is selectable</p>
Sample jQuery:
$(document).ready(function(){
$('.notSelectable').disableSelection();
});
Plugin code:
$.fn.extend({
disableSelection: function() {
this.each(function() {
this.onselectstart = function() {
return false;
};
this.unselectable = "on";
$(this).css('-moz-user-select', 'none');
$(this).css('-webkit-user-select', 'none');
});
return this;
}
});
Per your message comment: I still need to be able to trigger events (notably, touchstart, touchmove, and touchend) on the elements.
I would simply would use a wrapper that is not affected by this plugin, yet it's text-contents are protected using this plugin.
To allow interaction with a link in a block of text, you can use span tags for all but the link and add class name .notSelected for those span tags only, thus preserving selection and interaction of the anchors link.
Status Update: This updated jsFiddle confirms you concern that perhaps other functions may not work when text-selection is disabled. Shown in this updated jsFiddle is jQuery Click Event listener that will fire a Browser Alert for when the Bold Text is clicked on, even if that Bold Text is not text-selectable.
-webkit-user-select:none; wasn't supported on Android until 4.1 (sorry).
I'm trying to read in a website (XML/XSLT), and change the theme to one that I've created so that it looks better on the web. The site currently is horribly formatted for mobile devices, and i want to fix that. :) Is this possible? If so, how?
So far I've got my app loading the website:
WebView view = (WebView) findViewById(R.id.webview);
view.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
activity.setTitle("Loading...");
activity.setProgress(progress * 100);
if (progress == 100)
activity.setTitle(R.string.app_name);
}
});
view.setWebViewClient(new MyViewerClient());
view.getSettings().setJavaScriptEnabled(true);
view.loadUrl("http://www.somewebsite.com");
Now i'm looking for something like:
String html = view.getHTML(); // <---- does a function like this exist?
html = myparser(html); // parse html and change out xsl theme
view.loadData(html); // set html back and continue on
Side info: this site has a login (SSL), and uses cookies (haven't got there yet but don't want to corner myself with a solution that won't work in those instances)
Few things, firstly, if you have access to the server side code, you might want to make changes there so that the web site looks better on mobile devices, intact devices of may different sizes. This is a very common problem nowadays and I believe the recommended solution is to use different css files to theme your website appropriately for different screen sizes.
Now if you can't or don't have access to server side code, then we have a problem. You'll really have to reverse engineer the site/page's code and strip out the pieces of html/css that are not of interest on a smaller device. Note that this will not reduce the traffic as you'd still need to get all of the page locally and then make a pass to strip out the unneeded pieces and insert new ones.
If you favor the second approach, know that it is going to be brittle. Any changes to the web site and boom, your application would stop working as expected. If you still insist, then search for ways to perform html parsing on the android. I know there are several xml parsers, but I'm not sure about html.