$.fn.scroll = function (opt) {
    
    var def = {
        target: null
    }

    $.extend(def, opt);


    // generar botones en def
    var botones = {
        up: 'arriba',
        down: 'abajo',
        left: 'izquierda',
        right: 'derecha'
    }

    for(a in botones) {
        if(!opt[a] || opt[a] === false)
            continue;

        def[a] = { };

        def[a].top = opt[a].top ? opt[a].top : null;
        def[a].left = opt[a].left ? opt[a].left : null;
        def[a].src = opt[a].src ? opt[a].src : 'scripts/boton_' + botones[a] + '.gif';
    }


    $(this).each(function () {
        var parent = $(this)
        var content = null;

        if(def.target)
            content = $(this).find(def.target);
        else {
            var content = $('<div></div>')

            parent.html(content.append(parent.html()))

            // mueve estilos
            var s = [
                'padding-top',
                'padding-bottom',
                'padding-left',
                'padding-right',
                'width'
            ];

            for(a in s)
                content.css(s[a], parent.css(s[a]));

            parent.css('padding', '0px');
        }


        var offset = $(this).offset();
        var dim = {
            width: $(this).width(),
            height: $(this).height()
        }

        // posiciones por omision
        var botones_posiciones = {
            up: 'Height - 10',
            down: 'Height + 10',
            left: 'Width - 10',
            right: 'Width + 10'
        }

        for(a in botones) {
            if(!def[a])
                continue;

            var aux = botones_posiciones[a].match(/^(\w+) (\-|\+) (\d+)$/);

            var otro = aux[1] == 'Height' ? 'Width' : 'Height';

            var o_1, o_2;
            if(aux[1] == 'Height') {
                o_1 = 'top';
                o_2 = 'left';
            }
            else {
                o_1 = 'left';
                o_2 = 'top';
            }

            if(def[a][o_1] == null)
                def[a][o_1] = aux[2] == '-' ? -1 * aux[3] - 7 : eval('parent.outer' + aux[1] + '()') + 7 ;

            if(def[a][o_2] == null)
                def[a][o_2] = Math.round(eval('parent.outer' + otro + '()') / 2) - 7;
        }

        content
            .css('position', 'absolute')
            .css('top', 0)
            .css('left', 0)

        if(parent.css('position') == 'static')
            parent
                .css('position', 'relative')
                .css('top', 0)
                .css('left', 0)


        var simi = {
            v : {
                up: 1,
                down: 1
            },
            h: {
                left: 1,
                right: 1
            }
        }

        var b = $('body');

        for(a in botones) {
            if(!def[a])
                continue;

            var orientation = a == 'right' || a == 'down' ? -1 : 1;
            var side = simi.v[a] ? 'top' : 'left';

            b.append(
                $('<img \
                    id="jqs_' + a + '" \
                    src="' + def[a].src + '" \
                    style=" \
                        display: none; \
                        cursor: pointer; \
                        position: absolute; \
                        left: ' + (offset.left + def[a].left) + 'px; \
                        top: ' + (offset.top + def[a].top) + 'px; \
                ">')
                    .load((function (orientation) { return function () {
                        if($(this).data('marca'))
                            return;

                        $(this).data('marca', true)

                        // inicialmente solo se muestra el boton de avance (solo si es requerido dibujar el scroll)
                        var r = side == 'top' ? 'Height' : 'Width'
                        if(orientation < 0 && content['outer' + r]() > parent['inner' + r]())
                            $(this).fadeIn('slow');

                    }})(orientation))
                    .each(function () {
                        if(this.complete && !$(this).data('marca')) {
                            $(this).load();
                        }
                    })
                    .mousedown((function (s_css, o) { return function () {
                        var __d = (function (boton) { return function () {
                            var n = parseInt(content.css(s_css), 10);
    
                            n += 5 * o;
    
                            var s = s_css == 'left' ? 'Width' : 'Height';
                            var limit = (content['outer' + s]() - parent['inner' + s]()) * -1;
    
                            if(limit > 0)
                                limit = parent['inner' + s]() * -1;
    
                            var continuar = true;
                            if(n >= 0) {
                                n = 0;
                                continuar = false;
                            }
                            else if(n < limit) {
                                n = limit;
                                continuar = false;
                            }
                            else
                                $(s_css == 'top' ? '#jqs_up, #jqs_down' : '#jqs_left, #jqs_right').css('display', 'block');

                            content.css(s_css, n + 'px');

                            if(continuar && $(boton).data('st') != 'para')
                                $(boton).data('st', setTimeout(__d, 50))
                                
                            if(!continuar)
                                $(boton).css('display', 'none');

                        }})(this)
                        
                        var st = $(this).data('st');

                        if(st && st != 'para')
                            clearTimeout(st);

                        $(this).data('st', setTimeout(__d, 50))

                        return false;
                    }})(side, orientation))
                    .mouseup((function (a, o) { return function () {
                        var st = $(this).data('st');

                        if(st)
                            clearTimeout(st);

                        $(this).data('st', 'para')

                        return false;
                    }})(side, orientation))
            )
        }

    })


    return this;
}
