Strange jQuery behaviour while showing hiding contents - javascript

I have a series of html contents called filters which is generated from database. The contents can change dynamically according to the page. I have given css IDs to each main div and appended a number with them while looping. Below is a sample snippet:
<div><a id="filter-1">Brands</a></div>
<div id="filter-op-1">This is option 1</div>
<div><a id="filter-2">Size</a></div>
<div id="filter-op-2">This is option 2</div>
<div><a id="filter-3">Color</a></div>
<div id="filter-op-3">This is option 3</div>
the ids filter-1 and filter-op-1 and so on are generated by the number of loops, so we dont know how much contents on the page will be generated for the filters.
I need to show/hide the filter-op-x contents by a click, so i wrote the following jQuery code:
$(document).ready(function () {
$('div a').click(function() {
var self = $(this);
var cssId = self.attr('id');
var child = $('div#filter-op-'+cssId);
child.toggle();
});
});
Now the problem is that it is not working in this way, but if i remove the cssId in js code and -1, -2 etc in html, it start working, but it is hiding all contents no matter which a i clicked.
I dont understant what is causing this issue. Anybody can explain this problem and give some good advice how to handle it?
JsFiddle is here
Thanks

You need to make some changes in your JS code like this:
$(document).ready(function () {
$('div a').click(function() {
var self = $(this);
var cssId = self.attr('id');
console.log(cssId); // This gives the `a` id.
var id = cssId.split("-")[1]; // Split and get the number part
console.log(id);
var child = $('div#filter-op-'+id); // append the number part here
child.toggle();
});
});
The fiddle: https://jsfiddle.net/sandenay/uk1Lquuh/1/

Problem found :
your cssId always return filter-1, filter-2, filter-3
and child become as 'div#filter-op-'+cssId) ==> 'div#filter-op-filter-1 which is produce wrong id of child div.
I have added extra data attribute
Here is my working code:
HTML :
<div><a id="filter-1" data="1">Brands</a></div>
<div id="filter-op-1">This is option 1</div>
<div><a id="filter-2" data="2">Size</a></div>
<div id="filter-op-2">This is option 2</div>
<div><a id="filter-3" data="3">Color</a></div>
<div id="filter-op-3">This is option 3</div>
JS :
$(document).ready(function () {
$('div a').click(function() {
var self = $(this);
var cssId = self.attr('data');
var child = $('div#filter-op-'+cssId);
child.toggle();
});
});
updated JSFIDDLE example

Related

Loading content in a target div using jquery

So the first part of the code works fine as it should be, the two grid and list view loads in the views-div when clicked, however, I want a default view shown in the views-div using jquery, I tried loading using clone and prependto but it doesn't work. any suggestion on how to do this?
note: the content I'm loading from the backend has tags and ID's so if I use the html markup to show a default content in the views-div the content repeats. So I'm hoping if use jquery to load content, the repeating will not occur.
here's a demo http://jsfiddle.net/soulsurfer/eta0uyye/
$(document).ready(function() {
$('.iw-grid-select, .iw-list-select').on('click', function() {
var aID = $(this).attr('href');
var elem = $('' + aID).html();
$('#iw-grid-view').fadeOut("slow", 1000);
$('#iw-listview').fadeOut("slow", 1000);
$('#iw-views-div').html(elem);
});
$( "#iw-grid-view" ).contents().find( ".iw-grid-list-col" ).clone().prependTo("#iw-views-div");
});
The simplest solution could be is to trigger a click event
$(document).ready(function() {
$('.iw-grid-select, .iw-list-select').on('click.view', function() {
var aID = $(this).attr('href');
var elem = $('' + aID).html();
$('#iw-grid-view').fadeOut("slow", 1000);
$('#iw-listview').fadeOut("slow", 1000);
$('#iw-views-div').html(elem);
}).first().trigger('click.view');
});
.iw-listview,
.iw-grid-view {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="iw-filter-col ">
grid view link
list view link
</div>
<div class="row iw-listing-view-row">
<div class="iw-grid-view" id="iw-grid-view">Grid view content</div>
<div id="iw-listview" class="iw-listview">list view content</div>
<div class="iw-views-div" id="iw-views-div">Content loading column</div>
<div id="loading"></div>
</div>
I know that this has been resolved, but just in case anyone was wondering where OP went wrong, I have a theory.
This:
$( "#iw-grid-view" ).contents().find( ".iw-grid-list-col" ).clone().prependTo("#iw-views-div");
Should be changed to this:
$( "#iw-grid-view" ).find( ".iw-grid-list-col" ).clone().prependTo("#iw-views-div");
If the .iw-grid-list-col element was an immediate child of #iw-grid-view, then find() wouldn't have found it when called on the return value of contents(). This is because find() searches through descendants of elements. The return value of contents(), in this case, would have included the .iw-grid-list-col element and find() would not have found it since it was a member of the array that find() was called on, rather than a descendant of a member of the array.
Removing contents() from that chain of function calls allows find() to search all of the descendants of #iw-grid-view instead of just the descendants of its immediate children.

count of dynamically created DIVs returning zero

Following is my code and relevant HTML , what i wanna do is that i wanna count the number of search-img-box within search-img-ctrl but i get 0 as output, just to tell here that
following div search-img-box is dynamically created.
jQuery(document).ready(function() {
var numberOfDivs = jQuery('#search-img-ctrl').filter('.search-img-box').length;
alert(numberOfDivs);
});
following is my HTML
<div id="search-img-ctrl" class="search-img-ctrl">
<div id="search-img-box" class="search-img-box" name="search-img-box">
<img width="335" height="206" src="" alt="">
<ul>
</div>
<div id="search-img-box" class="search-img-box" name="search-img-box">
</div> </div>
Here's a fiddle: http://jsfiddle.net/t5jcT/
I changed filter to find and got rid of the duplicate ids in the html.
jQuery(document).ready(function() {
var numberOfDivs = jQuery('#search-img-ctrl').find('.search-img-box').length;
alert(numberOfDivs);
});
or you can use selectors instead of the find as others have pointed out:
jQuery(document).ready(function() {
var numberOfDivs = jQuery('#search-img-ctrl .search-img-box').length;
alert(numberOfDivs);
});
use .find instead of .filter:
var numberOfDivs = jQuery('#search-img-ctrl').find('.search-img-box').length;
alert(numberOfDivs);
If you want to only find the number of direct children with that class you can use .children
var numberOfDivs = jQuery('#search-img-ctrl').children('.search-img-box').length;
Also make sure you edit your html so that your html elements don't have duplicate IDs

Adding removed attributes back on hover method

have used the following code to remove the style and id attributes from my html, but I would like them to come back once the visitor moves to another element. I'm fairly new to jQuery and have no idea how to achieve that. I would really appreciate somebody's help.
<div class="base" style="background-image: url(img/3.jpg);">
<div id="overlay"></div>
</div>
<script>
$('.base').hover(function(){
$(this).removeAttr('style').children().removeAttr('id');
}, function(){
$(this).addBack();
});
</script>
You have a wrong idea of what addBack() does, anyway the best here might be to use CSS classes.
Something like:
$('.base').hover(function(){
$(this).addClass('myClass');
}, function(){
$(this).removeClass('myClass');
});
Example
The part of the code where you remove the ID is irreversible, so I would find a alternative behaviour/solution there...
Something like this should work :
<div class="base" style="background-image: url(img/3.jpg);">
<div id="overlay"></div>
</div>
<script>
$('.base').hover(function(){
var $this = $(this);
$this.data('style', $this.attr('style')).removeAttr('style').children().each(function(){
var $this = $(this);
$this.data('id', $this.attr('id')).removeAttr('id');
});
}, function(){
var $this = $(this);
$this.attr('style',$this.data('style')).removeData('style').children().each(function(){
var $this = $(this);
$this.attr('id', $this.data('id')).removeData('id');
});
});
</script>
Basically we are storing attribute values in jQuery data arrays. I didn't test it but it should work, I've used this approach more than once..
Updated the code, and here is a working jsfiddle example

Appended Content is Not Triggering - Even using .on()

I append the following content using jQuery to create a lightbox style popup that loads loads content using AJAX:
<div id="framebox-overlay">
<div id="framebox-wrapper">
<div id="framebox-nav-wrapper">
Previous
Next
</div>
<section id="framebox-content">
<!--AJAX to insert #single-project-wrapper content here-->
</section>
<div id="framebox-close">
<p>Click to close</p>
</div>
</div>
</div>
I am trying to get the appended next/previous links to work (.framebox-next and .framebox-prev as shown above), however the links are not triggering properly:
jQuery(document).ready(function(){
$('.framebox-trigger').click(function(e){
// Code that appends lightbox HTML and loads initial AJAX content goes here
});
// Code that isn't working:
$('body').on('click', 'a .framebox-next', function(e) {
e.preventDefault();
//remove and add selected class
var next = $('#portfolio-wrapper li.current-link').next('li > a');
$('#portfolio-wrapper li.current-link').removeClass('current-link');
$(next).addClass('current-link');
//fade out and fade in
var nexthref = $('#portfolio-wrapper li.current-link a').attr('href');
$('#single-page-wrapper').fadeOut('slow', function(){
var current = $('#portfolio-wrapper li.current-link a');
$(this).load(nexthref + " #single-page-wrapper", function(){
$(this).fadeIn('fast');
});
});
return false;
});
});
This last bit of code is not doing anything to the appended link .framebox-next. I have looked for other answers, and it seems that the .on() method should be effecting appended content.
Any help or input would be great.
Your selector is wrong for .framebox-next. You have a space between a and .framebox-next which would mean .framebox-next needs to be a child of the a element.
Use this selector instead:
$('body').on('click', 'a.framebox-next', function(e) {
...
}

Select hidden elements and manipulate them with jQuery

Within a div wrapper with a class of "section", I have dozens of HTML elements repeated across the page that look like this:
<div class="section">
<div class="article"></div>
<div class="article"></div>
<div class="article"></div>
</div>
And each contains certain information inside. Now, what I'm trying to do is once the page loads, show only the first 5, hide the rest in a new div inserted with jQuery, and when this new div is clicked it will display the next five , and then the next five on click again, and so on until the end. The idea is that this new div will function as a button that will always be positioned at the end of the page and will respond to these orders I just mentioned. So far I've got this down:
$('.section').each(function () {
var $this = $(this),
$allArticles = $this.find('.article');
if ($allArticles.length > 5) {
$('<div/>').addClass('hidden-articles').appendTo(this).append($allArticles.slice(5));
$('.hidden-articles .article').hide();
}
});
And that hides all but the first five. But now for the rest of the process, I can't get it to work. I don't seem to be able to select properly those hidden div with class "article" and manipulate them to function the way I described above. I would appreciate it a lot if someone more experienced with jQuery could guide me in the right direction and maybe offer a snippet. Many thanks in advance!
You can use the :hidden and :lt selectors to get the functionality you are looking for..
$('.section').each(function() {
var $this = $(this),
$allArticles = $this.find('.article');
if ($allArticles.length > 5) {
$('<div/>').addClass('hidden-articles')
.appendTo(this).append($allArticles.slice(5));
$this.find('.hidden-articles .article').hide();
}
});
$('#show').on('click',function() {
var $hidden = $('.hidden-articles .article:hidden:lt(5)');
$hidden.show();
});​
UPDATE
// If one one element to search
var elem = '.section' ;
hideArticles(elem);
// If Multiple Elements on the page...
$('.section').each(function() {
hideArticles(this);
});
$('#show').on('click', function() {
var $hidden = $('.hidden-articles .article:hidden:lt(5)');
$hidden.show();
});
function hideArticles(elem) {
var $this = $(elem),
$allArticles = $this.find('.article');
if ($allArticles.length > 5) {
$('<div/>').addClass('hidden-articles')
.appendTo(this).append($allArticles.slice(5));
$this.find('.hidden-articles .article').hide();
}
}​
Check Fiddle

Categories