分類彙整:JavaScript

【JavaScript】JS的位置

説明

在HTML檔案中,JS不論是寫在頁面上,或是用檔案引入,都建議放在body後面。

理由:HTML文件的讀取方式是由上而下,如果寫在body前面的話,網頁還沒讀完JS就執行了,所以DOM會抓不到東西。

但若一定要寫在body前面的話,可以在JS內容外面加上一層load事件,讓網頁全部讀完後,再執行JS。

window.addEventListener("load", function(){

 //這邊放入JS內容。

});

【JavaScript】smalot-bootstrap-datetimepicker

説明

這是一套基於BS的函式庫,可以快速製作時間選擇器的小元件。

【必裝的函式庫】

屬性介紹

format【字串形式】

意義
p am / pm
P AM / PM
s 秒(沒有0開頭)
ss 秒(有0開頭)
i 分(沒有0開頭)
ii 分(有0開頭)
h 時(沒有0開頭,24小時制)
hh 時(有0開頭,24小時制)
H 時(沒有0開頭,12小時制)
HH 時(沒有0開頭,12小時制)
d 日期(沒有0開頭)
dd 日期(有0開頭)
m 數字月份(沒有0開頭)
mm 數字月份(有0開頭)
M 英文月份簡寫
MM 英文月份全名
yy 西元年(末二位數)
yyyy 西元年(四位數)

StartView / MinView 【數字形式】

在「只選擇月份」或是「只選擇日期」的情況下,預設的介面卻可以指定到某天的分鐘,會不太適合。
可以透過調整這2個參數達成更精準的控制

  • StartView:一開始選擇時間的介面〔預設:2〕
  • MinView:最後選擇時間的介面〔預設:0〕
意義
0 【選分鐘】hour view
1 【選小時】day view
2 【選日期】month view
3 【選月份】year view
4 【選年份】10-year view

範例:選擇日期

.input-append.date.form_datetime(data-view='hour')
 input(size='16', type='text', value='', readonly='', placeholder='2017-11-15 16:35')
 span.add-on
 i.fa.fa-calendar
$(".form_datetime[data-view='hour']").datetimepicker({
 format: "yyyy-mm-dd", //這邊可以自訂時間表示的格式
 autoclose: true,
 minView: 3
 });

範例:選擇時與分

.input-append.date.form_datetime(data-view='hour')
 input(size='16', type='text', value='', readonly='', placeholder='2017-11-15 16:35')
 span.add-on
 i.fa.fa-calendar
$(".form_datetime[data-view='hour']").datetimepicker({
 format: "yyyy-mm-dd hh:ii",
 autoclose: true
 });

範例:選擇月份

.input-append.date.form_datetime(data-view='year')
 input(size='16', type='text', value='', readonly='', placeholder='2017-11')
 span.add-on
 i.fa.fa-calendar
$(".form_datetime[data-view='year']").datetimepicker({
 format: "yyyy-mm",
 autoclose: true,
 startView: 4,
 minView: 3
 });

Display

CODEPEN

 

 

【JavaScript】load HTML 外部載入HTML

用途

在一個HTML檔案的部分區域引入其他外部HTML

▼示意圖

上圖使用了2個外部HTML,檔案結構如下

  • 主頁面〔index.html〕
  • 主選單(橫條選單)〔main-nav.html〕
  • 側選單(直條選單)〔verti-nav.html〕

在主頁面〔index.html〕頁面中,引入2個選單HTML〔main-nav.html〕&〔verti-nav.html〕

native JS 方法

const xhr=new XMLHttpRequest();
xhr.open("GET", "../verti-navs.html", true);
xhr.send();

xhr.onreadystatechange=function(){
 if(xhr.readyState==4 && xhr.status==200){

    document.querySelectorAll(".verti-nav")[0].innerHTML = xhr.responseText;

    }
};

jQuery 方法:load

$(".verti-nav").load("verti-navs.html");

觀看環境

外部載入HTML、ajax等做法會涉及到檔案之間的溝通,所以無法普通地在本機電腦打開觀看。需要透過以下的環境打開檔案。

觀看環境一:localhost

將電腦設定成虛擬主機(localhost),有以下幾種方法
  • 安裝XAMPP
  • 使用Webpack+Node.js
  • 利用終端機內建的python設定localhost環境

以下介紹用終端機設定localhost環境的方法

cd /Users/Desktop/web 
#指定要打開的資料夾

python -m SimpleHTTPServer 9099

輸入完畢後開啟瀏覽器,打開網址:http://localhost:9099
就會跳出index.html的頁面

觀看環境二:FireFox

FireFox也支援檔案之間的溝通。
但是,必須要先從index.html打開,再用index.html連到其他的頁面。否則FF會抓不到根目錄。

JS的撰寫方式

針對load進來的選單HTML撰寫JS時,有時會發生選單相關JS沒有被執行到的狀況。(特別在localhost環境下觀看時)

原因:JS的語言特性會偷跑,如果所有HTML的JS都要統一管理成同一份檔案,必須考慮到瀏覽器載入HTML的順序,再安排JS的撰寫位置。

一般來說,瀏覽器載入檔案的順序會是這樣:

  1. 主HTML檔案
  2. JS檔案
  3. load進來的選單HTML
    (因為選單load進來的動作是由JS控制,所以JS一定會比選單HTML早一步執行)

※因為JS檔案(內含選單相關JS)在選單HTML存在前就被載入了,所以當JS執行的時候並不存在選單HTML,導致JS的程式無效。

解決:

  1. 將選單相關JS寫在XMLHttpRequest的動作裡面。
  2. 並且增加一條判斷式:如果response存在,才執行選單JS
const xhr=new XMLHttpRequest();
xhr.open("GET", "../verti-navs.html", true);
xhr.send();

xhr.onreadystatechange=function(){
 if(xhr.readyState==4 && xhr.status==200){

    document.querySelectorAll(".verti-nav")[0].innerHTML = xhr.responseText;
    if(xhr.responseText){
       //這邊撰寫選單相關JS

     }
  }
};

【JavaScript】change event

説明

<input>狀態改變時→觸發事件
【例】下拉式選單:變更選項→觸發事件
【例】核取方塊:勾選 / 取消勾選→觸發事件

label Choose a color
 select#sel(name="colors" onchange="selShow()")
 option(value="Nothing") Select One...
 option(value="red") RED
 option(value="blue") BLUE
 option(value="green") GREEN 
#changeStatus
function selShow(){
 changeStatus.textContent=`You selected ${sel.value}`
}

Display

【JavaScript】transitionend event

説明

transitionend event:漸變結束後→觸發事件

#box(ontransitionend="transShow()") hover me
p#transStatus
#box
 border: 1px solid #000
 display: inline-block
 transition-duration: 0.5s
 &:hover
  font-size: 30px
function transShow(){
 transStatus.textContent="Transition is Done"
}

Display

hover me

【JavaScript】keydown and keyup event

説明

  • keydown event:鍵盤按下時→觸發動作
  • keyup event:鍵盤按下後鬆開→觸發動作

 

p Press any key
p#pressStatus
window.addEventListener("keydown", function(e){
 pressStatus.textContent=`Key code of ${e.keyCode} is pressed`;
})

window.addEventListener("keyup", function(){
 pressStatus.textContent=`Now you left the key`
})

Display

Press any key

【JavaScript】focus and blur event

説明

  1. focus event:聚焦(點選到)該元素→觸發事件
    ※可以用滑鼠點選觸發focus,某些情況下也可以用鍵盤選取(Tab鍵),觸發focus
  2. blur event:focus的相反,離開該元素後→觸發事件
input#getText(type="text")
button(onclick="getFocus()") Get focus
button(onclick="loseFocus()") Lose focus
function getFocus(){
 getText.focus();
}

function loseFocus(){
 getText.blur();
}

Display

【JavaScript】mouse event series

説明

  • mousedown:滑鼠按下去的瞬間→觸發事件
  • mouseout:滑鼠離開→觸發事件
  • mouseup:滑鼠按下、離開的瞬間→觸發事件

 

p Try to draw it ↓↓
canvas#canvas(width="300", height="300")
#canvas
 width: 300px
 height: 300px
 border: 1px solid #000
let isDrawing=false;
let lastX=0;
let lastY=0;
const ctx=canvas.getContext("2d");

function draw(e){
 if(!isDrawing){
  return;
 }

 ctx.beginPath();
 ctx.moveTo(lastX, lastY);
 ctx.lineTo(e.offsetX, e.offsetY);
 ctx.strokeStyle="#000000";
 
 [lastX, lastY]=[e.offsetX, e.offsetY];
 
 ctx.stroke();
}

//滑鼠按下→開始畫圖,計算起始座標
canvas.addEventListener("mousedown", (e) => {
 isDrawing = true;
 [lastX, lastY]=[e.offsetX, e.offsetY];
});

//滑鼠移動→繼續畫圖
canvas.addEventListener("mousemove", draw);
//滑鼠放掉→停止畫圖
canvas.addEventListener("mouseup", () => isDrawing = false);
//滑鼠離開→停止畫圖
canvas.addEventListener("mouseout", () => isDrawing = false);

Display
Try to draw it ↓↓

【JavaScript】mousemove event

説明

滑鼠移動→觸發事件

#screenBox Hover me
#locate
#screenBox
 width: 300px
 height: 200px
 background-color: #eee
 text-align: center
 line-height: 200px
 color: rgba(0,0,0,0.5)
screenBox.addEventListener("mousemove", function(e){
 locate.textContent=`Mouse locate is (${e.offsetX}, ${e.offsetY})`
})

Display

Hover me