計算機概論Lab-8

javascript

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

https://hackmd.io/@IMOK/Lab8


Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

講師: 賴昱有


15puzzle game

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0"> 
    <!---
    width=device-width 表示網頁的寬度應該等於設備的寬度。
    確保網頁在不同設備上有適當的寬度。
    initial-scale=1.0 表示初始的縮放比例為1.0。
    這確保了網頁在載入時不進行縮放
    --->
	<title>15 Puzzle</title>
	<link rel="stylesheet" href="15puzzle.css">
</head>
<body>
	<div id="puzzle"></div>
    
	<div id="controls">
		<button id="solve">Solve</button>		
		<button id="scramble">Scramble</button>
	</div>
	

	<script src="script.js"></script>
</body>
</html>

div(division)

<div>
  <!-- 這裡可以包含其他HTML元素,如文本、圖片、表格等 -->
  <p>This is a paragraph inside a div.</p>
  <img src="example.jpg" alt="An example image">
</div>

經常作為CSS selector的容器,以便對特定區域設計樣式


CSS複習

定義每個文字的顏色、物件的外框、element 之間的距離,甚至撰寫動畫等等。

CSS語法重點:
1. selector 語法:用來指定 HTML 中,哪些 element 要套用這個樣式
2. 樣式描述:用來說明指定的 elements 要用什麼樣子去顯示


selectors種類

• Simple selectors (select elements based on name, id, class)
• Combinator selectors (select elements based on a specific relationship between them)
• Pseudo-class selectors (select elements based on a certain state)
• Pseudo-elements selectors (select and style a part of an element)
• Attribute selectors (select elements based on an attribute or attribute value)


Simple Selectors

• Element selector
• ID selector
• Class selector
• Grouping selector
• Universal selector


Element selector

選擇的 element 名稱來設定該類 element 的顯示樣式

p {
    color: yellow;
}
div {
    height: 50px;
    width: 60px;
}

ID selector

幫 element 設定 id attribute ,再利用這個 id 來設定不同的顯示樣式
HTML:

<div id="block"></div>

CSS:

#block {
    height: 50px;
    width: 50px;
    color: red;
}

Class selector

在 css 中先定義好一個種類的樣式,
然後在HTML 中透過 class attribute 來選擇要使用哪一個種類的樣式顯示。

CSS:

.redBlock {
    height: 50px;
    width: 50px;
    color: red;
}

HTML:

 <div class="redBlock"></div>

Grouping selector

group selector 的寫法可以省略重複的樣式定義。

p {
    color: red;
}
input {
    color: red;
}
div {
    color: red;
}
p, input , div {
    color: red;
}

Universal selector

對所有的 element 進行樣式定義。

* {
    color: red;
}

CSS Box Model

image
• Content : element 內容所顯示的區域
• Padding : 位於外框 (Border) 與內容 (Content) 之間的空間
• Border : element 的邊框
• Margin : element 與 element 之間的空間


CSS Properties

CSS 還可以做什麼呢?
https://www.w3schools.com/cssref/index.php

https://css-tricks.com/


15puzzle.css

/* pseudo-element */
::selection {background: transparent;}
p{margin: 0; font: 12px/150% Arial; text-align: center; color: #999;}
p a{color: #888;}

#controls{text-align: center;}
#controls button{
	cursor: pointer; /*設置鼠標懸停在按鈕上時的鼠標樣式為手型*/
	outline: none;	 /*去掉按鈕點擊時的默認輪廓線*/
	padding: 10px 20px;
	margin: 25px 2px;
	border: 0;
	border-radius: 4px;
	background: #001F1F;
	font: bold 14px Arial;
	text-align: center;
	text-transform: uppercase;
	text-shadow: -1px -1px 0 rgba(0,0,0, 0.5);
	color: #fff;
}
#controls button:hover{background: #003333;}

#puzzle{
	position: relative;
	width: 325px;
	height: 325px;
	margin: 0 auto;
	margin-top: 80px;
	border: 8px solid #001F1F;
	border-radius: 4px;
}
#puzzle span{
	position: absolute;
	display: block;
	width: 80px;
	height: 80px;
	border-radius: 4px;
}
#puzzle span.number{
	cursor: pointer;
	font: bold 36px/80px Arial;
	text-align: center;
	text-shadow: -1px -1px 0 rgba(0,0,0, 0.5);
	color: #fff;
}
#puzzle span.empty{background: transparent;}
#puzzle span.number.light{background: #226666;}
#puzzle span.number.dark{background: #003333;}

#puzzle.animate span{
	-webkit-transition: 0.15s left, 0.15s top;
 	transition: 0.15s left, 0.15s top; /*left、top 會在0.15s內被改變*/
    /*-webkit-transition 用於支援WebKit(例如Chrome和Safari等)的瀏覽器*/
    /*transition 則是標準的CSS3屬性*/
}

Javascript Introduction

image


Javascript做了哪些事情?

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

1. 接收使用者的輸入內容
2. 根據輸入內容來做判斷
3. 將結果顯示在網頁上


function search_animal() { 
	let input = document.getElementById('searchbar').value 
	input=input.toLowerCase(); 
	let x = document.getElementsByClassName('animals'); 
	
	for (i = 0; i < x.length; i++) { 
		if (!x[i].innerHTML.toLowerCase().includes(input)) { 
			x[i].style.display="none"; 
		} 
		else { 
			x[i].style.display="list-item";				 
		} 
	} 
} 

function checkEnter(event) {
    // 檢查是否按下的是 Enter 鍵
    if (event.key === "Enter") {
        search_animal();
    }
}

Hello world (- -b)

<!DOCTYPE html>
<html>
    <head>
        <title>Hello Javascript</title>
        <meta charset="utf-8">
        <script>
            console.log("Hello World"); 
            /*使用瀏覽器打開.html,按下F12,選擇console*/
        </script>
    </head>
    <body>
    </body>
</html>

image


Variable Declaration

告訴電腦說,我要產生一個變數,並且給他一個名子,
讓我們之後可以根據這個名子找到他。

var x = 5;

Data Type

var x = 1; //整 數(integer)
var y = 10.13; //浮 點 數(float)
var z = "Hello"; //字 串(String)
var p = true; //布 林 值 (Boolean)
var o = { firstName: 123 } //物 件 (object)
// = 這個符號,不是數學上的等於喔,他代表 Assignment 

Number Operator

var x = 1;
x = x + 2;

console.log(x); // 3

x = x - 1;
console.log(x); // 2

x = x * 12;
console.log(x); // 24

x = x / 3;
console.log(x); // 8

x = x % 5; //取餘數
console.log(x); //3

String Operator

這邊我們嘗試將字串進行串接 (+)

var str = "Hello";
var blank = " ";
var world = "World";

var helloWorld = str + blank + world;
console.log(helloWorld); //Hello World

Condition and Loop

撰寫flow chart可以幫助我們釐清流程,而撰寫程式與撰寫flow chart是相同的
在程式的流程中,主要影響正個流程的走向有兩種不同的語法,分別稱為 Condition 跟Loop。

image


Condition

最常用的判斷語法為 if 判斷句

if (grade > 60)
{
    console.log("good");
}
else if (grade == 60)
{
    console.log("safe")
}
else
{
    console.log("nice to meet you.see you next year!");
}

Comparison Operators

• == (等於)
• != (不等於)
• > (大於)
• < (小於)
• >= (大於等於)
• <= (小於等於)

Switch

var day;

switch (new Date().getDay())
{ 
    case 0:
        day = "Sunday";
        break;
    case 1:
        day = "Monday";
        break;
    case 2:
        day = "Tuesday";
        break;
    case 3:
        day = "Wednesday";
        break;
    case 4:
        day = "Thursday";
        break;
    case 5:
        day = "Friday";
        break;
    case  6:
        day = "Saturday";
    default:
        day = "Unknown"; // 在這裡添加了 default,以處理未知的日期情況
}
console.log("Today is " + day);

While loop

var x = 1;

while(x <= 5)
{
    console.log(x);
    x = x + 1;
}

For loop

for(let i =1; i<=5 ;i++){
    console.log(i)
}

Javascript Html Input

接下來看看javascript要怎麼知道要怎麼知道使用者輸入了甚麼呢


HTML DOM(Document Object Model) Event

在 HTML 中,當使用者使用鍵盤或是滑鼠對 element 進行操作的時候,
element 會發出一個訊號,這個訊號中會記錄了使用者正在對 element 進行甚麼樣的操作。
例如,當我們用滑鼠點擊 element ,他會發出一個訊號說使用者使用滑鼠左鍵進行點擊。
因此在獲取使用者的輸入之前,我們要先取得我們要關注的 Html element 。


image


從Javascript中取得Html Element(getElementById)

在 Javascript 中,我們可以透過 Html Element 的 ID attribute 來取得 html 中的 element
HTML:

<div id="block" class="a"></div>

Javascript:

var x = document.getElementById("block");
console.log(x.id); //block
console.log(x.className); //a

聽取 Html 中發出的 Event(addEventListener)

<!--創建一個按鈕被點擊時輸出Click!!!-->
<!DOCTYPE html>
<html>
    <head>
        <title>addEventListener</title>
        <meta charset="utf-8">
    </head>
    <body>
        <input id="btn" type="button" value="Click!!!">
        <script>
            function clickHandler()
            {
                console.log("Click!!");
            }
            var button = document.getElementById("btn");
            button.addEventListener("click", clickHandler , false);
        </script>
    </body>
</html>

Html 是直譯式語言,因此我們 getElementById 一
定要寫在要取得的 element 之後,這也是為什麼這邊的 script element 寫在 body 最後的原因。


更改 Html 的內容

透過 getElementById 取得 Html element 之後,我們可以透過他更改 element 的各種attriubte 以及 element content

<!DOCTYPE html>
<html>
    <head>
        <title>change element content</title>
        <meta charset="utf-8">
    </head>
    <body>
        <input id="btn" type="button" value="Click!!!">
        <div id="board">
        </div>
        <script>
            function clickHandler()
            {
                var board = document.getElementById("board");
                board.innerHTML = "Click!!";
                board.style = "color: red;";
            }
            var button = document.getElementById("btn");
            button.addEventListener("click", clickHandler , false);
        </script>
    </body>
</html>

常用element object method

.id : 存取指定element的id。
.nodeName : 取得指定element的節點名稱,但是無法變更element。
.innerHTML : 取出指定element下所有的內容。
.textContent : 取出指定element下的content。


15puzzle.js

(function(){
	
	var state = 1;
	var puzzle = document.getElementById('puzzle');

	// Creates solved puzzle
	solve();
	
	// Listens for click on puzzle cells
	puzzle.addEventListener('click', function(e){
		if(state == 1){
			// Enables sliding animation
			puzzle.className = 'animate';
			shiftCell(e.target);
		}
	});
	
	// Listens for click on control buttons
	document.getElementById('solve').addEventListener('click', solve);
	document.getElementById('scramble').addEventListener('click', scramble);

	/*Creates solved puzzle*/
	function solve(){
		
		if(state == 0){
			return;
		}
		
		puzzle.innerHTML = '';
		
		var n = 1;
		for(var i = 0; i <= 3; i++){
			for(var j = 0; j <= 3; j++){
				var cell = document.createElement('span');
				cell.id = 'cell-'+i+'-'+j;
				cell.style.left = (j*80+1*j+1)+'px';
				cell.style.top = (i*80+1*i+1)+'px';
				
				if(n <= 15){
					cell.classList.add('number');
					cell.classList.add((i%2==0 && j%2>0 || i%2>0 && j%2==0) ? 'dark' : 'light');
					cell.innerHTML = (n++).toString();
				} else {
					cell.className = 'empty';
				}
				
				puzzle.appendChild(cell);
			}
		}
		
	}

	/*Shifts number cell to the empty cell*/
	function shiftCell(cell){
		
		// Checks if selected cell has number
		if(cell.clasName != 'empty'){
			
			// Tries to get empty adjacent cell
			var emptyCell = getEmptyAdjacentCell(cell);
			
			if(emptyCell){
				// Temporary data
				var tmp = {style: cell.style.cssText, id: cell.id};
				
				// Exchanges id and style values
				cell.style.cssText = emptyCell.style.cssText;
				cell.id = emptyCell.id;
				emptyCell.style.cssText = tmp.style;
				emptyCell.id = tmp.id;
				
				if(state == 1){
					// Checks the order of numbers
					setTimeout(checkOrder, 150);
				}
			}
		}
		
	}

	/*Gets specific cell by row and column*/
	function getCell(row, col){
	
		return document.getElementById('cell-'+row+'-'+col);
		
	}

	/*Gets empty cell*/
	function getEmptyCell(){
	
		return puzzle.querySelector('.empty');
			
	}
	
	/*Gets empty adjacent cell if it exists*/
	function getEmptyAdjacentCell(cell){
		
		// Gets all adjacent cells
		var adjacent = getAdjacentCells(cell);
		
		// Searches for empty cell
		for(var i = 0; i < adjacent.length; i++){
			if(adjacent[i].className == 'empty'){
				return adjacent[i];
			}
		}
		
		// Empty adjacent cell was not found
		return false;
		
	}

	/*Gets all adjacent cells*/
	function getAdjacentCells(cell){
		
		var id = cell.id.split('-');
		
		// Gets cell position indexes
		var row = parseInt(id[1]);
		var col = parseInt(id[2]);
		
		var adjacent = [];
		
		// Gets all possible adjacent cells
		if(row < 3){adjacent.push(getCell(row+1, col));}			
		if(row > 0){adjacent.push(getCell(row-1, col));}
		if(col < 3){adjacent.push(getCell(row, col+1));}
		if(col > 0){adjacent.push(getCell(row, col-1));}
		
		return adjacent;
		
	}
	
	/*Chechs if the order of numbers is correct*/
	function checkOrder(){
		
		// Checks if the empty cell is in correct position
		if(getCell(3, 3).className != 'empty'){
			return;
		}
	
		var n = 1;
		// Goes through all cells and checks numbers
		for(var i = 0; i <= 3; i++){
			for(var j = 0; j <= 3; j++){
				if(n <= 15 && getCell(i, j).innerHTML != n.toString()){
					// Order is not correct
					return;
				}
				n++;
			}
		}
		
		// Puzzle is solved, offers to scramble it
		if(confirm('Congrats, You did it! \nScramble the puzzle?')){
			scramble();
		}
	
	}

	/*Scrambles puzzle*/
	function scramble(){
	
		if(state == 0){
			return;
		}
		
		puzzle.removeAttribute('class');
		state = 0;
		
		var previousCell;
		var i = 1;
		var interval = setInterval(function(){
			if(i <= 100){
				var adjacent = getAdjacentCells(getEmptyCell());
				if(previousCell){
					for(var j = adjacent.length-1; j >= 0; j--){
						if(adjacent[j].innerHTML == previousCell.innerHTML){
							adjacent.splice(j, 1);
						}
					}
				}
				// Gets random adjacent cell and memorizes it for the next iteration
				previousCell = adjacent[rand(0, adjacent.length-1)];
				shiftCell(previousCell);
				i++;
			} else {
				clearInterval(interval);
				state = 1;
			}
		}, 5);

	}
	
	/*Generates random number*/
	function rand(from, to){

		return Math.floor(Math.random() * (to - from + 1)) + from;

	}

}());

Self-Executing Anonymous Function

匿名函數or立即函數,這個語法的目的是在定義函數之後立即執行它。

(function() {
  // 這裡是函數體,可以包含你想要執行的程式碼
}());

1.作用域隔離: 這個函數的所有變數和函數定義都將位於函數作用域內,不會污染全局作用域。

2.避免衝突: 在這個函數內,你可以使用相同的變數名稱而不擔心與全局作用域中的變數產生衝突。


var 和 let

  • Function Scope: var 屬於函數作用域(Function Scope),變數的作用範圍限於聲明它的函數內。
    在函數內聲明,在函數外也可以訪問
  • Block Scope: let 屬於區塊作用域(Block Scope),變數的作用範圍僅限於它所在的區塊(例如,if語句、for循環等)。

Lab Questions


Question 1

使用至少4種simple selector美化自我介紹網頁


Question 2

在我最喜歡的神奇寶貝頁面使用至少2個CSS box model


Question 3

畫出flow chart並在自我介紹頁面,設計一個按鈕,content為九九乘法表真好玩,
並在script加入連結.js檔使用javascript於console顯示九九乘法表的計算結果
奇數從1乘到9,偶數從9乘到1,完成後換行,兩個計算結果之間需要使用空白作為間隔
(使用巢狀迴圈完成該要求)


Question 4

於自我介紹頁面建立一個內部連接至新的分頁,另外選一隻神奇寶貝並加入退化、進化按鈕
點選進(退)化按鈕後由進化前型態變更為進(退)化後的資訊
需包含神奇寶貝名稱,圖片及數值表格(如Lab7所顯示資訊)


Question 5

製作一個9 puzzle game(字體、字塊顏色不可和16puzzle範例相同)
並在自我介紹網頁建立作品集 內部連結連結至9puzzle game網頁
image


作業網站

http://140.121.197.13/tutorial

Select a repo