JQuery Filtering Using Bootstrap Columns - javascript

So I have this working fiddle: https://jsfiddle.net/p5ahob32/1/
$('#filter').keyup(function () {
var filter = $(this).val(), count = 0;
$('.col-md-3 a').each(function () {
// If the list item does not contain the text phrase fade it out
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut();
// Show the list item if the phrase matches and increase the count by 1
} else {
$(this).show();
count++;
}
});
// Update the count
var numberItems = count;
$("#filter-count").text("Number of Clients = " + count);
});
If you were to type 3 in the search box it would fade out all the other buttons except 3, however you will notice that the 3 button is all the way in the right because it is in a bootstrap column.
My question is how to I make it so that all the searched items will appear stacked nicely together at the top left?
Thank you!

get rid of all the rows except the outer one that wraps all the col's and hide parent of the <a>
$(this).parent().fadeOut();
//AND
$(this).parent().show()
DEMO

// change
$(this).fadeOut();
// to
$(this).parent().css("display","none");
// or
$(this).parent().fadeOut()

Related

JS hover negative space between items

So I have a container with a grid of items and I want to be able to detect hover between rows. Not the individual items.
Its important to remember that the number of items, in the container and per row, will change.
My container of items currently looks like this
<div class="container">
<div class="hover-placeholder"></div>
<div class="row">
<!-- Start : Items -->
<div class="col-md-3">...</div>
<div class="col-md-3">...</div>
<div class="col-md-3">...</div>
<div class="col-md-3">...</div>
...
<div class="col-md-3">...</div>
<!-- End : Items -->
</div>
</div>
Preferably I DO NOT want to put a placeholder element every 4th item. Mainly because on smaller screens the number of items per row will reduce. This is why in my example above I have a single placeholder outside the grid that I want to transform: translateY(..) to the position between the hovered rows.
This is what I have currently: https://jsfiddle.net/0t8c0h4m/
Its nowhere near the result I am after but I have got to the point where I am overthinking it and getting stuck.
Any help would be great!
UPDATE
The goal for this functionality is when the user hovers the negative space, the .hover-placeholder will translate to that position and become visible. And when clicked will add a permanent separator between the rows.
SUCCESS!
I have solved my issue! Thank you all for your help.
Here is my solution: https://jsfiddle.net/0t8c0h4m/9/
I think that you are complicating stuff too much if you are only looking for the hover effect between the elements and nothing else.
Updated:
var offsets;
function get_offsets() {
offsets = {};
$('.card').each(function() {
var $this = $(this);
var card_offset = $this.offset().top;
offsets[card_offset] = {
ele: $this
};
})
}
get_offsets();
function get_last_ele(mouse_location) {
var element;
var previous_key;
$.each(offsets, function(key, obj) {
if (key > mouse_location && previous_key > 0) {
element = offsets[previous_key].ele;
return false;
}
previous_key = key;
})
return element;
}
$('.container').mousemove(function(e) {
if ($(e.target).parents('.row').length == 0) {
var last_item_row = get_last_ele(e.pageY)
console.log(last_item_row.text())
}
});
JSFiddle: https://jsfiddle.net/0t8c0h4m/6/
I'm only providing the code that gets the last item on the row before the space you are hovering. From there you can append the line or transition the placeholder the way you like it.
Please try with following script
(function($) {
'use strict';
// Count items per row
function items_per_row($collection) {
var count = 0;
$collection.each(function() {
var $this = $(this);
if ($this.prev().length > 0) {
if ($this.position().top !== $this.prev().position().top) {
return false;
} else {
count++;
}
} else {
count++;
}
});
var last = count ? $collection.length % count : 0,
rows = count ? Math.round($collection.length / count) : 0;
if (last == 0) {
last = count;
}
return {
count: count,
last: last,
rows: rows
}
};
// On card hover, print current row
$('.card').mouseenter(function() {
var $card = $(this);
var item_count = items_per_row( $('.card') ),
index = $(this).index(),
current_row = Math.floor(index / item_count.count) + 1;
$('pre').text( $card.find('.inner').text() + ' is in row '+ current_row );
});
$('.card').mouseout(function(){
$('pre').text('');
});
})(jQuery);
So I have come up with a solution to show dividers between each row using CSS. I just have been overthinking this issue.
I have added a dividing element after each item and with css nth-child() I can show specific dividers at each break point.
I have also added the grouping functionality I was aiming for.
Updated example: https://jsfiddle.net/0t8c0h4m/9/

how to show child element in right panel?

hi can you please tell me how show child element in right element .My function work fine first time But it fail second time .
I do the following steps
1) Press Add button 2 times.Generate row2 as well as submenu of firstLevel.
2) Expand menu option (+) Button.Click "menu_tc_1".It remove rows on right panel .and press add button it create nested submenu .
3) When you press again "menu_tc_1" it show same number of rows as many you click add button.
4) But when you click "First Level " it should show two rows because it have two child("menu_tc_1","menu_tc_2") .It is showing all rows.Because in array it gives all values.
I need show only child
jsFiddle
$(document).on('click', 'ul li > a', function (e) {
//first method..
console.log($(this).siblings().length);
var selEl = [];
$(this).closest('ul').find('li').each(function (idx, el) {
var id= el.id.replace('menu_','');
selEl.push(id);
});
// alert(id);
console.log('aaa' + selEl);
getViewFromPanel(selEl);
});
function getViewFromPanel(arr) {
console.log(arr);
$('#ultest').html('');
for (var i = 1; i < arr.length; i++) {
$('#ultest').append('<li id=' + arr[i] + '>' + arr[i] + '</li>');
}
}
See this updated fiddle.
The main problem is $(this).closest('ul').find('li').each(function (idx, el) {. find will look for all sub levels, that is why is displays all menus. You only want the children of the next ul:
$(this).closest('li').children('ul').children().each(function (idx, el) {
Also, you skip the first element (probably due to using find) in getViewFromPanel - it should start at 0 index:
for (var i=0;i<arr.length;i++){
There is a problem with the way that you set the active class so when you go back and click add, it is added to the wrong hierarchy. I am not sure what your intention is with the active class, but I think that you should clear the class $('.active').removeClass('active') and set it again when the hierarchy changes.

How to reduce 180 lines of code down to 20 in Javascript?

I have a lot of click handler functions which are almost (textually and functionally) identical. I've got a menu with maybe 10 items in it; when I click on an item, the click handler simply makes one div visible, and the other 9 div's hidden. Maintaining this is difficult, and I just know there's got to be a smart and/or incomprehensible way to reduce code bloat here. Any ideas how? jQuery is Ok. The code at the moment is:
// repeat this function 10 times, once for each menu item
$(function() {
$('#menuItem0').click(function(e) {
// set 9 divs hidden, 1 visble
setItem1DivVisible(false);
// ...repeat for 2 through 9, and then
setItem0DivVisible(true);
});
});
// repeat this function 10 times, once for each div
function setItem0DivVisible(on) {
var ele = document.getElementById("Item0Div");
ele.style.display = on? "block" : "none";
}
Create 10 div with a class for marking
<div id="id1" class="Testing">....</div>
<div id="id2" class="Testing">....</div>
<div id="id3" class="Testing">....</div>
and apply the code
$('.Testing').each(function() {
$(this).click(function() {
$('.Testing').css('display', 'none');
$(this).css('display', 'block');
}
}
$(document).ready(function (){
$("div").click(function(){
// I am using background-color here, because if I use display:none; I won't
// be able to show the effect; they will all disappear
$(this).css("background-color","red");
$(this).siblings().css("background-color", "none");
});
});
Use .siblings() and it makes everything easy. Use it for your menu items with appropriate IDs. This works without any for loops or extra classes/markup in your code. And will work even if you add more divs.
Demo
Fiddle - http://jsfiddle.net/9XSJW/1/
It's hard to know without an example of the html. Assuming that there is no way to traverse from the menuItem to ItemDiv - you could use .index and .eq to match up the elements based on the order they match with the selector.
var $menuItems = $("#menuItem0, #menuItem1, #menuItem2, ...");
var $divs = $("#Item0Div, #Item1Div, #Item2Div, ...");
$menuItems.click(function(){
var idx = $(this).index();
// hide all the divs
$divs.hide()
// show the one matching the index
.eq(idx).show();
})
Try
function addClick(i) {
$('#menuItem'+i).click(function(e) {
// set nine divs hidden, 1 visble
for( var j = 0; j < 10; ++j ) {
var ele = document.getElementById("Item"+j+"Div");
ele.style.display = (i == j ? "block" : "none");
}
});
}
// One click function for all menuItem/n/ elements
$('[id^="menuItem"]').on('click', function() {
var id = this.id; // Get the ID of the clicked element
$('[id^="Item"][id$="Div"]').hide(); // Hide all Item/n/Div elements
$('#Item' + id + 'Div').show(); // Show Item/n/Div related to clicked element
});
Obviously this would be much more logical if you were using classes instead:
<elem class="menuItem" data-rel="ItemDiv-1">...</elem>
...
<elem class="ItemDiv" id="ItemDiv-1">...</elem>
$('.menuItem').on('click', function() {
var rel = $(this).data('rel'); // Get related ItemDiv ID
$('.ItemDiv').hide(); // Hide all ItemDiv elements
$('#' + rel).show(); // Show ItemDiv related to clicked element
});
Save the relevant Id's in an array - ["Item0Div", "Item1Div", ...]
Create a generic setItemDivVisible method:
function setItemDivVisible(visible, id) {
var ele = document.getElementById(id);
ele.style.display = visible ? "block" : "none";
}
And set your click handler method to be:
function(e) {
var arrayLength = myStringArray.length;
for (var i = 0; i < idsArray.length; i++) {
setItemDivVisible(idsArray[i] === this.id, idsArray[i]);
}
}
I think this will do the trick

Filtering divs based on classes, using jQuery

Looking for some help on how to write a function to filter out certain divs with certain classes.
Essentially I have thrown together a quick e-commerce example. There are lists of different filters, with values. There are then products. Each product div has a number of classes applied to it, e.g "green" or "adult" or "wool" - these are the filterable parameters.
Not being savvy at all with JS I'm trying to write something, but looking for some advice. Here is basically what I'm after:
Starts with displaying all
If user selects GREEN, all items that do not have GREEN attributed are display:none'd (with a fade transition
Rep #2 for any attribute checked
Notes: multiple attributes can be checked, when items are unchecked, everything needs to reappear.
Any help? I guess it's basically linking up the value of each checkbox to the class.
Not sure if there is a better way codewise to do this... data attributes maybe?
Working example of the code here (obviously no JS)
Updated your fiddle and added some jQuery to hide the divs where the classes don't match the selected checkboxes.
Demo: fiddle
JS is a bit verbose, you can refactor it further if you like:
$(document).ready(function() {
var allSelectedClasses;
allSelectedClasses = '';
$('input[type="checkbox"]').click(function(){
//ensure the correct classes are added to the running list
if(this.checked){
allSelectedClasses += '.' + $(this).val();
}else{
allSelectedClasses = allSelectedClasses.replace($(this).val(), '');
}
//format the list of classes
allSelectedClasses = allSelectedClasses.replace(' ', '');
allSelectedClasses = allSelectedClasses.replace('..', '.');
var selectedClasses;
var allSelected;
allSelected = '';
//format these for the jquery selector
selectedClasses = allSelectedClasses.split(".");
for(var i=0;i < selectedClasses.length;i++){
var item = selectedClasses[i];
if(item.length > 0){
if(allSelected.length == 0){
allSelected += '.' + item;
}else{
allSelected += ', .' + item;
}
}
}
//show all divs by default
$("div.prodGrid > div").show();
//hide the necessary ones, include the 2 top level divs to prevent them hiding as well
if(allSelected.length > 0){
$("div.prodGrid > div:not(" + allSelected + ")").hide();
}
});
});
I added a new class to your Colors ul. Hope that's okay.
Here's a crude version of a filtering function, it only takes colors into account so you have to modify it yourself to take everything into account but the basic outline is there.
It can be refactored massively! :)
Since you're using jQuery:
$('ul.colorFilter li input[type="checkbox"]').click(function(){
var checkedBoxes = $('ul.colorFilter li input[type="checkbox"]:checked');
var listOfClasses = [];
checkedBoxes.each(function(index, el){
listOfClasses.push(el.value);
});
if(listOfClasses.length >= 1){
$('div.prodGrid').children('div').hide();
for(var i = 0; i < listOfClasses.length; i++){
$('div.prodGrid > div.'+listOfClasses[i]).show();
}
} else {
$('div.prodGrid > div').show();
}
});
I made a fiddle as well:
http://jsfiddle.net/Z9ZVk/4/

Prevent checkbox tick after Nth selection (allow more from the same category)

We have checkboxes in two columns (they denote the same category, but different subscription)
We would like to limit the selection to 4. We have a jQuery code to disable the checkbox selection after the user selected 4.
But now we need to have the following logic:
Allow the user to choose both values from the same rows (aka: subscribe to both subscriptions from the same category) and do not count in the 4 limit we have if they have chosen more from the same row.
So if you look in the following screencast, we would like to be able to select the first checkbox (1st row).
The code we used was:
$("input:checkbox").click(function() {
var bol = $("input:checkbox:checked").length >= 4;
$("input:checkbox").not(":checked").attr("disabled",bol);
});
A jsFiddle has been created to reflect the current state of work:
http://jsfiddle.net/fFbLx/
Feel free to name the classes, inputs as you wish.
I think you would have to "categorise" them by the LI then. So count the LI's with an checked box - disable all others if more than 4 active.
See: http://jsfiddle.net/fFbLx/4/ (maybe give the UL's a class, so you can use the selector on that)
$("input:checkbox").click(function() {
var counter = 0;
$('li').each( function() {
if($(this).find("input:checkbox:checked").length)
{
$(this).addClass('active');
counter++;
} else {
$(this).removeClass('active');
}
});
var bol = counter >= 4;
$('li').not('.active').find("input:checkbox").not(":checked").attr("disabled",bol);
});
If you wrap your checkboxes in an element you can then use the jquery has selector filter to check how many have selected checkboxes:
$("input:checkbox").click(function() {
var bol = $(".myCheckboxWrapper:has(input:checkbox:checked)").length >= 4;
$("input:checkbox").not(":checked").attr("disabled",bol);
});
Try this http://jsfiddle.net/fFbLx/2/
$("input:checkbox").click(function() {
$(this).parent().find("input:checkbox:first").toggleClass("active");
var bol = $("input:checkbox:checked").length >= 4;
$("input:checkbox").not(":checked,.active").attr("disabled",bol);
});

Categories

Resources