My Function library

enter something useful

Verzia zo dňa 24.09.2016. Pozri najnovšiu verziu.

Tento skript by nemal byť nainštalovaný priamo. Je to knižnica pre ďalšie skripty, ktorú by mali používať cez meta príkaz // @require https://update.greatest.deepsurf.us/scripts/9160/149090/My%20Function%20library.js

"use strict";
//// ==UserScript==
// @name            My Function library
// @namespace       http://use.i.E.your.homepage/
// @version         0.45
// @description     enter something useful
// @grant           GM_getValue
// @grant           GM_setValue
// @grant           GM_deleteValue
// @grant           GM_listValues
// @grant           GM_xmlhttpRequest
// @run-at          document-start

// @created         2015-04-06
// @released        2014-00-00
// @updated         2014-00-00
// @history         @version 0.25 - first version: public@released - 2015-04-12
// @history         @version 0.30 - Second version: public@released - 2015-12-10
// @history         @version 0.35 - Second version: public@released - 2016-03-04
// @history         @version 0.45 - Second version: public@released - 2016-09-24
// @compatible      Greasemonkey, Tampermonkey
// @license         GNU GPL v3 (http://www.gnu.org/copyleft/gpl.html)
// @copyright       2014+, Magnus Fohlström
// ==/UserScript==

/*global $, jQuery*/
/*jshint -W014, -W030, -W082*/
// -W014, laxbreak, Bad line breaking before '+'
// -W030, Expected assignment or function call instead saw an expression
// -W082, a function declaration inside a block statement

/*
$("li").not(function() {
    // returns true for those elements with at least one span as child element
    return $(this).children('span').length > 0
}).each(function() { /* ...  })
*/
//noinspection JSUnresolvedFunction,JSUnresolvedVariable,BadExpressionStatementJS
    performance;

function setGM(){
    console.log('setGM' );
    window.GM_getValue      = function( key, def ){
        return localStorage[key] || def;
    };
    window.GM_setValue      = function( key, value ){
        localStorage[key] = value;
    };
    window.GM_deleteValue   = function( key ){
        delete localStorage[ key ];
    };
    window.GM_listValues    = function( ){
        return Object.keys( localStorage );
    };
    window.GM_lister        = function( remove, item ){
        var keys = window.GM_listValues(), i = 0, val;
        for ( i; i <= keys.length; i++ ) {
            val = keys[i];
            val !== undefined && (
                console.log( 'GM_ListItem: ' + val + ':', window.GM_getValue( val ) ),
                ( ( item !== undefined && val.inElem( item ) ) || item === undefined )
                && Boolean.parse( remove ) && window.GM_deleteValue( val ) );
        }
    };
}

console.log('isFunction( GM_getValue() )', $.isFunction( window.GM_getValue ) );

!!$.isFunction( window.GM_getValue ) || setGM();

(function(){

    var eventMatchers = {
        'HTMLEvents': /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,
        'MouseEvents': /^(?:click|mouse(?:down|up|over|move|enter|out))$/
    };

    var defaultOptions = {
        pointerX: 0,
        pointerY: 0,
        button: 0,
        ctrlKey: false,
        altKey: false,
        shiftKey: false,
        metaKey: false,
        bubbles: true,
        cancelable: true
    };

    jQuery.fn.simulate = function(eventName) {
        var element = this[0];
        var options = $.extend(true, defaultOptions, arguments[2] || { });
        var oEvent, eventType = null;

        for (var name in eventMatchers) {
            if (eventMatchers[name].test(eventName)) { eventType = name; break; }
        }

        if (!eventType)
            throw new SyntaxError('Only HTMLEvents and MouseEvents interfaces are supported');

        if (document.createEvent) {
            oEvent = document.createEvent(eventType);
            if (eventType == 'HTMLEvents') {
                oEvent.initEvent(eventName, options.bubbles, options.cancelable);
            }
            else {
                oEvent.initMouseEvent(eventName, options.bubbles, options.cancelable, document.defaultView,
                    options.button, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
                    options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, element);
            }
            element.dispatchEvent(oEvent);
        }
        else {
            options.clientX = options.pointerX;
            options.clientY = options.pointerY;
            oEvent = $.extend(document.createEventObject(), options);
            element.fireEvent('on' + eventName, oEvent);
        }
        return element;
    };
})();

    window.onerror = function (errorMsg, url, lineNumber, column, errorObj) {
        console.debug('Error: ' + errorMsg + '\nScript: ' + url + '\nLine: ' + lineNumber
        + '\nColumn: ' + column + '\nStackTrace: ' +  errorObj);
    };
    /**
    *  @namespace waitUntilExists_Intervals
    */
    $.fn.waitUntilExists = function (handler, shouldRunHandlerOnce, isChild){
        var found	= 'found',
            $this	= $(this.selector),
            $elements	= $this.not(function () { return $(this).data(found); }).each(handler).data(found, true);
        if( !isChild ) {
            (window.waitUntilExists_Intervals = window.waitUntilExists_Intervals || {})[this.selector] =
                window.setInterval(function () {
                    $this.waitUntilExists(
                        handler, shouldRunHandlerOnce, true);
                }, 500);
        }
        else if (shouldRunHandlerOnce && $elements.length){
            window.clearInterval(window.waitUntilExists_Intervals[this.selector]);
        }
        return $this;
    };

    $.extend( $.easing,{
        easeOutBounceSmall : function(x, t, b, c, d) {
            var ts=(t/=d)*t;
            var tc=ts*t;
            return b+c*(-16.195*tc*ts + 49.935*ts*ts + -53.785*tc + 21.795*ts + -0.75*t);
        },
        easeOutSmoothBounce : function(x, t, b, c, d) {
            var ts=(t/=d)*t;
            var tc=ts*t;
            return b+c*(-19.4293*tc*ts + 53.3838*ts*ts + -49.8485*tc + 15.8081*ts + 1.08586*t);
        }
    });

    $.extend( $.fn, {
        // Name of our method & one argument (the parent selector)
        /**
         * Suppress all rules containing "unused" in this
         * class
         *
         * @SuppressWarnings("unused")
         */
        //noinspection JSUnusedProperty
        within: function( pSelector ) {
            // Returns a subset of items using jQuery.filter
            return this.filter(function(){
                // Return truthy/falsey based on presence in parent
                return $(this).closest( pSelector ).length;
            });
            /* Example
                $("li").within(".x").css("background", "red");

                This selects all list items on the document, and then filters to only
                those that have .x as an ancestor. Because this uses jQuery internally,
                you could pass in a more complicated selector:

                $("li").within(".x, .y").css("background", "red");

                http://stackoverflow.com/questions/2389540/jquery-hasparent
                http://stackoverflow.com/a/2389549
             */
        }
    });

    $.fn.extend({
        exists              : function () {
            return !!this.length;
        },
        Exists              : function ( callback ) {
            var self = this;
            var wrapper = (function(){
                function notExists(){}
                //noinspection JSPotentiallyInvalidConstructorUsage
                notExists.prototype.ExistsNot = function( fallback ){
                    !self.length && fallback.call(); };
                //noinspection JSPotentiallyInvalidConstructorUsage
                return new notExists;
            })();
            self.length && callback.call();
            return wrapper;

            /*  And now i can write code like this -
                $("#elem").Exists(function(){
                    alert ("it exists");
                }).ExistsNot(function(){
                    alert ("it doesn't exist");
                });
             */
        },
        ifExists            : function ( fn ) {
            this.length && fn( this );
            /*
                 $("#element").ifExists( function( $this ){
                    $this.addClass('someClass').animate({marginTop:20},function(){alert('ok')});
                 });
             */
        },
        swapClass           : function ( replace, newClass) {
            this.className.replace(replace, newClass);
        },
        toggleClasses       : function ( add, remove, if_none) {
            var $this = $(this.selector);
            if_none !== undefined && !$this.hasClass(add) && !$this.hasClass(remove) && $this.addClass(if_none);
            $this.addClass(add).removeClass(remove);
        },
        thisCompStyle       : function ( cssStyle ) {
            return cssStyle !== undefined ? this.getComputedStyle().getPropertyValue( cssStyle ) : this.getComputedStyle();
        },
        refreshElement      : function ( speed, parentBoolean ) {
            var $elem = parentBoolean ? this.parent() : this, data = $elem.html();
            $elem.hide( speed / 2 ).empty().html( data ).fadeIn( speed );
        },
        hasId               : function ( id ) {
            return id === this.attr('id');
        },
        hasClasses          : function ( classes, any ) {
            classes = classes.split( classes.inElem(',') ? ',' : ' ' );
            var check = 0, i = 0;
            for ( i; i < classes.length; i++ ) {
                this.hasClass( classes[ i ] ) && check++;
                if ( any !== undefined && check !== 0 ) return true;
            }
            return check === classes.length;
        },
        hasNoChildren       : function ( selection ) {
            return $( this ).filter( function(){
                return $( this ).children( selection ).length === 0;
            });
        },
        /*        hasParent       : function( parentSelection ){
         return parentSelection.inElem('#')
            ? this.parent().hasId( parentSelection.split('#').shift() )
            : this.parent().hasClass( parentSelection.split('.').shift() );
         },
         */
        hasAncestor         : function ( Ancestor ) {
            return this.filter(function() {
                return !!$( this ).closest( Ancestor ).length;
            });
            //$('.element').hasAncestor('.container').myAction();
        },
        hasParent           : function ( selection ) {
            return !!$( this ).parent( selection ).length;
        },
        hasParents          : function ( selection ) {
            return !!$( this ).parents( selection ).length;
        },
        hasQuery            : function ( query ) {
            return d.querySelector(query).length;
        },
        hasAttr             : function ( name, val ) {
            var thisAttr = $( this ).attr( name );
            thisAttr =
                val !== undefined
                    ? thisAttr === val
                    : thisAttr;
            return ( typeof thisAttr !== "undefined" && thisAttr !== false && thisAttr !== null );

            //return val !== undefined
            //    ? attrName === val
            //    : typeof( attrName ) !== 'undefined';  //$( this )[0].hasAttribute( name );
        },
        isTag               : function ( tag ) {
            var e = this[0] || $('<undefined/>');
            //noinspection JSValidateTypes
            return e.nodeName !== undefined && e.nodeName.toLowerCase() === tag.toLowerCase();
        },
        isNode              : function ( node ) {
            var e = this[0] || $('<undefined/>');
            //noinspection JSValidateTypes
            return e.nodeName !== undefined && e.nodeName.toLowerCase() === node.toLowerCase();
        },
        searchAttr          : function ( search, type, chkLen ) { //bool name value length or 1 2 3 4
            var Attributes = this[0].attributes;
            c.i('Attributes', Attributes);
            if ( arguments.length === 0 ) {
                var obj = {};
                $.each( Attributes, function() {
                    this.specified && ( obj[ this.name ] = this.value );
                });
                return obj;
            } else if( search !== undefined ) {
                var name = '', val = '';
                //noinspection FunctionWithInconsistentReturnsJS
                $.each( Attributes, function() {
                    if( this.specified && type == 'length' ) {
                        if( this.name.length > chkLen ) {
                            name = this.name;
                            return false;
                        }
                    }
                    else if( this.specified && this.name.inElem( search ) ) {
                        name = this.name;
                        val = this.value;
                        return false;
                    }
                });
                return ( type == 'bool' || type == 1 ) ? name.length ? true : false :
                       ( type == 'name' || type == 2 ) ? name :
                       ( type == 'value' || type == 3 ) ? val :
                       ( type == 'length' || type == 4 ) && name;
            }
        },
        findClass           : function ( Class ) {
            return this.find('.' + Class);
        },
        href                : function ( newURL ) {
            return arguments.length === 0 ? this.attr('href') : this.attr('href', newURL);
        },
        src                 : function ( newSRC ) {
            return arguments.length === 0 ? this.attr('src') : this.attr('src', newSRC);
        },
        equals              : function ( compareTo ) {
            if (!compareTo || this.length != compareTo.length)
                return false;

            for (var i = 0; i < this.length; ++i) {
                if (this[i] !== compareTo[i])
                    return false;
            }
            return true;
        },
        justText            : function ( newText, prepend ) {
            var $children = null,
                placement = prepend === undefined ? 'prepend':'append';
            if ( newText ) {
                $children = $( this )
                    .children()
                    .clone();
                $( this )
                    .children()
                    .remove()
                    .end()
                    .text( newText )
                    [ placement ]( $children );
                return $(this);
            }
            else {
                return $.trim( $( this )
                    .clone()
                    .children()
                    .remove()
                    .end()
                    .text());
            }
        },
        uncomment           : function ( recurse ) {
           // <!-- hidden --> // this will reveal, whats inside. In this case it will bi the word hidden
            $( this ).contents().each(function() {
                if ( recurse && this.hasChildNodes() ) {
                    $( this ).uncomment(recurse);
                } else if ( this.nodeType == 8 ) {
                    // Need to "evaluate" the HTML content,
                    // otherwise simple text won't replace
                    var e = $('<span>' + this.nodeValue + '</span>');
                    $( this ).replaceWith( e.contents() );
                }
            });
            // $('#uncomment').uncomment( true );
            // http://stackoverflow.com/a/22439787
        },
        getComment          : function ( getValue ) {
            var COMMENT_NODE = this.contents().filter(function(){
                return this.nodeType == Node.COMMENT_NODE;
            });
            return getValue ?
                   COMMENT_NODE.each(function(){
                       return $( this ).nodeValue.str2html();
                   })
                   : COMMENT_NODE;
        },
        //$.get('defaultComp/foot.html', function(dataContent) {$('#foot').replaceWith(dataContent); });
        getURL          : function ( url, how ) {
            how = how || 'html';
            var that = this;
            $.get( url, function(dataContent) {
                $(that)[ how ](dataContent);
            });
            return this;
        },

        hasEvent            : function ( event ) {
            var eventHandlerType;
            $( this ).on( event, clickEventHandler ).triggerHandler( event );
            function clickEventHandler( e ) {
                eventHandlerType = e.type;
            }
            return eventHandlerType === event;
        },
        scrollTune          : function ( opt  ){
            // $("body").scrollTune({ pps: 1700, pageY: config.pageY, easing:'easeOutSmoothBounce', hsc: true }).promise()
            //          .done( function() { setTimeout(function(){ toggleClassState( config, 'fullPlayer', type ); },100); })

            console.log('scrollTune');

            var position,
                defaults 		= {
                    tune:		0,
                    speed:		0,
                    pps:        false, // pixel per second
                    ppsM:		1000,
                    pageYmini:	0,
                    pageY:      false, //{ pps: 300, pageY: event.pageY }
                    hsc:		false, // height speed compensation
                    animate:	false,
                    // require	http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js or jQueryUI - if other than ' swing or linear '
                    easing:     "easeInOutCubic", // easeInOutCubic  easeInOutQuad  easeInOutElastic http://easings.net/
                    delay:		0,
                    varStore:	'',
                    varAltStore:false,
                    name:		false,
                    start:   	false,
                    startTime: 	0,
                    step:   	false,
                    stepTime: 	0,
                    complete:   false,
                    completeTime: 0,
                    done:   	false,
                    doneTime: 	0,
                    goTo:		$('body')
                },
                heightSpeedComp	= function(){ return opt.hsc ? 1 + ( ( $(document).height() / opt.pageY ) / 1.4 ) : 1 ; },
                varStore = function( action, step ){
                    opt.name !== false
                        ? opt.varAltStore !== false
                            ? (console.log('Store'), opt.varAltStore[opt.name][ action ](step))
                            : (console.log('Store false'), opt.name[ action ](step))
                        : opt.pageYmini < opt.pageY || opt.varStore === config
                            ? (console.log('config'), opt.varStore[ action ](step))
                            : (console.log('config false'), opt.varStore(step));
                };

            console.log('opt.pageY',opt.pageY);
            opt = $.extend( {}, defaults, opt );
            position = ( $( this ).offset().top + opt.tune ) + 'px';

            opt.pps !== false || opt.animate !== false || ( typeof opt.speed === 'string' ? opt.speed.length !== 0 : opt.speed !== 0 )
                ? (
                opt.speed = opt.pps !== false ? parseInt( ( opt.pageY / opt.pps * heightSpeedComp() ) * opt.ppsM ) : opt.speed,
                    opt.goTo.delay( opt.delay ).animate(
                        { scrollTop	: position },
                        { duration	: opt.speed, easing: opt.easing,
                            start		: function(){
                                opt.start && setTimeout(function(){
                                    console.log('start');
                                    varStore('start');
                                }, opt.startTime );
                            },
                            step		: function(i){
                                opt.step && setTimeout(function(){
                                    console.log('step',i);
                                    varStore('step',i);
                                }, opt.stepTime );
                            },
                            complete	: function(){
                                opt.complete && setTimeout(function(){
                                    console.log('complete');
                                    varStore('complete');
                                }, opt.completeTime );
                            },
                            done		: function(){
                                opt.done && setTimeout(function(){
                                    console.log('done');
                                    varStore('done');
                                }, opt.doneTime );
                            }
                        }
                    )
                )
                : opt.goTo.scrollTop( position );

            return this; // for chaining...

        },
        scrollTuneOld       : function ( opt ){

            var position,
                defaults = {
                    tune:		0,
                    speed:		512,
                    animate:	false,
                    goTo:		$('html, body')
                };

            opt = $.extend( {}, defaults, opt );
            position = ( $( this ).offset().top + opt.tune ) + 'px';

            opt.animate !== false || ( typeof opt.speed === 'string' ? opt.speed.length !== 0 : opt.speed !== 0 )
                ? opt.goTo.animate({ scrollTop: position }, opt.speed )
                : opt.goTo.scrollTop( position );

            return this; // for chaining...
        },
        qUnWrap             : function (){
            $( this ).find(':first-child').unwrap();
        }
    });

    $.extend({
        confirm: function (title, message, yesText, noText, yesCallback) {
            //dialog needs jQueryUI
            /*
             $.confirm(
             "CONFIRM", //title
             "Delete " + filename + "?", //message
             "Delete", //button text
             deleteOk //"yes" callback
             );
             */
            $("<div></div>").dialog( {
                buttons: [{
                    text: yesText,
                    click: function() {
                        yesCallback();
                        $( this ).remove();
                    }
                },
                    {
                        text: noText,
                        click: function() {
                            $( this ).remove();
                        }
                    }
                ],
                close: function (event, ui) { $(this).remove(); },
                resizable: false,
                title: title,
                modal: true
            }).text(message).parent().addClass("alert");
        }
    });
    $.extend( $.expr[":"], {
        ldata: function(el, idx, selector) {
            var attr = selector[3].split(", ");
            return el.dataset[attr[0]] === attr[1];
        },
        value: function(el, idx, selector) {
            return el.value === selector[selector.length - 1];
        },
        isEmptyTrimmed: function(el){
            return !$.trim($(el).html());
        },
        data: $.expr.createPseudo
            ? $.expr.createPseudo(function( dataName ) {
                  return function( elem ) {
                      return !!$.data( elem, dataName );
                  };
              })
              // support: jQuery <1.8
            : function( elem, i, match ) {
                  return !!$.data( elem, match[ 3 ] );
              }
        });

    $.isInArray = function( item, array ) {
        return !!~$.inArray(item, array);
    };
    $.allVar = function( array, value, all, atLeast ) {
        var count = 0,
            arrLength = array.length,
            isBool = typeof value === 'boolean';

        $.each( array, function( i, e ){
            value === ( isBool ? !!e : e ) && count++;
        });

        return all ? count === arrLength : count >= atLeast;
    };
/*
   Object.defineProperty(HTMLMediaElement.prototype, 'playing', {
        //$( selector ).get(0).playing;
        get: function(){
            return !!( this.currentTime > 0 && !this.paused && !this.ended && this.readyState > 2 );
        }
    });
    */
 /*   Object.prototype.hasAttribute   = function( attrName, val ){
        var thisAttr =
                this.attr
                    ? val !== undefined
                        ? this.attr( attrName ) === val
                        : this.attr( attrName )
                    : this.getAttribute( attrName );
        return ( typeof thisAttr !== "undefined" && thisAttr !== false && thisAttr !== null );
    };
*/
    Array.prototype.findArrayObj    = function( findKey, exactValue ){
        return $.grep( this, function( obj ){
            return obj[ findKey ] === exactValue;
        })[0];
        //This prototype doesn't modify the array,
        // it gets the element that contains key with correct value and
        // the returns that element
    };
    Array.prototype.removeArrayObj  = function( findKey, exactValue ){
        //my own example test:  http://jsfiddle.net/aPH7m/82/
        //This prototype doesn't modify the array, needs to be overwritten or put into new var array
        return $.grep( this, function( obj ) {
            return obj[ findKey ] !== exactValue;
        });
    };
    Array.prototype.addKeyToArrayObj = function( findKey, exactValue, newKey, newValue ){
        return $.grep( this, function( obj ){
            return obj[ findKey ] === exactValue ? obj[ newKey ] = newValue : obj[ findKey ] !== exactValue;
        });
        // This prototype doesn't modify the array,
        // it gets the element that contains key with correct value and
        // adds a new key with its value to that element
    };

    Array.prototype.filterArrayObj  = function( doWhat, findKey, exactValue, newKey, newValue ){
        return  doWhat === 'remove'
            ? this.filter(function( obj ) {
                    return obj[ findKey ] !== exactValue;
              })
            : doWhat === 'addKey'
                    ? this.filter(function( obj ){
                            return obj[ findKey ] === exactValue
                                ?  obj[ newKey ]  = newValue
                                :  obj[ findKey ] !== exactValue;
                      })
                    : doWhat === 'find'
                        && this.filter(function( obj ){
                            return obj[ findKey ] === exactValue;
                          })[0];
    };
    Array.prototype.grepArrayObj    = function( doWhat, idKey, uniqueValue, theKey, theValue ){
        doWhat = doWhat === 'updateKey' ? 'addKey' : doWhat;
        return doWhat === 'remove'
            ?     $.grep( this, function( obj ){
                return obj[ idKey ] !== uniqueValue;
            })
            :  doWhat === 'addKey'
                ? $.grep( this, function( obj ){
                    return obj[ idKey ] === uniqueValue
                        ? (
                               obj[ theKey ] = theValue,
                               obj[ idKey ] === uniqueValue
                           )
                        : obj[ idKey ] !== uniqueValue;
                  })
            :  doWhat === 'find'
                ? $.grep( this, function( obj ){
                    return obj[ idKey ] === uniqueValue;
                    })[0]
            :  doWhat === 'deleteKey'
                && $.grep( this, function( obj ){
                    return obj[ idKey ] === uniqueValue
                        ? (
                              delete obj[ theKey ],
                              obj[ idKey ] === uniqueValue
                          )
                            : obj[ idKey ] !== uniqueValue;
                });
    };
    Array.prototype.sortObjArray    = function( key, reverse ){
        this.sort(function(a, b){
            return ( reverse || false ) ? b[key] - a[key] : a[key] - b[key];
        });
    };

    //noinspection JSPrimitiveTypeWrapperUsage
    Boolean.parse                   = function(val) {
    //    http://stackoverflow.com/a/24744599
        var falsely = /^(?:f(?:alse)?|no?|0+)$/i;
        return !falsely.test(val) && !!val;
    };


/*
	Object.prototype.isObjectType   = function( type, showType ){ //"[object Number]"
		var objectString = Object.prototype.toString.call( this );
		return  showType === 'show' ? objectString :
				showType === 'exact' ? objectString === type :
				showType === 'search' && objectString.toLowerCase().inElem( type.toLowerCase() );
	};
*/

    String.prototype.splitEvery     = function( splitter, every ){
        var array = this.split( splitter ), returnString = '';
        $.each( array, function( index, elem ){
            returnString += elem + ( index < array.length - 1 || index % every === 0 ) ? '' : splitter;
        });
        return returnString;
    };
    String.prototype.advSplit       = function( chr, nbr ){
            var str = this.split(chr),
                strLen = str.length,
                chrLen = chr.length,
                returnStr = ['',''],
                newArr = [];

            $.each( str, function( index ){
                returnStr[ index < nbr ? 0 : 1 ] += str[ index ] + chr;
            });

            $.each( returnStr, function( index ){
                returnStr[ index ] = returnStr[ index ].slice(0, - chrLen);
                returnStr[ index ].length > 0 && newArr.push( returnStr[ index]  );
            });

            return newArr;
        };
    String.prototype.advSplitJoin   = function( chr, nbr, ips ){

        var str = this.split(chr),
            strLen = str.length,
            ipsLen = ips.length,
            returnStr = '',
            returnStrLen;

        $.each( str, function( index ) {
            var add = index < strLen - 1
                ? chr
                : '';
            returnStr += index + 1 === nbr
                ? str[index] + ips
                : str[index] + add;
        });

        returnStrLen = returnStr.length;
        returnStr.slice( returnStrLen - ipsLen ) === ips
            && ( returnStr = returnStr.slice( 0, returnStrLen - ipsLen ) );

        return returnStr;
    };
    String.prototype.extract        = function( start, end, inside, newWay ){
        var str = this,
            myArray = [ true, 1, 'yes', 'inside' ],
            startCharIndex = str.indexOf( start ),
            endCharIndex = str.indexOf( end );

        newWay = newWay !== undefined ? $.inArray( newWay, myArray ) !== -1 : false;
        inside = inside !== undefined ? $.inArray( inside, myArray ) !== -1 : false;

        function simpler() {
            return inside
                ? str.split( start ).pop().split( end ).shift()
                : start + str.split( start ).pop().split( end ).shift() + end;
        }
        function older() {
            return inside //old buggy way, some old scripts may depends on it
                ? str.replace( start, '').replace( end, '')
                : str.substr( startCharIndex, endCharIndex );
        }
        return newWay ? simpler() : older()
    };
    String.prototype.extractNew     = function( start, end, inside ){
        var str = this;
        return inside !== undefined && inside
            ? str.split( start ).pop().split( end ).shift()
            : inside
               || start + str.split( start ).pop().split( end ).shift() + end;
    };

    String.prototype.charTrim       = function( char ){
        // alert("...their.here.".charTrim('.'));
        var first_pos = 0,
            last_pos = this.length- 1, i ;
        //find first non needle char position
        for( i = 0; i < this.length; i++ ){
            if( this.charAt( i ) !== char ){
                first_pos = ( i == 0 ? 0 : i );
                break;
            }
        }
        //find last non needle char position
        for( i = this.length - 1; i > 0; i-- ){
            if( this.charAt( i ) !== char ){
                last_pos = ( i == this.length ? this.length: i + 1 );
                break;
            }
        }
        return this.substring( first_pos, last_pos );
    };
    String.prototype.reduceWhiteSpace = function(){
        return this.replace(/\s+/g, ' ');
    };
    String.prototype.formatString   = function(){

        var inputStr = this.toString().reduceWhiteSpace()
                .split('!').join(' !').split('!;').join("!important;")
                .split(/\s+/g).join(' ')
                .split('{').join('{\n\t')
                .split('; ').join(';')



                .split('( ').join('(')
                .split(' )').join(')')

                .split(' :').join(':')

                .split(';').join(';\n\t')
                .split('*/').join('*/\n')
                .split(')*(').join(') * (')
                .split('}').join('}\n'),
            returnStr = '\t', pop;

        $.each( inputStr.split('\n'), function ( i, elem ) {

            elem.search( '{' ) === -1 && elem.search( ': ' ) === -1
	            && ( elem.search( ':' ) > 1
	                ? ( pop = elem.split(': ').join(':').split( ':' ).pop(), elem = elem.split( pop ).shift() + ' ' + pop )
	                : elem.search(':') === 1 && ( elem = elem.split(': ').join(':').split( ':' ).join( ': ' ) ) );
            //    : elem.search( '{' ) === 1 && ( elem.search( ': ' ) !== -1 || elem.search( ' :' ) !== -1 || elem.search( ' : ' ) !== -1 )
            //        && ( elem = elem.split( ': ' ).join( ' :' ).split( ' :' ).join( ':' ).split( ' : ' ).join( ': ' ) );

            returnStr += elem + '\n\t';
        });
	    returnStr = returnStr.split('>').join(' > ').split('  >  ').join(' > ').split( ': //' ).join( '://' ).split( ':url' ).join( ': url' );
        return returnStr.slice( 0, returnStr.lastIndexOf('}') ) + '}';
};

	/**
	 * Parses mixed type values into booleans. This is the same function as filter_var in PHP using boolean validation
	 * //@returny {Boolean|Null}
	 */
	String.prototype.parseBooleanStyle = function( nullOnFailure ){
		nullOnFailure = nullOnFailure || false;
		var bool, $this = this.toString().toLowerCase();
		switch( $this ){
			case 'true':
			case '1':
			case parseInt( $this ) > 0:
			case 'on':
			case 'yes':
				bool = true;
				break;
			case 'false':
			case '0':
			case 'off':
			case 'no':
				bool = false;
				break;
			default:
				bool = nullOnFailure ? null : false;
				break;
		}
		return bool;
	};
	String.prototype.parseBool      = function(){
		var thisStr = parseInt( this ) ? this === 0 ? 'false' : 'true' : '' + this,
			trueArray = [ 'on', 'yes','y', 'j', 'true', true ],
			falseArray = [ 'off', 'no', 'n', 'false', false ];

		thisStr = thisStr.toLowerCase().trim();

		return  $.inArray( thisStr, trueArray ) !== -1 ? true :
			$.inArray( thisStr, falseArray ) !== -1 ? false : this;
	};
    String.prototype.isType         = function( type ){
        return !!$.type( this ) === type;
    };
    String.prototype.undef          = function( replace ){
        return this === undefined ? replace : this;
    };
    String.prototype.isUndefined    = function( state, replace ){
        state = state !== undefined ? state : true;
        replace = replace !== undefined ? replace : true;
        return state ? this === undefined ? replace : this : state;
    };

    String.prototype.inURL          = function(){
        var winLoc = window.location.href;
        return winLoc.search(this) !== -1;
    };
    String.prototype.inString       = function( string ){
        return string !== undefined ? string.search(this) !== -1 : false;
    };
    String.prototype.inElem         = function( search ){
        return this !== undefined ? this.search(search) !== -1 : false;
    };
    String.prototype.count          = function( char, UpperCase ){
        var numberOf = this.toString().match( new RegExp( char, ( UpperCase ? "gi" : "g" ) ) );
        return numberOf != null ? numberOf.length : 0;
    };
    String.prototype.startsWith     = function( str ){
        return this.slice(0, str.length) == str;
    };
    String.prototype.removeStarts   = function( many ){
        return this.substring( many - 1, this.length );
    };
    String.prototype.removeEnds     = function( many ){
        return this.substring( 0, this.length - many );
    };
    String.prototype.endsWith       = function( str ){
        return this.slice( -str.length ) == str;
    };
    String.prototype.capitalizeFirst = function(){
        return this.charAt(0).toUpperCase() + this.slice(1);
    };
    String.prototype.lpad           = function( padString, length ){
        var str = this;
        while ( str.length < length ) {
            str = padString + str; }
        return str;
    };

    // use full to convert String URL, so that you can use location commands
    String.prototype.toLocation     = function(){
        var a = document.createElement('a');
        a.href = this;
        return a;
    };
    String.prototype.str2html       = function(){
        return $('<div/>').html( this ).contents();
    };
    String.prototype.toStyle        = function( styleId ){
        var cssID,
            cssSplit = this.split('¤'),
            cssStyled = cssSplit.pop().formatString();
        styleId = styleId !== undefined ? styleId : cssSplit.shift();
        cssID = $( 'head #' + styleId );
        cssID.length
            ? cssID.html( cssStyled )
            : $( $( '<style/>',{ id: styleId, class:'mySuperStyles', html: cssStyled } ) ).appendTo('head');
    };

    //HTMLObjectElement.prototype.obj2Str = function(){var objArr = $.makeArray( this ); return objArr[0].outerHTML;};
    /*
    String.prototype.replaceAll = function( target, replacement ) {
        return this.split(target).join(replacement);
    };
*/
    function ScrollZoomTune( selection, zooms, tune, ani, speed ){
        //ScrollZoomTune("div.thumb .title a",1,-25,1,'slow');
        var body = $('body'), sel = $( selection), position;
        //noinspection JSValidateTypes
        sel.size() !== 0 && (
            body.css('zoom',zooms),
                position = sel.position().top + tune,
                ani === 1
                    ? body.animate({ scrollTop: position * zooms }, speed )
                    : body.scrollTop( position * zooms )
        );
    }
    function refreshElement( elem , speed ){ //refreshElement('.videoPlayer','slow');
        var $elem = $( elem ), data = $elem.html();
        $elem.empty().html( data ).fadeIn( speed );
    }
    function autoCopyToClipboard( input ){
        var $copyThis = $( '#copyThis' );
        $( 'body' ).append( $('<textarea/>',{ id:'copyThis', rows:"4", cols:"50", type:"text", value: input }) );
        $copyThis.focus().select();
        document.execCommand("copy");
        $copyThis.remove();
    }
    function toStyle( styleId, str ){
        var $id = $( 'head #' + styleId ),
            cssID = str.formatString();
        $id.length
            ? $id.html( cssID )
            : $( $( '<style/>',{ id: styleId, class:'mySuperStyles', html: cssID } ) ).appendTo('head');
    }
    function obj2Str( obj ){
        var objArr = $.makeArray(obj);
        return objArr[0].outerHTML;
    }

    function sortBy(key, reverse) {
        // Usage: array.sort( sortBy( key, reverse ) )

        // Move smaller items towards the front
        // or back of the array depending on if
        // we want to sort the array in reverse
        // order or not.
        var moveSmaller = reverse ? 1 : -1;
            // Move larger items towards the front
            // or back of the array depending on if
            // we want to sort the array in reverse
            // order or not.
        var moveLarger = reverse ? -1 : 1;
        /**
         * @param  {*} a
         * @param  {*} b
         * @return {Number}
         */
        return function (a, b) {
            if (a[key] < b[key]) {
                return moveSmaller;
            }
            if (a[key] > b[key]) {
                return moveLarger;
            }
            return 0;
        };
    }

    function VideoTitleA( elem , state ){
        //VideoTitleA("div.thumb .title a",'on');
        $( elem ).each(function(){
            var $this    = $(this),
                strTitle = $this.attr('title'),
                strText  = $this.attr('data-text'),
                strHtml  = $this.text();
            state === 'on' ? $this.text(strTitle).attr('data-text',strHtml) : $this.text(strText);
        });
    }
    /**
     * @return {string}
     */
    function MultiString( f ){
        return f.toString().split('\n').slice(1, -1).join('\n');
    }
    function wrapWithTag( tag, text, selection ){
        var thisAttr = selection !== undefined && selection.startsWith('.') ? 'class' : selection.startsWith('#') && 'id',
            thisTag = $('<' + tag + '/>', { text: text });
        return thisAttr.length ? thisTag.attr( thisAttr, selection.splice( 1 ) ) : thisTag;
    }

    function clean( node ) {
        /*
         So to clean those unwanted nodes from inside the <body> element, you would simply do this:

         clean(document.body);
         Alternatively, to clean the entire document, you could do this:

         clean(document);
         */
        for( var n = 0; n < node.childNodes.length; n ++ ){
            var child = node.childNodes[ n ];
            ( child.nodeType === 8 || ( child.nodeType === 3 && !/\S/.test( child.nodeValue ) ) )
                ? (
                    node.removeChild( child ),
                    n --
                )
                : child.nodeType === 1 && clean( child );
        }
    }
    function commentsCleaner( array ){
        array = array === undefined ? [ '*', document, 'html' ] : array;

        // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
        // http://stackoverflow.com/a/2364760
        $.each( array, function( i, e ) {
            $( e ).contents().each( function() {
                this.nodeType === Node.COMMENT_NODE  && $( this ).remove(); }); });
    }

    function newUrlNoReload( title, url ){
        window.history.pushState("string", title, url );
    }
    function inURL( search, exact ){
        exact = exact || false;
        var winLoc = window.location.href;

        
        return exact ? winLoc === search : winLoc.search( search ) !== -1;
    }
    function loadDoc( href ){
        $( location ).attr('href', href );
    }

    function isPrimitiveType( value ){
        // will return true if the value is a primitive value
        switch ( typeof value ) {
            case 'string': case 'number': case 'boolean': case 'undefined': {
            return true;
        }
            case 'object': {
                return !value;
            }
        }
        return false;
    }
    function checkDividedIsInteger( num, div ){
        return ( num % div === 0 );
    }
    function isEven( value ){
        return ( value % 2 === 0 );
    }
    function inDom( array, onElement ) {
        var found = false,
            isArrayFN = function(){
                $.each( array, function( i, value ) {
                    value = onElement !== undefined
                        ? onElement + value
                        : value;
                    if( $( value ).length ) {
                        found = true;
                        return false;
                    }
                });
            };

        $.isArray( array )
            ? isArrayFN()
            : $( array ).length && ( found = true );

        /**
         * @return {boolean}
         */
        return found;
    }
    function isHTMLObject( obj ){
        obj = typeof obj == 'string' ? obj : $( obj );
        return obj.length
            ? !!( obj instanceof HTMLElement || obj[0] instanceof HTMLElement)
            : !!( obj && ( obj.nodeName || ( obj.prop && obj.attr && obj.find ) ) );
    }

    function isFunction( functionToCheck ){
        var getType = {};
        return functionToCheck && getType.toString.call( functionToCheck ) === '[object Function]';
    }
    function isNumeric( value ){
        return /^\d+$/.test( value );
    }

    function parseBoolean( Boolean , Type ) {
        //    http://stackoverflow.com/a/24744599
        Type = Type || false;
        var falsely = /^(?:f(?:alse)?|no?|0+)$/i,
            truely = /^(?:t(?:rue)?|yes?|1+)$/i;
        return Type ? !truely.test( Boolean ) && !!Boolean : !falsely.test( Boolean ) && !!Boolean;
    }
	function parseBooleanStyle( str, nullOnFailure ){
		nullOnFailure = nullOnFailure || false;
		var bool, $this = str.toString().toLowerCase();
		$this = parseInt( $this ) > 0 ? parseInt( $this ) : $this;
		console.log('parseBooleanStyle',$this);
		switch( $this ){
			case 'true':
			case '1':
			case parseInt( $this ) > 0:
			case 'on':
			case 'yes':
				bool = true;
				break;
			case 'false':
			case '0':
			case 'off':
			case 'no':
				bool = false;
				break;
			default:
				bool = nullOnFailure ? null : false;
				break;
		}
		return bool;
	}
    function getsComputedStyle( style, elem ) {
        elem = elem || 'body';
        return window.getComputedStyle( document[ elem ] )[ style ] !== undefined;
    }
    function isPropertySupported( property, elem ){
        elem = elem || 'body';
        return property in document[ elem ].style;
    }
    function cssPropertyValueSupported( prop, value, elem ) {
        //cssPropertyValueSupported('width', '1px');
        elem = elem || 'div';
        var d = document.createElement( elem );
        d.style[ prop ] = value;
        return d.style[ prop ] === value;
    }

    var cssSupports = (function(){
        // http://code.tutsplus.com/tutorials/quick-tip-detect-css3-support-in-browsers-with-javascript--net-16444
        var div = document.createElement('div'),
            vendors = 'Khtml Ms O Moz Webkit'.split(' '),
            len = vendors.length;

        return function(prop) {
            if ( prop in div.style ) return true;

            prop = prop.replace(/^[a-z]/, function(val) {
                return val.toUpperCase();
            });

            while(len--) {
                if ( vendors[len] + prop in div.style ) {
                    // browser supports box-shadow. Do what you need.
                    // Or use a bang (!) to test if the browser doesn't.
                    return true;
                }
            }
            return false;
        };
    })();

    function toggleClassState( config, Class, state, elem ){

        config === undefined ? window.config = {} : config;
        config = config || ( window.config = {} );
        
        config[ Class ] = typeof state === 'string' ? !config[ Class ] : state;
        $( elem || 'html' )[ config[ Class ] ? 'addClass' : 'removeClass' ]( Class );

    }
    function filterClick( e, $this ){
        return e.which == 1 && e.target == $this;
    }
    function dispatchEventResize() {
        //noinspection JSClosureCompilerSyntax,JSUnresolvedFunction
        window.dispatchEvent(new Event('resize'));
    }

    /**
     * @return {string}
     */
    function Undefined( check, replace ){
        return check === undefined ? replace.toString() : check.toString();
    }

    function getGlobal(){
        return (function(){
            return this;
        })();
    }
    function GM_lister( remove, item ){
        var keys = GM_listValues();
        for (var i = 0, key = null; key = keys[i]; i++) {
            GM_listValues()[i] !== undefined && (
                c.i('GM_ListItem: ' + GM_listValues()[i] + ':', GM_getValue(key)),
              ( ( item !== undefined && GM_listValues()[i].inElem( item ) ) || item === undefined )
                    && ( remove === true || remove === 'yes' || remove === 1 ) && GM_deleteValue(key));
        }
    }

    function roundFloat( num, dec ){
        var d = 1;
        for ( var i=0; i<dec; i++ ){
            d += "0";
        }
        return Math.round(num * d) / d;
    }
    function randomFloatBetween( min, max, dec ){
        dec = typeof( dec ) == 'undefined' ? 2 : dec;
        return parseFloat( Math.min( min + ( Math.random() * ( max - min ) ), max ).toFixed( dec ) );
    }
    function random( max ) {
        var min = 1,
            rand = function(){
                return Math.floor( Math.random() * ( max - min + 1 ) + min );
            },
            num1 = rand(),
            num2 = rand();

        return ( num1 > num2 ? num2/num1 : num1/num2 ) * max;
    }
    function roundNearPeace( number, peaces, dec ) {
        return ( Math.round( number * peaces ) / peaces ).toFixed( dec );
    }

    var w = window,
        glob = w,
        $w = $( w ),
        $l = $( location ),
        locDoc = window.location.href,
        d = document,
        $d = $( d ),

        c = {
            defaultState: 3,
            cute : function( type, msg, color ) {
                color = color || "black";
                var newColor, bgc = "White";
                switch ( color ) {
                    case "success":  newColor = "Green";      bgc = "LimeGreen";       break;
                    case "info":     newColor = "DodgerBlue"; bgc = "Turquoise";       break;
                    case "error":    newColor = "Red";        bgc = "Black";           break;
                    case "start":    newColor = "OliveDrab";  bgc = "PaleGreen";       break;
                    case "warning":  newColor = "Tomato";     bgc = "Black";           break;
                    case "end":      newColor = "Orchid";     bgc = "MediumVioletRed"; break;
                    default: //noinspection SillyAssignmentJS
                        newColor = color;
                }

                typeof msg == "object" ?
                    window.console[ type ]( msg )
                : typeof color == "object" ? (
                        window.console[ type ]("%c" + msg, "color: PowderBlue;font-weight:bold; background-color: RoyalBlue;"),
                        window.console[ type ]( newColor )
                    ) :
                    window.console[ type ]("%c" + msg, "color:" + newColor + "; background-color: " + bgc + ";");
            },
            show: function( showThis, type ){
                var State = GM_getValue( type + 'StateValue' ) || this.defaultState;
                return showThis !== 0 && State !== 0 && State === ( showThis || State ) || State === 'all';
            },
            pre: function( type, name, fn, line, color ){
                line = line == undefined ? '' : line + ': ';
                /**
                 * @return {string}
                 */
                var Fn = function(){ return fn !== undefined ? fn : ''; };
                typeof fn == "object" 
                    ? window.console[ type ]( name, Fn() ) 
                    : c.cute( type, line + name + ': ' + Fn(), color );
            },
            type: function( type, name, fn, line, color, showThis ){
                this.show( showThis, type ) && this.pre( type, name, fn, line, color );
            },
            l: function( name, fn, line, color, showThis ){
                this.type( 'log', name, fn, line, color, showThis );
            },
            h: function( name, fn, line, color, showThis ){
                this.type( 'handled', name, fn, line, color, showThis );
            },
            //c.l('name', 'fn'=='fn', 'line', 'blue')
            i: function( name, fn, line, color, showThis ){
                this.type( 'info', name, fn, line, color, showThis );
            },
            d: function( name, fn, line, color, showThis ){
                this.type( 'debug', name, fn, line, color, showThis );
            }
        },
        localStorageObj = {
            name        : 'setName', //important
            localArray  : function(){
                return window.localStorage.getItem( this.name );
            },
            getArray    : function(){
                return this.localArray() === null ? [] : JSON.parse( this.localArray() );
            },
            stringify   : function( array ){
                c.i('[stringify]', JSON.stringify(array) );
                window.localStorage.setItem( this.name, JSON.stringify(array) );
            },
            check       : function( key, value ){
                var array = this.getArray();
                return array.grepArrayObj('find', key, value );
            },
            viewConsole : function( json ){
                var array = this.getArray();
                // $.toJSON() --- https://github.com/Krinkle/jquery-json/blob/master/src/jquery.json.js
                // array.join('\n');
                c.d( this.name, array ); //debug mode important to make this work
                c.i( this.name, json ? isFunction( $.toJSON() ) ? $.toJSON( array ) : JSON.stringify( array ) : array.toSource() );
            },
            addTo       : function() {
                
            },
            add         : function( key, value, obj ){
                var array = this.getArray(),
                    inA = array;
                c.i('[check array 1]', inA );
                this.check( array, key, value )
                    || (
                        array.push( obj ),
                        c.i('[Added Object into array]', obj ),
                        c.i('[check array 2]', array )
                );
                this.stringify( array );
            },
            remove      : function( key, value, obj ){
                var array = this.getArray();
                this.check( array, key, value )
                    && (
                        array = array.grepArrayObj('remove', key, value ),
                        c.i('[Removed Object from array]', obj )
                    );
                this.stringify( array );
            }
        },
        booleanTimer = {
            timers  : [],
            start   : function( name, ms ){
                var that = this, value = name,
                    stop = setTimeout(function(){
                        that.stop( value );
                    }, ms );
                this.timers.push( { 'name': value, stop:stop } );
                //setTimeout(function(){that.stop( value );}, ms );
            },
            check   : function( value ){
                return this.timers.grepArrayObj( 'find', 'name', value ) !== undefined;
            },
            stop    : function( value ){
                this.timers = this.timers.grepArrayObj( 'remove', 'name', value );
            }
        },
        advTimer = {
            timers  : [],
            start   : function( name, ms ){
                var that = this, value = name,
                    stop = setTimeout(function(){
                        that.stop( value );
                    }, ms );
                //noinspection JSUnresolvedVariable
                this.timers.push({ 'name':value, start:window.performance.now(), timeout:ms, stop:stop });
            },
            check   : function( value ){
                var findObj = this.timers.grepArrayObj( 'find', 'name', value );
                //noinspection JSUnresolvedVariable
                return findObj !== undefined
                    ? findObj.timeout - ( window.performance.now() - findObj.start )
                    : false;
            },
            stop    : function( value ){
                this.timers = this.timers.grepArrayObj( 'remove', 'name', value );
            }
        },
        lap     = {
            data : {},
            tid  : function(){
                //noinspection JSUnresolvedVariable
                return performance.now();
            },
            set  : function(name){
                this.data[name] = this.tid();
            },
            get  : function(name){
                return this.tid() - this.data[name];
            },
            end  : function(name){
                this.print(name);
                this.del(name);
            },
            del  : function(name){
                delete this.data[name];
            },
            print: function(name){
                var get = this.get( name );
                c.i( 'Lap: ' + name,  isNaN( get ) ? 'There is no such a name ' : get + 'ms' );
            }
        },
        timer   = {
            ms  : 0,
            set : function(ms){
                var that = this;
                this.ms = ms;
                setTimeout(function(){
                    that.ms = 0;
                }, ms );
            }
        },
        counter = {
            data    : {},
            set     : function(name, start, base){
                this.data[name] = start || 0;
                this.data[name+'Default'] = base || 1;
            },
            get     : function(name){
                return this.data[name];
            },
            is      : function(name, count){
                return this.data[name] === count;
            },
            lessThen: function(name, count, equal ){
                return ( equal || false ) ? this.data[name] <= count : this.data[name] < count;
            },
            moreThen: function(name, count, equal){
                return ( equal || false ) ? this.data[name] >= count : this.data[name] > count;
            },
            del     : function(name){
                delete this.data[name];
            },
            exists  : function(name) {
                return this.data[name] !== undefined;
            },
            plus    : function(name, num){
                this.exists(name) || this.set(name);
                this.data[name] = this.data[name] + ( num === undefined ? this.data[name+'Default'] : num );
            },
            minus   : function(name, num){
                this.exists(name) || this.set(name);
                this.data[name] = this.data[name] - ( num === undefined ? this.data[name+'Default'] : num );
            },
            increase: function (name, num) {
                this.plus(name, num);
            },
            decrease: function (name, num) {
                this.minus(name, num);
            },
            '+'     : function (name, num) {
                this.plus(name, num);
            },
            '-'     : function (name, num) {
                this.minus(name, num);
            },
            up      : function (name, num) {
                this.plus(name, num);
            },
            down    : function (name, num) {
                this.minus(name, num);
            },
            add     : function (name, num) {
                this.plus(name, num);
            },
            subtract: function (name, num) {
                this.minus(name, num);
            },
            withdraw: function (name, num) {
                this.minus(name, num);
            }
        },
        g       = {
            locDoc  : window.location.href,
            ms      : 0,
            timer   : function(ms){
                g.ms = ms;
                setTimeout(function(){ g.ms = 0; }, ms );
            },

            GM      : {
                engine : function( mode, val, range ){
                    switch (mode){
                        case 'set':     GM_setValue( val.name, val.default );
                            break;
                        case 'get':     range ? config[ val.name ] = GM_getValue( val.name ):
                                                ui.config[ val.name ] = GM_getValue( val.name );
                            break;
                        case 'del':     GM_deleteValue( val.name );
                    }
                },
                manager : function( mode, array, range ){
                    $.each( array, function( i, val ){ this.engine( mode, val, range === undefined ); });
                    mode === 'del' && ( GM_deleteValue( 'firstRun' ), GM_deleteValue( 'yourVer' ) );
                }
            }
        },

        testPerformance = function( name, fn, testCycles ) {
            lap.set( name );
            var i = 0;
            for ( i ; i < testCycles; i++ ){
                fn();
            }
            lap.end( name );
        },
        perf = function (testName, fn) {
            var startTime = new Date().getTime();
            fn();
            var endTime = new Date().getTime();
            console.log(testName + ": " + (endTime - startTime) + "ms");
        };

$(document).on('click','*',function(e){
    this == e.target && c.i('target:', $(this)[0]
    ); });

c.i('my Function Library ö');
/*
isScrolledIntoView = (elem) ->
    docViewTop = $(window).scrollTop()
docViewBottom = docViewTop + $(window).height()
elemTop = $(elem).offset().top
elemBottom = elemTop + $(elem).height()

    (elemBottom - 200 < docViewBottom) and (elemBottom + $(elem).height() > docViewBottom )
*/