
var infoPopup = new (function () {

  // Configuration

  var popupHOffset = 10, // [px]
      popupVOffset = 10; // [px]

  // End of configuration

  var popupTable,
      popupTableStyle,
      popupTBody,
      headerNode,
      bodyNode,
      htmlBodyElement;

  function placePopup(popupLeft, popupTop, popupWidth, popupHeight, canvasWidth, canvasHeight, scrollLeft, scrollTop) {

    if (popupLeft + popupWidth > canvasWidth) {
      popupLeft = canvasWidth - popupWidth;
      popupLeft = popupLeft < 0 ? 0 : popupLeft;
    }
    if (popupTop + popupHeight > canvasHeight) {
      popupTop = canvasHeight - popupHeight;
      popupTop = popupTop < 0 ? 0 : popupTop;
    }

    popupTableStyle.left = popupLeft + scrollLeft + "px";
    popupTableStyle.top = popupTop + scrollTop + "px";

  }

  this.show = function () { };
  this.hide = function () { };

  if (document.addEventListener) {
    function mouseMoveListener(e) {
      placePopup(e.clientX + popupHOffset,
                 e.clientY + popupVOffset,
                 popupTable.offsetWidth,
                 popupTable.offsetHeight,
                 window.innerWidth,
                 window.innerHeight,
                 window.scrollX,
                 window.scrollY);
    }
    this.show = function (handlerArguments) {
      mouseMoveListener(handlerArguments[0]);
      document.addEventListener("mousemove", mouseMoveListener, false);
      popupTableStyle.display = "block";
    }
    this.hide = function () {
      document.removeEventListener("mousemove", mouseMoveListener, false);
      popupTableStyle.display = "none";
    }
  }

  if (document.attachEvent) {
    function mouseMoveListener() {
      placePopup(event.clientX + popupHOffset,
                 event.clientY + popupVOffset,
                 popupTable.offsetWidth,
                 popupTable.offsetHeight,
                 htmlBodyElement.clientWidth,
                 htmlBodyElement.clientHeight,
                 htmlBodyElement.scrollLeft,
                 htmlBodyElement.scrollTop);
    }
    this.show = function () {
      mouseMoveListener();
      document.detachEvent("onmousemove", mouseMoveListener);
      document.attachEvent("onmousemove", mouseMoveListener);
      popupTableStyle.display = "block";
    }
    this.hide = function () {
      document.detachEvent("onmousemove", mouseMoveListener);
      popupTableStyle.display = "none";
    }
  }

  this.setHeaderHTML = function (nodeHTML) {
    headerNode.innerHTML = nodeHTML;
  }
  this.setBodyHTML = function (nodeHTML) {
    bodyNode.innerHTML = nodeHTML;
  }

  // Creating popup table

  with (document) {
    popupTable = createElement("table");
    popupTBody = createElement("tbody");
    headerNode = createElement("th");
    bodyNode = createElement("td");
  }

  popupTableStyle = popupTable.style;

  with (popupTable) {
    cellPadding = 0;
    cellSpacing = 0;
    border = 0;
    className = "infoPopup";
    style.display = "none";
  }

  popupTBody.appendChild(document.createElement("tr")).appendChild(headerNode);
  popupTBody.appendChild(document.createElement("tr")).appendChild(bodyNode);

  popupTable.appendChild(popupTBody);

  // Adding popup table as the first child of the body element

  htmlBodyElement = document.getElementsByTagName("body")[0];
  htmlBodyElement.insertBefore(popupTable, htmlBodyElement.childNodes[0]);

});
