template/html/d3-graph.js
function onNodeContextClick(targetNode, coords)
   {
      // Hides any existing node context menu.
      hideNodeContextMenu();

      if (typeof coords !== 'object') { coords = getElementCoords(this); }

      var popupmenu = $('#contextpopup .mdl-menu__container');

      var packageData = targetNode.packageData;

      var packageLink, packageType, scmLink, scmType;

      if (packageData)
      {
         if (packageData.packageLink)
         {
            packageLink = packageData.packageLink.link;
            packageType = packageData.packageLink.type;

            // Create proper name for package type.
            switch (packageType)
            {
               case 'npm':
                  packageType = 'NPM';
                  break;
            }
         }

         if (packageData.scmLink)
         {
            scmLink = packageData.scmLink.link;
            scmType = packageData.scmLink.type;

            // Create proper name for SCM type.
            switch (scmType)
            {
               case 'github':
                  scmType = 'Github';
                  break;
            }
         }
      }

      // Populate data for the context menu.
      popupmenu.find('li').each(function(index)
      {
         var liTarget = $(this);

         switch (index)
         {
            case 0:
               if (scmLink && scmType)
               {
                  liTarget.text('Open on ' + scmType);
                  liTarget.data('link', scmLink);
                  liTarget.removeClass('hidden');
               }
               else
               {
                  liTarget.addClass('hidden');
               }
               break;

            case 1:
               if (packageLink && packageType)
               {
                  liTarget.text('Open on ' + packageType);
                  liTarget.data('link', packageLink);
                  liTarget.removeClass('hidden');
               }
               else
               {
                  liTarget.addClass('hidden');
               }
               break;

            case 2:
               if (packageData && packageData.version)
               {
                  liTarget.text('Version: ' + packageData.version);
                  liTarget.removeClass('hidden');
               }
               else
               {
                  liTarget.addClass('hidden');
               }
               break;
         }
      });

      // Wrapping in a 100ms timeout allows MDL to draw animation when showing a context menu after one has been hidden.
      setTimeout(function()
      {
         // Assign new selected context node and highlight related nodes.
         selectedContextNode = targetNode;

         fadeRelatedNodes(selectedContextNode, true, nodes, links);

         // For MDL a programmatic click of the hidden context menu.
         var contextMenuButton = $("#context-menu");
         contextMenuButton.click();

         // Necessary to defer reposition of the context menu.
         setTimeout(function()
         {
            popupmenu.parent().css({ position: 'relative' });
            popupmenu.css({ left: coords.x, top: coords.y, position:'absolute' });
         }, 0);
      }, 100);
   }
function onNodeContextClick(targetNode, coords)
   {
      // Hides any existing node context menu.
      hideNodeContextMenu();

      if (typeof coords !== 'object') { coords = getElementCoords(this); }

      var popupmenu = $('#contextpopup .mdl-menu__container');

      var packageData = targetNode.packageData;

      var packageLink, packageType, scmLink, scmType;

      if (packageData)
      {
         if (packageData.packageLink)
         {
            packageLink = packageData.packageLink.link;
            packageType = packageData.packageLink.type;

            // Create proper name for package type.
            switch (packageType)
            {
               case 'npm':
                  packageType = 'NPM';
                  break;
            }
         }

         if (packageData.scmLink)
         {
            scmLink = packageData.scmLink.link;
            scmType = packageData.scmLink.type;

            // Create proper name for SCM type.
            switch (scmType)
            {
               case 'github':
                  scmType = 'Github';
                  break;
            }
         }
      }

      // Populate data for the context menu.
      popupmenu.find('li').each(function(index)
      {
         var liTarget = $(this);

         switch (index)
         {
            case 0:
               if (scmLink && scmType)
               {
                  liTarget.text('Open on ' + scmType);
                  liTarget.data('link', scmLink);
                  liTarget.removeClass('hidden');
               }
               else
               {
                  liTarget.addClass('hidden');
               }
               break;

            case 1:
               if (packageLink && packageType)
               {
                  liTarget.text('Open on ' + packageType);
                  liTarget.data('link', packageLink);
                  liTarget.removeClass('hidden');
               }
               else
               {
                  liTarget.addClass('hidden');
               }
               break;

            case 2:
               if (packageData && packageData.version)
               {
                  liTarget.text('Version: ' + packageData.version);
                  liTarget.removeClass('hidden');
               }
               else
               {
                  liTarget.addClass('hidden');
               }
               break;
         }
      });

      // Wrapping in a 100ms timeout allows MDL to draw animation when showing a context menu after one has been hidden.
      setTimeout(function()
      {
         // Assign new selected context node and highlight related nodes.
         selectedContextNode = targetNode;

         fadeRelatedNodes(selectedContextNode, true, nodes, links);

         // For MDL a programmatic click of the hidden context menu.
         var contextMenuButton = $("#context-menu");
         contextMenuButton.click();

         // Necessary to defer reposition of the context menu.
         setTimeout(function()
         {
            popupmenu.parent().css({ position: 'relative' });
            popupmenu.css({ left: coords.x, top: coords.y, position:'absolute' });
         }, 0);
      }, 100);
   }
Shows the node context menu

@param {object}   targetNode - The target node.

@param {object}   coords - Object containing x / y position for context menu; if not provided Node position
determines coords.