JSFiddle - React, Tailwind, and code Playground
by Dogbert
HTML
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<div id="app" class="ui grid">
<div class="centered row">
<div class="eight wide column">
<div class="ui form" :class="{'error': !isValid}">
<div class="field">
<input type="text" v-model="input" @keyup="search" @keydown="search" id="input">
</div>
<div class="ui error message">
Please enter only alphabets, numbers, and hyphens.
</div>
</div>
</div>
</div>
<div class="sixteen wide column">
<table id="results" class="ui celled striped selectable table unstackable">
<tbody>
<tr v-for="(index, result) in results">
<td class="domain">{{result.domain}}</td>
<td class="availability">
<span v-for="tld in tlds" :class="{available: result.availability[tld] === true, taken: result.availability[tld] === false, unknown: result.availability[tld] === undefined}">
<template v-if="result.availability[tld] === undefined">...</template><template v-else>{{tld}}</template>
</span>
</td>
<td class="actions">
<button class="mini ui yellow button" :class="{basic: !result.isFavorite}" @click="result.toggleFavorite();">Favorite</button>
<button class="mini ui red button" @click="removeResult(index)">Remove</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
SCSS
body {
margin: 20px;
text-align: center;
}
#results .domain {
width: 100%;
}
#results .availability,
#results .actions {
white-space: nowrap;
}
#results .availability span {
margin: 0 10px;
}
#results .availability .available {
color: green;
}
#results .availability .taken {
color: red;
}
#results .ui.button {
padding: 8px 10px;
}
JavaScript
function Result(domain) {
var self = this;
this.domain = domain;
this.availability = {
com: undefined,
net: undefined,
org: undefined,
info: undefined
};
this.isFavorite = false;
this.toggleFavorite = function() {
this.isFavorite = !this.isFavorite;
}
check('com', 0.4, Math.random() * 4000);
check('net', 0.5, Math.random() * 5000);
check('org', 0.6, Math.random() * 6000);
check('info', 0.7, Math.random() * 7000);
function check(tld, probability, delay) {
setTimeout(function() {
self.availability[tld] = Math.random() < probability;
}, delay);
}
}
new Vue({
el: '#app',
data: {
input: "",
results: [],
cache: {},
tlds: ["com", "net", "org", "info"]
},
computed: {
isValid: function() {
return /^[a-zA-Z0-9-]*$/.test(this.input);
}
},
methods: {
search: function() {
if (!this.isValid) {
return;
}
var input = this.input;
if (!input || this.cache[input]) {
return;
}
this.cache[input] = true;
var result = new Result(input);
this.results.unshift(result);
},
removeResult: function(index) {
// var result = this.results[index];
// this.cache[result.domain] = false;
this.results.splice(index, 1);
}
},
})