1/** 2 * Bootstrap Vanilla JS Alternative 3 * æå°éã®Bootstrapæ©è½ãVanilla JSã§å®è£ 4 */ 5 6// Tooltipæ©è½ 7class SimpleTooltip { 8 constructor() { 9 this.init(); 10 } 11 12 init() { 13 // data-toggle="tooltip"ãæã¤è¦ç´ ãåå¾ 14 const tooltipElements = document.querySelectorAll('[data-toggle="tooltip"]'); 15 16 tooltipElements.forEach(element => { 17 this.setupTooltip(element); 18 }); 19 } 20 21 setupTooltip(element) { 22 let tooltip = null; 23 24 // ãã¦ã¹ã¨ã³ã¿ã¼æ 25 element.addEventListener('mouseenter', (e) => { 26 const title = element.getAttribute('title') || element.getAttribute('data-original-title'); 27 if (!title) return; 28 29 // æ¢åã®tooltipãåé¤ 30 this.removeTooltip(); 31 32 // æ°ããtooltipã使 33 tooltip = document.createElement('div'); 34 tooltip.className = 'tooltip fade in'; 35 tooltip.setAttribute('role', 'tooltip'); 36 37 const placement = element.getAttribute('data-placement') || 'top'; 38 tooltip.classList.add('tooltip-' + placement); 39 40 // tooltipã®å 容ãè¨å® 41 const tooltipInner = document.createElement('div'); 42 tooltipInner.className = 'tooltip-inner'; 43 tooltipInner.textContent = title; 44 45 const tooltipArrow = document.createElement('div'); 46 tooltipArrow.className = 'tooltip-arrow'; 47 48 tooltip.appendChild(tooltipArrow); 49 tooltip.appendChild(tooltipInner); 50 51 // bodyã«è¿½å 52 document.body.appendChild(tooltip); 53 54 // ä½ç½®ãè¨ç® 55 this.positionTooltip(element, tooltip, placement); 56 57 // originalã¿ã¤ãã«ãä¿åãã¦titleãåé¤ 58 if (element.getAttribute('title')) { 59 element.setAttribute('data-original-title', title); 60 element.removeAttribute('title'); 61 } 62 }); 63 64 // ãã¦ã¹ãªã¼ãæ 65 element.addEventListener('mouseleave', () => { 66 this.removeTooltip(); 67 }); 68 } 69 70 positionTooltip(element, tooltip, placement) { 71 const rect = element.getBoundingClientRect(); 72 const tooltipRect = tooltip.getBoundingClientRect(); 73 74 let top, left; 75 76 switch(placement) { 77 case 'top': 78 top = rect.top + window.scrollY - tooltipRect.height - 5; 79 left = rect.left + window.scrollX + (rect.width / 2) - (tooltipRect.width / 2); 80 break; 81 case 'bottom': 82 top = rect.bottom + window.scrollY + 5; 83 left = rect.left + window.scrollX + (rect.width / 2) - (tooltipRect.width / 2); 84 break; 85 case 'left': 86 top = rect.top + window.scrollY + (rect.height / 2) - (tooltipRect.height / 2); 87 left = rect.left + window.scrollX - tooltipRect.width - 5; 88 break; 89 case 'right': 90 top = rect.top + window.scrollY + (rect.height / 2) - (tooltipRect.height / 2); 91 left = rect.right + window.scrollX + 5; 92 break; 93 default: 94 top = rect.top + window.scrollY - tooltipRect.height - 5; 95 left = rect.left + window.scrollX + (rect.width / 2) - (tooltipRect.width / 2); 96 } 97 98 tooltip.style.top = top + 'px'; 99 tooltip.style.left = left + 'px'; 100 } 101 102 removeTooltip() { 103 const existingTooltip = document.querySelector('.tooltip'); 104 if (existingTooltip) { 105 existingTooltip.remove(); 106 } 107 } 108} 109 110// Alertæ©è½ï¼å¿ è¦ã«å¿ãã¦ï¼ 111class SimpleAlert { 112 constructor() { 113 this.init(); 114 } 115 116 init() { 117 // data-dismiss="alert"ãæã¤è¦ç´ ãåå¾ 118 document.addEventListener('click', (e) => { 119 if (e.target.getAttribute('data-dismiss') === 'alert') { 120 const alert = e.target.closest('.alert'); 121 if (alert) { 122 alert.style.opacity = '0'; 123 setTimeout(() => { 124 alert.remove(); 125 }, 150); 126 } 127 } 128 }); 129 } 130} 131 132// Collapseæ©è½ï¼å¿ è¦ã«å¿ãã¦ï¼ 133class SimpleCollapse { 134 constructor() { 135 this.init(); 136 } 137 138 init() { 139 document.addEventListener('click', (e) => { 140 if (e.target.getAttribute('data-toggle') === 'collapse') { 141 e.preventDefault(); 142 const targetSelector = e.target.getAttribute('data-target') || e.target.getAttribute('href');
143 const target = document.querySelector(targetSelector); 144 145 if (target) { 146 this.toggle(target); 147 } 148 } 149 }); 150 } 151 152 toggle(element) { 153 if (element.style.display === 'none' || !element.style.display) { 154 element.style.display = 'block'; 155 element.classList.add('in'); 156 } else { 157 element.style.display = 'none'; 158 element.classList.remove('in'); 159 } 160 } 161} 162 163// åæå 164document.addEventListener('DOMContentLoaded', () => { 165 new SimpleTooltip(); 166 new SimpleAlert(); 167 new SimpleCollapse(); 168}); 169 170// åçã«è¿½å ãããè¦ç´ ã«ãå¯¾å¿ 171const observer = new MutationObserver(() => { 172 new SimpleTooltip(); 173}); 174 175observer.observe(document.body, { 176 childList: true, 177 subtree: true 178});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.