---
# System prepended metadata

title: JS練習_Github搜尋器
tags: [javascript]

---

# JS練習_Github搜尋器

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

## 成品畫面
![](https://i.imgur.com/zXYkGr5.png)

## 功能
- 呈現使用者資訊(如:大頭照所屬公司專案數目何時加入....
- 若搜尋不到輸入資訊，出現告警提示
- 顯示使用者最新的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`