0

我需要制作一个浮动菜单,我在网上搜索并在这里找到了一个脚本http://www.jtricks.com/javascript/navigation/floating.html

/* Script by: www.jtricks.com
 * Version: 1.12 (20120823)
 * Latest version: www.jtricks.com/javascript/navigation/floating.html
 *
 * License:
 * GNU/GPL v2 or later http://www.gnu.org/licenses/gpl-2.0.html
 */
var floatingMenu =
{
    hasInner: typeof(window.innerWidth) == 'number',
    hasElement: typeof(document.documentElement) == 'object'
        && typeof(document.documentElement.clientWidth) == 'number'};

var floatingArray =
[
];

floatingMenu.add = function(obj, options)
{
    var name;
    var menu;

    if (typeof(obj) === "string")
        name = obj;
    else
        menu = obj;


    if (options == undefined)
    {
        floatingArray.push( 
            {
                id: name,
                menu: menu,

                targetLeft: 0,
                targetTop: 0,

                distance: .07,
                snap: true,
                updateParentHeight: false
            });
    }
    else
    {
        floatingArray.push( 
            {
                id: name,
                menu: menu,

                targetLeft: options.targetLeft,
                targetRight: options.targetRight,
                targetTop: options.targetTop,
                targetBottom: options.targetBottom,

                centerX: options.centerX,
                centerY: options.centerY,

                prohibitXMovement: options.prohibitXMovement,
                prohibitYMovement: options.prohibitYMovement,

                distance: options.distance != undefined ? options.distance : .07,
                snap: options.snap,
                ignoreParentDimensions: options.ignoreParentDimensions,
                updateParentHeight:
                    options.updateParentHeight == undefined
                    ? false
                    : options.updateParentHeight,

                scrollContainer: options.scrollContainer,
                scrollContainerId: options.scrollContainerId,

                confinementArea: options.confinementArea,

                confinementAreaId:
                    options.confinementArea != undefined
                    && options.confinementArea.substring(0, 1) == '#'
                    ? options.confinementArea.substring(1)
                    : undefined,

                confinementAreaClassRegexp:
                    options.confinementArea != undefined
                    && options.confinementArea.substring(0, 1) == '.'
                    ? new RegExp("(^|\\s)" + options.confinementArea.substring(1) + "(\\s|$)")
                    : undefined
            });
    }
};

floatingMenu.findSingle = function(item)
{
    if (item.id)
        item.menu = document.getElementById(item.id);

    if (item.scrollContainerId)
        item.scrollContainer = document.getElementById(item.scrollContainerId);
};

floatingMenu.move = function (item)
{
    if (!item.prohibitXMovement)
    {
        item.menu.style.left = item.nextX + 'px';
        item.menu.style.right = '';
    }

    if (!item.prohibitYMovement)
    {
        item.menu.style.top = item.nextY + 'px';
        item.menu.style.bottom = '';
    }
};

floatingMenu.scrollLeft = function(item)
{
    // If floating within scrollable container use it's scrollLeft
    if (item.scrollContainer)
        return item.scrollContainer.scrollLeft;

    var w = window.top;

    return this.hasInner
        ? w.pageXOffset  
        : this.hasElement  
          ? w.document.documentElement.scrollLeft  
          : w.document.body.scrollLeft;
};

floatingMenu.scrollTop = function(item)
{
    // If floating within scrollable container use it's scrollTop
    if (item.scrollContainer)
        return item.scrollContainer.scrollTop;

    var w = window.top;

    return this.hasInner
        ? w.pageYOffset
        : this.hasElement
          ? w.document.documentElement.scrollTop
          : w.document.body.scrollTop;
};

floatingMenu.windowWidth = function()
{
    return this.hasElement
        ? document.documentElement.clientWidth
        : document.body.clientWidth;
};

floatingMenu.windowHeight = function()
{
    if (floatingMenu.hasElement && floatingMenu.hasInner)
    {
        // Handle Opera 8 problems
        return document.documentElement.clientHeight > window.innerHeight
            ? window.innerHeight
            : document.documentElement.clientHeight
    }
    else
    {
        return floatingMenu.hasElement
            ? document.documentElement.clientHeight
            : document.body.clientHeight;
    }
};

floatingMenu.documentHeight = function()
{
    var innerHeight = this.hasInner
        ? window.innerHeight
        : 0;

    var body = document.body,
        html = document.documentElement;

    return Math.max(
        body.scrollHeight,
        body.offsetHeight, 
        html.clientHeight,
        html.scrollHeight,
        html.offsetHeight,
        innerHeight);
};

floatingMenu.documentWidth = function()
{
    var innerWidth = this.hasInner
        ? window.innerWidth
        : 0;

    var body = document.body,
        html = document.documentElement;

    return Math.max(
        body.scrollWidth,
        body.offsetWidth, 
        html.clientWidth,
        html.scrollWidth,
        html.offsetWidth,
        innerWidth);
};

floatingMenu.calculateCornerX = function(item)
{
    var offsetWidth = item.menu.offsetWidth;

    var result = this.scrollLeft(item) - item.parentLeft;

    if (item.centerX)
    {
        result += (this.windowWidth() - offsetWidth)/2;
    }
    else if (item.targetLeft == undefined)
    {
        result += this.windowWidth() - item.targetRight - offsetWidth;
    }
    else
    {
        result += item.targetLeft;
    }

    if (document.body != item.menu.parentNode
        && result + offsetWidth >= item.confinedWidthReserve)
    {
        result = item.confinedWidthReserve - offsetWidth;
    }

    if (result < 0)
        result = 0;

    return result;
};

floatingMenu.calculateCornerY = function(item)
{
    var offsetHeight = item.menu.offsetHeight;

    var result = this.scrollTop(item) - item.parentTop;

    if (item.centerY)
    {
        result += (this.windowHeight() - offsetHeight)/2;
    }
    else if (item.targetTop === undefined)
    {
        result += this.windowHeight() - item.targetBottom - offsetHeight;
    }
    else
    {
        result += item.targetTop;
    }

    if (document.body != item.menu.parentNode
        && result + offsetHeight >= item.confinedHeightReserve)
    {
        result = item.confinedHeightReserve - offsetHeight;
    }

    if (result < 0)
        result = 0;

    return result;
};

floatingMenu.isConfinementArea = function(item, area)
{
    return item.confinementAreaId != undefined
        && area.id == item.confinementAreaId
        || item.confinementAreaClassRegexp != undefined
        && area.className
        && item.confinementAreaClassRegexp.test(area.className);
};

floatingMenu.computeParent = function(item)
{
    if (item.ignoreParentDimensions)
    {
        item.confinedHeightReserve = this.documentHeight();
        item.confinedWidthReserver = this.documentWidth();
        item.parentLeft = 0;  
        item.parentTop = 0;  
        return;
    }

    var parentNode = item.menu.parentNode;
    var parentOffsets = this.offsets(parentNode, item);
    item.parentLeft = parentOffsets.left;
    item.parentTop = parentOffsets.top;

    item.confinedWidthReserve = parentNode.clientWidth;

    // We could have absolutely-positioned DIV wrapped
    // inside relatively-positioned. Then parent might not
    // have any height. Try to find parent that has
    // and try to find whats left of its height for us.
    var obj = parentNode;
    var objOffsets = this.offsets(obj, item);

    if (item.confinementArea == undefined)
    {
        while (obj.clientHeight + objOffsets.top
                   < item.menu.scrollHeight + parentOffsets.top
               || item.menu.parentNode == obj
               && item.updateParentHeight
               && obj.clientHeight + objOffsets.top
                   == item.menu.scrollHeight + parentOffsets.top)
        {
            obj = obj.parentNode;
            objOffsets = this.offsets(obj, item);
        }
    }
    else
    {
        while (obj.parentNode != undefined
               && !this.isConfinementArea(item, obj))
        {
            obj = obj.parentNode;
            objOffsets = this.offsets(obj, item);
        }
    }

    item.confinedHeightReserve = obj.clientHeight
        - (parentOffsets.top - objOffsets.top);
};

floatingMenu.offsets = function(obj, item)
{
    var result =
    {
        left: 0,
        top: 0
    };

    if (obj === item.scrollContainer)
        return;

    while (obj.offsetParent && obj.offsetParent != item.scrollContainer)
    {  
        result.left += obj.offsetLeft;  
        result.top += obj.offsetTop;  
        obj = obj.offsetParent;
    }  

    if (window == window.top)
        return result;

    // we're IFRAMEd
    var iframes = window.top.document.body.getElementsByTagName("IFRAME");
    for (var i = 0; i < iframes.length; i++)
    {
        if (iframes[i].contentWindow != window)
           continue;

        obj = iframes[i];
        while (obj.offsetParent)  
        {  
            result.left += obj.offsetLeft;  
            result.top += obj.offsetTop;  
            obj = obj.offsetParent;
        }  
    }

    return result;
};

floatingMenu.doFloatSingle = function(item)
{
    this.findSingle(item);

    if (item.updateParentHeight)
    {
        item.menu.parentNode.style.minHeight = 
            item.menu.scrollHeight + 'px';
    }

    var stepX, stepY;

    this.computeParent(item);

    var cornerX = this.calculateCornerX(item);

    var stepX = (cornerX - item.nextX) * item.distance;
    if (Math.abs(stepX) < .5 && item.snap
        || Math.abs(cornerX - item.nextX) <= 1)
    {
        stepX = cornerX - item.nextX;
    }

    var cornerY = this.calculateCornerY(item);

    var stepY = (cornerY - item.nextY) * item.distance;
    if (Math.abs(stepY) < .5 && item.snap
        || Math.abs(cornerY - item.nextY) <= 1)
    {
        stepY = cornerY - item.nextY;
    }

    if (Math.abs(stepX) > 0 ||
        Math.abs(stepY) > 0)
    {
        item.nextX += stepX;
        item.nextY += stepY;
        this.move(item);
    }
};

floatingMenu.fixTargets = function()
{
};

floatingMenu.fixTarget = function(item)
{
};

floatingMenu.doFloat = function()
{
    this.fixTargets();
    for (var i=0; i < floatingArray.length; i++)
    {
        this.fixTarget(floatingArray[i]);
        this.doFloatSingle(floatingArray[i]);
    }
    setTimeout('floatingMenu.doFloat()', 20);
};

floatingMenu.insertEvent = function(element, event, handler)
{
    // W3C
    if (element.addEventListener != undefined)
    {
        element.addEventListener(event, handler, false);
        return;
    }

    var listener = 'on' + event;

    // MS
    if (element.attachEvent != undefined)
    {
        element.attachEvent(listener, handler);
        return;
    }

    // Fallback
    var oldHandler = element[listener];
    element[listener] = function (e)
        {
            e = (e) ? e : window.event;
            var result = handler(e);
            return (oldHandler != undefined) 
                && (oldHandler(e) == true)
                && (result == true);
        };
};

floatingMenu.init = function()
{
    floatingMenu.fixTargets();

    for (var i=0; i < floatingArray.length; i++)
    {
        floatingMenu.initSingleMenu(floatingArray[i]);
    }

    setTimeout('floatingMenu.doFloat()', 100);
};

// Some browsers init scrollbars only after
// full document load.
floatingMenu.initSingleMenu = function(item)
{
    this.findSingle(item);
    this.computeParent(item);
    this.fixTarget(item);
    item.nextX = this.calculateCornerX(item);
    item.nextY = this.calculateCornerY(item);
    this.move(item);
};

floatingMenu.insertEvent(window, 'load', floatingMenu.init);


// Register ourselves as jQuery plugin if jQuery is present
if (typeof(jQuery) !== 'undefined')
{
    (function ($)
    {
        $.fn.addFloating = function(options)
        {
            return this.each(function()
            {
                floatingMenu.add(this, options);
            });
        };
    }) (jQuery);
}

该脚本要求菜单具有#floatdiv id。我创建了我的 div #floatdiv,并在头部添加了以下 javascript 行以使操作开始工作:

<script type="text/javascript">  
    floatingMenu.add('floatdiv',  
        {  
             targetLeft: 250,                

            targetTop: 290,                

            snap: true  
        });  
</script>

#floatdiv css 在这里,

#floatdiv{
    height:45px;
    width:830px;
    z-index:2;
}

该脚本工作正常。当我向下滚动时,菜单会按指定浮动。但我不希望菜单随着滚动一直浮动。只有当我输入特定的 div 而不是一直滚动时,我才需要触发菜单的浮动。有什么线索吗?

4

2 回答 2

0

这是什么样子?

html

<div id="header">HEADER</div>
<div id="content">
    <div id="left">LEFT</div>
    <div id="right">RIGHT</div>
</div>
<div id="footer">FOOTER</div>

js

$(function() {
    var $sidebar = $("#right"), 
        $window = $(window),
        rightOffset = $sidebar.offset(),
        rightDelta = $("#footer").offset().top - $("#header").offset().top - $("#header").outerHeight() - $("#right").outerHeight(),
        topPadding = 15;

    $window.scroll(function() {
            $sidebar.stop().animate({
                marginTop: Math.max(Math.min($window.scrollTop() - rightOffset.top + topPadding, rightDelta), 0)
            });
    });

});

工作演示

希望这对你有帮助

于 2013-03-31T04:52:10.020 回答
0

我编写了问题中列出的脚本。

该脚本非常通用,可以使 div 在特定区域内浮动(例如另一个容器 div)。以下是说明:

http://www.jtricks.com/javascript/navigation/floating/confined_demo.html

于 2013-06-26T21:18:39.670 回答