iPhone Detect Zoom - Help! - javascript

This works in all my test browsers:
<body onresize="handleResize()">
// Aint perfect, but works well enough!
function handleResize()
{
// Document.ready sets initialWidth = window.innerWidth;
var zoomAmount = Math.round((initialWidth / window.innerWidth) * 100);
$('#db').html(zoomAmount);
}
On iPhone when I use two fingers to zoom in and out, this number is not updated.
How can I trigger an event when the iPhone user zooms?

You can't. When you pinch to zoom on the iPhone web kit, you're not actually resizing the view of the web page in the same sense as when you resize a browser window -- notice that the content doesn't reflow. All the iPhone is doing is blowing up a certain section of the complete web content.

Related

iOS Safari - disable scroll / bounce but retain zoom

I'm creating a web-app for iOS Safari and have run into a slight hurdle.
My web-app only takes up 1024x768 of screen real estate and therefore does not need scrolling, but it does need to be able to zoom (it's a PDF annotator).
I have used a plugin called iNoBounce (https://github.com/lazd/iNoBounce/) which successfully removes scrolling from the page by firing an evt.preventDefault() on the touchmove/touchstart events. This is great.
What this does though, is remove zoom events as well as scroll events. Is there a way to remove scrolling/elastic bouncing but to retain zoom on iOS safari?
Many thanks
I managed to solve this issue by listening to some values on the touch event object, specifically changedTouches.length and scale.
First I set a global variable for zoomLevel at the top of the document var zoomLevel = 1
Next, I replaced evt.preventDefault() in iNoBounce with:
if(evt.changedTouches.length === 1 && zoomLevel <= 1){
evt.preventDefault();
}
if(evt.changedTouches.length > 1){
zoomLevel = evt.scale;
}
This looks at how many fingers are being used and if the page scale is not 100%, then acts accordingly.

Can't reliably detect scroll bottom between iPhone portrait and landscape modes

I'm trying to detect when a user has scrolled to the bottom of the document. My current solution works fine in desktop browsers, and with Mobile Safari in landscape mode (with a 1px variance that I can't yet explain). However, I'm getting a completely different result for Mobile Safari in landscape mode.
I have a working example here: http://dl.dropbox.com/u/5634676/checkbottom.html
The detection routine boils down to:
if ($(window).scrollTop() + $(window).height() >= $(document).height())) {
// Bottom reached
}
Can you explain the difference between the two modes and help me reliably detect when the user has scrolled to the bottom of the document?
Update
I've updated the linked example fixing the bug pointed out by theflyingbrush. The results for landscape and portrait modes are now closer together (but there is still an as yet unexplained variance of 52px). Importantly though, for both portrait and landscape modes scrolling to the bottom of the page is still not detected.
I had the same issue on IOS mobile devices. Replace 'document' with 'body' fixed my issue.
if($(window).scrollTop() + $(window).height() > $('body').height() - 200 )
Also, it is better to check if 'near' bottom of the screen.
The height of the window changes when the device orientation changes, invalidating your windowHeight var stored on doc ready. Update it by listening for the orientationchange event and recalculating the window height. Something like:
window.addEventListener("orientationchange", change);
function change(){
windowHeight = $(window).height();
}
Edit: Confusing this, because it also involves the viewport scale. Here's a link to a working version: http://appunit.co.uk/scroll
You need to account for the height of the address bar in your calculations, because $(window).scrollTop() returns 0 until the address bar is scrolled offscreen. So, add the address bar height (60px) to scrollTop to get the distance scrolled. This is made more complicated if you haven't set a viewport meta tag in your html specifying width=device-width. In that case the viewport will be scaled from 320x356 to 980x1091, and the amount of virtual height the address bar takes up is scaled also. Summary:
var scaleFactor = ($(window).height()/356).toPrecision(2);
// toPrecision(2) prevents rounding error..
var addressBarHeight = 60 * scaleFactor;
// and when calculating scrollTop
var scrollTop = addressBarHeight + $(window).scrollTop();

Android browser's screen.width, screen.height & window.innerWidth & window.innerHeight are unreliable

I'm working on a web app that is targeted to browsers on desktop, tablet and smartphone.
The web app has a light box implemented using Colorbox with an iframe. When the browser window is resized or the tablet/phone has it's orientation changed, Javascript code queries the window dimensions so that it can resize some elements of the light box.
The issue I'm having is that everything works fine on desktop (Windows: IE, Firefox, Chrome, Mac: Safari), iPad & iPhone but not on the Android smartphone (HTC) and Android Emulator.
Android always returns different values for screen.width, screen.height, window.innerWidth & window.innerHeight when they're queried from inside the window's resize event, which fires multiple times.
Why is the Android browser returning such a wide variance in values and how can I reliably detect the width and height of the browser window?
On Android, window.outerWidth and window.outerHeight are reliably the screen size. Depending on your version of Android, innerWidth/Height is usually incorrect.
Here's a really good writeup on the situation.
Below is differentiation based on readings with Samsung Tab running Android 4.1
screen.height - gives actual device height including task bar and
title bar
window.innerHeight - gives the height excluding task bar, title bar
and address bar(if visible)
window.outerHeight - gives the height excluding task bar and title
bar height, (no matter address bar is visible or hidden, outerHeight
include the address bar height.)
I took me hours to find a workaround.
The only constant among window.innerHeight, window.outerheight, etc was screen.height.
This code gave me the outerheight:
screen.height / window.devicePixelRatio - window.screenTop
Also, in order to support older versions of android, place your code in a setTimeout
I hope this is helpful =)
I'm using this to make it work between ios and android.
var screenHeight = (ionic.Platform.isIOS()) ? window.screen.height : window.innerHeight * window.devicePixelRatio;
Try this, and check your mobile reading
<script>
var total_height=screen.height*window.devicePixelRatio;
alert(total_height);
</script>
It should match the screen size (height) of your phone specifications.
var throttle = (function () {
var timer;
return function (fn, delay) {
clearTimeout(timer);
timer = setTimeout(fn, delay);
};
})(),
var callback = function (w, h) {
alert(w + ' ' + h);
}
window.onresize = throttle(function () {
width = Math.min(window.innerWidth, window.outerWidth);
height = Math.min(window.innerHeight, window.outerHeight);
callback(width, height);
}, 60);
Dan's answer fix the inconcistancy between android's browser..
so I post how I detect/change mobile viewport and adapt it when rotated
(don't know if usable for any one...
var lastorg=0; //set the begining of script
thisorg=parseInt(window.innerWidth)/parseInt(window.innerHeight); //for ratio to detact orietation
if(((lastorg<1 && thisorg>1) ||(lastorg>1 && thisorg<1) ||lastorg==0 )){ //is start or change
$("#viewport").attr('content', 'width=device-width, initial-scale=1,minimum-scale=1, maximum-scale=1'); // reset viewport to device
mywidth = Math.min(window.innerWidth, window.outerWidth); //Dan's way to fix the inconsistancy
myheight = Math.min(window.innerHeight, window.outerHeight);
lastorg=thisorg; //update the lastorg
wr=parseInt(mywidth)/1280; // the minimum desire width
hr=parseInt(myheight)/630; // the minimum desire height
if(hr<wr){
vscale=hr;
if(hr<1){ // if it if small screen, so desktop pc wouldn't change
windowHeight=630;
windowwidth=mywidth/hr;
}
}else{
vscale=wr;
if(wr<1){
windowwidth=1280;
windowHeight=myheight/wr;
}
}
$("#viewport").attr('content', 'width=device-width, initial-scale='+vscale+',minimum-scale='+vscale+', maximum-scale='+vscale); //reset viewport toresize window
if(thisorg>1){
$("#pro").fadeOut(500);
}else{
$("body").prepend("<div id=pro style='position:absolute;width:800px;height:30px;padding:30px;left:"+(windowwidth/2)+"px;top:"+(windowHeight/2)+"px;margin-left:-430px;margin-top:-45px;;border:1px solid #555;background:#ddeeff;text-align:center;z-index:99999;color:#334455;font-size:40px;' class=shadowme>Please rotate your phone/tablet</div>");//tell user to rotate
}
}
In my case, the setTimeout hook was not useful.
After some digging, I discover that different Android versions (and devices) have different devicePixelRatio values.
If the devicePixelRatio is equal or greater than 1, the actual number of pixels in the screen (for the html page point of view) is given by window.screen.width (or ...height).
But, if the window.screen.width is less than 1 (it happens in some old Android devices), the actual number of pixels becomes: window.screen.width/devicePixelRatio.
So, you just have to cope with this.
w = window.screen.width;
h = window.screen.height;
if(window.devicePixelRatio < 1){
w = window.screen.width/window.devicePixelRatio;
h = window.screen.height/window.devicePixelRatio;
}

How to make window.innerHeight work on mobile devices when zooming?

window.innerHeight
Yes, it will return the value of the browser's height on a mobile device. However, the problem comes (on some browsers) when a user tries to pinch to zoom in or zoom out. The value will not adjust properly and instead still return the full length of the page.
Let's say it was 500px when loaded. The user then zooms in and the height is now 200px. However, the value is still returning 500px.
Does anyone know a method to fix this? Been searching forever.
The way I fixed this was to remove any resize callback in my code. Sounds weird, but it worked for me.
Check out the accepted answer in this link:
Detect page zoom change with jQuery in Safari
If your want innerHeight, may be get original width and then zoomed width, get zoom ratio and then calculate the new Height (after zoom).
This worked for me. The first thing I do is grab window.innerHeight and window.innerWidth from the dom when the page loads so I get the original values and store them in javascript variables. Then in my window.onresize event handler I do this.
var height = null;
var width = null;
if (window.orientation && window.orientation == -90) {
height = myOriginalHeight;
width = myOriginalWidth;
}
else {
height = myOriginalWidth;
width = myOriginalHeight;
}
doCallbacks(width, height);
My app resizes a lot because I attempt to write one ui for all screen types. According to my testing with the app this works on ipad and andriod and all the resizing works when zoomed in or orientation changes which can sometimes cause zoom to occur.
The interesting aspect of this is mobile browsers never actually change screen sizes as they are fixed, they just zoom. But if you resize to original width/height and handle orientation this way it seems to work.

automatically detect web browser window width change?

i know that you with $(window).width() can get the size of the web browser.
i want to detect when the user change the size of his web browser so i could readjust the columns width. is there a way to automatically detect this or do i have to use setTimeinterval to loop and see if it has changed?
Try the resize event
$(window).resize(function() {
console.log('window was resized');
});
Writing this down cause somehow none of these answers give the modern best-practices way of doing this:
window.addEventListener("resize", function(event) {
console.log(document.body.clientWidth + ' wide by ' + document.body.clientHeight+' high');
})
The JavaScript event is named window.onresize.
The JQuery binding is named .resize()
In MDN they give a really good Javascript standalone code:
window.onresize = resize;
function resize()
{
alert("resize event detected!");
}
If you need just this kind of functionality I would recommend to go for it.
You might want to use debounce :
https://davidwalsh.name/javascript-debounce-function
Otherwise the
window.addEventListener("resize")
Will fire the whole time as the window resize is in progress.
Which will tax your CPU overhead.
Something to keep in mind- in IE, at least, resize events bubble, and positioned elements and the document body can fire independent resize events.
Also, IE fires a continuous stream of 'resize' events when the window or element is resized by dragging. The other browsers wait for the mouseup to fire.
IE is a big enough player that it is useful to have an intermediate handler that fields resize events- even if you branch only IE clients to it.
The ie handler sets a short timeout(100-200 msec)before calling the 'real' resize handler. If the same function is called again before the timeout, it is either a bubblng event or the window is being dragged to a new size, so clear the timeout and set it again.
Here's a little piece of code I put together for the same thing.
(function () {
var width = window.innerWidth;
window.addEventListener('resize', function () {
if (window.innerWidth !== width) {
window.location.reload(true);
}
});
})();
I use
media="only screen and (min-width: 750px)" href="... css file for wide windows"
media="only screen and (max-width: 751px)" href="...css file for mobiles"
When I move the right windows border left and right to increase and decrease my window size, my web browser will automatically switch from the wide window to the mobile. I do not have to include any Javascript code to detect window width. This works for Chrome, Firefox and Internet Explorer on both Windows and Macintosh computers.

Categories

Resources