I'm kind of new in JS and jQuery, and this is my first question here, I hope I make it clear:
I have a list of <a>, and I want to apply style only to the one whose href is the same than the URL.
I tried to simplify my html to show you, something like this:
Then, this is what I started on my Script (with jQuery):
var url = window.location.pathname;
if($('a').attr('href') === url){
//and now I want to apply .css() only to the <a> that passes the condition
}
So, is frustrating I can't achieve to attack the right object, and I guess is more than simple :/, any tip?
Thanks.
The force is with you if you have CSS powers.
Simply select only that a:
$("a[href="+url+"]")
This is done using the attribute selector from CSS.
Then go ahead an do your .css() magic:
$("a[href="+url+"]").css(/*whatever you desire*/);
This will work for relative URLs like those you showed in your code.
To make it also safe for URLs like //code.google.com/whatever/abc.html you need to pass URL enclosed in single quotes:
$("a[href='"+url+"']")
Take a look at jQuery's filter().
var url = "/myWeb/004.html";
$("a").filter(function() {
return $(this).attr("href") === url;
}).css("background-color", "red");
Here is a JSFiddle.
Use filter() instead:
var url = window.location.pathname;
$('a[href]').filter(function() { return this.href === url; } ).css({
...
});
Related
This is my first experience with JS, so please forgive the noob question.
I'm trying to make a userscript for a phpBB forum that'll allow me to automatically bookmark every topic I create.
My approach is to add an onclick listener to the submit button.
I'll use the code found in another question:
var submit = document.getElementsByTagName('input')[0];
submit.onclick = function() {
;
}
Before that though I want to find a link to bookmarking the topic in one of the hrefs on the page and store it as a variable.
I know that it will always take the form of
<a href="./viewtopic.php?f=FORUM_NUMBER&t=TOPIC_NUMBER&bookmark=1&hash=HASH"
The final code should look something like (hopefully it's the correct form)
var link = THE LINK EXTRACTED FROM THE MATCHED HREF
var submit = document.getElementsByTagName('input')[0];
submit.onclick = function() {
setTimeout(function(){ window.location.href = 'link'; }, 1000);
}
My issue is I don't know how to approach locating the href that I need and getting the link from it. Haven't found any similar questions about this.
Thanks in advance for any help
Maybe something like this?
var anchors = document.getElementsByTagName('a'); // get all <a> tags
var link = '';
if (anchors) {
// getAttribute(attributeName) gets the value of attributeName (in your case, the value of 'href' attribute
// .map(), .find() and .filter() are available methods for arrays in JS
// .startsWith() is an available method for matching strings in JS.
// You can even experiment with other regex-based string matching methods like .match()
// Use one of the following lines, based on what you require:
// to get the first matching href value
link = anchors.map(anchor => anchor.getAttribute('href')).find(url => url.startsWith('./viewtopic.php')); // or provide a better regex pattern using .match()
// to get all matching href values as an array
link = anchors.map(anchor => anchor.getAttribute('href')).filter(url => url.startsWith('./viewtopic.php')); // or provide a better regex pattern using .match()
}
Since you're not new to coding, check out this documentation if you're new to JS :)
Happy coding!
You can try document.getElementsByTagName("a"); which returns a collection of all the <a></a> loaded in the dom.
Then you can find it in the list and and use .href to get it's href attribute.
What is the best way to specify a nested selector when using $(this)?
In this example:
$('.example').each(function() {
var url = $(this).attr('href');
});
url would return undefined, because it would expects an 'a' selector first.
So ideally i would want to say:
var url = $(this, 'a').attr('href');
but that does not work, the following works as intended but doesn't look very tidy:
$('.example').each(function() {
var link = $(this).find('a');
var url = $(link).attr('href');
});
so how can i use $(this) and 'a' together correctly?
note: i know the following would work, but not for the purposes of my question.
$('.example > a').each(function() {
var url = $(this).attr('href');
});
use:
$(this).find('a').attr('href');
(This should be a comment, but I needed more space for code).
When you say
it would expects an 'a' selector first
what exactly do you mean with "it"? There is nothing there that "expects" anything. Any element (theoretically) could have a href attribute.
Also, how does your HTML look like? If it's
<a class="example" href="#">...</a>
then only your first example works, the others don't. Your other examples all expect
<div class="example">...</div>
which in turn doesn't work with the first example.
What exactly is the problem? If $(this).attr("href") returns undefined, then you can easily check for that. Can you give a concrete use case?
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.
I want to catch every a tag which href attribute contain word youtube.
I need to use jquery.
$('a[href*="youtube"]')
For more selectors, see the Selectors portion of the jQuery API.
Attribute Contains Selector:
$('a[href*="youtube"]');
You can always use "filter":
var allYoutubes = $('a').filter(function() { return /youtube/.test(this.href); });
You could use a fancier selector, but this is simple and clear and possibly faster, as the library doesn't need to do the work of figuring out what your selector means. It's a matter of taste mostly.
pretty simple...
$('a[href*="youtube"]')
http://api.jquery.com/attribute-contains-selector/
http://api.jquery.com/category/selectors/
These other answers are great; but in case you're interested it's not that difficult to do a pure JS (no jQuery) alternative
function getYouTubeLinks() {
var links = document.getElementsByTagName("a");
var ytlinks = [];
for(var i=0,l=links.length;i<l;i++){
if(links[i].href.replace("http://","").indexOf("youtube.com") === 0) {
ytlinks.push(links[i]);
}
}
return ytlinks;
}
var youtube = getYouTubeLinks();
for(var i=0,l=youtube.length;i<l;i++){
youtube[i].style.color = "pink";
}
it'd be a good idea to make sure to strip out "www." and "https://" as well.
(very new to JavaScript jQuery)
Can an if statement contain a collection of other functions, specifically .each functions? If yes, is there something wrong with my implementation?
var string2 = "domain";
var mainpath = (window.location.href);
if (mainpath.indexOf(string2)) {
$("#topnav a").each(function(){
var thishref = $(this).attr('href');
$(this).attr({href: thishref + '?lnkid=tnav'});
});
$("#nav a").each(function(){
var thishref = $(this).attr('href');
$(this).attr({href: thishref + '?lnkid=pnav'});
});
}
What I want to do is run the code inside the if statement only when the page is at my domain (rather than inside the development space of a cms).
-Thanks
sure it can. You are doing it basically correct. A suggestion:
Be explicit with your if conditional, so do something like
if (mainPath.indexOf(string2) !== -1) {...
}
yes, nothing wrong with it. but it can be easily tricked with the following URL:
http://www.other.tld/?domain
Perfectly valid to use an if to conditionally run code. Though there seems to be an issue with your condition:
if (mainpath.indexOf(string2))
The index of string2 within mainpath can be 0 which would prevent your code from executing and that's certainly not what you want.
Rather test like this:
if ( mainpath.indexOf > -1 ) ...
As a suggestion, you can add a query to each link like this:
$("#topnav a").each(function(){
this.search = 'lnkid=tnav';
});
There is no need for a roundabout way involving getting the href attribute, appending to it, and putting it back.
Demo: http://jsfiddle.net/3ZpMz/1/