JavaScript 系列五:第7課

── 學會 AJAX 與 data attribute 的結合

by applelily

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript 系列五:第6課 ── 學會 AJAX 與各種 HTTP 請求方法</title>
    <link rel="stylesheet" href="./05_js_data-attribute.css">
</head>
<body>
    <div class="container">
        <button id="load_products_btn" class="btn">Load Products</button>
        <div class="msg">抱歉,請稍後重新嘗試</div>
    </div>

    <hr>

    <div class="container">
        <ul id="products_lists" class="products_lists"></ul>
    </div>

    <div class="modal_wrap">
        <div class="detail-modal" id="detail-modal">
            <div class="image_div">
                <img src="" alt="" class="image">
            </div>
            <div class="product_content">
                <h2 class="title"></h2>
                <span class="category"></span>
                <p class="description"></p>
                <span class="price"></span>
            </div>

            <button id="btn-close" class="btn-close">✕</button>
        </div>
    </div>
    
    <script src="./05_js_data-attribute.js"></script>
</body>
</html>

CSS

* {
    padding: 0;
    margin: 0;
    list-style: none;
}

body {
    box-sizing: border-box;
}

#load_products_btn {
    width: 120px;
    height: 80px;
    color: #ccc;
    background-color: rgb(8, 81, 81);
    font-size: 20px;
    padding: 10px;
    margin: 20px 30px;
}

#load_products_btn:hover
{
    color: rgb(8, 81, 81);
    background-color: rgb(156, 176, 20);
    cursor: pointer;
}

#products_lists li button:nth-child(3):hover {
    color: rgb(8, 81, 81);
    background-color: rgb(156, 176, 20);
    cursor: pointer;
}

#products_lists button:last-child:hover {
    color: #fff;
    background-color: #f00;
    cursor: pointer;
}

.msg {
    position: absolute;
    top: 20px;
    width: 200px;
    height: 30px;
    display: none;
    background-color: #EDCAC7;
    color: #902105;
    padding: 10px;
    margin: 20px 0;
    border-radius: 5px;
    animation: my_message 5s;
    opacity: 0;
}

@keyframes my_message {
    from {
        left: 200px;
        opacity: 100;
    }
    to {
        left: 300px;
        opacity: 0;
    }
}

#products_lists {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    padding: 20px;
}

#products_lists li {
    width: 200px;
    margin: 10px;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
    background-color: #f9f9f9;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
}

#products_lists span {
    text-align: center;
    color: rgb(100, 100, 100);
    margin-bottom: 10px;
}

#products_lists button {
    width: 100px;
    padding: 5px;
    margin-top: 10px;
    color: rgb(238, 245, 245);
    background-color: rgb(69, 69, 68);
    border-radius: 5px;
}

#products_lists img {
    width: 100px;
    height: 100px;
    object-fit: contain;
    margin-bottom: 10px;
}

.modal_wrap {
    display: none;
    position: fixed;
    z-index: 1;
    padding-top: 100px;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
   ...

JavaScript

const load_products_btn = document.querySelector('#load_products_btn');

// 延遲5秒鐘
const set_display_timeout = (in_elem) => {
    in_elem.style.display = "block";
    setTimeout(() => {
        in_elem.style.display = "none";
    }, 5000);
};

const do_delete = (product_id, in_elem, msg) => {
    fetch('https://fakestoreapi.com/products/' + product_id, {
        method: "DELETE"
    })
    .then(res => res.json())
    .then(json => {
        if (json === null) {
            msg.style.display = 'block';
            set_display_timeout(msg);
        } else {
            in_elem.remove();
        }
    })
    .catch(error => {
        msg.style.display = 'block';
        set_display_timeout(msg);
        console.error('Error delete products:', error);
    });
};

const loadproducts = () => {
    const products_lists = document.querySelector('#products_lists');
    products_lists.innerHTML = ''; // 清除列表之前的產品
    const msg = document.querySelector('.msg');
    msg.style.display = 'none';

    fetch('https://fakestoreapi.com/products')
        .then(res => res.json())
        .then(json => {
            json.forEach(product => {
                const li = document.createElement('li');
                const img = document.createElement('img');
                const span = document.createElement('span');
                const detail_btn = document.createElement('button');
                const del_btn = document.createElement('button');
                const title = document.querySelector('.title');
                const category = document.querySelector('.category');
                const description = document.querySelector('.description');
                const price = document.querySelector('.price');
                const image =  document.querySelector('.image');
                const modal_wrap = document.querySelector('.modal_wrap');

                img.src = product.image;
                img.alt = product.title;
                li.appendChild(img);

           ...