1class Typography { 2 constructor(container, initialIndexes, createCookie, iframe, sendMessageToIframe=false) 3 { 4 this.container = container; 5 this.createCookie = createCookie; 6 7 this.fontSize = {}; 8 this.fontSize.base = 17; 9 this.fontSize.options = [1, 1.1, 1.2, 1.35, 1.5]; 10 11 this.lineHeight = {}; 12 this.lineHeight.options = [1, 1.1, 1.2, 1.3]; 13 14 this.letterSpacing = {}; 15 this.letterSpacing.options = [0, 0.05, 0.1, 0.15, 0.2]; 16 17 this.cursorSize = {}; 18 this.cursorSize.options = [ 0, 1, 2, 3]; 19 20 this.fontFamily = {}; 21 this.fontFamily.options = ['default', 'sans', 'serif']; 22 23 this.defaultValues = { 24 'fontSize': 1, 25 'lineHeight': 1, 26 'letterSpacing': 0, 27 'cursorSize': 0, 28 'fontFamily': 'default' 29 }; 30 this.units = { 31 'fontSize': 'px', 32 'lineHeight': '', 33 'letterSpacing': 'em', 34 'cursorSize': '', 35 'fontFamily': '' 36 }; 37 this.initialIndexes = initialIndexes; 38 this.elements = {}; 39 this.iframe = iframe; 40 // this.sendMessageToIframe = sendMessageToIframe ? ; 41 this.clone = []; 42 this.checkClickOutside = this.checkClickOutside.bind(this); 43 this.init(); 44 45 } 46 init(){ 47 this.renderElements(); 48 this.getElements(); 49 this.addListeners(); 50 this.initIndex(); 51 this.adjustWrapperPosition(); 52 window.addEventListener('resize', function(){ 53 this.adjustWrapperPosition(); 54 }.bind(this)); 55 } 56 57 renderElements(){ 58 let icon = document.createElement('DIV'); 59 icon.className = 'typography menu-icon sans menu-text-icon'; 60 icon.innerHTML = '<span>A</span>'; 61 let wrapper = document.createElement('DIV'); 62 wrapper.className = 'typography-menu-wrapper'; 63 let wrapper_html = ''; 64 wrapper_html += '<div class="typography-menu-section typography-menu-font-size"><div class="typography-menu-section-head">Size</div><div class="decrease-font-size typography-control-btn pointer">−</div><div class="increase-font-size typography-control-btn pointer">+</div></div>'; 65 wrapper_html += '<div class="typography-menu-section typography-menu-line-height"><div class="typography-menu-section-head">Line height</div><div class="decrease-line-height typography-control-btn pointer">−</div><div class="increase-line-height typography-control-btn pointer">+</div></div>'; 66 wrapper_html += '<div class="typography-menu-section typography-menu-letter-spacing"><div class="typography-menu-section-head">Letter spacing</div><div class="decrease-letter-spacing typography-control-btn pointer">−</div><div class="increase-letter-spacing typography-control-btn pointer">+</div></div>'; 67 wrapper_html += '<div class="typography-menu-section typography-menu-cursor-size"><div class="typography-menu-section-head">Cursor size</div><div class="decrease-cursor-size typography-control-btn pointer">−</div><div class="increase-cursor-size typography-control-btn pointer">+</div></div>'; 68 wrapper_html += '<div class="typography-menu-section typography-menu-font-family"><div class="psuedo-label">Sans</div><input id="font-family-sans" class="font-family-option" type="checkbox" value="1"><label class="pointer" button-type="slider" for="font-family-sans"></label></div>'; 69 wrapper_html += '<div class="typography-menu-section typography-menu-font-family"><div class="psuedo-label">Serif</div><input id="font-family-serif" class="font-family-option" type="checkbox" value="2"><label class="pointer" button-type="slider" for="font-family-serif"></label></div>'; 70 wrapper_html += '<div class="typography-menu-section typography-menu-reset typography-control-btn pointer border-btn">Reset</div>'; 71 wrapper.innerHTML = wrapper_html; 72 this.container.appendChild(icon); 73 let parent = document.querySelector("#main-container") ? document.querySelector("#main-container") : document.body; 74 parent.appendChild(wrapper); 75 this.elements.wrapper = wrapper; 76 } 77 getElements(){ 78 this.elements.icon = this.container.querySelector('.menu-icon.typography'); 79 this.elements.fontSize = {}; 80 this.elements.fontSize.increase = this.elements.wrapper.querySelector('.increase-font-size'); 81 this.elements.fontSize.decrease = this.elements.wrapper.querySelector('.decrease-font-size'); 82 this.elements.lineHeight = {}; 83 this.elements.lineHeight.increase = this.elements.wrapper.querySelector('.increase-line-height'); 84 this.elements.lineHeight.decrease = this.elements.wrapper.querySelector('.decrease-line-height'); 85 this.elements.letterSpacing = {}; 86 this.elements.letterSpacing.increase = this.elements.wrapper.querySelector('.increase-letter-spacing'); 87 this.elements.letterSpacing.decrease = this.elements.wrapper.querySelector('.decrease-letter-spacing'); 88 this.elements.cursorSize = {}; 89 this.elements.cursorSize.increase = this.elements.wrapper.querySelector('.increase-cursor-size'); 90 this.elements.cursorSize.decrease = this.elements.wrapper.querySelector('.decrease-cursor-size'); 91 92 this.elements.fontOptions = document.getElementsByClassName('font-family-option'); 93 94 this.elements.reset = this.elements.wrapper.querySelector('.typography-menu-reset'); 95 } 96 97 addListeners(){ 98 this.elements.icon.addEventListener('click', function(e){ 99 this.toggleMenu(e); 100 }.bind(this)); 101 this.elements.fontSize.increase.addEventListener('click', function(){ 102 this.increaseFontSize(); 103 }.bind(this)); 104 this.elements.fontSize.decrease.addEventListener('click', function(){ 105 this.decreaseFontSize(); 106 }.bind(this)); 107 this.elements.lineHeight.increase.addEventListener('click', function(){ 108 this.increaseLineHeight(); 109 }.bind(this)); 110 this.elements.lineHeight.decrease.addEventListener('click', function(){ 111 this.decreaseLineHeight(); 112 }.bind(this)); 113 this.elements.letterSpacing.increase.addEventListener('click', function(){ 114 this.increaseLetterSpacing(); 115 }.bind(this)); 116 this.elements.letterSpacing.decrease.addEventListener('click', function(){ 117 this.decreaseLetterSpacing(); 118 }.bind(this)); 119 this.elements.cursorSize.increase.addEventListener('click', function(){ 120 this.increaseCursorSize(); 121 }.bind(this)); 122 this.elements.cursorSize.decrease.addEventListener('click', function(){ 123 this.decreaseCursorSize(); 124 }.bind(this)); 125 for(let i = 0; i < this.elements.fontOptions.length; i++) 126 { 127 this.elements.fontOptions[i].addEventListener('click', function(event){ 128 if(event.target.checked) { 129 this.updateFontFamily(event.target.value); 130 for(let j = 0; j< this.elements.fontOptions.length; j++) 131 { 132 if(j == i || !this.elements.fontOptions[j].checked) continue; 133 this.elements.fontOptions[j].checked = false;
134 } 135 } 136 else { 137 this.updateFontFamily(0); 138 } 139 }.bind(this)); 140 } 141 142 this.elements.reset.addEventListener('click', function(){ 143 this.reset(); 144 }.bind(this)); 145 } 146 initIndex(){ 147 for(let prop in this.initialIndexes) 148 { 149 // console.log(prop); 150 151 let idx = parseInt(this.initialIndexes[prop]); 152 idx = idx !== null && typeof this[prop]['options'][idx] != 'undefined' ? idx : this.getIdxByValue(this.defaultValues[prop], this[prop].options) 153 this[prop].currentIndex = idx; 154 } 155 this.updateFontSize(this.fontSize.currentIndex); 156 this.updateLineHeight(this.lineHeight.currentIndex); 157 this.updateLetterSpacing(this.letterSpacing.currentIndex); 158 this.updateCursorSize(this.cursorSize.currentIndex); 159 this.updateFontFamily(this.fontFamily.currentIndex); 160 } 161 162 getIdxByValue(search, options){ 163 for(let i = 0; i <= options.length; i++) 164 { 165 if(options[i] === search) { 166 return i; 167 } 168 } 169 return false; 170 } 171 172 toggleMenu(event){ 173 if( !event.target.classList.contains("menu-icon") && event.target.tagName !== "SPAN") return; 174 document.body.classList.toggle('viewing-typography-menu'); 175 if(document.body.classList.contains('viewing-typography-menu')){ 176 setTimeout(()=>{ 177 window.addEventListener('click', this.checkClickOutside); 178 }, 0) 179 } 180 else{ 181 window.removeEventListener('click', this.checkClickOutside); 182 } 183 } 184 185 increaseIndex(property, elements){ 186 if( property.currentIndex >= property.options.length - 1 ) return property.currentIndex; 187 return property.currentIndex + 1; 188 } 189 190 decreaseIndex(property, elements){ 191 if( property.currentIndex == 0 ) return property.currentIndex; 192 return property.currentIndex - 1; 193 } 194 195 increaseFontSize(){ 196 this.fontSize.currentIndex = this.increaseIndex(this.fontSize, this.elements.fontSize); 197 this.updateFontSize(this.fontSize.currentIndex); 198 } 199 decreaseFontSize(){ 200 this.fontSize.currentIndex = this.decreaseIndex(this.fontSize, this.elements.fontSize); 201 this.updateFontSize(this.fontSize.currentIndex); 202 } 203 204 increaseLineHeight(){ 205 if( this.lineHeight.currentIndex == this.lineHeight.options.length - 1 ) return; 206 this.lineHeight.currentIndex ++; 207 this.updateLineHeight(this.lineHeight.currentIndex); 208 } 209 decreaseLineHeight(){ 210 if( this.lineHeight.currentIndex == 0 ) return; 211 this.lineHeight.currentIndex --; 212 this.updateLineHeight(this.lineHeight.currentIndex); 213 } 214 increaseLetterSpacing(){ 215 if( this.letterSpacing.currentIndex == this.letterSpacing.options.length - 1 ) return; 216 this.letterSpacing.currentIndex ++; 217 this.updateLetterSpacing(this.letterSpacing.currentIndex); 218 } 219 decreaseLetterSpacing(){ 220 if( this.letterSpacing.currentIndex == 0 ) return; 221 this.letterSpacing.currentIndex --; 222 this.updateLetterSpacing(this.letterSpacing.currentIndex); 223 } 224 increaseCursorSize(){ 225 if( this.cursorSize.currentIndex == this.cursorSize.options.length - 1 ) return; 226 this.cursorSize.currentIndex ++; 227 this.updateCursorSize(this.cursorSize.currentIndex); 228 } 229 decreaseCursorSize(){ 230 231 if( this.cursorSize.currentIndex == 0 ) return; 232 this.cursorSize.currentIndex --; 233 this.updateCursorSize(this.cursorSize.currentIndex); 234 } 235 // toggleDia(){ 236 // this.fontFamily = this.fontFamily == 'dia' ? 'default' : 'dia'; 237 // console.log('toggleDia(): ' + this.fontFamily); 238 // // if(this.fontFamily == 'default') this.elements.diaToggle.checked = false; 239 // this.updateFontFamily(this.fontFamily); 240 // } 241 // toggleSerif(){ 242 // this.fontFamily = this.fontFamily == 'serif' ? 'default' : 'serif'; 243 // // if(this.fontFamily == 'default') this.elements.serifToggle.checked = false; 244 // this.updateFontFamily(this.fontFamily); 245 // } 246 sendMessageToIframe(target, message){ 247 target.contentWindow.postMessage( JSON.stringify(message), '*'); 248 } 249 updateFontSize(idx){ 250 this.checkBtnAvailability(idx, this.fontSize.options, this.elements.fontSize); 251 let value = this.fontSize.options[idx]; 252 if(value == undefined) return; 253 value = this.fontSize.base * value + this.units['fontSize']; 254 document.body.style.setProperty('--font-size', value); 255 this.createCookie('ica-fontSize', value); 256 this.createCookie('ica-fontSize-index', idx); 257 if (!this.iframe || !this.sendMessageToIframe) return; 258 let message = { 259 'ica-fontSize': value, 260 }; 261 262 this.sendMessageToIframe(iframe, message); 263 } 264 updateLineHeight(idx){ 265 this.checkBtnAvailability(idx, this.lineHeight.options, this.elements.lineHeight); 266 let value = this.lineHeight.options[idx]; 267 if(value == undefined) return; 268 document.body.style.setProperty('--line-height-rate', value); 269 this.createCookie('ica-lineHeight', value); 270 this.createCookie('ica-lineHeight-index', idx); 271 if (!this.iframe || !this.sendMessageToIframe) return; 272 let message = { 273 'ica-lineHeight': value, 274 }; 275 this.sendMessageToIframe(iframe, message); 276 } 277 updateLetterSpacing(idx){
278 this.checkBtnAvailability(idx, this.letterSpacing.options, this.elements.letterSpacing); 279 let value = this.letterSpacing.options[idx]; 280 if(value == undefined) return; 281 value += this.units['letterSpacing']; 282 document.body.style.setProperty('--letter-spacing', value); 283 this.createCookie('ica-letterSpacing', value); 284 this.createCookie('ica-letterSpacing-index', idx); 285 if (!this.iframe || !this.sendMessageToIframe) return; 286 let message = { 287 'ica-letterSpacing': value, 288 }; 289 this.sendMessageToIframe(iframe, message); 290 } 291 updateCursorSize(idx){ 292 this.checkBtnAvailability(idx, this.cursorSize.options, this.elements.cursorSize); 293 let value = this.letterSpacing.options[idx]; 294 if(value == undefined) return; 295 document.body.setAttribute("ica-cursor-size", idx); 296 this.createCookie('ica-cursorSize', idx); 297 this.createCookie('ica-cursorSize-index', idx); 298 if (!this.iframe || !this.sendMessageToIframe) return; 299 let message = { 300 'ica-cursorSize': idx, 301 }; 302 this.sendMessageToIframe(iframe, message); 303 } 304 updateFontFamily(idx){ 305 let value = this.fontFamily.options[idx]; 306 if(value == undefined) return; 307 document.body.setAttribute('ica-font-family', value); 308 this.createCookie('ica-fontFamily', value); 309 this.createCookie('ica-fontFamily-index', idx); 310 for(let i = 0; i < this.elements.fontOptions.length; i++) 311 { 312 if(this.elements.fontOptions[i].value == idx) 313 this.elements.fontOptions[i].checked = true; 314 else 315 this.elements.fontOptions[i].checked = false; 316 } 317 if (!this.iframe || !this.sendMessageToIframe) return; 318 let message = { 319 'ica-fontFamily': value, 320 }; 321 this.sendMessageToIframe(iframe, message); 322 } 323 checkBtnAvailability(idx, options, elements){ 324 if(idx == options.length - 1) elements.increase.classList.add('disabled'); 325 else elements.increase.classList.remove('disabled'); 326 327 if(idx == 0) elements.decrease.classList.add('disabled'); 328 else elements.decrease.classList.remove('disabled'); 329 } 330 adjustWrapperPosition(){ 331 // let iconStyle = window.getComputedStyle(this.elements.icon); 332 let iconLeft = this.elements.icon.offsetLeft; 333 let iconTop = this.elements.icon.offsetTop; 334 let iconOffsetParent = this.elements.icon.offsetParent; 335 while(iconOffsetParent) 336 { 337 iconLeft += iconOffsetParent.offsetLeft; 338 iconTop += iconOffsetParent.offsetTop; 339 iconOffsetParent = iconOffsetParent.offsetParent; 340 } 341 this.elements.wrapper.style.left = iconLeft + 'px'; 342 this.elements.wrapper.style.top = iconTop + this.elements.icon.offsetHeight + 'px'; 343 let windowWidth = window.innerWidth; 344 let wrapperStyle = window.getComputedStyle(this.elements.wrapper); 345 let containerRightEdge = parseInt(wrapperStyle['width']) + iconLeft; 346 containerRightEdge += 10; 347 if( containerRightEdge < windowWidth ) 348 { 349 this.elements.wrapper.style.left = iconLeft + 'px'; 350 return; 351 } 352 this.elements.wrapper.style.left = parseInt(wrapperStyle.left) - (containerRightEdge - windowWidth) + 'px'; 353 } 354 checkClickOutside(event){ 355 356 let target = event.target; 357 do{ 358 if(target == this.elements.icon || target == this.elements.wrapper) 359 { 360 return; 361 } 362 target = target.parentNode; 363 } 364 while(target); 365 document.body.classList.remove('viewing-typography-menu'); 366 } 367 reset(){ 368 this.fontSize.currentIndex = this.getIdxByValue(this.defaultValues.fontSize, this.fontSize.options); 369 this.lineHeight.currentIndex = this.getIdxByValue(this.defaultValues.lineHeight, this.lineHeight.options); 370 this.letterSpacing.currentIndex = this.getIdxByValue(this.defaultValues.letterSpacing, this.letterSpacing.options); 371 this.cursorSize.currentIndex = this.getIdxByValue(this.defaultValues.cursorSize, this.cursorSize.options); 372 this.fontFamily.currentIndex = this.getIdxByValue(this.defaultValues.fontFamily, this.fontFamily.options); 373 this.updateFontSize(this.fontSize.currentIndex); 374 this.updateLineHeight(this.lineHeight.currentIndex); 375 this.updateLetterSpacing(this.letterSpacing.currentIndex); 376 this.updateCursorSize(this.cursorSize.currentIndex); 377 this.updateFontFamily(this.fontFamily.currentIndex); 378 } 379}
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.