Firefox Javascript: Why does .all not work? - javascript

In IE, I can go like:
var x = document.getElementById("header");
alert(x.all[0].tagName);
If I try that in Firefox, I get the error "all is undefined".
What is the Firefox equivalent of IE's .all property?

.all is a Microsoft-specific extension to the DOM, and is not supported by any other browsers (except Opera, I believe, who simulate it in order to improve compatibility with sites written for IE).
You can use things like x.children and x.childNodes, or x.getElementById() and x.getElementsByTagName() to reference elements below the current one in the tree, depending on your usage. I suspect in this case x.children is what you're after.

all would be the name of an array. It is not a native javascript keyword.
You may want to look at childNodes instead.

Related

Object.defineProperty for all browsers?

Asking about Object.defineProperty as demonstrated below:
function testComponent(){
var testProperty;
Object.defineProperty(this, "testProperty",
{
get : function()
{
return testProperty;
},
set : function(val)
{
testProperty = val;
}
});
}
Where it would be used like so:
testObject = new testComponent();
testObject.testProperty = "testValue";
Based on what I've seen so far, it looks like there is no cross browser solution, as I've tried using es5-shim with no luck, but I would like to confirm. I also found a reference to this post and my tests still fail in IE 7 & 8, can anyone shed any light on this?
I remember looking through a related question a few months ago somewhere on S/O and I think I saw someone had written a solution for this in an answer. Any general workarounds for getter / setters would also be appreciated. The idea is that I need some equivalent of a getter setter on an object without passing the parameter change through a method. I don't need IE6, but I would like to support browsers in the range of IE7+ ff 3.6+ , etc
QUnit tests below: (jsFiddles)
(these pass in all browsers on my machine except IE 7 & 8
direct use of defineProperty, no shims: http://jsfiddle.net/uSYFE/
fiddle using the ES5 shim, I'm assuming all I need to do is include it? : http://jsfiddle.net/hyperthalamus/ntwDy/
fiddle using the IE recommended solution : http://jsfiddle.net/hyperthalamus/xfvz3/
According to ES5-shim:
/!\ Object.defineProperty
This method will silently fail to set "writable", "enumerable", and "configurable" properties.
Providing a getter or setter with "get" or "set" on a descriptor will silently fail on engines that lack "defineGetter" and "defineSetter", which include all versions of IE up to version 8 so far.
IE 8 provides a version of this method but it only works on DOM objects. Thus, the shim will not get installed and attempts to set "value" properties will fail silently on non-DOM objects.
https://github.com/kriskowal/es5-shim/issues#issue/5
So you know your answer. It can be done on DOM elements, that's it (and on IE8 only).
I'd suggest you just use get/set methods if you want IE7 to work.
For older IEs you'd have to make sure your property is a dom object (even a fake tag) and use onPropertyChange to get notified. See this post by John Dyer for more details.
I've had this same question myself. (See here.) It doesn't look like it's fully possible in IE8 or lower. Otherwise the ES5 Shim is your best bet.

Old JavaScript Function Crashes Browser

I'm integrating a mootools script onto a page which has very old JavaScript functions which run a navigation vertical menu. This old script will be hard to change now.
The line breaking is:
function stgobj(id) {
with(document) return nIE && nVER < 5 ? all[id] : nNN4 ? layers[id] : getElementById(id);
}
Not sure exactly what's it's purpose, but it looks like it's rendering some elements. If commented the menu will disappear.
FF, Chrome, IE(doesn't crash, but menu does not render)
Any quick patch to resolve the browsers crashing?
Looks like its purpose is to return the element corresponding to the given ID. The code simply uses some different methods based on the browser - document.all for IE5 and earlier, and document.layers for Netscape 4. Unless you need to support those ancient browsers, you could alter the function to return just document.getElementById(id). Or better yet, ditch this function altogether and call document.getElementById directly.
However, if it's crashing modern browsers like Firefox and Chrome, then you should also look at the browser detection logic (the code that populates the nIE, nVER and nNN4 variables), otherwise it might just end up crashing elsewhere.
It's a "compatibility" function for document.getElementById. I think you should be able to equal it:
stgobj = document.getElementById.bind(document);

Is Math.ceil() & Math.round() supported on IE8?

I have a Javascript function that calculates a value and re-inserts the value into a <td> while also injecting the value into a hidden <input>.
This is my function:
$("input[name^='policies']:checkbox").change(function() {
var el = $(this);
if (el.is(":checked")) {
no_policies++;
}
if (el.is(":not(:checked)")) {
no_policies--;
}
subscription = no_policies*policy_cost;
first_payment = Math.ceil(subscription+no_policies*(policy_cost/days_month)*days_left).toFixed(2);
alert(first_payment);
$("td#first_payment").text("R "+first_payment);
$("input#first_payment_txt").val(first_payment);
$("td#subscription").text("R "+subscription.toFixed(2));
});
Everything works on IE8 up until this statement:
first_payment = Math.ceil(subscription+no_policies*(policy_cost/days_month)*days_left).toFixed(2);
I suspect IE8 is having trouble with Math.ceil, is that true? Also, is there any other function/method I can use to circumvent this?
Thanks in advance.
Answer is yes to both your questions:
Math.ceil()
Math.round()
Supported in the following document
modes: Quirks, Internet Explorer 6
standards, Internet Explorer 7
standards, Internet Explorer 8
standards, Internet Explorer 9
standards.
See also general table of Javascript compatibility for different IE versions:
Seems like microsoft supports Math.ceil on all versions beginning from ie6 (msdn), maybe one of the variables use is undefined or you devide by 0 or one of the variables is not a number so the result cannot be ceiled/rounded.
IE8 actually has a fairly good debugger. I recommend hitting F12 to open it, then going to the Script tab and selecting the Start Debugging button. This will let you set breakpoints along the script, letting it stop and wait for you to analyze variables as it executes at your own pace. As Adriano mentions in his comment, it's most likely an issue with one of your variables.

IE won't split string with Javascript

I have the following code:
$('#smallcart .plusone').live('click',function(){
var id = $(this).attr('id');
articlenr = id.split('_')[1];
});
this works fine in FF, safari, Chrome, however in IE (7 and 8) it throws an error on the split-function (this property or method is not supported by this object).
if I alert the 'id'-variable I get something like plus_5751. (so I want to get the '5751' part)
if I do alert(typeof(id)) I get String as an answer...
Maybe somebody can point me to the right answer?
Thx
The split works pretty well in IE. The problem is the part left of the equal-sign. It's an object with all input-fields having the name articlenr and therefor IE quits with 'this property or method is not supported by this object' when you're trying to assign a string to it.
Your code works just fine for me in Internet Explorer - as it should be expected to. The problem must lie elsewhere, perhaps something is overriding String.prototype.split?. You can see a working example of your code at http://jsfiddle.net/AndyE/6K77Y/. The first thing to check for is any Internet Explorer specific code in your scripts.
I would make one small improvement for efficiency. $(this).attr('id'); is pretty much the long winded way of writing this.id. It's slower, because a new jQuery object has to be created and then the attr function has to run. Without it, your code can be compressed more, whilst still remaining very readable, if you like:
$('#smallcart .plusone').live('click',function(){
articlenr = this.id.split('_')[1];
});
Try renaming your variable 'id' to something else. IE doesn't like it when you name things in your scripts the same as items in the DOM.
Never mind, that seems to have not been the issue in this case. I have, however, had issues in the past with IE specific bugs caused by variable names.

setAttribute doesn't work in IE6

how to set element attribute with javascript in IE6..? It seems setAttribute doesn't work. I really need to do it on the fly. Thanks.
Code
<script type="text/javascript" language="javascript">
menuItems = document.getElementById("menu").childNodes;
for (i = 0; i < menuItems.length; i++)
{
if (menuItems[i].className != "blue")
menuItems[i].setAttribute('onmouseover', 'HoverMenu(this)');
}
</script>
(Most of the below was before the OP clarified they were setting an event handler; left the list of other issues in case others find them useful)
IE6 makes a mess of several aspects of setAttribute. Without knowing the exact problem you were dealing with (this was before the edit inidicating it was an event handler), it's hard to be sure whether that's really the problem, but here are a couple of known issues:
You can't use setAttribute to set event handlers
It's best to set event handlers using the reflected property or with addEventListener [standard] / attachEvent [IE], not setAttribute (and you can't use setAttribute on IE).
So, any of these will work:
// Using reflected property
theElement.onclick = yourFunction;
// Using DOM2 standard addEventListener; note it's "click", not "onclick"
theElement.addEventListener("click", yourFunction, false);
// IE's non-standard alternative to addEventListener
theElement.attachEvent("onclick", yourFunction);
...not
// This doesn't work on IE (at least)
theElement.setAttribute("onclick", "yourFunction();");
The addEventListener / attachEvent way of doing this is cool for other reasons: You can have multiple event listeners on the same event of an element. You can't do that using the reflected property.
So for your specific situation:
menuItems = document.getElementById("menu").childNodes;
for (i = 0; i < menuItems.length; i++)
{
if (menuItems[i].className != "blue") {
menuItems[i].onmouseover = function() {
HoverMenu(this);
}
}
}
Certain attributes need their modified names
class
The correct way to set the class attribute is to use the reflected property className:
// Correct, cross-browser way. Works on IE6+, all versions of
// Chrome, etc. Completely reliable.
theElement.className = "new set of classes";
or on modern browsers (so, not IE6!) you can use classList.
One of IE6's many setAttribute bugs is that this doesn't work:
// Should also work, but fails on IE6 (and probably some other old versions)
theElement.setAttribute("class", "new set of classes");
Instead, IE6 (and probably a couple of other versions) make you use "className" instead of "class", even though that makes no sense whatsoever. The reflected property has the name className because it used to be that in JavaScript, you couldn't use reserved words (like class or for or if) as property literals (obj.class was invalid). That's not been true for a while now (ECMAScript 5 fixed it), but that's why the reflected property is className, not class.
But since setAttribute takes a string, it should accept the proper name of the attribute. The fact it doesn't is just an IE bug (and one they've fixed in modern versions of IE if they're not in [in]compatibility mode).
for
Similarly, to set the for attribute (for instance, on labels), one uses the htmlFor reflected property:
// Correct, cross-browser way. Works on IE6+, all versions of
// Chrome, etc. Completely reliable.
theLabel.htmlFor = "id-of-field";
On any non-broken browser, you can also use setAttribute:
// Should also work, but fails on IE6 (and probably some other old versions)
theLabel.setAttribute("for", "id-of-field");
...but not on IE6, it wants "htmlFor" instead of "for" for the same reason it wants "className" rather than "class" (e.g, because it's broken).
This page has quite a list of attributes that are problematic with IE.
setAttribute can't be used to set the style attribute
...you have to use the style property instead; but to be fair, that's usually a more convenient way. Example: This won't work on IE:
theElement.setAttribute("style", "color: blue"); // Doesn't work on IE
...but this will:
myElement.style.color = "blue";
Slightly OT: Look at libraries
JavaScript libraries like Prototype, jQuery, Closure, or any of several others will make most of the above a lot easier and smooth out differences amongst browsers if you go through their APIs.
I would really look at jquery. It has all the functionality that works with IE6 and this would be so much easier than the code you have here. It would look like this:
menuItems = $("#menu")[0].childNodes;
$.each(menuItems, function()
{
var item = $(this);
if (item.attr("className") != "blue")
item.mouseover(HoverMenu);
}
This code might need to be tweaked a little as I am just writing from memory.
I say easier because what you are trying to do in setting events like this varies based on browser and can be a headache to setup. But with jquery it is all done for you.

Categories

Resources