I have been working on a project using PhoneGap and jQuery Mobile. My setup uses multiple pages inside a single html file.
I am facing a problem and I haven't found anything similar anywhere:
When I revisit a page, which means I visited it, then navigated to another page, and now returned to the first page, there is some padding between the header and the content, and also between the footer and the content of the page.
As screenshots show below:
http://i.imgur.com/neBwZYx.png
Below you can see the padding added, red background, when returned to the page above afterwards (this happens with every page)
http://i.imgur.com/u1whW9b.png
The code is very large to post here so if anyone has a suggestion please tell me how to fix this or where to look for the problem.
It should be noted that the problem exists only if the app runs on Android tablets, and not when viewed through the browser on my laptop.
Thank you
You can force correct content height with this function:
function getRealContentHeight() {
var header = $.mobile.activePage.find("div[data-role='header']:visible");
var footer = $.mobile.activePage.find("div[data-role='footer']:visible");
var content = $.mobile.activePage.find("div[data-role='content']:visible:visible");
var viewport_height = $(window).height();
var content_height = viewport_height - header.outerHeight() - footer.outerHeight();
if((content.outerHeight() - header.outerHeight() - footer.outerHeight()) <= viewport_height) {
content_height -= (content.outerHeight() - content.height());
}
return content_height;
}
It must be activated during the pageshow event because only at that point page height is correct:
$(document).on('pageshow', '#index', function(){
$.mobile.activePage.find('.ui-content').height(getRealContentHeight());
});
Working example: http://jsfiddle.net/Gajotres/nVs9J/
If you want to find out more about this function read my other article: https://stackoverflow.com/a/14550417/1848600
Related
I have an hybrid app developed with ionic 1.x. When the app loads I am forcing the webview to take the focus from native side with the hope that after some initialization request a survey dialog appear and take the focus it self(When dialog appear I am forcing it to take focus). I am trying to make it work with talkback
The problem is that when you load the app from scratch the dialog is not focused so it is not read, after navigate through the app and come back to the original page then in works as expected, looks like as the user is in fact inside the page things works ok.
Is there any workaround or strategy to solve this particular situation?
Thanks in advance
I don't know if it helps you,
but we use it to focus on specific elements in the web view.
it works in android and ios,
but in android, before every element it read webview.
(if you found a solution for it please let me know)
function putFocus(elementForFocus) {
var $element = $(elementForFocus);
var focusInterval = 10; // ms, time between function calls
var focusTotalRepetitions = 10; // number of repetitions
$element.attr('tabindex', '0');
$element.blur();
var focusRepetitions = 0;
var interval = window.setTimeout(function () {
$element.focus();
}, focusInterval);
};
I can locate an iframe in an Android webview, but I need to interact with it. Various pages suggest
query("webView css:'iframe'", :stringByEvaluatingJavaScriptFromString => '...')
but that results in "No such method found: stringByEvaluatingJavaScriptFromString([String])" and it looks like an iOS function, so I'm pretty sure this is an iOS-only solution: I need Android.
I know I can pass javascript queries in by opening them in a URL, but I've only experienced getting stuff out of an Android webview with specially-code Chrome objects linked in to the application.
Any ideas for getting data out?
The iOS responses are correct, you should use javascript to get the contents of an iframe. However, you should use evaluate_javascript(query_string, javascript) to evaluate javascript in Android. e.g
evaluate_javascript("webview", "return document.getElementsByTagName('iframe')[0].contentWindow.document.getElementById('...').getBoundingClientRect();")
Use the coordinates to tap the view.
If the rect is not parsed correctly, you could do something like this:
var boundingBox = document.getElementsByTagName('iframe')[0].contentWindow.document.getElementById('main').getBoundingClientRect();
var rect = {};
rect.width = boundingBox.width;
rect.height = boundingBox.height;
rect.left = boundingBox.left;
rect.top = boundingBox.top;
return rect;
Secondly, query('webView css:#grabby') is not a valid query. query('webView css:"#grabby"') or query("webView css:'#grabby'") is. You are most likely running a (very) old version of Calabash-Android if the test-server is crashing instead of reporting it.
I wrote what amounted to an answer while I was exploring, but I'm posting it here to save someone else time (hopefully).
I can successfully run Javascript in the view:
query("webView index:0", :loadUrl => 'javascript:alert("Hello")')
so I can probably arrange to press buttons plausibly enough for testing:
query("webview index:0", :loadUrl => 'javascript: ifr = document.getElementsByTagName("iframe")[0]; idoc = ifr.contentDocument || ifr.contentWindow.document; idoc.getElementById('myCheck').click(); false')
To get data out again, I can create a DIV and set its title (for example) with some 'return' value:
query("webView index:0", :loadUrl => 'javascript:var idiv = document.createElement("div"); idiv.id="grabby"; document.getElementsByTagName("body")[0].appendChild(idiv); idiv.title="some return value"; false')
(The trailing 'false' in the javascript: command is there to prevent the result of running the javascript: command from replacing the page - that took a while to work out.)
I can look into the iframe too:
query("webView index:0", :loadUrl => 'javascript:var idiv = document.getElementById("grabby"); ifr = document.getElementsByTagName("iframe")[0]; idoc = ifr.contentDocument || ifr.contentWindow.document; idiv.title = idoc.getElementsByTagName("input")[3].id; false')
When I tried to retrieve it with
query('webView css:#grabby')
it hung for a while, then crashed with a timeout:
HTTPClient::ReceiveTimeoutError: execution expired
from /Users/tim./.rvm/gems/ruby-2.1.5/gems/httpclient-2.6.0.1/lib/httpclient/session.rb:876:in `gets'
from /Users/tim./.rvm/gems/ruby-2.1.5/gems/httpclient-2.6.0.1/lib/httpclient/session.rb:876:in `block in parse_header'
from ...
curiously, query('webView css:"*"') mostly seems to work without timeouts, and reports the 'grabby' DIV complete with the title string
query('webView css:"*"').find { |e| e['id'] == 'grabby' }
so that's useful enough. I'll have to write some horrible recursive descent thingy to fish out the iframe's contents - perhaps make the div invisible and just copy the htmlContent there.
I'm really not sure why the direct query crashes.
I am using the localstorage option to set a variable for using it in another page.The platform is Android
Just to simulate the problem, i just created 2 simple JQM pages and set the variable in page 1 and use it in page 2. That works fine for the first time. When i'm going back to page 1 and set a new value for the variable, page 2 tells me that it is the previous value(!). I'm a little bit lost how to use it. Can someone give me a clue how to manage this? The weird thing is that on an old Android version (like 2.3.3) it works fine, but on a new one (like > 4) it fails. I think it has something to do with ready() event?
Page 1 - Main page:
$(document).ready(function () {
$('#Klant_Lijst').delegate('li', 'click', function () { var x = $(this).data('nummer'); localStorage.setItem("Nummer", x);});
});
Page 2 - sub page
$(document).ready(function () {
GetFustInfoKlant(localStorage.getItem('Nummer'));
});
I hope someone can give me an hint in a direction. Thanks!
Please dont use ready() method, use JQM page events like pageshow, pagecreate, pagebeforeshow, etc..
I have recently come across something quite wierd, I'm not sure if it's maybe me just missing something but I can't understand why this is happening.
I have a site that has the following jQuery snippet running on it:
$(window).resize(function(){
alert("Resize fired!");
});
When I go to the site on an Android phone browser, and simply scroll up and down the site, I can see the alert.
The Android browsers scroll bars (which fade in and out) are overlayed ontop of the entire site and don't seem to cause any resizing of the window, so I'm guessing this event isn't being fired by them.
Does anyone know why the Android browser is firing this event on scrolling?
Any information will be greatly appreciated.
EDIT:
I have tried setting CSS for body, setting overflow-y to scroll to see if that was a viable solution but the event is still being fired on scrolling on Android.
EDIT #2:
I am using the following metatag in my HTML:
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
I was having the same problem, my solution was to check if the window size actually changed, for doing it I needed to store the past window width somewhere in my app. The code could be something like this:
$(window).resize(function() {
clearTimeout(app.resize.timer)
app.resize.timer = setTimeout(function(){
var window_changed = $(window).width() != app.size.window_width
if(window_changed) console.log('Window size changed! resize site')
}, 500)
})
I did not count on the window height because my Android browser hides and shows the address textbox when I scroll down the site making the window height change on vertical scroll
#john-mccollum is correct in the comments. It appears to be the disappearing browser interface causing a change in height that triggers the resize event. So check for change in width specifically in your function if you are doing responsive design stuff where you want to check if the width has been resized.
$(window).resize(function(){
var w = $(window).width();
if (typeof checkw == 'undefined') checkw = w;
if (w!=checkw) {
console.log("The width changed from "+checkw+" to "+w);
// do your responsive magic!
checkw = w;
}
});
Not required to make this work, but this pairs well with the Paul Irish / John Hann "smartresize" method.
i'm having the same problem too!
the problem is true because the height of the browser in Android will change when the url bar hide and show. So, we have to make the browser reload only happens when the width size changes.
i saw this question in Stackoverflow show me how to do this. And this is the jsfiddle.
var doit;
function resizedw(appwidth){
var window_changed = $(window).width() != appwidth;
if ($(window).width() != appwidth){
("body").append("did it"+appwidth+" ");
}
past_width = $(window).width();
}
var past_width = $(window).width();
window.onresize = function() {
clearTimeout(doit);
doit = setTimeout(function() {
resizedw(past_width);
}, 100);
};
I have some jQuery that sets the height and width of various divs.
jQuery(document).ready(function($) {
var h = $(window).height();
var w = $(window).width();
$('.slide') .css({'height': h});
$('.slide') .css({'width': w});
});
This has worked fine until recently i added a script to load userAgent specific css files, one for iPad, Android, and everything else. For some reason the two scripts wont run together. I can have EITHER the correct sized div, OR a multi platform website.
if(navigator.userAgent.match(/iPad/i)) {
document.write("<link type=\"text\/css\" *etc*>");}
else if(navigator.userAgent.match(/android/i)){
document.write("<link type=\"text\/css\" *etc*>");}
else {
document.write("<link type=\"text\/css\" *etc*>");
}
Any reason this last bit of script is stopping the first one from running?
My guess would be the following.
The jQuery.ready() function is called as soon as the dom structure is fully loaded, but before any external stylesheets are loaded. This means that there is a potential race condition between the code loading and applying the stylesheet and the code modifying the css.
You might try to call this fragment in the jQuery.onload().
var h = $(window).height();
var w = $(window).width();
$('.slide') .css({'height': h});
$('.slide') .css({'width': w});