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-start
12 // @updateURL https://github.com/CHibiki/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;
30 var md5_filters_arr
= [];
32 var number_of_filters
= 0;
33 var initial_filters
= [];
34 var filtered_threads
= [];
39 var blank_png
= "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAACXBIWXMAALiMAAC4jAHM9rsvAAAAG3RFWHRTb2Z0d2FyZQBDZWxzeXMgU3R1ZGlvIFRvb2zBp+F8AAAAo0lEQVR42u3RAQ0AAAjDMO5f9LFBSCdhTdvRnQIEiIAAERAgAgJEQIC4AERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABAQIECACAkRAgAjI9xbzUCtI4axs4wAAAABJRU5ErkJggg==";
41 //The following is image hiding functions.
42 //The next are filter functions
43 //The last are setup functions
46 0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
47 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
48 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
49 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
50 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
51 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
52 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
53 //0000000000000000000000000000000000000000000000000000000000000000000000000000000////0000000000000000000000000000000000000000000000000000000000000000000000000000000//
58 function storageAvailable(type
) {
60 var storage
= window
[type
],
61 x
= '__storage_test__';
62 storage
.setItem(x
, x
);
63 storage
.removeItem(x
);
67 //From https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
68 return e
instanceof DOMException
&& (
69 // everything except Firefox
73 // test name field too, because code might not be present
74 // everything except Firefox
75 e
.name
=== 'QuotaExceededError' ||
77 e
.name
=== 'NS_ERROR_DOM_QUOTA_REACHED') &&
78 // acknowledge QuotaExceededError only if there's something already stored
84 function detectBrowser() {
85 if((navigator
.userAgent
.indexOf("Opera") || navigator
.userAgent
.indexOf('OPR')) != -1 )
90 else if(navigator
.userAgent
.indexOf("Chrome") != -1 )
92 console
.log("Chrome");
95 else if(navigator
.userAgent
.indexOf("Safari") != -1)
97 console
.log("Safari");
100 else if(navigator
.userAgent
.indexOf("Firefox") != -1 )
102 console
.log("FireFox");
105 else if((navigator
.userAgent
.indexOf("MSIE") != -1 ) || (!!document
.documentMode
== true )) //IF IE > 10
112 console
.log("Other");
117 //hide image onclick listener.
118 //Method 404's a given image. This 404'ing allows image dissabling to be toggled on and off.
119 //Post number associated with the image is stored in local storage.
120 function hideImage(event
){
121 var hide_index
= this.src
.indexOf("base64");
122 if((event
.ctrlKey
&& event
.shiftKey
) && hide_index
== -1){
123 event
.preventDefault();
124 event
.stopPropagation();
125 if (storageAvailable('localStorage')) {
126 localStorage
.setItem(this.getAttribute("hide-grouping"), Date
.now());
129 console
.log("No Storage");
131 //some browsers require a querry on the image URL to 404 it.
132 this.setAttribute("hidden-src", this.src
);
133 this.src
= blank_png
;//this.src + ".HIDDEN" + "?" + Date.now();
136 else if(event
.ctrlKey
&& event
.shiftKey
){
137 event
.preventDefault();
138 event
.stopPropagation();
139 if (storageAvailable('localStorage')) {
140 localStorage
.removeItem(this.getAttribute("hide-grouping"));
143 console
.log("No Storage");
145 this.src
= this.getAttribute("hidden-src");
151 //functions to find properties by regex
152 function getPropertyByRegex(obj
,propName
) {
153 var re
= new RegExp("^" + propName
+ "(\\[\\d*\\])?$"),
162 //retrieve from memory the hidden images
163 //Images are stored in memory as f<ID_NUMBER>IMG and recalled using the storage_key
164 //Function makes a check to see if the hiding time limit for the thread has expired or not.
165 //Note: Must have the DOM itterate through before retrieval
166 function retrieveStates(){
167 var storage_position
= 0,
170 while(storage_position
< window
.localStorage
.length
) {
171 storage_key
= window
.localStorage
.key(storage_position
);
172 oJson
[storage_key
] = window
.localStorage
.getItem(storage_key
);
175 local_store_threads
= getPropertyByRegex(oJson
,"[0-9]+IMG");
176 expire_time
= localStorage
.getItem("Expiration_Time");
177 md5_filters
= localStorage
.getItem("MD5_List_FSE");
178 if(md5_filters
!== null)
179 md5_filters_arr
= md5_filters
.split("\n");
180 md5_filters_arr
.forEach(function(md5
, index
){
182 md5_filters_arr
[index
] = md5
.substring(1, md5
.length
- 1);
187 //settings for time expiration on image hiding
188 function hideWindow(){
189 var style
= document
.createElement('style');
190 style
.innerHTML
= ".inputs{background-color:rgb(200,200,200);margin:5px 7px;width:100px;}";
191 document
.body
.appendChild(style
);
193 var background_div
= document
.createElement("div");
194 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");
195 background_div
.setAttribute("id", "hiBackground");
196 document
.body
.appendChild(background_div
);
197 background_div
.addEventListener("click", hideToggle
);
199 var window_div
= document
.createElement("div");
200 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");
201 window_div
.setAttribute("id", "hiWindow");
203 var close_div
= document
.createElement("div");
204 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");
205 close_div
.addEventListener("click", hideToggle
);
206 window_div
.appendChild(close_div
);
208 var title_para
= document
.createElement("p");
209 title_para
.setAttribute("style", "margin-left:5px;margin-top:5px");
210 var title_text
= document
.createTextNode("Filter Settings");
211 title_para
.appendChild(title_text
);
212 window_div
.appendChild(title_para
);
214 var container_div
= document
.createElement("div");
215 container_div
.setAttribute("style","background-color:white;margin:0 0;padding:5px;");
216 window_div
.appendChild(container_div
);
218 var expiration_label
= document
.createElement("label");
219 var expiration_text
= document
.createTextNode("Non-MD5 Expiration Time(hours): ");
220 expiration_label
.appendChild(expiration_text
);
221 container_div
.appendChild(expiration_label
);
222 var expiration_input
= document
.createElement("input");
223 expiration_input
.setAttribute("id", "Expiration_Time");
225 expiration_input
.value
= expire_time
/ 3600000;
227 container_div
.appendChild(expiration_input
);
228 container_div
.appendChild(expiration_input
);
229 container_div
.appendChild(document
.createElement("hr"));
231 var md5_label
= document
.createElement("label");
232 var md5_text
= document
.createTextNode("MD5 Filters:");
233 var md5_textarea
= document
.createElement("TextArea");
234 md5_textarea
.setAttribute("style", "width:98%;height:217px");
236 if(md5_filters
!== null)
237 md5_textarea
.value
= md5_filters
;
239 md5_textarea
.setAttribute("placeholder", "Enter MD5 like on 4chanX... \n/abc123/\n/def890/");
240 md5_textarea
.setAttribute("ID", "MD5_List_FSE");
241 container_div
.appendChild(md5_label
);
242 md5_label
.appendChild(md5_text
);
243 container_div
.appendChild(document
.createElement("br"));
244 container_div
.appendChild(md5_textarea
);
246 container_div
.appendChild(document
.createElement("hr"));
248 var set_button
= document
.createElement("input");
249 set_button
.setAttribute("type", "button");
250 set_button
.setAttribute("id", "setTime");
251 set_button
.setAttribute("value", "Set");
252 set_button
.addEventListener("click", function(){
253 if (storageAvailable('localStorage')) {
254 var time
= document
.getElementById("Expiration_Time");
255 var millisecond_time
= time
.value
* 3600000;
256 if (millisecond_time
== 0 || millisecond_time
=== null || millisecond_time
=== undefined) millisecond_time
= default_expire_time
;
257 expire_time
= millisecond_time
;
258 localStorage
.setItem("Expiration_Time", millisecond_time
);
260 md5_filters
= document
.getElementById("MD5_List_FSE").value
;
261 localStorage
.setItem("MD5_List_FSE", md5_filters
);
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
);
301 /**111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
302 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
303 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
304 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
305 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
306 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
307 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
308 //111111111111111111111111111111111111111111111111111111111111////111111111111111111111111111111111111111111111111111111111111//
311 //store filter settings
312 function loadSettings(){
313 var filter_setting
= 0,
316 while( filter_setting
< window
.localStorage
.length
) {
318 storage_key
= window
.localStorage
.key(filter_setting
);
319 oJson
[storage_key
] = window
.localStorage
.getItem(storage_key
);
321 number_of_filters
= oJson
["q"];
322 filters
= getPropertyByRegex(oJson
,"filter[0-9]*");
323 filters
.forEach(function(filter
){
324 initial_filters
.push(formatSettings(oJson
[filter
]));
328 function saveSettings(){
330 kill
= []; //Determins if a certain pattern should be used or not due to regex errors from the user
332 if(storageAvailable('localStorage')){
333 window
.localStorage
.setItem("q", number_of_filters
);
334 for (var pattern_input
= 0 ; pattern_input
< number_of_filters
; pattern_input
++){
335 var pattern_to_store
= document
.getElementById("Pattern"+pattern_input
).value
;
336 var replacement_to_store
= document
.getElementById("Replacement"+pattern_input
).value
;
338 if(pattern_to_store
=== "" || replacement_to_store
=== "") continue;
339 if (pattern_to_store
.charAt(0) == "/" && pattern_to_store
.charAt(pattern_to_store
.length
- 1) == "/"){
340 pattern_to_store
= pattern_to_store
+ setting
;
342 else if(pattern_to_store
.charAt(0) !== "/" && pattern_to_store
.substr(pattern_to_store
.length
- 2).match(/\/[a-zA-Z$]/) == null){
343 pattern_to_store
= "/" + pattern_to_store
+ "/" + setting
;
345 document
.getElementById("Pattern"+pattern_input
).value
= pattern_to_store
;
346 var save_string
= '"' + document
.getElementById("Active"+pattern_input
).checked
+ '"-"' + pattern_to_store
+ '"-"' + replacement_to_store
+ '"';
347 window
.localStorage
.setItem("filter" + pattern_input
, save_string
);
350 alert("Replacements Saved");
353 //Splits the saved settings into components
354 function formatSettings(input
){
355 var rtn
= input
.split('"-"');
357 rtn
.forEach(function(filter
){
358 rtn
[i
] = filter
.replace("\"", "");
364 function filterWindow(){
365 var style
= document
.createElement('style');
366 style
.innerHTML
= ".inputs{background-color:rgb(200,200,200);margin:5px 7px;width:100px;}";
367 document
.body
.appendChild(style
);
369 var background_div
= document
.createElement("div");
370 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");
371 background_div
.setAttribute("id", "FilterBackground");
372 document
.body
.appendChild(background_div
);
373 background_div
.addEventListener("click", filterToggle
);
375 var window_div
= document
.createElement("div");
376 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");
377 window_div
.setAttribute("id", "FilterWindow");
379 var close_div
= document
.createElement("div");
380 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");
381 close_div
.addEventListener("click", filterToggle
);
382 window_div
.appendChild(close_div
);
384 var title_para
= document
.createElement("p");
385 title_para
.setAttribute("style", "margin-left:5px;margin-top:5px");
386 var title_text
= document
.createTextNode("Filter Settings");
387 title_para
.appendChild(title_text
);
388 window_div
.appendChild(title_para
);
390 var container_div
= document
.createElement("div");
391 container_div
.setAttribute("style","background-color:white;margin:0 0;padding:5px;");
392 window_div
.appendChild(container_div
);
394 var filter_table
= document
.createElement("table");
395 filter_table
.setAttribute("style", "text-align:center;");
396 filter_table
.setAttribute("id", "filter_table");
397 container_div
.appendChild(filter_table
);
399 var table_row
= document
.createElement("tr");
400 filter_table
.appendChild(table_row
);
401 var table_head_active
= document
.createElement("th");
402 var head_text_active
= document
.createTextNode("Active");
403 table_head_active
.appendChild(head_text_active
);
404 filter_table
.appendChild(table_head_active
);
405 var table_head_pattern
= document
.createElement("th");
406 var headTextPattern
= document
.createTextNode("Pattern");
407 table_head_pattern
.appendChild(headTextPattern
);
408 filter_table
.appendChild(table_head_pattern
);
409 var table_head_replacement
= document
.createElement("th");
410 var head_text_replacement
= document
.createTextNode("Replacement");
411 table_head_replacement
.appendChild(head_text_replacement
);
412 filter_table
.appendChild(table_head_replacement
);
415 //Create the pattern table
416 //loop to create rows
417 if (number_of_filters
=== 0 || isNaN(number_of_filters
)) number_of_filters
= 6;
418 for (var i
= 0; i
< number_of_filters
; i
++){
419 var table_row_contents
= document
.createElement("tr");
420 table_row_contents
.setAttribute("id", "FilterRow" + i
);
422 var table_data_active
= document
.createElement("td");
423 var table_checkbox_active
= document
.createElement("input");
424 table_checkbox_active
.setAttribute("type", "checkbox");
425 table_checkbox_active
.setAttribute("id", "Active" + i
);
426 table_data_active
.appendChild(table_checkbox_active
);
427 table_row_contents
.appendChild(table_data_active
);
429 var table_data_pattern
= document
.createElement("td");
430 var table_input_pattern
= document
.createElement("input");
431 table_input_pattern
.setAttribute("class", "inputs");
432 table_input_pattern
.setAttribute("id", "Pattern" + i
);
433 table_data_pattern
.appendChild(table_input_pattern
);
434 table_row_contents
.appendChild(table_data_pattern
);
436 var table_data_replacement
= document
.createElement("td");
437 var table_input_replacement
= document
.createElement("input");
438 table_input_replacement
.setAttribute("class", "inputs");
439 table_input_replacement
.setAttribute("id", "Replacement" + i
);
440 table_data_replacement
.appendChild(table_input_replacement
);
441 table_row_contents
.appendChild(table_data_replacement
);
443 filter_table
.appendChild(table_row_contents
);
446 var table_last_contents
= document
.createElement("tr");
448 var table_add_collumn
= document
.createElement("td");
449 var table_add_row_button
= document
.createElement("input");
450 var table_subtract_row_button
= document
.createElement("input");
451 table_subtract_row_button
.setAttribute("type", "button");
452 table_subtract_row_button
.setAttribute("value", "-");
453 table_subtract_row_button
.setAttribute("style", "padding: 7px 0; margin:5px 0;");
454 table_add_collumn
.appendChild(table_subtract_row_button
);
455 table_subtract_row_button
.addEventListener("click", removeRow
);
456 table_add_row_button
.setAttribute("type", "button");
457 table_add_row_button
.setAttribute("value", "+");
458 table_add_row_button
.setAttribute("style", "padding: 7px 0; margin:5px 0;");
459 table_add_collumn
.appendChild(table_add_row_button
);
460 table_add_row_button
.addEventListener("click", addRow
);
462 table_last_contents
.appendChild(table_add_collumn
);
464 var table_set_collumn
= document
.createElement("td");
465 var table_confirm_button
= document
.createElement("input");
466 table_confirm_button
.setAttribute("type", "button");
467 table_confirm_button
.setAttribute("id", "table_confirm_button");
468 table_confirm_button
.setAttribute("value", "Set Replacements");
469 table_confirm_button
.setAttribute("style", "padding: 7px 0; margin:5px 0;");
470 table_confirm_button
.addEventListener("click", saveSettings
);
471 table_confirm_button
.addEventListener("click", modifyDOM
);
472 table_confirm_button
.addEventListener("click", filterToggle
);
473 table_set_collumn
.appendChild(table_confirm_button
);
474 table_last_contents
.appendChild(table_set_collumn
);
477 var table_close_collumn
= document
.createElement("td");
478 var table_close_button
= document
.createElement("input");
479 table_close_button
.setAttribute("type", "button");
480 table_close_button
.setAttribute("value", "Close Menu");
481 table_close_button
.setAttribute("style", "padding: 7px 0; margin:5px 0;");
482 table_close_button
.addEventListener("click", filterToggle
);
483 table_close_collumn
.appendChild(table_close_button
);
484 table_last_contents
.appendChild(table_close_collumn
);
486 filter_table
.appendChild(table_last_contents
);
488 document
.body
.appendChild(window_div
);
492 function filterToggle(){
493 if(window_displayed
){
494 document
.getElementById("FilterWindow").style
.display
= "none";
495 document
.getElementById("FilterBackground").style
.display
= "none";
496 window_displayed
= false;
499 document
.getElementById("FilterWindow").style
.display
= "inline-block";
500 document
.getElementById("FilterBackground").style
.display
= "inline-block";
501 window_displayed
= true;
505 function filterButton(){
506 var filter_button
= document
.createElement("input");
507 filter_button
.setAttribute("Value", "Word Filter Settings");
508 filter_button
.setAttribute("type", "button");
509 filter_button
.setAttribute("style", "position:absolute;top:75px");
510 filter_button
.addEventListener("click", filterWindow
);
511 document
.body
.appendChild(filter_button
);
512 filter_button
.addEventListener("click", filterToggle
);
516 var filter_table
= document
.getElementById("filter_table");
517 filter_table
.deleteRow(parseInt(number_of_filters
) + 1);
520 var table_row_contents
= document
.createElement("tr");
521 table_row_contents
.setAttribute("id", "FilterRow" + (number_of_filters
- 1));
523 var table_data_active
= document
.createElement("td");
524 var table_checkbox_active
= document
.createElement("input");
525 table_checkbox_active
.setAttribute("type", "checkbox");
526 table_checkbox_active
.setAttribute("id", "Active" + (number_of_filters
- 1));
527 table_data_active
.appendChild(table_checkbox_active
);
528 table_row_contents
.appendChild(table_data_active
);
530 var table_data_pattern
= document
.createElement("td");
531 var table_input_pattern
= document
.createElement("input");
532 table_input_pattern
.setAttribute("class", "inputs");
533 table_input_pattern
.setAttribute("id", "Pattern" + (number_of_filters
- 1));
534 table_data_pattern
.appendChild(table_input_pattern
);
535 table_row_contents
.appendChild(table_data_pattern
);
537 var table_data_replacement
= document
.createElement("td");
538 var table_input_replacement
= document
.createElement("input");
539 table_input_replacement
.setAttribute("class", "inputs");
540 table_input_replacement
.setAttribute("id", "Replacement" + (number_of_filters
- 1));
541 table_data_replacement
.appendChild(table_input_replacement
);
542 table_row_contents
.appendChild(table_data_replacement
);
544 filter_table
.appendChild(table_row_contents
);
546 var table_last_contents
= document
.createElement("tr");
548 var table_add_collumn
= document
.createElement("td");
549 var table_add_row_button
= document
.createElement("input");
550 var table_subtract_row_button
= document
.createElement("input");
551 table_subtract_row_button
.setAttribute("type", "button");
552 table_subtract_row_button
.setAttribute("value", "-");
553 table_subtract_row_button
.setAttribute("style", "padding: 7px 0; margin:5px 0;");
554 table_add_collumn
.appendChild(table_subtract_row_button
);
555 table_subtract_row_button
.addEventListener("click", removeRow
);
556 table_add_row_button
.setAttribute("type", "button");
557 table_add_row_button
.setAttribute("value", "+");
558 table_add_row_button
.setAttribute("style", "padding: 7px 0; margin:5px 0;");
559 table_add_collumn
.appendChild(table_add_row_button
);
560 table_add_row_button
.addEventListener("click", addRow
);
562 table_last_contents
.appendChild(table_add_collumn
);
564 var table_set_collumn
= document
.createElement("td");
565 var table_confirm_button
= document
.createElement("input");
566 table_confirm_button
.setAttribute("type", "button");
567 table_confirm_button
.setAttribute("id", "table_confirm_button");
568 table_confirm_button
.setAttribute("value", "Set Replacements");
569 table_confirm_button
.setAttribute("style", "padding: 7px 0; margin:5px 0;");
570 table_confirm_button
.addEventListener("click", saveSettings
);
571 table_confirm_button
.addEventListener("click", modifyDOM
);
572 table_confirm_button
.addEventListener("click", filterToggle
);
573 table_set_collumn
.appendChild(table_confirm_button
);
574 table_last_contents
.appendChild(table_set_collumn
);
576 var table_close_collumn
= document
.createElement("td");
577 var table_close_button
= document
.createElement("input");
578 table_close_button
.setAttribute("type", "button");
579 table_close_button
.setAttribute("value", "Close Menu");
580 table_close_button
.setAttribute("style", "padding: 7px 0; margin:5px 0;");
581 table_close_button
.addEventListener("click", filterToggle
);
582 table_close_collumn
.appendChild(table_close_button
);
583 table_last_contents
.appendChild(table_close_collumn
);
585 filter_table
.appendChild(table_last_contents
);
588 function removeRow(){
589 var filter_table
= document
.getElementById("filter_table");
590 if(number_of_filters
!= 0){
591 filter_table
.deleteRow(number_of_filters
);
597 var filter_count
= 0;
598 initial_filters
.forEach(function(filter
){
599 if(filter
[2] === null || filter
[1] === null || filter
[0] === null || filter_count
== number_of_filters
) return;
600 if(filter
[0] == "true"){
601 document
.getElementById("Active"+filter_count
).checked
= true;
603 else if(filter
[0] == "false"){
604 document
.getElementById("Active"+filter_count
).checked
= false;
606 document
.getElementById("Pattern"+filter_count
).value
= filter
[1];
607 document
.getElementById("Replacement"+filter_count
).value
= filter
[2];
613 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
614 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
615 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
616 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
617 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
618 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
619 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
620 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
621 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
622 //222222222222222222222222222222222222222222222222222222222222////2222222222222222222222222222222222222222222222222222222222221111111111111111111111111111//
624 //Functions to set the DOM listener and observers
626 var hidden_count
= 0;
627 function modifyDOM(){
628 var start
= document
.getElementById("delform");
629 var itterator
= document
.createTreeWalker(start
, NodeFilter
.SHOW_ELEMENTS
, NodeFilter
.SHOW_ELEMENTS
);
632 while((node
= itterator
.nextNode())){
633 decisionProcess(node
, itterator
);
636 console
.log("HIDDEN THREADS: " + hidden_count
);
639 function decisionProcess(node
, itterator
){
640 var cname
= node
.className
;
641 var tag
= node
.tagName
;
642 if(tag
=== "IMG" || tag
=== "img"){
643 if(!/\d+IMG/.test(node
.getAttribute("hide-grouping")) && (node
.getAttribute("data-md5") !== null)){
647 else if(cname
== "postMessage"){
648 var blockquote_id
= node
.id
;
649 var already_filtered
= false;
650 filtered_threads
.forEach(function(thread_id
){
651 if(thread_id
== blockquote_id
) {
652 already_filtered
= true;
656 if(!already_filtered
){
657 if(itterator
== undefined) itterator
= document
.createTreeWalker(node
, NodeFilter
.SHOW_ELEMENTS
, NodeFilter
.SHOW_ELEMENTS
);
659 while((localNode
= itterator
.nextNode())){
660 var className
= localNode
.className
;
661 if(className
== undefined || className
== "quotelink"){
662 for(var i
= 0 ; i
< number_of_filters
; i
++){
663 if(kill
[i
] == true) continue;
664 filter
= document
.getElementById("Pattern"+i
);
665 replacement
= document
.getElementById("Replacement"+i
);
666 active
= document
.getElementById("Active"+i
);
668 var lastChar
= filter
.value
.length
- 1;
669 var filterText
= filter
.value
;
670 if(filterText
=== "") break;
671 var setting
= filterText
.substr(lastChar
);
672 filterText
= filterText
.substr(1, lastChar
-2);
674 var regex
= new RegExp(filterText
, setting
);
675 var node_text
= localNode
.textContent
;
676 if(regex
.test(node_text
)){
677 localNode
.textContent
= node_text
.replace(regex
, replacement
.value
);
678 filtered_threads
.push(blockquote_id
);
682 alert(i
+ "'s regex was invalid");
694 function filterImage(node
){
695 var sister_node
= node
.parentNode
.parentNode
.parentNode
.getElementsByClassName("catalog-thumb")[0]; // the catalog sister to index
696 if(sister_node
=== undefined) sister_node
= node
;
698 node
.setAttribute("hide-grouping", node
.parentNode
.parentNode
.id
.substring(1) + "IMG");
699 sister_node
.setAttribute("hide-grouping", node
.parentNode
.parentNode
.id
.substring(1) + "IMG");
701 node
.addEventListener("click", hideImage
, {passive
:false, capture
:false, once
:false});
702 sister_node
.addEventListener("click", hideImage
, {passive
:false, capture
:false, once
:false});
704 var threadstore_len
= local_store_threads
.length
;
705 var node_group_id
= node
.getAttribute("hide-grouping");
707 for(var thread
= 0 ; thread
< threadstore_len
; thread
++){
708 if(node_group_id
== local_store_threads
[thread
]){
709 node
.setAttribute("hidden-src", node
.src
);
710 node
.src
= blank_png
;//this.src + ".HIDDEN" + "?" + Date.now();
712 sister_node
.setAttribute("hidden-src", sister_node
.src
);
713 sister_node
.src
= blank_png
;//this.src + ".HIDDEN" + "?" + Date.now();
719 //index node holds the MD5
720 var node_md5
= node
.getAttribute("data-md5");
721 var md5_filters_arr_len
= md5_filters_arr
.length
;
722 for(var md5
= 0 ; md5
< md5_filters_arr_len
; md5
++){
723 if(node_md5
== md5_filters_arr
[md5
]){
724 node
.setAttribute("hidden-src", node
.src
);
725 node
.src
= blank_png
;//this.src + ".HIDDEN" + "?" + Date.now();
727 sister_node
.setAttribute("hidden-src", sister_node
.src
);
728 sister_node
.src
= blank_png
;//this.src + ".HIDDEN" + "?" + Date.now();
736 function hoverUIObserver(mutations
){
737 mutations
.forEach(function(mutation
){
738 mutation
.addedNodes
.forEach(function(image_node
){
739 var unprocessed_id
= image_node
.getAttribute("data-full-i-d");
740 if (unprocessed_id
=== null) return;
741 var image_node_id
= unprocessed_id
.substring(unprocessed_id
.indexOf(".") + 1) + "IMG";
742 var threadstore_len
= local_store_threads
.length
;
743 for(var thread
= 0 ; thread
< threadstore_len
; thread
++){
744 if(image_node_id
== local_store_threads
[thread
]){
745 image_node
.removeAttribute("src");
753 //initial onload setup
754 function hideSetup(){
759 function filterSetup(){
767 // var initial_setup_observer;
768 // document.onreadystatechange = function(e)
770 // if (document.readyState === 'interactive')
772 // initial_setup_observer = new MutationObserver(function(mutations){
773 // mutations.forEach(function(mutation){
774 // mutation.addedNodes.forEach(function(node){
775 // //decisionProcess(node);
779 // initial_setup_observer.observe(document.all[0], {childList: true, subtree: true });
781 // if(document.readyState == "complete") console.log("Complete Time: " + (Date.now() - start));
785 expire_time
= localStorage
.getItem("Expiration_Time");
786 md5_filters
= localStorage
.getItem("MD5_List_FSE");
790 // initial_setup_observer.disconnect();
792 document
.addEventListener('PostsInserted',function(e
){
796 new MutationObserver(function(mutations
){
798 hoverUIObserver(mutations
);
799 }).observe(document
.getElementById("hoverUI"), {childList
: true });
803 var page_setup
= false;
804 document
.addEventListener('4chanXInitFinished', function(e
) {
805 browser
= detectBrowser();
807 console
.log("Script loaded: 4chanPKX");
809 //console.log("InitFinished Time: " + (Date.now() - start));
812 var start
= Date
.now();