text: /*!
   * 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.
  			if (e) {
  				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));