2

I have the following jQuery code:

$("body.page-calendar-practices-2012-05 #content-header h1#title")

which works fine. I can use it to alter the html in my page. But I really want to select pages which have a class in the body STARTING WITH 'page-calendar-practices' ie: it will include other pages with different dates. I tried the following:

$("body[class^=page-calendar-practices] #content-header h1#title")

and it didn't work. What is wrong?

EDIT - here's the HTML:

<body class="not-front logged-in page-calendar two-sidebars page-calendar-practices-2012-05 section-calendar" >
5
  • 1
    Are you sure the class starts with that? The syntax of your first selector is incorrect (note ]) Commented Jun 20, 2012 at 18:19
  • 1
    It works for me: jsfiddle.net/rekqG Commented Jun 20, 2012 at 18:20
  • save everyone from guessing and post enough live html to see what you are actually traversing Commented Jun 20, 2012 at 18:21
  • Sorry about the syntax, I copy pasted it wrong. But yest, the class starts with that, I am looking at it right now. Commented Jun 20, 2012 at 18:22
  • also quote attribute values in selectors per examples in API api.jquery.com/category/selectors Commented Jun 20, 2012 at 18:23

3 Answers 3

5

[class^=page-calendar-practices] will only select an element who's class attribute starts with "page-calendar-practices"; not an element of which one of its classes starts with "page-calendar-practices".

So it would select an element such as this:

<body class="page-calendar-practices-2012-05">

You can use the * selector:

$('body[class*=page-calendar-practices]')

but that will also select the following:

<body class="page some-page-calendar-practices">

Alternatively, you can filter with this simple check:

$('body').filter(function() {
    return ~(' ' + this.className).indexOf(' page-calendar-practices');
}).find('#content-header h1#title');

which is a little more verbose than the simple "contains" selector, but is more accurate.

Here's the fiddle: http://jsfiddle.net/DR9K4/


To make things easier, you can add your own filter to jQuery, as follows:

jQuery.expr[':']['class-starts']​ = function(el, i, m) {
    return ~(' ' + el.className).indexOf(' ' + m[3]);
};

and then simply use it wherever you want:

$('body:class-starts(page-calendar-practices)');

See it here in action: http://jsfiddle.net/gEJeW/


Update: In jQuery 1.8, the Sizzle engine was completely rewritten. As part of the update, the expression extension architecture has also been reworked, so the above function won't work anymore.

If you're using jQuery 1.8+, use this:

$.expr[':']['class-starts'] = $.expr.createPseudo(function (arg) {
    return function (el) {
        return ~(' ' + el.className).indexOf(' ' + arg);
    };
});

Here's the fiddle: http://jsfiddle.net/gEJeW/2/


For more information, see here: Getting the "match" object in a Custom Filter Selector in jQuery 1.8

Sign up to request clarification or add additional context in comments.

3 Comments

Ok, so how can I write a selector which will make the selection that I want.
+1 Nice jQuery custom selector. I didn't know it was that easy to do.
@jfriend00 - Unfortunately, it's not that easy anymore. See my update.
2

Your attempt is looking for a class attribute that starts with your string, not a specific class name in that attribute that starts with your string.

I think you can probably just use the attribute contains logic:

$("body[class*='page-calendar-practices'] #content-header h1#title")

This could match class names that don't start with that, but it seems unlikely you'd be using class names like that.


If you wanted to be exact, I don't think you could do it in a simple selector - you'd probably need some javascript logic:

$(document.body).filter(function() {
    return((" " + this.className).indexOf(" page-calendar-practices") != -1);
}).find("#content-header h1#title");

3 Comments

+1 I like the way you prepend a space, then just use that in your regex. Nice touch!
@JosephSilber - I just removed the regex since I realized it wasn't needed. I learned the space addition trick in jQuery source. I like your jQuery custom selector. I didn't know it was that easy to extend.
That's right. Hope you don't mind me borrowing this method for my filter expression.
1

http://api.jquery.com/attribute-starts-with-selector/

jQuery('[attribute^="value"]')

Description: Selects elements that have the specified attribute with a value beginning exactly with a given string.

Yours doesn't start with it - it has the matching string halfway through

You want to use the * selector: http://api.jquery.com/attribute-contains-selector/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.