Search widget
Uses Vue.js for logic and Google Spreadsheets for the data.
by cambraca
HTML
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js "></script>
<section id="search-widget" v-cloak>
<input type="search" v-model="search" placeholder="Search for countries or regions" debounce="300">
<ul>
<li class="region" v-for="(region, countries) in results">
<strong>{{ region }}</strong>
<ul>
<li class="country" v-for="(country, population) in countries">
{{ country }} <span class="population">{{ population | numberFormat }}</span>
</li>
</ul>
</li>
</ul>
</section>
SCSS
[v-cloak] {
display: none;
}
#search-widget {
max-width: 400px;
input[type=search] {
border-radius: 15px;
line-height: 20px;
padding: 5px;
border: 1px solid gray;
width: 100%;
&:focus {
outline: none;
}
}
.region {
list-style: none;
margin-top: 15px;
ul {
margin-top: 5px;
}
}
.population {
float: right;
font-style: italic;
}
}
JavaScript
var url = 'https://spreadsheets.google.com/feeds/list/16_BOjZ3i51ZaTco_ZICBskfzlmHAWKm4MCUOJnnUIzM/1/public/values?alt=json';
function restructure(res, row) {
if (typeof res[row.gsx$region.$t] === 'undefined')
res[row.gsx$region.$t] = {};
res[row.gsx$region.$t][row.gsx$country.$t] = parseInt(row.gsx$population.$t);
return res;
}
$.getJSON(url, json => dataLoaded(json.feed.entry.reduce(restructure, {})));
function dataLoaded(data) {
Vue.filter('numberFormat', function (value) {
return Number(value).toLocaleString();
});
new Vue({
el: '#search-widget',
data: {
search: '',
populations: data
},
computed: {
results: function() {
var query = this.search.trim().toLowerCase();
var result = {};
if (query.length < 3)
return result;
for (var region in this.populations) {
if (this.matches(query, region)) {
result[region] = this.populations[region];
} else {
var regionIncluded = false;
for (var country in this.populations[region]) {
if (this.matches(query, country)) {
if (!regionIncluded) {
result[region] = {};
regionIncluded = true;
}
result[region][country] = this.populations[region][country];
}
}
}
}
return result;
}
},
methods: {
matches: function(query, string) {
return string.toLowerCase().indexOf(query) !== -1;
}
}
});
}