I made an read more read less script for my Magento 2 webshop. This is used on a category page where there are serval subcategorie blocks to choose, each subcategory has a description with.
The problem: if I click read more all the descriptions of the subcategories will expand in stead of only the description of the subcategory I clicked read moreI am starting to learn PHP and Magento 2 but I can't fix this, does someone know the solution?
<div class="product description product-item-description">
<div class="more">
<?php if ($_subCategory->getDescription()) {
$string = strip_tags($_subCategory->getDescription());
if (strlen($string) > 250) {
// truncate string
$stringCut = substr($string, 0, 250);
$string = substr($stringCut, 0, strrpos($stringCut, ' ')).'... Lees meer';
}
echo $string;
?>
</div>
<?php
}else {?>
<?php /* #escapeNotVerified */ echo $_attributeValue;
}
?>
</div>
<div class="less" style="display:none">
<?php echo $_subCategory->getDescription(); ?>
Lees minder
</div>
<script type="text/javascript">
console.log('test');
require(["jquery"],function($){
$('.readmore').on("click",function(){
$('.less').show();
$('.more').hide();
});
$('.readless').on("click",function(){
$('.less').hide();
$('.more').show();
});
});
</script>
</div>
This is because, when you type $('.less').hide(); this is grabbing every element with the attribute class='less'. This is the way I would overcome this:
Start by attaching a unique attribute to each <div class="more"> or <div class="less"> - in this case, we use the class attribute: (and move 'more' or 'less' to an id)
<div id="read-more-block" class="cat-<?php echo $_subCategory->getId(); ?>">
<!-- my "read more" content -->
<a class="link" href="#read-more-block">Read Less</a>
</div>
<div id="read-less-block" class="cat-<?php echo $_subCategory->getId(); ?>">
<!-- my "read less" content -->
<a class="link" href="#read-less-block">Read More</a>
</div>
We now have a read-more-block and a read-less-block for each subcategory. When we click the inside link a jQuery event should fire which will hide itself and display the other.
And then, in your jQuery:
$('#read-more-block .link').on('click', function() {
var $readLessBlock = $('#read-less-block.' + $(this).parent().attr('class'));
$readLessBlock.show(); //Show the read less block
$(this).parent().hide(); //Hide the read more block
});
..and vice versa for read less.
Related
Scenario:
I have a bit tricky case here:
Upon cicking the button inside the first div block (I have named it as DIV Block A for readability), I want to display the channels which is inside the second DIV Block
(I have named it as DIV Block B for readability).
The id of button from DIV Block A is:
id="sub_category_dc_button_<?=$category['category_id'];?>"
Upon clicking this button, the content inside the DIV Block B should be displayed.
Attempt 1:
For this, I have followed this approach:
$(".sub_dc_channels").on("click", function(){
$($(this).attr("data-target")).show();
});
Here is my DIV Block A:
<div class="sub_cat_buttons channel" id="dc_subcategory_button_tab">
<div class="sub_dc_channels" id="sub_dc_button">
<?php foreach ($output as $category) {
<button type="button" data-toggle="collapse"
id="sub_category_dc_button_<?=$category['category_id'];?>"
class="btn btn-primary sub_digitalchannel_button"
data-target="#Category_<?= $category['category_id'];?>">
<?= $category['category_title']?>
</button>
</div>
</div>
Here is my DIV Block B:
<?php foreach ($output as $category) {?>
<div class="channel" id="Category_<?= $category['category_id'];?>">
<div id="subchannel_list_tab">
<?php foreach ($output as $category) {?>
<?php foreach ($category['channels'] as $channels) { ?>
<img src="<?= $channels['channel_logo']; ?>"
alt="<?= $channels['channel_name']; ?>"
title="<?= $channels['channel_name']; ?>"
style="width: 100px; height: 60px;" />
<?php } ?>
<?php } ?>
</div>
</div>
<?php } ?>
Attempt 2:
I have also used this approach with the same DIV Blocks but it fails too.
$('div[id^="Category_"]').click(function() {
$(".channel").hide();
$("#subchannel_list_tab").show();
});
Issue Faced:
When I clicked the button from DIV Block A then it targets the contents inside the DIV Block B but the contents inside the DIV Block B are not shown.
What am I missing here? Or am I following the wrong approach?
Suggestions are highly appreciated.
your click is going to be triggered in the div and not in the button, it is likely that this is the problem.
Here's a dummy example of what I think you're up to.
$('.showDiv').click( function () {
let div = $(this).attr('data-target');
$(`#${div}`).show();
});
#divB {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="divA">
<button class="showDiv" data-target="divB">show div</button>
</div>
<div id="divB">
info divB
</div>
You want to show dynamic data as per id of button click.You missed a target button class in selector.your issue is solved.
$(document).on("click",".sub_dc_channels .sub_digitalchannel_button",function(){
alert();
$($(this).attr("data-target")).show();
});
for reference you can click here.
(This is an extension of a series of questions I have asked previously as I'm going through the process of learning how to work with Wordpress)
I'm using a small javascript to turn on and off the display of posts on a page, depending on the posts respective category. The script enables a group of filter buttons at the top of the page to switch between displaying posts that belong to a certain category.
Now I would like to change the page's code so that upon loading the page for the first time (i.e. before any of the filter buttons have been clicked) there is no content/posts being displayed at all. Right now when accessing the page, all posts which belong to the parent category of the sub-categories (which the buttons allow to filter) are being displayed.
How do I have to change the site to do so?
An online version of the site can be visited here: http://udkdev.skopec.de/category/studierende/
Here's the site's code along with the javascript of the filter-button at the bottom:
<?php get_header(); ?>
</div>
<br>
<div class="wrapper-offset-fix wrapper-studierende">
<div class="projekte content">
<div class="button-group filters-button-group">
<button class="projekt-btn btn" id="category-stud-sose17">SoSe 2017</button>
<button class="projekt-btn btn" id="category-stud-wise1617">WiSe 2016/17</button>
<button class="projekt-btn btn" id="category-wise-201415">SoSe 2016 </button>
<button class="projekt-btn btn" id="category-sose-14">WiSe 2015/16</button>
<button class="projekt-btn btn" id="category-sose-14">SoSe 2015 </button>
<button class="projekt-btn btn" id="category-sose-14">WiSe 2014/15</button>
</div>
<?php if (have_posts()): ?>
<?php while(have_posts()): the_post(); ?>
<div <?php post_class(); ?>>
<?php
if ( has_post_thumbnail() ) {
the_post_thumbnail('full');
} ?>
<?php the_content(); ?>
</a>
<!--<div class="meta">Tags: <?php the_tags( '', ', ', '<br />' ); ?> </div>-->
</div>
<?php endwhile; ?>
<?php else : ?>
<h2>Couldn’t find any articles!</h2>
<?php endif; ?>
</div>
<script>
var $btns = $('.btn').click(function() {
if (this.id == 'all') {
$('.projekte > .post').fadeIn(300);
} else {
var $el = $('.' + this.id).fadeIn(300);
$('.projekte > .post').not($el).fadeOut(300);
}
$btns.removeClass('active');
$(this).addClass('active');
})
</script>
<?php get_footer(); ?>
You can begin this by first hiding all the posts. One way to do this would be add a CSS style
.projekte .post {display:none;}
Looking at your codes, rest should just work out by itself. I would however swap these lines so that the posts are removed before the new ones are added like this:
$('.projekte > .post').not($el).fadeOut(300);
var $el = $('.' + this.id).fadeIn(300);
I am trying to create a YouTube Esque sidebar 'Show More' button.
The posts from the same category are displayed in my template sidebar using the following code:
<div class="sidebar-left">
<div class="grid-container">
<?php
global $post;
$category = get_the_category($post->ID);
$current_cat = $category[0]->cat_name;
$my_query = new WP_Query('category_name='.$current_cat.'&showposts=10');
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<a href="<?php the_permalink(); ?>">
<div class="grid-item-meta">
<span><?php echo $entry_cats; ?></span>
<h3><?php the_title(); ?></h3>
<h5>Written by <?php echo get_the_author(); ?></h5>
</div>
</a>
<?php endwhile;
wp_reset_postdata();
?>
</div>
</div>
Is it possible to limit this query / offset it and fetch more on clicking a 'Show More' button. Once show more has been toggled I need to change it to 'Show Less'. I'm quite happy pulling all posts in one query and hiding them on the front end (i'm not too concerned with getting into complex AJAX).
Limiting the height of the div could cut off a post in the middle. Seems there is lots of info / answers on loading more mosts via AJAX or loading a post in a particular div, however not a simple show and hide scenario like I'm after. Many thanks in advance.
If you don't mind loading all the posts you could use some jQuery to get that effect. Check out the CodePen link.
https://codepen.io/pen/QvOpGK
declare at which point you will hide posts, 4 will be the first post we hide
#posts div:nth-child(n + 4) {
display: none;
}
Then use jQuery to show posts on click, I'm adding a class show that gives a display: block;
//We need to tell jQuery which posts to show in hiddenPosts
var hiddenPosts = $('#posts div:nth-child(n + 4)');
var button = $('#showMore');
$(button).click(function() {
hiddenPosts.toggleClass( 'show' );
//change button's text
if (button.text() == "Show More") {
button.text("Show Less");
} else {
button.text("Show More");
}
});
I have a page with a few jquery tabs, each of which I want to display the result of a php function, as follows:
<ul id="tabs" class="ccm-dialog-tabs">
<li class="ccm-nav-active">Tab 1 Title </li>
<li>Tab 2 Title></li>
</ul>
<div id="tabs-1-tab">
<?php echo "This is tab 1<br>"; ?>
</div>
<div id="tabs-2-tab">
<?php echo "This is tab 2<br>"; ?>
</div>
The jquery to make the tabs work is:
<script type="text/javascript" language="javascript">
var ccm_activeTransactionsTab = "tabs-1";
$("#transaction_tabs a").click(function() {
$("li.ccm-nav-active").removeClass('ccm-nav-active');
$("#" + ccm_activeTransactionsTab + "-tab").hide();
ccm_activeTransactionsTab = $(this).attr('id');
$(this).parent().addClass("ccm-nav-active");
$("#" + ccm_activeTransactionsTab + "-tab").show();
});
</script>
The problem I am having is that when the page loads, the active tab shows the result of both php statements - i.e. it shows:
echo "This is tab 1<br>;
echo "This is tab 2<br>;
If I click between the tabs a few times then the extra information disappears. These tabs work fine normally, the problem only arises when they show the output of a php function.
I would suggest you use hide then at start using simple CSS
<div id="tabs-1-tab" style='display:none'>
<?php echo "This is tab 1<br>"; ?>
</div>
<div id="tabs-2-tab" style='display:none'>
<?php echo "This is tab 2<br>";?>
</div>
Also you have missed closing quotes in statement <?php echo "This is tab 1<br>; ?>
You missed the qoute on echo "This is tab 1<br>; but echo "This is tab 1<br>";
I'm new to jQuery and am having trouble figuring out the right way to loop a set of code for a basic carousel/banner rotator. I've tried a few versions of "for" statements and .each(), but I can't get it to work on my own so I'm reaching out for help.
Here's my code so far:
$('.next-1').click(function () {
$('.featured-1').fadeOut(500,function(){
$('.featured-2').fadeIn(500,function(){
$('.featured-2').toggleClass("hide");
});
});
});
$('.next-2').click(function () {
$('.featured-2').fadeOut(500,function(){
$('.featured-3').fadeIn(500,function(){
$('.featured-3').toggleClass("hide");
});
});
});
And then a similar code block for going back within the slider:
$('.prev-2').click(function () {
$('.featured-2').fadeOut(500,function(){
$('.featured-1').fadeIn(500,function(){
$('.featured-2').toggleClass("hide");
});
});
});
$('.prev-3').click(function () {
$('.featured-3').fadeOut(500,function(){
$('.featured-2').fadeIn(500,function(){
$('.featured-3').toggleClass("hide");
});
});
});
This code does work right now, I just don't want to have to output so many unnecessary lines of code when I know I could loop it. I'd like to be able to loop until there are no more "featured-n" divs to cycle through (being able to cycle around to the beginning would be great too!)
Here's the PHP/HTML I'm using to generate each "featured-n" div block:
function home_slider_loop() {
$count = 0;
query_posts ('tag=slider');
if (have_posts()) : while (have_posts()) : the_post();
$count++;
?>
<div class="featured-post featured-<?php echo $count; if ($count>1) { echo ' hide';}?>">
<div class="featured-header">
<h1 class="featured-title"><?php the_title(); ?></h1>
<p class="author">Written by Evan Luzi</p>
</div>
<div class="image-wrap">
<?php the_post_thumbnail('full', array('class' => 'slider-image')); ?>
<div class="slider-nav">
<div class="featured-prev prev-<?php echo $count; ?>"></div>
<div class="featured-next next-<?php echo $count; ?>"></div>
</div><!--End Navigation-->
</div><!--End Image <?php echo $count; ?>-->
<div class="featured-footer">
<?php the_excerpt(); ?>
<a class="more-link" href="<?php the_permalink(); ?>" alt="<?php the_title(); ?>" >Read more</a>
</div>
</div><!--End Featured <?php echo $count; ?>-->
<?php
endwhile;
endif;
}
Here's a sample of one of the static HTML outputs (just imagine this iterated several times with the "featured-n" classes incrementing:
<div class="featured-1">
<div class="featured-header">
<h1 class="featured-title">5 Useful Cinematography Apps for iOS You Should Download Today</h1>
<p class="author">Written by Evan Luzi</p>
</div>
<div class="image-wrap">
<img width="1018" height="416" src="http://www.tbabdev.com/wp-content/uploads/2013/07/cinematography-apps-8-hero.jpg" class="slider-image wp-post-image" alt="cinematography-apps-8-hero" />
<div class="slider-nav">
<div class="featured-prev prev-1"></div>
<div class="featured-next next-1"></div>
</div><!--End Navigation-->
</div><!--End Image 1-->
<div class="featured-footer">
<p>The devices we have in our pockets, the ones that can run these apps, these are the new leathermans. They have everything we need. They eliminate the need to carry paper manuals and enable us to do complex timelapse calculations in a fraction of the time as a paper and pen.</p>
<a class="more-link" href="http://www.tbabdev.com/?p=27" alt="5 Useful Cinematography Apps for iOS You Should Download Today" >Read more</a>
</div>
</div><!--End Featured 1-->
You can see the code in action at http://www.tbabdev.com/
Thank you in advance for your help and please be kind to a n00b :)
Use something like this :
$('.nav .prev').click(function(){
activeBlock = $('.featured.active');
prevBlock = activeBlock.prev('.featured');
activeBlock.fadeOut('slow',function(){
prevBlock.fadeIn().addClass('active');
}).removeClass('active');
});
$('.nav .next').click(function(){
activeBlock = $('.featured.active');
nextBlock = activeBlock.next('.featured');
activeBlock.fadeOut('slow',function(){
nextBlock.fadeIn().addClass('active');
}).removeClass('active');
});
Html
<div class="nav">
<div class="prev"> </div>
<div class="next"> </div>
</div>
<div class="featured-post featured <?php if($count>1) echo 'hide' ?>">
<div class="featured-header">
<h1 class="featured-title"><?php the_title(); ?></h1>
<p class="author">Written by Evan Luzi</p>
</div>
<div class="image-wrap">
<?php the_post_thumbnail('full', array('class' => 'slider-image')); ?>
</div>
<!--End Image <?php echo $count; ?>-->
<div class="featured-footer">
<?php the_excerpt(); ?>
<a class="more-link" href="<?php the_permalink(); ?>" alt="<?php the_title(); ?>" >Read more</a>
</div>
</div>
You could do it this way :
$('.featured-next, .featured-prev').click(function () {
//find out if the clicked element is a prev or next element, extract the last part, will be useful later
var direction = $(this).hasClass("featured-next") ? "next" : "prev";
//select the ".featured-n" block which is the super-parent of clicked element
var $fullBlock = $(this).closest('div[class^="featured-"]'); //or add a class here to make your life easier
//fade out full block
$fullBlock.fadeOut(500, function () {
//search for the next element and show it
//note that $fullBlock.next() => $fullBlock["next"]() => $fullBlock[direction]()
$fullBlock[direction]().fadeIn(500, function () {
//toggle the class "hide" of the element next to fullBlock
$(this).toggleClass("hide");
});
});
});
Explanation:
You can join up both prev and next events together.
Then, you have to check if its a next or a prev element. Set that to a variable called direction. We'll be using this to find out if we have to use prev() or next() when we're trying to fadeIn featured-n divs.
Find the parent with the class set to featured-n (in your case its the superparent). It might be better if you give a common class to all these elements so that we can stop using 'div[class^="featured-"]' selector, which is slightly inefficient.
Fade out the superparent.
In the callback, based on the direction variable, we'll have to decide if the carousel is gonna go to prev block or next block, something like this :
if(direction === "prev")
{
$fullBlock.prev().fadeIn(//your code)
}
else
{
$fullBlock.next().fadeIn(//your code)
}
You must also know that, in an object like this :
var data = {"name" : "Blah Blah"}
To get the "Blah Blah" out, we can say
data.name
or we could say :
data["name"]
So based on this, in our situation, instead of
$fullBlock.prev()
Or we could say
$fullBlock["prev"]()
Which is what direction variable contains. So finally, we could do this to select the next/prev element based on what was clicked :
$fullBlockdirection
Show the prev/next element.
Add/remove "hide" class.
Hope this helped!