1 2function decode (str) { 3 return str.replace(/'/g, "'") 4 .replace(/"/g, '"') 5 .replace(/>/g, '>') 6 .replace(/</g, '<') 7 .replace(/&/g, '&'); 8}; 9 10function highlight(input, text) { 11 var indices = []; 12 function mark(str, txt, idx) { 13 idx = str.indexOf(txt, idx+txt.length); 14 if (idx >= 0) { 15 indices.push(idx); 16 mark(str, txt, idx); 17 } 18 } 19 var innerLower = input.toLowerCase(); 20 text_lower = text.toLowerCase(); 21 var index = innerLower.indexOf(text_lower); 22 if (index >= 0) { 23 indices.push(index); 24 var formatted_html = ""; 25 formatted_html = input.substring(0,index); 26 mark(innerLower, text, index); 27 for (var i = 0; i < indices.length; i++) { 28 let highlighted = "<mark>" + input.substring(indices[i],indices[i] + text.length) + "</mark>"; 29 if(typeof indices[i+1] === 'undefined') { 30 highlighted += input.substring(indices[i] + text.length); 31 } else { 32 highlighted += input.substring(indices[i] + text.length, indices[i+1]); 33 } 34 formatted_html += highlighted; 35 } 36 return formatted_html; 37 } 38} 39 40function srch(item, searchText) { 41 var matched = false; 42 var content = ""; 43 var ch_title = ""; 44 var section = ""; 45 var footnotes = ""; 46 var title_matched = false; 47 var section_matched = false; 48 var p_matched = false; 49 var img_matched = false; 50 var is_interview = false; 51 var fn_matched = false; 52 var url = "/" 53 if (item[0].startsWith("int")){ 54 url = "/interviews/" + item[0].replace("int", ""); 55 } else { 56 url = "/section/" + item[0] + "/" + item[1].url + "/"; 57 } 58 if (item[1].ch == "Interviews") { 59 is_interview = true; 60 } else { 61 ch_title = highlight(item[1].ch_title, searchText); 62 if (ch_title) { 63 matched = true; 64 } else { 65 ch_title= item[1].ch_title; 66 } 67 section = highlight(item[0], searchText); 68 if (section) { 69 matched = true; 70 section_matched = true; 71 } else { 72 section = item[0]; 73 } 74 } 75 var title = highlight(item[1].title, searchText); 76 if (title) { 77 matched = true; 78 title_matched = true; 79 } else { 80 title = item[1].title; 81 } 82 //var cntnt = item[1].content; 83 //cntnt = cntnt.toLowerCase(); 84 //var content_index = cntnt.indexOf("https://archive.computerhistory.org/"); 85 //console.log(content_index); 86 //<a href="https://archive.computerhistory.org/resources/access/text/2013/05/102746645-05-01-acc.pdf">Norm Abramson Interviewed by James Pelkey 10/13/88</a> 87 88 var matched_sentence = ""; 89 var decoded_content = decode(item[1].content); 90 var matched_img = ""; 91 var search_rx = new RegExp(searchText, "gi"); 92 if (search_rx.test(decoded_content)) { 93 var a_rex = /<\s*a[^>]*>(.*?)<\s*\/\s*a>/g; 94 var img_rex = /<img([\w\W]+?)\/>/g; 95 var imgs = decoded_content.match(img_rex); 96 97 var paragraphs = []; 98 decoded_content = decoded_content.replace(a_rex, "").replace(img_rex, "").replace(/<p>*<\/p>/g, ""); 99 decoded_content.replace(/<p>(.*?)<\/p>/g, function () { 100 paragraphs.push(arguments[1]); 101 }); 102 if (imgs) { 103 var prev_img_count = 0; 104 for (var i=0; i<imgs.length; i++) { 105 var img_match_count = (imgs[i].match(search_rx) || []).length; 106 // search between tags using regex?? 107 if (img_match_count > 0 && img_match_count > prev_img_count) { 108 prev_img_count = img_match_count; 109 matched_img = imgs[i]; 110 } 111 } 112 } 113 if (matched_img) { 114 matched = true; 115 var img_dom = document.createElement('html'); 116 img_dom.innerHTML = matched_img; 117 var shadow_img = img_dom.getElementsByTagName('IMG')[0] 118 if (shadow_img) { 119 if (shadow_img.src) { 120 var classname = "imgc"; 121 var img_title = highlight(shadow_img.title, searchText); 122 if (!img_title) { 123 img_title = shadow_img.title; 124 } 125 if (img_title != "") { 126 img_title = "<h3>" + img_title + "</h3>"; 127 } 128 var formatted_img = 129 "<div class='" + classname + "'>" + 130 "<img src='" + shadow_img.src + "' alt='" + shadow_img.alt + "' >" + 131 img_title + 132 "</div>"; 133 matched_img = formatted_img; 134 img_matched = true; 135 } 136 } 137 } 138 var search_count = 0; 139 for (var i=0; i<paragraphs.length; i++) { 140 if (paragraphs[i].toLowerCase().includes(text_lower)) { 141 let sentences = paragraphs[i].split(/((?![.\n\s])[^.\n"]*(?:"[^\n"]*[^\n".]"[^.\n"]*)*(?:"[^"\n]+\."|\.|(?=\n)))/gi); 142 for (var s=0; s<sentences.length; s++) { 143 var count = (sentences[s].match(search_rx) || []).length; 144 if (count > 0 && count > search_count) { 145 search_count = count; 146 matched_sentence = sentences[s]; 147 if (matched_sentence.startsWith('â ')) { 148 matched_sentence = matched_sentence.replace('â ', ''); 149 } 150 if (matched_sentence.startsWith(", ")) { 151 matched_sentence = matched_sentence.replace(", ", ""); 152 } 153 } 154 } 155 } 156 } 157 } 158 content = highlight(matched_sentence, searchText); 159 if (content) { 160 matched = true; 161 p_matched = true; 162 content = "<p>" + content + "</p>"; 163 } else { 164 content = ""; 165 } 166 if (item[1].footnotes !== undefined) { 167 var matched_fn = item[1].footnotes.filter(obj => obj.src.toLowerCase().indexOf(searchText.toLowerCase()) >= 0); 168 var fn_size = Object.keys(matched_fn).length; 169 if (fn_size) { 170 matched = true; 171 fn_matched = true; 172 footnotes = matched_fn.map(footnote => { 173 let found_fn = highlight(footnote.src.replace(/(<([^>]+)>)/ig, ""), searchText); 174 if (found_fn !== undefined) { 175 return `<p><span>[${footnote.num}]</span> : ${found_fn}</p>`; 176 } 177 }); 178 } 179 } 180 if (matched) { 181 //console.log("\n\n" + section); 182 var search_item = {}; 183 if (Object.keys(footnotes).length > 0) { 184 let footnotes_str = footnotes.join(""); 185 footnotes = footnotes_str; 186 footnotes = `<div class="footnote"><div>Footnotes:</div>${footnotes}</div>` 187 } else { 188 footnotes = ""; 189 } 190 var html = 191 `<a href="${url}" class="search-item"><h1>${ch_title}</h1><h2>${section} ${title}</h2>${content}${matched_img}${footnotes}</a>`; 192 if (is_interview) { 193 if (title_matched) { 194 //console.log("int title matched"); 195 search_item.interview = [html]; 196 } else { 197 search_item.interviews = [html]; 198 //console.log("int no title matched"); 199 } 200 } 201 else if (section_matched || title_matched) { 202 search_item.h2 = html; 203 //console.log("non-int section/title matched"); 204 } else if (p_matched && !section_matched && !title_matched) { 205 search_item.p = [html]; 206 //console.log("p matched"); 207 } else if (img_matched && !section_matched && !title_matched && !p_matched) { 208 search_item.img = [html]; 209 //console.log("img matched"); 210 } else if (fn_matched && !section_matched && !title_matched && !p_matched && !img_matched && footnotes != "") { 211 //console.log("footnotes matched"); 212 search_item.footnotes = html; 213 //console.log(html); 214 //console.log(footnotes); 215 } 216 return search_item; 217 } 218} 219 220let search_timeout = null; 221document.getElementById('search').addEventListener('keyup', function (e) { 222 clearTimeout(search_timeout); 223 search_timeout = setTimeout(function () { 224 let html = ""; 225 let searchText = document.getElementById('search').value; 226 if (searchText.length < 2) { // Clear when input or matches are empty 227 hideResults(); 228 } else { 229 showResults(); 230 var search_results = { 231 "h2" : [], 232 "interview" : [], 233 "interviews" : [], 234 "p" : [], 235 "img" : [], 236 "footnotes" : [] 237 }; 238 for (var i=1; i<search_array.length; i++) { // offset first entry for toc 239 let search_query = srch(search_array[i], searchText); 240 if (search_query) { 241 if (search_query.h2){ 242 search_results.h2.push(search_query.h2); 243 } 244 if (search_query.interview){ 245 search_results.interview.push(search_query.interview); 246 } 247 if (search_query.interviews){ 248 search_results.interviews.push(search_query.interviews); 249 } 250 if (search_query.p){ 251 search_results.p.push(search_query.p); 252 } 253 if (search_query.img){ 254 search_results.img.push(search_query.img); 255 } 256 if (search_query.footnotes){ 257 search_results.footnotes = search_results.footnotes.concat(search_query.footnotes); 258 } 259 } 260 } 261 //console.log(search_results); 262 html = search_results.h2.join(""); 263 if (search_results.interview.length > 0) { 264 html += "<div class='search-item'><h1>Interviews:</h1></div>"; 265 html += search_results.interview.join(""); 266 } 267 html += search_results.p.join(""); 268 html += search_results.img.join(""); 269 if (search_results.interviews.length > 0) { 270 html += "<div class='search-item'><h1>Interviews:</h1></div>"; 271 html += search_results.interviews.join(""); 272 } 273 if (search_results.footnotes.length > 0) { 274 //html += search_results.footnotes; 275 html += search_results.footnotes.join(""); 276 //console.log(search_results.footnotes); 277 } 278 } 279 document.getElementById('results').innerHTML = html; 280 }, 250); 281});
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.