Acquire Internet Explorer window position - javascript

How do I get in Internet Explorer values equivalent to: window.screenX and window.screenY in Firefox ?
I've seen some "solution": window.screenLeft and window.screenTop but it is not correct. These properties give inner coordinates.
I move a window and I need values to use with window.moveTo() to restore the original location.

var saveLeft = window.screenLeft;
var saveTop = window.screenTop;
window.moveTo(saveLeft, saveTop);
var savePos = [
saveLeft + (saveLeft - window.screenLeft),
saveTop + (saveTop - window.screenTop)
];
Seems to work

Equivalent properties don't appear to exist for Internet Explorer windows. Have you seen the window.resizeBy(w, h) method? Using that you could grow by a specific amount and then shrink back down using negative values (or vice versa):
window.resizeBy(300, 300); // expand window by 300x300 pixels
window.setTimeout(function ()
{
window.resizeBy(-300, -300); // back to original size
}, 10000);

There are years since i did any MSIE programming, but i roughly remember using something like this
save screenLeft and Top as window postion (this is wrong but read on)
when restoring the position, window.moveTo(saved position)
(current screenLeft > saved Left) window.moveBy(-1,0)
the same for y position
the idea is that we place the window in a wrong position first and then correct it step by step

Related

Modify FireFox extension: If (scrollbar exists) var - 30 else var -14

Hello fellow code people :)
I am a frontend web developer and as such in need of constant knowledge of the actual viewport size in order to see where in responsive designing breakpoints start and end.
I know FF's own 'test window size' function, but came across a very handy extension: FireSizer.
the extension has one itsy bitsy drawback: It gives back the window-size including FF's borders and scrollbar. I need the viewport-size though. So I need the extension hacked, but dont't know enough javaScript to do so. Maybe someone is willing to help em out here?
I would love the extension to actually look for the scrollbar, and subtract from the width
a) 14 if no scrollbar present or
b) 30 if scrollbar present
I found of what I think is the right place to alter the code:
//
// Update the status bar panel with the current window size
//
function FiresizerUpdateStatus() {
var width = window.outerWidth + ''; // <- Think code needs to be edited here
var height = window.outerHeight + '';
document.getElementById("firesizer-statuspanel").label = width + 'x' + height;
}
Thanks for any effort!
AO
#Chen Asraf:
Well thank you very much. I didn't know there was an element to call the document-width. I changed the code to the following, and that did the trick (also when compared to FF's own 'Responsive Design View mode', which is spot on, its off by 2px - which i subtract from clientWidth.)
function FiresizerUpdateStatus() {
var width = window.outerWidth + ''; // changed this line to:
var width = document.documentElement.clientWidth-2 + '';
var height = window.outerHeight + '';
document.getElementById("firesizer-statuspanel").label = width + 'M' + height;
}
Thanks
AO
Possible duplicate of Get the browser viewport dimensions with JavaScript
Seems like you can get the window's inner dimensions by using:
// My window is maximized; screen is 1366x768
alert(document.documentElement.clientWidth);
// ^ returns 1349 (17 missing pixels because of scrollbar)
alert(document.documentElement.clientHeight);
// ^ returns 643 (125 pixels missing because of start bar & Chrome toolbars)
You can then compare the following with whatever else you need (for example, compare client width with window width to find if the difference is big enough to be a scrollbar - just experiment with the sizes)

Raphael JS : how to move/animate a path object?

Somehow this doesn't work...
var paper = Raphael("test", 500, 500);
var testpath = paper.path('M100 100L190 190');
var a = paper.rect(0,0,10,10);
a.attr('fill', 'silver');
a.mousedown( function() {
testpath.animate({x: 400}, 1000);
});
I can move rects this way but not paths, why is that, and how do I move a path object then?!
With the latest version of Raphael, you can do this:
var _transformedPath = Raphael.transformPath('M100 100L190 190', 'T400,0');
testpath.animate({path: _transformedPath}, 1000);
This saves you from the trouble of having to clone a temp object.
It seems a path object doesn't get a x,y value - so your animation probably still runs, but does nothing. Try instead animating the path function:
testpath.animate({path:'M400 100L490 190'},1000);
It makes it a bit trickier to write the animation, but you have the benefit of getting rotation and scaling for free!
BTW: I'm sure this is just an example, but in your above code testpath gets put in the global scope because you don't initialize as var testpath
Solved, with thanx to Rudu!
You need to create a new path to animate to. You can do this with clone() and then apply the transformations to that clone. Seems very complex for a simple move like this, but it works...
var paper = Raphael("test", 500, 500);
var testpath = paper.path('M100 100L190 190');
var a = paper.rect(0,0,10,10);
a.attr('fill', 'silver');
a.mousedown( function() {
var temp = testpath.clone();
temp.translate(400,0);
testpath.animate({path: temp.attr('path')}, 1000);
temp.remove();
});
TimDog answer was best solution.
In addition, just remember, transform string in this case means, that it will add 400 points to every path point/line X coordinate, and 0 points to every Y coordinate.
That means, M100 100L190 190 will turn into M500 100L590 190.
So, if you need to move a path element to another position, the difference between current position and new position coordinates should be calculated. You can use first element to do that:
var newCoordinates = [300, 200],
curPos = testpath.path[0],
newPosX = newCoordinates[0] - curPos[1],
newPosY = newCoordinates[1] - curPos[2];
var _transformedPath = Raphael.transformPath(testpath.path, "T"+newPosX+","+newPosY);
testpath.animate({path: _transformedPath});
Hope this will help someone.
Here's some code that generalises the best of the above answers and gives Raphael paths a simple .attr({pathXY: [newXPos, newYPos]}) attribute similar to .attr({x: newXPosition}) and .animate({x: newXPosition}) for shapes.
This lets you move your path to a fixed, absolute position or move it by a relative amount in a standard way without hardcoding path strings or custom calculations.
Edit: Code below works in IE7 and IE8. An earlier version of this failed in IE8 / VML mode due to a Raphael bug that returns arrays to .attr('path') in SVG mode but strings to .attr('path') in VML mode.
Code
Add this code (Raphael customAttribute, and helper function) after defining paper, use as below.
paper.customAttributes.pathXY = function( x,y ) {
// use with .attr({pathXY: [x,y]});
// call element.pathXY() before animating with .animate({pathXY: [x,y]})
var pathArray = Raphael.parsePathString(this.attr('path'));
var transformArray = ['T', x - this.pathXY('x'), y - this.pathXY('y') ];
return {
path: Raphael.transformPath( pathArray, transformArray)
};
};
Raphael.st.pathXY = function(xy) {
// pass 'x' or 'y' to get average x or y pos of set
// pass nothing to initiate set for pathXY animation
// recursive to work for sets, sets of sets, etc
var sum = 0, counter = 0;
this.forEach( function( element ){
var position = ( element.pathXY(xy) );
if(position){
sum += parseFloat(position);
counter++;
}
});
return (sum / counter);
};
Raphael.el.pathXY = function(xy) {
// pass 'x' or 'y' to get x or y pos of element
// pass nothing to initiate element for pathXY animation
// can use in same way for elements and sets alike
if(xy == 'x' || xy == 'y'){ // to get x or y of path
xy = (xy == 'x') ? 1 : 2;
var pathPos = Raphael.parsePathString(this.attr('path'))[0][xy];
return pathPos;
} else { // to initialise a path's pathXY, for animation
this.attr({pathXY: [this.pathXY('x'),this.pathXY('y')]});
}
};
Usage
For absolute translation (move to fixed X,Y position) - Live JSBIN demo
Works with any path or set of paths including sets of sets (demo). Note that since Raphael sets are arrays not groups, it moves each item in the set to the defined position - not the centre of the set.
// moves to x=200, y=300 regardless of previous transformations
path.attr({pathXY: [200,300]});
// moves x only, keeps current y position
path.attr({pathXY: [200,path.pathXY('y')]});
// moves y only, keeps current x position
path.attr({pathXY: [path.pathXY('x'),300]});
Raphael needs to handle both x and y co-ordinates together in the same customAttribute so they can animate together and so they stay in sync with each other.
For relative translation (move by +/- X,Y) - Live JSBIN demo
// moves down, right by 10
path.attr({pathXY: [ path.pathXY('x')+10, path.pathXY('y')+10 ]},500);
This also works with sets, but again don't forget that Raphael's sets aren't like groups - each object moves to one position relative to the average position of the set, so results may not be what are expected (example demo).
For animation (move a path to relative or absolute positions)
Before animating the first time, you need to set the pathXY values, due to a bug/missing feature up to Raphael 2.1.0 where all customAttributes need to be given a numeric value before they are animated (otherwise, they will turn every number into NaN and do nothing, failing silently with no errors, or not animating and jumping straight to the final position).
Before using .animate({pathXY: [newX,newY]});, run this helper function:
somePath.pathXY();
Yet another way is to use "transform" attribute:
testpath.animate({transform: "t400,0"}, 1000);
to move the path to the right by 400px, relative to the original position.
This should work for all shapes, including paths and rectangles.
Note that:
"transform" attribute is independent of x, y, cx, cy, etc. So these attributes are not updated by the animation above.
The value of "transform" attribute is always based on the original position, not the current position. If you apply the animation below after the animation above, it will move it 800px to the left relatively, instead of moving it back to its original position.
testpath.animate({transform: "t-400,0"}, 1000);

How to map deviceorientation to MozOrientation values

I have previously created a labyrinth game which works with Firefox's MozOrientation. I am now looking into getting it working with WebKit also...
But Webkit uses the w3c's DeviceOrientation. The values appear to be totally different, but someone must have some algorithm to get it from one to the other? Or am I missing something simple?
The labyrinth game with github link
http://playground.marmaladeontoast.co.uk/labyrinth/
MozOrientation
https://developer.mozilla.org/en/Detecting_device_orientation
DeviceOrientation
http://dev.w3.org/geo/api/spec-source-orientation.html
Some sample values I have obtained:
Chrome
alpha = null
beta = -178
gamma = 4.57
Firefox
x = 0.035999998450279236
y = -0.02800000086426735
z = 1
Any help would be greatly appreciated :)
I've been playing around with this a bit. The source below 'maps' both alternatives to an understandable degrees range for x/gamma and y/beta.
The MozOrientation.z value is completely different from the deviceorientation.alpha value. The first returns the vertical orientation, the latter returns a sort of compass value. These values are therefor not interchangable / convertible.
function displayOrientation(orientData){
var x = Math.round(orientData.x);
var y = Math.round(orientData.y);
var z = orientData.z;
document.getElementById('x').value = x;
document.getElementById('y').value = y;
document.getElementById('z').value = z;
}
window.addEventListener("MozOrientation", function(orientData){
var obj = {};
obj.x = orientData.x * 90;
obj.y = orientData.y * 90;
obj.z = orientData.z;
displayOrientation(obj);
}, true);
window.addEventListener("deviceorientation", function(orientData) {
var obj = {};
obj.x = orientData.gamma;
obj.y = orientData.beta;
obj.z = orientData.alpha;
displayOrientation(obj);
}, true);
It seems the current desktop Safari (5.0.3) doesn't support this event at all. The beta value in desktop Chrome 9 is exactly 180 less than it is in mobile Safari.
The x & y values in Firefox and mobile Safari should be approximately the same.
I hope that this codes clarify everything. Although the values this code returns can't be matched directly with the values of beta and gamma:
Mozilla returns the sin of the angle so, to get the angle...
X: Math.asin(eventInfo.x)*180/Math.PI
Y: Math.asin(eventInfo.y)*180/Math.PI
Z: Math.asin(eventInfo.z)*180/Math.PI
Webkit returns the acceleration in each axe. Then, to get the angle... (The sing changes is just to unify returned values)
X: Math.asin(clean(eventInfo.accelerationIncludingGravity.x/GRAVITY))*180/Math.PI
Y: Math.asin(clean(-eventInfo.accelerationIncludingGravity.y/GRAVITY))*180/Math.PI
Z: Math.asin(clean(-eventInfo.accelerationIncludingGravity.z/GRAVITY))*180/Math.PI
Being clean: (Because sometimes, the data returned, even without accelerating the phone, it's more than 9.8)
function clean(data)
{
if(data<-1.0)
{
return -1.0;
}
else
{if(data>1.0)
{
return 1.0;
}else
{
return data;
}}
}
The meaning of each axe is:
X-> inclination of the mobile to its right or left. Will be + if you tilt the mobile to its right (clockwise), keeping the buttons of volume up.
Y-> Tells if the mobile is up -if the lock/on-off button is up- (angle +) or down (angle -). It tells the inclination of the mobile relative to the floor. (angle of Y vector with plane X-Z)
Z-> Tells if the mobile screen is facing up (angle +) or upside down (angle -). It's the angle of the Z vector on the plane Y-X
Hope this is worthy for you!
Anyway, I'm working on some GWT classes to make working with this easier :) It's not difficult but I do not have so much time.
I'll tell you
You should be able to calculate one according to the other.
The problem I see is that Mozilla doesn't tell what means the data it returns.
I'm working now with three mobile devices: ipad, iphone4 and nokia n900.
When I work with iOS and safari and I get the accelerationIncludingGravity, I get values from -9.8 to 9.8. Those are values of the gravity that affect each axe. Then using trigonometry, I can calculate the angle in each axe.
If I get orientation in the iphone4, I can get directly the angle in each axe.
The problem comes with nokia n900, whose browser is based in Mozilla. That browser only returns data from -1 to 1. Documentation says that it's the tilt of each axe. In what unities? Cosine? Or just angle/180?
I guess that it's the cosine as when I put it in horizontal, it returns 0, and when I put it in vertical, it gets 1. And upside down, returns -1. Moreover, If you tilt it in aprox 60degrees, it returns 1/2.
As far I've seen, when using a Macbook laptop with Firefox, the data x,y and z is get as the cosine.
Mozilla Firefox now fully supports the W3C DeviceOrientation Events API. You should not use MozOrientation in your web applications any more.

Detecting if the browser window is moved with JavaScript?

This is for a demo... and i was just curious, can you detect if the window has been moved? Like if you move Firefox/Chrome/IE around your monitor? I doubt it, but I wanted to see since you can check for resize and focus/blurred windows.
I can only think of this (heavy) work-around, where you check if window.screenX and window.screenY have changed every x milliseconds
var oldX = window.screenX,
oldY = window.screenY;
var interval = setInterval(function(){
if(oldX != window.screenX || oldY != window.screenY){
console.log('moved!');
} else {
console.log('not moved!');
}
oldX = window.screenX;
oldY = window.screenY;
}, 500);
Though I would not recommend this -- it might be slow and I'm not sure if screenX and screenY are supported by all browsers
A potentially more optimised version of this is to only check for window movement when outside of the window combined with Harmen's answer:
var interval;
window.addEventListener("mouseout", function(evt){
if (evt.toElement === null && evt.relatedTarget === null) {
//if outside the window...
if (console) console.log("out");
interval = setInterval(function () {
//do something with evt.screenX/evt.screenY
}, 250);
} else {
//if inside the window...
if (console) console.log("in");
clearInterval(interval);
}
});
If using jQuery, it may normalise screenX/Y in this case so it's worth running a few tests on that. Jquery would use this format instead of addEventListener:
$(window).on('mouseout', function () {});
If you are moving the window in Windows OS via alt + Space, and find that windows resizes are ignored, I would recommend adding an extra level of detection via keypress events.
Re the first answer: I use the 'poll window position' in production code. It's a very lightweight thing to do. Asking for a couple of object properties twice a second is not going to slow anything down. Cross-browser window position is given by:
function get_window_x_pos()
{
var winx;
if(window.screenX)
winx=window.screenX;
else if(window.screenLeft)
winx=window.screenLeft;
return winx;
}
and similarly for vertical position. In my code I use this to fire an AJAX event off to the server to store position and size of the window so next time it will open where it was the last time (I'm probably moving to HTML5 local storage soon.) One little wrinkle you might want to cover is not generating spurious updates while the window is being dragged. The way to handle this is to register when the window has been moved for the first time and only trigger an update when two subsequent polls of window position return the same value. A further complication is for windows which allow resizing from all sides. If the left or top side are dragged, the DOM will give you a resize event, but the nominal window position will have altered as well.
Unfortunately not. The DOM is only notified about window sizes, cursor positions, "focus" and "blur", etc; anything that affects drawing. Since moving a window doesn't necessarily require any of the contents to be "redrawn" (in a Javascript/Html engine sort of sense), the DOM, therefore, doesn't need to know about it.
Sadly, no. Although I did find this page that claims there is such a thing. I tested that in IE, Chrome, and FireFox, no luck.

Javascript execution order issues with Dojo

Before I ask my question, here's the offending code:
var coords = dojo.coords(g);
g.style.left = coords.x + "px";
g.style.top = coords.y + "px";
g.style.position = "absolute";
Now imagine that g is a relatively positioned element with an x position of 70 and a y position of 30. If I comment out the last line of the above code, that's what dojo.coords(g) gives me. But as soon as I add the last line, dojo.coords(g) returns an x position of 18, which is where the element would be if it were absolutely positioned. It seems to me that the call to dojo.coords() shouldn't be affected by code below it, but it is.
I'm also seeing the same problem with dojo.require() where if I call it directly before the function call that it's loading, I get an undefined error for that given function.
I'm testing in Firefox 3, but I also am noticing similar problems in Safari 3. Any ideas?
It is not the Dojo quirk but the way browsers work. Basically it may take some time for DOM to reflect your changes and reposition elements, or even change the layout. That's why you see what you see.
Another reason may be in the parent of your element. dojo.coords() returns the position relative to the viewport. If you pass "true" as the second value, it will return the position relative to the document root. Assigning top/left directly and changing position to "absolute" makes the element positioned relatively to its parent, if it was positioned too (absolute, relative, or fixed), or to the document root. It is a subtle difference, but sometimes it bites people. Relevant references: Containing Block, MSDN: position Attribute, Google doctype: position.
PS: personally I rely on Dojo to set left/top hoping it'll do the right thing working around browser quirks, and I set the position first:
var coords = dojo.coords(g);
g.style.position = "absolute";
dojo.marginBox(g, {l: coords.x, t: coords.y});
I still would love someone to explain why this works, but here's a solution:
var coords = dojo.coords(g);
g.style.left = coords.x + "px";
g.style.top = coords.y + "px";
setTimeout(function(h) {
h.style.position = "absolute";
}, 0, g);
Cheers
sorry to not respond your question, (because I do not know dojo) but unless coords.x and coords.y returns a string, there is an error in your function,
g.style.left = coords.x + "px";
g.style.top = coords.y + "px";
You need to pass always a string to style, so add these also:
g.style.left = parseInt(coords.x) + "px";
g.style.top = parseInt(coords.y) + "px";
You would be surprised how many times this kind of error got my head spinning. About the answer, sorry, but I can't help you.
Good luck!
Edited:
Oh, if I understood, I can help you now.. well, since I do not know dojo, I can point out to you a javascript similar that will do what you want.
g.offsetTop
and
g.offsetLeft
Will give you the coords from the position of the element. Try them out and see if it works..

Categories

Resources