Get Font Awesome icons and display them in a list

An AJAX request to get the Font Awesome 4.7.0 icons and then display them in a list.

by Hugo Carneiro

HTML

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.1/css/bootstrap.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/3.12.0/js-yaml.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.11/handlebars.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
<div class="container">
	<div class="search-holder">
		<input type="text" placeholder="Search icons" class="form-control search-field" />
	</div>
	<div class="icon-list-holder">

		<!-- List will be appended here -->

	</div>
</div>



<template id="font-icons-template">
{{#each this}}
<h2>{{@key}}</h2>
<ul>
  {{#each this}}
  <li id="{{id}}">
    <div class="holder">
      <div class="icon">
        <i class="fa fa-{{id}}"></i>
      </div>
      <div class="title">
        <span>{{id}}</span>
      </div>
    </div>
  </li>
  {{/each}}
</ul>
{{/each}}
</template>

<template id="search-results-template">
<h2>Searching for '{{value}}'</h2>
<ul>
  {{#each icons}}
  <li id="{{id}}">
    <div class="holder">
      <div class="icon">
        <i class="fa fa-{{id}}"></i>
      </div>
      <div class="title">
        <span>{{id}}</span>
      </div>
    </div>
  </li>
  {{/each}}
</ul>
</template>

CSS

@import url('https://fonts.googleapis.com/css?family=Roboto');

body {
  font-family: 'Roboto', sans-serif;
  color: #333333;
}

.search-holder {
	margin-top: 25px;
}

.search-holder input {
	border-radius: 25px;
}

h2 {
	padding-bottom: 9px;
	margin: 40px 0 20px;
	border-bottom: 1px solid #eee;
}

ul {
  padding: 0;
  margin: 0;
  list-style-type: none;
  
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  
  -webkit-box-orient: horizontal;
  -ms-flex-direction: row;
  flex-direction: row;
  
  -ms-flex-wrap: wrap;
  flex-wrap: wrap;
  
  -webkit-box-align: start;
  -ms-flex-align: start;
  align-items: flex-start;

  -webkit-box-pack: start;
  -ms-flex-pack: start;
  justify-content: flex-start;
  
  cursor: pointer;
}

ul li {
  display: inline-block;
  width: 16.66666%;
  margin: 0;
  padding-bottom: 1rem;
}

li .holder {
  position: relative;
  border-radius: .25rem;
	overflow: hidden;

  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;

  -webkit-box-orient: vertical;
  -ms-flex-direction: column;
  flex-direction: column;

  -webkit-box-direction: normal;

  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
  
  -webkit-transition: all .5s cubic-bezier(.165,.84,.44,1);
  transition: all .5s cubic-bezier(.165,.84,.44,1);
}

li .holder:hover {
  background-color: #fff;
  box-shadow: 0px 6px 20px 0px rgba(0,0,0,0.1);
}

.holder .icon {
  padding: .5rem;
  
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;

  -webkit-box-orient: vertical;
  -ms-flex-direction: column;
  flex-direction: column;

  -webkit-box-direction: normal;

  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;

  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
}

.holder:hover .icon {
  background-color: #4dadf7;
}

.icon .fa {
  font-size: 30px;
}

.holder:hover .icon .fa {
  color: #ffffff;
}

.holder .title {
	font-size: .8rem;
	text-align: center;
	padding-top:...

JavaScript

var iconsJSON;

function attachListeners() {
	$('.search-field').on('keyup change', function(e) {
		var value = $(this).val();
		if (value.length) {
			value = value.toLowerCase();
			searchIcon(value);
		} else {
			renderFullList(iconsJSON);
		}
	});
}

function searchIcon(value) {
	var results = _.filter(iconsJSON.icons, function(icon) {
		var found = false;

		if (icon.filter) {
			icon.filter.forEach(function(filter) {
				if (filter.toLowerCase().indexOf(value) > -1) {
					found = true;
				}
			});
		}
		
		if (icon.id.toLowerCase().indexOf(value) > -1) {
			found = true;
		}
		
		return found;
	});
	
	console.log(results);
	var finalResult = {
		value: value,
		icons: results
	};
	$('.icon-list-holder h2').text('Searching for "'+value+'"');
	var template = $('#search-results-template').html();
	var hbTemplate = Handlebars.compile(template);
	var $target = $('.icon-list-holder');
	var compiledTemplate = hbTemplate(finalResult);
	$target.html(compiledTemplate);
}

function renderFullList(iconsJSON) {
	var groups = _.groupBy(iconsJSON.icons, function(icon) {
		return icon.categories[0];
	});

	var template = $('#font-icons-template').html();
	var hbTemplate = Handlebars.compile(template);
	var $target = $('.icon-list-holder');
	var compiledTemplate = hbTemplate(groups);
	$target.html(compiledTemplate);
}

function init() {
	attachListeners();

	$.ajax({
		type: 'GET',
		url: 'https://cors-anywhere.herokuapp.com/https://raw.githubusercontent.com/FortAwesome/Font-Awesome/fa-4/src/icons.yml',
		success: function(data) {
			iconsJSON = jsyaml.load(data);
			
			renderFullList(iconsJSON)
		},
		error: function(error) {
			console.log('error')
		}
	});
}

var nTimer = setInterval(function() {
	if (window.jQuery) {
		init();
		clearInterval(nTimer);
	}
}, 100);