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
17 This userscript enables 4chan users to hide images in the catalog and threads.
18 Gives the ability to hide images with ctrl+shift+click. Stores in browser memory for new sessions.
19 Also includes the ability to do word replacements with a regex replacement system.
22 var local_store_threads;
25 var window_displayed = false;
26 var default_expire_time = 172800000;
29 var number_of_filters = 0;
30 var initial_filters = [];
35 //The following is image hiding functions.
36 //The next are filter functions
37 //The last are setup functions
40 0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
41 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
42 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
43 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
44 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
45 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
46 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
47 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
52 function storageAvailable(type) {
54 var storage = window[type],
55 x = '__storage_test__';
56 storage.setItem(x, x);
57 storage.removeItem(x);
61 //From https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
62 return e instanceof DOMException && (
63 // everything except Firefox
67 // test name field too, because code might not be present
68 // everything except Firefox
69 e.name === 'QuotaExceededError' ||
71 e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
72 // acknowledge QuotaExceededError only if there's something already stored
78 function detectBrowser() {
79 if((navigator.userAgent.indexOf("Opera") || navigator.userAgent.indexOf('OPR')) != -1 )
81 //console.log("Opera");
84 else if(navigator.userAgent.indexOf("Chrome") != -1 )
86 //console.log("Chrome");
89 else if(navigator.userAgent.indexOf("Safari") != -1)
91 //console.log("Safari");
94 else if(navigator.userAgent.indexOf("Firefox") != -1 )
96 //console.log("FireFox");
99 else if((navigator.userAgent.indexOf("MSIE") != -1 ) || (!!document.documentMode == true )) //IF IE > 10
106 //console.log("Other");
111 //hide image onclick listener.
112 //Method 404's a given image. This 404'ing allows image dissabling to be toggled on and off.
113 //Post number associated with the image is stored in local storage.
114 function hideImage(event){
115 var hide_index = this.src.indexOf(".HIDDEN");
116 if((event.ctrlKey && event.shiftKey) && hide_index == -1){
117 event.preventDefault();
118 event.stopPropagation();
119 if (storageAvailable('localStorage')) {
120 if(this.id.charAt(0) == "p") this.id = "f" + this.id.substr(1);
121 localStorage.setItem(this.id, Date.now());
124 //console.log("No Storage");
126 //some browsers require a querry on the image URL to 404 it.
127 this.src = this.src + ".HIDDEN" + "?" + Date.now();
130 else if(event.ctrlKey && event.shiftKey){
131 event.preventDefault();
132 event.stopPropagation();
133 if (storageAvailable('localStorage')) {
134 if(this.id.charAt(0) == "p") this.id = "f" + this.id.substr(1);
135 localStorage.removeItem(this.id);
138 //console.log("No Storage");
140 this.src = this.src.substring(0, hide_index);
146 //functions to find properties by regex
147 function getPropertyByRegex(obj,propName) {
148 var re = new RegExp("^" + propName + "(\\[\\d*\\])?$"),
157 //retrieve from memory the hidden images
158 //Images are stored in memory as f<ID_NUMBER>IMG and recalled using the storage_key
159 //Function makes a check to see if the hiding time limit for the thread has expired or not.
160 var hidden_count = 0;
161 function retrieveStates(){
162 var storage_position = 0,
165 while(storage_position < window.localStorage.length) {
167 storage_key = window.localStorage.key(storage_position);
168 oJson[storage_key] = window.localStorage.getItem(storage_key);
170 local_store_threads = getPropertyByRegex(oJson,"f[0-9]*IMG");
171 expire_time = localStorage.getItem("ExpirationTime");
173 local_store_threads.forEach(function callback(thread){
174 //console.log(Date.now() - oJson[thread] + " > " + expire_time);
175 if(Date.now() - oJson[thread] > expire_time)
176 localStorage.removeItem(thread);
180 image_node = document.getElementById(""+thread);
181 if(image_node !== null && image_node.src.indexOf(".HIDDEN") == -1){
182 image_node.src = image_node.src + ".HIDDEN" + "?" + Date.now();
186 image_node = document.getElementById("p"+thread.substring(1));
187 if(image_node !== null && image_node.src.indexOf(".HIDDEN") == -1){
188 image_node.src = image_node.src + ".HIDDEN" + "?" + Date.now();
192 image_node = document.getElementById("thread-"+thread.substring(1));
193 if(image_node !== null && image_node.src.indexOf(".HIDDEN") == -1){
194 image_node.src = image_node.src + ".HIDDEN" + "?" + Date.now();
197 image_node = document.getElementById("thumb-"+thread.substring(1));
198 if(image_node !== null && image_node.src.indexOf(".HIDDEN") == -1){
199 image_node.src = image_node.src + ".HIDDEN" + "?" + Date.now();
206 // half the ammount because it hides both index and catalog
207 console.log("HIDDEN THREADS: " + hidden_count / 2);
211 //settings for time expiration on image hiding
212 function hideWindow(){
213 var style = document.createElement('style');
214 style.innerHTML = ".inputs{background-color:rgb(200,200,200);margin:5px 7px;width:100px;}";
215 document.body.appendChild(style);
217 var background_div = document.createElement("div");
218 background_div.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");
219 background_div.setAttribute("id", "hiBackground");
220 document.body.appendChild(background_div);
221 background_div.addEventListener("click", hideToggle);
223 var window_div = document.createElement("div");
224 window_div.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");
225 window_div.setAttribute("id", "hiWindow");
227 var close_div = document.createElement("div");
228 close_div.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");
229 close_div.addEventListener("click", hideToggle);
230 window_div.appendChild(close_div);
232 var title_para = document.createElement("p");
233 title_para.setAttribute("style", "margin-left:5px;margin-top:5px");
234 var title_text = document.createTextNode("Filter Settings");
235 title_para.appendChild(title_text);
236 window_div.appendChild(title_para);
238 var container_div = document.createElement("div");
239 container_div.setAttribute("style","background-color:white;margin:0 0;padding:5px;");
240 window_div.appendChild(container_div);
242 var expiration_label = document.createElement("label");
243 var expiration_text = document.createTextNode("Expiration Time(hours): ");
244 expiration_label.appendChild(expiration_text);
245 container_div.appendChild(expiration_label);
246 var expiration_input = document.createElement("input");
247 expiration_input.setAttribute("id", "expirationTime");
248 container_div.appendChild(expiration_input);
249 container_div.appendChild(expiration_input);
250 container_div.appendChild(document.createElement("br"));
251 var set_button = document.createElement("input");
252 set_button.setAttribute("type", "button");
253 set_button.setAttribute("id", "setTime");
254 set_button.setAttribute("value", "Set Time");
255 set_button.addEventListener("click", function(){
256 if (storageAvailable('localStorage')) {
257 var time = document.getElementById("expirationTime");
258 var millisecond_time = time.value * 3600000;
259 if (millisecond_time == 0 || millisecond_time === null || millisecond_time === undefined) millisecond_time = default_expire_time;
260 expire_time = millisecond_time;
261 localStorage.setItem("ExpirationTime", millisecond_time);
265 expiration_input.setAttribute("value", localStorage.getItem("ExpirationTime") / 3600000);
266 container_div.appendChild(set_button);
268 document.body.appendChild(window_div);
272 function hideToggle(){
273 if(window_displayed){
274 document.getElementById("hiWindow").style.display = "none";
275 document.getElementById("hiBackground").style.display = "none";
276 window_displayed = false;
279 document.getElementById("hiWindow").style.display = "inline-block";
280 document.getElementById("hiBackground").style.display = "inline-block";
281 window_displayed = true;
285 function hideButton(){
286 var hide_button = document.createElement("input");
287 hide_button.setAttribute("Value", "Hide Image Settings");
288 hide_button.setAttribute("type", "button");
289 hide_button.setAttribute("style", "position:absolute;top:45px");
290 hide_button.addEventListener("click", hideWindow);
291 if(document.body === null){
292 setTimeout(hideButton, 30);
295 document.body.appendChild(hide_button);
296 hide_button.addEventListener("click", hideToggle);
298 expire_time = localStorage.getItem("ExpirationTime");
302 /**111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
303 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
304 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
305 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
306 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
307 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
308 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
309 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
312 //store filter settings
313 function loadSettings(){
314 var filter_setting = 0,
317 while( filter_setting < window.localStorage.length) {
319 storage_key = window.localStorage.key(filter_setting);
320 oJson[storage_key] = window.localStorage.getItem(storage_key);
322 number_of_filters = oJson["q"];
323 //console.log(number_of_filters);
324 filters = getPropertyByRegex(oJson,"filter[0-9]*");
325 filters.forEach(function(filter){
326 initial_filters.push(formatSettings(oJson[filter]));
330 function saveSettings(){
332 kill = []; //Determins if a certain pattern should be used or not due to regex errors from the user
334 if(storageAvailable('localStorage')){
335 window.localStorage.setItem("q", number_of_filters);
336 for (var pattern_input = 0 ; pattern_input < number_of_filters; pattern_input++){
337 var pattern_to_store = document.getElementById("Pattern"+pattern_input).value;
338 var replacement_to_store = document.getElementById("Replacement"+pattern_input).value;
340 if(pattern_to_store === "" || replacement_to_store === "") continue;
341 if (pattern_to_store.charAt(0) == "/" && pattern_to_store.charAt(pattern_to_store.length - 1) == "/"){
342 pattern_to_store = pattern_to_store + setting;
344 else if(pattern_to_store.charAt(0) !== "/" && pattern_to_store.substr(pattern_to_store.length - 2).match(/\/[a-zA-Z$]/) == null){
345 pattern_to_store = "/" + pattern_to_store + "/" + setting;
347 document.getElementById("Pattern"+pattern_input).value = pattern_to_store;
348 var save_string = '"' + document.getElementById("Active"+pattern_input).checked + '"-"' + pattern_to_store + '"-"' + replacement_to_store + '"';
349 window.localStorage.setItem("filter" + pattern_input, save_string);
352 alert("Replacements Saved");
355 //Splits the saved settings into components
356 function formatSettings(input){
357 var rtn = input.split('"-"');
359 rtn.forEach(function(filter){
360 rtn[i] = filter.replace("\"", "");
367 function filterWindow(){
368 var style = document.createElement('style');
369 style.innerHTML = ".inputs{background-color:rgb(200,200,200);margin:5px 7px;width:100px;}";
370 document.body.appendChild(style);
372 var background_div = document.createElement("div");
373 background_div.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");
374 background_div.setAttribute("id", "FilterBackground");
375 document.body.appendChild(background_div);
376 background_div.addEventListener("click", filterToggle);
378 var window_div = document.createElement("div");
379 window_div.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");
380 window_div.setAttribute("id", "FilterWindow");
382 var close_div = document.createElement("div");
383 close_div.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");
384 close_div.addEventListener("click", filterToggle);
385 window_div.appendChild(close_div);
387 var title_para = document.createElement("p");
388 title_para.setAttribute("style", "margin-left:5px;margin-top:5px");
389 var title_text = document.createTextNode("Filter Settings");
390 title_para.appendChild(title_text);
391 window_div.appendChild(title_para);
393 var container_div = document.createElement("div");
394 container_div.setAttribute("style","background-color:white;margin:0 0;padding:5px;");
395 window_div.appendChild(container_div);
397 var filter_table = document.createElement("table");
398 filter_table.setAttribute("style", "text-align:center;");
399 filter_table.setAttribute("id", "filter_table");
400 container_div.appendChild(filter_table);
402 var table_row = document.createElement("tr");
403 filter_table.appendChild(table_row);
404 var table_head_active = document.createElement("th");
405 var head_text_active = document.createTextNode("Active");
406 table_head_active.appendChild(head_text_active);
407 filter_table.appendChild(table_head_active);
408 var table_head_pattern = document.createElement("th");
409 var headTextPattern = document.createTextNode("Pattern");
410 table_head_pattern.appendChild(headTextPattern);
411 filter_table.appendChild(table_head_pattern);
412 var table_head_replacement = document.createElement("th");
413 var head_text_replacement = document.createTextNode("Replacement");
414 table_head_replacement.appendChild(head_text_replacement);
415 filter_table.appendChild(table_head_replacement);
418 //Create the pattern table
419 //loop to create rows
420 if (number_of_filters === 0 || isNaN(number_of_filters)) number_of_filters = 6;
421 for (var i = 0; i < number_of_filters ; i++){
422 var table_row_contents = document.createElement("tr");
423 table_row_contents.setAttribute("id", "FilterRow" + i);
425 var table_data_active = document.createElement("td");
426 var table_checkbox_active = document.createElement("input");
427 table_checkbox_active.setAttribute("type", "checkbox");
428 table_checkbox_active.setAttribute("id", "Active" + i);
429 table_data_active.appendChild(table_checkbox_active);
430 table_row_contents.appendChild(table_data_active);
432 var table_data_pattern = document.createElement("td");
433 var table_input_pattern = document.createElement("input");
434 table_input_pattern.setAttribute("class", "inputs");
435 table_input_pattern.setAttribute("id", "Pattern" + i);
436 table_data_pattern.appendChild(table_input_pattern);
437 table_row_contents.appendChild(table_data_pattern);
439 var table_data_replacement = document.createElement("td");
440 var table_input_replacement = document.createElement("input");
441 table_input_replacement.setAttribute("class", "inputs");
442 table_input_replacement.setAttribute("id", "Replacement" + i);
443 table_data_replacement.appendChild(table_input_replacement);
444 table_row_contents.appendChild(table_data_replacement);
446 filter_table.appendChild(table_row_contents);
449 var table_last_contents = document.createElement("tr");
451 var table_add_collumn = document.createElement("td");
452 var table_add_row_button = document.createElement("input");
453 var table_subtract_row_button = document.createElement("input");
454 table_subtract_row_button.setAttribute("type", "button");
455 table_subtract_row_button.setAttribute("value", "-");
456 table_subtract_row_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
457 table_add_collumn.appendChild(table_subtract_row_button);
458 table_subtract_row_button.addEventListener("click", removeRow);
459 table_add_row_button.setAttribute("type", "button");
460 table_add_row_button.setAttribute("value", "+");
461 table_add_row_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
462 table_add_collumn.appendChild(table_add_row_button);
463 table_add_row_button.addEventListener("click", addRow);
465 table_last_contents.appendChild(table_add_collumn);
467 var table_set_collumn = document.createElement("td");
468 var table_confirm_button = document.createElement("input");
469 table_confirm_button.setAttribute("type", "button");
470 table_confirm_button.setAttribute("id", "table_confirm_button");
471 table_confirm_button.setAttribute("value", "Set Replacements");
472 table_confirm_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
473 table_confirm_button.addEventListener("click", saveSettings);
474 table_confirm_button.addEventListener("click", modifyDOM);
475 table_confirm_button.addEventListener("click", filterToggle);
476 table_set_collumn.appendChild(table_confirm_button);
477 table_last_contents.appendChild(table_set_collumn);
480 var table_close_collumn = document.createElement("td");
481 var table_close_button = document.createElement("input");
482 table_close_button.setAttribute("type", "button");
483 table_close_button.setAttribute("value", "Close Menu");
484 table_close_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
485 table_close_button.addEventListener("click", filterToggle);
486 table_close_collumn.appendChild(table_close_button);
487 table_last_contents.appendChild(table_close_collumn);
489 filter_table.appendChild(table_last_contents);
491 document.body.appendChild(window_div);
495 function filterToggle(){
496 if(window_displayed){
497 document.getElementById("FilterWindow").style.display = "none";
498 document.getElementById("FilterBackground").style.display = "none";
499 window_displayed = false;
502 document.getElementById("FilterWindow").style.display = "inline-block";
503 document.getElementById("FilterBackground").style.display = "inline-block";
504 window_displayed = true;
508 function filterButton(){
509 var filter_button = document.createElement("input");
510 filter_button.setAttribute("Value", "Word Filter Settings");
511 filter_button.setAttribute("type", "button");
512 filter_button.setAttribute("style", "position:absolute;top:75px");
513 filter_button.addEventListener("click", filterWindow);
514 document.body.appendChild(filter_button);
515 filter_button.addEventListener("click", filterToggle);
519 var filter_table = document.getElementById("filter_table");
520 filter_table.deleteRow(parseInt(number_of_filters) + 1);
523 var table_row_contents = document.createElement("tr");
524 table_row_contents.setAttribute("id", "FilterRow" + (number_of_filters - 1));
526 var table_data_active = document.createElement("td");
527 var table_checkbox_active = document.createElement("input");
528 table_checkbox_active.setAttribute("type", "checkbox");
529 table_checkbox_active.setAttribute("id", "Active" + (number_of_filters - 1));
530 table_data_active.appendChild(table_checkbox_active);
531 table_row_contents.appendChild(table_data_active);
533 var table_data_pattern = document.createElement("td");
534 var table_input_pattern = document.createElement("input");
535 table_input_pattern.setAttribute("class", "inputs");
536 table_input_pattern.setAttribute("id", "Pattern" + (number_of_filters - 1));
537 table_data_pattern.appendChild(table_input_pattern);
538 table_row_contents.appendChild(table_data_pattern);
540 var table_data_replacement = document.createElement("td");
541 var table_input_replacement = document.createElement("input");
542 table_input_replacement.setAttribute("class", "inputs");
543 table_input_replacement.setAttribute("id", "Replacement" + (number_of_filters - 1));
544 table_data_replacement.appendChild(table_input_replacement);
545 table_row_contents.appendChild(table_data_replacement);
547 filter_table.appendChild(table_row_contents);
549 var table_last_contents = document.createElement("tr");
551 var table_add_collumn = document.createElement("td");
552 var table_add_row_button = document.createElement("input");
553 var table_subtract_row_button = document.createElement("input");
554 table_subtract_row_button.setAttribute("type", "button");
555 table_subtract_row_button.setAttribute("value", "-");
556 table_subtract_row_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
557 table_add_collumn.appendChild(table_subtract_row_button);
558 table_subtract_row_button.addEventListener("click", removeRow);
559 table_add_row_button.setAttribute("type", "button");
560 table_add_row_button.setAttribute("value", "+");
561 table_add_row_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
562 table_add_collumn.appendChild(table_add_row_button);
563 table_add_row_button.addEventListener("click", addRow);
565 table_last_contents.appendChild(table_add_collumn);
567 var table_set_collumn = document.createElement("td");
568 var table_confirm_button = document.createElement("input");
569 table_confirm_button.setAttribute("type", "button");
570 table_confirm_button.setAttribute("id", "table_confirm_button");
571 table_confirm_button.setAttribute("value", "Set Replacements");
572 table_confirm_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
573 table_confirm_button.addEventListener("click", saveSettings);
574 table_confirm_button.addEventListener("click", modifyDOM);
575 table_confirm_button.addEventListener("click", filterToggle);
576 table_set_collumn.appendChild(table_confirm_button);
577 table_last_contents.appendChild(table_set_collumn);
579 var table_close_collumn = document.createElement("td");
580 var table_close_button = document.createElement("input");
581 table_close_button.setAttribute("type", "button");
582 table_close_button.setAttribute("value", "Close Menu");
583 table_close_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
584 table_close_button.addEventListener("click", filterToggle);
585 table_close_collumn.appendChild(table_close_button);
586 table_last_contents.appendChild(table_close_collumn);
588 filter_table.appendChild(table_last_contents);
591 function removeRow(){
592 var filter_table = document.getElementById("filter_table");
593 if(number_of_filters != 0){
594 filter_table.deleteRow(number_of_filters);
600 var filter_count = 0;
601 initial_filters.forEach(function(filter){
602 if(filter[2] === null || filter[1] === null || filter[0] === null || filter_count == number_of_filters) return;
603 if(filter[0] == "true"){
604 document.getElementById("Active"+filter_count).checked = true;
606 else if(filter[0] == "false"){
607 document.getElementById("Active"+filter_count).checked = false;
609 document.getElementById("Pattern"+filter_count).value = filter[1];
610 document.getElementById("Replacement"+filter_count).value = filter[2];
616 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
617 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
618 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
619 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
620 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
621 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
622 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
623 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
624 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
625 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
627 //Functions to set the DOM listener and observers
629 //detect page changes
630 function observeDynamicMutation(node){
631 if(node === undefined)
633 //on mutation event call functions
634 observer = new MutationObserver(function callBack(mutations){
637 var config = {subtree: true, childList:true};//Subtree checks children of node, while subtree repeats actions on the child and sets observers on them
638 observer.observe(node, config);
641 function modifyDOM(){
642 var start = document.getElementById("delform");
643 var itterator = document.createTreeWalker(start, NodeFilter.SHOW_ELEMENTS, NodeFilter.SHOW_ELEMENTS);
646 while((node = itterator.nextNode())){
647 var cname = node.className;
648 var tag = node.tagName;
649 if(tag === "IMG" || tag === "img"){
650 if(!/(f|p)\d+IMG/.test(node.id) && (node.getAttribute("data-md5") !== null || node.className.indexOf("thumb") != -1)){
651 node.id = node.parentNode.parentNode.id + "IMG";
652 node.addEventListener("click", hideImage, {passive:false, capture:false, once:false});
655 else if(cname == "postMessage"){
656 while((localNode = itterator.nextNode())){
657 var className = localNode.className;
658 if(className == undefined || className == "quotelink"){
659 for(var i = 0 ; i < number_of_filters; i++){
660 if(kill[i] == true) continue;
661 filter = document.getElementById("Pattern"+i);
662 replacement = document.getElementById("Replacement"+i);
663 active = document.getElementById("Active"+i);
665 var lastChar = filter.value.length - 1;
666 var filterText = filter.value;
667 if(filterText === "") break;
668 var setting = filterText.substr(lastChar);
669 filterText = filterText.substr(1, lastChar-2);
670 filterText = "(^|[\\s!$%^&*()_+|~\\-=`{}\\[\\]:\";'<>?,\\.\\/])" + filterText + "([\\s!$%^&*()_+|~\\-=`{}\\[\\]:\";'<>?,\\.\\/]|$)";
672 var regex = new RegExp(filterText, setting);
673 localNode.textContent = localNode.textContent.replace(regex, " " + replacement.value + " ");
676 alert(i + "'s regex was invalid");
689 if (window.top != window.self) //-- Don't run on frames or iframes
692 //initial onload setup
693 function hideSetup(){
698 function filterSetup(){
709 observeDynamicMutation();
713 //currently has issues due to a bug in 4chanX's API
714 var page_setup = false;
715 document.addEventListener('4chanXInitFinished', function(e) {
716 setTimeout(function(){// bypass 4chanX bug
717 browser = detectBrowser();
719 console.log("Script loaded: 4chanPKX");
724 setTimeout(function(){
726 browser = detectBrowser();
728 console.log("Script loaded: 4chanPKX");