Filter Elements

Here is a simple element filter that hides or shows elements whose data attribute contains the selected tags.




This is from the idea of this post.

Where I managed to get something working but not really how I liked at least.

The Template is me experimenting to create my own filter.

It has two javascript functions that do all the work.

The first is an init() :

 //--SET UP BUTTONS COLOURS
	 
	 var GroupButtons = $("div.tag");
	 
	 
	 
	 $.each(GroupButtons, function( index, value ) {
	 
	
	 
	$(value).css("background-Color", "white");
	 
	
	 });
	 
	 
	  //--SET UP ELEMENT TAG LIST TO DISPLAY TAGS
	  var elementItems  = $("div.item.col-md-3"); 
	  $.each(elementItems, function( index, thisItem ) {
	 var counter =0;
	 
	 var tagString = $(thisItem).attr('data-item-tags');
	 
	 tagString = tagString.replace(/,/g," /\r");
	 
	 var childElement1 = $(thisItem).children()[0] ; 
	 
 
	 
	 var childElement2 = $(childElement1).children(".item-tags")[0];
	 
	 $(childElement2).html(tagString);
	 
	 
	
	 });

This setup the tag buttons colour and also populates the item elements tag list text. Which is displayed at the bottom of each item element.

You can change this to suit you needs. i.e remove the elements tag list text code or add your own setup.

The second function filter() does all the grunt work.

Each item element ( in this example ) is a rectangle with innerHTML added.
Each item element has it's own data attribute,

<div class="item col-md-3" data-item-id="2" data-item-tags="MySQL,JavaScript,jQuery,Memcached,Scala,Rails,Hadoop,Redis">

Which lists its set of tags.
Each item element has text paragraph <p class="item-tags"></p> which is populated by the init() function tags.

The filter() function is called on a filter button click.

The buttons are filter buttons that you select to filter by either a single tag or multiple tags. (buttons)

Each button uses the class name of tag and uses their id uses the name of the tag.

The filter() uses these to know which tags are selected when it is called.

		 //--SET BUTTON COLOUR
	var buttonBackgroundColor =  element.style.backgroundColor;
	
	if (buttonBackgroundColor == "white") {

element.style.backgroundColor = "pink";

 
}else{

element.style.backgroundColor = "white";

}
  
	var hideArray =[];
	var showArray =[];
	var answerElement = element.id;	
	
	 
	  //--TOGGLE THE CLASS OF THIS BUTTON
	$(element).toggleClass( "show" );
	
	//--GET ALL THE ITEM ELEMENTS 
	 var elementItems  = $("div.item.col-md-3"); 
	   
	   //--GET ALL THE TAG BUTTON ELEMENTS 
	var activeTagList =  $("div.HYPE_element.tag.show");
	 
	
	
	var dataListItems =[];
	 ///---->
	  //--GET THE TAG  
	$.each(activeTagList, function( index, tagValue ) {
	var tagged =$(tagValue).attr('id');
	
	 dataListItems.push(tagged);
	 
	});
	
	///---<
 
	
	 ///---->>-
	  //--ITERATE OVER THE ITEM ELEMENTS
	 $.each(elementItems, function( index, thisItem ) {
	 var counter =0;
	 
	  //--GET IT'S  TAG LIST FROM THE DATA ATTRIB.
	 var tagArray = $(thisItem).attr('data-item-tags').split(",");
	 

	 ///---->
	  //--ITERATE OVER THE ACTIVE TAGS
	  $.each(dataListItems, function( index, thisDataItem ) {
	 var tags = tagArray.indexOf(thisDataItem);
		console.log(  tags);
	if ( tags > -1){
	//--TAG EXISTS
	counter++;
	 
	}
	 });
	 ///----<
 
 
	 if ( counter == dataListItems.length ){
	
	  $(thisItem).show();
	 }else{
	 $(thisItem).hide();
	 }
	
		counter =0;	
			
	});

You will notice I have some css styles in the <Head>

This is just because I am using the demo elements from the Original Taggert. And is only used for these elements display. You will not need it for you own


There is more to do on this, like maybe try and animate the filter elements in to a nice order and maybe the auto creation of buttons.

TagFilter_v1.hypetemplate.zip (185.4 KB)

4 Likes

The elements now animate:


I came up with this code.

 //-- ANIMATION
 
 var columnCount = 6
  var leftRange = 45;
  var topRange = 162;
  var counter = 0;
  var changed = false;
  $.each(animateArray, function( index, thisItem ) {
 
 if (counter >= columnCount) {
 topRange = 453;
 
  }
if (  counter >= columnCount) {
if (! changed) {
  
  leftRange = 45;
 changed = true;
 }
  }  
  console.log(counter);
 console.log(leftRange);
  $(thisItem).parent("div.rect").animate({ "left": leftRange, "top": topRange }, "slow" );
 
  
  
  
  leftRange = leftRange + 121;
 
 counter++;
	});

Which is added on to the end of the filter()

Again for your own elements you would need to adjust.

But this will give you some idea of a way to possibly animate the filtered elements.

Also doing it this way does change the overall order of the elements. ( I think I can fix that by giving each element a number and animate in higher number animates last… which thinking about is is why the original TagSort has numbers for each element. I wondered what they where for.

Update:

I fixed the problem of order of the elements when all displayed changing from the original order by using the number I mention above and .Sort() .

It was more simple than I thought it would be :smile:

 animateArray.sort(function(obj1, obj2) {
  
	return $(obj1[0]).attr("data-item-id")  - $(obj2[0]).attr("data-item-id") 
	
});

Updated from v2 to v3


TagFilter_v3.hypetemplate.zip (184.9 KB)

4 Likes

Nice work Mark. Simple and elegant.

D

1 Like

Thanks @DBear,

Still working on it.

I have a reset working now. Just about to start on populating the buttons automatically.

I want to do it so you have a choice of auto or your own.

Mark you did a great job - congratulation. I tried to add a third line and it short well when I click on a button. Nevertheless as soon I click on the same button again to reset the third line get added to the second line. Unfortunately I am a greenhorn in terms of Java Script. Therefore could you please give me a hint how I can fix this problem.

Thank you in advance for your help
Alain

Can you post what you have.

Cheers

here we go

third line.hype.zip (158.1 KB)

Ok. Took me a minute to refresh my memory of this.

I have changed a bit of the code to hopefully account for new rows better.

So what should happen is when we get a row of six elements, (columnCounter >= columnCount) we add 291 pixels to the top property var. And set the leftproperty to back to 45.
We then can reset the column counter to 0.

Look at the code it should make more sense.

TagFilter_v4.hypetemplate.zip (203.0 KB)

3 Likes

Mark - this is perfect. Works absolutely great - exactly what I was looking for. Thank you very much for your fast help.

Hey Mark, the stuff you’re doing to extend Tagsort is really neat. If you’re interested, you should contribute to the GitHub project because I’d love to get your work into the plugin itself.

Came back on this @MarkHunte.
Looking for a solution where i can counting in numbers the filtered objects.
So like having a amount of all tag-objects and then subtract the outfiltered ones and give the result back in a div as text.
How would that be looking in code?

Olof

@Olof

Just above where the sort animation code is add this code.

We simply need to get the existing count of the animateArray and elementItems Arrays.

var shown = animateArray.length ;
var hidden = elementItems.length ;
console.log("shown " + shown);
console.log("hidden " +  ( hidden - shown)); 
	 
	  //-- SORT ANIMATION array

That easy? Wow. Thank you.

i am using this code


and find it great, but i need a amendment.
At present you can select 1 or more options from the tag searches but i need t
the user to click on 1 choice and the other options grewy
out of hide so they cant be selected.
Can someone show me the code to get this up a running.
Cheers

A little to the code to detect button color, change pointer events.

Change :

		 //--SET BUTTON COLOUR
	var buttonBackgroundColor =  element.style.backgroundColor;
	
	if (buttonBackgroundColor == "white") {

element.style.backgroundColor = "pink";

 
}else{

element.style.backgroundColor = "white";

}

To

         //--SET BUTTON COLOUR

 var GroupButtons = $("div.tag");
    	  
    	var buttonBackgroundColor =  element.style.backgroundColor;
   
    	if (buttonBackgroundColor == "white" || buttonBackgroundColor == "grey") {
     
    	 
    	 $.each(GroupButtons, function( index, value ) {
    	 
    	
    	 
    	$(value).css("background-Color", "grey");
    	 $(value).css("pointer-events", "none");
    	
    	 });
    element.style.backgroundColor = "pink";
    element.style.pointerEvents = "auto";
     
    }else{

     $.each(GroupButtons, function( index, value ) {
    	 
    	
    	 
    	$(value).css("background-Color", "white");
    	 $(value).css("pointer-events", "auto");
    	
    	 });

    }

Cheers Mark
Tried and cant seem to get it to work.
Any chance you could send the file amended

Update … Oops posted wrong one…

:stuck_out_tongue_winking_eye:Tag_Single_Filter.hypetemplate.zip (203.8 KB)

Cheers Mark
Thanks for solving this

1 Like

thanks again Mark for the help.
getting stuck with what i am trying to achevie.
I need to set up a smart filter form and this seems to solve most of the problem, but not quite.
i need the user to select options say
male, female the result shows options
one, two, three then shows more options
one, two, three, four the result of this shows a list of the tags attached.
the reason for the one click was only one option can be choosen at a time to reveal the next result options.
hope I have explained ok can this be acheived .
Cheers

Are you able to post your Hype project or an example