Ever been in a situation where you have already gathered your results from the server, but you need to do some arbitrary text searching on them? Here's a handy way to do it.
Here it is in action:
See the Pen Filtering Fun with JavaScript by Lorin Tackett (@ltackett ) on CodePen .
... and here's the code:
contacts.haml
Basic iteration through all the elements.
%input .form-control { data: { action: 'text-search' } , type: "text", placeholder: "Filter by name or location" }
.contacts
- contacts . each do | contact |
.card { data: { element: 'item' } }
%h4 = contact . name
%p = contact . address
%p = contact . citystate
contacts.scss
Simple styling for the cards.
@include 'compass' ;
body { padding-top : 3em ; }
.form-control {
position : fixed ;
top : 0 ;
left : 0 ;
right : 0 ;
width : 100% ;
padding : 0 .75em 0 .5em ;
z-index : 1 ;
}
.contacts {
position : relative ;
overflow : hidden ;
padding : 0 .5% ;
& { font-size : 0 ; }
& .card { font-size : initial ; }
}
.card {
@include border-radius ( 0 .25em );
@include box-sizing ( border-box );
display : inline-block ;
background : #333333 ;
color : #ffffff ;
margin : 0 .5% ;
padding : 2em ;
width : 32 .25% ;
& [ data-filtered = false ] { display : none ; }
& [ data-filtered = true ] { display : inline-block ; }
h4 , p {
overflow : hidden ;
text-overflow : ellipsis ;
white-space : nowrap ;
line-height : 1 .25em ;
}
h4 { margin : 0 0 0 .5em ; }
p { margin : 0 ; }
}
text_search.coffee
When I was wiring it up, I chose to use data attr bindings instead of class names. Decoupling your event bindings from your markup classes is a good idea in almost every case.
# Utility function for searching by a word.
hasWordInString = ( word ) -> @ indexOf ( word ) isnt - 1
# Function for filtering items by an array of words
window . filterItems = ( $el ) ->
words = $el . val (). toLowerCase ()
$items = $ ( "[data-element=item]" )
# Split `text` to a space-delimited array.
# We will search by this array later.
words = words . split ( " " )
# Hide all items on event.
$items . attr ( 'data-filtered' , false )
# Is the first item of `text` a non-empty string?
# Cool. Filter the items and show them.
if words [ 0 ]. length > 0
# Iterate through the array of words.
# If any of those words are found in
# the `itemText`, this will return `true`.
# This tells the filter that this item
# matches the search, which then shows it.
$items = $items . filter ->
item = $ ( this )
return words . every ( hasWordInString , item . text (). toLowerCase ())
return
# Show filtered items
$items . attr ( 'data-filtered' , 'true' )
# Text input is empty? Show all items.
else $items . removeAttr ( 'data-filtered' )
return
# Bind actions to event handlers
$ ( "[data-action]" ). each ->
$el = $ ( @ )
action = $el . data ( 'action' )
if action == 'text-search' then $el . on 'keyup' , ( event ) -> filterItems ( $el )