【JavaScript】滑鼠相關屬性

滑鼠相關屬性

clientX & clientY

定位基準:視窗長&寬
視窗長&寬→window.innerHeight / Width
※視窗的範圍:瀏覽器的畫面,扣掉上方網址列的部分。
如果把瀏覽器畫面,視窗也會跟著變小

▼示意圖▼

intro.addEventListener("mousemove", function(e){
   console.log(e.clientX, e.clientY);
 }
)

offsetX & offset Y

定位基準:目標元素的長&寬
目標元素的長&寬:id.clientHeight / Width

▼示意圖▼

intro.addEventListener("mousemove", function(e){
   console.log(e.offsetX, e.offsetY);
 }
)

pageX & pageY

定位基準:整個頁面的長&寬
整個頁面的長&寬:document.body.clientHeight / Width
※【沒設定頁面寬的情況】瀏覽器的寬度拉小,整個網頁頁面的寬度也會跟著變小(被壓縮了)
※【有設定頁面寬的情況】瀏覽器的寬度拉小,整個網頁頁面的寬度不會跟著變小(會出現橫向的卷軸)

▼示意圖▼

intro.addEventListener("mousemove", function(e){
   console.log(e.pageX, e.pageY);
 }
)

screenX & screenY

定位基準:電腦畫面的長&寬
電腦的長&寬:screen.height / width
※電腦整個畫面:上方有包含網址列,下方有包含工具列
※跟clientX / Y 的差別:定義的外圍是電腦畫面,所以即便拉小瀏覽器視窗,也不會有任何影響

▼示意圖▼

intro.addEventListener("mousemove", function(e){
   console.log(e.screenX, e.screenY);
 }
)

【JavaScript】load事件 網頁打開後馬上觸發

説明

網頁一載入→觸發事件
【例】表單填入網頁:頁面一打開,焦點就對準輸入格。

範例

寫法一

監聽load事件

input#input(type="text" placeholder="input something...")
window.addEventListener("load", function(){
 input.focus();
})

寫法二

使用window.load

window.onload=input.focus();

Display

【JavaScript】Event Listener 監聽事件一覽

用法

①透過特定event觸發動作

用法基礎篇

目標物.addEventListener("特定的event", 
 function(){
  //這邊寫要觸發的動作
 }
)

②操控目標元素完成某動作

用#button按鈕操控,讓超連結#theURL被點擊

a#theURL(href="ianchen.thisistap.com") 超連結
br
button(onclick="openURL()") click it and open the URL
//onclick的用法參見下方
function openURL(){
 theURL.click();
}

Display

超連結

③ON+EVENT名稱:用HTML直接呼叫 function

基礎範例

HTML用法:on+event名=”函式名()”
※如果要呼叫event的話,需要使用這種形式:on+event名=”函式名(event)”

【例如】click event & makeItBigger function
→onclick="makeItBigger()" 
//這個東西放在HTML tag裡面
//記得要另外寫makeItBigger這個函式

【上述用法等同】
id.eventListener("click", makeitBigger());

滑鼠相關監聽事件

  1. click event:滑鼠按下→觸發事件
  2. mousemove event:滑鼠移動→觸發事件
  3. mousedown event:滑鼠按下去的瞬間→觸發事件
  4. mouseout event:滑鼠離開→觸發事件
  5. mouseup event:滑鼠按下、離開的瞬間→觸發事件

打字相關監聽事件

  1. focus event:聚焦(點選到)該元素→觸發事件
    ※可以用滑鼠點選觸發focus,某些情況下也可以用鍵盤選取(Tab鍵),觸發focus
  2. blur event:focus的相反,離開該元素後→觸發事件
  3. keydown event:鍵盤按下時→觸發動作
  4. keyup event:鍵盤按下後鬆開→觸發動作
  5. input event:輸入文字→觸發動作

其他監聽事件

  1. transitionend event:漸變結束後→觸發事件
  2. change event:<input>狀態改變時→觸發事件
    【例】下拉式選單:變更選項→觸發事件
    【例】核取方塊:勾選 / 取消勾選→觸發事件

 

【JavaScript】input相關Method

value

偵測文字輸入框的內容

input#input(type="text")
br
#show
window.addEventListener("keyup", function(){
 show.textContent=`What you input is "${input.value}"`;
})

Display

What you input is

checked


監測核取方塊被點選的狀態。並且傳回布林值

input#checkbox(type="checkbox")
br
p#ckeckStatus
btn.addEventListener("click", function(){
 ckeckStatus.innerHTML=`ckecked status: ${checkbox.checked}`;
})

Display


【JavaScript】Contains Method

説明

  1. 判斷節點(Node)裡面有沒有含有檢索的內容。
  2. 若有,回傳true
  3. 若無,回傳false

範例

#p.hi 123
console.log(p.classList.contains("hi"));
//true

進階:防止選取子元素

母選單設定點選→觸發子選單展開・收合的function,但因為子選單包在母選單底下,所以在子選單打開的狀況下,點選子選單內容,會觸發function,造成子選單收合

解決方法:在function裡面增加contains條件(選取子選單的class),防止子選單觸發

.nav
 ul
 li.first
 |list 01 click
 ul.second
 li.not-choose list 02
 li.not-choose list 02
 li.not-choose list 02
 li.not-choose list 02
 li.first
 |list 01 click
 ul.second
 li.not-choose list 02
 li.not-choose list 02
 li.not-choose list 02
 li.not-choose list 02
 li.first
 |list 01 click
 ul.second
 li.not-choose list 02
 li.not-choose list 02
 li.not-choose list 02
 li.not-choose list 02
 li.first
 |list 01 click
 ul.second
 li.not-choose list 02
 li.not-choose list 02
 li.not-choose list 02
 li.not-choose list 02
 li.first
 |list 01 click
 ul.second
 li.not-choose list 02
 li.not-choose list 02
 li.not-choose list 02
 li.not-choose list 02
.second
 max-height: 0px
 overflow: hidden
 transition-duration: 0.5s
 
.open
 max-height: 100px
// if(e.target.classList.contains("list02")==true) return;
// // 讓他不要選到children
const firsts=document.querySelectorAll(".first");

firsts.forEach(first => first.addEventListener("click", function(e){
 //讓他不要選到children
 if(e.target.classList.contains("not-choose")==true) return;
 this.children[0].classList.toggle("open")
 
 
}))

Display

【Vue.js】ready指令 API串接

説明

用ready串接後台API

範例

API載入純文字

#app
 p {{text}}
const vm=new Vue({
 el: "#app",
 data: {
  text: ""
  },
 ready: function(){
  $.ajax({
   url: "https://awiclass.monoame.com/api/command.php?type=get&name=notifydata",
   success: function(res){
    vm.text=res;
    }
   })
  }
 
})

Display

哈囉!! 這邊是你用AJAX載入的純文字公告!!

API載入JSON

要先轉換成JSON格式,否則會變成純字串

#app
 ul
  li(v-for="item in items") 【{{item.name}}】${{item.price}}
const vm=new Vue({
 el: "#app",
 data: {
  items: []
  },
 ready: function(){
  $.ajax({
   url: "https://awiclass.monoame.com/api/command.php?type=get&name=itemdata",
   success: function(res){
    vm.items=JSON.parse(res); //轉換成JSON格式
    }
   })
 }
 
})

Display

  • 【吹風機】$300
  • 【麥克筆】$9000
  • 【筆記型電腦】$54555
  • 【Iphone 9】$32000
  • 【神奇海螺】$5000
  • 【PSP1007】$2000
  • 【鍵盤】$3500

【JavaScript】Ajax

説明

jQuery版本
使用原生的JavaScript串接Ajax

  1. 建立HTTPRequest請求  new XMLHttpRequest()
  2. 建立回應函式  onreadystatechange
  3. 確認readyState、status(HTTP狀態碼)OK
  4. 執行回應動作,回應的值為responseText
  5. 定義後端api網址與method  open()
  6. 前端傳送資料  send()

readyState

 值  狀態  說明
 0  UNSET  尚未讀取
 1  OPENED  讀取中
 2  HEADERS_RECEIVED  已下載完畢
 3  LOADING  資訊交換中
 4  DONE  成功

status

status為200,表示成功

HTTP狀態碼一覽

範例

JavaScript版

p#p
const xmlhttp=new XMLHttpRequest();

xmlhttp.onreadystatechange=function(){
 if(this.readyState==4 && this.status==200){
  p.textContent=this.responseText; //API連成功的動作
 }
};

xmlhttp.open("GET", "https://awiclass.monoame.com/api/command.php?type=get&name=notifydata");//API網址
xmlhttp.send();

Display

哈囉!! 這邊是你用AJAX載入的純文字公告!!

jQuery版

p#p
$.ajax({
 url: "https://awiclass.monoame.com/api/command.php?type=get&name=notifydata",
 success: function(res){
  p.textContent=res;
 }
})

Display

哈囉!! 這邊是你用AJAX載入的純文字公告!!

用ajax取得header, menu等共用HTML

#header
var headerXhr=new XMLHttpRequest();

headerXhr.open('GET', 'header.html', true);
headerXhr.send();

headerXhr.onreadystatechange=function(){
    if(headerXhr.readyState==4 && headerXhr.status==200){
        header.innerHTML = headerXhr.responseText;
    }
};

用ajax傳送JSON

TIPS: 先把JSON轉成string格式,再傳送

var xmlhttp=new XMLHttpRequest();

xmlhttp.open('POST', 'http://9.102.60.125:5000/api/bbinqcan', true);
xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xmlhttp.onreadystatechange=function(){

    if(xmlhttp.readyState==4 && xmlhttp.status==200){
        res.textContent=xmlhttp.responseText;
    }
};

xmlhttp.send(
        //checkedJSON是一個JSON格式的變數
    JSON.stringify(checkedJSON);
)

【Vue.js】v-on

説明

methods寫在JS裡面,v-on寫在HTML裡面。
功能類似原生JS的addEventListener。

範例

#app
 button(v-on:click="show") click me
 p#vueText some text
#vueText
 color: #fff
var vm=new Vue({
 el: "#app",
 methods: {
 show: function(){
  vueText.style.color="#000"
  }
 }
})

Display

some text

【JavaScript】子物件指定

説明

JS中有2種方式可以指定子物件。

方法一:dot連接

常用方法,利用dot連接母物件與子物件

const obj={
 akasha: 222,
 typhoon: 15151515,
 tks: "33333333"
}

console.log(obj.akasha); //222

方法二:中括號

母物件後面用中括號,中括號裡面可以用字串指定,或是用變數代換

const obj={
 akasha: 222,
 typhoon: 15151515,
 tks: "33333333"
}

//字串指定法
console.log(obj["akasha"]); //222

/*****************************/

//變數代換法
const typ = "typhoon";
console.log(obj[typ]); //15151515

 

【Vue.js】v-if

使用方法

①data物件裡面建立會用到布林値的變數
②用v-model操控使用者變更布林値
③v-if=”變數名稱”,當布林値為真,顯示某些元素

範例

當核取方塊被點選,就會顯示下方文字

#app
 label Show text
 input(type="checkbox" v-model="show")
 p the value of show is {{show}}
 hr
 p(v-if="show") Hey the box is clicked !!
var vm=new Vue({
 el: "#app",
 data: {
 show: false
 }
});

Display

the value of show is false


【Vue.js】v-for

基本用法

v-for=”項目 in 陣列”

#app
 ul
  li(v-for="item in shoplist") {{item}}
var vm=new Vue({
 el: "#app",
 data: shoplist: ["apple", "banana", "papaya"]
});

Display

  • apple
  • banana
  • papaya

物件形式與存取編號

編號用id表示

#app
 ul
  li(v-for="(id, item) in shoplist2") {{id+1}}. {{item.name}}
  br
  |${{item.price}}

//陣列的編號從0開始計算,但是一般商品的編號要從1開始,所以id+1
var vm=new Vue({
 el: "#app",
 data: shoplist2: {
 name: "apple",
 price: 1000,
 origin: ["美國", "日本"]
 },
 {
 name: "banana",
 price: 500,
 origin: ["台灣", "韓國", "菲律賓"]
 },
 {
 name: "papaya", 
 price: 300,
 origin: ["亞特蘭提斯", "印度"]
 }
});

Display

  • 1. apple
    $1000
  • 2. banana
    $500
  • 3. papaya
    $300

使用第二層v-for

#app
 ul
  li(v-for="(id, item) in shoplist2") 【編號】{{id+1}} 
  br
  |【品名】{{item.name}}
  br
  |【價錢】${{item.price}}
  br
  |【生產地】
  span(v-for="place in item.origin") </br>{{place}}
var vm=new Vue({
 el: "#app",
 data: shoplist2: {
 name: "apple",
 price: 1000,
 origin: ["美國", "日本"]
 },
 {
 name: "banana",
 price: 500,
 origin: ["台灣", "韓國", "菲律賓"]
 },
 {
 name: "papaya", 
 price: 300,
 origin: ["亞特蘭提斯", "印度"]
 }
});

Display

  • 【編號】1
    【品名】apple
    【價錢】$1000
    【生產地】
    美國
    日本
  • 【編號】2
    【品名】banana
    【價錢】$500
    【生產地】
    台灣
    韓國
    菲律賓
  • 【編號】3
    【品名】papaya
    【價錢】$300
    【生產地】
    亞特蘭提斯
    印度

 

 

【Vue.js】變數代換

説明

Vue.js是前端框架,用JS解決HTML資料處理。
→技術文件

HTML:寫模板
JS:代入資料
→解決①HTML重複撰寫太多②資料即時更新問題

應用

引入Vue.js

<head>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.28/vue.js"></script>
</head>

建立模板與代入資料

#app
//指定Vue作用區域
 h1 Vue.js 使用大括號與變數代換
 hr
 p 我的名字叫做{{name}},來自{{city}}
 //用兩個大括號{{}}建立模板
 br
 |最近正在學習如何使用{{lang}},
 br
 |他其實就像是一個{{text}}
 p Vue.js的代換可以用物件來表示,甚至陣列來判斷。
//建立一個Vue, 即時監測資料更新狀況
var vm=new Vue({
 el: "#app", //指定作用區域
 data: { //用物件形式存放資料
 name: "陳怡安",
 city: "基隆市",
 lang: "Vue.js",
 text: "資料置換法",
 notation: "兩個大括號{{變數名稱}}",
 }
})

Display

我的名字叫做陳怡安,來自基隆市
最近正在學習如何使用Vue.js,
他其實就像是一個資料置換法

Vue.js的代換可以用物件來表示,甚至陣列來判斷。
只要在裡面用兩個大括號{{變數名稱}}包起來就可以了。

陣列與v-for列表渲染

#app
 p 我的技能有:
 /**************
 非v-for法
 ul 
  li {{skills[0]}}
  li {{skills[1]}}
  li {{skills[2]}}
  li {{skills[3]}}
 ****************/
 //v-for法
 ul
  li(v-for="skill in skills") {{skill}}
  //skill 可以自己命名
  //skills要根據vue撰寫的内容指定
var vm=new Vue({
 el: "#app",
 data: {
 skills: ["程式開發", "網頁設計", "翻譯", "口譯"],
});

Display

我的技能有:

  • 程式開發
  • 網頁設計
  • 翻譯
  • 口譯

 使用物件資料

#app
 p 我踏入網頁設計已經有{{infos.year}}年了,希望可以持續進步。
var vm=new Vue({
 el: "#app",
 data: {
 infos:{
 year: 1
  },
 }
});

Display
我踏入網頁設計已經有1年了,希望可以持續進步。

代入HTML程式碼

使用3組大括號代入HTML程式碼

#app
 p Vue.js除了預設帶入是一般的純文字以外,三組大括號可以代入HTML原始碼
 div {{{html}}}
.block
 width: 100px
 padding: 10px
 border: 1px solid #000
var vm=new Vue({
 el: "#app",
 data: {
  html: "<div class='block'>代入HTML</div>"
  //雙引號内的HTML字串裡面要改單引號
 }
});

Display

代入HTML

globalCompositeOperation 合成效果

説明

對canvas產生圖層混合的效果。
類似CSS的mix-blend-mode

範例

canvas#canvas(width="800", height="800")
html, body
 margin: 0
 padding: 0
 overflow: hidden
const ctx=canvas.getContext("2d");


ctx.fillStyle="#FFA500";
ctx.fillRect(400, 400, 100, 100);

//合成效果一覽
ctx.globalCompositeOperation="multiply";

ctx.fillStyle="#f7f4c8";
ctx.fillRect(450, 450, 100, 100);

Display
Display

destructuring assignment 分離指派式

説明

可以將陣列或物件的資料取出成獨立變數。
※通常用來大量指定變數,可以一行寫完。

範例

/********
以前的寫法
const a=1;
const b=2;
*********/

/***ES6新寫法***/
[a, b]=[1, 2]
//可以簡潔地指定一坨變數。

console.log(a, b)//1 2

canvas stroke 描繪線條

步驟

  1. 建立路徑
    beginPath()
  2. 設定線條寬度(可省)
    lineWidth=”5″
  3. 設定顏色(可省)
    strokeStyle=”green”
  4. 開始
    moveTo(0, 100)
  5. 結束
    lineTo(300, 100)
  6. 畫出線來
    stoke()

範例

canvas#canvas(width="300", height="150")
const ctx=canvas.getContext("2d");
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;

//draw a line
ctx.beginPath();//start to draw a line
ctx.lineWidth="5";//set line width
ctx.strokeStyle="green";//set color
ctx.moveTo(0, 100);//start point
ctx.lineTo(300, 100);//end point
ctx.stroke();//draw it

Display

const

const 的特性

  1. 不可以被修改(再指定)
  2. 如果有block,在block裡面可以被改,但是回到外面會變回初始值

cant’t be updated & defined

const width=100;

width=200;
console.log(width);//100
//不可被修改

block scope

let points=50;
const winner=false;


if(points>40) {
 const winner=true;
 console.log(winner);//true
 //只有在block內部,才能夠被更改
}

console.log(winner);//false
//在外部則不會被更改,呈現初始值

By Value or By Reference

當資料類型為By Value時〔Number, String, Boolean〕
以const宣告的變數是不能被再指定的(即等於不能被改)

//錯誤示例
const name='Ian';
name='Chen'; //←ERROR!!

但若資料類型是By Reference時〔Object, Array〕,
以const宣告後可以用push, object.item=xxx等方式修改其值。
但一樣不能進行再指定的動作

//正確示例
const fruits=['apple', 'banana', 'orange'];
console.log(fruits); //['apple', 'banana', 'orange']

fruits.push('grape');
console.log(fruits); //['apple', 'banana', 'orange', 'grape']
//錯誤示例
const colors=['red', 'blue', 'green'];
colors=['pink', 'black', 'white'] //←ERROR!!

let

block

block是指大括弧 {} 裡面。
像是if述句,for述句,function裡面都是block

  • global scope→任何地方都能被改
  • block socpe→在if述句,for述句,function裡面可以被改(大括號包起來的地方),在外面還是回到初始值
  • function scope→只有在function裡面才可以被改

let 的特性

  1. 可以被修改
  2. 如果有block,在block裡面可以被改,但是回到外面會變回初始值

updated & defined

let width=100;

width=200;
console.log(width);//200
//可被修改

block scope

let points=50;
let winner=false;


if(points>40) {
 let winner=true;
 console.log(winner);//true
 //只有在block內部,才能夠被更改
}

console.log(winner);//false
//在外部則不會被更改,呈現初始值

var

var的特性

  1. 可以被重新定義(redefined)
  2. 可以被更新(updated)
  3. 若存在於函式內(function),就是函式變數(function scope),只能在函式內部被存取、修改。
  4. 若沒再函式內,會變成全域變數(global scope),不論在函式內或是外面都可以被存取,修改。

redefined and updated

var width=100;
console.log(width);//100

width=200;
console.log(width);//200
//可被修改

function scope

function setWidth() {
 var width = 100;
 console.log(width);//100
}

setWidth();
console.log(width);//nothing
//width只能在setWidth裡面作用

global scope

var width;
function setWidth() {
 width = 100;
 console.log(width);//100
}

setWidth();
console.log(width);//100
//width 在任何地方都能被修改或存取
let points = 50;
var winner = false;

if(points > 40) {
 var winner = true
 console.log(winner);//true
}

console.log(winner);//true
//因為if不是function,所以winner變成全域變數
//能在任何地方被修改與存取

建立canvas

説明

canvas 是一種強大的繪圖功能。
透過 HTML 與 JS 的使用 (主要是 JS )
可以在瀏覽器上繪製任何向量圖型。
跟 SVG 有點像,但用途更多元。

步驟解説

設定 HTML 與 CSS

canvas#canvas(width="800", height="800")
//呼叫canvas,然後給一個id,設定畫布長寬
//這邊設定的長800寬800會成為指定向量元素的絶對定位參考

html, body
 margin: 0
 overflow: hidden
//讓邊界不會多出來

定義 context 與長寬

context 是作畫的畫布。
圖形都要畫在 context 上面。

//定義context
const ctx=canvas.getContext("2d");//平面圖型用2d

//定義長寬
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;//設定畫布=全螢幕

開始作畫(添加圖形元素)

  1. 先設定顏色
  2. 再設定圖形
//填色
ctx.fillStyle="#FFA500";


//畫正方形
ctx.fillRect(400, 400, 100, 100);
//※顏色要在最上面,否則正方形會變成黑的

splice() 陣列項目刪除

説明

刪除或增添陣列項目

範例

刪除項

陣列.splice(編號,刪除幾項)

【例】arr.splice(1, 1)
→從 arr[1] 開始刪除1項
→刪掉 arr[1]

const fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'];
fruits.splice(1, 1)//從fruits[1]開始,刪掉1項。

console.log(fruits);//["Banana", "Lemon", "Apple", "Mango"]

增添項

const fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'];
fruits.splice(1, 1, "Melon")//從fruits[1]開始,刪掉1項,插入“Moko”

console.log(fruits);//["Banana", "Melon", "Lemon", "Apple", "Mango"]

 

slice() 保留部分陣列項目

定義

指定陣列編號範圍,返回一組新的陣列

【必須値】開始,結束
※返回的値不會包含結束的編號,但會包含開始的那個編號

範例

const fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'];

const sl=fruits.slice(0, 2);
//return//fruits[0], fruits[1];
console.log(sl);//["Banana", "Orange"]

【省略結束値】回報至最末項

const fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'];

const sl=fruits.slice(2);
//等於fruits.slice(2, fruits.length);
//return fruits[2], fruits[3], fruits[4]
console.log(sl);//["Lemon", "Apple", "Mango"]

擷取多範圍

fruits共有5項資料。
保留【第1項】【第3~5項】。

多條件要用中括號[]包起來。
條件之間用逗號, 連結。
並且加上spread operator轉換成array形式。

const fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'];

const sl=[
 ...fruits.slice(0, 1),
 ...fruits.slice(2)
];

console.log(sl);
//["Banana", "Lemon", "Apple", "Mango"]

陣列相關方法2

Ref: JavaScript30

some()  確認有沒有人符合條件

給予條件→找出是否有一個人(或以上)符合條件。

//共用陣列資料
const people = [
 { name: 'Wes', year: 1988 },
 { name: 'Kait', year: 1986 },
 { name: 'Irv', year: 1970 },
 { name: 'Lux', year: 2015 }
];

確認是否有人已滿19歳

/*****【方法一】function*************/
const isAdult1=people.some(

function(person){
 //getFullYear?
 const currentYear=new Date().getFullYear();
 if(currentYear-person.year>=19){
 return true;
 }
}
 
);


/*****【方法二】arrow function*******/
const isAdult2=people.some(person => new Date().getFullYear()-person.year>=19);
console.log(isAdult2);//true

every()  確認是否全員符合條件

給予條件→找出是否所有人都符合條件。

確認是否全員都滿19歳

const everyAdult=people.every(person => new Date().getFullYear()-person.year>=19);

console.log(everyAdult);//false

find()  找出特定的項目

//共用陣列資料
const comments = [
 { text: 'Love this!', id: 523423 },
 { text: 'Super good', id: 823423 },
 { text: 'You are the best', id: 2039842 },
 { text: 'Ramen is my fav food ever', id: 123523 },
 { text: 'Nice Nice Nice!', id: 542328 }
];

找出id為【823423】的留言

const comment=comments.find(comment => comment.id===823423);

console.log(comment);
/**
Object {
  id: 823423,
  text: "Super good"
}
**/

findIndex 找出特定項目的陣列編號

【※注意】陣列編號由 0 開始算。編號 0 為第1項、編號 1 為第 2 項。

找出id為【823423】的陣列編號

const index=comments.findIndex(comment => comment.id===823423);

console.log(index);//1 ←comments[1];

splice 刪除特定編號的陣列

參考文章
【※注意】只能指定編號刪除。

comments.splice(1, 1);

//然後comments就會少一項了。但不保留沒刪除前的内容。

slice 摘取陣列

參考文章

也可以達到刪除特定項目陣列的效果。
但方法是擷取保留項目,像是指定列印頁數。

共5頁的資料→只列印【第1頁】、【第3-5頁】→最後印出來的資料就會少了第2頁

用slice可以同時保留刪除前的陣列與刪除後的陣列。

const newComments=[
 ...comments.slice(0, 1),//only return comments[0]
 ...comments.slice(2)//omit end value
 //保留slice[0], slice[2-4]→等於去掉slice[1]
]; 

console.log(newComments);
/**
const newC=[
 ...comments.slice(0, 1),//only return comments[0]
 ...comments.slice(2)//omit end value
];
**/

 

搜尋器

Reference: JavaScript 30

先備知識

範例

form.search-form
 input.search(type='text', placeholder='City or State')
 ul.suggestions
 li Filter for a city
 li or a state
html
 box-sizing: border-box
 background: #ffc600
 font-family: 'helvetica neue'
 font-size: 20px
 font-weight: 200

*
 box-sizing: inherit
 &:before, &:after
 box-sizing: inherit

input
 width: 100%
 padding: 20px

.search-form
 max-width: 400px
 margin: 50px auto

input.search
 margin: 0
 text-align: center
 outline: 0
 border: 10px solid #F7F7F7
 width: 120%
 left: -10%
 position: relative
 top: 10px
 z-index: 2
 border-radius: 5px
 font-size: 40px
 box-shadow: 0 0 5px rgba(0, 0, 0, 0.12), inset 0 0 2px rgba(0, 0, 0, 0.19)

.suggestions
 margin: 0
 padding: 0
 position: relative
 /*perspective:20px;
 li
 background: white
 list-style: none
 border-bottom: 1px solid #D8D8D8
 box-shadow: 0 0 10px rgba(0, 0, 0, 0.14)
 margin: 0
 padding: 20px
 transition: background 0.2s
 display: flex
 justify-content: space-between
 text-transform: capitalize
 &:nth-child(even)
 transform: perspective(100px) rotateX(3deg) translateY(2px) scale(1.001)
 background: linear-gradient(to bottom, #ffffff 0%, #EFEFEF 100%)
 &:nth-child(odd)
 transform: perspective(100px) rotateX(-3deg) translateY(3px)
 background: linear-gradient(to top, #ffffff 0%, #EFEFEF 100%)

span.population
 font-size: 15px

.details
 text-align: center
 font-size: 15px

.hl
 background: #ffc600

.love
 text-align: center

a
 color: black
 background: rgba(0, 0, 0, 0.1)
 text-decoration: none
const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';

const cities=[];

//blob用來指稱原始資料
//轉換成JSON資料
fetch(endpoint)
 .then(blob => blob.json())
 .then(data => cities.push(...data))

function find(word, cities){
 
 return cities.filter(place => {
 const regex=new RegExp(word, "gi");
 return place.city.match(regex) || place.state.match(regex)
 })

}

function commas(x){
 return x.toString().replace(/B(?=(d{3})+(?!d))/g, ",");
}


function display(){
 const match=find(this.value, cities);
 const html=match.map(place => {
 const regex=new RegExp(this.value, "gi");
 const cityName=place.city.replace(regex, `<span class="hl">${this.value}</span>`);
 const stateName=place.state.replace(regex, `<span class="hl">${this.value}</span>`);
 
 return `
 <li>
 <span class="name">${cityName}, ${stateName}</span>
 <span class="population">${commas(place.population)}</span>
 </li>
 `
 }).join("");
 
 
 suggestions.innerHTML=html;
}

const search=document.querySelector(".search");
const suggestions=document.querySelector(".suggestions");


search.addEventListener("change", display);
search.addEventListener("keyup", display);

Display

CODEPEN

regex【i】不區別大小寫

功能

讓字串不區分大小寫,也能通過正規表達式檢査。
應用實例:搜尋不用區分大小寫,也能找到同樣的内容。

類似的東西:regex【g】找出所有

範例

方法一【/i】

i代表 insensitive ,對大小寫不敏感。

const regex=/apple/i;

const str1="APPLE";
const str2="Apple";
const str3="apple";

str1.match(regex);//["APPLE"]
str2.match(regex);//["Apple"]
str3.match(regex);//["apple"]
//不論大小寫(或混用)都能通過驗證

方法二【new RegExp】

使用時機:需要檢査的字串不是固定値,而是變數時(像是使用者鍵入的搜尋字詞)

寫法跟【/i】不同,但是效果相同。

const regex=new RegExp("apple", "i");

const str1="APPLE";
const str2="Apple";
const str3="apple";

str1.match(regex);//["APPLE"]
str2.match(regex);//["Apple"]
str3.match(regex);//["apple"]

onclick

功能

onclick 是 HTML 的屬性,等於 JavaScript 的 click 事件

範例

button#btn(onclick="scale()") click me
/******
onclick="scale()"等於這個
btn.addEventListener("click", scale);
******/

function scale(){
 btn.style.transform="scale(2)";
 btn.style.transformOrigin="left top";
}

Display

程式碼上色函式庫 highlight.js

功能

程式碼上色,可以用 syntax 找相關的英文資源 ,這個函式庫可以將部落格的程式碼文字依照關鍵字、註解等上不同顏色。

使用方法

  1. 引入 css 與 js 函式庫
  2. 依照規範撰寫pre tag 與 code tag
  3. 寫進指定 js 碼

※css有各種style。

一般網頁

外引CDN函式庫的方法

引入 js 與 css 函式庫

<head>
 
 //引入css,這裡選擇tomorrow style
 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.9.0/styles/tomorrow.min.css" />

 //引入js
 <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.9.0/highlight.min.js"></script>
</head>

依照規範撰寫 pre 與 code

  1. pre tag 裡面包一層 code tag
  2. <code class=”程式語言名”>
//以寫css碼為例
<pre>
 <code class="css">
  pre {
  border: 1px solid #eee;
  width: 400px;
 }
 </code>
</pre>

寫進指定 js

function custom(){
 hljs.initHighlightingOnLoad();
}
custom();

Display

CODEPEN

WordPress

header.php→引入 css 與 js 函式庫、寫入指定 js

<head>

//在head tag之間加上下面這3行
<!--highlight.js-->
 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.9.0/styles/tomorrow.min.css">
 <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.9.0/highlight.min.js"></script>

</head>

<body <?php body_class(); ?>>

//在<body>下面加上這段script
<script>
hljs.initHighlightingOnLoad();
</script>

文章編輯:text editor→依照規範撰寫 pre 與 code

//以寫css碼為例
<pre>
 <code class="css">
  pre {
  border: 1px solid #eee;
  width: 400px;
 }
 </code>
</pre>

Display

CODEPEN

 

 

match() 與 test()

功能

兩者都是搭配正規表達式的Method

match()

字串.match(正規表達式);
//回傳比對出的部分字串結果
//若比對不到東西,則回傳null

const str="apple";
const check=/[a-c]/;

str.match(check);//["a"]

test()

正規表達式.test(字串);
//有比對到回傳true,沒有則回傳false

const str="apple";
const check=/[a-c]/;

check.test(str);//true

setInterval

功能

設定每隔一段時間執行一次動作,可以模擬動畫效果
缺點:只能處理能夠數值化的CSS屬性(width, opacity, scale, rotate等等),不能完成顏色漸變等效果

button(onclick="show()") click me
br
br
#box show up
#box
 width: 200px
 height: 100px
 background-color: #aaffe2
 text-align: center
 line-height: 100px
function show(){
 //pos是變動的透明度數值
 var pos=0;
 //setInterval(動作, 毫秒)→每隔幾毫秒,執行一次動作
 const id=window.setInterval(function(){
 
 if(pos>=1){
 //如果pos夠大了,清掉Interval,阻止繼續增加下去
 clearInterval(id);
 pos=0;
 }else{
 pos+=0.1;
 box.style.opacity=pos;
 }
 
 }, 50)
}

show up

正規表達式

説明

正規表達式,是專門用來處理字串邏輯的條件語法。
常常用在 input 表單上,檢査使用者輸入的内容有沒有符合特定格式。
諸如信用卡號格式驗證,密碼強度驗證等等。

相關方法:match(),test()

語法

宣告正規表達式

正規表達式的前後要各用1個斜線/包起來(有點像字串需要用”包起來)。

const str="abcde";
const check=/abc/;

str.match(cri);//["abc"]
//回傳 被找到的字串
if(str.match(cri)){
 console.log(true);
 //↑通常驗證表單會寫成這個形式,裡面放通過驗證後的動作
}else{
 console.log(false)
}//true

尋找某區間内文字

設定檢索區間: [a-e]
a為開始値,e為終止値。

const str="apple";
const check=/[a-c]/;//尋找有沒有 a,b,c 這3個字母
//※寫成/[a-c]/g會比較好(下面會説明)
//※也可以比對多重區間(下面説明)

str.match(check)//["a"]

if(str.match(cri)){
 console.log(true);
}else{
 console.log(false);
}//true ←但只有 a 有被找到而已,pple並沒有被找到

/*****注意*****
※這個例子match是寬鬆尋找方法,只要有1個字元被找到,就會跑出true
*************/

尋找全部【/g】

參考這篇文章

一般情況下,match只會1次比對一個字串字元而已,所以回傳値只會吐出第1項符合的字元。
如果要叫他吐出所有,就要使用/g←放在正規表達式的最後面

※但如果是用 if(str.match(check)) 的話不使用 /g 也沒差

const str="apple";
const check=/[a-e]/;
const check2=/[a-e]/g;//尋找全部寫法


str.match(check);//["a"]
str.match(check2);//["a", "e"]←這樣寫就可以一條一條找出所有符合的字元了

/****比對多重區間***/
const check3=/[a-eo-p]/g//←直接接下去加入就好

str.match(check3);//["a", "p", "p", "e"]

尋找數字與數字字符【\d】

有2種方法可以找到數字

  • 設定 0-9 的區間
  • 正規字符【\d】
const str="apple123";
const check=/[0-9]/g
const check2=/\d/g; //\d效果同等於[0-9]


str.match(check);//["1", "2", "3"]
str.match(check2);//["1", "2", "3"]

檢査數字長度

使用大括號{}指定該字元必須出現幾次

const str="123456";
const check=/\d{4}/;//{4}表示數字(\d)要連續出現4次←4位數字

str.match(check);//["1234"]

if(str.match(check)){
 console.log(true);
}else{
 console.log(false);
}//ture
/*****
str="123456"→true
str="1234"→true
str="12"→false

只有當str不足4位數字時才會回報false(match找不到匹配値,回傳null)
str滿足或超過4位數都會回傳true
※那要怎麼寫手機號碼驗證!←下面告訴你
*****/

設定嚴格的條件:使用開始【^】與結束【$】字符

在上例中可以發現,只有當字串不滿足條件時才會報 false ,剛好符合或超過條件的清況都會回報 true 。

但某些情況下,我們需要非常精確的格式,比如

  • 手機號碼必須是 10 位數字
  • 信用卡號必為 4位數-4位數-4位數-4位數
  • 身份證字號為 1大寫英文 + 9 為數字

所以我們必須更進階地規定條件,不足或超出條件者都必須是 false。

以下為嚴格化寫法

  • 在開頭加入開始字符^
  • 結尾加入結束字符$
//驗證手機號碼
const str1="0912345678";
const str2="0912";
const str3="09123456789999"
const check=/^\d{10}$/;

str1.match(check); //["0912345678"]
str2.match(check); //null
str3.match(check); //null

//進階:規定前2碼為09

const check2=/^09\d{8}$/; //指定09跟後面的8碼條件不用任何東西連接,直接加上就行

str1.match(check2); //["0912345678"]

英數字集符號【\w】

如同 \d 為 [0-9] 的簡寫一般,
\w 則為 [a-zA-Z0-9_] 的簡寫。

可以檢查所有英文大小寫字母,底線,以及數字

const str="ianchen_0419";

const check=/\w/g;
const check2=/[a-zA-Z0-9_]/g;
//這兩個效果一樣

str.match(check);//["i", "a", "n", "c", "h", "e", "n", "_", "0", "4", "1", "9"]
str.match(check2);//["i", "a", "n", "c", "h", "e", "n", "_", "0", "4", "1", "9"]

 

可有可無的條件【?】

『使用者名稱可以包含減號-』

這樣的情況下,不論字串有無減號-,皆可滿足條件。
因此減號-是一個可有可無的條件。

在減號-後面加上問號 ? ,便可以構成可有可無的驗證式

const str1="ianchen";
const str2="ian-chen";
const str3="ian--chen";
const str4="-ianchen";
const str5="ianchen-";

const check=/\w-?\w/;
const check2=/^\w-?\w$/;
//用check2的話5個str都會是null,因為check2必須是【1字母 + 有無底線皆可 + 1字母】的組合才行。


str1.match(check);//["ia"]
str2.match(check);//["ia"]
str3.match(check);//["ia"]
str4.match(check);//["-i"]
str5.match(check);//["ia"]
//結論:5種情況都可以true

比對特殊字元:前置反斜線\

Regex特殊字元【.^$?】

這些字元都是Regex特殊字符,帶有特殊的意義。
若要單純比對這些符號,必須前置反斜線\以做區別。

const str1="$";
const str2="^";
const str3=".";
const str4="?";

const check1=/\$/;
const check2=/\^/;
const check3=/\./;
const check4=/\?/;

str1.match(check1);//["$"]
str2.match(check2);//["^"]
str3.match(check3);//["."]
str4.match(check4);//["?"]

比對很多次【+】

重複比對【+】前面的東西很多次

const str="ianchen_0419";
const check=/\w+/;
//重複比對英文字元(←【+】前面的)很多次,直到比對不了為止

str.match(check);//["ianchen_0419"]

有後面再比對前面【?=】

a(?=b)→如果有找到b的話,再檢查前面有沒有a,並且比對出a
【?=b】要使用括號包起來

const str1="ianchen0419";
const str2="ianchen"
const str3="0419ianchen";
const check=/[a-z]+(?=\d)/;
//後面有數字的話,再比對前面有沒有英文
//然後把所有的英文都找出來【+】

str1.match(check);//["ianchen"]
str2.match(check);//null ←這個因為後面找不到數字所以沒辦法比對英文
str3.match(check);//null ←這個因為數字前面沒有英文所以一樣無法

沒有後面再比對前面【?!】

a(?!b)→如果沒有找到b的話,再檢查前面有沒有a,並且比對出a
【?!b】要使用括號包起來

使用情境:給數字加上分隔逗號,每3碼加一個逗號,但是要從最末位往前數(所以要確保後面沒有落單的數字)

【例】1,234,567,890

const str1="ianchen0419";
const str2="ianchen"
const str3="0419ianchen";
const check=/[a-z]+(?!\d)/;
//後面沒有數字的話,再比對前面有沒有英文
//然後把所有的英文都找出來【+】

str1.match(check);//null ←這個因為後面有數字了所以不能比對前面的英文
str2.match(check);//["ianchen"]
str3.match(check);//["ianchen"]

找出英文邊界【\b】

※前提,英文句子要用空格隔開單字

【\b\w】→找到每個單字字首
【\w\b】→找到每個單字字尾

const str="this is a apple";//必須要有空格
const check1=/\b\w/g;//找字首
const check2=/\w\b/g;//找字尾

str.match(check1);//["t", "i", "a", "a"]
//"this is a apple"

str.match(check2);//["s", "s", "a", "e"]
//"this is a apple"

找出非英文邊界【\B】

用途:數字,符號等等

const str="1234567890";
const check1=/\B\d{3}/g;//每3個字斷開(從後面開始數)
const check2=/\d{3}\B/g;//每3個字斷開(從前面開始數)


str.match(check1);//["234", "567", "890"]
str.match(check2);//["123", "456", "789"]

英文數字逗點

【例】1234567890→1,234,567,890

function commas(x){
 return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 //①從最末位往前數3碼(後面沒有數字的話,比對出3個數字)
 //②一直數一直數
 //③符合①就給他分隔符號
 //④\B比對非英文字的邊界,如果沒有\B的話會變成",123,456,789"
 //取代所有分隔符號為","

}

線上練習網站:RegexOne

JavaScript Array methods 陣列相關方法1

本篇介紹的method

filter()[👧, 👦, 👩, 👨, 👵, 🧓] => [👦, 👨, 🧓]原本的陣列有 6 個,後來變成 3 個
map()[👧, 👦, 👩, 👨, 👵, 🧓] => [👧🏿, 👦🏿, 👩🏿, 👨🏿, 👵🏿, 🧓🏿]陣列內容都變成不一樣的顏色了(但數量一樣是 6 個)
sort()[👧, 👦, 👩, 👨, 👵, 🧓] => [👧, 👩, 👵 👦, 👨, 🧓]陣列的順序改變了
reduce()[👧, 👦, 👩, 👨, 👵, 🧓] => 👨‍👩‍👧陣列被綜合成一個東西了

本篇使用到的共用物件

const inventors = [
 { first: 'Albert', last: 'Einstein', year: 1879, passed: 1955 },
 { first: 'Isaac', last: 'Newton', year: 1643, passed: 1727 },
 { first: 'Galileo', last: 'Galilei', year: 1564, passed: 1642 },
 { first: 'Marie', last: 'Curie', year: 1867, passed: 1934 },
 { first: 'Johannes', last: 'Kepler', year: 1571, passed: 1630 },
 { first: 'Nicolaus', last: 'Copernicus', year: 1473, passed: 1543 },
 { first: 'Max', last: 'Planck', year: 1858, passed: 1947 },
 { first: 'Katherine', last: 'Blodgett', year: 1898, passed: 1979 },
 { first: 'Ada', last: 'Lovelace', year: 1815, passed: 1852 },
 { first: 'Sarah E.', last: 'Goode', year: 1855, passed: 1905 },
 { first: 'Lise', last: 'Meitner', year: 1878, passed: 1968 },
 { first: 'Hanna', last: 'Hammarström', year: 1829, passed: 1909 }
 ];

filter() 把陣列的數量變少,但是內容不變

filter() 裡面放一個函數,filter() 可以物件→物件,也能夠陣列→陣列

應用:篩選出出生於 16 世紀的投資客(出生年介於 1500 到 1600 之間)

const arr1=inventors.filter(function(item){
 if(item.year>=1500 && item.year<1600){
  return true;
 }
})

console.log(arr1); //[{ first: 'Galileo', last: 'Galilei', year: 1564, passed: 1642 }, { first: 'Johannes', last: 'Kepler', year: 1571, passed: 1630 }]

ES6 應用:箭頭函數(省略 return

const arr1=inventors.filter(item => item.year>=1500 && item.year<1600);

console.log(arr1); //[{ first: 'Galileo', last: 'Galilei', year: 1564, passed: 1642 }, { first: 'Johannes', last: 'Kepler', year: 1571, passed: 1630 }]

map() 陣列數量固定,但裡面內容置換

map() 可以物件→陣列,也可以陣列→陣列

應用:列出所有投資客的全名(first + last

const arr1=inventors.map(item => `${item.first} ${item.last}`);

console.log(arr1); //["Albert Einstein", "Isaac Newton", "Galileo Galilei", "Marie Curie", "Johannes Kepler", "Nicolaus Copernicus", "Max Planck", "Katherine Blodgett", "Ada Lovelace", "Sarah E. Goode", "Lise Meitner", "Hanna Hammarström"]

sort() 更動陣列順序

sort() 可以物件→物件,也能夠陣列→陣列
  • return 1:往後移動
  • return -1:往前移動

應用①:將投資客由老排到年輕(出生年數字越大代表越年輕,所以要越往後移動)

sort() 裡面的函數可以塞兩個參數,第一個值代表比較的第一個人、第二個值代表比較的第二個人,sort() 會幫忙把所有排列組合都列出來
const arr1=inventors.sort(function(a, b){
 if(a.year>b.year){
  return 1; //如果a的年紀比b小,a往後擺
 }else{
  return -1;
 }
});

console.table(arr1); //結果會出來一個由老排到小的物件

ES6 應用:箭頭函數 + if 簡寫

const arr1=inventors.sort((a, b) => a.year>b.year ? 1 : -1)

console.table(arr1);

應用②:將投資客的名字 (firstname) 開頭字母由A排到Z

const arr1=inventors.sort((a, b) => a.first>b.first ? 1 : -1)

console.table(arr1);

reduce() 將陣列內容輸出為單一值

reduce() 可以物件→單一值,也可以陣列→單一值

應用①:計算所有投資客總共活了多久

  • reduce() 裡面的函數的第一個參數為「累加器 accumulator」,第二個參數為「迭代中的元素 currentValue
  • reduce() 裡面的第二個值為一個數字,表示「累加器初始值 initialValue」(通常填 0
const value=inventors.reduce(function(total, item){
 return total += (item.passed-item.year);
}, 0)

console.log(value); //861

ES6 應用:箭頭函數

const value=inventors.reduce((total, item) => total += (item.passed-item.year), 0)

console.log(value); //861

應用②:統計各個交通工具出現的次數

//原始資料
const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck' ];
var value=data.reduce((obj, item)=>{
 obj[item]++;
 return obj;
},{
 car: 0,
 walk: 0,
 truck: 0,
 bike: 0,
 van: 0
})

console.log(value); // {bike: 2, car: 5, truck: 3, van: 2, walk: 2}

符號分割字串 split()

字串的分割

split() 裡面填入一個字串形式的值,這個值用來切割其他要拿來切割的字串
var str='2020/01/01';
console.log(str.split('/')); //["2020", "01", "01"]

陣列=>字串的分割

陣列可以搭配 map() 轉換成字串在分割,但分割後的格式會變成陣列中的陣列
var arr=['2020/01/01 15:00', '2020/04/04 13:00', '2020/03/03 09:00'];
var arr2=arr.map(item => item.split(' '));
console.log(arr2); //[["2020/01/01", "15:00"], ["2020/04/04", "13:00"], ["2020/03/03", "09:00"]]
或乾脆只抓取分割後的某部分,組成新的陣列
var arr=['2020/01/01 15:00', '2020/04/04 13:00', '2020/03/03 09:00'];
var arr2=arr.map(item => {
 var [date, time]=item.split(' ');
 return date;
})
console.log(arr2); //["2020/01/01", "2020/04/04", "2020/03/03"]

shift() 切出第一個字串

var str="2020/01/01"
console.log(str.split('/').shift()); //"2020"

pop() 切出最後一個字串

var str="2020/01/01"
console.log(str.split('/').pop()); //"01"