javascript DOM

javascript DOM 文件物件模型
DOM = Document Object Model
用javascript操作物件是個方便的功能,就如同夾娃娃機一樣,先抓到DOM,然後對內容進行我們想要的操作,例如改變值、或者是進行計算。


目錄:


常用語法(如同夾娃娃機的爪子):

getElementById()
getElementsByClassName()
getElementsByName()

在jsbin寫HTML

HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
	<div class="doll" id="doll-1">娃娃1</div>
	<div class="doll" id="doll-2">娃娃2</div>
</body>
</html>

Output

娃娃1
娃娃2

用javascript取出元素

1. getElementById()

取出id為doll-1的元素,並用其他值帶換

var d1 = document.getElementById('doll-1');
d1.innerHTML = "畫家貓";

Output

畫家貓
娃娃2

2. getElementsByClassName()

取出所有class為doll的元素 並用迴圈代換

/*設定allDolls變數為陣列名稱*/
var allDolls = document.getElementsByClassName('doll');

for (var i = 0; i < allDolls.length; i++) {

     /* 每跑一次迴圈,指定每個陣列值為變數d */
    var d = allDolls[i];
    
    /* 指定新值,取代d在HTML裡的原始值*/
    d.innerHTML = "達菲兔" + (i+1);

}

Output

達菲兔1
達菲兔2

getElementById(), getElementsByClassName()比較

HTML:

<div class="doll" id="doll-1">娃娃1</div>
<div class="doll" id="doll-2">娃娃2</div>

Javascrip:

//取得 id = doll-1 的元素(一個)
//d1為字串
var d1 = document.getElementById('doll-1');

//取得 class 是 doll 的元素們(全部)
//allDolls為陣列

var allDolls = document.getElementsByClassName('doll');

3. querySelector()

querySelector() 取代 getElementById()

var d1 = document.querySelector('#doll-1');
d1.innerHTML = "伊布";

Output

伊布
娃娃2

4. querySelectorAll()

querySelectorAll() 取代 getElementsByClassName()

var allDolls = document.querySelectorAll('.doll');

for (var i = 0; i < allDolls.length; i++) {

     /* 每跑一次迴圈,指定每個陣列值為變數d */
    var d = allDolls[i]; 

    /* 指定新值,取代d在HTML裡的原始值*/
    d.innerHTML = "迷你Q" + (i+1);

}

在Console印出HTML裡的元素

querySelector()

var d1 = document.querySelector('#doll-1');
console.log(d1.innerHTML);
d1.innerHTML = "伊布";

Console

"娃娃1"

Output

伊布
娃娃2

querySelectorAll()

/*指定allDolls陣列,存放class裡所有的值*/
var allDolls = document.querySelectorAll('.doll');

for (var i = 0; i < allDolls.length; i++) {
    
    /* 每跑一次迴圈,用console印出陣列裡的值 */
    console.log(allDolls[i].innerHTML);
    
     /* 每跑一次迴圈,指定每個陣列值為變數d */
    var d = allDolls[i]; 
    
    /* 指定新值,取代d在HTML裡的原始值*/
    d.innerHTML = "迷你Q" + (i+1); 

}

Console

"娃娃1"
"娃娃2"

Output

迷你Q1
迷你Q2

實作練習1: BMI計算機

Step1. 希望按下按扭online會出現效果

=> 設定function名稱calculateBMI();

HTML

<input type="submit" value="計算" onclick="calculateBMI();">

Javascript

function calculateBMI() {
  var height = document.querySelector('#bodyHeight');
  
  var weight = document.querySelector('#bodyWeight');
  
  console.log(height); /*先試試看console會不會印出東西*/ 
}

問題:console印的是輸入隔的格式,而非輸入的數值。

Console

<input id="bodyHeight" min="0" type="number">

解法:將.querySelector('#bodyHeight')後接.value

  var height = document.querySelector('#bodyHeight').value;

Console

10

Step2. 拆開計算功能,傳出參數,另寫一function bmi(height, wight)

=> height, weight值取出後,傳入另一個function,利用parseInt()轉為數值。

javascript

function bmi(height, weight) {
  // 取完值後轉為數值
  var w = parseInt(weight);
  var h = parseInt(height) / 100;
  return (w / ( h * h ));
}

function calculateBMI() {
  //  按下去後取值
  var height = document.querySelector('#bodyHeight').value;
  
  var weight = document.querySelector('#bodyWeight').value;
  console.log(bmi(height, weight));
}

問題:如何印出小數點第2位?

console

24.218749999999996

解法:使用.toFixed(2);

  return (w / ( h * h )).toFixed(2);

console

24.22

Step3. calculateBMI()把結果印出來

function calculateBMI() {
  //  按下去後取值
  var height = document.querySelector('#bodyHeight').value;
  var weight = document.querySelector('#bodyWeight').value;
  var result = document.querySelector('#resultText');
  // 不用.value, 因為此表單格式非input
   
  result.innerHTML = bmi(height, weight);
  //console.log(bmi(height, weight));
}

Step4. 簡單的防呆機制

空白值計算後會產生NaN,用邏輯判斷if else擋掉空白以及除數為0的情況

  if ((height != '') && ( height != 0) && (weight != '')){
    result.innerHTML = bmi(height, weight);
  } else {
    alert('請輸入正確數值!');
  }

Step5. 加上肥胖提醒

javascript

// 程式碼寫在這裡!
function bmi(height, weight) {
  // 取完值後轉為數值
  var w = parseInt(weight);
  var h = parseInt(height) / 100;
  var r = (w / ( h * h )).toFixed(2);
  return r;
}

function printHealth(height, weight) {
  if (bmi(height, weight) >= 24){
    return "有點胖喔!多起來走動走動";
  } else if(bmi(height, weight) < 18) {
    return "有點瘦喔!多吃一點";
  } else { return "正常" };
}

function calculateBMI() {
  //  按下去後取值
  var height = document.querySelector('#bodyHeight').value;
  var weight = document.querySelector('#bodyWeight').value;
  var result = document.querySelector('#resultText'); // 不用.value
  var health = document.querySelector('#healthText');
  if ((height != '') && ( height != 0) && (weight != '')){
    result.innerHTML = bmi(height, weight);
    health.innerHTML = printHealth(height, weight);
  } else {
    alert('請輸入正確數值!');
  }
  //console.log(bmi(height, weight));
}

完成品:https://codepen.io/tingtinghsu/full/zbaRQd

實作練習2: 購物車

加上選擇全部功能和計算價錢功能

selectAllSkills() 選擇全部的函數

html

<a href="#" class="selectAll" onclick="selectAllSkills()">我全都要 </a>

從html發現skillset的標籤,不同技能的class名稱都是skill,因此可以用DOM抓取此變數。

<section class="skillset">
      <h1>想學會的技能</h1>
      <input type="checkbox" class="skill" id="html" value="html"><label for="html">HTML</label>
      <input type="checkbox" class="skill" id="css" value="css"><label for="css">CSS</label>
      <input type="checkbox" class="skill" id="javascript" value="javascript"><label for="javascript">JavaScript</label>
      <input type="checkbox" class="skill" id="git" value="git"><label for="git">Git</label>
      <input type="checkbox" class="skill" id="ruby" value="ruby"><label for="ruby">Ruby</label>
      <input type="checkbox" class="skill" id="ruby-on-rails" value="ruby-on-rails"><label for="ruby-on-rails">Ruby on Rails</label>
      <a href="#" class="selectAll" onclick="selectAllSkills()">我全都要</a>
</section>

javascript

function selectAllSkills() {
  var skills = document.querySelectorAll('.skill');
  //skills為一個陣列
  for (var i = 0; i < skills.length; i++){
    var s = skills[i];
    //改變.checked屬性
    s.checked = true;
  }
}

addProduct() 改變商品的數量及價格

不管+1或-1,若將函數帶入數值,可以做成同一個function

html

<td><span id="item1Quantity">0</span>
    <a href="#" class="addProduct" onclick="addProduct(-1)">-</a>
    <a href="#" class="addProduct" onclick="addProduct(1)">+</a>
</td>

用DOM抓取欄位和價格 問題:輸入框input可以用.value取值,但是span是HTML標籤,要如何取值?

解法:用inner.HTML,再加上parseInt()轉換成數值

javascript

function addProduct(amount) {
  var quantityField = document.querySelector('#item1Quantity');
  var priceField = document.querySelector('#item1Price');

  /* 量 */
  var quantity = parseInt(quantityField.innerHTML);
  //原始值0已抓取
  quantity += amount; //增減後的數值
  if (quantity < 0) { quantity = 0 } //數量最小值為0
  
  quantityField.innerHTML = quantity; 
  //將量HTML餵回去

 /* 價 */
  var unitpriceField = document.querySelector('#unitPrice');
  var unitpriceInt = parseInt(unitpriceField.innerHTML);

  priceField.innerHTML = unitpriceInt * quantity; 
  //單價*新量,餵回去HTML總價
}

相關連結

HackMD筆記
CodePen練習一
CodePen練習二
網頁版-BMI計算機
網頁版-網站購物車