Reputation: 35
This should be fairly simple, but I seem to be missing something. I'm working on a little project in which the code that I'm writing aims to do a few things across the document. Here's the HTML code that I want to apply my script's actions to:
<div class="entry">
<p>First paragraph</p>
<p>Second paragraph</p>
<p>Third paragraph</p>
<p>One more...</p>
<div class="bttn"><a href="#">Click for More</a></div>
</div>
This template (that is, several p elements and one div with the class "bttn" inside a wrapper div with the class "entry") is repeated multiple times across the document. Users add content to the paragraphs and eventually publish it to the site. And here's what I wish to do in my .js file:
So basically, if the user who published the content added more than two paragraphs to the HTML template, when the doc is ready I want the script to take the other paragraphs, move them to a new div element, and add a new class to the button. In the end when the "Click for More" button is clicked, the extra paragraphs that were removed and inserted afterwards will fade in nicely (since I'll keep them hidden under the button once I've re-inserted them). Here's what I've done so far:
$('.entry').each(function () {
$counter = $('.entry p').length;
if ($counter > 2) {
$removeExtra = $(this).find('p').not(':eq(1)').not(':eq(0)').detach();
$(this).find('.bttn').after(function () {
return '<div class="slider">' + $removeExtra.html() + '</div>';
}).addClass('show');
}
});
Issues:
Would greatly appreciate any help with this. Thanks in advance!
Upvotes: 1
Views: 222
Reputation: 268452
My initial suggestion would be to use :gt
:
$(".entry").each(function(){
var ps = $("p:gt(1)", this);
if ( ps.length ) {
$(".bttn", this).addClass("show").after(function(){
return $("<div>").addClass("slider").append(ps);
});
}
});
I apologize if I got the details mixed up in any degree - the question is a bit verbose.
Fiddle: http://jsfiddle.net/FfmaB/1/
Upvotes: 3
Reputation: 7601
review the documentation for $.html()
function:
http://api.jquery.com/html/
If the selector expression matches more than one element, only the first match will have its HTML content returned.
I believe this is what you wanted:
$(document).ready(Process);
function Process() {
$('.entry').each(function() {
var $this = $(this);
$counter = $this.find('p').length;
if ($counter > 2) {
var $Extras = $this.find('p').not(':eq(1)').not(':eq(0)');
$($Extras.get().reverse()).each(function() {
var extra = $(this).html();
$this.find('.bttn').after('<div class="slider">' + extra + '</div>');
$this.find('p').not(':eq(1)').not(':eq(0)').detach();
})
$this.find(".bttn").addClass('show');
}
});
}
DEMO: http://jsfiddle.net/xcuh9/2/
regards,
Nitin J.
Upvotes: 1
Reputation: 150070
This line:
$counter = $('.entry p').length;
Is finding all paragraphs within any ".entry" div, when you want paragraphs just within the current ".entry" div. Also you don't need to use the callback-function syntax with .after()
since you're using it to add after only one element at a time.
Try this instead:
$('.entry').each(function () {
var $this = $(this),
$p = $this.find('p');
if ($p.length > 2) {
$('<div class="slider"/>').appendTo(this).append($p.slice(2));
$this.find('.bttn').addClass('show');
}
});
I've used the .append()
method rather than .after()
since .append()
will automatically add them after the last child of the element you're appending to. You don't need to detach the paragraphs before appending them to the new div because .append()
will move them (at least, it will move them when there is only one target element - as is the case here).
I've used .slice()
rather than your .not(':eq(1)').not(':eq(0)')
.
Note that you should declare variables with var
or they become globals.
Upvotes: 3