Selecting multiple, but not all HTML classes - javascript

So lets say I want to hide a div or span with CSS of a particular class.
Is there anyway to do so for the first X number of instances, or better yet, do it for all except for the last one? I imagine this would require javascript.
pseudocode I am thinking would look like this
if divname.class = "XYZ" {
select all instances -1
execute code that inserts random programmatic id into each class
execute code that hides all ids except the last one
}
Am I on the right track? Or is there any easier/better way?

If you can use jQuery and its nice pseudo-selectors, you could do something like
$('.question-summary:not(:last)')
You can test on the SO homepage.

You could do something like this,
var class_div = document.getElementsByClassName("class_name");
var i =0;
for(i=0;i<class_div.length-1;i++){
//do whatever you want with class_div[n-1] elements.
}
I am not sure how you do this with jquery but this is one possible solution for javascript.

If you were using jQuery...
$('.class_name').hide().last().show();

Here ya go - http://jsfiddle.net/uUK6G/
Set all your divs to the same class. Then use jQuery to filter out the last one.
$('.myDiv').filter(':not(:last)').hide();​

You can use the :last-child selector in CSS to do this.
http://www.w3schools.com/cssref/sel_last-child.asp

Is there anyway to do so for the first X number of instances, or
better yet, do it for all except for the last one? I imagine this
would require javascript.
You can try:
var elms = document.getElementsByClassName('XYZ'), total = elms.length;
for (var i = 0; i < total; i++){
elms[i].style.display = 'none';
}
In above loop, i will contain index of each element, you can put condition or rather range to specify which ones to delete. For example, if you wanted to hide all except for last one, you would modify it like:
for (var i = 0; i < total - 1; i++){
elms[i].style.display = 'none';
}

Related

Values of all textboxes on a page - without knowing the ID?

I am developing a Chrome Extension that, when the user leaves the page, saves all the text from the textboxes on that page and outputs it to a file.
If I knew the IDs of the textboxes on the page, then it wouldn't be a problem, but the issue is that I need the extension to get the values of all of the textboxes on the page without knowing the IDs, as it will be a different website each time the extension is used.
Also, how would the information be collected? In a string? It would be nice to go down the page and add each textbox to a file, one by one, instead of one huge string.
I've never used jQuery or understood it, and there's probably a solution in it staring me in the face. If anyone suggests using it, please could you explain it a little bit?
Thanks in advance. I would post my code, but I don't know where to start - ergo I don't have any.
you could store it in array using $.each, as :
var valsArr = [];
$("input[type=text]").each(function() {
valsArr.push( $(this).val() );
});
or create object with name as key and value as its value, like:
var valsObj = {};
$("input[type=text]").each(function() {
valsObj[this.name] = $(this).val();
});
You can do it like this:
function onClick(){
var areas = document.getElementsByTagName("textarea");
for(var i = 0; i < areas.length; i++){
alert(areas[i].value);
}
}
<textarea></textarea>
<textarea></textarea>
<button onclick="onClick()">Gather information</button>
Also see this regarding your "save to a file" question Using HTML5/Javascript to generate and save a file
Use the selector and apply it in an each cycle.
$(":text").each(function(){
alert($(this).val());
});
Make a for loop
for(i=0; i < $("input[type='text']").length; i++){
$("input[type='text']").index(i).value();
}
You can use .map() : It returns an array.
var arr = $(":text").map(function() {
return this.value
}).get(); //add join(',') after get() to get a simple comma separated list.
Instead of input[type="text"] you could also use :text pseudo selector.
Demo

Select tags that starts with "x-" in jQuery

How can I select nodes that begin with a "x-" tag name, here is an hierarchy DOM tree example:
<div>
<x-tab>
<div></div>
<div>
<x-map></x-map>
</div>
</x-tab>
</div>
<x-footer></x-footer>
jQuery does not allow me to query $('x-*'), is there any way that I could achieve this?
The below is just working fine. Though I am not sure about performance as I am using regex.
$('body *').filter(function(){
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
Working fiddle
PS: In above sample, I am considering body tag as parent element.
UPDATE :
After checking Mohamed Meligy's post, It seems regex is faster than string manipulation in this condition. and It could become more faster (or same) if we use find. Something like this:
$('body').find('*').filter(function(){
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
jsperf test
UPDATE 2:
If you want to search in document then you can do the below which is fastest:
$(Array.prototype.slice.call(document.all)).filter(function () {
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
jsperf test
There is no native way to do this, it has worst performance, so, just do it yourself.
Example:
var results = $("div").find("*").filter(function(){
return /^x\-/i.test(this.nodeName);
});
Full example:
http://jsfiddle.net/6b8YY/3/
Notes: (Updated, see comments)
If you are wondering why I use this way for checking tag name, see:
JavaScript: case-insensitive search
and see comments as well.
Also, if you are wondering about the find method instead of adding to selector, since selectors are matched from right not from left, it may be better to separate the selector. I could also do this:
$("*", $("div")). Preferably though instead of just div add an ID or something to it so that parent match is quick.
In the comments you'll find a proof that it's not faster. This applies to very simple documents though I believe, where the cost of creating a jQuery object is higher than the cost of searching all DOM elements. In realistic page sizes though this will not be the case.
Update:
I also really like Teifi's answer. You can do it in one place and then reuse it everywhere. For example, let me mix my way with his:
// In some shared libraries location:
$.extend($.expr[':'], {
x : function(e) {
return /^x\-/i.test(this.nodeName);
}
});
// Then you can use it like:
$(function(){
// One way
var results = $("div").find(":x");
// But even nicer, you can mix with other selectors
// Say you want to get <a> tags directly inside x-* tags inside <section>
var anchors = $("section :x > a");
// Another example to show the power, say using a class name with it:
var highlightedResults = $(":x.highlight");
// Note I made the CSS class right most to be matched first for speed
});
It's the same performance hit, but more convenient API.
It might not be efficient, but consider it as a last option if you do not get any answer.
Try adding a custom attribute to these tags. What i mean is when you add a tag for eg. <x-tag>, add a custom attribute with it and assign it the same value as the tag, so the html looks like <x-tag CustAttr="x-tag">.
Now to get tags starting with x-, you can use the following jQuery code:
$("[CustAttr^=x-]")
and you will get all the tags that start with x-
custom jquery selector
jQuery(function($) {
$.extend($.expr[':'], {
X : function(e) {
return /^x-/i.test(e.tagName);
}
});
});
than, use $(":X") or $("*:X") to select your nodes.
Although this does not answer the question directly it could provide a solution, by "defining" the tags in the selector you can get all of that type?
$('x-tab, x-map, x-footer')
Workaround: if you want this thing more than once, it might be a lot more efficient to add a class based on the tag - which you only do once at the beginning, and then you filter for the tag the trivial way.
What I mean is,
function addTagMarks() {
// call when the document is ready, or when you have new tags
var prefix = "tag--"; // choose a prefix that avoids collision
var newbies = $("*").not("[class^='"+prefix+"']"); // skip what's done already
newbies.each(function() {
var tagName = $(this).prop("tagName").toLowerCase();
$(this).addClass(prefix + tagName);
});
}
After this, you can do a $("[class^='tag--x-']") or the same thing with querySelectorAll and it will be reasonably fast.
See if this works!
function getXNodes() {
var regex = /x-/, i = 0, totalnodes = [];
while (i !== document.all.length) {
if (regex.test(document.all[i].nodeName)) {
totalnodes.push(document.all[i]);
}
i++;
}
return totalnodes;
}
Demo Fiddle
var i=0;
for(i=0; i< document.all.length; i++){
if(document.all[i].nodeName.toLowerCase().indexOf('x-') !== -1){
$(document.all[i].nodeName.toLowerCase()).addClass('test');
}
}
Try this
var test = $('[x-]');
if(test)
alert('eureka!');
Basically jQuery selector works like CSS selector.
Read jQuery selector API here.

How to get HTML data with javascript

I have an HTML web page full of divs and span tags identified with class that have lots of data I need in other format. I was wondering what would be the best way to do this with javascript.
Thank you for the help.
The fastest way? jQuery:
$(".myClass").each(function() {
// work with your data here
});
More lowlevel, but should be a lot faster (a lot less overhead):
var myelements = document.evaluate('//div[#class=myClass"]', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < myelements.snapshotLength; i++) {
var dataElement = myelements.snapshotItem(i);
// work with your data here
}
(ok, you'd have to do it twice (once for div and once for span), it's more code and doesn't look as nice, but it should still be faster)
If you are wanting to get at all of the documents with a specific class then you will need to test for the presence of that class on each object. You will want to use a
document.getElementByTagName("*") // This should select everything
and loop through them to detect the proper name.
if (regex test == true) {
// you found an element that matches
// do what you will with it.
}
If you find the elements you need do what you need with them. Now you have processed all elements on the page and found elements that match your criteria. Good luck.

how to using "For" instead of "each" function in jquery

Today i'm very stack with a Work and jQ. I was get a morning for it but i can't resolve it :(.
My Work here:
<div class="container">
<p class="test">a</p>
<div>
<p class="test">a</p>
</div>
</div>
In normal, i can using jQ with each function for select all <p class="test">a</p> EX:
$(".test").each(function() {
$(this).text('a');
});
But i hear everyone talk that, for function get a less timeload than each function. Now i want using for instead of each.. but i don't know how to write code jQ in this case.
Somebody can help me!. thankyou!
I wouldn't worry about it unless you were iterating through hundreds of them.
for loop is usually used with normal DOM (aka without jQuery) traversing, like...
var elements = document.getElementById('something').getElementsByTagName('a');
var elementsLength = elements.length;
for (var i = 0; i < elementsLength; i++) {
elements[i].style.color = 'red';
}
Caching of elementsLength is a good idea so it is not calculated every iteration. Thanks to CMS for this suggestion in the comments.
Just adapt that for your jQuery object if you wanted to do it with jQuery.
Replace elements variable with your jQuery collection, like $('#something a'). I think you may need to rewrap the object if you need to do any more jQuery stuff with it.
One thing to watch out for is that using an ordinal accessor on the result of a jQuery selection will return a native DomElement. If you want to use jQuery methods on them, you have to re-wrap them:
var testElements = $('.test');
for (var i = 0; i < testElements.length; i++) {
// Using $() to re-wrap the element.
$(testElements[i]).text('a');
}
I'd second what others have said though. Unless you're dealing with many elements, this is premature optimization. Re-wrapping the elements to use the .text() method may even bring it back to no gain at all.
have you tried the obvious solution?
var nodes = $(".test");
for(var i = 0; i < nodes.length; i++)
{
var node = nodes[i];
}
This article shows that each() has no significant performance penalty until you get into the hundreds of thousands of looped-over items.
Another alternative:
for (var i = 0; i < $('.test').length; i++){
var element = $('.test').eq(i);
}

popluating multiple id tags

How can i populate multiple id tags simultaneously.
On my page i have id tags starting with "total_" phrase, like total_1, total_2 etc., is there a way by which i can populate each of them on a single click in javascript.
Should i use regex or parser.
Any help will be highly appreciated.
Thank you.
for(var i=1; true; i++){
var elm = document.getElementById("total_"+i);
if(elm == undefined){
break;
}
elm.innerHTML = "Some text here";
}
Using jQuery you can do the following:
$("div[id^='total_']").html("Some text Here");
If you know how many there are, you can simply loop through the numbers:
for (var i=1; i<=10; i++) {
document.getElementById('total_'+i).innerHTML = 'text';
}
If you are using jQuery, you can loop through all elements of a specific type, and look for the id. It's less efficient, but more flexible. It will work even if the numbers are not contiguous:
$('div').filter(this.id && this.id.substr(0,6) == 'total_').html('text');
(You can of course loop through elements without a library like jQuery, but then it's a bit more code...)

Categories