html-utils

utils for DOM manipulation and fetching info of a webpage

Version vom 06.09.2016. Aktuellste Version

Dieses Skript sollte nicht direkt installiert werden. Es handelt sich hier um eine Bibliothek für andere Skripte, welche über folgenden Befehl in den Metadaten eines Skriptes eingebunden wird // @require https://update.greasyforks.org/scripts/20131/146279/html-utils.js

// ==UserScript==
// @name            html-utils
// @name:de         html-utils
// @namespace       dannysaurus.camamba
// @version         0.1
// @license         MIT License
// @description     utils for DOM manipulation and fetching info of a webpage
// @description:de  utils for DOM manipulation and fetching info of a webpage
// ==/UserScript==

var LIB = LIB || {};
/**
 * Html Elements
 * @type {{Element, Button, Div, Input, Checkbox, Label, TextArea, Option, Select}}
 */
LIB.htmlUtils = (function() {
    'use strict';
    var objectUtils = LIB.objectUtils;
    var keeper = objectUtils.Keeper();
    /**
     * Adds a HTML child node to a HTML parent node.
     * @param {HtmlElement|Element} parent - The html parent node
     * @param {HtmlElement|Element} child - The html child Element to be connected to the parent node
     * @param {boolean} [asFirstChild] - <code>true</code> to have the child be added as the first child before any other child
     */
    var connectParentChild = function(parent, child, asFirstChild) {
        var elParent = parent instanceof Element ? parent.domElement : parent;
        var elChild = child instanceof Element ? child.domElement : child;
        if (asFirstChild && elParent.hasChildNodes()) {
            elParent.insertBefore(elChild, elParent.firstChild);
        } else {
            elParent.appendChild(elChild);
        }
    };
    /**
     * Removes a HTML child element from a HTML parent node.
     * @param {HTMLElement} parent - The parent node
     * @param {HTMLElement} elChild - The child node to be removed of the parent element
     */
    var disconnectParentChild = function(parent, elChild) {
        var elParent = parent instanceof Element ? parent.domElement : parent;
        elParent.removeChild(elChild);
    };
    /**
     * Removes all HTML children from a parent node.
     * @param {HTMLElement} parent - The HTML parent node
     */
    var removeAllChildren = function(parent) {
        var elParent = parent instanceof Element ? parent.domElement : parent;
        while (elParent.hasChildNodes()) {
            elParent.removeChild(elParent.firstChild);
        }
    };

    /**
     * Sorts options of a html 'select' element from a certain property of the option (e.g. text or value).
     * @param {HTMLElement|Element} select - The Select Element to be sorted
     * @param {string} [property=text] - The Name of the property from wich the option should be compared like <code>value</code> or <code>text</code>.
     * @param {boolean} [isOrderDescending] - <code>true</code> to reverse the sort order.
     */
    var sortSelectBy = function(select, property, isOrderDescending) {
        var elSelect = select instanceof Element ? select.domElement : select;
        var propertyName = property || 'text';
        var sortOptions = [];
        // options to array
        for (var i = 0; i <= select.length - 1; i++) {
            var option = select[i];
            sortOptions.push({
                value:option.value,
                text:option.text,
                selected:option.selected
            });
        }
        // sort array
        sortOptions.sort(function (a, b) {
            if (a[propertyName] < b[propertyName]) { return  isOrderDescending ? 1 : -1; }
            if (a[propertyName] > b[propertyName]) { return isOrderDescending ? -1 : 1; }
            return 0;
        });
        // array to options
        sortOptions.forEach(function (opt, i) {
            select[i].text = opt.text;
            select[i].value = opt.value;
            select[i].selected = opt.selected;
        });
    };

    /**
     * Wrapper for any type of HTML element.
     * @param {string} tagName - The type of element to be created and value of the <code>nodeName</code> attribute
     * @param {string} [id] - The value for the <code>id</code> attribute
     * @param {string} [className] - The value for the <code>class</code> attribute
     * @constructor
     */
    function Element(tagName, id, className) {
        if (!(this instanceof Element)) {
            return new Element(tagName, id, className);
        }
        var domElement = document.createElement(tagName);
        Object.defineProperty(this, "domElement", {
            get: function() { return domElement },
            configurable: true, enumerable: true
        });
        if (typeof id !== 'undefined') {
            this.domElement.id = id;
        }
        if (typeof className !== 'undefined') {
            this.domElement.className = className;
        }
    }
    Element.prototype = {
        constructor: Element,
        /**
         * Adds this HTML element to a parent node HTML element.
         * It will be added as the last child of the node.
         * @param {HTMLElement|Element} elParent - The parent HTML node element
         */
        addAsLastChild : function(elParent) {
            var parent = elParent instanceof Element ? elParent.domElement : elParent;
            connectParentChild(elParent, this.domElement, false);
        },
        /**
         * Adds this HTML element to a parent node HTML element.
         * It will be added as the first child of the node.
         * @param {HTMLElement|Element} elParent - The parent HTML node element
         */
        addAsFirstChild : function(elParent) {
            var parent = elParent instanceof Element ? elParent.domElement : elParent;
            connectParentChild(elParent, this, true);
        },
        /**
         * Adds this HTML element to a parent node HTML element.
         * All children elements will be removed and replaced with this node.
         * @param {HTMLElement|Element} elParent - The parent HTML node element
         */
        addAsOnlyChild : function(elParent) {
            var parent = elParent instanceof Element ? elParent.domElement : elParent;
            removeAllChildren(elParent);
            connectParentChild(elParent, this);
        },
        /**
         * Appends Html node elements to this node as their last children.
         * @param {...HTMLElement|Element} elements - Html elements to be added as children.
         */
        appendChildren : function(elements) {
            for (var i = 0; i <= arguments.length - 1; i++) {
                var child = arguments[i];
                this.domElement.appendChild(child instanceof Element ? child.domElement : child);
            }
        },
        /**
         * Adds Html node Elements to this node as their new children.
         * All current children elements will be removed and replaced with the new children.
         * @param {...HTMLElement} [elements] Html elements to be added as children
         *         No argument will only remove all children.
         */
        setChildren : function(elements) {
            removeAllChildren(this);
            for (var i = 0; i <= arguments.length - 1; i++) {
                connectParentChild(this, arguments[i]);
            }
        }
    };

    /**
     * Wrapper for a 'button' html element.
     * @param {string} [className] - the value for the <code>class</code> attribute
     * @param {function} [callback] - the callback function for the <code>onclick<code> event
     * @param {string} [text] - the content text of the element (text shown on the button)
     * @param {string} [id] - the value for the <code>id</code> attribute
     * @constructor
     */
    function Button(className, callback, text, id) {
        if (!(this instanceof Button)) {
            return new Button(className, callback, text, id);
        }
        Element.call(this, 'BUTTON', id, className);
        if (typeof callback === 'function') {
            this.domElement.addEventListener('click', callback);
        }
        if (typeof text !== 'undefined') {
            this.domElement.appendChild(document.createTextNode(text));
        }
    }
    objectUtils.extend(Button).from(Element);

    /**
     * Wrapper for a 'div' html element.
     * @param {string} [id] - The value for the <code>id</code> attribute
     * @param {string} [className] - The value for the <code>class</code> attribute
     * @constructor
     */
    function Div(id, className) {
        if (!(this instanceof Div)) {
            return new Div(id, className);
        }
        Element.call(this, 'DIV', id, className);
    }
    objectUtils.extend(Div).from(Element);

    /**
     * Wrapper for an 'input' HTML element as a field for text.
     * @param {number|string} [maxLength] - The maximum number of characters
     * @param {string} [text] - The value of the <code>text</code> attribute (content initially shown in the field)
     * @param {string} [className] - The value for the <code>class</code> attribute
     * @param {string} [id] - The value for the <code>id</code> attribute
     * @constructor
     */
    function Input(maxLength, text, className, id) {
        if (!(this instanceof Input)) {
            return new Input(maxLength, text, className, id);
        }
        Element.call(this, 'INPUT', id, className);
        if (typeof maxLength !== 'undefined') {
            this.domElement.maxlength = maxLength;
        }
        if (typeof text !== 'undefined') {
            this.domElement.value = text;
        }
    }
    objectUtils.extend(Input).from(Element);

    /**
     * Creates an 'input' HTML element of type 'checkbox'.
     * @param {function} [callback] - The callback function for the <code>onChange<code> event
     * @param {string} [className] - The value for the <code>class</code> attribute
     * @param {string} [id] - The value for the <code>id</code> attribute
     * @constructor
     */
    function Checkbox (callback, className, id) {
        if (!(this instanceof Checkbox)) {
            return new Checkbox(callback, className, id);
        }
        Element.call(this, 'INPUT', id, className);
        this.domElement.type = 'checkbox';
        if (typeof callback === 'function') {
            this.domElement.addEventListener('change', callback);
        }
    }
    objectUtils.extend(Checkbox).from(Element);

    /**
     * Wrapper for a 'label' html element.
     * @param {string} htmlFor - The value of the <code>for</code> attribute. The id value of another element to bind the label to that element.
     * @param {string} [text] - The content text of the element (text shown on the label)
     * @param {string} [className] - The value for the <code>class</code> attribute
     * @param {string} [id] - The value for the <code>id</code> attribute
     * @constructor
     */
    function Label(htmlFor, text, className, id) {
        if (!(this instanceof Label)) {
            return new Label(htmlFor, text, className, id);
        }
        Element.call(this, 'LABEL', id, className);
        if (typeof text !== 'undefined') {
            this.domElement.appendChild(document.createTextNode(text));
        }
        if (typeof htmlFor !== 'undefined') {
            this.domElement.htmlFor = htmlFor;
        }
    }
    objectUtils.extend(Label).from(Element);

    /**
     * Wrapper for a 'TextArea' html element.
     * @param {number|string} [cols] - The number of columns
     * @param {number|string} [maxLength] The maximum number of characters
     * @param {string} [text] - The value of the <code>text</code> attribute (content initially shown in the field)
     * @param {string} [className] - The value for the <code>class</code> attribute
     * @param {string} [id] - The value of the <code>id</code> attribute
     * @constructor
     */
    function TextArea(cols, maxLength, text, className, id) {
        if (!(this instanceof TextArea)) {
            return new TextArea(cols, maxLength, text, className, id);
        }
        Element.call(this, 'TEXTAREA', id, className);
        if (typeof cols !== 'undefined') {
            this.domElement.cols = cols;
        }
        if (typeof maxLength !== 'undefined') {
            this.domElement.maxlength = maxLength;
        }
        if (typeof text !== 'undefined') {
            this.domElement.value = text;
        }
    }
    objectUtils.extend(TextArea).from(Element);

    /**
     * Wrapper for an 'option' html element which can be added to a 'select' html element.
     * @param text The value of the <code>text</code> attribute shown in the select dropdown
     * @param value THe value of the <code>value</code> attribute
     * @constructor
     */
    function Option(text, value) {
        if (!(this instanceof Option)) {
            return new Option(text, value);
        }
        Element.call(this, 'OPTION');
        this.domElement.text = text;
        this.domElement.value = value;
    }
    objectUtils.extend(Option).from(Element);

    /**
     * Wrapper for a 'Select' html element.
     * @param {string} [id] - The value of the <code>id</code> attribute
     * @param {function} [callback] - callback function triggered by the events <code>OnChange</code>, <code>OnKeyUp</code> and <code>OnFocus</code>
     * @param {string} [className] - The value for the <code>class</code> attribute
     * @constructor
     */
    function Select(className, callback, id) {
        if (!(this instanceof Select)) {
            return new Select(className, id);
        }
        Element.call(this, 'SELECT', id, className);

        var idx = keeper.push({ onChangeCallback : callback });
        Object.defineProperty(this, 'idx', { get: function() { return idx } });
        Select.prototype.setOnChangeKeyUpFocus(callback);
    }
    Select.prototype = {
        constructor: Select,
        addNewOption: function(text, value) {
            var newOption = Option(text, value);
            this.domElement.add(newOption.domElement);
            return newOption;
        },
        sortOptionsByText: function(isOrderDesc) {
            sortSelectBy(this.domElement, 'text', isOrderDesc);
        },
        sortOptionsByValue: function(isOrderDesc) {
            sortSelectBy(this.domElement, 'value', isOrderDesc);
        },
        /**
         * Sets a callback function triggered from the events <code>OnChange</code>, <code>OnKeyUp</code> and <code>OnFocus</code>.
         * Removes any former callback function registered to these events.
         * @param {function} callback
         */
        setOnChangeKeyUpFocus: function(callback) {
            var newCallback = (typeof callback === 'function') ? callback : objectUtils.emptyFunction;

            var formerCallback = keeper.get(this.idx).onChangeCallback;
            this.domElement.removeEventListener("focus", formerCallback);
            this.domElement.removeEventListener("change", formerCallback);
            this.domElement.removeEventListener("keyup", formerCallback);

            keeper.get(this.idx).onChangeCallback = newCallback;
            this.domElement.addEventListener("focus", newCallback);
            this.domElement.addEventListener("change", newCallback);
            this.domElement.addEventListener("keyup", newCallback);
        }
    };
    objectUtils.extend(Select).from(Element);

    /**
     * Parses a param object into a query string and vice verca.
     * @param {Object|string} query - the queryObject object or query string
     * @return {string|Object}
     */
    var parseParams = function(query){
        var result;
        if (typeof query === 'string') {
            result = {};
            var decode = function(s) {
                return decodeURIComponent(s.replace(/\+/g, " "));
            };
            var match, search = /([^&=]+)=?([^&]*)/g;
            while ((match = search.exec(query)) !== null) {
                result[decode(match[1])] = decode(match[2]);
            }
            return result;
        } else {
            result = "";
            Object.keys(query).forEach(function(key, index) {
                if (index >= 1) {
                    result += "&";
                }
                result += key + "=" + query[key];
            });
            return result;
        }
    };

    /**
     * Deals with parameters of a query.
     * @param {string|Object} query - the query search as a string or as parameter object in {key:value} form
     * @constructor
     */
    function Params(query) {
        if (!(this instanceof Params)) {
            return new Params(query);
        }
        var _params = {};
        Object.defineProperties(this, {
            /** The {key:value} parameter object */
            queryObject: {
                get: function() { return _params; },
                enumerable: true, configurable: true
            },
            /** The queryString without leading '?' */
            queryString: {
                get: function () {
                    if (!_params || Object.keys(_params).length === 0) {
                        return "";
                    } else {
                        return parseParams(_params);
                    }
                },
                set: function(val) {
                    if (val) {
                        if (val.charAt(0) === '?') {
                            val = val.substring(1);
                        }
                        _params = parseParams(val);
                    } else {
                        _params = {};
                    }
                },
                enumerable: true, configurable: true
            }
        });
        if (typeof query === 'string') {
            this.queryString = query;
        } else {
            _params = query;
        }
        Object.defineProperty(this, "value", {
            get: function () { return this.queryString; }
        });
    }
    objectUtils.extend(Params).from(objectUtils.Truthy);

    var getPageAsync = function(url, onSuccess, onError) {
        if (typeof onSuccess !== 'function') { onSuccess = objectUtils.emptyFunction;}
        if (typeof onError !== 'function') { onError = objectUtils.emptyFunction;}

        return GM_xmlhttpRequest({
            method: 'GET',
            url: url,
            onload: function(resp) {
                if (resp.status == 200  ||  resp.status == 304) {
                    resp.html = new DOMParser().parseFromString(resp.responseText, 'text/html');
                    onSuccess(resp);
                } else {
                    onError(resp);
                }
            },
            onerror: onError
        });
    };

    return {
        Element: Element,
        Button: Button,
        Div : Div,
        Input : Input,
        Checkbox : Checkbox,
        Label : Label,
        TextArea : TextArea,
        Option : Option,
        Select : Select,
        Params : Params,
        requestPageAsync : getPageAsync
    };
})();
长期地址
遇到问题?请前往 GitHub 提 Issues。