Unfix Fixed Position Element on Firefox Context Menu

Add new item to top of right-click context menu to override position:fixed on elements in a page.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        Unfix Fixed Position Element on Firefox Context Menu
// @description Add new item to top of right-click context menu to override position:fixed on elements in a page.
// @author      Jefferson "jscher2000" Scher
// @namespace   JeffersonScher
// @copyright   Copyright 2016 Jefferson Scher
// @license     BSD 3-clause
// @include     *
// @version     0.5.1
// @grant       none
// ==/UserScript==

// Context menu options -- Firefox only, and do not replace any existing context menu! Also, do not run in iframes
if (!document.body.hasAttribute("contextmenu") && "contextMenu" in document.documentElement && (window.self == window.top)) {
  var cmenu = document.createElement("menu");
  cmenu.id = "UFPEcontext";
  cmenu.setAttribute("type", "context");
  cmenu.innerHTML = '<menu id="UFPEFlyout" label="Unfix Fixed Element" ufpeundolist="">' +
    '<menuitem id="UFPEStatic" label="Make Static"></menuitem>' +
    '<menuitem id="UFPEHide" label="Hide"></menuitem>' +
    '<menuitem id="UFPEUnHide" label="UnHide"></menuitem>' +
    '</menu>';
  document.body.appendChild(cmenu);
  document.getElementById("UFPEStatic").addEventListener("click", UFPE_doStyle, false);
  document.getElementById("UFPEHide").addEventListener("click", UFPE_doStyle, false);
  document.getElementById("UFPEUnHide").addEventListener("click", UFPE_dispUnHide, false);
  // attach menu and create event for filtering
  document.body.setAttribute("contextmenu", "UFPEcontext");
  document.body.addEventListener("contextmenu", UFPE_cmenuFilter, false);
} else {
  console.log("DIDN'T ADD CONTEXT MENU!");
}
function UFPE_cmenuFilter(e){
  // Mark the right-clicked element for later reference (is there an easier way?)
  var tgt = e.target;
  // Compute and store a highly unique element based on the current time
  var dNew = new Date();
  tgt.setAttribute('unfixtime', dNew.getTime());
  // Store that same time on the first context menu item for each of reference
  document.getElementById('UFPEFlyout').setAttribute('unfixtgt', tgt.getAttribute('unfixtime'));
}
function UFPE_doStyle(e){
  // What is the action?
  var axn = e.target.id.substr(4); // Static or Hide
  // Find the right-clicked element using the stored timestamp -- should be unique
  var tgtval = document.getElementById('UFPEFlyout').getAttribute('unfixtgt');
  var tgt = document.querySelector('[unfixtime="'+tgtval+'"]');
  if (!tgt){
    // Oh crap, something went wrong
    alert('Unable to find my target!');
    return;
  }
  // Find the position:fixed element -- it could be the right-clicked element or an ancestor containing it
  while (tgt.nodeName != 'BODY') {
    var posval = window.getComputedStyle(tgt,null).getPropertyValue('position');
    // For debugging purposes
    // console.log('tgt.nodeName='+tgt.nodeName+' has '+posval);
    if (posval=='fixed' || (posval=='static' && tgt.hasAttribute('ufpestatic') && axn=='Hide')){
      // This is the nearest ancestor with position:fixed
      switch (axn){
        case 'Static':
          // Set position:static and store a timestamp for reference
          tgt.style.position = 'static';
          tgt.setAttribute('ufpestatic', tgtval);
          return;
        case 'Hide':
          // Set a timestamp for reference and add it to the undo list
          tgt.setAttribute('ufpehidden', tgtval);
          tgt.setAttribute('ufpedisplay', window.getComputedStyle(tgt,null).getPropertyValue('display'));
          var hidden = document.getElementById('UFPEFlyout').getAttribute('ufpeundolist');
          if (hidden.length === 0) hidden = tgtval;
          else hidden += ',' + tgtval;
          document.getElementById('UFPEFlyout').setAttribute('ufpeundolist', hidden);
          // Set display:none to hide the element
          tgt.style.display = 'none';
          return;
      }
      console.log('Value for axn is corrupted!');
      break;
    } else {
      // Check the next higher ancestor
      tgt = tgt.parentNode;
    }
  }
}
function UFPE_dispUnHide(e){
  // Retrieve undo list
  var hidden = document.getElementById('UFPEFlyout').getAttribute('ufpeundolist');
  if (hidden.length === 0){
    alert('Nothing is hidden right now');
    return;
  }
  // Split off the last timestamp in the list
  var cpos = hidden.lastIndexOf(',');
  if (cpos === -1){
    tgtval = hidden;
    hidden = '';
  } else {
    tgtval = hidden.substr(cpos+1);
    hidden = hidden.substr(0, cpos);
  }
  // Update the undo list
  document.getElementById('UFPEFlyout').setAttribute('ufpeundolist', hidden);
  // Seek the hidden element
  var tgt = document.querySelector('[ufpehidden="'+tgtval+'"]');
  if (!tgt){
    // Oh crap, something went wrong
    alert('The hidden item seems to be gone. Maybe try again?');
    return;
  } else {
    // Restore the previous value of the display property
    tgt.style.display = tgt.getAttribute('ufpedisplay');
  }
}