Is there a way to loop through all fields in a fieldset? - javascript

I would like to change the class for all the fields in a specific fieldset.
Is there a way to loop through the fields in a fieldset?

You can use getElementsByTagName.
var fieldset= document.getElementById('something');
var fieldtags= ['input', 'textarea', 'select', 'button'];
for (var tagi= fieldtags.length; tagi-->0) {
var fields= fieldset.getElementsByTagName(fieldtags[tagi]);
for (var fieldi= fields.length; fieldi-->0;) {
fields[fieldi].className= 'hello';
}
}
(If you only care about input fields, you could lose the outer tag loop.)
If you needed them in document order (rather than grouped by tag) you'd have to walk over the elements manually, which will be a pain and a bit slow. You could use fieldset.querySelectorAll('input, textarea, select, button'), but not all browsers support that yet. (In particular, IE6-7 predate it.)

Using jQuery (yay!):
$('#fieldset-id :input').each(function(index,element) {
//element is the specific field:
$(element).doSomething();
});

Note the solution below is for NON-JQUERY Implementations.
Implement a getElementsByClassName Method like this:
After you implement the code below you can then use document.getElementsByClassName("elementsInFieldSetClass") it will return an array of the elements with that class.
function initializeGetElementsByClassName ()
{
if (document.getElementsByClassName == undefined) {
document.getElementsByClassName = function(className)
{
var hasClassName = new RegExp("(?:^|\\s)" + className + "(?:$|\\s)");
var allElements = document.getElementsByTagName("*");
var results = [];
var element;
for (var i = 0; (element = allElements[i]) != null; i++) {
var elementClass = element.className;
if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass))
results.push(element);
}
return results;
}
}
}
window.onload = function () {
initializeGetElementsByClassName();
};

Another jQuery solution here.
If you are simply adding a class(es) to the elements, it's this simple:
$('fieldset :input').addClass('newClass');
.addClass() (like many other jQuery functions) will work on all of the elements that match the selector.
Example: http://jsfiddle.net/HANSG/8/

Permanently? Find & replace in your editor of choice.
When the user clicks something? jQuery way:
$('fieldset <selector>').each(function() {
$(this).removeClass('old').addClass('new');
});

Related

How can I modify my code to select specific checkboxes?

I want to write a simple javascript script to select from a large list of checkbox items on a website. Lets say I want to select the 3rd, 12th, and 25th checkbox. How would I do that? Right now it selects every item.
var script = document.createElement('script');
script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js';
script.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(script);
$("#detail input:checkbox").click();
I would use filter() and prop()
var indexesToCheck = [2,11,24];
$("#detail input:checkbox").filter(function(index){
return $.inArray( index, indexesToCheck ) > -1;
/* OR something like*/
return $(this).hasClass('someClass');
}).prop('checked',true);
Since it's not clear how you intend to determine which ones get checked I used a simple array. You could aslo check classes or any other element attributes inside filter using this which would be the instance of each element
References:
filter() docs
prop() docs
I will provide a solution in javascript and equivalent jQuery. I added a last solution (my favourite), which would generic, creating a custom pseudo selector.
For javascript, I chose all the inputs and verify their type. Incrementing a counter when the type is checkbox. Then I compare with an array of the indexes I want to select and I push the element to the final array with all my elements (mySelection):
var mySelection = [];
var checkboxIndexes = [3,12,25];
var checkCounter = 0;
var allInputs = document.getElementsByTagName("input");
for(var i=0;i<allInputs.length;i++) {
if (allInputs[i].type == 'checkbox') {
if(checkboxIndexes.indexOf(checkCounter) > -1;)
mySelection.push(allInputs[i]);
checkCounter++;
}
};
For the jQuery you could use:
$('#detail input:checkbox:eq(index)');
But I did an equivalent to the javascript one using filter. I personally like more this solution since you can put all the index to be selected in one array:
var checkboxIndexes = [3, 12, 25];
var mySelection = $("#detail input:checkbox").filter(function(index) {
return checkboxIndexes.indexOf(index) > -1;
});
The last solution would be a generic solution which will allow to create a custom pseudo selector that I called "multieq". The goal is to use "multieq" as a filter directly from the selector in this way:
var mySelection = $("input:checkbox:multieq(3, 12, 25)");
And this is the code I used in order to create that pseudo selector:
$.expr[':'].multieq = $.expr.createPseudo ?
$.expr.createPseudo(function(match) {
var checkboxIndexes=match.split(',');
for(var i=0; i<checkboxIndexes.length;i++) checkboxIndexes[i] = parseInt(checkboxIndexes[i], 10);
var index=-1;
return function( elem, doc, isXML ) {
index++;
return checkboxIndexes.indexOf(index) > -1;
};
}) :
function( elem, index, match ) {
var checkboxIndexes=match[3].split(',');
for(var i=0; i<checkboxIndexes.length;i++) checkboxIndexes[i] = parseInt(checkboxIndexes[i], 10);
return checkboxIndexes.indexOf(index) > -1;
};
//Now we can use this:
var mySelection = $("input:checkbox:multieq(3, 12, 25)");
Since 1.8+ $.expr breaks for certain cases and it is not including the param index, it is recommended to use createPseudo(), that is why there is a fallback function for jQuery version under 1.8. createPseudo, does not include index neither but allow us to create the index (as a counter).
I hope it helps!
<input type="checkbox" name="multi_selection"/>
var idArr = [];
$.each($("input[name='multi_selection']:checked"), function(){
idArr.push($(this).val());
});
Now idArr is the array of the selected checkboxes... alert(idArr)

Obtain a substring of a string using jQuery

I have a div with the following classes:
form-group val-presence-text val-type-pos-int val-length-10 has-success has-feedback
I want to get the 10 from the val-length-10 class name. I've tried various methods, but none seem to work for a dynamic multi-class attribute such as this. In addition, the 10 could be any positive integer and the class could be located anywhere within the group of classes.
Any ideas?
You can use this:
var val_length = $('div').attr("class").match(/val-length-(\d+)/)[1];
One possible solution:
var n = (this.className.match(/val-length-(\d+)/) || []).pop();
Or in the context:
$('[class*="val-length-"]').each(function() {
var n = (this.className.match(/val-length-(\d+)/) || []).pop();
console.log(n);
});
Assuming that the it is 'val-length' that never changes and just the integer on the end of it, you should be able to do this:
//get an array of classes on a specific element
var classList =$('#elementId').attr('class').split(/\s+/);
//loop through them all
$.each( classList, function(index, item){
//check if any of those classes begin with val-length-
if (item.indexOf('val-length' === 0) {
console.log(item.substring(11))
}
});
Try this...
$("div[class*=val-length-]").each(function() {
var s = this.className;
var length = 0;
$(s.split(" ")).each(function() {
if (this.search("val-length-") === 0) {
length = this.substr(11);
}
});
console.log(length);
});
It will find the relevant div and pull the value for you.

YUI nested selectors

I am a YUI(AUI) beginner. In jQuery I would do
$(image).find(selector).text();
How can this be achieved in YUI?
AUI().use('event', 'node', function(A) {
var subImages = A.all('.sub_image_conatiner');
for (var i = 0; i < subImages.size(); i++){
var image = subImages.get(i);
//get child elements of image here
}
});
I thought Y.all(foo).all(selector).get('text') would just work but it unfortunately doesn't.
I'd recommend that you use only one selector to match the sub elements:
Y.all('.parent-class .child-class').get('text');
If you can't, then you don't have to iterate through the nodes like a normal JS array. You can use .each().
var texts = [];
Y.all(foo).each(function (node, i) {
texts = texts.concat(node.all(bar).get('text'));
});
console.log(texts);
I'll file a bug with YUI to see if it makes sense to add Y.NodeList.prototype.all

How to get all HTML attributes which start with something (the attribute names, *not* their values!)

I would like to get all the elements/nodes in an HTML page which contain attributes that start with something (again, the attribute names start with something, not their values!). For example, TinyMCE has a tendency of adding custom attributes to the elements it saves, like "mce_style", "mce_href", "mce_bogus", etc. I would like to have something like the CSS3 selector for attribute values, [attr^="mce_"], but not for the values, the attribute names.
Of course, I can iterate through all DOM nodes and their attributes and check them one by one, but I was wondering whether there is a more efficient way.
Please don't give me TinyMCE-specific answers, I'm pretty sure there's a flag which would prevent TinyMCE for saving these attributes, but the question is generic.
here's a simple demo to find all elements that contain an attribute starting with mce_. might need some refinements.
function getMCE() {
var el, attr, i, j, arr = [],
reg = new RegExp('^mce_', 'i'), //case insensitive mce_ pattern
els = document.body.getElementsByTagName('*'); //get all tags in body
for (i = 0; i < els.length; i++) { //loop through all tags
el = els[i] //our current element
attr = el.attributes; //its attributes
dance: for (j = 0; j < attr.length; j++) { //loop through all attributes
if (reg.test(attr[j].name)) { //if an attribute starts with mce_
arr.push(el); //push to collection
break dance; //break this loop
}
}
}
return arr;
}
console.log(getMCE())​
Try this:
FUNCTIONS
//custom selector expression
$.extend($.expr[':'],{
attr:function(o,i,m){
var attrs=$.getAttrAll(o),re=m[3],found=false;
$.each(attrs,function(k,v){
if(new RegExp(re).test(v)) { return found=true;}
});
return found;
}
});
// get all atrributes of an element
$.getAttrAll=function(el){
var rect = [];
for (var i=0, attrs=el.attributes, len=attrs.length; i<len; i++){
rect.push(attrs.item(i).nodeName);
}
return rect;
};
`
USAGE
// calling custom selector expression :attr(regexp)
$(function(){
$('body').find(':attr("^mce_")').css({background:'yellow'});
});
HTML
<body>
<p mce_style="height:50px" id="x" data-hello="hello">selected</p>
<div not_mce_bogus="abc">not_mce_bogus</div>
<div mce_href="http://rahenrangan.com">selected</div>
<p>othrs</p>
</body>
One option, if you don't mind temporarily altering your DOM, is to extract your HTML into a string and search for the attributes via RegExp. When you find the attributes, you could append a "needle" in the DOM so that you can use jQuery to select the elements.
Here is a working concept (run with console open):
http://jsfiddle.net/skylar/N43Bm/
Code:
$.fn.extend({
findAttributes: function(attribute) {
var attributeFinder = new RegExp(attribute + '(.+)="', "gi");
var elementHTML = this.html().replace(attributeFinder, "data-needle='pin' "+attribute+"$1=\"");
this.html(elementHTML);
return this.find("[data-needle=pin]").removeAttr('data-needle');
}
});
console.log($("body").findAttributes('mce_'));
Note: my regexp is not great. You'll have to take better care than I have in this example.
Try this: (I tried putting * instead of a tag but it colored all the elements including those who do not have mce_style attribute as well)
a[mce_style] { color : red; }​
Demo : http://jsfiddle.net/Tcdmb/
More info : https://developer.mozilla.org/en/CSS/Attribute_selectors

How do I clear the contents of a div without innerHTML = "";

I have a div that is filled by JS created DOM elements,
I want the div to be cleared upon the JS function repeating, however I have heard that using document.getElementById('elName').innerHTML = ""; is not a good idea,
What is a valid alternative to doing this to clear the div's contents?
If you have jQuery then:
$('#elName').empty();
Otherwise:
var node = document.getElementById('elName');
while (node.hasChildNodes()) {
node.removeChild(node.firstChild);
}
The Prototype way is Element.update() e.g.:
$('my_container').update()
If you're using jQuery have a look at the .empty() method http://api.jquery.com/empty/
You could loop through its children and remove then, ie.
var parDiv = document.getElementById('elName'),
parChildren = parDiv.children, tmpChildren = [], i, e;
for (i = 0, e = parChildren.length; i < e; i++) {
tmpArr.push(parChildren[i]);
}
for (i = 0; i < e; i++) {
parDiv.removeChild(tmpChildren[i]);
}
Or use .empty() if you are using jQuery.
This is just an alternative solution, a while loop is much more elegant.
You can redefine .innerHTML. In Firefox and Chrome, it's not a problem to clear the elements with .innerHTML = "". In IE, it is, because any child elements are immediately cleared. In this example, "mydiv.innerHTML" would normally return "undefined". (without the redefine, that is, and in IE 11 as of the date of this post creation)
if (/(msie|trident)/i.test(navigator.userAgent)) {
var innerhtml_get = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").get
var innerhtml_set = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").set
Object.defineProperty(HTMLElement.prototype, "innerHTML", {
get: function () {return innerhtml_get.call (this)},
set: function(new_html) {
var childNodes = this.childNodes
for (var curlen = childNodes.length, i = curlen; i > 0; i--) {
this.removeChild (childNodes[0])
}
innerhtml_set.call (this, new_html)
}
})
}
var mydiv = document.createElement ('div')
mydiv.innerHTML = "test"
document.body.appendChild (mydiv)
document.body.innerHTML = ""
console.log (mydiv.innerHTML)
http://jsfiddle.net/DLLbc/9/
2022 Answer:
Use element.replaceChildren()
Emptying a node
replaceChildren() provides a very convenient mechanism for emptying a node of all its children. You call it on the parent node without any argument specified:
Doc

Categories