# JS練習_Github搜尋器
透過串接製作一個[github REST API](https://docs.github.com/en/rest)搜尋器,輸入github用戶帳號或是repo名稱可以列表將使用者專案數、所屬公司列表追蹤人數列表出來,若是搜尋不到則會觸發告警提示。
## 成品畫面

## 功能
- 呈現使用者資訊(如:大頭照所屬公司專案數目何時加入....
- 若搜尋不到輸入資訊,出現告警提示
- 顯示使用者最新的repo在下方,可以透過點擊連結相關網頁
## HTML/CSS
主要透過bootStrap已設定好的樣式呈現。
## JS
### getUserData()
利用`ajax`串接API,確認`串接網址`/`資料型態`/`方式`/成功或失敗獲得我們想要的資訊,並在前面取得資料時要是載入錯誤,則會觸發error函式,最後呼叫函式顯示在頁面上。
- 成功:會取得GitHub用戶資訊並呼叫`showProfile()`將取得內容當做函式參數。
- 失敗:會呼叫`showAlert()`利用`alert alert-danger` 的 class 讓其顯示為紅色。
```js
function getUserData(){
$.ajax({
//github endpoint
url: `https://api.github.com/users/${userName}`,
method: 'GET',
dataType: 'json',
success: function(res) {
let obj = {};
obj.avatar_url = res.avatar_url !== null ? res.avatar_url : '';
obj.name = res.name !== null ? res.name : '';
obj.html_url = res.html_url !== null ? res.html_url : '';
obj.public_repos = res.public_repos !== null ? res.public_repos : '';
obj.public_gists = res.public_gists !== null ? res.public_gists : '';
obj.followers = res.followers !== null ? res.followers : '';
obj.following = res.following !== null ? res.following : '';
obj.company = res.company !== null ? res.company : '';
obj.blog = res.blog !== null ? res.blog : '';
obj.location = res.location !== null ? res.location : '';
obj.created_at = res.created_at.substr(0, 10) !== null ? res.created_at.substr(0, 10) : '';
obj.updated_at = res.updated_at.substr(0, 10) !== null ? res.updated_at.substr(0, 10) : '';
showProfile(obj);
},
error: function(res) {
data = res.responseJSON.message;
if (data === 'Not Found') {
showAlert(data, 'alert alert-danger');
}
}
});
```
### getRepoData()
同樣利用`ajax`串接API,確認連結位置,決定資料型態,取得資料,並在連結成功時,呼叫函式`showRepo`函式。
url裡的連結網址有設定`per_page=5`,讓展現搜尋資料時,只會出現五筆資料。
```.js
function getRepoData(){
$.ajax({
url:`https://api.github.com/users/${userName}/repos?per_page=5&sort=created: asc`,
method:'GET',
datatype:'json',
success: function(data){
getData = data;
showRepo(getData);
}
})
}
```
### showProfile()
在一開始`getUserData`函式中設定呼叫`showProfile()`函式,將得到的使用者資料寫入選取容器的html裡。
```.js
function showProfile(user){
$('#profile').html(
`<div class="card card-body border-0">
<div class="row">
<div class="col-md-3">
<img src="${user.avatar_url}" class="img-fluid rounded-circle mb-2">
<h5 class="mt-2 text-center">${user.name}</h5>
<a href="${user.html_url}" target="_blank" class = "btn btn-primary btn-block mb-4">View Profile</a>
</div>
<div class="col-md-9">
<div class="container mt-2 px-0">
<span class="badge badge-primary ml-5">Public Repos: ${user.public_repos}</span>
<span class="badge badge-secondary">Public Gists: ${user.public_gists}</span>
<span class="badge badge-success">Followers: ${user.followers}</span>
<span class="badge badge-info">Following: ${user.following}</span>
</div>
<ul class="list-group list-group-flush mt-2 ml-5">
<li class="list-group-item">Company: ${user.company}</li>
<li class="list-group-item">Website/Blog: ${user.blog}</li>
<li class="list-group-item">Location: ${user.location}</li>
<li class="list-group-item">Member Since: ${user.created_at}</li>
<li class="list-group-item">Currently Updated: ${user.updated_at}</li>
</ul>
</div>
</div>
</div>
<div class="col-md-12">
<h3 class="page-heading mb-3">Latest Repos</h3>
<div id="repos"></div>
</div>
`
)}
```
### showRepo()
把取得資料利用`forEach`方式加入至創建好的容器`repo`裡,並決定其html外觀樣式。
```.js
//show repo
function showRepo(repos){
repos.forEach(function(repo){
//把repodata東西加在getRepoData中創建的容器後
const repoData = $('<div class = "card card-body mb-2 border-0"></div>').appendTo('#repos');
let repoDes = repo.description !== null ? repo.description : '';
repoData.html(`
<div class="row shadow-sm p-3 bg-white rounded">
<div class="col-md-6">
<a href="${repo.html_url}" target="_blank">
<h3>${repo.name}</h3>
</a>
<p>${repoDes}</p>
</div>
<div class="col-md-6">
<span class="badge badge-warning m-1">Stars ${repo.stargazers_count}</span>
<span class="badge badge-success m-1">Watchers ${repo.watchers_count}</span>
<span class="badge badge-info m-1">Forks ${repo.forks_count}</span>
</div>
</div>
`)}
);
}
```
### showAlert()
當使用者輸入資訊在GitHub網站找不到時,會秀出紅色示警視窗,並經過設定時間五秒後示警視窗消失。
創立變數alertMessage,設定其元素、屬性及其內容,使用`insertBefore`在alertMessage==前==再加上bootstrap設定好的屬性,並將搜尋結果欄清空。
```.js
//showalert function
function showAlert(message, className){
const alertMessage = $('<div></div>').attr('class', className + ' text-center');
alertMessage.text(`User "${userName}" is ${message}`)
//insertBefore在現有的子節點前插入一個新的子節點
alertMessage.insertBefore($('.search.card.card-body.border-0'))
$('#profile').html('');
//setTimeout 2秒後把alertMessage移開
setTimeout(function(){
alertMessage.remove()
},5000)
}
```
### click event
透過在選取的`searchBtn`點擊後觸發函式,給定userName當作參數。
```.js
const searchBtn = $('.search-btn');
searchBtn.click(function(){
//指定searchUser 的val 給username
userName = searchUser.val();
getUserData(userName);
getRepoData(userName);
searchUser.val('');
})
```
###### tags: `javascript`