Part 7 JavaScript – 主題(theme)的更新
學習資源:
- 最新源碼下載(2021/3/3) 源碼跟內文不一致,請從頭到尾跟著最新源碼做。(內文一直沒有時間更新)
- 目前的程式示範連結:index-7-1.html
這個單元學習,我們要透過”Change Theme”按鈕叫出色彩選擇對話框。
在此之前,我們先做一件事,我們在顯示日期的序數詞時,忽略掉一件事,上標的字體大小應該變小(一般來說),
我們針對<sup>元素進行css格式設定:
<style media="screen"> sup { font-size: 50%; } </style>
設定上標文字的大小比例為50%。測試沒問題後,將此css格式設定移至先前的css/main.css。
我們在第3個單元學習中,已經把對話方塊寫好了,然後用closed的設定將對話方塊進行關閉,這個對話方塊有2個子元件:fav-color與make-note:
我們可用手動的方式將closed這個設定去除掉,此時,你會發現整個畫面依照在第3單元學習會進入灰暗顯示,接著,把fav-color裏的hidden設定去除掉,此時,我們設計的色彩選擇對話方塊就會顯示在畫面的正中間:
我們先做個程式練習,將modal這個對話框架方塊打開,以及將fav-color這個對話的hidden屬性去除掉:
<script language="JavaScript"> updateData(); //更新日期相關資料 var modal = document.getElementById("modal"); modal.open = true; var template = document.getElementById("fav-color"); template.removeAttribute("hidden"); </script>
我們在更新月曆畫面/表格後,加上上面4行直接打開色彩選擇的對話。
2021/10/07註記:
一個DOM元素物件的無值的屬性(例:在月曆這個應用中,HTML標籤裏的open、hidden)可以透過指定true或false的方式加入到tag裏或從tag裏移除,比用setAttribute與 removeAtrribute更簡單:
// 打開色彩主題的對話方塊 function openFavColor(){ let modal = document.getElementById("modal"); modal.open = true; //為modal元素加上一個沒有值的open屬性 let template = document.getElementById("fav-color"); // template.removeAttribute("hidden"); template.hidden = false; //為template元素移除掉一個hidden屬性 } // 關閉色彩主題的對話方塊 function closeFavColor(){ let modal = document.getElementById("modal"); modal.open = false; let template = document.getElementById("fav-color"); // template.setAttribute("hidden", ""); template.hidden = true; }
上面只是個測試,上面的動作必須透過按鈕”Change Theme”點擊來觸發,加入onClick事件指定(我們的月曆App有2個Change Theme按鈕,一個是landscape,一個是portrait:
<button id="theme-landscape" class="font button" onclick="openFavColor();">Change theme</button>
<button id="theme-portrait" class="font button color" onclick="openFavColor();">Change theme</button>
把開啟modal與fav-color的4行程式包裝在openFavColor(),搭配上面的函式呼叫,於是,我們完成了點擊”Change Theme”按鈕後,打開色彩選擇對話。
<script language="JavaScript"> updateData(); //更新日期相關資料 function openFavColor(){ var modal = document.getElementById("modal"); modal.open = true; var template = document.getElementById("fav-color"); template.removeAttribute("hidden"); } </script>
接著,我們要透過”Update”這個按鈕來關閉色彩選擇對話方塊:
1.changeColor方法
<script language="JavaScript"> updateData(); //更新日期相關資料 function openFavColor(){ var modal = document.getElementById("modal"); modal.open = true; var template = document.getElementById("fav-color"); template.removeAttribute("hidden"); } function changeColor(){ var modal = document.getElementById("modal"); modal.open = false; var template = document.getElementById("fav-color"); template.setAttribute("hidden", "hidden"); } </script>
2.Update按鈕事件
<button id="update-theme-button" class="button font" onclick="changeColor();">Update</button>
Fade in and out
JavaScript: fadeIn() and fadeOut() without jQuery
(待增加對話方塊淡入與淡出特性)
目前的程式連結:index-7-2.html
勾選功能
勾選表示在一開始進行設計的時候,我們是第1個顏色-藍色加上一個元素 <i class=”fas fa-check checkmark”></i>
<div class="color-option"> <div class="color-preview" id="blue" style="background-color: #1B19CD;"><i class="fas fa-check checkmark"></i></div> <h5>Blue</h5> </div>
撰寫addCheckMark方法
function addCheckMark(color_name){ var colorPreviews = document.getElementsByClassName("color-preview"); for (let i = 0; i < colorPreviews.length; i++){ if (colorPreviews[i].id == color_name) { console.log(colorPreviews[i].id + "," + color_name) colorPreviews[i].innerHTML = "<i class='fas fa-check checkmark'></i>"; } } }
上面這個方法先透過document.getElementsByClassName(“color-preview”)取得所有div類別名稱有”color-preview”的元素,由於文檔裏有多個元素都有同樣的類別名稱,所以此敘述會回傳一個元素的物件集合,此物件名稱我們命名為colorPreviews。
接著,我們用一個for迴圈走訪colorPreviews這個集合物件,比對裏面的每一個物件是否其id名稱(也就是個別的顏色名稱)是否跟這個方法所接收到的color_name值相同,相同的話,我們就將 <i class=”fas fa-check checkmark”></i>元素加入。
2022/07/26新增改寫(較簡單)
function addCheckMark(color_name){ let color_block = document.getElementById(color_name); if (color_block) color_block.innerHTML = '<i class="fas fa-check checkmark"></i>'; }
測試畫面如下:
邏輯上,我們要加上勾選符號時,應先將原本的勾選符號除掉,再加上新的勾選。
addCheckMark方法修改如下:
function addCheckMark(color_name){ // alert("你按了" + color_name + " DIV"); //清除/移除類別有"checkmark"的元素,也就是清除掉勾選的顯示 var checkmarks = document.getElementsByClassName("checkmark"); //找到有勾選符號的元素,以單選來說,整個有勾選符號的元素只會有一個 checkmarks[0].parentNode.innerHTML = ""; //加上勾選的顯示 var colorPreviews = document.getElementsByClassName("color-preview"); for (let i = 0; i < colorPreviews.length; i++){ //走訪12個有class=color-preview的元素 if (colorPreviews[i].id == color_name) { //Bingo colorPreviews[i].innerHTML = "<i class='fas fa-check checkmark'></i>"; break; //中斷/跳開for迴圈,Bingo之後,後面的元素就不用再比對了! } } }
2022/07/26新增改寫(較簡單)
function addCheckMark(color_name){ let color_blocks = document.getElementsByClassName("color-preview"); for (i = 0; i < color_blocks.length ; i++ ) color_blocks[i].innerHTML = ""; let color_block = document.getElementById(color_name); if (color_block) color_block.innerHTML = '<i class="fas fa-check checkmark"></i>'; }
目前的程式連結:index-7-3.html
接下來,我們要根據所選的顏色,按下Update按鈕後,進行顏色的變換。
步驟大概為:
1.取得勾選的色彩名稱
我們在程式裏設置一個全域物件變數currentColor,然後使用者勾選色彩時,會呼叫addCheckMark(color_name),其中color_name就是我們選取的色彩名稱,我們只要在這個函式裏面把color_name指定給currentColor.name就行了。
var currentColor = { name : "blue", color : "#1B19CD", off_color : "#7c7EFB" }; //用來紀錄目前主題的色彩名稱、色彩編碼 function addCheckMark(color_name){ currentColor.name = color_name; //將勾選的色彩名稱color_name指定給全域變數currentColorName,以便在changeColor方法裏使用,來設定整個主題的色彩。 var checkmarks = document.getElementsByClassName("checkmark"); for(var i = 0; i < checkmarks.length; i++){ checkmarks[i].parentNode.removeChild(checkmarks[i]); } var colorPreviews = document.getElementsByClassName("color-preview"); for (var i = 0; i < colorPreviews.length; i++){ if (colorPreviews[i].id == color_name) { console.log(colorPreviews[i].id + "," + color_name + "," + currentColor.name) colorPreviews[i].innerHTML = "<i class='fas fa-check checkmark'></i>"; } } }
2.用currentColor.name一個一個比對color_data陣列裏的色彩名稱,並從中取出色彩碼(color與off color)。
3.將整個月曆color、border-color與off-color用上面步驟取出的色碼進行色彩設定。
<script src="js/updateData.js"></script> <script language="JavaScript"> var currentColor = { name : "blue", color : "#1B19CD", off_color : "#7c7EFB" }; var color_data = [ { name: 'blue', color_code: '#1B19CD', off_color_code: '#7C7EFB' }, { name: 'red', color_code: '#D01212', off_color_code: '#EEA19B' }, { name: 'purple', color_code: '#721D89', off_color_code: '#EBADFB' }, { name: 'green', color_code: '#158348', off_color_code: '#57C664' }, { name: 'orange', color_code: '#EE742D', off_color_code: '#F7A77A' }, { name: 'deep-orange', color_code: '#F13C26', off_color_code: '#F77D59' }, { name: 'baby-blue', color_code: '#31B2FC', off_color_code: '#3D8DD9' }, { name: 'cerise', color_code: '#EA3D69', off_color_code: '#FCBECC' }, { name: 'lime', color_code: '#2ACC32', off_color_code: '#4FFA4F' }, { name: 'teal', color_code: '#2FCCB9', off_color_code: '#7FE7E3' }, { name: 'pink', color_code: '#F50D7A', off_color_code: '#FFB9EA' }, { name: 'black', color_code: '#212524', off_color_code: '#687E7B' } ]; updateData(); //更新日期相關資料 //用來紀錄目前主題的色彩名稱、色彩編碼 function addCheckMark(color_name){ currentColor.name = color_name; //將勾選的色彩名稱color_name指定給全域變數currentColorName,以便在changeColor方法裏使用,來設定整個主題的色彩。 var checkmarks = document.getElementsByClassName("checkmark"); for(var i = 0; i < checkmarks.length; i++){ checkmarks[i].parentNode.removeChild(checkmarks[i]); } var colorPreviews = document.getElementsByClassName("color-preview"); for (var i = 0; i < colorPreviews.length; i++){ if (colorPreviews[i].id == color_name) { console.log(colorPreviews[i].id + "," + color_name + "," + currentColor.name) colorPreviews[i].innerHTML = "<i class='fas fa-check checkmark'></i>"; } } } function openFavColor(){ var modal = document.getElementById("modal"); modal.open = true; modal.classList.add("fade-in"); //淡入效果 var template = document.getElementById("fav-color"); template.removeAttribute("hidden"); } function changeColor(){ //第1步:先找出勾選色彩所設定的色碼 console.log(currentColor.name) color_data.forEach(function(arr_data){ //陣列的走訪,每走訪一個陣列元素,帶出的元素以arr_data變數呈現(arr_data我們自取的名稱) if(currentColor.name == arr_data.name){ //找到color_data陣列中符合的色彩, currentColor.color = arr_data.color_code; currentColor.off_color = arr_data.off_color_code; } }); var elements; //先清除掉所有的style設置(td) elements = document.getElementsByTagName("td"); for(let i=0; i < elements.length; i++) { elements[i].style = null; } //改變目前的色彩設置 elements = document.getElementsByClassName("color"); for(let i=0; i < elements.length; i++) { elements[i].style.backgroundColor = currentColor.color; } elements = document.getElementsByClassName("border-color"); for(let i=0; i < elements.length; i++) { elements[i].style.borderColor = currentColor.color; } elements = document.getElementsByClassName("off-color"); for(let i=0; i < elements.length; i++) { elements[i].style.color = currentColor.off_color; } //關閉對話方塊 var modal = document.getElementById("modal"); modal.open = false; modal.classList.remove("fade-out"); //淡出效果 var template = document.getElementById("fav-color"); template.setAttribute("hidden", "hidden"); } </script>
另外,在fillInMonth()方法最後一行,加上:
changeColor();
填完表格,應該要再重新上一次色(changeColor();)。
最後,就是把這部份的功能放到新的的js/changeTheme.js,另外把轉場的css格式移入css/main.css。
最後的程式連結:Part-7