Browse Source

Remove search overlay

- Fixes #88
- Replace overlay with dedicated search page (see /search/index.md)
- Replace simpleJekyllSearch.js
- Include pages in search.json index
Michael Rose 4 years ago
parent
commit
a9ab8b7bf7

+ 1
- 0
404.md View File

@@ -3,6 +3,7 @@ layout: page
3 3
 title: "Page Not Found"
4 4
 description: "Page not found. Your pixels are in another canvas."
5 5
 sitemap: false
6
+search_omit: true
6 7
 ---  
7 8
 
8 9
 Sorry, but the page you were trying to view does not exist --- perhaps you can try searching for it below.

+ 1
- 1
README.md View File

@@ -11,7 +11,7 @@ Looking for a simple, responsive, theme for your Jekyll powered blog? Well look
11 11
 * Minimal embellishments and subtle animations.
12 12
 * Optional large feature images for posts and pages.
13 13
 * [Custom 404 page](http://mmistakes.github.io/so-simple-theme/404.html) to get you started.
14
-* [Simple site search](https://github.com/christian-fei/Simple-Jekyll-Search)
14
+* Basic [search capabilities](https://github.com/mathaywarduk/jekyll-search)
15 15
 * Support for Disqus Comments
16 16
 
17 17
 ![screenshot of So Simple Theme](http://mmistakes.github.io/so-simple-theme/images/so-simple-theme-preview.jpg)

+ 1
- 1
_config.yml View File

@@ -5,7 +5,7 @@ locale: en_US
5 5
 description: Describe your website here.
6 6
 logo: site-logo.png
7 7
 search: true
8
-url: 
8
+url: http://localhost:4000
9 9
 
10 10
 
11 11
 # Jekyll configuration

+ 4
- 1
_data/navigation.yml View File

@@ -13,4 +13,7 @@
13 13
   url: /theme-setup/
14 14
 
15 15
 - title: Made Mistakes
16
-  url: http://mademistakes.com
16
+  url: http://mademistakes.com
17
+
18
+- title: Search
19
+  url: /search/

+ 0
- 3
_includes/navigation.html View File

@@ -9,15 +9,12 @@
9 9
 		    {% endif %}
10 10
 		    <li><a href="{{ domain }}{{ link.url }}" {% if link.url contains 'http' %}target="_blank"{% endif %}>{{ link.title }}</a></li>
11 11
 		  {% endfor %}
12
-        {% if site.search %}<li class="dosearch"><span><i class="fa fa-search"></i> Search</span></li>{% endif %}
13 12
 	    </ul>
14 13
 	</nav>
15 14
 </div><!-- /.navigation-wrapper -->
16 15
 
17 16
 {% include browser-upgrade.html %}
18 17
 
19
-{% if site.search %}{% include site-search.html %}{% endif %}
20
-
21 18
 {% if page.image.feature %}<header class="masthead">
22 19
 	{% if site.logo != null %}
23 20
 		<div class="wrap">

+ 0
- 38
_includes/scripts.html View File

@@ -1,45 +1,7 @@
1 1
 <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
2 2
 <script>window.jQuery || document.write('<script src="{{ site.url }}/assets/js/vendor/jquery-1.9.1.min.js"><\/script>')</script>
3 3
 <script src="{{ site.url }}/assets/js/scripts.min.js"></script>
4
-{% if site.search %}
5
-<!-- Jekyll Simple Search option -->
6
-<script>
7
-  $(document).ready(function() {
8
-      $('.search-field').jekyllSearch({
9
-          jsonFile: '{{ site.url }}/search.json',
10
-          searchResults: '.search-results',
11
-          template: '<li><article><a href="{url}">{title} <span class="entry-date"><time datetime="{date}">{shortdate}</time></span></a></article></li>',
12
-          fuzzy: true,
13
-          noResults: '<p>Nothing found.</p>'
14
-        });
15
-  });
16 4
 
17
-  (function( $, window, undefined ) {
18
-    
19
-     var bs = {
20
-          close: $(".close-btn"),
21
-          searchform: $(".search-form"),
22
-          canvas: $(".js-menu-screen"),
23
-          dothis: $('.dosearch')
24
-      };
25
-    
26
-    bs.dothis.on('click', function() {
27
-      $('.search-wrapper').css({ display: "block" });
28
-      $('body').toggleClass('no-scroll');
29
-      bs.searchform.toggleClass('active');
30
-      bs.searchform.find('input').focus();
31
-      bs.canvas.toggleClass('is-visible');
32
-    });
33
-    
34
-      bs.close.on('click', function() {
35
-        $('.search-wrapper').removeAttr( 'style' );
36
-        $('body').toggleClass('no-scroll');
37
-        bs.searchform.toggleClass('active');
38
-        bs.canvas.removeClass('is-visible');
39
-    });
40
-  })( jQuery, window );
41
-</script>
42
-{% endif %}
43 5
 {% if site.owner.google.analytics %}
44 6
 <!-- Asynchronous Google Analytics snippet -->
45 7
 <script>

+ 0
- 7
_includes/site-search.html View File

@@ -1,7 +0,0 @@
1
-<div class="search-wrapper">
2
-  <div class="search-form">
3
-    <input type="text" class="search-field" placeholder="Search...">
4
-    <button class="close-btn"><i class="fa fa-times-circle fa-2x"></i></button>
5
-    <ul class="search-results post-list"></ul><!-- /.search-results -->
6
-  </div><!-- /.search-form -->
7
-</div><!-- ./search-wrapper -->

+ 22
- 1
_sass/_forms.scss View File

@@ -229,4 +229,25 @@ select:focus {
229 229
 .form-inline .checkbox input[type="checkbox"] {
230 230
 	float : left;
231 231
 	margin-left : 0;
232
-	margin-right : 3px; }
232
+	margin-right : 3px; }
233
+
234
+
235
+// Search
236
+// --------------------------------------------------
237
+
238
+.simple-search {
239
+	text-align: center;
240
+	label {
241
+		display: none;
242
+	}
243
+
244
+	/* input field */
245
+	#goog-wm-qt {
246
+		@include media($medium) {
247
+			width: 80%;
248
+		}
249
+	}
250
+
251
+	/* submit button */
252
+	#goog-wm-sb {}
253
+}

+ 6
- 0
_sass/_layout.scss View File

@@ -344,6 +344,12 @@ span + .entry-title {
344 344
 			display: inline;
345 345
 		}
346 346
 	}
347
+	/* post excerpt */
348
+	.excerpt {
349
+		display: block;
350
+		float: none;
351
+		@include font-size(14, no, 16);
352
+	}
347 353
 }
348 354
 // Tag index
349 355
 .tag-box {

+ 0
- 78
_sass/_simple-search.scss View File

@@ -1,78 +0,0 @@
1
-// Jekyll Simple Search
2
-// -------------------------------------------------
3
-.search-form {
4
-  width: 100%;
5
-  position: relative;
6
-  opacity: 0;
7
-  transition: all 200ms 100ms cubic-bezier(0, 0.6, 0.4, 1);
8
-  top: 0;
9
-  left: -200px;
10
-  z-index: 9002;
11
-  .search-field {
12
-    -webkit-appearance: none;
13
-    border: none;
14
-    width: 100%;
15
-    color: $white;
16
-    border: none;
17
-    border-bottom: 1px solid lighten($white, 20);
18
-    background-color: transparent;
19
-    box-shadow: none;
20
-    border-radius: 0;
21
-    background-clip: padding-box;
22
-    @include font-size(32);
23
-    &:focus {
24
-      box-shadow: none;
25
-      outline: none;
26
-    }
27
-  }
28
-  &.active {
29
-    opacity: 1;
30
-    top: 0;
31
-    left: 0;
32
-  }
33
-  &.hidden {
34
-    display: none;
35
-  }
36
-  ::-webkit-input-placeholder {
37
-    @include font-size(32);
38
-  }
39
-  .search-field::-webkit-search-decoration,
40
-  .search-field::-webkit-search-cancel-button,
41
-  .search-field::-webkit-search-results-button,
42
-  .search-field::-webkit-search-results-decoration {
43
-    display: none;
44
-  }
45
-  .post-list {
46
-    position: absolute;
47
-    width: 100%;
48
-    h4, li, p, a {
49
-      color: $white;
50
-    }
51
-    li {
52
-      border-bottom: 1px solid lighten($white,20);
53
-    }
54
-  }
55
-}
56
-// search button in navigation
57
-.no-js .dosearch {
58
-  display: none;
59
-}
60
-.dosearch {
61
-  span {
62
-    display: block;
63
-    margin-bottom: 10px;
64
-    padding: 12px 20px;
65
-    @include media($medium) {
66
-      margin-bottom: 0;
67
-      padding: 6px 10px;
68
-    }
69
-    cursor: pointer;
70
-    @include rounded(4px);
71
-    background-color: transparent;
72
-    color: $white;
73
-    &:hover {
74
-    @include box-shadow($shadow: inset 0 0 1px $white);
75
-      background-color: lighten($black, 10);
76
-    }
77
-  }
78
-}

+ 1
- 0
articles/index.md View File

@@ -2,6 +2,7 @@
2 2
 layout: page
3 3
 title: Sample Articles
4 4
 excerpt: "An archive of articles sorted by date."
5
+search_omit: true
5 6
 ---
6 7
 
7 8
 <ul class="post-list">

+ 0
- 1
assets/css/main.scss View File

@@ -26,4 +26,3 @@ sitemap: false
26 26
 @import "layout";
27 27
 @import "vendor/font-awesome/font-awesome";
28 28
 @import "vendor/magnific-popup/magnific-popup";
29
-@import "simple-search";

+ 200
- 0
assets/js/plugins/search.js View File

@@ -0,0 +1,200 @@
1
+/**
2
+ * A simple JSON search
3
+ * Requires jQuery (v 1.7+)
4
+ *
5
+ * @author  Mat Hayward - Erskine Design
6
+ * @version  0.1
7
+ */
8
+
9
+
10
+ /* ==========================================================================
11
+    Initialisation
12
+    ========================================================================== */
13
+
14
+var q, jsonFeedUrl = "/search.json",
15
+    $searchForm = $("[data-search-form]"),
16
+    $searchInput = $("[data-search-input]"),
17
+    $resultTemplate = $("#search-result"),
18
+    $resultsPlaceholder = $("[data-search-results]"),
19
+    $foundContainer = $("[data-search-found]"),
20
+    $foundTerm = $("[data-search-found-term]"),
21
+    $foundCount = $("[data-search-found-count]"),
22
+    allowEmpty = true,
23
+    showLoader = true,
24
+    loadingClass = "is--loading";
25
+
26
+
27
+$(document).ready( function() {
28
+    
29
+    // hide items found string
30
+    $foundContainer.hide();
31
+
32
+    // initiate search functionality
33
+    initSearch();
34
+});
35
+
36
+
37
+
38
+
39
+ /* ==========================================================================
40
+    Search functions
41
+    ========================================================================== */
42
+ 
43
+
44
+/**
45
+ * Initiate search functionality.
46
+ * Shows results based on querystring if present.
47
+ * Binds search function to form submission.
48
+ */
49
+function initSearch() {
50
+
51
+    // Get search results if q parameter is set in querystring
52
+    if (getParameterByName('q')) {
53
+        q = decodeURIComponent(getParameterByName('q'));
54
+        $searchInput.val(q);
55
+        execSearch(q);
56
+    }
57
+
58
+    // Get search results on submission of form
59
+    $(document).on("submit", $searchForm, function(e) {
60
+        e.preventDefault();
61
+        q = $searchInput.val();
62
+        execSearch(q);
63
+    });
64
+}
65
+
66
+
67
+/**
68
+ * Executes search
69
+ * @param {String} q 
70
+ * @return null
71
+ */
72
+function execSearch(q) {
73
+    if (q != '' || allowEmpty) {
74
+        if (showLoader) {
75
+            toggleLoadingClass();
76
+        }
77
+
78
+        getSearchResults(processData());
79
+    }
80
+}
81
+
82
+
83
+/**
84
+ * Toggles loading class on results and found string
85
+ * @return null
86
+ */
87
+function toggleLoadingClass() {
88
+    $resultsPlaceholder.toggleClass(loadingClass);
89
+    $foundContainer.toggleClass(loadingClass);
90
+}
91
+
92
+
93
+/**
94
+ * Get Search results from JSON
95
+ * @param {Function} callbackFunction 
96
+ * @return null
97
+ */
98
+function getSearchResults(callbackFunction) {
99
+    $.get(jsonFeedUrl, callbackFunction, 'json');
100
+}
101
+
102
+
103
+/**
104
+ * Process search result data
105
+ * @return null
106
+ */
107
+function processData() {
108
+    $results = [];
109
+    
110
+    return function(data) {
111
+        
112
+        var resultsCount = 0,
113
+            results = "";
114
+
115
+        $.each(data, function(index, item) {
116
+            // check if search term is in content or title 
117
+            if (item.excerpt.toLowerCase().indexOf(q.toLowerCase()) > -1 || item.title.toLowerCase().indexOf(q.toLowerCase()) > -1) {
118
+                var result = populateResultContent($resultTemplate.html(), item);
119
+                resultsCount++;
120
+                results += result;
121
+            }
122
+        });
123
+
124
+        if (showLoader) {
125
+            toggleLoadingClass();
126
+        }
127
+
128
+        populateResultsString(resultsCount);
129
+        showSearchResults(results);
130
+    }
131
+}
132
+
133
+
134
+/**
135
+ * Add search results to placeholder
136
+ * @param {String} results
137
+ * @return null
138
+ */
139
+function showSearchResults(results) {
140
+    // Add results HTML to placeholder
141
+    $resultsPlaceholder.html(results);
142
+}
143
+
144
+
145
+/**
146
+ * Add results content to item template
147
+ * @param {String} html 
148
+ * @param {object} item
149
+ * @return {String} Populated HTML
150
+ */
151
+function populateResultContent(html, item) {
152
+    html = injectContent(html, item.title, '##Title##');
153
+    html = injectContent(html, item.link, '##Url##');
154
+    html = injectContent(html, item.excerpt, '##Excerpt##');
155
+    html = injectContent(html, item.date, '##Date##');
156
+    return html;
157
+}
158
+
159
+
160
+/**
161
+ * Populates results string
162
+ * @param {String} count 
163
+ * @return null
164
+ */
165
+function populateResultsString(count) {
166
+    $foundTerm.text(q);
167
+    $foundCount.text(count);
168
+    $foundContainer.show();
169
+}
170
+
171
+
172
+
173
+
174
+ /* ==========================================================================
175
+    Helper functions
176
+    ========================================================================== */
177
+
178
+
179
+/**
180
+ * Gets query string parameter - taken from http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
181
+ * @param {String} name 
182
+ * @return {String} parameter value
183
+ */
184
+function getParameterByName(name) {
185
+    var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
186
+    return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
187
+}
188
+
189
+
190
+/**
191
+ * Injects content into template using placeholder
192
+ * @param {String} originalContent
193
+ * @param {String} injection
194
+ * @param {String} placeholder 
195
+ * @return {String} injected content
196
+ */
197
+function injectContent(originalContent, injection, placeholder) {
198
+    var regex = new RegExp(placeholder, 'g');
199
+    return originalContent.replace(regex, injection);
200
+}

+ 0
- 108
assets/js/plugins/simpleJekyllSearch.js View File

@@ -1,108 +0,0 @@
1
-/*global jQuery */
2
-/*!
3
-* Simple Jekyll Search
4
-* Christian Fei - https://github.com/christian-fei/Simple-Jekyll-Search *
5
-*
6
-*/
7
-
8
-(function($) {
9
-    $.fn.jekyllSearch = function(options) {
10
-        var settings = $.extend({
11
-            jsonFile            : '/search.json',
12
-            template            : '<a href="{url}" title="{desc}">{title}</a>',
13
-            searchResults       : '.results',
14
-            searchResultsTitle  : '<h4>Search results</h4>',
15
-            limit               : '10',
16
-            noResults           : '<p>Oh shucks<br/><small>Nothing found :(</small></p>'
17
-        }, options);
18
-
19
-        var jsonData = [],
20
-            origThis = this,
21
-            searchResults = $(settings.searchResults);
22
-
23
-        var matches = [];
24
-
25
-        if(settings.jsonFile.length && searchResults.length){
26
-            $.ajax({
27
-                type: "GET",
28
-                url: settings.jsonFile,
29
-                dataType: 'json',
30
-                success: function(data, textStatus, jqXHR) {
31
-                    jsonData = data;
32
-                    registerEvent();
33
-                },
34
-                error: function(x,y,z) {
35
-                    console.log("***ERROR in jekyllSearch.js***");
36
-                    console.log(x);
37
-                    console.log(y);
38
-                    console.log(z);
39
-                    // x.responseText should have what's wrong
40
-                }
41
-            });
42
-        }
43
-
44
-        function registerEvent(){
45
-            origThis.keyup(function(e){
46
-                if(e.which === 13){
47
-                    if(matches)
48
-                        window.location = matches[0].url;
49
-                        
50
-                    //follow the first link
51
-                    // if(searchResults.children().length)
52
-                }
53
-                if($(this).val().length){
54
-                    writeMatches( performSearch($(this).val()) );
55
-                }else{
56
-                    clearSearchResults();
57
-                }
58
-            });
59
-        }
60
-
61
-        function performSearch(str){
62
-            matches = [];
63
-
64
-            for (var i = 0; i < jsonData.length; i++) {
65
-                var obj = jsonData[i];
66
-                for (key in obj) {
67
-                    if(obj.hasOwnProperty(key)){
68
-                        if (obj[key] instanceof Array){
69
-                            var seen = false;
70
-                            for (var j = 0; j < obj[key].length; j++){
71
-                                if(obj[key][j].toLowerCase().indexOf(str.toLowerCase()) >= 0){
72
-                                    matches.push(obj);
73
-                                    break;
74
-                                }
75
-                            }
76
-                        }else if (obj[key].toLowerCase().indexOf(str.toLowerCase()) >= 0){
77
-                            matches.push(obj);
78
-                            break;
79
-                        }
80
-                    }
81
-                }
82
-            }
83
-            return matches;
84
-        }
85
-
86
-        function writeMatches(m){
87
-            clearSearchResults();
88
-
89
-            searchResults.append( $(settings.searchResultsTitle) );
90
-
91
-            if(m && m.length){
92
-                for (var i = 0; i < m.length && i < settings.limit; i++) {
93
-                    var obj = m[i];
94
-                    output = settings.template;
95
-                    output = output.replace(/\{(.*?)\}/g, function(match, property) {
96
-                        return obj[property];
97
-                    });
98
-                    searchResults.append($(output));
99
-                }
100
-            }else{
101
-                searchResults.append( settings.noResults );
102
-            }
103
-        }
104
-        function clearSearchResults(){
105
-            searchResults.children().remove();
106
-        }
107
-    }
108
-}(jQuery));

+ 2
- 2
assets/js/scripts.min.js
File diff suppressed because it is too large
View File


+ 1
- 0
blog/index.md View File

@@ -2,6 +2,7 @@
2 2
 layout: page
3 3
 title: Blog
4 4
 excerpt: "An archive of blog posts sorted by date."
5
+search_omit: true
5 6
 ---
6 7
 
7 8
 <ul class="post-list">

+ 1
- 0
index.html View File

@@ -2,6 +2,7 @@
2 2
 layout: page
3 3
 title: Latest Posts
4 4
 excerpt: "A simple and clean responsive Jekyll theme for words and photos."
5
+search_omit: true
5 6
 ---
6 7
 
7 8
 <ul class="post-list">

+ 20
- 10
search.json View File

@@ -1,15 +1,25 @@
1 1
 ---
2 2
 sitemap: false
3 3
 ---
4
+
4 5
 [
5
-	{% for post in site.posts %}
6
-		{
7
-		  "title"      : "{{ post.title | escape }}",
8
-		  "category"   : "{{ post.category }}",
9
-      "tags"       : "{{ post.tags | array_to_sentence_string }}",
10
-		  "url"        : "{{ site.url }}{{ post.url }}",
11
-		  "date"       : "{{ post.date }}",
12
-		  "shortdate"  : "{{ post.date | date: '%B %d, %Y' }}"
13
-		} {% unless forloop.last %},{% endunless %}
14
-	{% endfor %}
6
+{% for post in site.posts %}
7
+  {% if post.title != null and post.title != empty and post.search_omit != true %}
8
+    {% if forloop.index > 1 %},{% endif %}{
9
+      "title"			: {{ post.title | jsonify }},
10
+      "link"			: "{{ site.url }}{{ post.url }}",
11
+      "excerpt"		: "{{ post.excerpt }}"
12
+    }
13
+  {% endif %}
14
+{% endfor %}
15
+
16
+{% for page in site.pages %}
17
+  {% if page.layout != 'none' and page.layout != 'none' and page.title != null and page.title != empty and page.search_omit != true %}
18
+    {% if forloop.index > 1 %},{% endif %}{
19
+      "title"			: {{ page.title | jsonify }},
20
+      "link"			: "{{ site.url }}{{ page.url | replace: 'index.html', '' }}",
21
+      "excerpt"		: "{{ page.excerpt }}"
22
+    }
23
+  {%endif%}
24
+{% endfor %}
15 25
 ]

+ 32
- 0
search/index.md View File

@@ -0,0 +1,32 @@
1
+---
2
+layout: page
3
+title: "Search"
4
+date: 
5
+modified:
6
+excerpt:
7
+image:
8
+  feature:
9
+search_omit: true
10
+sitemap: false
11
+---
12
+  
13
+<!-- Search form -->
14
+<form method="get" action="{{ site.url }}/search/" data-search-form class="simple-search">
15
+  <label for="q">Search {{ site.title }} for:</label>
16
+  <input type="search" name="q" id="q" placeholder="What are you looking for?" data-search-input id="goog-wm-qt" />
17
+  <input type="submit" value="Search" id="goog-wm-sb" />
18
+</form>
19
+
20
+<!-- Search results placeholder -->
21
+<h6 data-search-found>
22
+  <span data-search-found-count></span> result(s) found for &ldquo;<span data-search-found-term></span>&rdquo;.
23
+</h6>
24
+<ul class="post-list" data-search-results></ul>
25
+
26
+<!-- Search result template -->
27
+<script type="text/x-template" id="search-result">
28
+  <li>
29
+  <article>
30
+    <a href="##Url##">##Title## <span class="excerpt">##Excerpt##</span></a>
31
+  </article></li>
32
+</script>

+ 1
- 0
tags/index.md View File

@@ -2,6 +2,7 @@
2 2
 layout: page
3 3
 title: Tag Index
4 4
 excerpt: "An archive of posts sorted by tag."
5
+search_omit: true
5 6
 ---
6 7
 
7 8
 {% capture site_tags %}{% for tag in site.tags %}{{ tag | first }}{% unless forloop.last %},{% endunless %}{% endfor %}{% endcapture %}

+ 3
- 6
theme-setup/index.md View File

@@ -323,14 +323,11 @@ Here's an example of a tweet with Twitter Cards enabled.
323 323
 
324 324
 ---
325 325
 
326
-## Simple Search
326
+## Jekyll search
327 327
 
328
-Adding `search: true` to your `_config.yml` enables search using Christian Fei's [Simple Jekyll jQuery plugin](https://github.com/christian-fei/Simple-Jekyll-Search). Clicking the search link in the navigation bar will overlay a Search box that searches on post titles using an auto generated JSON file.
328
+This is a very basic attempt at [indexing a Jekyll site](https://github.com/mathaywarduk/jekyll-search) and returning search results with JSON --- Google this is not.
329 329
 
330
-<figure>
331
-  <img src="{{ site.url }}/images/simple-search-screenshot.jpg" alt="search screenshot">
332
-  <figcaption>Search your site by post title</figcaption>
333
-</figure>
330
+To exclude posts/pages from search results add `search_omit: true` to their YAML Front Matter.
334 331
 
335 332
 ---
336 333
 

Loading…
Cancel
Save