-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwebcooler.user.js
More file actions
1697 lines (1258 loc) · 110 KB
/
Copy pathwebcooler.user.js
File metadata and controls
1697 lines (1258 loc) · 110 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// ==UserScript==
// @name WebCooler
// @namespace http://www.kupietz.com/WebCooler
// @description Cools down my web experience by hiding content that tends to make me hot under the collar. For when your desire to be informed has finally been overcome by your desire to stay sane.
// @version 3.10
// @match *://*/*
// @require https://gist.githubusercontent.com/arantius/3123124/raw/grant-none-shim.js
// @require https://code.jquery.com/jquery-3.3.1.slim.min.js
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
/*
Author: Michael Kupietz https://www.kupietz.com
This script is provided as-is. My javascript is sloppy, this was patched together with kite string and scotch tape over many years.
It sucks. It will break your computer. You shouldn't use it.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Version History:
3.10 add "!CONSOLE_DEBUGGING_MESSAGES_ON ||" to prevent anything from even log values from even evaluating if logging is off, get rid of json.stringify, was causing errors with circular objects and adding a replacer function to fix them made it more complicated. Also add some new terms to keep up with changes in parent object hierarchy in facebook comments.
3.9 Put badwords filter first when scanning tree... only consider trees at all if they contain badwords
3.8 Somewhere along the way a few sections of code got randomly duplicated, cleaned it up
3.7 consider text content of span tags with multiple child nodes as a whole, to catch <span>bad <em>words</em></span>, like Google sometimes does within search results
3.6.1 fix regression error where 3.6 wasn't matching any pages, add a few new classes to block features on Google search results for individual I want to disappear.
3.6 improved performance by adding site specific parents to remove only if a child is hidden rather than relying on selectors to always hide and a horribly inefficient :has() selector
3.5.1 Append comments in head showing matches.
3.5 Tossed my cookies. Now using GM_setValue and GM_getValue because some sites were deleting my cookies on reload.
3.4 Numerous optamazetions. Replace each with for loops, cache lengths and $() objects in variables
3.3 Added async, performance enhancements, contextual menu and keystroke unexemption options, lots of other stuff, read the diff.
3.2 added and subsequently removed debugout. Oh well. Added try/catch to main to hopefully alert on errors, since some browsers truncate logs despite your best efforts to see what the f you're doing.
3.1 changed function main() to use mutation.addedNodes when available instead of mutation.target... seems way faster! Also fixed some bugs. YouTube pages work again. Created some code (currently commented out) to store log in comments in page <head> for when FireFox's console log is broken, like tonight.
3.0 jshinted and added fb softblock by name
2.5 finally get it to stop striking editable content (ie, deleting my facebook rants as I type them [NO! Doesn't work when theClosest contains editable, I think]) and optimized some code.
2.02 - Myriad small changes. Read the diff.
2.01 - changed line endings from mac \r to unix \n so tampermonkey can import from github.
2.0 - updated to jQuery for fun and good times
*/
// Licensed for unlimited modification and redistribution by any terrestrial being as long as
// this notice is kept intact.
/* todo: configuration options https://github.com/odyniec/MonkeyConfig or https://github.com/sizzlemctwizzle/GM_config/
NO! These only store values per domain, which appears to be a completely useless function. My kingdom for an easy way to
bring up an options dialog and store values without having to hardcode them into the script! */
var thisScriptHiddenAttribute = "hiddenbyuserscript"+ GM.info.script.name.replace(/[^a-zA-Z]/g, ''); //don't change
/* switches & debugging options */
var observerEnable = true; //enable mutation observer
var CONSOLE_DEBUGGING_MESSAGES_ON = false ;//new RegExp(/normal|ultra|greencrit|observer/,"gi");//true; //log debug messages? true|false|normal(non-categorized)|new RegExp("logClass1|logClass2|logClass3")
/*** CAUTION!!! CONSOLE_DEBUGGING_MESSAGES_ON != false is a HUGE performance hit! It completely broke Twitter for me tonight. ***/
/*** TURN IT OFF WHEN YOU ARE DONE DEBUGGING. ***/
/******* Maybe add a visual indicator if debugging is on. Also add a visual indicator if somehting has been removed... like only add exempt link then ***/
var TURN_CONSOLE_DEBUGGING_MESSAGES_ON_PHRASE = ""; //turn logging on if this is found. Leave set to "" to improve performance. Debugging tool for catching sporadic problems that disappear when you turn on logging and reload the page.
var CONSOLE_MESSAGES_ADDED_TO_HEAD = true; //add messages to document head, for when FireFox annoyingly truncates logs
var HILIGHT_ONLY = false; //consider all pages exempt and hilite rather than remove. turn this on if the damn cookie system breaks again
var HILIGHT_ELEMENTS_BEING_PROCESSED = false; //visual cue as each page element is processed?
var RECORD_DEBUGGING_INFO_IN_NODE_ATTRIBUTES_AS_THEY_ARE_PROCESSED = false; //Do I even use this anymore? I dunno
var MAX_NUMBER_OF_CALLS_PER_PAGE = 100000000; //prevent endless loops. Set to very high number for actual production use.
var BLOCK_ONLY_IMAGES_CONTAINING_ONLY_TEXT = true; //hide tweet screencaps & probably some memes on FB
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Starting - logging ", CONSOLE_DEBUGGING_MESSAGES_ON);
this.$ = this.jQuery = jQuery.noConflict(true);
/* necessary for compatibility, according to https://wiki.greasespot.net/@grant */
/* from webcooler.xpi contentScript.js */
/***********************************************************************************************
*********************************** USER GLOBAL VARIABLES GO HERE ******************************
************************************************************************************************/
/*** GLOBAL BLOCKING ***/
/* the below all are regexps. BadWords match text, ones marked as selectors match jquery selectors. */
var globalBadWords =
"\\btrump\\b|donald[_ .j]?[_ .j]?[_ .j]?trump|DeSantis|Yeezy|Adidas|Elon ?Musk|\\bElon\\b|SpaceX|parler|transgender|\\bwoke\\b|MSNBC|taylor greene|\\bbiden|kamala|boebert|cambridge *analytica|(keep|make) america great|AOC|huckabee sanders|bader ginsburg|sarah sanders|Ocasio-Cortez|theapricity|Breitbart|proud boys|roger stone|apricity|jordan[ Bb.]*peterson|mansplain|bolsonaro|gerrymander|steve king|mitch mcconnell|school shoot|huckabee[^'s]|rex reed|fake news|roseanne *barr|stormy *daniels|eagles of death metal|kanye west|kim kardashian|laughing ?squid|proud boy|parkland|stoneman douglas|sandy hook|kaepernick|dylann roof|Arpaio|John Bolton|Rick Santorum|crisis actor|[^A-Za-z]NRA[^A-Za-z]|maxine waters|environmentalist|religious (freedom|liberty|right)|patriot prayer|deep state|crooked hillary|Conservative Political Action Conference|cpac|actblue|truthdig|sexual misconduct|goyim|shithole countr|\'shithole\'|\"shithole\"|(blue|all|white) lives matter|raw water|assault rifle|political[-lly ]*correct|social justice|roy moore|white nationalist|manafort|rob *schneider|the ?blaze|confederate flag|\\bsharia\\b|hillary clinton|bill ?o['’]?reilly|Wilbur Ross|o[’']?reilly ?factor|\\bTrump\\b|ajit pai|ann coulter|tucker carlson|bill maher|spicer|actblue|Hannity|David\\ Brock|Daily ?Stormer|alex jones|daily caller|bill nye|rachel maddow|infowars|rand paul|keith olbermann|Angus ?King|Cernovich|ann coulter|roger stone|climate deni[ae]|townhall\\.com|richard ?b?\\.? ?spencer|slate.com|kanye|paul joseph watson|prison ?planet|s1\\.zetaboards\\.com|anthroscape|daily ?kos|gamergate|betsy devos|steve bannon|\#*maga[^a-z]|corporate america|healthcare|marine le pen|red ?pill|Yiannopoulos|geert wilders|vox day|huffington|cuckservative|libtard|Bernie Sanders|SJW|alt-right|Tim Pool|Chelsea Clinton|\\@potus|\\@realdonaldtrump|(\\.|\\!) sad\\!|racist|Bernie bros|zero ?hedge|This Tweet is unavailable|liberal propaganda|supremacist|liberal media|electoral landslide|typical liberal|white privilege|Robert Morris|Robert Tappan Morris|Morris Worm|stormfront";
/* Please note, my personal collection of badWords is selected not by political ideology, but by what seems to attract either the most heated or the most egregiously stupid comments and content online, regardless of political slant. Any apparent political alignment is strictly a 'shoe fits' situation. Also includes a couple of what I think are just totally biased and unreliable propaganda sites and commentators on both ends of the spectrum. */
/* \\btrump\\b|donald[_ .j]?[_ .j]?[_ .j]?trump proven effective at blocking trump but not "strumpet" */
var selectorsToConsiderTogether =
'aside|#hyperfeed_story_id|li[data-hveid]|div[data-hook="review"]|li.yt-shelf-grid-item.yt-uix-shelfslider-item';
/* block higher-level elements if any descendant elements contain badwords. Like, remove a whole tweet, or a whole fb reply, not just the <div> containing the badword. Otheriwse it looks for the smallest element it can remove. */
/* aside is on guardian.com, but maybe it's used eslewher, I dunno */
var selectorsToAlwaysHide = "div.cnnoutbrain|div.outbrain-hotlist|div.outbrain-module";
/* hide some page structures no matter what. Good for blocking ads, etc. Can also use ':has(["+thisScriptHiddenAttribute+"=true])' selector to always block certain parent elements if they contain an element the script has hidden, so the empty parent elements don't display. */
/*** SITE-BY-SITE BLOCKING ***/
/* block extra words on a site-by-site basis, like, fer instance, twitter and facebook, where ignorant people are particularly vocal: */
/* note: \b word boundaries doesn't work in userscript. We need \\b in the string, because the string just passes \b as 'b'. \b is a regex code, not recognized by strings. */
var siteSpecificBadWords = {
/* social media sites*/
"twitter.com$|nextdoor.com$|quora.com$|reddit.com$|facebook.com$|youtube.com$": "James Witcher|Nikki Beach|Jussie Smollett|Mueller|Barr report|William Barr|\,” Tom said |Cindy McCain|John McCain|chick-fil-a|America great|AOC|biden|covington|jill stein|abortion|ocasio-cortez|\\bAOC\\b|gabbard|ideological[ly]* pur|purity test|tear *gas|grassley|merrick garland|McCain|soros|Kavanaugh|traitor|Ivanka|same[- ]sex|Jared Kushner|\\bpence\\b|\\bgender\\b|nikki haley|MSM|deplorable|medicaid|melania|the left|climate change|global warming|russia|walmart|wal-mart|[^a-zA-Z]NRA[^a-zA-Z]|nader|climate scien|single[ -]*payer|racism|net neutrality|gubb[aer]+m[ie]+nt|(second|2nd) amendment|government spend|prsident|zionis|taxpayer|anti-*semit|republican|democratic party|democrats?\\b|liberals|healthcare|extremist|comey\\b|libertarian|antifa\\b|bakedalaska|protestor|conservatives|poor people|gov'?t|climate change|terroris[tm]|tax plan|snowflake|global warming|drain the swamp|feminis[tm]|\\bMRA|PUA\\b|unborn|\\btwp|rac(ial|e) realism|venezuela|abortion|\\bISIS\\b|devos|communist|commie|socialist|\\bweev\\b|aurenheimer|white (house|guys)|obama|bDNC\\b|cultural\\ appropriation|hate\\ crime|\RNC\\b|democratic socialism|leftist|rightist|mar-?a-?lago|(white|black|brown) *(wom[ae]n|m[ae]n|people|(-*skin))|burqa|Kellyanne\\ Conway|illegal alien|\\bTrump\\b|white nationalist|Nazi|This tweet is unavailable.",
"twitter.com$": "\\bshill\\b",
/*common troll comment on twitter, used in other ways on non-political Reddit subs */
"reddit.com$": "GreenIn2",
"tumblr.com$": "#branflake|#kung-fu kutie",
/* "facebook.com$": "[0-9][0-9][0-9] shares", I Guess at some point I didn't want to see widely-shared things. Not sure why */
/* news sites */
"abcnews.go.com$|feedly.com$|newsblur.com$|apnews.com|reuters.com|theguardian.com|npr.org|hosted.ap.org": "molester|world cup|civility|transgender|missile|same[- ]sex|Ivanka|Jared Kushner|\\bNFL\\b|gorsuch|tensions|kim jong un|Pence|N(\\.|orth) Korea|Rod Dreher"
};
/* never run on sites matching these */
/*ok, this is really dumb, but I have some personal sites (social media, etc) I don't want to publicly associate myself with. */
/* So, since I post this script publicly, I created the StupidHash function (see below) that inserts a wchash attribute into */
/* the body of each page. You can put the page's wchash here instead of the url. */
var exemptSites = "heisenbergreport\\.com|github\\.com|178496.2674270637|H1231.5759860347705|fivethirtyeight\\.com$|H184.74811863139513|18297985\.81780946|139514\.47879774484|H1269643\.1719910516|78882\.83274254062|\\.gov[/?:]|\\.gov$|H784\.1647977343692|H2603\.8344187906177"; //URL or wchash or wchashhost. NEED \\ to match periods, otherwise periods AND everything else matches in urls. fivethirtyeight\.com$ would match fivethirtyeightacom$. Doesn't matter as much in stupidhashes, as not likely to have two of them identical except for a character in place of the dot.
/* 78882.83274254062 = Dave M */
/* Now, some useful definitions for the below sections: */
//var fb_OutermostWhiteBox = "div._4-u2"; /*Does this ever change? We'll see. */
//var fb_OutermostWhiteBox = "div._5jmm._5pat._3lb4"; /*Looks like it changed. Dec 7 2018 */
var fb_OutermostWhiteBox = "div._5pcb"; // changed again. 2019jan26
var fb_post = "div.fbUserContent"; /* entire post */
var fb_postContent =
"div._1dwg"; /*._1dwg is around post content (the top) but not comments or the bar with "like, share" etc. */
/* site-specific extras to consider with selectorsToConsiderTogether: */
var siteSpecificSelectorsToConsiderTogether = {
"youtube.com$": ".video-list-item|ytd-compact-video-renderer",
"tumblr.com$": "li.post_container|article",
"twitter.com$": 'div[aria-label="Timeline: Conversation"]>div>div|div[aria-label="Timeline: Tweet"]>div>div|div.TweetWithPivotModule|div.MomentCapsuleSummary--card|.TwitterCard|.QuoteTweet|.CardContent|li[data-item-type="tweet"]|.ProfileCard|li.trend-item|.js-account-summary.account-summary.js-actionable-user',
/* removed twitter:'.js-stream-item.stream-item' because was hiding entire 'tweets you might have missed' if one matched */
"reddit.com$": '.noncollapsed|.was-comment|.recipient|.message|div.comment ',
"google.com$": "div.unNqGf|div[jsname='yEVEwb']|explore-desktop-accordion|div.kp-wholepage.ss6qqb.u7yw9.zLsiYe.mnr-c.UBoxCb.kp-wholepage-osrp.Jb0Zif.EyBRub|div.RzdJxc|div.Kot7x|div.Ow4Ord|div.g|div._oip._Czh|g-section-with-header|div._NId>div.srg>div.g|div.AJLUJb > div|div.sATSHe| div.XqFnDf[data-hveid='CAYQDQ']>",
/* div.kp-wholepage.ss6qqb.u7yw9.zLsiYe.mnr-c.UBoxCb.kp-wholepage-osrp.Jb0Zif.EyBRub is a "knowledge panel,
div.RzdJxc is video result | div.AJLUJb > div is "related searches", div.unNqGf is "+" button across top,
div[class='XqFnDf'][data-hveid='CAYQDQ'] appears to be top-of-page "onebox",
div.sATSHe is "About" box in right column, div[jsname='yEVEwb'] is "people also ask" */
"facebook.com$": 'div._4eeo|div[aria-label="Comment"]|article._55wo|div[role=article]|li.jewelItemNew|div._3soj|div.UFIRow.UFIComment|div._1yt|li._5my2|li._58rc|div._4-u3|' + fb_postContent,
/* li._5my2 is 'trending' row. div.div._4-u3 is a "related article" beneath a share.
li._58rc is a 'related content' box. div._1yt is a search result post */
/* div._4eeo is a div around an image in a content */
"mbasic.facebook.com$": 'div[role="article"]|div#m_story_permalink_view>div>div>div>div',
"feedly.com$": "div.feed-large.item.feed|div.entry|div.entry.unread.u4.density-29",
"abcnews.go.com$": "article.news-feed-item",
"theguardian.com$": "li.fc-slice__item|li.headline-list__item|li.right-most-popular-item",
"usatoday.com": "a.srrfsm-link",
"theatlantic.com$": 'div[class^="ArticleRecirc_itemRoot__"]|li[class^="ArticleMostPopular_li__"]',
"nytimes.com$": "li.collection-item|li.Ribbon-ribbonStory--2vH2y|div.Recirculation-recirculationItem--1bXrY|ul.menu.layout-horizontal.theme-story li|aside.trending-module div ol li",
"bbc.com$": "div.features-and-analysis__story",
"newsblur.com$": "div.NB-story-title.NB-story-grid.NB-story-neutral",
"npr.org$": "div.story-recommendations__result",
"time.com$": "article.tile"
};
/* div._NId>div.srg>div.g google search result */
/* li.jewelItemNew is notification row */
/*div[role=article] is mbasic.facebook.com article */
/* I *think* div._3soj is a notification popup bubble. */
/* article._55wo touch.facebook.com article */
/* Other things to always hide. Useful to, say, hide an entire facebook post only if the main comment comtains badwords, but _not_ if a reply comment does.
(Hence siteSpecificSelectorsToConsiderTogether wouldn't do the trick.) */
var constantSiteSpecificSelectorsToAlwaysHide = {
"facebook.com$": "div.x1n2onr6 > a[href*='https://www.facebook.com/photo'] img[alt*=Twitter]|div._n3 div._6iiv|div._n3 div._6iin|div.UFIRow.UFIComment["+thisScriptHiddenAttribute+"=true]+div.UFIReplyList|" + /* that's the reply list under a hidden comment */
"div.pagelet-group.pagelet|img[alt*='may contain: text']:not(.spotlight)|img[alt*=', text']:not(.spotlight)|div[data-referrer='pagelet_trending_tags_and_topics']|div._6iiv._6r_e"
/* div._6iiv._6r_e is comments on lightbox image */ /* .spotlight is a lightbox image... if it's in a lightbox, I clicked on it, and want to see it. */
/* had this but it appears not to be used anymore: fb_OutermostWhiteBox +
":has(div._14bf)" */,
/* This actually worked, but worried it'll be slow "reddit.com$":"div.Comment:has(>div._2OpuabFjFVU3UZ4jcP58gJ["+thisScriptHiddenAttribute+"=true]),div._2OpuabFjFVU3UZ4jcP58gJ:has(>div._1mvcEtI04YyIVKsT-vUkiN["+thisScriptHiddenAttribute+"=true]),div._1mvcEtI04YyIVKsT-vUkiN:has(>div.hpOP1hjcTLrw1L2rfRtMP["+thisScriptHiddenAttribute+"=true]),div.hpOP1hjcTLrw1L2rfRtMP:has(>div._3CecFEZvC8MFSvLsfuVYUs["+thisScriptHiddenAttribute+"=true]),div._3CecFEZvC8MFSvLsfuVYUs:has(>div._2QR1H6z3qpmyHNdkMUnzVu["+thisScriptHiddenAttribute+"=true]),div._2QR1H6z3qpmyHNdkMUnzVu:has(>div.Ov9DvczDidxNqJMR_axF2._3ezOJqKdLbgkHsXcfvS5SA["+thisScriptHiddenAttribute+"=true]),div.Ov9DvczDidxNqJMR_axF2._3ezOJqKdLbgkHsXcfvS5SA:has(>div["+thisScriptHiddenAttribute+"=true]) ", */
/* weirdly, this seemed faster than the above */ "reddit.com$":"div:has(>div["+thisScriptHiddenAttribute+"=true]):not(:has(div.Comment))",
/* careful this crashed the script: div[role='article']:has(img[alt*='may contain:[^']*text']) */
/* used to have div[role='article']:has(img[alt*='may contain: text'])|div[role='article']:has(img[alt*=', text']) ut these have got to be super-slow because there are so many role=article divs... trying just the img. */
"youtube.com$": "ytd-video-meta-block > ytd-badge-supported-renderer",
"reuters.com$":"div.container_19G5B:has(h1["+thisScriptHiddenAttribute+"=true])|div.container_19G5B:has(a[href=\"/news/archive/rcom-sponsored\"])", /* article where title is hidden, or sponsored */
/* get rid of annoying corproate channels */
"twitter.com$": "div.promoted-tweet|div[data-disclosure-type=promoted]|div[data-advertiser-id]|div[data-promoted=true]",
"abcnews.go.com$": "article.article:has(header.article-header:has(["+thisScriptHiddenAttribute+"=true]))|article.artcle:has(div.article-copy["+thisScriptHiddenAttribute+"=true])" /*hide article if headline is hidden or whole article body is hidden*/
};
/* div._n3 div._6iiv|div._n3 div._6iin are "most relevant" header and comment blocks on lightbox images. Really need to find a way to apply this to Public images only, but for now this'll do */
var siteSpecificParentsToHideIfAChildIsHidden = { /* NOTE WORKING? Reddit entry didn't work. */
/* ok, here's the deal... when hiding a parent, that parent also receives the child's classes in a new hiddenclasses tag. This is so we can make <li><div><div class='cl"> hide the div and li ONLY if they contain div.cl, without using ":has(div.cl)" because that doesn't work with the pure javascript .matches() function that we use. now we can specify li[hiddenclass*=cl],div[hiddenclass*=cl]. */
"nextdoor.com$":"div.comment-detail,div.cee-media-body,div.comment-detail-content,div.comment-detail-content div",
/*DIDN'T WORK, WHY? "reddit.com$":"div.Ov9DvczDidxNqJMR_axF2._3ezOJqKdLbgkHsXcfvS5SA", */
"duckduckgo.com$":"div.result,div.result__body,div.result__extras__url",
"facebook.com$": "div._5jmm,div._4-u2.mbm._4mrt._5v3q._7cqq._4-u8,div._3ccb,div._5pcr,"+fb_postContent /*basic feed post container, a lot of the below use this */
+",div._1dwg._1w_m._q7o,div._5pcr > div._1dwg._1w_m._q7o > div,div._3x-2,div._3x-2 > div,div.mtm,div.mtm > div,div._1ktf,a._4-eo._2t9n,div._46-h._517g,div.uiScaledImageContainer"
/* replaces fb_OutermostWhiteBox +
":has(" + fb_postContent + "["+thisScriptHiddenAttribute+"=true])" */
/* it's a whole chain from a hidden post image, on up through a hidden post, on up to the outer container, so a whole post is hidden if an imaage or top post is hidden. */
+",div[hiddenclass*=_4eek],li[hiddenclass*=_4eek]"
/* hide whole LI if comment is hidden so like that shows how many replies there are gets hidden.*/
+",div[hiddenclasstheclosest*=x1n2onr6],li"
//one above this was no longer catching all LIs as of Mar 2023
+",div.x1n2onr6,a.x1i10hfl.x1qjc9v5.xjbqb8w.xjqpnuy.xa49m3k.xqeqjp1.x2hbi6w.x13fuv20.xu3j5b3.x1q0q8m5.x26u7qi.x972fbf.xcfux6l.x1qhh985.xm0m39n.x9f619.x1ypdohk.xdl72j9.x2lah0s.xe8uvvx.xdj266r.x11i5rnm.xat24cr.x1mh8g0r.x2lwn1j.xeuugli.xexx8yu.x4uap5.x18d9i69.xkhd6sd.x1n2onr6.x16tdsg8.x1hl2dhg.xggy1nq.x1ja2u2z.x1t137rt.x1o1ewxj.x3x9cwd.x1e5q0jg.x13rtm0m.x1q0g3np.x87ps6o.x1lku1pv.x1a2a7pz.x1lliihq.x1pdlv7q:first-child, div.x6s0dn4.x78zum5.xdt5ytf.x6ikm8r.x10wlt62.x1n2onr6.xh8yej3.x1jx94hy:first-child,div.x6s0dn4.x78zum5.xdt5ytf.x6ikm8r.x10wlt62.x1n2onr6.xh8yej3.x1jx94hy:first-child > div:first-child,div.xqtp20y.x6ikm8r.x10wlt62.x1n2onr6:first-child,div.x10l6tqk.x13vifvy"
/* that's the whole path to from a hidden photo's parent div up to the div you need to collapse to get rid of the blank white space as of march 20, 2023. */
+",div._3-8j,div._3-8j > div"
/* general enclosure for an item that more than one friend has shared */
+",div._6m2._1zpr._dcs._4_w4._41u-._59ap._2bf7._64lx._3eqz._20pq._3eqw._2rk1._359m._1-9r,div._2r3x,div._2r3x > div,span._3m6-,div._3ekx._29_4,div._6m3._--6,div._3n1k"
/* path up from a heading or description on a shared link that more than one friend has shared, to above enclosure */
+",div._5r69._sds._1hvl, div._5r69._sds._1hvl > div.mts, div._5r69._sds._1hvl > div.mts > div"
/* path up from an image (alt="*text*", most probably) that more than one friend has shared, to above enclosure */
+",div._1dwg > div,div._3x-2"
/* another path up from a post image, maybe an image in a post where a friend was tagged? */
};
/* NOTE: div._4-u2 is the outer container for a facebook post (and any other white box on their gray background as of this writing. Does this ever change? We'll see. div.fbUserContent is right inside that and seems less likely to change, but the outer one has the margins. */
/* ._5r69 seems to be the div surrounding a shared post. */ /* _5x46 is the header with who posted and who it was shared from */ /* div._14bf is either "suggested post" or "sponsored" */ /* div.pagelet-group.pagelet is suggested pages (or is it groups? Or both?) */
/* use div[role='article']:has(img[alt~='text'][alt*='may contain:']) to block any FB images that contain text even if the contain other things. */
/* before simplification, FB also had "div.fbUserContent:has(div.fbUserContent:has(div.userContent["+thisScriptHiddenAttribute+"=true]))|div._4-u2.mbm._4mrt._5jmm._5pat._5v3q._4-u8:has(div.userContent:has(["+thisScriptHiddenAttribute+"=true]))|div._5r69:has(["+thisScriptHiddenAttribute+"=true])|div._5x46:has(["+thisScriptHiddenAttribute+"=true])|div._4-u2.mbm._4mrt._5jmm._5pat._5v3q._4-u8:has(div._5x46["+thisScriptHiddenAttribute+"=true])|div._4-u2.mbm._4mrt._5jmm._5pat._5v3q._4-u8:has(div._1dwg["+thisScriptHiddenAttribute+"=true])|" */
/* I think div._3b-9._j6a is comments on image lightboxes. Sick of seeing people's stupid comments on things I click on to save. NOPE it's all comment blocks. Gotta refine that one. */
/*** END BLOCKING LISTS ***/
/* following vars not used yet: */
var badFBURLWords = "xyz123xyz"; /* FB username part of url */
var badFBNames = "abc123abc"; /*FB Name*/
var badURLWords =
".*trump.*|zippyaudio2|propublica|crowdignite|zerohedge|dailymail|hannitylive|townhall\.com|everydayfeminism|huffingtonpost|breitbart|jezebel|buzzfeed|zergnet|outbrain"; //urls to block links to, etc
/* block links containing badURLWords in href. Not yet implemented. */
/* NOTES: */
/* There's a :regex jQuery selector at https://j11y.io/javascript/regex-selector-for-jquery/ */
/* TO DO: Do a folder action that watches for TamperMonkey backups in dropbox, runs a script to decompress and copy this script into the GitHub repo, and use command line commands to upload to GitHub. */
/* TO DO: Maybe make a list of less bad words that only block if match() returns a list of more than 1 of them. Like "believe|lies|", "Trump|unfair" or "o'reilly|fox" or something. */
/* TO DO: mark editable elements as soon as found and ignore subsequently, even if they stop being editable at any point, as some do on complex social media sites. */
/* TO DO: implement badURLWords. */
/* To DO: Perhaps actually remove innerHTML of hidden elements to lighten page. See if it makes a difference in performance. */
/* Am I still using the sessionIDs to prevent redundant checks? Should probably switch them to jquery .data() and use again if not. */
/*I should prob have mutationobserver just mark nodelist with a class, then use jquery to find them, pare them down using descentant and contains and selectorsToConsiderTogether selectors, and style them using '.css='>
/* contains() example: $( "div:contains('John')" ).css( "text-decoration", "underline" ); */
/* highlight leaf nodes containing text (beware, case-sensitive): $('*:contains("I am a SIMPLE string")').each(function(){ //!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √173√ 'function( )' ~ ~ ~","","ULTRA");
if($(this).children().length < 1) $(this).css("border","solid 2px green") });
^^More info, including wrapping found text in tags, at http://stackoverflow.com/questions/926580/find-text-string-using-jquery */
/* not() selector: https://api.jquery.com/not-selector/ */
/* how to run a callback function on all text nodes matching a string or regexp: http://stackoverflow.com/questions/4060056/jquery-find-replace-without-changing-original-text/4060635#4060635 */
/* .text() method returns innerText, ignoring embedded tags. "a<i>b</i>c".text() returns "abc".
^^ if you wanted to get just "ac" from that, see http://viralpatel.net/blogs/jquery-get-text-element-without-child-element/ */
/* Use .each() and $(this) to iterate: $('.someDivList .divItem').each(function() { //!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √179√ 'function( ) ' ~ ~ ~","","ULTRA");
$(this).css('background', 'lightblue');
}); */
/* how to use jQuery on node lists, such as mutation records: http://stackoverflow.com/questions/12596231/can-jquery-selectors-be-used-with-dom-mutation-observers
it's as easy as setting: var jq = $(mutation.addedNodes); */
/* good docs on what mutation returns (addedNodes, removedNodes, changed attributes, etc.): https://davidwalsh.name/mutationobserver-api
good, simple MutationObserver demo (be sure to show Console to see mutation object returned) https://jsfiddle.net/dimshik/p9gx43Lx/*/
/* to catch all changes including text nodes, config = {
attributes: true, childList: true, characterData: true, subtree: true} */
/* check for display:none : $(element).is(":visible"); */
/* find some way not to be triggered on user input */
/* .closest starts with current node and traverses upwords until matching selector is found. https://api.jquery.com/closest/ */
/* .parentsUntil() traverses up tree and finds child of node matching selector. */
/* get all leaf nodes: $("div").filter( function(index) { //!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √191√ 'function( index) ' ~ ~ ~","","ULTRA");
var isLeaf = $(this).children().length === 0;
return isLeaf;
}
); */
/* check if js has access to iframe contents: http://stackoverflow.com/questions/11872917/check-if-js-has-access-to-an-iframes-document. This way we can
have it act on same-domain iframes, like twitter uses for article embeds. */
/*** USER: END GLOBAL VARIABLES ***/
/* Let's get our variables together & tailored to whatever the current site is */
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Checking keys now");
globalBadWords = attachSiteSpecifics(globalBadWords||"dummysonothingchokes", siteSpecificBadWords);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("globalBadWords ", globalBadWords);
selectorsToConsiderTogether = attachSiteSpecifics(selectorsToConsiderTogether||"dummysonothingchokes", siteSpecificSelectorsToConsiderTogether);
var selectorsToConsiderTogetherRegex = selectorsToConsiderTogether.replace(/\|/g, ",");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("selectorsToConsiderTogether ", selectorsToConsiderTogether);
selectorsToAlwaysHide = attachSiteSpecifics(selectorsToAlwaysHide||"dummysonothingchokes", constantSiteSpecificSelectorsToAlwaysHide);
var selectorsToAlwaysHideRegex = selectorsToAlwaysHide.replace(/\|/g, ",");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("selectorsToAlwaysHide ", selectorsToAlwaysHide);
var parentsToHideIfAChildIsHidden = attachSiteSpecifics("dummysonothingchokes",siteSpecificParentsToHideIfAChildIsHidden).replace(/\|/g, ",");
var exemptRegexp = new RegExp(exemptSites, "gi");
var theBadFBURLWords = new RegExp("https?\:\/\/[w.]*facebook\.com\/(" + badFBURLWords + ")[?/]", "gi");
var theBadFBNames = new RegExp("mdelimiter(" + badFBNames + ")mdelimiter", "gi");
if (!Element.prototype.matches) {
Element.prototype.matches =
Element.prototype.matchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector ||
Element.prototype.oMatchesSelector ||
Element.prototype.webkitMatchesSelector ||
function(s) {
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
i = matches.length;
while (--i >= 0 && matches.item(i) !== this) {}
return i > -1;
};
} /* this 'polyfill' provides the function element.matches() whether or not the browser provides it natively. from https://developer.mozilla.org/en-US/docs/Web/API/Element/matches */
if (typeof GM_registerMenuCommand == 'undefined') {
function GM_registerMenuCommand(caption, commandFunc, accessKey) {
if (!document.body) {
console.error('GM_registerMenuCommand got no body.');
return;
}
let menu = document.getElementById('gm-registered-menu');
if (!menu) {
menu = document.createElement('menu')
menu.setAttribute('id', 'gm-registered-menu');
menu.setAttribute('type', 'context');
document.body.appendChild(menu);
document.body.setAttribute('contextmenu', 'gm-registered-menu');
}
let menuItem = document.createElement('menuitem');
menuItem.textContent = caption;
menuItem.addEventListener('click', commandFunc, true);
menu.appendChild(menuItem);
}
}
$(document).keydown(function (e) {
if (e.originalEvent.ctrlKey && e.originalEvent.altKey && e.originalEvent.shiftKey && e.originalEvent.keyCode == 32) {
exemptThisPage(0); //EXEMPT PAGE WITH CTRL-OPTION-SHIFT-SPACE
}
if (e.originalEvent.ctrlKey && e.originalEvent.altKey && e.originalEvent.shiftKey && e.originalEvent.code == "KeyL") {
CONSOLE_DEBUGGING_MESSAGES_ON=(CONSOLE_DEBUGGING_MESSAGES_ON==false); //turn off logging with CTRL-OPTION-SHIFT-L
alert("logging is now "+CONSOLE_DEBUGGING_MESSAGES_ON);
}
});
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("########### PRELIMINARY DECLARATIONS FINISHED ############################### ");
function attachSiteSpecifics(globalString, siteSpecificArray) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √224√ starting 'function attachSiteSpecifics( globalString, siteSpecificArray) ' ~ ~ ~", "", "ULTRA");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Attaching site specifics for ", globalString);
Object.keys(siteSpecificArray).forEach(function(key) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √226√ starting 'function( key) ' ~ ~ ~", "", "ULTRA");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Checking key ", key);
var value = siteSpecificArray[key];
var hostRegexp = new RegExp(key, "gi");
var hostMatch = document.location.hostname.match(hostRegexp); /* time consuming, according to chrome profiler 1.3 secs */
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("About to match 3 ", hostMatch);
if (hostMatch !== null) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √235√ 'if ( hostMatch !== null) ' ~ ~ ~", "", "ULTRA");
globalString = value + (globalString == "" ? "" : "|" + globalString );
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("added site-specific " + key);
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √226√ ending 'function( key) ' ~ ~ ~ ~ ~", "", "ULTRA");
});
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √224√ ending 'function attachSiteSpecifics( globalString, siteSpecificArray) ' ~ ~ ~ ~ ~", "", "ULTRA");
return globalString;
}
/* Create our artisanal handcrafted regexes to use below */
var theBadWords = new RegExp(globalBadWords, "gi");
var theBadWordsAndFBNames = new RegExp("(" + globalBadWords + ")|(" + badFBNames + ")", "gi");
/* Note currently used:
var theNotAsBadWords = new RegExp(notAsBadWords, "gi");
var theBadWords_forURLs = new RegExp(badURLWords, "gi");
var allBadWords = new RegExp(badURLWords + "|" + notAsBadWords + "|" + globalBadWords, "gi");
*/
/*$.extend($.expr[":"], {
followsWebCooled: function(a) {
return $(a).prev().attr(thisScriptHiddenAttribute) == "true";
}
});*/ /* maybe I'll use this... someday... */
function stupidHash(theString) {
var j;
var out = 1;
for (j = 0; j < theString.length; j++) {
out = out * (1.0001 + ((theString.charCodeAt(j)) + j) / (256 + j));
}
return out.toString();
}
var docbodyjq=$(document.body);
if(!document.body.hasAttribute("wcHash")) {
docbodyjq.attr("wcHash", stupidHash(document.location.href)); /* custom hash usable in exemptsites variable */ /* time consuming, according to chrome profiler 1.1 secs */
}
if(!document.body.hasAttribute("wcHashHost")) {
docbodyjq.attr("wcHashHost", "H" + stupidHash(document.location.hostname)); /* custom hash usable in exemptsites variable */
}
async function mainScript(elLengthOld, theDelay, mutation, sessionID, currentMatches) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Mutation in MainScript ",mutation.target);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √270√ starting 'function main( elLengthOld, theDelay, mutation, sessionID,currentMatches) ' ~ ~ ~", "", "ULTRA");
/* big stuff happens here */
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Main running. Mutation:", mutation);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Main running mutation.length:", mutation.length);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Main running. currentMatches:", currentMatches);
observerEnable = false;
var thisActiveElement = document.activeElement;
/* var thisTarget = $(mutation.target); */
var i;
var loopLength = (mutation.type = "childList" ? mutation.addedNodes.length : 1);
for (i = 0; i < loopLength; i++) { //begin for loop to hit all added nodes
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("In for loop:", "iteration " + i + " of " + loopLength);
var targetNotJQ = mutation.type = "childList" ? mutation.addedNodes[i] : mutation.target; //we checked that addedNodes has length >0 before calling main(), so no error here
var thisTarget = $(targetNotJQ);
var theTargetInnerHTML = targetNotJQ.innerHTML
if (targetNotJQ.offsetWidth >0 && targetNotJQ.offsetHeight >0 && thisTarget.attr(thisScriptHiddenAttribute) !="true" && theTargetInnerHTML != thisTarget.data("oldInnerHTML") ){
thisTarget.data("oldInnerHTML",theTargetInnerHTML);
//only check the mut.target if no nodes are recorded as having been added, and innerHTML has changed since last run
var mutationParent = thisTarget.parent();
/* You know, if the mutationtype is "added nodes", you can get the added nodes from the mutation object and just check those. If nodes are removed, it may be marked "added nodes" but then the addednodes attribute is empty and removednodes is not. */
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("ThisTarget is: (about to detach):", thisTarget);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("mutationParent:", mutationParent);
/* for next line: thisTarget is an OBJECT, not a page elemnt! you have to get the page element by index! */
/* userscripts are triggered when body is added... that's why we can't detach and re-add the body, it'll get stuck in a loop. Maybe shoudl add an attrubute to the body or something to let it do it once but not again. */
if (!!thisTarget.length && thisTarget[0].tagName != "BODY") {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √278√ 'if( thisTarget.tagName != ''BODY'') ' ~ ~ ~:", thisTarget[0].tagName, "ULTRA");
/* something was interfering with a lot of normal page operations, things were reloading, etc. I'm hoping this conditional fixes it. */
var placeholder = $('<span style="display: none;" />').insertAfter(thisTarget);
thisTarget.detach();
}
//makes things faster
/* DIDN'T WORK... see bottom of main function */
if (HILIGHT_ELEMENTS_BEING_PROCESSED) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √284√ 'if ( HILIGHT_ELEMENTS_BEING_PROCESSED) ' ~ ~ ~", "", "ULTRA");
observerEnable = false;
targetNotJQ.style =
"border: 5px dotted rgba(100,0,100,1) !important; background:rgb(100,0,100) !important;" +
targetNotJQ.style;
thisTarget.data("highlighted", true);
observerEnable = true;
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("checking node:", targetNotJQ);
if (typeof thisTarget.data() === "object" &&
(!thisTarget.data("scriptprocid") ||
thisTarget.data("scriptprocid") != sessionID)
) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √296√ starting 'if ( typeof thisTarget.data() === ''object'' && 298 (!thisTarget.data(''scriptprocid'') || 299 thisTarget.data(''scriptprocid'') != sessionID) 300 ) ' ~ ~ ~", "", "ULTRA");
wcSetAttributeSafely(targetNotJQ, "scriptprocid", sessionID);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Confirmed not yet checked this session:", targetNotJQ);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("about to find selectorsToConsiderTogether:", "");
/* I should skip this and the next if the top-level node's inner text doesn't contain badwords, save some time cycling through them */
/* var theseNodes=thisTarget
.find("*")
.addBack(); */
var theseNodesForEach = thisTarget
.find(selectorsToConsiderTogetherRegex).addBack(selectorsToConsiderTogetherRegex)
.filter(function() {
var filtThis = this;
var filtThisInnerHTML = filtThis.innerHTML;
var filtThisjq= $(this);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √312√ starting 'function( ) ' ~ ~ ~", "", "ULTRA");
if (HILIGHT_ELEMENTS_BEING_PROCESSED) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √313√ 'if ( HILIGHT_ELEMENTS_BEING_PROCESSED) ' ~ ~ ~", "", "ULTRA");
/* debugger; */
filtThis.style =
"border: 5px dotted rgba(0,0,160,1) !important; background:rgba(0,0,255,.5) !important;" +
filtThis.style;
filtThisjq.data("highlighted", true);
}
var theBadWordsFound = filtThisjq.text().match(currentMatches) ? filtThisjq.text().match(theBadWords) : null; /* check current matches first to save time, then check against actual regex so partial text matches dont cause false positives (IE 'hanran' doesn't match "NRA" in the second one.) */
if (theBadWordsFound !== null && filtThisjq.data("oldInnerHTML") != filtThisInnerHTML && (!filtThisjq.data("scriptprocid") ||
filtThisjq.data("scriptprocid") != sessionID) &&
/* was: !$(this).prop("isContentEditable") */
(thisActiveElement.tagname == "BODY" ? true : (!!filtThisjq.prop("isContentEditable") == false && filtThisjq.has("[contenteditable]").length == 0)) /* rejects anything with editable descendants */
) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √321√ starting 'if ( theBadWordsFound!== null && (!$(this).data(''scriptprocid'') || 324 $(this).data(''scriptprocid'') != sessionID) && 325 /* was: !$(this).prop(''isContentEditable'') */ 326 ( thisActiveElement.tagname==''BODY''?true: ($(this).prop(''isContentEditable'')==false && $(this).has(''[contenteditable]'').length==0)) /* rejects anything with editable descendants */ 327 ) ' ~ ~ ~", "", "ULTRA");
if (HILIGHT_ELEMENTS_BEING_PROCESSED) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √328√ 'if ( HILIGHT_ELEMENTS_BEING_PROCESSED) ' ~ ~ ~", "", "ULTRA");
/* debugger; */
filtThis.style =
"border: 5px dotted rgba(0,160,160,1) !important; background:rgba(0,255,255,.5) !important;" +
filtThis.style;
filtThisjq.data("highlighted", true);
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("found '" + theBadWordsFound + "' in selectorsToConsiderTogether", filtThis);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √321√ ending 'if ( theBadWordsFound!== null && (!$(this).data(''scriptprocid'') || 324 $(this).data(''scriptprocid'') != sessionID) && 325 /* was: !$(this).prop(''isContentEditable'') */ 326 ( thisActiveElement.tagname==''BODY''?true: ($(this).prop(''isContentEditable'')==false && $(this).has(''[contenteditable]'').length==0)) /* rejects anything with editable descendants */ 327 ) ' ~ ~ ~ ~ ~", "", "ULTRA");
filtThisjq.data("scriptprocid", sessionID);
filtThisjq.data("oldInnerHTML", filtThisInnerHTML);
return true;
} else {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √321√ 'else ', returning false ~ ~ ~", "", "ULTRA");
return false;
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √312√ ending 'function( ) ' ~ ~ ~ ~ ~", "", "ULTRA");
}); /* end filter function */
var theseNodesForEachl = theseNodesForEach.length;
//start replacement to get rid of .each() because it's very slow
for (var theseNodesForEachi=0;theseNodesForEachi<theseNodesForEachl; theseNodesForEachi++) {
var tn=theseNodesForEach[theseNodesForEachi];
var tnjq=$(tn);
var hiddencounttnjq = 0;
var hiddenclasstnjq =tnjq.attr('class');
while (typeof tnjq.parent()[0] != 'undefined' && tnjq.parent().attr("hiddenclasstnjq",hiddenclasstnjq)[0].matches(parentsToHideIfAChildIsHidden)) {tnjq = tnjq.parent();
tnjq.attr("hiddencount",++hiddencounttnjq).attr("hiddenclass",hiddenclasstnjq);}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √347√ starting 'function( ) ' ~ ~ ~", "", "ULTRA");
if (thisPageIsExempt) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √348√ 'if ( thisPageIsExempt) ' ~ ~ ~", "", "ULTRA");
tnjq
.css("border", "3px solid red")
.css("background", "rgba(255,225,225,.5)")
.attr(thisScriptHiddenAttribute, "true");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("TEST added red to", tn);
} else {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √353√ 'else ' ~ ~ ~", "", "ULTRA");
tnjq
.hide()
.data("savedstyle", tnjq.attr("style"))
.attr("style", "display:none !important")
.attr(thisScriptHiddenAttribute, "true");
}
wcSetAttributeSafely(tn, "scriptprocid", sessionID);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("added red to",tn);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √347√ ending 'function( ) ' ~ ~ ~ ~ ~", "", "ULTRA");
}
//end replacement
/* TEXT NODES ONLY NOW: */
var walk = thisTarget /*find ordinarily only returns child elements unless you add addBack.*/
/* .find(':visible:not("iframe")').addBack(':visible:not("iframe")') */
/* march 2023: not even going to walk the tree if text content of top node doesn't contain badwords. Hopefully this will improve performance */
.filter(function() {
var theFiltThis=this.textContent;
var theBadWordsNodeValueFound = theFiltThis.match(/[a-zA-Z]/) ?theFiltThis.match(theBadWords) : null; /* first make sure theres even text content to filter *//*see comment above on previous use of this about this */
return (theBadWordsNodeValueFound !== null );
/* was !$(this).prop( "isContentEditable" ) /~ cant use === false because .prop("isContentEditable") === undefined for text nodes ~/ */
/* update... !!value will coerce value=undefined to false */
})
/* end march 2023 addition */
.find(':not("iframe,script,style")').addBack(':visible:not("iframe,script,style")')
.contents() /* like children() but also includes text and comment nodes */
.filter(function() {
return (this.nodeType === 3);
})
.filter(function() {
var theFiltThis=this;
var theFiltThisjq=$(this);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √372√ starting 'function( ) ' ~ ~ ~", "", "ULTRA");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("filtering node:", theFiltThis, "greenCrit");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("filtered nodeValue is:", theFiltThis.nodeValue, "greenCrit");
/* //!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("filtered node value - currentMatches is:", currentMatches, "greenCrit");
*/
/* //!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("filtered node value - theBadWords is:", theBadWords,"greenCrit");
*/
var theBadWordsNodeValueFound = theFiltThis.nodeValue.match(/[a-zA-Z]*/) ?theFiltThis.nodeValue.match(currentMatches) ? theFiltThis.nodeValue.match(theBadWords) : null:null; /* first make sure theres even text content to filter *//*see comment above on previous use of this about this */
var theCriteria =
theBadWordsNodeValueFound !== null &&
(thisActiveElement.tagName == "BODY" ? true : (!!theFiltThisjq.prop("isContentEditable") == false && !!theFiltThisjq.has("[contenteditable]").length == false)); /* rejects anything with editable descendants */
/* was !$(this).prop( "isContentEditable" ) /~ cant use === false because .prop("isContentEditable") === undefined for text nodes ~/ */
/* update... !!value will coerce value=undefined to false */
var tempVar = theFiltThisjq;
var theCritResult = {
"filter returns result": theCriteria,
"theBadWordsNodeValueFound": theBadWordsNodeValueFound,
"thisActiveElement": thisActiveElement,
"thisActiveElement.tagName": thisActiveElement.tagName,
"!!$(this).prop('isContentEditable')": !!tempVar.prop("isContentEditable"),
"!!$(this).has('[contenteditable]').length==false)": !!tempVar.has("[contenteditable]").length == false
};
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("the filter returns (true for include):", theCritResult, "greenCrit");
if (theCriteria && CONSOLE_DEBUGGING_MESSAGES_ON) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("456 Matched green ", theBadWordsNodeValueFound, "greenCrit");
}
if (!theCriteria && CONSOLE_DEBUGGING_MESSAGES_ON) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √393√ 'if ( !theCriteria && CONSOLE_DEBUGGING_MESSAGES_ON) ' ~ ~ ~", "", "ULTRA");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("theBadWordsNodeValueFound ", theBadWordsNodeValueFound, "greenCrit");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("document.activeElement.tagName ", thisActiveElement.tagName, "greenCrit");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("$(this) ", tempVar );
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("$(this).prop(isContentEditable) ", tempVar.prop("isContentEditable"), "greenCrit" );
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("$(this).has([contenteditable]).length ", tempVar.has("[contenteditable]").length, "greenCrit" );
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √372√ ending 'function( ) ' ~ ~ ~ ~ ~", "", "ULTRA");
return theCriteria;
}); /* filter function 2 done */
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("about to walk text leaves:", walk);
//about to replace walk.each
var walkl=walk.length;
for (var walki=0;walki<walkl; walki++){
var wvar=walk[walki];
var wvjq=$(wvar);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √420√ starting 'function( ) ' ~ ~ ~","beginning to look for selectors to consider together", "ULTRA");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("walking text leaf:", wvjq[0] || wvar);
/* don't know why this[0] is sometimes, maybe always, not evaluating. don't care right now. maybe needs to be $(this)[0]?*/
var theClosest = wvjq.closest(selectorsToConsiderTogetherRegex); /* I need to use nextUntil() and prevUntil() to add consecutive sibling dd's and dt's to theClosest so one doesn't get left if the other is removed. See https://en.wikipedia.org/wiki/List_of_music_considered_the_worst for example. Too tired to do it right now though. */
var theClosestBlock = theClosest.length === 0 ? wvjq.closest("p,div,td,table,h1,h2,h3,h4,h5,h6,li,dd,dt" /* '[style*=display:block]'*/ ) : theClosest;
theClosest = theClosest.length === 0 ? theClosestBlock : theClosest;
/* sometimes the mutation target is just a text node that changed (like clicking a "more" link on facebook. In that case, see if it's enclosed in one of selectorsToConsiderTogether before just looking for the closest() parent block element. */
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("theClosestBlock:", theClosestBlock);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("theClosest:", theClosest);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("theClosestBlock:");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging(theClosestBlock);
var hiddencounttheClosest = 0;
var hiddenclasstheClosest =theClosest.attr('class');
while (typeof theClosest.parent()[0] != 'undefined' && theClosest.parent().attr("hiddenclasstheClosest",hiddenclasstheClosest)[0].matches(parentsToHideIfAChildIsHidden)) {theClosest = theClosest.parent();
theClosest.attr("hiddencount",++hiddencounttheClosest).attr("hiddenclass",hiddenclasstheClosest);}
if (thisPageIsExempt) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √437√ starting 'if ( thisPageIsExempt) ' ~ ~ ~", "", "ULTRA");
theClosest
.css("border", "1px solid green")
.css("background", "rgba(225,255,225,.5)")
.attr(thisScriptHiddenAttribute, "true");
if (theClosest != theClosestBlock) {
theClosestBlock
.css("border", "1px dotted darkgreen")
.css("background", "rgba(200,255,200,.5)")
.attr(thisScriptHiddenAttribute, "true");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("495 Setting css for (theClosest != theClosestBlock)", theClosestBlock, "ULTRA");
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √437√ ending 'if ( thisPageIsExempt) ' ~ ~ ~ ~ ~", "", "ULTRA");
} else {
theClosest
.hide()
.data("savedstyle", theClosest.attr("style"))
.attr("style", "display:none !important")
.attr(thisScriptHiddenAttribute, "true");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √437√ ELSE (page isn't exempt) ' ~ ~ ~ ~ ~", theClosest, "ULTRA");
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("added green to", theClosest[0] || theClosest);
/* don't know why theClosest[0] is sometimes, maybe always, not evaluating. don't care right now. */
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √420√ ending 'function( ) ' ~ ~ ~ ~ ~", "endinging looking for selectors to consider together", "ULTRA");
}
//end replacement
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("done walking text leaves", walk);
/* NOW A ONLY */
var theseAnodes = thisTarget
.find("span.fwb, a[data-hovercard]").addBack("span.fwb, a[data-hovercard]").filter(function() {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("filtering theseAnodes", this, "ULTRA");
// WAS .find("A,span.fwb") , BUT DON'T NEED A, NAME IS ENOUGH
var theFiltThis = this;
var theFiltThisjq = $(this);
return (typeof theFiltThisjq.data() === "object" &&
(!theFiltThisjq.data("scriptprocid") ||
theFiltThisjq.data("scriptprocid") != sessionID)); /* it seemed to work without this semicolon, but jshint said I need it. */
});
/* that was A selectors to consider together, this is other A nodes */
var aWalk = theseAnodes /*find ordinarily only returns child elements unless you add addBack.*/
.filter(function() {
var theFiltThis = this;
var theFiltThisjq = $(this);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √475√ 'function( ) ' ~ ~ ~", "", "ULTRA");
wcSetAttributeSafely(theFiltThis, "scriptprocid", sessionID);
var itsAhref = false; /* was (typeof this.href) === 'string' && (this.href.match(theBadFBURLWords) || ("mdelimiter"+$(this).text()+"mdelimiter").match(theBadFBNames)) && this.href != "#"; */
var itsFWBSpan = (typeof theFiltThis.tagName) === 'string' && theFiltThis.tagName == "SPAN" /* fails if not uppercase */ && theFiltThisjq.hasClass("fwb");
var itsDataHovercard = (typeof theFiltThis.tagName) === 'string' && theFiltThis.tagName == "A" && theFiltThisjq.is("[data-hovercard]");
var itsAname = (itsFWBSpan || itsDataHovercard) && ("mdelimiter" + theFiltThisjq.text() + "mdelimiter").match(theBadFBNames);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("found A section fwb span", theFiltThisjq.text());
/* //!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("itsAname",itsAname);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("(typeof this.tagName) === 'string'",(typeof this.tagName) === 'string');
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("this.tagName=='span'",this.tagName);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("$(this).hasClass('fwb')",$(this).hasClass("fwb"));
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("('mdelimiter'+$(this).text()+'mdelimiter').match(theBadFBNames)",("mdelimiter"+$(this).text()+"mdelimiter").match(theBadFBNames));
*/
return (itsAhref || itsAname);
})
.filter(function() {
var theFiltThis = this;
var theFiltThisjq = $(this);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √490√ starting 'function( ) ' ~ ~ ~", "", "ULTRA");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("filtering A section pt II node:", theFiltThis);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("filtered A section pt II node value is:", theFiltThis.nodeValue);
var theCriteria =
(thisActiveElement.tagName == "BODY" ? true : (!!theFiltThisjq.prop("isContentEditable") == false && theFiltThisjq.has("[contenteditable]").length == 0)); /* rejects anything with editable descendants */
/* was !$(this).prop( "isContentEditable" ) /~ cant use === false because .prop("isContentEditable") === undefined for text nodes ~/ */
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("the A section filter returns (true for include):", theCriteria );
if (theCriteria && CONSOLE_DEBUGGING_MESSAGES_ON) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √503√ starting 'if ( theCriteria && CONSOLE_DEBUGGING_MESSAGES_ON) ' ~ ~ ~", "", "ULTRA");
if ((typeof theFiltThis.href) === "string" && theFiltThis.href.match(theBadFBURLWords)) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Matched purple href ", theFiltThis.href.match(theBadFBURLWords));
} else {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Matched purple contents ", ("mdelimiter" + theFiltThisjq.text() + "mdelimiter").match(theBadFBNames));
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √503√ ending 'if ( theCriteria && CONSOLE_DEBUGGING_MESSAGES_ON) ' ~ ~ ~ ~ ~", "", "ULTRA");
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √490√ ending 'function( ) ' ~ ~ ~ ~ ~", "", "ULTRA");
return theCriteria;
});
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("about to walk A leaves in A section:", aWalk);
var awalkl=aWalk.length;
for (var awalki=0;awalki<awalkl; awalki++) {
var awvar=theseNodesForEach[theseNodesForEachi];
var awjq=$(awvar)
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √526√ starting 'function( ) ' ~ ~ ~", "", "ULTRA");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("walking A section leaf:", awjq[0] || awvar);
/* don't know why this[0] is sometimes, maybe always, not evaluating. don't care right now. maybe needs to be $(this)[0]?*/
var theClosest = awjq.closest(selectorsToConsiderTogetherRegex); /* I need to use nextUntil() and prevUntil() to add consecutive sibling dd's and dt's to theClosest so one doesn't get left if the other is removed. See https://en.wikipedia.org/wiki/List_of_music_considered_the_worst for example. Too tired to do it right now though. */
var theClosestBlock = theClosest.length === 0 ? awjq.closest("p,div,td,table,h1,h2,h3,h4,h5,h6,li,dd,dt" /* '[style*=display:block]' */ ) : theClosest;
theClosest = theClosest.length === 0 ? theClosestBlock : theClosest;
/* sometimes the mutation target is just a text node that changed (like clicking a "more" link on facebook. In that case, see if it's enclosed in one of selectorsToConsiderTogether before just looking for the closest() parent block element. */
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("theClosestBlock:", theClosestBlock);
var hiddencounttheClosest = 0;
var hiddenclasstheClosest =theClosest.attr('class');
while (typeof theClosest.parent()[0] != 'undefined' && theClosest.parent().attr("hiddenclasstheClosest",hiddenclasstheClosest)[0].matches(parentsToHideIfAChildIsHidden)) {theClosest = theClosest.parent();
theClosest.attr("hiddencount",++hiddencounttheClosest).attr("hiddenclass",hiddenclasstheClosest);}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("theClosest:", theClosest);
if (thisPageIsExempt == true) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √543√ starting 'if ( thisPageIsExempt == true) ' ~ ~ ~", "", "ULTRA");
theClosest
.css("border", "1px solid aqua")
.css("background", "rgba(150,250,250,.5)")
.attr(thisScriptHiddenAttribute, "true");
if (theClosest != theClosestBlock) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √548√ 'if ( theClosest != theClosestBlock) ' ~ ~ ~", "", "ULTRA");
theClosestBlock
.css("border", "1px dotted aqua")
.css("background", "rgba(150,250,250,.5)")
.attr(thisScriptHiddenAttribute, "true");
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √543√ ending 'if ( thisPageIsExempt == true) ' ~ ~ ~ ~ ~", "", "ULTRA");
} else {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √554√ 'else ' ~ ~ ~", "", "ULTRA");
theClosest
.hide()
.data("savedstyle", theClosest.attr("style"))
.attr("style", "display:none !important")
.attr(thisScriptHiddenAttribute, "true");
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("added aqua to", theClosest[0] || theClosest);
/* don't know why theClosest[0] is sometimes, maybe always, not evaluating. don't care right now. */
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √526√ ending 'function( ) ' ~ ~ ~ ~ ~", "", "ULTRA");
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("done walking A section text leaves", aWalk);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √296√ ending 'if ( typeof thisTarget.data() === ''object'' && 298 (!thisTarget.data(''scriptprocid'') || 299 thisTarget.data(''scriptprocid'') != sessionID) 300 ) ' ~ ~ ~ ~ ~", "", "ULTRA");
} else {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √571√ 'else ' ~ ~ ~", "", "ULTRA");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("skipped crit1:", targetNotJQ);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("skipped crit2: typeof thisTarget.data():", typeof thisTarget.data());
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("skipped crit3:thisTarget.data(scriptprocid) :", thisTarget.data("scriptprocid"));
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("skipped crit4: sessionID:", sessionID);
wcSetDebuggingAttributeSafely(targetNotJQ, "thisNodeSkippedForSession", sessionID);
}
/* Now let's check for wrongly hidden things. this is because sometimes Twitter seems to be setting input fields temporarily to uneditable while backspace key is being hit, and the script jumps in and hides them. */
/* this isn't the best way to do this, I don't think. Sometimes a "+thisScriptHiddenAttribute+" element CONTAINS an editable one. Not sure if this catches those. (UPDATE: seems to be working, will fix if it doesn't always. */
if (thisActiveElement.tagName != "BODY") {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √585√ starting 'while backspace key is being hit, and the script jumps in and hides them. */ 586 587 588 /* this isn't the best way to do this, I don't think. Sometimes a "+thisScriptHiddenAttribute+" element CONTAINS an editable one. Not sure if this catches those. (UPDATE: seems to be working, will fix if it doesn't always. */ if(thisActiveElement.tagName != ''BODY'') ' ~ ~ ~", "", "ULTRA");
/* only do if there is an active input element */
var hiddenWalk = thisTarget
.find("["+thisScriptHiddenAttribute+"=true]:has([contenteditable])")
.addBack("["+thisScriptHiddenAttribute+"=true]:has([contenteditable])");
if (thisPageIsExempt) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √594√ starting 'if ( thisPageIsExempt) ' ~ ~ ~", "", "ULTRA");
var hiddenwalkl=hiddenWalk.length;
for (var hiddenwalki=0;hiddenwalki<hiddenwalkl; hiddenwalki++) {
var hw=hiddenWalk[hiddenwalki];
var hwjq=$(hw);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √595√ 'function( ) ' ~ ~ ~", "", "ULTRA");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("unhiding text leaf:", hw);
hwjq
.css("border", "1px solid blue")
.css("background", "#CCCCFF")
.css("background", "rgba(225,225,255,.5)")
.attr("style", hwjq.data("savedstyle"))
.attr(thisScriptHiddenAttribute, "");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("added blue to", hwjq);
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √594√ ending 'if ( thisPageIsExempt) ' ~ ~ ~ ~ ~", "", "ULTRA");
} else {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √608√ starting 'else ' ~ ~ ~", "", "ULTRA");
var hiddenwalkl=hiddenWalk.length;
for (var hiddenwalki=0;hiddenwalki<hiddenwalkl; hiddenwalki++) {
var hw=hiddenWalk[hiddenwalki];
var hwjq=$(hw);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √609√ 'function( ) ' ~ ~ ~", "", "ULTRA");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("unhiding text leaf:",hw);
hwjq.show().attr(thisScriptHiddenAttribute, "");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("added blue to", hwjq);
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √608√ ending 'else ' ~ ~ ~ ~ ~", "", "ULTRA");
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √585√ ending 'while backspace key is being hit, and the script jumps in and hides them. */ 586 587 588 /* this isn't the best way to do this, I don't think. Sometimes a "+thisScriptHiddenAttribute+" element CONTAINS an editable one. Not sure if this catches those. (UPDATE: seems to be working, will fix if it doesn't always. */ if(thisActiveElement.tagName != ''BODY'') ' ~ ~ ~ ~ ~", "", "ULTRA");
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("targetNotJQ ",targetNotJQ);
var theSelectorsToAlwaysHide = docbodyjq /*don't use thisTarget -- the selector to always hide can sometimes be in the mutationTarget but not in the addedNodes (UPDATE THIS. USE THE MUTATION.TARGET, NOT THE DOCUMENT.BODY AND SEE IF IT WORKS.*/
.find(selectorsToAlwaysHideRegex)
.not("["+thisScriptHiddenAttribute+"]");
//while (theSelectorsToAlwaysHide ) { //!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √620√ starting 'while (theSelectorsToAlwaysHide ) ' ~ ~ ~","","ULTRA");
var theSelectorsToAlwaysHidel=theSelectorsToAlwaysHide.length;
for (var theSelectorsToAlwaysHidei=0;theSelectorsToAlwaysHidei<theSelectorsToAlwaysHidel; theSelectorsToAlwaysHidei++) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √621√ starting 'function( ) ' ~ ~ ~", "", "ULTRA");
/* we do this _after_ seaching for badwords so selectortoalwayshide that use ["+thisScriptHiddenAttribute+"] will get catch things that were just hidden */
var tstah = theSelectorsToAlwaysHide[theSelectorsToAlwaysHidei];
var tsjq = $(tstah);
var theClosesttsjq = tsjq.closest(selectorsToConsiderTogetherRegex);
theClosesttsjq = theClosesttsjq.length > 0? theClosesttsjq : tsjq;
var hiddencounttsjq = 0;
var hiddenclasstsjq =theClosesttsjq.attr('class');
while (typeof theClosesttsjq.parent()[0] != 'undefined' && theClosesttsjq.parent().attr("hiddenclasstsjq",hiddenclasstsjq)[0].matches(parentsToHideIfAChildIsHidden)) {theClosesttsjq = theClosesttsjq.parent();
theClosesttsjq.attr("hiddencount",++hiddencounttsjq).attr("hiddenclass",hiddenclasstsjq);}
if (thisPageIsExempt) {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √624√ 'if ( thisPageIsExempt) ' ~ ~ ~", "", "ULTRA");
theClosesttsjq
.css("border", "1px solid orange")
.css("background", "rgba(255,240,225,.5")
.attr(thisScriptHiddenAttribute, "true");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Added orange to", theClosesttsjq);
} else {
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~ √630√ 'else ' ~ ~ ~", "", "ULTRA");
theClosesttsjq.hide().attr(thisScriptHiddenAttribute, "true");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("Added orange to", theClosesttsjq);
}
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("added orange to", tstah);
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √621√ ending 'function( ) ' ~ ~ ~ ~ ~", "", "ULTRA");
}
// theSelectorsToAlwaysHide =thisTarget.find(selectorsToAlwaysHide.replace(/\|/g, ",")).not("["+thisScriptHiddenAttribute+"]");
!CONSOLE_DEBUGGING_MESSAGES_ON || logForDebugging("~~~~~ √620√ ending 'while (theSelectorsToAlwaysHide ) ' ~ ~ ~ ~ ~","","ULTRA");
if (!!thisTarget.length && thisTarget[0].tagName != "BODY") {