這個是第二版, 這次主要會變成帶實作(好像後面的課程就會取消這一塊了)

  • [1] 問卷
  • [1] Windows 下的編輯工具 5
  • [1] HTML 影片 21mins + 練習
  • [1] CSS 影片 40mins + 練習
  • [1] BREAK
  • [1] HTML & CSS 影片 15 mins + 練習
  • [1] 3cschool/browser support HTML CSS
  • [1] Github Page 使用 影片
  • [1] 練習1: 將自我介紹的網頁建立到 Github Pages
  • [1] 練習2: 加上img
  • [1] BREAK
  • [1] HTML/CSS ref
  • [1] 簡述前端 Roadmap

  • [2] colab 使用

  • [2] HTTP 介紹 ref
  • [2] JSON 介紹 ref
  • [2] 建立 API service
  • [2] BREAK
  • [2] FastAPI 的介面使用
  • [2] curl的安裝與使用 ref
  • [2] POST/GET/PUT/DELETE sample
  • [2] BREAK
  • [2] 習作題目
  • [2] BREAK
  • [2] 簡述後端 Roadmap

  • [2] Question: colab file access, google drive access 是否已經學過?

  • [3] Intro 影片 5mins + 練習

  • [3] Variable/Operator 影片 28 mins + 練習 相等比較 運算子
  • [3] ~~Chrome dev tool 的使用~~
  • [3] Flow control 影片 15 mins + 練習
  • [3] BREAK
  • [3] Looping 影片 15 mins + 練習
  • [3] Function 影片1 影片2 (20+14) + 練習 Scope
  • [3] HTML DOM 影片 20 mins + 練習題目:
  • [3] HTML Form 影片 30mins
  • [3] JS 練習 身分證字號檢測, 答案
  • [3] HTML Event handling 影片1 17mins 影片2 11 mins ref
  • [3] BREAK
  • [3] XMLHTTPRequest 的使用 + JS的同步與非同步簡介 + python requests 的使用. XHR使用. 跟隨實做 CORS參考資料

  • [4] [練習] 利用fastapi 取出 腳踏車道, 來源 讓前端網頁可以讀取, 然後列出相關資訊(加上 Travellinginfo, Remarks, Bike_length)

  • [4] BREAK
  • [4] leaflet js lib 的使用
  • [4] [練習] 建立web page 提供車道查詢, 並顯示在地圖上
  • [4] [練習] 取出Route_XY作為路線繪製
  • [4] BREAK
  • [4] BootStrap 的使用
  • [4] BREAK
  • [4] telegram bot的建立以及使用
  • [4] [練習] 利用 bootstrap 建立交易顧問 web page, 提供註冊查詢服務
  • [4] [練習] 建立API service 註冊, 連線 telegram bot 提供查詢服務

參考資料


Smaple Code

建立 API service

利用 colab 建立 fastapi平台

code:

!pip install fastapi nest-asyncio pyngrok uvicorn python-multipart

from fastapi import FastAPI, UploadFile, File, Request
from fastapi.middleware.cors import CORSMiddleware
from datetime import datetime
from typing import Optional
from pydantic import BaseModel

local_customer = []

class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None

class Customer(BaseModel):
    name: str
    phone_number: Optional[str] = None
    email: Optional[str] = None
    bitcoin_asset: Optional[float] = 0

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=['*'],
    allow_credentials=True,
    allow_methods=['*'],
    allow_headers=['*'],
)

@app.get("/customers/{customer_name}")
async def get_customer(customer_name):
    if not customer_name:
        return local_customer
    for c in local_customer:
        if c.name == customer_name:
            return c
    return {'status': 'no data'}

@app.post("/customers/")
async def add_customer(customer: Customer):
    is_exist = False
    for c in local_customer:
        if c.name == customer.name:
            is_exist = True
    if not is_exist:
        local_customer.append(customer)

    return {'status': 'success'}

@app.put("/customers/")
async def update_customer(customer: Customer):
    for c in local_customer:
        if c.name == customer.name:
            c.phone_number = customer.phone_number
            c.email = customer.email
            c.bitcoin_asset = customer.bitcoin_asset
            return c
    return {'status': '不存在'}

@app.delete("/customers/")
async def delete_customer(customer: Customer):
    for c in local_customer:
        if c.name == customer.name:
            local_customer.remove(c)
            return {'status': '已刪除'}        
    return {'status': '不存在'}

@app.get('/test/{id}/{birthday}/{address})
async def root(id, birthday, address):
    print(f'id: {id}, birthday: {birthday}, address: {address}')
    return {'hello': 'world', 'now_time': datetime.now().strftime("%m/%d/%Y, %H:%M:%S")}

@app.post("/insert_data/{client_name}")
async def insert_data(request: Request, client_name):
    count = 0
    for header in request.headers:
        print('H [{}] {}'.format(header, request.headers[header]))
        count = count + 1
    print(await request.json())
    return {'header_length': count}

@app.post("/items/")
async def create_item(item: Item):
    print('item: {}'.format(item))
    return item

@app.put("/items/")
async def update_item(item: Item):
    print('UPDATE {}'.format(item))
    return {'status': 'updated'}


@app.post("/upload_sample")
async def upload_csshtml(htmlfile: UploadFile=File(...)):
    try:
        print(htmlfile.filename)
        with open('./{}'.format(htmlfile.filename), 'wb+') as f:
            f.write(htmlfile.file.read())
        return {'status': 'success'}
    except BaseException as ex:
        import traceback
        r = {'error': '{}'.format(ex), 'error_detail': '{}'.format(traceback.format_exc())}
        return json.dumps(r)

import nest_asyncio
from pyngrok import ngrok
import uvicorn

ngrok_tunnel = ngrok.connect(8000)
print('Public URL:', ngrok_tunnel.public_url)
nest_asyncio.apply()
uvicorn.run(app, port=8000)

程式碼的解說

介紹Restful API 的特別的地方 ref

POST/GET/PUT/DELETE sample

利用 fastapi 建立 HTTP相關的服務

DEMO 題目: 註冊數位貨幣網站用戶 (用戶註冊, 用戶資料查詢, 用戶資料更改, 用戶取消)


進階練習1: 條列出 外送餐點網站所需要的 API (單客戶 單外送 多餐廳)

進階練習2: 建立相對應的API

ref

BootStrap 的使用

ref

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
    <link rel="stylesheet" href="bs5.css">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
    integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
    crossorigin=""/>
    <!-- Make sure you put this AFTER Leaflet's CSS -->
    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
    <title>數位貨幣推薦系統</title>
</head>
<body>
    <!-- Navbar -->
    <navbar class="navbar navbar-expand-lg bg-dark navbar-dark py-3 fixed-top">
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navmenu">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="container">
            <a href="#" class="navbar-brand">數位貨幣推薦系統</a>
            <div class="collapse navbar-collapse" id="navmenu">
                <ul class="navbar-nav">
                    <li class="nav-item">
                        <a href="#about" class="nav-link">有關推薦系統</a>
                    </li>
                    <li class="nav-item">
                        <a href="#service" class="nav-link">服務項目</a>
                    </li>
                    <li class="nav-item">
                        <a href="#success-case" class="nav-link">成功案例</a>
                    </li>
                </ul>
            </div>
        </div>
    </navbar>

    <!-- Showcase -->
    <section class="bg-dark text-light p-5 p-lg-3 pt-lg-5 text-center text-sm-start">
        <dev class="container">
            <div class="d-sm-flex align-items-center justify-content-between">
                <div>
                    <h1>客製<span class="text-warning">推薦系統</span>增加你的財富</h1>
                    <p class="lead my-4">
                        推薦系統是一種信息過濾系統,用於預測用戶對物品的「評分」或「偏好」。 推薦系統近年來非常流行,應用於各行各業。 
                    </p>
                    <button class="btn btn-primary btn-lg" data-bs-toggle="modal" data-bs-target="#enroll">開始你的財富之旅</button>
                </div>
                <img class="img-fluid w-50 d-none d-sm-block" src="/img/sample.jpeg" alt="">
            </div>
        </dev>
    </section>

    <!-- About -->
    <section class="bg-primary text-light p-5">
        <div class="container">
            <div class="d-md-flex justify-content-between align-items-center">
                <h3 class="mb-3 mb-md-0">輸入Email以獲取最新訊息</h3>
                <div class="input-group news-input">
                    <input type="text" class="form-control" placeholder="輸入Email">
                    <button class="btn btn-dark btn-lg" type="button">輸入</button>
                  </div>
            </div>
        </div>
    </section>

    <!-- Box -->
    <section class="p-5">
        <div class="container">
            <div class="row text-center g-4">
                <div class="col-md">
                    <div class="card bg-dark text-light">
                        <div class="card-body text-center">
                            <div class="h1 mb-3"><i class="bi bi-laptop"></i></div>
                            <h3 class="card-title mb-3">系統</h3>
                            <p class="card-text">
                                Lorem ipsum, dolor sit amet consectetur adipisicing elit. Asperiores mollitia adipisci minus suscipit ut delectus harum porro odit dolore labore, fuga enim ex necessitatibus facilis? Facilis reprehenderit omnis itaque assumenda.
                            </p>
                            <a href="" class="btn btn-primary">知道更多</a>
                        </div>
                    </div>
                </div>
                <div class="col-md">
                    <div class="card bg-secondary text-light">
                        <div class="card-body text-center">
                            <div class="h1 mb-3"><i class="bi bi-person-square"></i></div>
                            <h3 class="card-title mb-3">智慧分享</h3>
                            <p class="card-text">
                                Lorem ipsum, dolor sit amet consectetur adipisicing elit. Asperiores mollitia adipisci minus suscipit ut delectus harum porro odit dolore labore, fuga enim ex necessitatibus facilis? Facilis reprehenderit omnis itaque assumenda.
                            </p>
                            <a href="" class="btn btn-dark">知道更多</a>
                        </div>
                    </div>
                </div>
                <div class="col-md">
                    <div class="card bg-dark text-light">
                        <div class="card-body text-center">
                            <div class="h1 mb-3"><i class="bi bi-people"></i></div>
                            <h3 class="card-title mb-3">展望未來</h3>
                            <p class="card-text">
                                Lorem ipsum, dolor sit amet consectetur adipisicing elit. Asperiores mollitia adipisci minus suscipit ut delectus harum porro odit dolore labore, fuga enim ex necessitatibus facilis? Facilis reprehenderit omnis itaque assumenda.
                            </p>
                            <a href="" class="btn btn-primary">知道更多</a>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- 簡述 -->
    <section class="p-5" id="about">
        <div class="container">
            <div class="row align-items-center justify-content-between">
                <div class="col-md">
                    <img src="/img/process1.png" class="img-fluid" alt="">
                </div>
                <div class="col-md p-5">
                    <h2>推薦系統的作用</h2>
                    <p class="lead">
                        推薦系統是一種有效代替搜索算法的方式,因為他們幫助用戶找到一些他們自己沒有辦法找到的物品。有趣的是,推薦系統在實現之時通常使用搜尋引擎對非傳統數據索引。
                    </p>
                    <p>
                        Montaner 從智能代理角度給出了有關推薦系統的第一篇綜述文章[13]Adomavicius給出了一種新的有關推薦系統的全景[14]Herlock提供了有關評價推薦系統的技術綜述[15]Beel等討論了離線評價中的問題[16]Beel等同事也提供了現有有關推薦系統的研究文獻與現存挑戰[17][18][19]
                    </p>
                    <a href="" class="btn btn-light mt-3">
                        <i class="bi bi-chevron-right"></i>知道更多
                    </a>
                </div>
            </div>
        </div>
    </section>

    <!-- 簡述2 -->
    <section class="p-5 bg-dark text-light" id="about-detail">
        <div class="container">
            <div class="row align-items-center justify-content-between">
                <div class="col-md p-5">
                    <h2>推薦系統的威力</h2>
                    <p class="lead">
                        推薦系統是一種有效代替搜索算法的方式,因為他們幫助用戶找到一些他們自己沒有辦法找到的物品。有趣的是,推薦系統在實現之時通常使用搜尋引擎對非傳統數據索引。
                    </p>
                    <p>
                        Montaner 從智能代理角度給出了有關推薦系統的第一篇綜述文章[13]Adomavicius給出了一種新的有關推薦系統的全景[14]Herlock提供了有關評價推薦系統的技術綜述[15]Beel等討論了離線評價中的問題[16]Beel等同事也提供了現有有關推薦系統的研究文獻與現存挑戰[17][18][19]
                    </p>
                    <a href="" class="btn btn-light mt-3">
                        <i class="bi bi-chevron-right"></i>知道更多
                    </a>
                </div>
                <div class="col-md">
                    <img src="/img/rs.png" class="img-fluid" alt="">
                </div>
            </div>
        </div>
    </section>

    <!-- 問與答 -->
    <section class="p-5" id="questions">
        <div class="container">
            <h2 class="text-center mb-4">問與答</h2>
            <div class="accordion accordion-flush" id="questions">
                <!-- item-1 -->
                <div class="accordion-item">
                    <h2 class="accordion-header">
                        <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#question-one">
                            推薦系統的來源
                        </button>
                    </h2>
                    <div id="question-one" class="accordion-collapse collapse" aria-labelledby="flush-headingOne" data-bs-parent="#questions">
                        <div class="accordion-body">Placeholder content for this accordion, which is intended to demonstrate the <code>.accordion-flush</code> class. This is the first item's accordion body.</div>
                    </div>
                </div>
                <!-- item-2 -->
                <div class="accordion-item">
                    <h2 class="accordion-header">
                        <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#question-two">
                            推薦系統的運作
                        </button>
                    </h2>
                    <div id="question-two" class="accordion-collapse collapse" aria-labelledby="flush-headingOne" data-bs-parent="#questions">
                        <div class="accordion-body">Placeholder content for this accordion, which is intended to demonstrate the <code>.accordion-flush</code> class. This is the first item's accordion body.</div>
                    </div>
                </div>
                <!-- item-3 -->
                <div class="accordion-item">
                    <h2 class="accordion-header">
                        <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#question-three">
                            推薦系統的成本
                        </button>
                    </h2>
                    <div id="question-three" class="accordion-collapse collapse" aria-labelledby="flush-headingOne" data-bs-parent="#questions">
                        <div class="accordion-body">Placeholder content for this accordion, which is intended to demonstrate the <code>.accordion-flush</code> class. This is the first item's accordion body.</div>
                    </div>
                </div>
                <!-- item-4 -->
                <div class="accordion-item">
                    <h2 class="accordion-header">
                        <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#question-four">
                            推薦系統的交互作用
                        </button>
                    </h2>
                    <div id="question-four" class="accordion-collapse collapse" aria-labelledby="flush-headingOne" data-bs-parent="#questions">
                        <div class="accordion-body">Placeholder content for this accordion, which is intended to demonstrate the <code>.accordion-flush</code> class. This is the first item's accordion body.</div>
                    </div>
                </div>
                <!-- item-4 -->
                <div class="accordion-item">
                    <h2 class="accordion-header">
                        <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#question-five">
                            成功案例
                        </button>
                    </h2>
                    <div id="question-five" class="accordion-collapse collapse" aria-labelledby="flush-headingOne" data-bs-parent="#questions">
                        <div class="accordion-body">Placeholder content for this accordion, which is intended to demonstrate the <code>.accordion-flush</code> class. This is the first item's accordion body.</div>
                    </div>
                </div>
              </div>
        </div> 
    </section>
    <!-- 成功案例 -->
    <section id="successcases" class="p-5 bg-primary">
        <div class="container">
            <h2 class="text-center text-white">成功案例</h2>
            <p class="lead text-center text-white mb-5">
                沒有良好的行銷策略,就像無頭蒼蠅一樣開始做宣傳,可能讓消費者對公司跟產品的形象搞得一頭霧水,對公司長期來說也不是良好效應。
            </p>
            <div class="row g-4">
                <div class="col-md-6 col-lg-3">
                    <div class="card bg-light">
                        <div class="card-body text-center">
                            <img src="https://randomuser.me/api/portraits/men/22.jpg" class="rounded-circle mb-3" alt="">
                            <h3 class="card-title mb-3">賺真大公司</h3>
                            <p class="card-text">由於勞工意識抬頭,這種吃力不討好的工作其實不員工不好找,加上基本薪資持續調漲,超商經營的成本越來越高,日前跟傳出日本7-ELEVEN 母公司打算關閉近...</p>
                            <a href=""><i class="bi bi-facebook text-dark mx-1"></i></a>
                            <a href=""><i class="bi bi-twitter text-dark mx-1"></i></a>
                            <a href=""><i class="bi bi-linkedin text-dark mx-1"></i></a>
                            <a href=""><i class="bi bi-instagram text-dark mx-1"></i></a>
                        </div>
                    </div>
                </div>
                <div class="col-md-6 col-lg-3">
                    <div class="card bg-light">
                        <div class="card-body text-center">
                            <img src="https://randomuser.me/api/portraits/women/66.jpg" class="rounded-circle mb-3" alt="">
                            <h3 class="card-title mb-3">真真</h3>
                            <p class="card-text">由於勞工意識抬頭,這種吃力不討好的工作其實不員工不好找,加上基本薪資持續調漲,超商經營的成本越來越高,日前跟傳出日本7-ELEVEN 母公司打算關閉近...</p>
                            <a href=""><i class="bi bi-facebook text-dark mx-1"></i></a>
                            <a href=""><i class="bi bi-twitter text-dark mx-1"></i></a>
                            <a href=""><i class="bi bi-linkedin text-dark mx-1"></i></a>
                            <a href=""><i class="bi bi-instagram text-dark mx-1"></i></a>
                        </div>
                    </div>
                </div>
                <div class="col-md-6 col-lg-3">
                    <div class="card bg-light">
                        <div class="card-body text-center">
                            <img src="https://randomuser.me/api/portraits/men/22.jpg" class="rounded-circle mb-3" alt="">
                            <h3 class="card-title mb-3">強森</h3>
                            <p class="card-text">由於勞工意識抬頭,這種吃力不討好的工作其實不員工不好找,加上基本薪資持續調漲,超商經營的成本越來越高,日前跟傳出日本7-ELEVEN 母公司打算關閉近...</p>
                            <a href=""><i class="bi bi-facebook text-dark mx-1"></i></a>
                            <a href=""><i class="bi bi-twitter text-dark mx-1"></i></a>
                            <a href=""><i class="bi bi-linkedin text-dark mx-1"></i></a>
                            <a href=""><i class="bi bi-instagram text-dark mx-1"></i></a>
                        </div>
                    </div>
                </div>
                <div class="col-md-6 col-lg-3">
                    <div class="card bg-light">
                        <div class="card-body text-center">
                            <img src="https://randomuser.me/api/portraits/women/33.jpg" class="rounded-circle mb-3" alt="">
                            <h3 class="card-title mb-3">網紅圳再開</h3>
                            <p class="card-text">由於勞工意識抬頭,這種吃力不討好的工作其實不員工不好找,加上基本薪資持續調漲,超商經營的成本越來越高,日前跟傳出日本7-ELEVEN 母公司打算關閉近...</p>
                            <a href=""><i class="bi bi-facebook text-dark mx-1"></i></a>
                            <a href=""><i class="bi bi-twitter text-dark mx-1"></i></a>
                            <a href=""><i class="bi bi-linkedin text-dark mx-1"></i></a>
                            <a href=""><i class="bi bi-instagram text-dark mx-1"></i></a>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- contact and map -->
    <section class="p-5">
        <div class="container">
            <div class="row">
                <div class="col-md-6 col-sm-12 contacts-container">
                    <h2 class="text-center mb-4">聯繫我們</h2>
                    <ul class="list-group list-group-flush lead">
                        <li class="list-group-item">
                            <span class="fw-bold">地址:</span>中正路一號
                        </li>
                        <li class="list-group-item">
                            <span class="fw-bold">Email:</span>admin@xxxx.conc.co
                        </li>
                        <li class="list-group-item">
                            <span class="fw-bold">電話:</span>0999999999
                        </li>
                        <li class="list-group-item">
                            <span class="fw-bold">傳真:</span>0222222222
                        </li>
                    </ul>
                </div>
                <div class="col-md-6 col-sm-12 map-container rounded flex-fill" id="mapid"></div>
            </div>
        </div>
    </section>
    <!-- Footer -->
    <footer class="p-5 bg-dark text-white text-center position-relative">
        <div class="container">
            <p class="lead">Copyright &copy; 2021 數位貨幣推薦系統</p>
            <a href="#" class="position-absolute bottom-0 end-0 p-5">
                <i class="bi bi-arrow-up-circle h1"></i>
            </a>
        </div>
    </footer>

    <!-- form -->
    <!-- Modal -->
    <div class="modal fade" id="enroll" tabindex="-1" aria-labelledby="enrollLabel" aria-hidden="true">
        <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
            <h5 class="modal-title" id="enrollLabel">Modal title</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <p class="lead">我們會根據資料儘速回覆你</p>
                <form action="">
                    <div class="mb-3">
                        <label for="username" class="col-form-label">姓名</label>
                        <input type="text" class="form-control" id="usernmae">
                    </div>
                    <div class="mb-3">
                        <label for="email" class="col-form-label">Email</label>
                        <input type="text" class="form-control" id="email">
                    </div>
                    <div class="mb-3">
                        <label for="phone" class="col-form-label">電話</label>
                        <input type="text" class="form-control" id="phone">
                    </div>
                </form>
            </div>
            <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">關閉</button>
            <button type="button" class="btn btn-primary">確定</button>
            </div>
        </div>
        </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
    <script>
        var mymap = L.map('mapid').setView([51.505, -0.09], 13);
        L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={your token}', {
        attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
        maxZoom: 18,
        id: 'mapbox/streets-v11',
        tileSize: 512,
        zoomOffset: -1,
        accessToken: 'your token'
        }).addTo(mymap);
    </script>
</body> 
</html>

JS sample

// 註解

/*
很多行的註解的第一行
很多行的註解的第二行
*/
// 基本變數的設定以及使用    
// var x = 15;
// console.log('[1]變數x的值:' + x);
// x = '這個世界變化快';
// console.log('[2]變數x的值:' + x);
// // 布林變數
// var condition1 = true;
// console.log('變數condition1的值:' + condition1);
// // 變數間的運算
// x = 16;
// var v = 15 + x;
// console.log('[3]變數v的值:' + v);
// v ++;
// console.log('[4]變數v的值:' + v);
// v = v + 1;
// console.log('[5]變數v的值:' + v);
// // 布林運算
// console.log('4 > 3:' + (4 > 3));
// console.log('2 > 3:' + (2 > 3));
// console.log('2 == 3:' + (2 == 3));
// console.log('3 == 3:' + (3 == 3));
// var d = 3;
// v = d * d;
// console.log('[6]變數v的值:' + v);
// // 輸入->運算->輸出
// var input1 = prompt('請輸入數值:', '12');
// var input2 = prompt('請輸入數值:', '12');
// v = input1 * input2;
// console.log('[7]兩者相乘的值:' + v);

// 相等
var num = 0;
var obj = new String("0");
var str = "0";
console.log('[8]變數num的值:' + num + ', 型別為:' + typeof(num));
console.log('[8]變數obj的值:' + obj + ', 型別為:' + typeof(obj));
console.log('[8]變數str的值:' + str + ', 型別為:' + typeof(str));
console.log('num === obj => ' + (num === obj));
console.log('num === str => ' + (num === str));
console.log('obj === str => ' + (obj === str));
console.log('null === undefined => ' + (null === undefined));
console.log('obj === null => ' + (obj === null));
console.log('obj === undefined => ' + (obj === undefined));
console.log('num == obj => ' + (num == obj));
console.log('num == str => ' + (num == str));
console.log('obj == str => ' + (obj == str));
console.log('null == undefined => ' + (null == undefined));
console.log('obj == null => ' + (obj == null));
console.log('obj == undefined => ' + (obj == undefined));
var withdraw = prompt('請輸入提款金額', '');
if (withdraw > 30000){
    console.log('不好意思, 金管會為了防止詐騙不允許提那麼多錢!');
}else{
    console.log('請點收現鈔');
}

var input = prompt('請輸入數字')
if (input % 3 == 0){
    console.log('被3整除');
}else if(input % 3 == 1){
    console.log('餘數為1');
}else{
    console.log('餘數為2');
}

var input1 = prompt("input v1", "");
var input2 = prompt("input v1", "");
var op = prompt("operator is +-*/:", "");
input1 = Number(input1);
input2 = Number(input2);
if(op=='+'){
    alert(input1 + input2);
}else if(op == '-'){
    alert(input1 - input2);
}else if(op == '*'){
    alert(input1 * input2);
}else if(op == '/'){
    alert(input1 / input2);
}else{
    alert('不認識');
}

Loop

// 陣列使用
var a = [12, 45, 88, 47, 33];
var i = 0;
// while 迴圈使用
while(i < a.length){
    if (a[i] % 3 == 0){
        console.log(a[i] + '被3整除');
    }
    i++;
}
// for 迴圈使用
var sum = 0;
for (var i = 1; i <= 100; i++){
    sum = sum + i;
}
console.log('sum = ' + sum);

Function

var x = 3;
function test(x){
    console.log('[1]x = ' + x);
    var x = 12;
    var y = 99;
    console.log('[2]x = ' + x);
    console.log('[2]y = ' + y);
}
test(x);
console.log('[3] y = ' + y);

HTML Dom

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        var simple_count = 0;
        var weather_array = ["下雨", "颱風", "超熱", "可以打球的好天氣", "風大適合逛夜市"];
        var weather_color = ["red", "green", "Tomato", "Orange", "SlateBlue"];
        var weather_count = 0;
        function update_count(){
            simple_count ++;
            window.document.getElementById('counter').innerHTML = ('count:' + simple_count);
        }
        function update_weather(){
            var spanObj = document.getElementById('weather');
            weather_count ++;
            if (weather_count >= weather_array.length){
                weather_count = 0;
            }
            console.log('weather_count = ' + weather_count);
            spanObj.innerHTML = weather_array[weather_count];
            spanObj.style.color = weather_color[Math.floor(Math.random() * weather_color.length)];
        }
    </script>
</head>
<body>
    <div id="counter">count</div>
    <button onclick="update_count()">加數字</button>
    <hr>
    <button onclick="update_weather()">改天氣</button>
    <div><span id="weather">下雨</span></div>
</body>
</html>

JS 遞增數字填滿 ARRAY

function range(start, end) {
  return Array(end - start + 1).fill().map((_, idx) => start + idx)
}
var result = range(9, 18); // [9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
console.log(result);

JS Form

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML Form</title>    
    <style type="text/css">
        form{
            line-height: 2em;
        }
        form>input, form>select{
            padding: 5px, 10px;border: tomato 1px solid;border-radius: 5px;
        }
        form>.ok{
            color:darkgreen;
        }
        form>input:valid+.ok{
            display: inline;
        }
        form>input:invalid+.ok{
            display: none;
        }

    </style>
</head>
<body>
    <h3>Sign up</h3>
    <form onsubmit="alert('表班送出');">
    帳號: <input type="text" placeholder="4-12英數字" pattern="[0-9a-zA-Z]{4,12}" required><span class='ok'>ok</span> <br/>
    密碼: <input type="password" pattern="[0-9a-zA-Z]{8,16}" required><span class='ok'>ok</span><br/>
    Email: <input type="email" required><span class='ok'>ok</span><br/>
    電話: <input type="text" pattern="[0-9]{8,10}" required><span class='ok'>ok</span><br/>
    性別: 男 <input type="radio" name="gender" value="male" required><input type="radio" name="gender" value="female" required>
    其他 <input type="radio" name="gender" value="other" required><span class='ok'>ok</span><br/>
    生日: <select name="birthday" id="birthday_year" required><span class='ok'>ok</span></select>  
    <br/>
    <input type="submit" name="" id="" value="送出資料">
    </form>
    <script>
        var a = Array(2020 - 1900 + 1).fill().map((_, idx) => 1900 + idx)
        for (var i = 0; i<a.length; i++){
            var opt = document.createElement('option');
            opt.value = a[i];
            opt.innerHTML = a[i];
            document.getElementById('birthday_year').add(opt, null);
        }
    </script>
</body>
</html>

JS Event

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        function over_div(el){
            el.style.color = 'yellow';
        }
        function out_div(el){
            el.style.color = 'green';
        }
        function init(){
            var btn = document.getElementById('btn');
            var handler = function(){document.getElementById('x-div').innerHTML="不是空的";}
            btn.addEventListener('click', handler);

            var btn2 = document.getElementById('btn2');
            var handler2 = function(e){
                document.getElementById('x-div2').innerHTML="不是空的";
                console.log(e.clientX + ',' + e.clientY);
            }
            btn2.addEventListener('click', handler2);
        }
        document.addEventListener('keydown', function(e){console.log(e.keyCode)});
        function keyup(e){
            console.log('keyup[' + e.keyCode + ']');
        }
        document.addEventListener('keyup', keyup);
    </script>
</head>
<body onload="init();">
    <span onmouseover="this.style.color='red';" onmouseout="this.style.color='black';">拖鞋是鞋子的一種。鞋後跟全空,只有前面有鞋頭,多為平底。材質經常是相當輕軟的皮料、塑膠、布料、橡膠等。</span>
    <div onmouseover="over_div(this);" onmouseout="out_div(this);">拖鞋的種類依穿著的場合有所區分,例如:海灘拖鞋和浴室的拖鞋,就不會是布料製,而是塑膠材質,這是為了要防水,好清洗的緣故,鞋頭的型式也依功能設計。</div>
    <button id="btn">按鈕</button>
    <div id="x-div">空的</div>
    <hr>
    <button id="btn2">按鈕</button>
    <div id="x-div2">空的</div>
</body>
</html>

XHR(1)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自行車道</title>
</head>
<body>
    選擇 <select id="route-selector" onchange="update_info();"></select>
    <div id="route-info"></div>

    <script>
        var a = new XMLHttpRequest();
        a.open('get', 'https://blog.robertiv.org/images/Bike_f.json', false);
        a.send();
        var b = JSON.parse(a.responseText);
        var datalist = b["XML_Head"]["Infos"]["Info"];
        var route_names = datalist.map(x => x.Name);
        let selector = document.getElementById("router-selector");
        let desc = document.getElementById("route-info");
        for(i=0; i< route_names.length; i++){
            var opt = document.createElement('option');
            opt.text = route_names[i];
            opt.value = route_names[i];
            selector.add(opt, null);
        }
        function update_info(){
            for(i=0;i<datalist.length;i++){
                if(datalist[i]["Name"] == selector.selectedOptions[0].value){
                    desc.innerHTML = "<h2>" + datalist[i]["region"] + "</h2><p>" + datalist[i]["Toldescribe"] + "</p>";
                    break;
                }
            }
        }
    </script>
</body>
</html>

co-lab for XHR

!pip install fastapi nest-asyncio pyngrok uvicorn python-multipart requests
from fastapi import FastAPI, UploadFile, File, Request
from fastapi.middleware.cors import CORSMiddleware
from datetime import datetime
from typing import Optional
from pydantic import BaseModel
import requests
import json

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=['*'],
    allow_credentials=True,
    allow_methods=['*'],
    allow_headers=['*'],
)

@app.get("/route-info")
async def route_info():
    try:
        r = requests.get('https://gis.taiwan.net.tw/XMLReleaseALL_public/Bike_f.json')
        print(r.text[:100])
        route_data = json.loads(r.text)
        return route_data
    except BaseException as ex:
        print(ex)
import nest_asyncio
from pyngrok import ngrok
import uvicorn

ngrok_tunnel = ngrok.connect(8000)
print('Public URL:', ngrok_tunnel.public_url)
nest_asyncio.apply()
uvicorn.run(app, port=8000)

XHR(2)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自行車道</title>
</head>
<body>
    選擇 <select id="route-selector" onchange="update_info();"></select>
    <div id="route-info"></div>

    <script>
        datalist = null;
        let selector = document.getElementById("route-selector");
        let desc = document.getElementById("route-info");

        function reqListener(){
            var b = JSON.parse(this.responseText);
            datalist = b.XML_Head.Infos.Info;
            var route_names = datalist.map(x => x.Name);
            for(i=0; i< route_names.length; i++){
                var opt = document.createElement('option');
                opt.text = route_names[i];
                opt.value = route_names[i];
                selector.add(opt, null);
            }            
        }

        var a = new XMLHttpRequest();
        a.open('get', 'http://81ad01ce44d9.ngrok.io/route-info');
        a.addEventListener("load", reqListener);
        a.send();

        // var a = new XMLHttpRequest();
        // a.open('get', 'http://81ad01ce44d9.ngrok.io/route-info', false);
        // a.send();
        // var b = JSON.parse(a.responseText);
        // var datalist = b["XML_Head"]["Infos"]["Info"];
        // var route_names = datalist.map(x => x.Name);
        // let selector = document.getElementById("route-selector");
        // let desc = document.getElementById("route-info");
        // for(i=0; i< route_names.length; i++){
        //     var opt = document.createElement('option');
        //     opt.text = route_names[i];
        //     opt.value = route_names[i];
        //     selector.add(opt, null);
        // }

        function update_info(){
            for(i=0;i<datalist.length;i++){
                if(datalist[i]["Name"] == selector.selectedOptions[0].value){
                    var k = datalist[i];
                    desc.innerHTML = "<h2>" + k.Region + "</h2><p>" + k.Toldescribe + "</p><p>路線簡述:" +
                        k.Travellinginfo + "</p><p>路線長度" + k.Bike_length + "公尺</p><p>注意事項: " +
                        k.Remarks + '</p>';
                    break;
                }
            }
        }
    </script>
</body>
</html>

Leaflet

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自行車道</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
    integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
    crossorigin=""/>
    <!-- Make sure you put this AFTER Leaflet's CSS -->
    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
    integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
    crossorigin=""></script>
    <style type="text/css">
        #mapid {height: 500px;}
    </style>
</head>
<body>
    選擇 <select id="route-selector" onchange="update_info();"></select>
    <div id="route-info"></div>
    <div id="mapid"></div>
    <script>
        datalist = null;
        let selector = document.getElementById("route-selector");
        let desc = document.getElementById("route-info");

        function reqListener(){
            var b = JSON.parse(this.responseText);
            datalist = b.XML_Head.Infos.Info;
            var route_names = datalist.map(x => x.Name);
            for(i=0; i< route_names.length; i++){
                var opt = document.createElement('option');
                opt.text = route_names[i];
                opt.value = route_names[i];
                selector.add(opt, null);
            }            
        }

        var a = new XMLHttpRequest();
        a.open('get', 'https://blog.robertiv.org/images/Bike_f.json');
        a.addEventListener("load", reqListener);
        a.send();

        // var a = new XMLHttpRequest();
        // a.open('get', 'http://81ad01ce44d9.ngrok.io/route-info', false);
        // a.send();
        // var b = JSON.parse(a.responseText);
        // var datalist = b["XML_Head"]["Infos"]["Info"];
        // var route_names = datalist.map(x => x.Name);
        // let selector = document.getElementById("route-selector");
        // let desc = document.getElementById("route-info");
        // for(i=0; i< route_names.length; i++){
        //     var opt = document.createElement('option');
        //     opt.text = route_names[i];
        //     opt.value = route_names[i];
        //     selector.add(opt, null);
        // }

        function update_info(){
            for(i=0;i<datalist.length;i++){
                if(datalist[i]["Name"] == selector.selectedOptions[0].value){
                    var k = datalist[i];
                    desc.innerHTML = "<h2>" + k.Region + "</h2><p>" + k.Toldescribe + "</p><p>路線簡述:" +
                        k.Travellinginfo + "</p><p>路線長度" + k.Bike_length + "公尺</p><p>注意事項: " +
                        k.Remarks + '</p>';
                    var latlngs = k.Trail_Periphery.map(x => [x.Py, x.Px]);
                    console.log(latlngs);
                    var polyline = L.polyline(latlngs, {color: 'red'}).addTo(mymap);
                    mymap.fitBounds(polyline.getBounds())
                    break;
                }
            }
        }
        var mymap = L.map('mapid').setView([23.1001253946, 121.379766259], 13);
        L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={token}', {
            attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
            maxZoom: 18,
            id: 'mapbox/streets-v11',
            tileSize: 512,
            zoomOffset: -1,
            accessToken: 'your.mapbox.access.token'
        }).addTo(mymap);
    </script>
</body>
</html>


Comments

comments powered by Disqus