-
-
Save frontendecoder/319c53080567b43eae0d7270b0b6fbbf to your computer and use it in GitHub Desktop.
Github API tech finder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
// Usage | |
// Create root HTML tag: <div id="app"></div> | |
// Create widget instance: var app = new GridGitHubJS('app'); | |
// or Create widget with search params (keyword, technology): var app = new GridGitHubJS('app', 'map', 'javascript'); | |
class GridGitHubJS { | |
constructor(rootElId, keyword='', tech='') { | |
// Private data | |
this.data = {}; | |
this.curPageNum = 1; | |
this.itemsPerGage = 30; | |
this.rowCount = 0; | |
this.searchKeyword = keyword; | |
this.searchTech = tech; | |
this.apiUrl = 'https://api.github.com/search/repositories'; | |
// https://api.github.com/search/repositories?q=map+language:javascript&sort=stars&order=desc | |
const template = ` | |
<div class="gridsterContainer"> | |
<div class="searchBox"> | |
<input type="text" id="searchWordGrst" value="${ this.searchKeyword }" placeholder="Keyword"/ > | |
<input type="text" id="searchTechGrst" value="${ this.searchTech }" placeholder="Technology" /> | |
<button id="searchBtnGrst">Search</button> | |
</div> | |
<div class="stats"> | |
<div class="total">Total items: <span id="rowCount"></span></div> | |
<div class="pager"> | |
<button id="prevPageBtn">Prev</button> | |
<span> | |
<span id="curPageNum"></span>/<span id="maxPageNum"></span> | |
</span> | |
<button id="nextPageBtn">Next</button> | |
</div> | |
</div> | |
<table class="gridster"> | |
<thead> | |
<tr> | |
<th>Index</th> | |
<th>Name</th> | |
<th>Owner</th> | |
<th>Url</th> | |
<th>Description</th> | |
<th>Stars</th> | |
<th>Detail</th> | |
</tr> | |
</thead> | |
<tbody id="gridsterTableBody"></tbody> | |
</table> | |
</div> | |
<div id="gridsterDetailPopup" class="gridsterDetailPopup"> | |
<div class="body"></div> | |
<div class="fog"></div> | |
</div> | |
`; | |
// Add template to dom | |
document.getElementById(rootElId).innerHTML = template; | |
// Init | |
this.searchWordEl = document.getElementById('searchWordGrst'); | |
this.searchTechEl = document.getElementById('searchTechGrst'); | |
this.tableBody = document.getElementById('gridsterTableBody'); | |
this.popupEl = document.getElementById('gridsterDetailPopup'); | |
this.popupBody = this.popupEl.querySelector('.body'); | |
this.rowCountEl = document.getElementById('rowCount'); | |
this.curPageNumEl = document.getElementById('curPageNum'); | |
this.maxPageNumEl = document.getElementById('maxPageNum'); | |
const self = this; | |
// Add search button click event listener | |
document.getElementById('searchBtnGrst').addEventListener('click', (e)=>{ | |
self.searchBtnClickHandler(self); | |
}, false); | |
// Add button click event listener to tablebody for show popup | |
this.tableBody.addEventListener('click', (e)=>{ | |
self.tableBodyClickHandler(e, self); | |
}, false); | |
// Add Close popup event listener | |
this.popupEl.querySelector('.fog').addEventListener('click', ()=>{ | |
self.hideDetailPopup(); | |
}, false); | |
// Pagination | |
document.getElementById('prevPageBtn').addEventListener('click', (e)=>{ | |
self.prevPage(self); | |
}, false); | |
document.getElementById('nextPageBtn').addEventListener('click', (e)=>{ | |
self.nextPage(self); | |
}, false); | |
// Launch. Fetch data | |
this.fetchData(self); | |
} | |
fillTable(self, data) { | |
let tableRowAll = '', | |
tableBodyTemplate = ''; | |
const itemsLen = data.items.length; | |
for (let i=0; i < itemsLen; i++) { | |
let item = data.items[i], | |
index = (self.curPageNum * self.itemsPerGage - self.itemsPerGage) + i + 1; | |
tableBodyTemplate = `<tr> | |
<td>${ index }</td> | |
<td>${ item.name }</td> | |
<td>${ item.owner.login }</td> | |
<td><a href="${ item.html_url }" target="_blank" title="${ item.html_url }">URL</a></td> | |
<td>${ item.description }</td> | |
<td>${ item.stargazers_count }</td> | |
<td><button class="showDetailPopup" data-idx="${i}">Detail</button></td> | |
</tr> | |
`; | |
tableRowAll += tableBodyTemplate; | |
} | |
this.tableBody.innerHTML = tableRowAll; | |
} | |
fetchData(self) { | |
let fullQuery = self.apiUrl | |
+'?q='+ self.searchKeyword | |
+'+language:'+ self.searchTech | |
+ '&sort=stars&order=desc' | |
+ '&page='+self.curPageNum | |
+ '&per_page='+self.itemsPerGage; | |
fetch(fullQuery) | |
.then((response) => { | |
if (!response.ok) { | |
throw Error(response.statusText); | |
} | |
return response.json(); | |
}).then((data) => { | |
self.data = data; | |
self.rowCount = data.total_count; | |
self.itemsPerGage = data.items.length; | |
self.fillTable(self, data); | |
self.updateStats(self); | |
}).catch((error) => { | |
console.log(error); | |
}); | |
} | |
searchBtnClickHandler(self) { | |
self.searchKeyword = self.searchWordEl.value; | |
self.searchTech = self.searchTechEl.value; | |
self.curPageNum = 1; | |
self.fetchData(self); | |
} | |
tableBodyClickHandler(e, self) { | |
if (e.target.className === 'showDetailPopup') { | |
const idx = e.target.getAttribute('data-idx'); | |
let itemData= JSON.stringify(self.data.items[idx], null, '<br>'); | |
self.popupBody.innerHTML = itemData; | |
// self.popupBody.textContent = itemData; | |
self.showDetailPopup(); | |
} | |
} | |
showDetailPopup() { | |
this.popupEl.classList.add('show'); | |
} | |
hideDetailPopup() { | |
this.popupEl.classList.remove('show'); | |
} | |
updateStats(self) { | |
self.rowCountEl.textContent = self.rowCount; | |
self.curPageNumEl.textContent = self.curPageNum; | |
self.maxPageNumEl.textContent = parseInt(self.rowCount / self.itemsPerGage); | |
} | |
prevPage(self) { | |
if (self.curPageNum <= 1) return false; | |
self.curPageNum--; | |
self.fetchData(self); | |
} | |
nextPage(self) { | |
if (self.curPageNum >= self.maxPageNum) return false; | |
self.curPageNum++; | |
self.fetchData(self); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment