PageSourceSearch

https://wordsmith.social/js/h.js

js wordsmith.social collected 2026-09-24 06:33:14 UTC 7,512 bytes, 297 lines download raw bytes

1/**
2 * H.js
3 * 
4 * Lightweight, extremely bare-bones library for manipulating the DOM and
5 * saving some typing.
6 */
7
8var Element = function(domElement) {
9	this.el = domElement;
10};
11
12/**
13 * Creates a toggle button that adds / removes the given class name from the
14 * given element.
15 *
16 * @param {Element} $el - The element to modify.
17 * @param {string} onClass - The class to add to the given element.
18 * @param {function} onFunc - Additional actions when toggling on.
19 * @param {function} offFunc - Additional actions when toggling off.
20 */
21Element.prototype.createToggle = function($el, onClass, onFunc, offFunc) {
22	this.on('click', function(e) {
23		if ($el.el.className === '') {
24			$el.el.className = onClass;
25			onFunc(new Element(this), e);
26		} else {
27			$el.el.className = '';
28			offFunc(new Element(this), e);
29		}
30		e.preventDefault();
31	}, false);
32};
33Element.prototype.on = function(event, func) {
34	events = event.split(' ');
35	var el = this.el;
36	if (el == null) {
37		console.error("Error: element for event is null");
38		return;
39	}
40	var addEvent = function(e) {
41		if (el.addEventListener) {
42			el.addEventListener(e, func, false);
43		} else if (el.attachEvent) {
44			el.attachEvent(e, func);
45		}
46	};
47	if (events.length === 1) {
48		addEvent(event);
49	} else {
50		for(var i=0; i<events.length; i++) {
51			addEvent(events[i]);
52		}
53	}
54};
55Element.prototype.setClass = function(className) {
56	if (this.el == null) {
57		console.error("Error: element to set class on is null");
58		return;
59	}
60	this.el.className = className;
61};
62Element.prototype.removeClass = function(className) {
63	if (this.el == null) {
64		console.error("Error: element to remove class on is null");
65		return;
66	}
67	var regex = new RegExp(' ?' + className, 'g');
68	this.el.className = this.el.className.replace(regex, '');
69};
70Element.prototype.text = function(text, className) {
71	if (this.el == null) {
72		console.error("Error: element for setting text is null");
73		return;
74	}
75	if (this.el.textContent !== text) {
76		this.el.textContent = text;
77		if (typeof className !== 'undefined') {
78			this.el.className = this.el.className + ' ' + className;
79		}
80	}
81};
82Element.prototype.insertAfter = function(newNode) {
83	if (this.el == null) {
84		console.error("Error: element for insertAfter is null");
85		return;
86	}
87	this.el.parentNode.insertBefore(newNode, this.el.nextSibling);
88};
89Element.prototype.remove = function() {
90	if (this.el == null) {
91		console.error("Didn't remove element");
92		return;
93	}
94	this.el.parentNode.removeChild(this.el);
95};
96Element.prototype.hide = function() {
97	if (this.el == null) {
98		console.error("Didn't hide element");
99		return;
100	}
101	this.el.className += ' effect fade-out';
102};
103Element.prototype.show = function() {
104	if (this.el == null) {
105		console.error("Didn't show element");
106		return;
107	}
108	this.el.className += ' effect';
109};
110
111
112var H = {
113	getQEl: function(elementQuery) {
114		return new Element(document.querySelector(elementQuery));
115	},
116	getEl: function(elementId) {
117		return new Element(document.getElementById(elementId));
118	},
119	save: function($el, key) {
120		localStorage.setItem(key, $el.el.value);
121	},
122	saveClassic: function($titleEl, $el, key) {
123		var out = "";
124		var title = $titleEl.el.value;
125		if (title !== "") {
126			out = "# "+title+"\n\n";
127		}
128		out += $el.el.value;
129		localStorage.setItem(key, out);
130	},
131	load: function($el, key, onlyLoadPopulated, postUpdated) {
132		var val = localStorage.getItem(key);
133		if (onlyLoadPopulated && val == null) {
134			// Do nothing
135			return true;
136		}
137		$el.el.value = val;
138		if (postUpdated != null) {
139			var lastLocalPublishStr = localStorage.getItem(key+'-published');
140			if (lastLocalPublishStr != null && lastLocalPublishStr != '') {
141				try {
142					var lastLocalPublish = new Date(lastLocalPublishStr);
143					if (postUpdated > lastLocalPublish) {
144						return false;
145					}
146				} catch (e) {
147					console.error("unable to parse draft updated time");
148				}
149			}
150		}
151		return true;
152	},
153	loadClassic: function($titleEl, $el, key, onlyLoadPopulated) {
154		var val = localStorage.getItem(key);
155		if (onlyLoadPopulated && val == null) {
156			// Do nothing
157			return;
158		}
159		if (val.indexOf("# ") === 0) {
160			var eol = val.indexOf("\n");
161			title = val.substring("# ".length, eol);
162			val = val.substring(eol+"\n\n".length);
163			$titleEl.el.value = title;
164		}
165		$el.el.value = val;
166	},
167	set: function(key, value) {
168		localStorage.setItem(key, value);
169	},
170	get: function(key, defaultValue) {
171		var val = localStorage.getItem(key);
172		if (val == null) {
173			val = defaultValue;
174		}
175		return val;
176	},
177	remove: function(key) {
178		localStorage.removeItem(key);
179	},
180	exists: function(key) {
181		return localStorage.getItem(key) !== null;
182	},
183	createPost: function(id, editToken, content, created) {
184		var summaryLen = 200;
185		var titleLen = 80;
186		var getPostMeta = function(content) {
187			var eol = content.indexOf("\n");
188			if (content.indexOf("# ") === 0) {
189				// Title is in the format:
190				//
191				//   # Some title
192				var summary = content.substring(eol).trim();
193				if (summary.length > summaryLen) {
194					summary = summary.substring(0, summaryLen) + "...";
195				}
196				return {
197					title: content.substring("# ".length, eol),
198					summary: summary,
199				};
200			}
201
202			var blankLine = content.indexOf("\n\n");
203			if (blankLine !== -1 && blankLine <= eol && blankLine <= titleLen) {
204				// Title is in the format:
205				//
206				//   Some title
207				//
208				//   The body starts after that blank line above it.
209				var summary = content.substring(blankLine).trim();
210				if (summary.length > summaryLen) {
211					summary = summary.substring(0, summaryLen) + "...";
212				}
213				return {
214					title: content.substring(0, blankLine),
215					summary: summary,
216				};
217			}
218
219			// TODO: move this to the beginning
220			var title = content.trim();
221			var summary = "";
222			if (title.length > titleLen) {
223				// Content can't fit in the title, so figure out the summary
224				summary = title;
225				title = "";
226				if (summary.length > summaryLen) {
227					summary = summary.substring(0, summaryLen) + "...";
228				}
229			} else if (eol > 0) {
230				summary = title.substring(eol+1);
231				title = title.substring(0, eol);
232			}
233			return {
234				title: title,
235				summary: summary
236			};
237		};
238		
239		var post = getPostMeta(content);
240		post.id = id;
241		post.token = editToken;
242		post.created = created ? new Date(created) : new Date();
243		post.client = "Pad";
244		
245		return post;
246	},
247	getTitleStrict: function(content) {
248		var eol = content.indexOf("\n");
249		var title = "";
250		var newContent = content;
251		if (content.indexOf("# ") === 0) {
252			// Title is in the format:
253			// # Some title
254			if (eol !== -1) {
255				// First line should start with # and end with \n
256				newContent = content.substring(eol).leftTrim();
257				title = content.substring("# ".length, eol);
258			}
259		}
260		return {
261			title: title,
262			content: newContent
263		};
264	},
265};
266
267var He = {
268	create: function(name) {
269		return document.createElement(name);
270	},
271	get: function(id) {
272		return document.getElementById(id);
273	},
274	$: function(selector) {
275		var els = document.querySelectorAll(selector);
276		return els;
277	},
278	postJSON: function(url, params, callback) {
279		var http = new XMLHttpRequest();
280
281		http.open("POST", url, true);
282
283		// Send the proper header information along with the request
284		http.setRequestHeader("Content-type", "application/json");
285
286		http.onreadystatechange = function() {
287			if (http.readyState == 4) {
288				callback(http.status, JSON.parse(http.responseText));
289			}
290		}
291		http.send(JSON.stringify(params));
292	},
293};
294
295String.prototype.leftTrim = function() {
296	return this.replace(/^\s+/,"");
297};

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.