4

The following is a simple test case to demonstrate what I'm trying to do:

<html>
<head>
<title>Test</title>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
    $(":target").css('color', 'red');
});
</script>
<ul>
    <li id="one">One</li>
    <li id="two">Two</li>
    <li id="three">Three</li>
</ul>
</body>
</html>

The idea is to do something through jQuery/Javascript to the targetted item, when something is targetted (for example, test.html#two).

This works as I expect it to in Firefox and IE 10, but not in Chrome, Opera or Safari, which leaves me wondering if this is a bug in some browsers, if what I'm trying to do is somehow wrong, or if I've run afoul of an inadequately precise part of some specification or other.

If I change the jQuery code to do

alert($(":target").length);

it becomes apparent that Chrome, Opera and Safari can't find the :target element during document.ready(), but calling the same code later (via console or function attached to a click event) does find the elements.

When should :target become accessible to JS?

rink.attendant.6
  • 44,500
  • 61
  • 101
  • 156
Stephen Baillie
  • 509
  • 4
  • 9

5 Answers5

3

This was posted as a comment but was later removed, you can try waiting for the window load event:

$(window).on('load hashchange', function(){
    $(':target').css('color', 'red');
});

This for me produced mixed results on Chrome, it worked when doing a page refresh (F5) but not when hitting enter in the address bar.

I don't know if there's any way to handle this correctly on page load using the :target selector but you could always get the hash value and use it as your selector:

$(window).on('load hashchange', function(){
    var target = window.location.hash;
    $(target).css('color', 'red');
});

UPDATE

I've been doing some research on the issue plus some tests and I have a couple of insights to share:

First off, we need to understand that when calling $(':target') jQuery internally makes use of querySelectorAll(':target') which means it's directly related to the CSS specification of the pseudo-class, but why isn't working inside document.ready()?

Well, I found that wrapping the code inside setTimeout(fn,0) actually makes the selector available:

$(document).ready(function(){
    setTimeout(function(){
        $(':target').css('color', 'red'); //THIS WORKS
    },0);
});

You can read this answer for an explanation on how adding a zero-ms timeout actually makes a difference, but basically it allows the browser to complete other non-javascript related tasks (in which we would find making the actual CSS pseudo-class available for query). I believe Firefox somehow manages its internal processes differently and that's why the code works there without the need for a timeout.

Now I also discovered that jQuery's internal sizzle selector engine provides a fallback for browsers that do not support CSS :target pseudo-class, which you can use inside document.ready() without issue:

$(document).ready(function(){
    $(':target()').css('color', 'red');
});

This works because instead of relying on the CSS class it is a javascript implementation that makes use of the hash property on the window.location object, internally it is defined as follows:

"target": function( elem ) {
        var hash = window.location && window.location.hash;
        return hash && hash.slice( 1 ) === elem.id;
    }

The only think you should note is that this function will go through every element on the page if it's not passed a selector like :target(div), so I believe using the workaround I provided earlier would still be a better option than this.

Community
  • 1
  • 1
omma2289
  • 54,161
  • 8
  • 64
  • 68
  • Interestingly, `window.location.hash` DOES seem to be available during document.ready(), even though :target doesn't match anything at that point. This is enough for a workaround, but doesn't answer the question of whether this is a browser bug. – Stephen Baillie Aug 22 '13 at 07:00
  • ...and while `$(":target")` doesn't find anything during `document.ready()`, `$(window.location.hash)` does find the appropriate item. Curiouser and curiouser... – Stephen Baillie Aug 22 '13 at 07:20
  • @StephenBaillie I updated my answer with some insights on the issue – omma2289 Aug 22 '13 at 08:41
1

Because the page is not been reloaded. You need bind it to hashchange:

$(window).on('hashchange', function(){
    $(":target").css('color', 'red');
});

http://jsfiddle.net/sXsYx/

Notice that you have much more work to make it right, maybe combine it with $(document).ready

Kabie
  • 10,489
  • 1
  • 38
  • 45
0

you can use css3 target selector for styling work

:target
{
 color:red;
}
0

Since there is no specialized logic in your example (if statements or such), why don't you just do the styling in CSS? The :target pseudo-class is a CSS3 selector.

:target {
    color: red;
}

Note that this will work in all modern browsers, and even some very old browsers (Chrome 1 and Firefox 1.3, for instance), but with Internet Explorer it is only supported starting from version 9.

You can also do it in both places if you wish (CSS and JavaScript), however the JavaScript would seem redundant unless you specifically need IE <= 8 compatibility.

I've noticed that you are using jQuery version 1.10.1, which retains support for IE <= 8. Is that important? If not you can also move to jQuery 2.0.2 (latest version at time of writing).

rink.attendant.6
  • 44,500
  • 61
  • 101
  • 156
  • I think what he is trying to achieve might not just be turning it to red. – Kabie Aug 22 '13 at 04:31
  • @Kabie is entirely correct - that's just a dummy payload to demonstrate the problem. What I actually want to do with the :target item involves .parent() and then some further DOM traversal, and until the next iteration of CSS gives us ! or $ to select an element that's not the bottom of the search list, that needs JS. – Stephen Baillie Aug 22 '13 at 06:26
-1

You should do like this

$("li:target")

This will select the element. This is the better way

Refer this please,

http://api.jquery.com/target-selector/

Or you should remove document ready and put the script at the end of the html document

Manu M
  • 1,074
  • 5
  • 17