JSFiddle - React, Tailwind, and code Playground
HTML
<body>
<header>
<h1 id="heading">theMetaCity<wbr><span id="headerhighlight">Workshop</span></h1>
<h3 id="subheading" >Documentation, explanation and showcase for projects.</h3>
</header>
<div id="workshopsearch">
<input type="text" id="searchinput" placeholder="Type to search the workshop"/>
<button id="reset">Reset</button>
</div>
<main id="workshopBlurbEntries">
<article class="workshopentry">
<header>
<h1><a href="/workshop/3">Custom Canon 400D autotaker</a></h1>
<h5>Started: 2013-12-07</h5>
<h5>Updated: 2014-04-04</h5>
<ul>
<li><a rel="tag" href="/workshop/tag/Arduino">Arduino</a></li>
<li><a rel="tag" href="/workshop/tag/Hacking">Hacking</a></li>
</ul>
</header>
<div class="right">
<p>The Canon 400D has a 2.5mm stereo jack on the side that allows a shutter trigger access to the camera. Lets build one.</p>
</div>
</article>
<article class="workshopentry">
<header>
<h1><a href="/workshop/2">Developing, deploying and administrating on Tomcat, PostgreSQL and Linux</a></h1>
<h5>Started: 2013-09-04</h5>
<h5>Updated: 2013-09-15</h5>
<ul>
<li><a rel="tag" href="/workshop/tag/guide">guide</a></li>
</ul>
</header>
<div class="right">
<p>This is an ongoing journal about aspects of developing, deploying and administrating a fairly small website (this one) on a Tomcat, PostgreSQL and Linux stack. It chronicles some of the decisions I have made as a well as technical solutions and pseudo-documentation of the whole process. It is very much an ongoing piece of work.</p>
</div>
</article>
<article class="workshopentry">
<header>
<h1><a...
JavaScript
$(document).ready(function () {
"use strict";
var $noResults, $searchBox, $entries, searchTimeout, firstRun, loc, hist, win;
$noResults = $('#noresults');
$searchBox = $('#searchinput');
$entries = $('#workshopBlurbEntries');
searchTimeout = null;
firstRun = true;
loc = location;
hist = history;
win = window;
function reset() {
if (hist.state !== undefined) { // Avoid infinite loops
hist.pushState({"tag": undefined}, "theMetaCity - Workshop", "/workshop/");
}
$noResults.hide();
$entries.fadeOut(150, function () {
$('header ul li', this).removeClass('searchMatchTag');
$('header h1 a span', this).removeClass('searchMatchTitle'); // The span remains but it is destroyed when filtering using the text() function
$(".workshopentry", this).show();
});
$entries.fadeIn(150);
}
function filter(searchTerm) {
if (searchTerm === undefined) { // Only history api should push undefined to this, explicitly taken care of otherwise
reset();
} else {
var rePattern = searchTerm.replace(/[.?*+^$\[\]\\(){}|]/g, "\\$&"), searchPattern = new RegExp('(' + rePattern + ')', 'ig'); // The brackets add a capture group
$entries.fadeOut(150, function () {
$noResults.hide();
$('header', this).each(function () {
$(this).parent().hide();
// Clear results of previous search
$('li', this).removeClass('searchMatchTag');
// Check the title
$('h1', this).each(function () {
var textToCheck = $('a', this).text();
if (textToCheck.match(searchPattern)) {
textToCheck = textToCheck.replace(searchPattern, '<span class="searchMatchTitle">$1</span>'); //capture group ($1) used so that the replacement...