function closeContextMenu() {
  var g = getE('cMenu');
  g && g.parentNode.removeChild(g);
}
function setContextMenu(de,t,e) {
  var te, g, mh = 0, mw = {$number:min_width}, link, text, line = 0,
    bb, r, pos = svgCursorCoords(e,de), x = pos[0], y = pos[1],
    spacing = {$number:spacing},
    shadow, shadow_opacity = {$number:shadow_opacity}, target = '{$string:link_target}';
  g = newel('g', { id: 'cMenu', 'font-size': {$number:font_size}, 'font-family':
    '{$string:font}', 'font-weight': '{$string:font_weight}', fill:'{$string:colour}'});
  for(te in t) {
    text = newel('text', { x: '0px', y: '0px' });
    text.appendChild(newtext(t[te][0]));
    g.appendChild(text);
    de.appendChild(g);
    bb = text.getBBox();
    de.removeChild(g);
    g.removeChild(text);
    if(bb.width > mw)
      mw = bb.width;
  }
  for(te in t) {
    text = newel('text', { x: {$number:pad_x} + 'px', y: ({$number:text_start} + line * spacing) + 'px' });
    text.appendChild(newtext(t[te][0]));
    if(t[te][1]) {
      link = newel('a', { 'fill' : '{$string:link_colour}'{$string:underline_part} });
      link.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', t[te][1]);
      target && setattr(link, 'target', target);
      r = newel('rect', { x: {$number:pad_x} + 'px', y: ({$number:rect_start} + line * spacing) + 'px',
        width: mw + 'px', height: spacing + 'px', fill: '#000', opacity: 0});
      link.appendChild(r);
      link.appendChild(text);
      g.appendChild(link);
      link.addEventListener('mouseover', function(e) {
        setattr(this, 'fill', '{$string:link_hover_colour}');
        setattr(this.querySelector('rect'), 'opacity', 0.1);
      });
      link.addEventListener('mouseout', function(e) {
        setattr(this, 'fill', '{$string:link_colour}');
        setattr(this.querySelector('rect'), 'opacity', 0);
      });
    } else {
      g.appendChild(text);
    }
    ++line;
  }
  mw += {$number:pad_x} * 2;
  mh = (line * spacing) + {$number:pad_y} * 2;
  r = newel('rect', { x: '0px', y: '0px', width: mw + 'px', height: mh + 'px',
    'stroke-width': {$number:stroke_width} + 'px',
    fill: '{$string:back_colour}', stroke: '{$string:colour}'{$string:round_part}});
  g.insertBefore(r, g.childNodes[0]);
  x = Math.min(de.width.baseVal.value - mw - {$number:off_right},x);
  y = (de.height.baseVal.value - mh - {$number:off_bottom} < y ? y - mh : y);
  if(shadow_opacity > 0) {
    shadow = newel('rect',{ fill: '#000', opacity: {$number:shadow_opacity},
    'stroke-width': {$number:stroke_width} + 'px', stroke: '#000'{$string:round_part},
    x:'{$number:cmoffs}px',y:'{$number:cmoffs}px', width: mw + 'px', height: mh + 'px'});
    g.insertBefore(shadow, g.childNodes[0]);
  }
  setattr(g, 'transform', 'translate(' + x + ',' + y + ')');
  de.appendChild(g);
}
function contextMenuInit() {
  var c, e, nn = '{$string:namespace}svg';
  for(c in menus) {
    e = getE(c);
    e && e.addEventListener && e.addEventListener('contextmenu', function(e) {
      e.preventDefault();
      e.stopPropagation();
      var t = finditem(e,menus), de = svgNode(e,1), g = getE('cMenu');
      g && g.parentNode.removeChild(g);
      setContextMenu(de,t,e);
      return false;
    },false);
  }
  e = document.querySelectorAll(nn);
  for(c = 0; c < e.length; ++c) {
    e[c].addEventListener('click', closeContextMenu, false);
{$string:mouseleave}
    e[c].addEventListener('keydown', function(e) {
      if(e.keyCode == 27)
        closeContextMenu();
    },false);
    e[c].addEventListener('contextmenu', rootContextMenu, false);
  }
}
