I want to take the second class of an element, and then add a class to the element that has that ID. In Chrome, Firefox, etc. it works perfectly but in IE11 it does not. Do you know why? Help me please
for (var i = 0; i < $('#example .item').length; i++) {
var class_svg = document.getElementsByClassName("item")[i].className.split(' ')[1];
var $elem = document.getElementById(class_svg);
$elem.classList.add("show");
}
According to the docs classList is only partially supported before Edge. Use className instead like:
$elem.className += ' show';
edit: thanks for the hint #Sterling Archer
Creating a basic example using an SVG element (which I assume you have based on your example code) and looking at it in IE11 and Edge, you can see that the className property is a [object SVGAnimatedString]. That is some special object for SVG elements, instead of dealing with that special object, lets just deal with the attribute itself using getAttribute. Here is the code that works in most all browsers:
for (var i = 0; i < $('#example .item').length; i++) {
var class_svg = document.getElementsByClassName("item")[i].getAttribute("class").split(' ')[1];
var $elem = document.getElementById(class_svg);
var classList = $elem.getAttribute("class");
classList += " show";
$elem.setAttribute("class",classList);
}
Hope that works for you.
Related
I am trying to clear some (10 of 50) fields by selecting elements by their shared id. The problem is that I can only select one at a time with getElementById()
Here is the jsFiddle demonstrating the single element grab. jsFiddle
function toggleBankCount() {
secBankFields = document.getElementById('2ndBankFields');
secBankFields.value = '';
}
I am fairly certain I can do what I want with getElementsByName() which returns an array of elements. However, I am using Perl and the name of the elements must be different in order for %fdat to work properly on submit. Can you help me?
Here's how you can do it:
toggleBankCount = function () {
secBankFields = document.getElementsByTagName('input');
for (var i = 0; i < secBankFields.length; ++i) {
if(secBankFields[i].id === '2ndBankFields')
secBankFields[i].value = '';
}
}
though ids should be unique, consider using classes instead. Also, classes and ids shouldn't begin with a digit.
Check it out: JSFiddle
There are some Javascript functions which should help you.
Get element by ID attribute
Id should be unique.
var elm = document.getElementById("some_id");
Get elements by Tag name
// get all div elements
var elms = document.getElementsByTagName("div");
Get element by Class attribute
// get all elements with class .some_class
var elms = document.getElementsByClassName("some_class");
Get element by Name attribute
// get all elements with attribute name some_name
var elms = document.getElementsByName("some_name");
Get element by CSS selector
var elms = document.querySelectorAll("div.box, span.title");
for (var i = 0; i < elms.length; i++) {
var elm = elms[i];
console.log(elm);
}
I have the following line of code:
document.getElementById("question_*").setAttribute("disabled", "false");
I want to use a form of wildcard for the element ID. The script is run and used by lots of different buttons, they all have ID's of question_something - is it possible to make this setAttribute to make the button enabled for various ID's?
<button id="question_1a" onClick="nextQuestion(this.id)" disabled>Next question</button>
EDIT:
I've switched to a classname as suggested. Buttons now are:
<button id="question_1a" class="nextButton" disabled>Next question</button>
I've added the following line to make this not disabled:
var elems = document.getElementsByClassName('nextButton').setAttribute("disabled", "false");
But I get: Uncaught TypeError: Object # has no method 'setAttribute'
You can't use wildcards with document.getElementById(), you can, however, with document.querySelectorAll():
var elems = document.querySelectorAll('button[id^="question_"]');
This, of course, requires a relatively up to date browser; on the other hand using a class-name (for example question) to associate those elements would allow you to use:
var elems = document.getElementsByClassName('question');
Or:
var elems = document.querySelectorAll('button.question');
I tried doing this: var elems = document.getElementsByClassName('nextButton').setAttribute("disabled", "false"); - but I get: Uncaught TypeError: Object # has no method 'setAttribute'
That's because you can't modify the properties of a NodeList all at once, you can, however, use a for (){...} loop, or similar to do so:
Using for(){...}:
var elems = document.getElementsByClassName('question');
for (var i = 0, len = elems.length; i < len; i++){
elems[i].disabled = false; // to make them all enabled
}
JS Fiddle demo.
Or using forEach (up to date browsers):
var elems = document.getElementsByClassName('question');
[].forEach.call(elems, function(a){
a.disabled = false; // will make all elements enabled
});
JS Fiddle demo.
References:
Array.prototype.forEach().
CSS attribute-selectors.
document.getElementById().
document.getElementsByClassName().
document.querySelector() compatibility.
document.querySelectorAll() compatibility.
Function.prototype.call().
JavaScript for loop.
That's precisely what classes are for:
<button class="question" id="question_1a" onClick="nextQuestion(this.id)" disabled>Next question</button>
And
var elems = document.getElementsByClassName("question");
for(var z=0;z<elems.length; z++){
elems[z].setAttribute("disabled", "false")
}
Another possibility, if querySelectorAll or getElementsByClassName (could be shimmed in a similar manner) wasn't available and you wanted to match multiple IDs.
HTML
<button>Question</button>
<button id="question_1a">Question</button>
<button id="question_1b">Question</button>
<button id="question_1c">Question</button>
<button id="question_1d">Question</button>
<button id="question_2a">Question</button>
Javascript
function getElementsById(regex) {
var tags = document.getElementsByTagName('*'),
tagsLength = tags.length,
matches = [],
index,
tag;
for (index = 0; index < tagsLength; index += 1) {
tag = tags[index];
if (regex.test(tag.id)) {
matches.push(tag);
}
}
return matches;
}
console.log(getElementsById(/^question_1[a-z]?$/));
Output
[button#question_1a, button#question_1b, button#question_1c, button#question_1d]
On jsFiddle
Then you can iterate this array and set the attributes
And the getElementsByclassName shim
function getElementsByClassName(node, className) {
var array = [],
regex = new RegExp("(^| )" + className + "( |$)"),
elements = node.getElementsByTagName("*"),
length = elements.length,
i = 0,
element;
while (i < length) {
element = elements[i];
if (regex.test(element.className)) {
array.push(element);
}
i += 1;
}
return array;
}
Nope wildcard isn't supported. But to solve this problem you can use jQuery to do the same.
P. S. I will try to post code once I am back at desk
Update
agree David Thomas & Beemo's code hint that should solve your problem
You can use JQuery $("[id^='question_']") selector to get all elements with an id starting by question_
I've got a series of checkboxes with the same class. I want to get all the checkboxes with that same class as a collection and extract their id and checked status. But all the select by class examples I've seen just apply a single change to all elements of that class. I need to get a collection/array of all the checkbox elements with that class so I can iterate over them.
Ok, I've tried some of the suggestions and had no luck.
This throws an Object Expected error in IE8:
var checkboxes = document.querySelectorAll("input[type='checkbox'].chkRoles");
And this gives me an empty array every time, regardless of what's checked.
var mandatoryRoleIDs = [];
$('input.chkRoles[type="checkbox"]').each(function (i, checkbox)
{
if ($(checkbox).attr('checked'))
mandatoryRoleIDs.push($(checkbox).attr('id'));
});
Since your question is tagged with jQuery, here's how you can do it with jQuery's each() function:
$('input.someClass[type="checkbox"]').each(function(i,el){
var $this = $(el),
id = $this.attr('id'),
checked = $this.attr('checked');
/* do stuff with id and checked */
});
var checkboxes = document.getElementsByClassName('classname');
Then iterate over it to do what you need.
for(var i = 0; i < checkboxes.length; i++) {
var current = checkboxes[i];
// stuff on current
}
Using jQuery is not necessary in this simple case, and querySelectorAll is not totally supported by older browser; Vanilla JS is the best way to do it!
Since you need to support IE8(damn Microsoft) you should do something like this:
var inputs = document.getElementsByTagName('input'),
className = "classname";
for (var i = 0; i < inputs.length; i++) {
var current = inputs[i];
if (current.type !== 'checkbox' || current.className.indexOf(className) === -1) continue;
//do stuff with current
}
See a working JSFiddle example of this snippet.
I'm reusing an old application of mine and want to change the code so I'm applying the DOM structure that I build up to a node's class instead of it's id.
Below is a piece of the code and as you can see I try to combine jQuery (getting the node by it's class) with the old structure, but something doesn't work properly here.
Is it possible to combine jQuery and JS native like this?
If not, is there another way to accomplish what I want to do?
var gamearea = $('<div/>', {
text': 'testarea',
class': 'gamearea'
}).appendTo('.memory:last');
alert("this.rows: " + this.rows);
for (var j = 0; j < this.rows; j++){
var box = document.createElement('div');
for (var i = 0; i < this.cols; i++){
var iterator = (this.cols * j) + i;
var img = document.createElement('img');
var aNod = document.createElement('a');
aNod.href = "#";
img.src = "pics/0.png";
aNod.appendChild(img);
box.appendChild(aNod);
}
gamearea.appendChild(box);
}
You should be able to get it working by changing gamearea.appendChild(box); to gamearea[0].appendChild(box);
The reason behind that is you can get the bare DOM element for a jQuery extended object by simply doing obj[0], where obj is a jQuery extended object obtained like obj = $(...) etc. And the appendChild method in your code is a method of bare DOM element.
i'm having a bug on firefox 3.6 using this function
function GetRefreshedResults(response)
{
var splitted = response.value.split("|");
var panel = document.getElementById('my-glider');
var anchors = panel.getElementsByTagName('a');
for (var i=0; i<anchors.length; i++)
{
anchors[i].innerHTML=splitted[i];
}
}
which ads in DOM anchors like
"< a xmlns="http://www.w3.org/1999/xhtml">
I'm now trying to use this instead:
function GetRefreshedResults(response)
{
var splitted = response.value.split("|");
var panel = document.getElementById('my-glider');
var anchors = panel.getElementsByTagName('a');
for (var i=0; i<anchors.length; i++)
{
anchors[i].empty();
anchors[i].appendChild(splitted[i]);
// anchors[i].innerHTML=splitted[i];
}
}
but i get the following error in appendChild :
Uncaught Error: NOT_FOUND_ERR: DOM Exception 8
i don't understand why it's not working. can anyone help me ?
thanks
EDIT:
Example:
splitted[0] contains :
"<div class="var">Visits</div><div class="percent-zero">0%</div><div class="val">0<div class="val-alt">Unique Visits: 0</div></div>"
i want to update 8 anchors with new content, contained in splitted[0], splitted[1]...splitted[7]
splitted[i] is the problem. appendChild appends a DOM-element to an existing DOM-element, but it looks like you ar trying to append a string value. If you want to use appendChild, either create a container element and use innerHTML for that to insert the string, or just use innerHTML. It is not a bug that you can't append a string as DOM-element, I'd say. See also the MDN-page on appendChild.
response.value.split("|"); Indicates to me that you are passing response as a string. appendChild only works with elements. You can't append a child to a flat string.