Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Harmonator
- // @namespace Dalek-Human-Alliance
- // @description Harmonator makes some paragraphs pink.
- // @include http://*
- // @include https://*
- // @grant none
- // @version 1.0.0.0
- // ==/UserScript==
- //------------------------------------------------------------------------------
- // Index
- //------------------------------------------------------------------------------
- // Debugging functions
- // FunctionName(): String
- // Defined(x): Boolean
- // Assigned(x): Boolean
- // Assert(Assertion, ErrorMsg)
- // Object helper functions
- // IsEmpty(ObjectOrArray): Boolean
- // String helper functions
- // String.TrimLeft(): String
- // String.TrimRight(): String
- // String.Trim(): String
- // String.TrimDS(): String
- // String.HasWord(Word): Boolean
- // String.AddWord(Word): String
- // String.IncludeWord(Word): String
- // String.ExcludeWord(Word): String
- // HTML/CSS helper functions
- // GetFirstElementByTagName(Root, TagName): Element
- // GetFirstElementByTagNameAndClass(Root, TagName, ClassName): Element
- // AddCSS(CSSText): Element
- // HasClass(Element, ClassName): Boolean
- // IncludeClass(Element, ClassName)
- // ExcludeClass(Element, ClassName)
- // SetClassBoolean(Element, ClassName, DoInclude)
- // Harmonator implementation
- // AddCustomStyles(): Element
- // StyleUnsightlyText(Node, VisitedClassName, MarkedClassName, Keywords)
- // Harmonate(Node, Keywords)
- // Main()
- //------------------------------------------------------------------------------
- // Debugging functions
- //------------------------------------------------------------------------------
- // FunctionName(): String
- //
- // Returns the name of whatever function calls this. The call operator "()" is
- // excluded.
- function FunctionName() {
- return arguments.callee.caller.name;
- }
- //------------------------------------------------------------------------------
- // Defined(x): Boolean
- //
- // Returns true iff x is defined. A defined value may be an empty string, zero,
- // a NaN or even null.
- function Defined(x) {
- return typeof x != 'undefined';
- }
- //------------------------------------------------------------------------------
- // Assigned(x): Boolean
- //
- // Returns true iff x is both defined and assigned any value but null. The
- // name "Assigned" is intended to mirror the Delphi function for testing if
- // a pointer is not nil, but is augmented to fit with Javascript's inclusion
- // of a distinct 'undefined' datatype.
- //
- // This function is useful for object references. It enhances code clarity and
- // lessens the risk of the relational operator used to test for assignment being
- // mistakenly applied to surrounding expression terms.
- function Assigned(x) {
- return Defined(x) && (x != null);
- }
- //------------------------------------------------------------------------------
- // Assert(Assertion, ErrorMsg)
- //
- // If Assertion is false, an exception with the given error message is raised.
- function Assert(Assertion, ErrorMsg) {
- if (!Assertion) {
- throw new Error(ErrorMsg);
- }
- }
- //------------------------------------------------------------------------------
- // Object helper functions
- //------------------------------------------------------------------------------
- // IsEmpty(ObjectOrArray): Boolean
- //
- // Returns true iff the array or object has no elements or properties (key-value
- // pairs), not counting those that are a part of the property chain, the means
- // by which new methods are defined for new objects created with their usual
- // constructors.
- function IsEmpty(ObjectOrArray) {
- var Result;
- var Key;
- Assert(
- typeof ObjectOrArray == 'object',
- 'IsEmpty() cannot be used on anything of the "' +
- (typeof ObjectOrArray) + '" data type.'
- )
- if (ObjectOrArray instanceof Array) {
- Result = ObjectOrArray.length == 0;
- } else {
- Result = true;
- for (Key in ObjectOrArray) {
- if (ObjectOrArray.hasOwnProperty(Key)) {
- // This object has a property it truly owns, not just something
- // that's just a part of the property chain. Therefore, the object
- // is not empty.
- Result = false;
- break;
- }
- }
- }
- return Result;
- }
- //------------------------------------------------------------------------------
- // String helper functions
- //------------------------------------------------------------------------------
- // String.TrimLeft(): String
- //
- // Returns the string with leading spaces removed.
- String.prototype.TrimLeft = function() {
- return this.replace(/^ +/, '');
- }
- //------------------------------------------------------------------------------
- // String.TrimRight(): String
- //
- // Returns the string with trailing spaces removed.
- String.prototype.TrimRight = function() {
- return this.replace(/ +$/, '');
- }
- //------------------------------------------------------------------------------
- // String.Trim(): String
- //
- // Returns the string with both leading and trailing spaces removed.
- String.prototype.Trim = function() {
- return this.TrimRight().TrimLeft();
- }
- //------------------------------------------------------------------------------
- // String.TrimDS(): String
- //
- // Returns the string with leading and trailing spaces removed and with any
- // run of spaces replaced with just one space. "DS" refers to doubled spaces,
- String.prototype.TrimDS = function() {
- return this.replace(/ {2,}/g, ' ').Trim();
- }
- //------------------------------------------------------------------------------
- // String.HasWord(Word): Boolean
- //
- // Returns true iff the string contains an occurrence of Word delimited
- // at each end by either a space or the start or end of the string.
- //
- // Trailing or leading spaces in Word are ignored.
- //
- // For convenience, Word may be undefined, unassigned, an empty string or
- // a string containing nothing but spaces. In those cases this method will
- // return false.
- String.prototype.HasWord = function(Word) {
- var Result = false;
- var ValWord = Defined(Word) ? Word.Trim() : '';
- if (ValWord) {
- var Padded = ' ' + this + ' ';
- var IsFound = Padded.search(ValWord) >= 0;
- return IsFound;
- }
- return Result;
- }
- //------------------------------------------------------------------------------
- // String.AddWord(Word): String
- //
- // Returns the original string with Word appended to it, separated by a space,
- // stripping trailing and leading spaces from (copies of) both the original
- // string and Word.
- //
- // For convenience, word may be unassigned, an empty string or a string
- // containing only spaces. In those cases this method will return the
- // (trimmed) original string.
- //
- // The original string may be empty or full of spaces, in which case the
- // result is Word (or an empty string is Word is empty or undefined).
- //
- // It's permissible for Word to consist of multiple space-delimited words. This
- // function is really a space-delimited word string concatenation function. The
- // name "AddWord" reflects the anticipated use.
- String.prototype.AddWord = function(Word) {
- var Result;
- var ValStr = this.Trim();
- var ValWord = Defined(Word) ? Word.Trim() : '';
- if (!ValStr) {
- Result = ValWord;
- } else if (ValWord) {
- Result = ValStr + ' ' + ValWord;
- } else {
- Result = ValStr;
- }
- Result = Result.TrimDS();
- return Result;
- }
- //------------------------------------------------------------------------------
- // String.IncludeWord(Word): String
- //
- // Returns the existing string with Word appended to it, but only if Word
- // does not already appear in the space-delimited string of words. Else the
- // original string is returned (with leading or trailing spaces removed).
- //
- // Words are considered distinct even if they only differ by letter case.
- //
- // As with AddWord(), the existing string may be empty and Word may be empty
- // or undefined.
- String.prototype.IncludeWord = function(Word) {
- if (this.HasWord(Word)) {
- return this.TrimDS();
- } else {
- return this.AddWord(Word)
- }
- }
- //------------------------------------------------------------------------------
- // String.ExcludeWord(Word): String
- //
- // Removes any occurrence of Word in the space-delimited string of words.
- // Words are considered distinct even if they only differ by letter case.
- //
- // As with IncludeWord(), the existing string may be empty and Word may be
- // empty or undefined.
- String.prototype.ExcludeWord = function(Word) {
- var ValWord;
- var re;
- var Result;
- ValWord = Defined(Word) ? Word.Trim() : '';
- if (ValWord) {
- re = RegExp('(?:^| )' + ValWord + '(?= |$)', 'g');
- Result = this.replace(re, '');
- } else {
- Result = this;
- }
- Result = Result.TrimDS();
- return Result;
- }
- //------------------------------------------------------------------------------
- // HTML/CSS helper functions
- //------------------------------------------------------------------------------
- // GetFirstElementByTagName(Root, TagName): Element
- //
- // Returns the first HTML element with the given tag name if such an
- // element exists, otherwise null. The matching is case-insensitive.
- //
- // The search is performed recursively from Root. Usually, "document"
- // is a good place to start.
- //
- // Examples of tag names include "BODY", "H2", "P", and "DIV".
- function GetFirstElementByTagName(Root, TagName) {
- var Elements;
- var Result = null;
- Elements = Root.getElementsByTagName(TagName);
- if (Assigned(Elements)) {
- if (Elements.length > 0) {
- Result = Elements[0];
- }
- }
- return Result;
- }
- //------------------------------------------------------------------------------
- // GetFirstElementByTagNameAndClass(Root, TagName, ClassName): Element
- //
- // Returns the first HTML element with the given tag name and with ClassName
- // included in the "class" attribute, if such an element exists, otherwise null.
- // The matching of the tag name is case-insensitive but the matching of the
- // class name is sensitive to letter case.
- //
- // The search is performed recursively from Root. Usually, "document"
- // is a good place to start.
- function GetFirstElementByTagNameAndClass(Root, TagName, ClassName) {
- var Result = null;
- var Elements;
- var Element;
- var i;
- Elements = Root.getElementsByTagName(TagName);
- if (Assigned(Elements)) {
- for (i = 0; i < Elements.length; ++i) {
- Element = Elements[i];
- if (HasClass(Element, ClassName)) {
- Result = Element;
- break;
- }
- }
- }
- return Result;
- }
- //------------------------------------------------------------------------------
- // AddCSS(CSSText): Element
- //
- // Adds to the current HTML/XHTML document a block of CSS code.
- //
- // A reference to the new styles element is returned so that the caller may
- // set its attributes to make it easy to find later.
- function AddCSS(CSSText) {
- var StylesElement; // The newly created CSS stylesheet element
- var Head;
- Assert(Assigned(CSSText), 'CSSText is not assigned.');
- StylesElement = document.createElement('style');
- Assert(Assigned(StylesElement), 'Failed to create StylesElement.');
- StylesElement.type = 'text/css';
- Head = GetFirstElementByTagName(document, 'HEAD');
- Assert(
- Assigned(Head),
- 'There is no document HEAD to which a CSS style sheet may be added.'
- );
- if (StylesElement.styleSheet) {
- StylesElement.styleSheet.cssText = CSSText;
- } else {
- StylesElement.appendChild(document.createTextNode(CSSText));
- }
- return Head.appendChild(StylesElement);
- }
- //------------------------------------------------------------------------------
- // HasClass(Element, ClassName): Boolean
- //
- // Returns true iff the "class" attribute of Elements is defined and
- // contains ClassName. (Elements can be styled with multiple classes,
- // each class delimited from another by a space.)
- //
- // If ClassName is empty or unassigned, false is returned.
- function HasClass(Element, ClassName) {
- var Result = false;
- var ClassAttr;
- Assert(Assigned(Element), 'HasClass(): Element is unassigned.');
- if (Assigned(ClassName) && (ClassName != '')) {
- ClassAttr = '' + Element.getAttribute('class');
- if (ClassAttr) {
- Result = ClassAttr.HasWord(ClassName);
- }
- }
- return Result;
- }
- //------------------------------------------------------------------------------
- // IncludeClass(Element, ClassName)
- //
- // Each elements on an HTML/XHTML page may be styled with multiple classes by
- // setting the "class" attribute to a space-delimited list of CSS class names.
- //
- // This function adds the "class" attribute to the element if it does not exist
- // already and adds the given class name if it is not already included in the
- // attribute.
- function IncludeClass(Element, ClassName) {
- var ClassAttr;
- Assert(Assigned(Element), 'IncludeClass(): Element is unassigned.');
- Assert(Assigned(ClassName), 'IncludeClass(): ClassName is unassigned.');
- Assert(ClassName != '', 'IncludeClass(): ClassName is empty.');
- Assert(
- ClassName.search(/' '/) < 0,
- 'IncludeClass(): ClassName must not contain any spaces.'
- );
- if (!HasClass(Element, ClassName)) {
- ClassAttr = Element.getAttribute('class');
- if (!Assigned(ClassAttr)) {
- ClassAttr = '';
- }
- Element.setAttribute('class', ClassAttr.AddWord(ClassName));
- }
- }
- //------------------------------------------------------------------------------
- // ExcludeClass(Element, ClassName)
- //
- // Removes any reference to ClassName from the "class" attribute of the element,
- // if it exists. If the class attribute is found to be empty, it is removed.
- function ExcludeClass(Element, ClassName) {
- var ClassAttr;
- Assert(Assigned(Element), 'ExcludeClass(): Element is unassigned.');
- Assert(Assigned(ClassName), 'ExcludeClass(): ClassName is unassigned.');
- Assert(ClassName != '', 'ExcludeClass(): ClassName is empty.');
- Assert(
- ClassName.search(/' '/) < 0,
- 'ExcludeClass(): ClassName must not contain any spaces.'
- );
- if (HasClass(Element, ClassName)) {
- ClassAttr = Element.getAttribute('class');
- if (Assigned(ClassAttr)) {
- ClassAttr = ClassAttr.ExcludeWord(ClassName);
- }
- ClassAttr = ClassAttr.ExcludeWord(ClassName);
- if (ClassAttr) {
- Element.setAttribute('class', ClassAttr);
- } else {
- Element.removeAttribute('class');
- }
- }
- }
- //------------------------------------------------------------------------------
- // SetClassBoolean(Element, ClassName, DoInclude)
- //
- // Calls IncludeClass() or ExcludeClass() depending on the value of DoInclude,
- // thus the presence or absence of a class reference cane be conveniently
- // matched to a Boolean.
- function SetClassBoolean(Element, ClassName, DoInclude) {
- if (DoInclude) {
- IncludeClass(Element, ClassName);
- } else {
- ExcludeClass(Element, ClassName);
- }
- }
- //------------------------------------------------------------------------------
- // Harmonator implementation
- //------------------------------------------------------------------------------
- // AddCustomStyles(): Element
- //
- // Colours anything Doctor Who-oriented a fabulous pink.
- function AddCustomStyles() {
- var CSS = '\
- /* Fabulous colour accents */\n\
- \n\
- .donotwant {\n\
- border: 0px solid #fdf !important;\n\
- color: #c7a !important;\n\
- }\n\
- .donotwant a:link {\n\
- background: transparent !important;\n\
- color: #f7c !important;\n\
- }\n\
- .donotwant a:visited {\n\
- background: transparent !important;\n\
- color: #f7c !important;\n\
- }\n\
- \n\
- /* Force plain background */\n\
- \n\
- body {\n\
- /* background-image: none !important; */\n\
- }\n\
- ';
- return AddCSS(CSS);
- }
- //------------------------------------------------------------------------------
- // StyleUnsightlyText(Node, VisitedClassName, MarkedClassName, Keywords)
- //
- // For the given node or its children where applicable, unvisited
- // paragraphs containing unsightly keywords are marked.
- function StyleUnsightlyText(Node, VisitedClassName, MarkedClassName, Keywords) {
- //----------------------------------------------------------------------------
- // HasUnsightlyText(Element): Boolean
- //
- // Returns true iff at least one unsighly word appears within
- // the element's text.
- function HasUnsightlyText(Element) {
- var Result = false;
- var KIx;
- var Keyword;
- var RE;
- var Text;
- if (Assigned(Element)) {
- Text = Element.textContent;
- for (KIx = 0; KIx < Keywords.length; ++KIx) {
- Keyword = Keywords[KIx];
- RE = RegExp('\\b' + Keyword + '\\b', 'i');
- if (Text.search(RE) >= 0) {
- Result = true;
- break;
- }
- }
- }
- return Result;
- }
- //----------------------------------------------------------------------------
- var Items;
- var Ix;
- var Item;
- //console.log('--BEGIN--');
- if (Node.nodeType == 1 && Node.tagName == 'P' &&
- !HasClass(Node, VisitedClassName)) {
- //console.log('Direct P');
- IncludeClass(Node, VisitedClassName);
- if (HasUnsightlyText(Node)) {
- IncludeClass(Node, MarkedClassName);
- }
- } else {
- Items = Node.getElementsByTagName('P');
- if (Items) {
- //console.log(Items.length, 'items');
- for (Ix = 0; Ix < Items.length; ++Ix) {
- Item = Items[Ix];
- if (!HasClass(Item, VisitedClassName)) {
- //console.log('P');
- IncludeClass(Item, VisitedClassName);
- if (HasUnsightlyText(Item)) {
- //console.log(' Marked!');
- IncludeClass(Item, MarkedClassName);
- }
- }
- }
- }
- }
- }
- //------------------------------------------------------------------------------
- // Harmonate(Node, Keywords)
- //
- // Marks all messages in Node containing any word in Keywords.
- function Harmonate(Node, Keywords) {
- StyleUnsightlyText(Node, 'beenthere', 'donotwant', Keywords);
- }
- //------------------------------------------------------------------------------
- // Main()
- //
- // Adds custom styles and styles posts containing unsightly words.
- function Main() {
- const Keywords = [
- 'pudding', 'baloney', 'sausage', 'cheese',
- 'wensleydale', 'harry potter', 'vector',
- 'fox', 'moon', 'landing', 'hoax'
- ]
- var Stream = null;
- AddCustomStyles();
- Stream = document.getElementsByTagName('body')[0];
- if (Stream) {
- Harmonate(Stream, Keywords);
- /*window.addEventListener(
- 'load',
- function() {
- var Stream = document.getElementsByTagName('body')[0];
- if (Stream) {
- //Harmonate(Stream, Keywords);
- Stream.addEventListener(
- 'DOMNodeInserted',
- function(e) {
- Harmonate(e.currentTarget, Keywords);
- },
- false
- );
- }
- },
- false
- );*/
- }
- }
- //------------------------------------------------------------------------------
- Main();
- //------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement