PageSourceSearch

https://ica.art/static/js/Typography.js

js ica.art collected 2026-09-24 09:09:25 UTC 15,426 bytes, 379 lines download raw bytes

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">&minus;</div><div class="increase-font-size typography-control-btn pointer">&plus;</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">&minus;</div><div class="increase-line-height typography-control-btn pointer">&plus;</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">&minus;</div><div class="increase-letter-spacing typography-control-btn pointer">&plus;</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">&minus;</div><div class="increase-cursor-size typography-control-btn pointer">&plus;</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.