2 // @name 4chan-Ignoring-Enhancements
3 // @namespace http://tampermonkey.net/
5 // @description 4chan Pain Kill Extension
6 // @author ECHibiki-/qa/
7 // @match http://boards.4chan.org/*
8 // @match https://boards.4chan.org/*
9 // @include https://boards.4chan.org/*
10 // @include http://boards.4chan.org/*
11 // @run-at document-body
12 // @updateURL https://github.com/ECHibiki/4chan-UserScripts/raw/master/4chan-Ignoring-Enhancements.user.js
13 // @downloadURL https://github.com/ECHibiki/4chan-UserScripts/raw/master/4chan-Ignoring-Enhancements.user.js
16 var localStoreThreads;
19 var windowDisplayed = false;
20 var defaultExpireTime = 172800000;
23 var windowDisplayed = false;
24 var numberOfFilters = 0;
25 var initialFilters = [];
29 var secondObserverSet;
32 function storageAvailable(type) {
34 var storage = window[type],
35 x = '__storage_test__';
36 storage.setItem(x, x);
37 storage.removeItem(x);
41 return e instanceof DOMException && (
42 // everything except Firefox
46 // test name field too, because code might not be present
47 // everything except Firefox
48 e.name === 'QuotaExceededError' ||
50 e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
51 // acknowledge QuotaExceededError only if there's something already stored
57 function detectBrowser() {
58 if((navigator.userAgent.indexOf("Opera") || navigator.userAgent.indexOf('OPR')) != -1 )
63 else if(navigator.userAgent.indexOf("Chrome") != -1 )
65 console.log("Chrome");
68 else if(navigator.userAgent.indexOf("Safari") != -1)
70 console.log("Safari");
73 else if(navigator.userAgent.indexOf("Firefox") != -1 )
75 console.log("FireFox");
78 else if((navigator.userAgent.indexOf("MSIE") != -1 ) || (!!document.documentMode == true )) //IF IE > 10
90 //hide image onclick listener
91 function hideImage(event){
92 var hideIndex = this.src.indexOf(".HIDDEN");
93 if((event.ctrlKey && event.shiftKey) && hideIndex == -1){
94 event.preventDefault();
95 event.stopPropagation();
96 if (storageAvailable('localStorage')) {
97 if(this.id.charAt(0) == "p") this.id = "f" + this.id.substr(1);
98 localStorage.setItem(this.id, Date.now());
101 console.log("No Storage");
103 this.src = this.src + ".HIDDEN" + "?" + Date.now();
106 else if(event.ctrlKey && event.shiftKey){
107 event.preventDefault();
108 event.stopPropagation();
109 if (storageAvailable('localStorage')) {
110 if(this.id.charAt(0) == "p") this.id = "f" + this.id.substr(1);
111 localStorage.removeItem(this.id);
114 console.log("No Storage");
116 this.src = this.src.substring(0, hideIndex);
122 //functions to find properties by regex
123 function getPropertyByRegex(obj,propName) {
124 var re = new RegExp("^" + propName + "(\\[\\d*\\])?$"),
133 //retrieve from memory the hidden iamges
135 function retrieveStates(){
139 while( i < window.localStorage.length) {
141 sKey = window.localStorage.key(i);
142 oJson[sKey] = window.localStorage.getItem(sKey);
144 localStoreThreads = getPropertyByRegex(oJson,"f[0-9]*IMG");
145 localStoreThreads.forEach(function callback(elem){
146 if(Date.now() - oJson[elem] > expireTime)
147 localStorage.removeItem(elem);
148 var node = document.getElementById(""+elem);
149 if(node !== null && node.src.indexOf(".HIDDEN") == -1){
150 node.src = node.src + ".HIDDEN" + "?" + Date.now();
153 else if((node = document.getElementById("p"+elem.substring(1))) !== null && node.src.indexOf(".HIDDEN") == -1){
154 node.src = node.src + ".HIDDEN" + "?" + Date.now();
157 else if((node = document.getElementById("thread-"+elem.substring(1))) !== null && node.src.indexOf(".HIDDEN") == -1){
158 node.src = node.src + ".HIDDEN" + "?" + Date.now();
161 else if((node = document.getElementById("thumb-"+elem.substring(1))) !== null && node.src.indexOf(".HIDDEN") == -1){
162 node.src = node.src + ".HIDDEN" + "?" + Date.now();
171 function hideWindow(){
172 var style = document.createElement('style');
173 style.innerHTML = ".inputs{background-color:rgb(200,200,200);margin:5px 7px;width:100px;}";
174 document.body.appendChild(style);
176 var backgroundDiv = document.createElement("div");
177 backgroundDiv.setAttribute("style", "border:solid 1px black;position:fixed;width:100%;height:100%;background-color:rgba(200,200,200,0.3);top:0;left:0;display:none; z-index:9");
178 backgroundDiv.setAttribute("id", "hiBackground");
179 document.body.appendChild(backgroundDiv);
180 backgroundDiv.addEventListener("click", hideToggle);
182 var windowDiv = document.createElement("div");
183 windowDiv.setAttribute("style", "border:solid 1px black;position:fixed;width:400px;background-color:rgb(200,200,200);left:40%;top:20%;margin-bottom:0; display:none; z-index:10");
184 windowDiv.setAttribute("id", "hiWindow");
186 var closeDiv = document.createElement("div");
187 closeDiv.setAttribute("style", "border:solid 1px black;position:absolute;width:25px;height:25px;background-color:rgba(255,100,90,0.9); right:3px;top:3px; z-index:10");
188 closeDiv.addEventListener("click", hideToggle);
189 windowDiv.appendChild(closeDiv);
191 var titleP = document.createElement("p");
192 titleP.setAttribute("style", "margin-left:5px;margin-top:5px");
193 var titleText = document.createTextNode("Filter Settings");
194 titleP.appendChild(titleText);
195 windowDiv.appendChild(titleP);
197 var containerDiv = document.createElement("div");
198 containerDiv.setAttribute("style","background-color:white;margin:0 0;padding:5px;");
199 windowDiv.appendChild(containerDiv);
201 var expirationLabel = document.createElement("label");
202 var expirationText = document.createTextNode("Expiration Time(hours): ");
203 expirationLabel.appendChild(expirationText);
204 containerDiv.appendChild(expirationLabel);
205 var expirationInput = document.createElement("input");
206 expirationInput.setAttribute("id", "expirationTime");
207 containerDiv.appendChild(expirationInput);
208 containerDiv.appendChild(expirationInput);
209 containerDiv.appendChild(document.createElement("br"));
210 var setButton = document.createElement("input");
211 setButton.setAttribute("type", "button");
212 setButton.setAttribute("id", "setTime");
213 setButton.setAttribute("value", "Set Time");
214 setButton.addEventListener("click", function(){
216 if (storageAvailable('localStorage')) {
217 var time = document.getElementById("expirationTime");
218 var msTime = time.value * 3600000;
219 if (msTime == 0) msTime = defaultExpireTime;
221 //console.log("B" + expireTime);
222 localStorage.setItem("ExpirationTime", msTime);
226 expirationInput.setAttribute("value", localStorage.getItem("ExpirationTime") / 3600000);
227 containerDiv.appendChild(setButton);
229 document.body.appendChild(windowDiv);
233 function hideToggle(){
235 document.getElementById("hiWindow").style.display = "none";
236 document.getElementById("hiBackground").style.display = "none";
237 windowDisplayed = false;
240 document.getElementById("hiWindow").style.display = "inline-block";
241 document.getElementById("hiBackground").style.display = "inline-block";
242 windowDisplayed = true;
246 function hideButton(){
247 var button = document.createElement("input");
248 button.setAttribute("Value", "Hide Image Settings");
249 button.setAttribute("type", "button");
250 button.setAttribute("style", "position:absolute;top:45px");
251 button.addEventListener("click", hideWindow);
252 if(document.body === null){
253 setTimeout(hideButton, 30);
256 document.body.appendChild(button);
257 button.addEventListener("click", hideToggle);
259 expireTime = localStorage.getItem("ExpirationTime");
260 //console.log("Z" + expireTime);
264 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
265 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
266 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
267 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
268 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
269 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
270 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
271 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
273 function formatSettings(input){
274 var rtn = input.split('"-"');
276 rtn.forEach(function(filter){
277 rtn[i] = filter.replace("\"", "");
283 function loadSettings(){
287 while( i < window.localStorage.length) {
289 sKey = window.localStorage.key(i);
290 oJson[sKey] = window.localStorage.getItem(sKey);
292 numberOfFilters = oJson["q"];
293 console.log(numberOfFilters);
294 filters = getPropertyByRegex(oJson,"filter[0-9]*");
295 filters.forEach(function(filter){
296 initialFilters.push(formatSettings(oJson[filter]));
300 function saveSettings(){
302 if(storageAvailable('localStorage')){
303 window.localStorage.setItem("q", numberOfFilters);
304 for (var i = 0 ; i < numberOfFilters; i++){
305 var pattern = document.getElementById("Pattern"+i).value;
306 var replacement = document.getElementById("Replacement"+i).value;
308 if(pattern === "" || replacement === "") continue;
309 if (pattern.charAt(0) == "/" && pattern.charAt(pattern.length - 1) == "/"){
310 pattern = pattern + setting;
312 else if(pattern.charAt(0) !== "/" && pattern.substr(pattern.length - 2).match(/\/[a-zA-Z$]/) == null){
313 pattern = "/" + pattern + "/" + setting;
315 document.getElementById("Pattern"+i).value = pattern;
316 var saveString = '"' + document.getElementById("Active"+i).checked + '"-"' + pattern + '"-"' + replacement + '"';
317 window.localStorage.setItem("filter" + i, saveString);
320 alert("Replacements Saved");
323 function filterWindow(){
324 var style = document.createElement('style');
325 style.innerHTML = ".inputs{background-color:rgb(200,200,200);margin:5px 7px;width:100px;}";
326 document.body.appendChild(style);
328 var backgroundDiv = document.createElement("div");
329 backgroundDiv.setAttribute("style", "border:solid 1px black;position:fixed;width:100%;height:100%;background-color:rgba(200,200,200,0.3);top:0;left:0;display:none; z-index:9");
330 backgroundDiv.setAttribute("id", "FilterBackground");
331 document.body.appendChild(backgroundDiv);
332 backgroundDiv.addEventListener("click", filterToggle);
334 var windowDiv = document.createElement("div");
335 windowDiv.setAttribute("style", "border:solid 1px black;position:fixed;width:400px;background-color:rgb(200,200,200);left:40%;top:20%;margin-bottom:0; display:none; z-index:10");
336 windowDiv.setAttribute("id", "FilterWindow");
338 var closeDiv = document.createElement("div");
339 closeDiv.setAttribute("style", "border:solid 1px black;position:absolute;width:25px;height:25px;background-color:rgba(255,100,90,0.9); right:3px;top:3px; z-index:10");
340 closeDiv.addEventListener("click", filterToggle);
341 windowDiv.appendChild(closeDiv);
343 var titleP = document.createElement("p");
344 titleP.setAttribute("style", "margin-left:5px;margin-top:5px");
345 var titleText = document.createTextNode("Filter Settings");
346 titleP.appendChild(titleText);
347 windowDiv.appendChild(titleP);
349 var containerDiv = document.createElement("div");
350 containerDiv.setAttribute("style","background-color:white;margin:0 0;padding:5px;");
351 windowDiv.appendChild(containerDiv);
353 var filterTable = document.createElement("table");
354 filterTable.setAttribute("style", "text-align:center;");
355 filterTable.setAttribute("id", "FilterTable");
356 containerDiv.appendChild(filterTable);
358 var tableRow = document.createElement("tr");
359 filterTable.appendChild(tableRow);
360 var tableHeadActive = document.createElement("th");
361 var headTextActive = document.createTextNode("Active");
362 tableHeadActive.appendChild(headTextActive);
363 filterTable.appendChild(tableHeadActive);
364 var tableHeadPattern = document.createElement("th");
365 var headTextPattern = document.createTextNode("Pattern");
366 tableHeadPattern.appendChild(headTextPattern);
367 filterTable.appendChild(tableHeadPattern);
368 var tableHeadReplacement = document.createElement("th");
369 var headTextReplacement = document.createTextNode("Replacement");
370 tableHeadReplacement.appendChild(headTextReplacement);
371 filterTable.appendChild(tableHeadReplacement);
373 //loop to create rows
374 //console.log(numberOfFilters);
375 if (numberOfFilters === 0 || isNaN(numberOfFilters)) numberOfFilters = 6;
376 //console.log(numberOfFilters);
377 for (var i = 0; i < numberOfFilters ; i++){
378 var tableRowContents = document.createElement("tr");
379 tableRowContents.setAttribute("id", "FilterRow" + i);
381 var tableDataActive = document.createElement("td");
382 var tableCheckBoxActive = document.createElement("input");
383 tableCheckBoxActive.setAttribute("type", "checkbox");
384 tableCheckBoxActive.setAttribute("id", "Active" + i);
385 tableDataActive.appendChild(tableCheckBoxActive);
386 tableRowContents.appendChild(tableDataActive);
388 var tableDataPattern = document.createElement("td");
389 var tableInputPattern = document.createElement("input");
390 tableInputPattern.setAttribute("class", "inputs");
391 tableInputPattern.setAttribute("id", "Pattern" + i);
392 tableDataPattern.appendChild(tableInputPattern);
393 tableRowContents.appendChild(tableDataPattern);
395 var tableDataReplacement = document.createElement("td");
396 var tableInputReplacement = document.createElement("input");
397 tableInputReplacement.setAttribute("class", "inputs");
398 tableInputReplacement.setAttribute("id", "Replacement" + i);
399 tableDataReplacement.appendChild(tableInputReplacement);
400 tableRowContents.appendChild(tableDataReplacement);
402 filterTable.appendChild(tableRowContents);
405 var tableLastContents = document.createElement("tr");
407 var tableAddCollumn = document.createElement("td");
408 var tableAddRowButton = document.createElement("input");
409 var tableSubtractRowButton = document.createElement("input");
410 tableSubtractRowButton.setAttribute("type", "button");
411 tableSubtractRowButton.setAttribute("value", "-");
412 tableSubtractRowButton.setAttribute("style", "padding: 7px 0; margin:5px 0;");
413 tableAddCollumn.appendChild(tableSubtractRowButton);
414 tableSubtractRowButton.addEventListener("click", removeRow);
415 tableAddRowButton.setAttribute("type", "button");
416 tableAddRowButton.setAttribute("value", "+");
417 tableAddRowButton.setAttribute("style", "padding: 7px 0; margin:5px 0;");
418 tableAddCollumn.appendChild(tableAddRowButton);
419 tableAddRowButton.addEventListener("click", addRow);
421 tableLastContents.appendChild(tableAddCollumn);
423 var tableSetCollumn = document.createElement("td");
424 var tableConfirmButton = document.createElement("input");
425 tableConfirmButton.setAttribute("type", "button");
426 tableConfirmButton.setAttribute("id", "tableConfirmButton");
427 tableConfirmButton.setAttribute("value", "Set Replacements");
428 tableConfirmButton.setAttribute("style", "padding: 7px 0; margin:5px 0;");
429 tableConfirmButton.addEventListener("click", saveSettings);
430 tableConfirmButton.addEventListener("click", modifyDOM);
431 tableConfirmButton.addEventListener("click", filterToggle);
432 tableSetCollumn.appendChild(tableConfirmButton);
433 tableLastContents.appendChild(tableSetCollumn);
436 var tableCloseCollumn = document.createElement("td");
437 var tableCloseButton = document.createElement("input");
438 tableCloseButton.setAttribute("type", "button");
439 tableCloseButton.setAttribute("value", "Close Menu");
440 tableCloseButton.setAttribute("style", "padding: 7px 0; margin:5px 0;");
441 tableCloseButton.addEventListener("click", filterToggle);
442 tableCloseCollumn.appendChild(tableCloseButton);
443 tableLastContents.appendChild(tableCloseCollumn);
445 filterTable.appendChild(tableLastContents);
447 document.body.appendChild(windowDiv);
451 function filterToggle(){
453 document.getElementById("FilterWindow").style.display = "none";
454 document.getElementById("FilterBackground").style.display = "none";
455 windowDisplayed = false;
458 document.getElementById("FilterWindow").style.display = "inline-block";
459 document.getElementById("FilterBackground").style.display = "inline-block";
460 windowDisplayed = true;
464 function filterButton(){
465 var button = document.createElement("input");
466 button.setAttribute("Value", "Word Filter Settings");
467 button.setAttribute("type", "button");
468 button.setAttribute("style", "position:absolute;top:75px");
469 button.addEventListener("click", filterWindow);
470 document.body.appendChild(button);
471 button.addEventListener("click", filterToggle);
475 var table = document.getElementById("FilterTable");
476 table.deleteRow(parseInt(numberOfFilters) + 1);
479 var tableRowContents = document.createElement("tr");
480 tableRowContents.setAttribute("id", "FilterRow" + (numberOfFilters - 1));
482 var tableDataActive = document.createElement("td");
483 var tableCheckBoxActive = document.createElement("input");
484 tableCheckBoxActive.setAttribute("type", "checkbox");
485 tableCheckBoxActive.setAttribute("id", "Active" + (numberOfFilters - 1));
486 tableDataActive.appendChild(tableCheckBoxActive);
487 tableRowContents.appendChild(tableDataActive);
489 var tableDataPattern = document.createElement("td");
490 var tableInputPattern = document.createElement("input");
491 tableInputPattern.setAttribute("class", "inputs");
492 tableInputPattern.setAttribute("id", "Pattern" + (numberOfFilters - 1));
493 tableDataPattern.appendChild(tableInputPattern);
494 tableRowContents.appendChild(tableDataPattern);
496 var tableDataReplacement = document.createElement("td");
497 var tableInputReplacement = document.createElement("input");
498 tableInputReplacement.setAttribute("class", "inputs");
499 tableInputReplacement.setAttribute("id", "Replacement" + (numberOfFilters - 1));
500 tableDataReplacement.appendChild(tableInputReplacement);
501 tableRowContents.appendChild(tableDataReplacement);
503 table.appendChild(tableRowContents);
505 var tableLastContents = document.createElement("tr");
507 var tableAddCollumn = document.createElement("td");
508 var tableAddRowButton = document.createElement("input");
509 var tableSubtractRowButton = document.createElement("input");
510 tableSubtractRowButton.setAttribute("type", "button");
511 tableSubtractRowButton.setAttribute("value", "-");
512 tableSubtractRowButton.setAttribute("style", "padding: 7px 0; margin:5px 0;");
513 tableAddCollumn.appendChild(tableSubtractRowButton);
514 tableSubtractRowButton.addEventListener("click", removeRow);
515 tableAddRowButton.setAttribute("type", "button");
516 tableAddRowButton.setAttribute("value", "+");
517 tableAddRowButton.setAttribute("style", "padding: 7px 0; margin:5px 0;");
518 tableAddCollumn.appendChild(tableAddRowButton);
519 tableAddRowButton.addEventListener("click", addRow);
521 tableLastContents.appendChild(tableAddCollumn);
523 var tableSetCollumn = document.createElement("td");
524 var tableConfirmButton = document.createElement("input");
525 tableConfirmButton.setAttribute("type", "button");
526 tableConfirmButton.setAttribute("id", "tableConfirmButton");
527 tableConfirmButton.setAttribute("value", "Set Replacements");
528 tableConfirmButton.setAttribute("style", "padding: 7px 0; margin:5px 0;");
529 tableConfirmButton.addEventListener("click", saveSettings);
530 tableConfirmButton.addEventListener("click", modifyDOM);
531 tableConfirmButton.addEventListener("click", filterToggle);
532 tableSetCollumn.appendChild(tableConfirmButton);
533 tableLastContents.appendChild(tableSetCollumn);
535 var tableCloseCollumn = document.createElement("td");
536 var tableCloseButton = document.createElement("input");
537 tableCloseButton.setAttribute("type", "button");
538 tableCloseButton.setAttribute("value", "Close Menu");
539 tableCloseButton.setAttribute("style", "padding: 7px 0; margin:5px 0;");
540 tableCloseButton.addEventListener("click", filterToggle);
541 tableCloseCollumn.appendChild(tableCloseButton);
542 tableLastContents.appendChild(tableCloseCollumn);
544 table.appendChild(tableLastContents);
547 function removeRow(){
548 var table = document.getElementById("FilterTable");
549 if(numberOfFilters != 0){
550 table.deleteRow(numberOfFilters);
557 initialFilters.forEach(function(filter){
558 if(filter[2] === null || filter[1] === null || filter[0] === null || i == numberOfFilters) return;
559 if(filter[0] == "true"){
560 document.getElementById("Active"+i).checked = true;
562 else if(filter[0] == "false"){
563 document.getElementById("Active"+i).checked = false;
565 document.getElementById("Pattern"+i).value = filter[1];
566 document.getElementById("Replacement"+i).value = filter[2];
572 //1111111111111111111111111111111111111111111111111111111111111111111111////11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111//
573 //1111111111111111111111111111111111111111111111111111111111111111111111////11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111//
574 //1111111111111111111111111111111111111111111111111111111111111111111111////11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111//
575 //1111111111111111111111111111111111111111111111111111111111111111111111////11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111//
576 //1111111111111111111111111111111111111111111111111111111111111111111111////11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111//
577 //1111111111111111111111111111111111111111111111111111111111111111111111////11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111//
578 //1111111111111111111111111111111111111111111111111111111111111111111111////11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111//
579 //1111111111111111111111111111111111111111111111111111111111111111111111////11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111//
580 //1111111111111111111111111111111111111111111111111111111111111111111111////11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111//
581 //1111111111111111111111111111111111111111111111111111111111111111111111////11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111//
584 function modifyDOM(){
586 var start = document.getElementById("delform");
587 if (start === null) start = document.body;
588 else start = start.firstChild;
589 if(!secondObserverSet){
590 //console.log(start);
591 observer.disconnect();
592 observeDynamicMutation(start);
593 secondObserverSet = true;
597 var start = document;
599 if(start === null) return;
600 var itterator = document.createTreeWalker(start, NodeFilter.SHOW_ELEMENTS, NodeFilter.SHOW_ELEMENTS);
603 //console.log("modify DOM");
604 while((node = itterator.nextNode())){
605 var cname = node.className;
606 var tag = node.tagName;
607 if(tag === "IMG" || tag === "img"){
608 if(node.getAttribute("data-md5") !== null || node.className.indexOf("thumb") != -1){
610 node.id = node.parentNode.parentNode.id + "IMG";
611 node.addEventListener("click", hideImage, {passive:false, capture:false, once:false});
614 else if(cname == "postMessage"){
615 while((localNode = itterator.nextNode())){
616 var className = localNode.className;
617 if(className == undefined || className == "quotelink"){
618 for(var i = 0 ; i < numberOfFilters; i++){
619 //console.log(localNode.className);
620 if(kill[i] == true) continue;
621 filter = document.getElementById("Pattern"+i);
622 replacement = document.getElementById("Replacement"+i);
623 active = document.getElementById("Active"+i);
626 var lastChar = filter.value.length - 1;
627 var filterText = filter.value;
628 if(filterText === "") break;
629 var setting = filterText.substr(lastChar);
630 filterText = filterText.substr(1, lastChar-2);
631 filterText = "(^|[\\s!$%^&*()_+|~\\-=`{}\\[\\]:\";'<>?,\\.\\/])" + filterText + "([\\s!$%^&*()_+|~\\-=`{}\\[\\]:\";'<>?,\\.\\/]|$)";
633 var regex = new RegExp(filterText, setting);
634 localNode.textContent = localNode.textContent.replace(regex, " " + replacement.value + " ");
637 alert(i + "'s regex was invalid");
640 // console.log("Inner: " + (Date.now() - later));
651 //detect page changes
652 function observeDynamicMutation(node){
653 if(node === undefined)
655 observer = new MutationObserver(function callBack(mutations){
656 var later = Date.now();
659 //console.log("PKX: " + (Date.now() - later));
661 var config = {subtree: true, childList:true};
662 observer.observe(node, config);
665 if (window.top != window.self) //-- Don't run on frames or iframes
668 //initial onload setup
669 function hideSetup(){
675 function filterSetup(){
685 observeDynamicMutation();
688 browser = detectBrowser();
690 console.log("Script loaded: 4chanPKX");