IE移动式菜单问题JQuery

时间:2014-03-08 23:37:35

标签: javascript jquery internet-explorer mobile

我有以下JQuery:

function Dropdown(opts) {
    this.opts = opts;
    this.trigger = $(opts.trigger);
    this.menu = $(opts.menu);

    this.hide = this.hide.bind(this);
    this.hideCallbacks = [];
    this.onHide = this.hideCallbacks.push.bind(this.hideCallbacks);
}

Dropdown.prototype.alignMenu = function () {
    if (!this.opts.position) return;

    var pos = this.trigger.position();

    var x = pos.left;
    var y = pos.top;

    var current = this.opts.position === 'activeItem' && this.menu.find('.active');
    if (!current.length) current = this.menu.children(':first');
    y -= current.position().top + (current.outerHeight(true) - this.trigger.outerHeight(true)) / 2;

    this.menu.css({ top: y, left: x });
};

Dropdown.prototype.show = function () {
    this.menu.show();
    this.alignMenu();
    this.menu.find('.active').focus();

    var doc = $(document);

    // If a dropdown trigger is only visible on :hover, hide the menu when the trigger vanishes.
    this.activeBind(doc, 'mouseout', function (e) {
        if (!$.contains(e.target, this.trigger[0])
            && e.target !== this.menu[0] && !$.contains(this.menu[0], e.target))    // Only catch mouseouts on parents of the trigger
            return;
        if (this.trigger.css('visibility') === 'hidden' || this.trigger.is(':hidden'))
            this.hide();
    }.bind(this));

        this.activeBind(this.menu.children(), 'click', this.hide);

    //Prevent the handler that opened the menu in the first place from opening it again.
    // Wait until this event finishes, in case we were shown before bubbling up to here.
    setTimeout(function () {
        this.activeBind(this.trigger, 'click', function (e) {
            e.stopImmediatePropagation();
            this.hide();
            return false;
        }.bind(this));

        // Hide on outer mouse click
        this.activeBind(doc, 'click', function (e) {
            if (e.target === this.menu[0] || $.contains(this.menu[0], e.target))
                return; // Ignore clicks inside the menu
            this.hide();
            return false;
        }.bind(this));
    }.bind(this), 1);

    // Make keyboard start from hovered item
    this.activeBind(this.menu.children(), 'mouseenter', function (e) {
        e.target.focus();
    }.bind(this));
    // Allow navigation via keyboard
    this.activeBind(doc, 'keydown', function (e) {
        if (e.keyCode === 27) this.hide();
        if (!/(38|40)/.test(e.keyCode)) return;

        var items = this.menu.children();

        if (!items.length) return;

        var index = items.index(document.activeElement || items.filter('.active'));

        if (e.keyCode === 38 && index > 0) index--;                               // up
        if (e.keyCode === 40 && index < items.length - 1) index++;                // down
        if (index < 0) index = 0;

        items.eq(index).focus();

        return false;
    }.bind(this));
};

Dropdown.prototype.hide = function () {
    this.menu.hide();
    this.hideCallbacks.forEach(Function.call.bind(Function.call));
};

Dropdown.prototype.activeBind = function (elem, eventName, handler) {
    elem.bind(eventName, handler);
    this.hideCallbacks.push(function () { elem.unbind(eventName, handler); });
};

$(document).on('click', '.UserTrigger', function () {
    var menu = $('#userMenu'), trigger = $(this);

    var header = $(this).closest('header');
    header.addClass("MenuOpen");

    var dropdown = new Dropdown({ trigger: trigger, menu: menu });
    dropdown.onHide(function () { header.removeClass("MenuOpen"); });
    setScrollDisabled(true, true);
    dropdown.onHide(function () { setScrollDisabled(false, true); });

    dropdown.show();

    // automatically stops propagation
    return false;
});

function setScrollDisabled(value, mobileOnly) {
    var className = mobileOnly ? "OverlaidBase-Mobile" : "OverlaidBase";
    if (value) {
        $('.BaseContent').css('top', -$(window).scrollTop()).addClass(className);
        $(window).scrollTop($(window).scrollTop());
    } else {
        var y = parseInt($('.BaseContent').css('top'), 10);
        $('.BaseContent').removeClass(className);
        setTimeout(function () { $(window).scrollTop(-y); }, 0);
    }
}

然而在IE中我得到以下js错误:

Webpage error details
Message: Object doesn't support this property or method
Line: 387
Char: 2
Code: 0
URI: http://new.dpwebdev.co.uk/new-brand/business-sites/dorset-dub-fest/js/dorset-core.js

第387行是这样的: this.hideCallbacks.forEach(Function.call.bind(Function.call));

问题是什么,我该如何解决?有什么想法吗?

1 个答案:

答案 0 :(得分:0)

感谢@varinder,这是解决方案:

在脚本顶部添加:

if (!Array.prototype.forEach)
{
  Array.prototype.forEach = function(fun /*, thisArg */)
  {
    "use strict";

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== "function")
      throw new TypeError();

    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
    for (var i = 0; i < len; i++)
    {
      if (i in t)
        fun.call(thisArg, t[i], i, t);
    }
  };
}

它解决了这个问题,因为任何想要知道问题的人都是因为Internet Explorer不支持“for each”循环而引起的。

此代码段来自MDN文档,来自ECMA-262。 Snippet相当于ECMA-262 foreach功能。

有关详细信息,请参阅Here