/*!
 * Bootstrap Context Menu
 * Author: @sydcanem
 * https://github.com/sydcanem/bootstrap-contextmenu
 *
 * Inspired by Bootstrap's dropdown plugin.
 * Bootstrap (http://getbootstrap.com).
 *
 * Licensed under MIT
 * ========================================================= */

;(function($) {

    'use strict';

    /* CONTEXTMENU CLASS DEFINITION
     * ============================ */
    var toggle = '[data-toggle="context"]';

    var ContextMenu = function (element, options) {
        this.$element = $(element);

        this.before = options.before || this.before;
        this.onItem = options.onItem || this.onItem;
        this.scopes = options.scopes || null;

        if (options.target) {
            this.$element.data('target', options.target);
        }

        this.listen();
    };

    ContextMenu.prototype = {

        constructor: ContextMenu
        ,show: function(e) {

            var $menu
                , evt
                , tp
                , items
                , relatedTarget = { relatedTarget: this, target: e.currentTarget };

            if (this.isDisabled()) return;

            this.closemenu();

            if (this.before.call(this,e,$(e.currentTarget)) === false) return;

            $menu = this.getMenu();
            $menu.trigger(evt = $.Event('show.bs.context', relatedTarget));

            tp = this.getPosition(e, $menu);
            items = 'li:not(.divider)';
            $menu.attr('style', '')
                .css(tp)
                .addClass('open')
                .on('click.context.data-api', items, $.proxy(this.onItem, this, $(e.currentTarget)))
                .trigger('shown.bs.context', relatedTarget);

            // Delegating the `closemenu` only on the currently opened menu.
            // This prevents other opened menus from closing.
            $('html')
                .on('click.context.data-api', $menu.selector, $.proxy(this.closemenu, this));

            return false;
        }

        ,closemenu: function(e) {
            var $menu
                , evt
                , items
                , relatedTarget;

            $menu = this.getMenu();

            if(!$menu.hasClass('open')) return;

            relatedTarget = { relatedTarget: this };
            $menu.trigger(evt = $.Event('hide.bs.context', relatedTarget));

            items = 'li:not(.divider)';
            $menu.removeClass('open')
                .off('click.context.data-api', items)
                .trigger('hidden.bs.context', relatedTarget);

            $('html')
                .off('click.context.data-api', $menu.selector);
            // Don't propagate click event so other currently
            // opened menus won't close.
            e.stopPropagation();
        }

        ,keydown: function(e) {
            if (e.which == 27) this.closemenu(e);
        }

        ,before: function(e) {
            return true;
        }

        ,onItem: function(e) {
            return true;
        }

        ,listen: function () {
            this.$element.on('contextmenu.context.data-api', this.scopes, $.proxy(this.show, this));
            $('html').on('click.context.data-api', $.proxy(this.closemenu, this));
            $('html').on('keydown.context.data-api', $.proxy(this.keydown, this));
        }

        ,destroy: function() {
            this.$element.off('.context.data-api').removeData('context');
            $('html').off('.context.data-api');
        }

        ,isDisabled: function() {
            return this.$element.hasClass('disabled') ||
                    this.$element.attr('disabled');
        }

        ,getMenu: function () {
            var selector = this.$element.data('target')
                , $menu;

            if (!selector) {
                selector = this.$element.attr('href');
                selector = selector && selector.replace(/.*(?=#[^\s]*$)/, ''); //strip for ie7
            }

            $menu = $(selector);

            return $menu && $menu.length ? $menu : this.$element.find(selector);
        }

        ,getPosition: function(e, $menu) {
            var mouseX = e.clientX
                , mouseY = e.clientY
                , boundsX = $(window).width()
                , boundsY = $(window).height()
                , menuWidth = $menu.find('.dropdown-menu').outerWidth()
                , menuHeight = $menu.find('.dropdown-menu').outerHeight()
                , tp = {"position":"absolute","z-index":9999}
                , Y, X, parentOffset;

            if (mouseY + menuHeight > boundsY) {
                Y = {"top": mouseY - menuHeight + $(window).scrollTop()};
            } else {
                Y = {"top": mouseY + $(window).scrollTop()};
            }

            if ((mouseX + menuWidth > boundsX) && ((mouseX - menuWidth) > 0)) {
                X = {"left": mouseX - menuWidth + $(window).scrollLeft()};
            } else {
                X = {"left": mouseX + $(window).scrollLeft()};
            }

            // If context-menu's parent is positioned using absolute or relative positioning,
            // the calculated mouse position will be incorrect.
            // Adjust the position of the menu by its offset parent position.
            parentOffset = $menu.offsetParent().offset();
            X.left = X.left - parentOffset.left;
            Y.top = Y.top - parentOffset.top;

            return $.extend(tp, Y, X);
        }

    };

    /* CONTEXT MENU PLUGIN DEFINITION
     * ========================== */

    $.fn.contextmenu = function (option,e) {
        return this.each(function () {
            var $this = $(this)
                , data = $this.data('context')
                , options = (typeof option == 'object') && option;

            if (!data) $this.data('context', (data = new ContextMenu($this, options)));
            if (typeof option == 'string') data[option].call(data, e);
        });
    };

    $.fn.contextmenu.Constructor = ContextMenu;

    /* APPLY TO STANDARD CONTEXT MENU ELEMENTS
     * =================================== */

    $(document)
       .on('contextmenu.context.data-api', function() {
            $(toggle).each(function () {
                var data = $(this).data('context');
                if (!data) return;
                data.closemenu();
            });
        })
        .on('contextmenu.context.data-api', toggle, function(e) {
            $(this).contextmenu('show', e);

            e.preventDefault();
            e.stopPropagation();
        });

}(jQuery));
