getAttribute cannot return class in IE7? - javascript

I need to find random nodes according to random attribute values.
To do that I use getAtrribute on nodes from getElementsByTagName.
It seems like when I look for class name as attribute it does not work on IE (works on FF).
Anyone know if getAtrribute doesn't work only on 'class' or other attributes as well? (if its only class I'll do a workaround.)

It's worth testing all of your Javascript cross-platform, if you're not using something like jQuery to take the pain away, but Class may just be a special case.
This should be a cross-platform way of getting the class:
element.className

Anyone know if getAtrribute doesn't work only on 'class' or other attributes as well?
It fails for all attributes where the HTML attribute name differs from the DOM property name (className, htmlFor), plus you have to use the DOM-style capitalisation. It also returns the wrong datatype for attributes whose DOM properties aren't strings:
disabled, readOnly, checked, selected, multiple,
compact, declare, isMap, noHref, defer, noResize,
size, cols, rows, width, height, hspace, vspace,
maxLength, tabIndex, colSpan, rowSpan
and possibly others I've missed!
element.getAttribute(x)
in IE is exactly the same as saying:
element[x]
So in general you should avoid using getAttribute, and use the simple DOM Level 1/2 HTML interfaces such as ‘element.className’ instead.
This is finally fixed in IE8.

IE is broken in this respect. You can access the class in IE via getAttribute("className") but of course this isn't really the attribute so it doesn't work in !IE.
That leaves you with a choice of branching to get element.className or branching to getAttribute on "className" or "class". Not good.

You can grab a list of all attributes from your elements and test their value that way. This snippet handles both IE and WebKit browsers, and will return the string value of the CSS class:
var value = "";
var elements = document.getElementsByTagName("div");
for(var i = 0; i < elements.length; i++){
if(typeof elements[i].attributes['class'] == "undefined"){
value = elements[i].getAttribute("class");
} else {
value = elements[i].attributes['class'].nodeValue;
}
alert(value); // careful, this will be a lot of alerts
}

Here you can get and set the class attribute with cross browser compatibility.
//also works with IE7 and below
//get class attribute value
var class_name = document.getElementById('elem_id').className;
//set class attribute
document.getElementById('elem_id').className = 'new-class-name';

Related

Javascript: get content of an element with incorrect style definition

I'm creating a stylesheet for a certain site, using javascript to assign classes to certain elements. For whatever reason some of 'td' elements use weird class assignments and inline styles, so I loop over them, clean them up and assign proper class names to reference in external stylesheet.
I don't have access to the site itself (nor administrative permission to change anything) so I use Stylish and Greasemonkey for Firefox (plus Adblock to dispose of the original stylesheet).
Here is a little part of js code responsible for that:
var cellStyleBg = cCell.style.backgroundColor;
if (cellStyleBg) {
switch(cellStyleBg) {
case 'white':
cCell.removeAttribute('style');
if ( cCell.parentNode.nodeName == 'TR' ) {
cCell.parentNode.className = 'deadlineSet';
}
break;
...
The problem is there is one particular case where this doesn't work:
<td class="td2h" style="background: dd97f0;">
As you can see, there is no octotorp in front of the color code. I assume that is the reason in this one case the variable cellStyleBg is 'null'.
I tried (instead of 'cCell.style.backgroundColor') to use 'cCell.style' and 'cCell.style.background', but they don't return plain text for me to parse.
What can I do to handle this particular case?
I think the only way to go is to get the raw value of the style attribute.
You do this by
//will output background: dd97f0
cCell.getAttribute('style');
If needed, you can breakdown the style into key value pairs using this snippet
//give "background: dd97f0", will output "background=dd97f0"
var stylePattern = /(.*?):([^;]*);?/g
while (match = stylePattern.exec(style)) {
console.log(match[1].trim() + "=" + match[2].trim());
}

Internet Explorer 10 - (Javascript or jQuery) How to change attributes and property without knowing which type it is (dynamic changes)?

Please bear with the pseudocode and formatting, I can't really remember the code off the top of my head.
In IE9 and below, I know you could set properties and attributes by using the setAttribute() method, but that seems to have been changed in IE10 by a separating attributes and properties separately.
Even doing something like
element.setAttribute("className", "myClass");
sets the element to appear as
<tag className = "myClass" />
which doesn't even set the property.
In my code, I have a JSON list that I use to store the names and values of the attributes/properties, which I simply set with setAttribute();
createElement(tag, list)
{
//pseudocode
var element = createElementWithTag(tag);
for each(attr in attributes)
if (attributes.hasOwnKey(attr))
element.setAttribute(attr, attributes[attr]);
}
And this worked fine for IE7-9, but completely fails in IE10.
Is there some way that I can set the property and attribute without which type (attr or prop) it is?
I can't even think of a way to set the property dynamically, without hardcoding a case for which property I want to change.
A solution would probably also be helpful.
i think something like this is what you want:
function tag(tag, attribs) {
if(tag.charAt) tag = document.createElement(tag);
var alias = {
htmlFor: "for",
className: "class"
}, prop;
for (prop in attribs) if (attribs.hasOwnProperty(prop)) {
if("style" == prop) tag.style.cssText = attribs[prop];
try {
tag[prop] = attribs[prop];
} catch (h) {
tag.setAttribute( alias[prop] || prop, attribs[prop]);
}
}
return tag;
}
//test it:
tag("a", {href:"/", target:"_blank", innerHTML:" some text ", className: "1 2 3"}).outerHTML
tested in IE8 and Chrome.
if anyone knows of more dom->attrib mappings (like htmlFor), please edit them into the answer, thanks!

How know if there is a style for an id or a class?

// instead of 'width' could be 'font-size', 'color', 'position', etc
var result = getCSS('some_id_name_or_class_name', 'width');
// may be the value or 'null' if there is no style for such an id name or a class name
alert(result);
(The matter is that there is yet no element created with such id or class.)
You could give the getStyle method from QuirksMode a shot (it only works with Ids though, but you could modify it):
function getStyle(el,styleProp)
{
var x = document.getElementById(el);
if (x.currentStyle)
var y = x.currentStyle[styleProp];
else if (window.getComputedStyle)
var y = document.defaultView
.getComputedStyle(x,null)
.getPropertyValue(styleProp);
return y;
}
You should definitely make a trip to the link though. There are some quirks (different browsers expect the styleProp parameter to be in different formats.
Again, you can use this as a base and build out the functionality you need (like hiding the cross-browser issues, making it work with classes, etc.).
EDIT
Since you're not looking to get computed values, you can use the document.styleSheets collection to read the values out of your CSS:
W3C DOM tests - styleSheets
Again, there are some cross-browser implementation details (cssRules vs. rules) but you can write your code to work around those.
http://jquery.com/
jQuery is great for this kind of stuff.
alert($("#yourIdHere").css("whateverCssPropertyYouWant"));

how to remove css property using javascript?

is it possible to remove a CSS property of an element using JavaScript ?
e.g. I have div.style.zoom = 1.2,
now i want to remove the zoom property through JavaScript ?
You have two options:
OPTION 1:
You can use removeProperty method. It will remove a style from an element.
el.style.removeProperty('zoom');
OPTION 2:
You can set it to the default value:
el.style.zoom = "";
The effective zoom will now be whatever follows from the definitions set in the stylesheets (through link and style tags). So this syntax will only modify the local style of this element.
removeProperty will remove a style from an element.
Example:
div.style.removeProperty('zoom');
MDN documentation page:
CSSStyleDeclaration.removeProperty
div.style.removeProperty('zoom');
element.style.height = null;
output:
<div style="height:100px;">
// results:
<div style="">
You can use the styleSheets object:
document.styleSheets[0].cssRules[0].style.removeProperty("zoom");
Caveat #1: You have to know the index of your stylesheet and the index of your rule.
Caveat #2: This object is implemented inconsistently by the browsers; what works in one may not work in the others.
You can try finding all elements that have this class and setting the "zoom" property to "nothing".
If you are using jQuery javascript library, you can do it with $(".the_required_class").css("zoom","")
Edit: Removed this statement as it turned out to not be true, as pointed out in a comment and other answers it has indeed been possible since 2010.
False: there is no generally known way for modifying stylesheets from JavaScript.
You can also do this in jQuery by saying $(selector).css("zoom", "")
This should do the trick - setting the inline style to normal for zoom:
$('div').attr("style", "zoom:normal;");
actually, if you already know the property, this will do it...
for example:
var txt = "";
txt = getStyle(InterTabLink);
setStyle(InterTabLink, txt.replace("zoom\:1\.2\;","");
function setStyle(element, styleText){
if(element.style.setAttribute)
element.style.setAttribute("cssText", styleText );
else
element.setAttribute("style", styleText );
}
/* getStyle function */
function getStyle(element){
var styleText = element.getAttribute('style');
if(styleText == null)
return "";
if (typeof styleText == 'string') // !IE
return styleText;
else // IE
return styleText.cssText;
}
Note that this only works for inline styles... not styles you've specified through a class or something like that...
Other note: you may have to escape some characters in that replace statement, but you get the idea.
To change all classes for an element:
document.getElementById("ElementID").className = "CssClass";
To add an additional class to an element:
document.getElementById("ElementID").className += " CssClass";
To check if a class is already applied to an element:
if ( document.getElementById("ElementID").className.match(/(?:^|\s)CssClass(?!\S)/) )

getElementsByName in IE7

I have some code doing this :
var changes = document.getElementsByName(from);
for (var c=0; c<changes.length; c++) {
var ch = changes[c];
var current = new String(ch.innerHTML);
etc.
}
This works fine in FF and Chrome but not in IE7. Presumably because getElementsByName isn't working in IE. What's the best workaround?
In case you don't know why this isn't working in IE, here is the MSDN documentation on that function:
When you use the getElementsByName method, all elements in the document that have the specified NAME attribute or ID attribute value are returned.
Elements that support both the NAME attribute and the ID attribute are included in the collection returned by the getElementsByName method, but elements with a NAME expando are not included in the collection; therefore, this method cannot be used to retrieve custom tags by name.
Firefox allows getElementsByName() to retrieve elements that use a NAME expando, which is why it works. Whether or not that is a Good Thing™ may be up for debate, but that is the reality of it.
So, one option is to use the getAttribute() DOM method to ask for the NAME attribute and then test the value to see if it is what you want, and if so, add it to an array. This would require, however, that you iterate over all of the nodes in the page or at least within a subsection, which wouldn't be the most efficient. You could constrain that list beforehand by using something like getElementsByTagName() perhaps.
Another way to do this, if you are in control of the HTML of the page, is to give all of the elements of interest an Id that varies only by number, e.g.:
<div id="Change0">...</div>
<div id="Change1">...</div>
<div id="Change2">...</div>
<div id="Change3">...</div>
And then have JavaScript like this:
// assumes consecutive numbering, starting at 0
function getElementsByModifiedId(baseIdentifier) {
var allWantedElements = [];
var idMod = 0;
while(document.getElementById(baseIdentifier + idMod)) { // will stop when it can't find any more
allWantedElements.push(document.getElementById(baseIdentifier + idMod++));
}
return allWantedElements;
}
// call it like so:
var changes = getElementsByModifiedId("Change");
That is a hack, of course, but it would do the job you need and not be too inefficient compare to some other hacks.
If you are using a JavaScript framework/toolkit of some kind, you options are much better, but I don't have time to get into those specifics unless you indicate you are using one. Personally, I don't know how people live without one, they save so much time, effort and frustration that you can't afford not to use one.
There are a couple of problems:
IE is indeed confusing id="" with name=""
name="" isn't allowed on <span>
To fix, I suggest:
Change all the name="" to class=""
Change your code like this:
-
var changes = document.getElementById('text').getElementsByTagName('span');
for (var c=0; c<changes.length; c++) {
var ch = changes[c];
if (ch.className != from)
continue;
var current = new String(ch.innerHTML);
It's not very common to find elements using the NAME property. I would recommend switching to the ID property.
You can however find elements with a specific name using jQuery:
$("*[name='whatevernameYouWant']");
this will return all elements with the given name.
getElementsByName is supported in IE, but there are bugs. In particular it returns elements whose ‘id’ match the given value, as well as ‘name’. Can't tell if that's the problem you're having without a bit more context, code and actual error messages though.
In general, getElementsByName is probably best avoided, because the ‘name’ attribute in HTML has several overlapping purposes which can confuse. Using getElementById is much more reliable. When specifically working with form fields, you can more reliably use form.elements[name] to retrieve the fields you're looking for.
I've had success using a wrapper to return an array of the elements. Works in IE 6, and 7 too. Keep in mind it's not 100% the exact same thing as document.getElementsByName, since it's not a NodeList. But for what I need it for, which is to just run a for loop on an array of elements to do simple things like setting .disabled = true, it works well enough.
Even though this function still uses getElementsByName, it works if used this way. See for yourself.
function getElementsByNameWrapper(name) {
a = new Array();
for (var i = 0; i < document.getElementsByName(name).length; ++i) {
a.push(document.getElementsByName(name)[i]);
}
return a;
}
Workaround
var listOfElements = document.getElementsByName('aName'); // Replace aName with the name you're looking for
// IE hack, because it doesn't properly support getElementsByName
if (listOfElements.length == 0) { // If IE, which hasn't returned any elements
var listOfElements = [];
var spanList = document.getElementsByTagName('*'); // If all the elements are the same type of tag, enter it here (e.g.: SPAN)
for(var i = 0; i < spanList.length; i++) {
if(spanList[i].getAttribute('name') == 'aName') {
listOfElements.push(spanList[i]);
}
}
}
Just another DOM bug in IE:
Bug 1: Click here
Bug 2: Click here

Categories