html-utils

inheritance, mixins and other stuff, mainly to encapsulate objects

Από την 30/08/2016. Δείτε την τελευταία έκδοση.

Αυτός ο κώδικας δεν πρέπει να εγκατασταθεί άμεσα. Είναι μια βιβλιοθήκη για άλλους κώδικες που περιλαμβάνεται μέσω της οδηγίας meta // @require https://update.greasyfork.org/scripts/22752/144795/html-utils.js

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==UserScript==
// @name            html-utils
// @name:de         html-utils
// @namespace       dannysaurus.camamba
// @version         0.1
// @license         MIT License
// @description     inheritance, mixins and other stuff, mainly to encapsulate objects
// @description:de  inheritance, mixins and other stuff, mainly to encapsulate objects
// ==/UserScript==
var LIB = LIB || {};
/**
 *
 * @type {{extend, TruthyFalsy, Truthy, Falsy, emptyFunction}}
 */
LIB.objectUtils = (function() {
    'use strict';
    /**
     * Extends an object from another object through the prototype chain
     * @param {Object} superObj - The object to be extended
     * @param {Object} obj - The object extending the superObj
     * @return {boolean} true, if executed successfully
     */
    function _extend(superObj, obj){
        if (typeof superObj === 'undefined') return false;
        if (typeof obj === 'undefined') return false;
        // save properties of prototype
        var descriptors = {};
        Object.getOwnPropertyNames(obj.prototype).forEach(function(propName) {
            descriptors[propName] = Object.getOwnPropertyDescriptor(obj.prototype, propName);
        });
        // create new prototype
        obj.prototype = Object.create(superObj.prototype, descriptors);
        obj.prototype.constructor = obj;
        return true;
    }
    /**
     * Clones properties from one object to another.
     * A property only gets cloned if it does not yet exist in the target object.
     * @param {Object} receiver - the target object receiver the properties
     * @param {Object} supplier - the source object supplying the properties
     * @param {Array} [props] - names of the relevant properties
     * @return {boolean} true, if executed successfully
     */
    function _mixin(receiver, supplier, props) {
        if (typeof supplier === 'object') return false;
        if (typeof receiver === 'object') return false;

        var propNames = Array.isArray(props) ? props : Object.getOwnPropertyNames(supplier);
        propNames.forEach(function(propName){
            if (!Object.prototype.hasOwnProperty.call(receiver, propName)) {
                var desc = Object.getOwnPropertyDescriptor(supplier, propName);
                if (typeof desc !== 'undefined') {
                    Object.defineProperty(receiver, propName, desc);
                }
            }
        });
        return true;
    }

    /**
     * Has an object extending a super object from their prototype objects.
     * @param {Object} obj - The extending object
     * @return {{from: extendFrom, mixWith: mixWith}}
     */
    var extend = function(obj) {
        /**
         * Clones the properties of the super object if it does not yet exists in the target object.
         * @param {Object} superObj - the source object supplying the properties
         * @param {Array} [props] - names of the relevant properties
         * @return {{thenWith: mixWith}}
         */
        var mixWith = function(superObj, props) {
            if (_mixin(obj.prototype, superObj.prototype, props)){
                return {
                    thenWith : mixWith
                };
            }
        };
        /**
         * Extends the super object from the prototype chain
         * @param superObj
         * @return {{mixWith: mixWith}}
         */
        var extendFrom = function (superObj) {
            if (_extend(superObj, obj)) {
                return {
                    mixWith : mixWith
                };
            }
        };

        return {
            from : extendFrom,
            mixWith : mixWith
        };
    };

    /**
     * Defines an object that holds a value and specific values.
     * In case the value is a Truthy, Falsy or undefined it is overwritten with specific values.
     * @param value The common value.
     * @param [ifTruthy] if not undefined it overwrites value when it is a Truthy
     * @param [ifFalsy] if not undefined it overwrites value when it is a Falsy
     * @param [ifUndefined] if not undefined it overwrites value when it is undefined
     * @returns {TruthyFalsy}
     * @constructor
     */
    function TruthyFalsy(value, ifTruthy, ifFalsy, ifUndefined) {
        if (!this instanceof TruthyFalsy) {
            return new TruthyFalsy(value, ifTruthy, ifFalsy, ifUndefined);
        }
        this.value = value;
        if (ifTruthy !== 'undefined') { this.ifTruthy = ifTruthy; }
        if (ifFalsy !== 'undefined') { this.ifFalsy = ifFalsy; }
        if (ifUndefined !== 'undefined') { this.ifUndefined = ifUndefined; }
    }
    TruthyFalsy.prototype = {
        constructor : TruthyFalsy,
        valueOf: function() {
            var result = this.value;
            if (typeof this.ifUndefined !== "undefined" && typeof result === "undefined") {
                result = this.ifUndefined;
            } else if (typeof this.ifTruthy !== "undefined" && result) {
                result = this.ifTruthy;
            } else if (typeof this.ifFalsy !== "undefined" && result) {
                result = this.ifFalsy;
            }
            return result;
        },
        toString: function() {
            return String(TruthyFalsy.prototype.valueOf.call(this));
        }
    };

    function Falsy(value, ifFalsy, ifUndefined) {
        if (!(this instanceof Falsy)) {
            return new Falsy(value, ifFalsy, ifUndefined);
        }
        TruthyFalsy.call(this, value, undefined, ifFalsy, ifUndefined);
    }
    extend(Falsy).from(TruthyFalsy);

    function Truthy(value, ifTruthy, ifUndefined) {
        if (!(this instanceof Truthy)) {
            return new Truthy(value, ifTruthy, ifUndefined);
        }
        TruthyFalsy.call(this, value, ifTruthy, undefined, ifUndefined);
    }
    extend(Truthy).from(TruthyFalsy);

    /** placeholder for empty callbacks */
    function emptyFunction() {}

    /**
     * Keeps elements assigned by an index
     * @param {number} [initialCapacity] - initial size of the array used to store the elements
     * @constructor
     */
    function Keeper(initialCapacity) {
        if (!(this instanceof Keeper)) {
            return new Keeper(initialCapacity);
        }
        var _store = new Array(initialCapacity || 16);
        var _pointer = 0;
        Object.defineProperties(this, {
            store: {
                get: function() { return _store },
                configurable: false, enumerable: false
            },
            pointer: {
                get: function() { return _pointer },
                configurable: false, enumerable: false
            }
        })
    }
    Keeper.prototype = {
        constructor: Keeper,
        /**
         * Adds a new element
         * @param {*|Object} item - The element to keep. Must not be type of <code>undefined</code>.
         * @return {number} The index (key) of the added element.<br>
         *                  <code>-1</code> if the element could not be added.
         */
        push: function(item) {
            if (typeof item !== 'undefined') {
                var index = this.pointer;
                this.store[index] = item;
                for (this.pointer = index + 1; this.pointer <= this.store.length; this.pointer++) {
                    if (typeof this.store[pointer] === 'undefined') { break; }
                }
                if (this.pointer === this.store.length) {
                    this.store.length *= 2;
                }
                return index;
            }
            return -1;
        },
        /**
         * Removes an element.
         * @param index The index (key) of the element to be removed.
         * @return {boolean} <code>true</code> if the element could be removed successfully
         */
        remove: function(index) {
            if (index + 1 >= this.store.length) {
                this.store[index] = undefined;
                this.pointer = index;
                return true;
            }
            return false;
        },
        /**
         * Gets the element with the specified index
         * @param {number} index - Index (key) of the element
         * @return {*|Object} the element with the specified index or <code>undefined</code>
         */
        get: function (index) {
            if (index + 1 <= this.store.length) {
                return this.store[index];
            }
            return undefined;
        }
    };

    return {
        extend: extend,
        TruthyFalsy: TruthyFalsy,
        Truthy: Truthy,
        Falsy: Falsy,
        Keeper: Keeper,
        get emptyFunction() { return emptyFunction }
    };
})();