目前來說進行專案還都主要以 Bootstrap 4 版本為主,透過專案的需求要做出提示功能,正好利用這個機會多了解 Bootstrap 5 版使用 JavaScript 原生 Vanilla.js 寫法。
Bootstarp Popovers 官方文件連結:英文、中文。
起手式
CDN 引入相關連結
1 2 3 4 5 6 7 8 9 10 11 | <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous" /> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous" ></script> |
在任何地方啟用彈出提示框 (操作全部 [data-bs-toggle=”popover”] 屬性)
1 2 3 4 | var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')) var popoverList = popoverTriggerList.map(function (popoverTriggerEl) { return new bootstrap.Popover(popoverTriggerEl) }) |
類陣列的處理
類陣列 (Array-Likes) 主要是由多個選定 DOM 元素所產生的結構,與純陣列的呈現方式有點像,但最大的差別就是 __prototype__ 下的操作陣列方法較少,在 Bootstrap 的官方文件才透過 [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')) 將類陣列轉換成存陣列結構。
先以 Bootstrap 官方文件中的四個方向 Popover 為例,取用四個按鈕為操作對象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" data-bs-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus."> Popover on top </button> <button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="right" data-bs-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus."> Popover on right </button> <button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="bottom" data-bs-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus."> Popover on bottom </button> <button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="left" data-bs-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus."> Popover on left </button> |
1 2 | let getAllPopoverNodelist = document.querySelectorAll('[data-bs-toggle="popover"]'); console.log('getAllPopoverNodelist', getAllPopoverNodelist); // NodeList(4) |
上面程式碼的部份,主要是要用來看類陣列與存陣列的差別,首先先將 getAllPopoverNodelist 展開查看,此時會發現類陣列 NodeList(4) 的下方 __prototye__ 可使用的相關方法很少,像是常用的陣列方法 .map() 是沒有列在裡面。
[].slice.call(arguments) 將類陣列轉換成為純陣列元素
1 2 3 4 5 | let popoverTriggerList = [].slice.call(getAllPopoverNodelist); // 官方文件轉換陣列寫法 console.log('popoverTriggerList', popoverTriggerList); // Array(4) let getAllPopoverNodelistToArray = [...getAllPopoverNodelist]; // 使用展開陣列寫法 console.log('getAllPopoverNodelistToArray', getAllPopoverNodelistToArray); // Array(4) |
[].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
將對象有 data-bs-toggle="popover" 屬性的元素取出當成參數,取出後會是個類陣列。
查看轉換成將 Node List 轉換成 DOM 元素的陣列後,展開的 __prototye__ 可見到相關的陣列方法會比較多。
將類陣列轉換成陣列元素,除了使用 [].slice.call() 外,也可以透過 [...<Node List>] 處理轉換。
參考資料:
BootStrp 5 DOM 元素類陣列與陣列操作
See the Pen BootStrp 5 – DOM 元素類陣列與陣列操作與 Popover 在任何地方啟用彈出提示框 by Jimmy_Wu (@Jimmy_Wu) on CodePen.
另外這裡提,選 DOM 元素 document.querySelectorAll('[data-bs-toggle="popover"]') 方式裡面有 .forEach() 的陣列方法,實際以迴圈執行建構新的 Popover 物件 ( new bootstrap.Popover(<建構綁定元素對象>)),也確實沒問題。
指定單一元素對象建構 Popover
單一元素對象基本建構 Popover
除了透過 document.querySelectorAll('[data-bs-toggle="popover"]') 一次選取 DOM 結構中所有的元素中有 data-bs-toggle="popover" 屬性的對象元素外,另外也可以直接指定單一對象進行操作,下面是直接以 JavaScript 透過 document.getElementById('example') 選取對象將 <a id="example"> 連結標籤為 Popover 建構綁定對象,指定好綁定對象後自然也可以透過 Popover 的方法進行動態操作。
1 2 3 4 5 6 7 8 9 10 11 | <a id="example" tabindex="0" class="btn btn-lg btn-danger" role="button" title="Dismissible popover" data-bs-toggle="popover" data-bs-content="And here's some amazing content. It's very engaging. Right?" > Dismissible popover </a> |
1 2 | let examplePopover = new bootstrap.Popover(document.getElementById('example')); console.log('examplePopover', examplePopover); // 綁定 example 按鈕為觸發對象,Popover 功能以建構式產生一個物件 |
透過 console.log('examplePopover', examplePopover) 查看,會在開發者工具上回應是一個 Object {} 物件,這樣的方式就是指透過 new bootstrap.Popover() 建構函式已建立出一個 Popover 物件出來並賦予在 examplePopover 變數上,這樣就可以針對 <a id="example"> 連結標籤點按操作。
See the Pen BootStrp 5 Popover-指定單一元素對象建構 Popover by Jimmy_Wu (@Jimmy_Wu) on CodePen.
Popover 建構後的方法操作
賦予在 examplePopover 變數上之後就成為 Popover 物件,賦予之變數後就可以進行 Popover 的相關方法進行操作,下面是透過 .show() 方法,直接在建構後做 Popover 畫面顯示,另外透過 setTimeout() 的回呼函式於三秒後直接於畫面中自動關閉 Popover。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | let examplePopover = new bootstrap.Popover(document.getElementById('example')); console.log('examplePopover', examplePopover); // 綁定 example 按鈕為觸發對象,Popover 功能以建構式產生一個物件 function PopoverPlayFn() { examplePopover.show(); // 顯示 Popover setTimeout(() => { examplePopover.hide(); }, 3000); // 三秒後關閉 Popover } PopoverPlayFn(); // 直接執行觸發畫面顯示於三秒後自動關閉 // 點按按鈕後觸發畫面顯示於三秒後自動關閉 document.getElementById('rePlayBtn').onclick = function() { PopoverPlayFn(); }; |
See the Pen BootStrp 5 Popover-指定單一元素對象建構 Popover 建構後做畫面顯示於三秒後自動關閉 by Jimmy_Wu (@Jimmy_Wu) on CodePen.
Popover 客製化
在 Bootstrap 5 文件中的 用法 > 選項 > template 設定中提到,可以透過此方法客製 Popover 的 HTML 結構。
可客製樣版但有的元素還是無法插入使用,像是 <a href="#"></a> 的部份屬性如 href="#" 會無法帶出於樣版,另外還有 <button></button> 元素無法直接括入 Popover 樣版使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <div class="container u-pt-150px pb-5 text-center"> <button type="button" class="btn btn-secondary" title="Popover Title - 1" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" data-bs-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus."> Popover on top </button> <button type="button" class="btn btn-secondary" title="Popover Title - 2" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="right" data-bs-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus."> Popover on right </button> <button type="button" class="btn btn-secondary" title="Popover Title - 3" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="bottom" data-bs-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus."> Popover on bottom </button> <button type="button" class="btn btn-secondary" title="Popover Title - 4" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="left" data-bs-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus."> Popover on left </button> </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | .c-popoverArrow--dark { &.bs-popover-top > .popover-arrow::before { border-top-color: rgba(0,0,0,1); } &.bs-popover-end > .popover-arrow::before { border-right-color: rgba(0,0,0,1); } &.bs-popover-start > .popover-arrow::before { border-left-color: rgba(0,0,0,1); } &.bs-popover-bottom { & > .popover-arrow { &::before { border-bottom-color: rgba(0,0,0,1); } &::after { border-bottom-color: rgba(0,0,0,1); } } } & .popover-header::before { border-bottom: 1px solid rgba(0,0,0,1); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | document.querySelectorAll('[data-bs-toggle="popover"]') .forEach((item, i)=>{ // console.log(`allPopoverEL.forEach (item, ${i})`, item); // 綁定對象觸發按鈕 // itemPopoverObj 為 Popover 實體化對象 let itemPopoverObj = new bootstrap.Popover(item, { template: ` <div class="popover border-dark c-popoverArrow--dark" role="tooltip"> <div class="popover-arrow"></div> <h3 class="popover-header border-dark bg-dark text-white"></h3> <div class="popover-body border-dark"></div> </div>`, }); }); |
- 在 Popover 綁定的按鈕上加上 title="Popover Title - n" 啟用 popover-header 的結構。
- 在 bootstrap.Popover() 實體化後,帶入第二個物件設定參數,裡面的屬性 template 使用樣版字面值處理 HTML 樣版結構。
- HTML 樣版中除了使用 Bootstrap 的工具類樣式外,也使用 .c-popoverArrow--dark 擴充黑色 popover-header 結構的 tip 箭頭樣式。
See the Pen BootStrp 5 Popover-Popover 客製化 by Jimmy_Wu (@Jimmy_Wu) on CodePen.
補充資料
JavaScript 與 jQuery 選取元素方法
jQuery 會慢慢的不使用於各框架中,習慣了方便的使用方式,但還是需要以原生 JavaScript 寫法為主。
1 2 3 4 5 6 7 8 | var a = document.getElementById("dom"); del_space(a); //清理空格 var b = a.childNodes; //獲取a的全部子節點; var c = a.parentNode; //獲取a的父節點; var d = a.nextSibling; //獲取a的下一個兄弟節點 var e = a.previousSibling; //獲取a的上一個兄弟節點 var f = a.firstChild; //獲取a的第一個子節點 var g = a.lastChild; //獲取a的最後一個子節點 |
1 2 3 4 5 6 7 8 9 10 | jQuery.parent(expr) //找父親節點,可以傳入expr進行過濾,比如$("span").parent()或者$("span").parent(".class") jQuery.parents(expr) //類似於jQuery.parents(expr),但是是查找所有祖先元素,不限於父元素 jQuery.children(expr) //返回所有子節點,這個方法只會返回直接的孩子節點,不會返回所有的子孫節點 jQuery.contents() //返回下面的所有內容,包括節點和文本。這個方法和children()的區別就在於,包括空白文本,也會被作為一個jQuery對象返回,children()則只會返回節點 jQuery.prev() //返回上一個兄弟節點,不是所有的兄弟節點 jQuery.prevAll() //返回所有之前的兄弟節點 jQuery.next() //返回下一個兄弟節點,不是所有的兄弟節點 jQuery.nextAll() //返回所有之後的兄弟節點 jQuery.siblings() //返回兄弟姐妹節點,不分前後 jQuery.find(expr) //跟jQuery.filter(expr)完全不一樣。jQuery.filter()是從初始的jQuery對象集合中篩選出一部分,而jQuery.find()的返回結果,不會有初始集合中的內容,比如$("p"),find("span"),是從p元素開始找,等同於$("p span"). |