tags:

views:

72

answers:

4

I have about 25 show/hide (toggle) elements on a page like so...

HTML:

<h2><a href="#" class="link1">Headline One</a></h2>
<div class="toggle-item-link1">content</div>

<h2><a href="#" class="link2">Headline Two</a></h2>
<div class="toggle-item-link2">content</div>

JS:

$('[class^=toggle-item]').hide();
//toggle content on click
$('[class^=link]').click(function() {
var $this = $(this);
var x = $this.attr("className");
$('.toggle-item-' + x).toggle();
$(this).text($(this).text() == 'open' ? 'close' : 'open');

So what is happening is that the H2 text (Headline One, Headline Two) is being completely replaced with the text "open/close" depending on the toggle state. What I want to do is add Open/Close text to the actual headline depending on the toggle state.

For example:

Open Headline One / Close Headline One

Open Headline Two / Close Headline Two

I'm just not seeing how to do that here. Any help would be great. Thanks!

A: 

You can add content to an element using $('#id').append(). If you append a with a class you can later remove that with $('.class #id').remove().

Use your own selectors as you need :-) You can also set the text in an element with the $('#id').text('my_text) function. Or if you need to set its HTML $('#id').html('my_html').

ikanobori
A: 

Try something like this: http://jsfiddle.net/ZgyAx/

Here's the code for it:

$('[class^=toggle-item]').hide();
//toggle content on click
$('[class^=link]').click(function() {
    var $toggleItem = $('.toggle-item-' + $(this).attr("class"));
    var $toggleLink = $(this);
    $toggleItem.slideToggle(function() {
        var $stateSpan = $('<span class="state"></span>');
        $toggleItem.is(':visible') ? $stateSpan.text('Close ') : $stateSpan.text('Open ');
        $toggleLink.children('.state').remove().end().prepend($stateSpan);
    });
}).prepend($('<span class="state">Open </span>'));

I changed the toggle to be slideToggle, in order to have the text be revealed/hidden smoothly, rather than jumping open and closed. Of course, if you prefer that, you can just change slideToggle back to toggle.

To make the text replacement easier, it wraps the open/close text in a <span> with a class that will allow it to be quickly grabbed. Then to keep things simple, it tests the toggle item for visibility, and uses that to determine whether to say Open or Close. Note that this must be done inside the callback for slideToggle, because the visibility test won't be accurate until the animation has completed. Finally, simply remove any existing open/close state text, and insert the new one.

Ender
this is awesomely so close! I just need the text of "Open" to show before I actually toggle. Right now it shows up after I toggle the div closed. Thank you thank you!
Melissa
I've updated my answer and the live demo. Just have to add .prepend($('<span class="state">Open </span>')) after the click binding.
Ender
+2  A: 

Just to keep things simple, I'd put the Open/Close text in a span, and reference that:

Example: http://jsfiddle.net/8TXDM/1/

HTML

<h2><a href="#" class="link1"><span>Open</span> Headline One</a></h2>
<div class="toggle-item-link1">content</div>

<h2><a href="#" class="link2"><span>Open</span> Headline Two</a></h2>
<div class="toggle-item-link2">content</div>​

jQuery

$('[class^=toggle-item]').hide();

$('[class^=link]').click(function() {
    $('.toggle-item-' + this.className).toggle();
    $('span',this).text(function(i,txt) {
        return txt === "Open" ? "Close" : "Open";
    });
});​

Also, instead of selecting the .toggle-item- element from the DOM each time, I'd probably just traverse there.

Example: http://jsfiddle.net/8TXDM/2/

$('[class^=link]').click(function() {
    $('span', this).text(function(i, txt) {
        return txt === "Open" ? "Close" : "Open";
    }).end().parent().next().toggle();
});
patrick dw
this works great too! Thank you so much!
Melissa
@Melissa - You're welcome. :o)
patrick dw
A: 

If your layout is like it is in the question, instead of finding by class you can find the element relatively. Also wrapping the text in another element for easy changing would be easier, like this:

$('h2 + div').hide();
$('h2 a').prepend('<span>Open</span> ');

$('h2 a').click(function(e) {
    var vis = $(this).parent().next().toggle().is(':visible');
    $(this).find('span').text(vis ? 'Close' : 'Open');
    e.preventDefault();
});​​

You can give it a try here.

Nick Craver
Thank you! This works wonderfully as well.
Melissa