What is different with window and div widths between firefox and IE - javascript

I have a web page that uses a scrolling div to display table information. When the window is resized (and also on page load), the display is centered and the div's scrollbar positioned to the right of the page by setting its width. For some reason, the behaviour is different under firefox than IE. IE positions/sizes the div as expected, but firefox seems to make it too wide, such that the scrollbar begins to disappear when the window client width reaches about 800px. I'm using the following methods to set the position and size:
function getWindowWidth() {
var windowWidth = 0;
if (typeof(window.innerWidth) == 'number') {
windowWidth=window.innerWidth;
}
else {
if (document.documentElement && document.documentElement.clientWidth) {
windowWidth=document.documentElement.clientWidth ;
}
else {
if (document.body && document.body.clientWidth) {
windowWidth=document.body.clientWidth;
}
}
}
return windowWidth;
}
function findLPos(obj) {
var curleft = 0;
if (obj.offsetParent) {
curleft = obj.offsetLeft
while (obj = obj.offsetParent) {
curleft += obj.offsetLeft
}
}
return curleft;
}
var bdydiv;
var coldiv;
document.body.style.overflow="hidden";
window.onload=resizeDivs;
window.onresize=resizeDivs;
function resizeDivs(){
bdydiv=document.getElementById('bdydiv');
coldiv=document.getElementById('coldiv');
var winWdth=getWindowWidth();
var rghtMarg = 0;
var colHdrTbl=document.getElementById('colHdrTbl');
rghtMarg = parseInt((winWdth - 766) / 2) - 8;
rghtMarg = (rghtMarg > 0 ? rghtMarg : 0);
coldiv.style.paddingLeft = rghtMarg + "px";
bdydiv.style.paddingLeft = rghtMarg + "px";
var bdydivLft=findLPos(bdydiv);
if ((winWdth - bdydivLft) >= 1){
bdydiv.style.width = winWdth - bdydivLft;
coldiv.style.width = bdydiv.style.width;
}
syncScroll();
}
function syncScroll(){
if(coldiv.scrollLeft>=0){
coldiv.scrollLeft=bdydiv.scrollLeft;
}
}
Note that I've cut out other code which sets height, and other non-relevant parts. The full page can be seen here. If you go to the link in both IE and firefox, resize width until "800" is displayed in the green box top-right, and resize height until the scrollbar at the right is enabled, you can see the problem. If you then resize the IE width, the scrollbar stays, but if you resize the firefox width wider, the scrollbar begins to disappear. I'm at a loss as to why this is happening....
Note that AFAIK, getWindowWidth() should be cross-browser-compatible, but I'm not so sure about findLPos().... perhaps there's an extra object in Firefox's DOM or something, which is changing the result??

You are dealing with "one of the best-known software bugs in a popular implementation of Cascading Style Sheets (CSS)" according to Wikipedia. I recommend the Element dimensions and CSS Object Model View pages on Quirksmode.org.
Also: I think you'll find that Safari and Opera behave like Firefox in most circumstances. A more compatible approach to working around these problems is testing for, and making exceptions for, MSIE instead of the other way around.

Ok, I found the problem. Seems to be that firefox does not include the style.paddingLeft value in its style.width setting, whereas IE does, thus the div was ending up exactly style.paddingLeft too wide. That is, if for example style.paddingLeft is 8, IE's style.width value would be 8 more than FireFox's - and thus the inverse when setting the value, for FireFox I needed to subtract the style.paddingLeft value
Modified code with:
if (__isFireFox){
bdydiv.style.width = winWdth - bdydivLft - rghtMarg;
} else {
bdydiv.style.width = winWdth - bdydivLft;
}

As long as you don't include a valid doctype, you can't expect consistent results, due to Quirks Mode. Go add one (HTML 4.01 Transitional is fine), then let us know if it still occurs.
Also see http://en.wikipedia.org/wiki/Quirks_mode.

In your getWindowWidth() function, whenever you grab the width of something, instead of this:
windowWidth = document.documentElement.clientWidth;
try this
windowWidth = Math.max(document.documentElement.scrollWidth, document.documentElement.clientWidth);

A detail to help optimize some of your code:
function getPos(elm) {//jumper
for(var zx=zy=0;elm!=null;zx+=elm.offsetLeft,zy+=elm.offsetTop,elm=elm.offsetParent);
return {x:zx,y:zy}
}
(jumper is a user who posted this code in Eksperten.dk)

Related

Resize table columns with mouse

I am writing a script to allow a client to mouse drag table cell borders and resize columns in a table. So far I have a working model in Firefox but there is a flaw in width measurement that leaves the mouse out of sync when the change gets large. Worse, the script fails in other browsers (opera,safari) or even if I change the browser zoom in Firefox.
function doDrag() {document.body.style.cursor='crosshair';}
function noDrag() {document.body.style.cursor='auto';}
var xpos=0;
var sz=0;
var dragObj = {};
function resizeOn(el)
{
dragObj = document.getElementById(el);
document.addEventListener("mousemove",resize, true);
document.addEventListener("mouseup",resizeOff, true);
}
function resize(ev)
{
if(xpos == 0) {xpos=ev.clientX;}
if(xpos != ev.clientX)
{
sz = dragObj.offsetWidth + (ev.clientX - xpos);
dragObj.style.width = sz - 10 + "px";
alert("size="+sz+" offsetwidth="+dragObj.offsetWidth);
if(dragObj.offsetWidth != sz)
{
resizeOff();
return false;
}
xpos=ev.clientX;
}
}
function resizeOff()
{
xpos = 0;
document.removeEventListener("mousemove",resize, true);
document.removeEventListener("mouseup",resizeOff, true);
}
The HTML looks like:
<th id="col0" class="edit">client</th>
<th class="drag" onmouseover="doDrag()" onmouseout="noDrag()" onmousedown="resizeOn('col0')"></th>
The second cell is made to appear as the right edge of the first.
I assume the problem is dragObj.style.width = sz - 10. The -10 was derived purely by trial and error. I suspect this is the difference between the actual width of the cell including borders, padding etc and offsetwidth. It should really be, per my css, 10 for padding + 1 for the left border = 11px. Either my fixed padding/borders aren't staying fixed or there is some other css property between the offsetWidth and the actual with of the element. Is there some way to get the actual width of the element regardless of the browsers scaling?
Have a look at the documentation in www.quirksmode.org and/or http://help.dottoro.com. Confirm whether the properties are supported by your target browser. They also have comments on how zoom affects offsetX and similar.
Also, you should note that ev.clientX has been broken in IE by a recent patch (KB2846071). If the patch is installed, clientX returns a meaningless result.
Hopefully MS will release a patch for their patch!

Browser detection using javascript failing on refresh

I'm trying to detect for devices that do not have support for position:fixed. EDIT: I've fixed the code so it's detecting features rather than browser/OS detection.
I think I was confusing people when I first typed this out. My issue is coming into play when I refresh the page. The height is being incorrectly calculated, which is a completely different issue I know, but am looking for assistance nonetheless.
Updated detection script below:
function fixed() {
var container = document.body;
if (document.createElement && container && container.appendChild && container.removeChild) {
var el = document.createElement('div');
if (!el.getBoundingClientRect) return null;
el.innerHTML = 'x';
el.style.cssText = 'position:fixed;top:100px;';
container.appendChild(el);
var originalHeight = container.style.height,
originalScrollTop = container.scrollTop;
container.style.height = '3000px';
container.scrollTop = 500;
var elementTop = el.getBoundingClientRect().top;
container.style.height = originalHeight;
var isSupported = (elementTop === 100);
container.removeChild(el);
container.scrollTop = originalScrollTop;
return isSupported;
}
return null;
}
//TEST FOR MOBILE, SET TOP IMAGE TO RELATIVE
if(fixed()) {
image_height = jQuery("#outer_homepage_image").height() - 45;
jQuery("#content").css("top",image_height);
jQuery(window).resize(function() {
image_height = jQuery("#outer_homepage_image").height() - 45;
alert(image_height);
jQuery("#content").css("top",image_height);
});
} else {
jQuery("#outer_homepage_image").css("position","relative");
}
This is an extremely brittle and ill-conceived thing to be doing.
if(/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)) {
For example, iOS has fully supported position:fixed properly since iOS 4. We're now on 6. For Android & Blackberry, I'm not sure but would err on the side of "supported".
You need to test for features, not user agent. As I said, you could have one iOS device that doesn't support it and another one that does. Indeed, most do these days.
Here's a helpful link to lead you to moral, godly choices: http://kangax.github.com/cft/#IS_POSITION_FIXED_SUPPORTED
Thanks for all the support guys. I solved it with jQuery(window).load(function() {
it works now because everything else is loaded so I can calculate the proper height.

Getting current page position in IE8 when scrolling

Reference is this page:
http://demo.mypreviewbetasite.com/laverona/menu.html
File in question: http://demo.mypreviewbetasite.com/laverona/scripts/menu.js
The page works as expected in Firefox and Chrome, where as the user scrolls, the position of the window is checked against the position of my sub-menu, so that before it gets scrolled out of view, its position is set to fixed.
However, in IE8, the window position never gets updated as the user scrolls. My testing has shown that IE gets through all the functions, but only updates the windowPos variable when the page loads.
What can be done so that this page behaves the same in IE as it does in FF and Chrome?
this is from jquery documentation:
"The .offset() method allows us to retrieve the current position of an element RELATIVE TO THE DOCUMENT."
I can't understand why FF or Chrome return $('html').offset().top relative to the client screen/ It seems that IE's approach is more predictable.
Try that (use .scrollTop property of the DOM element instead of .offset().top):
$(document).ready(function(e){
//alert("subPos: " + subPos);
//first find the position of the things to sticky
submenu = $("#sub");
//submenu.removeClass("no-js");
subPos = $("#sub").position();
subPos = subPos.top;
var preScrollHtml = document.getElementsByTagName('html').item(0).scrollTop;
var preScrollBody = document.getElementsByTagName('body').item(0).scrollTop;
var checkPos = function(){
var scrolledHtml = document.getElementsByTagName('html').item(0).scrollTop;
var scrolledBody = document.getElementsByTagName('body').item(0).scrollTop;
if (preScrollHtml !== scrolledHtml) {
windowPos = scrolledHtml;
}
else {
windowPos = scrolledBody;
}
preScrollHtml = scrolledHtml;
preScrollBody = scrolledBody;
calculate();
}
var calculate = function() {
subPos = 64;
if (windowPos >= subPos){
$("#sub").addClass("fixed");
$("#minestre").css("marginTop", "50px");
}
else if (windowPos < subPos){
$("#sub").removeClass("fixed");
$("#minestre").css("marginTop", "0px");
}
//Setting text fields to show the values of everything can help in debugging
$("#windowpos").val(windowPos);
$("#subp").val(subPos);
}
//every time the window scrolls, this function is run
if ($(window).scroll){
$(window).scroll(checkPos);
}
else if(window.onscroll){
window.onscroll = checkPos;
}
});
I know this is old, but for new people coming to this question, you may want to check out Andy's answer to a similar question (which also seems to solve this one): https://stackoverflow.com/a/11396681/1793128

Resizing an image using Javascript running in Opera Browser

I hope someone can help with this quirky issue I am having with the Opera Browser, I have version 11 Beta installed, but I suspect is a common problem in Opera.
The website and page in question is http://www.amigaos.net/index.html.
At the bottom of the body of the html I have the following code which resizes the 3 images you see on this webpage depending on width of the viewport at page load. In Safari and FireFox the code works fine, but in Opera the following lines which involve resizing the width and height of an image do not work:
document.getElementById('img1').width = '475';
document.getElementById('img1').height = '375';
Here is the code in full (sorry, about the layout, stackoverflow hasn't formatted carriage returns correctly)
<script type="text/javascript">
function GetWidth()
{
var x = 0;
if (typeof window.innerWidth != 'undefined')
{
x = window.innerWidth;
}
else if (document.documentElement && document.documentElement.clientHeight)
{
x = document.documentElement.clientWidth;
}
else if (document.body)
{
x = document.getElementsByTagName('body')[0].clientWidth;
}
return x;
}
width = GetWidth();
if (width>=1680)
{
document.getElementById('img1').width = '475';
document.getElementById('img1').height = '375';
document.getElementById('img2').width = '475';
document.getElementById('img2').height = '375';
document.getElementById('img3').width = '475';
document.getElementById('img3').height = '375';
}
else if ((width>800) && (width<=1280))
{
document.getElementById('img1').width = '300';
document.getElementById('img1').height = '235';
document.getElementById('img2').width = '300';
document.getElementById('img2').height = '235';
document.getElementById('img3').width = '300';
document.getElementById('img3').height = '235';
}
else if (width<=800)
{
document.getElementById('img1').width = '225';
document.getElementById('img1').height = '195';
document.getElementById('img2').width = '225';
document.getElementById('img2').height = '195';
document.getElementById('img3').width = '225';
document.getElementById('img3').height = '195';
}
</script>
instead of doing width and height attributes, I think you can just set width: 33% via CSS and have the scaling happen automatically, regardless of the browser window size. Better solution than trying to use javascript, IMHO.
Here's a simple tutorial: http://haslayout.net/css-tuts/CSS-Proportional-Image-Scale
you are making this way too complicated. I don't think your issue is browser-specific, you just need to recode your script.
First. I would recommmend using percentages.. Not sure how you will guess the visitors browser width in pixels.
Let's say that your three resizeable images are 20% width of your browser. So your css would be:
#img1, #img2, #img3 {
width: 20%;
}
now that your css says that your images are 20% of the total with, you're good to add some js. Keep in mind that the percentage will be that of its outer container.
<script type=text/javascript">
function resizeImages() {
document.getElementById('img1').style.height = (document.body.clientHeight - 100) * 0.2;
document.getElementById('img2').style.height = (document.body.clientHeight - 100) * 0.2;
document.getElementById('img3').style.height = (document.body.clientHeight - 100) * 0.2;
}
</script>
and most importantly.. call your function:
add this to your body tag:
<body onresize="resizeImages()">
boom.. you're done.

Determine if an HTML element's content overflows

Can I use JavaScript to check (irrespective of scrollbars) if an HTML element has overflowed its content? For example, a long div with small, fixed size, the overflow property set to visible, and no scrollbars on the element.
Normally, you can compare the client[Height|Width] with scroll[Height|Width] in order to detect this... but the values will be the same when overflow is visible. So, a detection routine must account for this:
// Determines if the passed element is overflowing its bounds,
// either vertically or horizontally.
// Will temporarily modify the "overflow" style to detect this
// if necessary.
function checkOverflow(el)
{
var curOverflow = el.style.overflow;
if ( !curOverflow || curOverflow === "visible" )
el.style.overflow = "hidden";
var isOverflowing = el.clientWidth < el.scrollWidth
|| el.clientHeight < el.scrollHeight;
el.style.overflow = curOverflow;
return isOverflowing;
}
Tested in FF3, FF40.0.2, IE6, Chrome 0.2.149.30.
Try comparing element.scrollHeight / element.scrollWidth to element.offsetHeight / element.offsetWidth
http://developer.mozilla.org/en/DOM/element.offsetWidth
http://developer.mozilla.org/en/DOM/element.offsetHeight
http://developer.mozilla.org/en/DOM/element.scrollWidth
http://developer.mozilla.org/en/DOM/element.scrollHeight
Another way is compare the element width with its parent's width:
function checkOverflow(elem) {
const elemWidth = elem.getBoundingClientRect().width
const parentWidth = elem.parentElement.getBoundingClientRect().width
return elemWidth > parentWidth
}
I don't think this answer is perfect. Sometimes the scrollWidth/clientWidth/offsetWidth are the same even though the text is overflow.
This works well in Chrome, but not in IE and Firefox.
At last, I tried this answer: HTML text-overflow ellipsis detection
It's perfect and works well anywhere. So I choose this, maybe you can try, you won't disappoint.
I didn't like any of these, so I wrote this one. Works great!
function isOverflowY(element) {
return element.scrollHeight != Math.max(element.offsetHeight, element.clientHeight)
}
With jQuery you could do:
if ( $(".inner-element").prop('scrollHeight') > $(".inner-element").height() ) {
console.log("element is overflowing");
} else {
console.log("element is not overflowing");
}
Change to .prop('scrollWidth') and .width() if needed.
This is a javascript solution (with Mootools) that will reduce the font size to fit the bounds of elHeader.
while (elHeader.clientWidth < elHeader.scrollWidth || elHeader.clientHeight < elHeader.scrollHeight) {
var f = parseInt(elHeader.getStyle('font-size'), 10);
f--;
elHeader.setStyle('font-size', f + 'px');
}
The CSS of elHeader:
width:100%;
font-size:40px;
line-height:36px;
font-family:Arial;
text-align:center;
max-height:36px;
overflow:hidden;
Note the wrapper of elHeader sets the width of elHeader.

Categories

Resources