userAgent jQuery script conflicting - android

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});

Related

On Android in Cucumber/Calabash, how do I test with a webview iframe?

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.

phonegap app with 'touchstart' still very slow

Im making an app in html5 and converting it to an apk with phonegap.
For now you only have to alternately push the left div and the right div.
and when you do it your score wil get higher.
The problem is when i press them very fast the score wont change. It will only change upto a certain speed wich is very slow.
leftt = left div, rightt is right div
code:
// JavaScript Document
window.onload = function ()
{
var left= 0;
var right= 1;
var score =0;
var el = document.getElementById("leftt");
var el2 = document.getElementById("rightt");
el.addEventListener("touchstart", function(e) {
if(right ==1)
{
left=1;
right=0;
score++;
document.getElementById("score").innerHTML= score;
}
});
el2.addEventListener("touchstart", function(e) {
if(left ==1)
{
left=0;
right=1;
score++;
document.getElementById("score").innerHTML= score;
}
});
}
You should add the 'user-scalable=no' parameter to your viewport.
This will remove the 300ms delay that some browsers will add to your web application to account to double clicks (The fastclick library will actually turn itself off if it detects this scenario- https://github.com/ftlabs/fastclick).
There is a lot more in depth on this topic on HTML5Rocks - http://updates.html5rocks.com/2013/12/300ms-tap-delay-gone-away
While this article is applicable to Chrome for Android, the user-scalable=no trick has been in Chrome for some time and is in the Android WebView in KitKat.
There is a bug with Android version 4.0.4+ .Try turning off hardware acceleration for your webview with this line of code in your app java file:
super.appView.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
This may be fixed as of 4.4 (KitKat uses Chromeview rather than webview).

Phonegap breaks jQuery Mobile pages when reloaded - visiting the same page again

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

Android Browser Triggers jQuery $(window).resize() on scrolling

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);
};

iFrame Changes window.innerHeight / window.innerWidth on Android + PhoneGap

I'm creating an App using PhoneGap for Android. One of the pages in the App contains an iFrame (with local content) that is larger than the rest of the pages (this is a single-page App).
The problem I've run into is that once the iFrame page is viewed, the window.innerHeight and window.innerWidth JavaScript objects change their values to match the iFrame's width/height which is causing the rest of the 'pages' to display incorrectly as they are not the same size.
This persists even after I remove the iFrame from the DOM.
Has anyone run into this or has an idea of a workaround?
I just was in the same situation and also I removed the iframe, the solution (that worked for me) is to put the next in your html head:
<meta name="viewport" content="width=device-width, initial-scale=1">
I always though that this part was unnecessary because the innerWidth and innerHeight don't complicate on the desktop, but it cost me 6 hours.
I would like to know if it worked for you, bye.
First, for sure there is a bug here !
I just had the same issue and resolved, here is how.
I changed all the iframes & images width to 100% or less for those wider than window.innerWidth.
Here is the corresponding HaxeJS code:
resizeNodeChildrenTag(_contentContainer,"iframe");
resizeNodeChildrenTag(_contentContainer,"img");
private function resizeNodeChildrenTag(node:HtmlDom, tagName:String):Void
{
var tagNodes:HtmlCollection<HtmlDom> = node.getElementsByTagName(tagName);
// for all nodes with the given tag name
for (i in 0...tagNodes.length)
{
if(tagNodes[i].clientWidth > Lib.window.innerWidth)
tagNodes[i].setAttribute("width", "96%");
tagNodes[i].setAttribute("height", "");
}
}
}

Categories

Resources