<commit_before>/**
 * @constructor
 *
 * A class for handling context menus. Only one context menu will be shown at
 * a time, so all methods are static.
 */
var ContextMenu = function() {};

/**
 * Holds all registered context menus.
 */
ContextMenu.registered_menus = {};

/**
 * Registers a new context menu, or adds items to an already registered context menu.
 *
 * @param {String} menu_id An id correspoding to an id specified with a data-menu
 *                         attribute in the markup. May be an already existing
 *                         menu, in which case the items are added.
 * @param {Array} item_list An array of objects with 'id', 'label' and 'handler'
 *                          (function).
 *
 */
ContextMenu.register = function(menu_id, item_list)
{
  var menu = ContextMenu.registered_menus[menu_id];
  // If it already is registered, merge it
  if (menu)
  {
    ContextMenu.registered_menus[menu_id] = menu.concat(item_list);
  }
  else if (menu_id && item_list)
  {
    ContextMenu.registered_menus[menu_id] = item_list;
  }
};

/**
 * Show and position a context menu.
 *
 * @param {String} menu_id Id of a registered context menu.
 * @param {Int} x The left position of the menu, relative to the viewport.
 * @param {Int} y The top position of the menu, relative to the viewport.
 */
ContextMenu.show = function(menu_id, x, y)
{
  var menu = ContextMenu.registered_menus[menu_id];
  if (menu)
  {
    var contextmenu = document.documentElement.render(window.templates.contextmenu(menu_id, menu));

    const DEFAULT_MARGIN = 5;
    var max_height = 0;
    var box = contextmenu.getBoundingClientRect();
    var box_width = box.width;
    var box_height = box.height;
    var window_height = window.innerHeight;
    var window_width = window.innerWidth;
    var double_margin = DEFAULT_MARGIN * 2;

    // Check if the menu height fits within the window
    if (box_height + double_margin > window_height)
    {
      // It doesn't fit, apply max-height to make it scroll
      y = DEFAULT_MARGIN;
      max_height = window_height - double_margin - 2; // 2 = border-width (top+bottom)
    }
    // It doesn't fit downwards, flip it or reposition it
    else if (y + box_height + double_margin > window_height)
    {
      // Check if we can just flip it upwards
      if (box_height + DEFAULT_MARGIN < y)
      {
        y -= box_height;
      }
      // Reposition it upwards as much as needed
      else
      {
        var overflow = window.innerHeight - y - box_height;
        y += overflow - DEFAULT_MARGIN;
      }
    }

    // It doesn't fit to the right, flip it
    if (x + box_width + double_margin > window_width)
    {<commit_msg>Some small clarifications in comments, and small rewrite.<commit_after>/**
 * @constructor
 *
 * A class for handling context menus. Only one context menu will be shown at
 * a time, so all methods are static.
 */
var ContextMenu = function() {};

/**
 * Holds all registered context menus.
 */
ContextMenu.registered_menus = {};

/**
 * Registers a new context menu, or adds items to an already registered context menu.
 *
 * @param {String} menu_id An id correspoding to an id specified with a data-menu
 *                         attribute in the markup. May be an already existing
 *                         menu, in which case the items are added.
 * @param {Array} item_list An array of objects with 'id', 'label' and 'handler'
 *                          (function).
 *
 */
ContextMenu.register = function(menu_id, item_list)
{
  var menu = ContextMenu.registered_menus[menu_id];
  // If it already is registered, merge it
  if (menu)
  {
    ContextMenu.registered_menus[menu_id] = menu.concat(item_list);
  }
  else if (menu_id && item_list)
  {
    ContextMenu.registered_menus[menu_id] = item_list;
  }
};

/**
 * Show and position a context menu.
 *
 * @param {String} menu_id Id of a registered context menu.
 * @param {Int} x The left position of the menu, relative to the viewport.
 * @param {Int} y The top position of the menu, relative to the viewport.
 */
ContextMenu.show = function(menu_id, x, y)
{
  var menu = ContextMenu.registered_menus[menu_id];
  if (menu)
  {
    var contextmenu = document.documentElement.render(window.templates.contextmenu(menu_id, menu));

    const DEFAULT_MARGIN = 2;
    var max_height = 0;
    var box = contextmenu.getBoundingClientRect();
    var box_width = box.width;
    var box_height = box.height;
    var window_height = window.innerHeight;
    var window_width = window.innerWidth;

    // Check if the menu height fits within the window
    if (box_height + (DEFAULT_MARGIN * 2) > window_height)
    {
      // It doesn't fit, apply max-height to make it scroll
      y = DEFAULT_MARGIN;
      max_height = window_height - (DEFAULT_MARGIN * 2) - 2; // 2 = border-width (top+bottom)
    }
    // It fits within the window, check if it fits downwards or not. If it
    // doesn't, we have to adjust the position.
    else if (y + box_height + DEFAULT_MARGIN > window_height)
    {
      // Check if we can just flip it upwards
      if (box_height + DEFAULT_MARGIN < y)
      {
        y -= box_height;
      }
      // It doesn't fit upwards, reposition it upwards as much as needed
      else
      {
        var overflow = window.innerHeight - y - box_height;
        y += overflow - DEFAULT_MARGIN;
      }
    }

    // It doesn't fit to the right, flip it
    if (x + box_width + DEFAULT_MARGIN > window_width)
    {
{'fraction_non_alphanumeric': 0.09522065555759018, 'fraction_numerical': 0.0020142830983336385, 'mean_word_length': 2.6510695187165774, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '944971', 'n_tokens_mistral': 1683, 'n_tokens_neox': 1618, 'n_words': 581}