word replacements
[4Free-FSE.git] / 4chan-Ignoring-Enhancements.user.js
blob5d3c2a8afeaa40e8976aa5e8622cb00c959e75c0
1 // ==UserScript==
2 // @name         4chan-Ignoring-Enhancements
3 // @namespace    http://tampermonkey.net/
4 // @version      1.4
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
14 // ==/UserScript==
16 var localStoreThreads;
17 var bowser;
18 var finished = false;
19 var windowDisplayed = false;
20 var defaultExpireTime = 172800000;
21 var expireTime;
23 var windowDisplayed = false;
24 var numberOfFilters = 0;
25 var initialFilters = [];
26 var kill = [];
27 var finished = false;
28 var observer;
29 var secondObserverSet;
31 //is storage possible
32 function storageAvailable(type) {
33     try {
34         var storage = window[type],
35             x = '__storage_test__';
36         storage.setItem(x, x);
37         storage.removeItem(x);
38         return true;
39     }
40     catch(e) {
41         return e instanceof DOMException && (
42             // everything except Firefox
43             e.code === 22 ||
44             // Firefox
45             e.code === 1014 ||
46             // test name field too, because code might not be present
47             // everything except Firefox
48             e.name === 'QuotaExceededError' ||
49             // Firefox
50             e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
51             // acknowledge QuotaExceededError only if there's something already stored
52             storage.length !== 0;
53     }
56 //What Browser
57 function detectBrowser() { 
58     if((navigator.userAgent.indexOf("Opera") || navigator.userAgent.indexOf('OPR')) != -1 ) 
59     {
60         console.log("Opera");
61         return 0;
62     }
63     else if(navigator.userAgent.indexOf("Chrome") != -1 )
64     {
65         console.log("Chrome");
66         return 1;
67     }
68     else if(navigator.userAgent.indexOf("Safari") != -1)
69     {
70         console.log("Safari");
71         return 2;
72     }
73     else if(navigator.userAgent.indexOf("Firefox") != -1 ) 
74     {
75         console.log("FireFox");
76         return 3;
77     }
78     else if((navigator.userAgent.indexOf("MSIE") != -1 ) || (!!document.documentMode == true )) //IF IE > 10
79     {
80         console.log("IE");
81         return 4;
82     }  
83     else 
84     {
85         console.log("Other");
86         return -1;
87     }
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());
99         }
100         else {
101             console.log("No Storage");
102         }
103         this.src = this.src + ".HIDDEN" +  "?" + Date.now();
104         return false;
105     }
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);
112         }
113         else {
114             console.log("No Storage");
115         }
116         this.src = this.src.substring(0, hideIndex);
117         return false;
118     }
119     return true;
122 //functions to find properties by regex
123 function getPropertyByRegex(obj,propName) {
124     var re = new RegExp("^" + propName + "(\\[\\d*\\])?$"),
125         key;
126     var rtnArray = [];
127     for (key in obj)
128         if (re.test(key))
129             rtnArray.push(key);
130     return rtnArray;
133 //retrieve from memory the hidden iamges
134 var j = 0;
135 function retrieveStates(){
136     var i = 0,
137         oJson = {},
138         sKey;
139     while( i < window.localStorage.length) {
140         i++;
141         sKey = window.localStorage.key(i);
142         oJson[sKey] = window.localStorage.getItem(sKey);
143     }
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(); 
151             j++;
152         }
153         else if((node = document.getElementById("p"+elem.substring(1))) !== null && node.src.indexOf(".HIDDEN") == -1){
154             node.src = node.src + ".HIDDEN" +  "?" + Date.now();           
155             j++;
156         }
157         else if((node = document.getElementById("thread-"+elem.substring(1))) !== null && node.src.indexOf(".HIDDEN") == -1){
158             node.src = node.src + ".HIDDEN" +  "?" + Date.now(); 
159             j++;
160         }
161         else if((node = document.getElementById("thumb-"+elem.substring(1))) !== null && node.src.indexOf(".HIDDEN") == -1){
162             node.src = node.src + ".HIDDEN" +  "?" + Date.now(); 
163             j++;
164         }
165     });
166     console.log(j);
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(){
215         // console.log("A");
216         if (storageAvailable('localStorage')) {
217             var time = document.getElementById("expirationTime");
218             var msTime = time.value * 3600000;
219             if (msTime == 0) msTime = defaultExpireTime; 
220             expireTime = msTime;
221             //console.log("B" + expireTime);
222             localStorage.setItem("ExpirationTime", msTime);
223             hideToggle();
224         }
225     });
226     expirationInput.setAttribute("value", localStorage.getItem("ExpirationTime") / 3600000);
227     containerDiv.appendChild(setButton);
229     document.body.appendChild(windowDiv);
233 function hideToggle(){
234     if(windowDisplayed){
235         document.getElementById("hiWindow").style.display = "none";
236         document.getElementById("hiBackground").style.display = "none";
237         windowDisplayed = false;
238     }
239     else{
240         document.getElementById("hiWindow").style.display = "inline-block";
241         document.getElementById("hiBackground").style.display = "inline-block";
242         windowDisplayed = true;
243     }     
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);
254     }
255     else{
256         document.body.appendChild(button);
257         button.addEventListener("click", hideToggle);
258     }
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('"-"');
275     var i = 0;
276     rtn.forEach(function(filter){
277         rtn[i] = filter.replace("\"", "");
278         i++;
279     });
280     return rtn;
283 function loadSettings(){
284     var i = 0,
285         oJson = {},
286         sKey;
287     while( i < window.localStorage.length) {
288         i++;
289         sKey = window.localStorage.key(i);
290         oJson[sKey] = window.localStorage.getItem(sKey);
291     }
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]));
297     });
300 function saveSettings(){
301     kill = [];
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;
307             var setting = "g";
308             if(pattern === "" || replacement === "") continue; 
309             if (pattern.charAt(0) == "/" && pattern.charAt(pattern.length - 1) == "/"){
310                 pattern = pattern + setting;
311             }
312             else if(pattern.charAt(0) !== "/" && pattern.substr(pattern.length - 2).match(/\/[a-zA-Z$]/) == null){
313                 pattern = "/" + pattern + "/" + setting;
314             }
315             document.getElementById("Pattern"+i).value = pattern;
316             var saveString = '"' + document.getElementById("Active"+i).checked + '"-"' + pattern + '"-"' + replacement + '"';
317             window.localStorage.setItem("filter" + i, saveString);
318         }
319     }
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);
403     }
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(){
452     if(windowDisplayed){
453         document.getElementById("FilterWindow").style.display = "none";
454         document.getElementById("FilterBackground").style.display = "none";
455         windowDisplayed = false;
456     }
457     else{
458         document.getElementById("FilterWindow").style.display = "inline-block";
459         document.getElementById("FilterBackground").style.display = "inline-block";
460         windowDisplayed = true;
461     }
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);
474 function addRow(){
475     var table = document.getElementById("FilterTable");
476     table.deleteRow(parseInt(numberOfFilters) + 1);
477     numberOfFilters++;
478     
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);
520     
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);
551         numberOfFilters--;
552     }
555 function setTable(){
556     var i = 0;
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;
561         }
562         else if(filter[0] == "false"){
563             document.getElementById("Active"+i).checked = false;
564         }
565         document.getElementById("Pattern"+i).value = filter[1];
566         document.getElementById("Replacement"+i).value = filter[2];
567         i++;
568     });
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(){
585     if(finished) {
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;
594         }
595     }
596     else {
597         var start = document;
598     }
599     if(start === null) return;
600     var itterator = document.createTreeWalker(start, NodeFilter.SHOW_ELEMENTS, NodeFilter.SHOW_ELEMENTS);
601     var node = "";
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){
609                 finished = true;
610                 node.id = node.parentNode.parentNode.id + "IMG";
611                 node.addEventListener("click", hideImage, {passive:false, capture:false, once:false});
612             }
613         }
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);
624                         if(active.checked){
625                             finished = true;
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!$%^&*()_+|~\\-=`{}\\[\\]:\";'<>?,\\.\\/]|$)";
632                             try{
633                                 var regex = new RegExp(filterText, setting);
634                                 localNode.textContent = localNode.textContent.replace(regex, " " + replacement.value + " ");
635                             }
636                             catch(e){
637                                 alert(i + "'s regex was invalid");
638                                 kill[i] = true;
639                             }
640                             // console.log("Inner: " + (Date.now() - later));
641                         }
642                     }
643                 }
644                 else break;
645             }
647         }
648     }
651 //detect page changes
652 function observeDynamicMutation(node){
653     if(node === undefined)
654         node = document;
655     observer = new MutationObserver(function callBack(mutations){
656         var later = Date.now();
657         retrieveStates();
658         modifyDOM();
659         //console.log("PKX: " + (Date.now() - later));
660     });
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
666     return;
668 //initial onload setup
669 function hideSetup(){
670     modifyDOM();
671     retrieveStates();
672     hideButton();
675 function filterSetup(){
676     loadSettings();
677     filterButton();
678     filterWindow();
679     setTable();
682 function pkxSetup(){
683     hideSetup();
684     filterSetup();
685     observeDynamicMutation();
688 browser = detectBrowser();
689 pkxSetup();
690 console.log("Script loaded: 4chanPKX");