  
    var baseUri = "http://helma.org/Mailing+Lists/";

    // currently showing menu id
    var currentMenu;

    document.onmousedown = function(event) {
        if (currentMenu) {
            event = event || window.event;
            var elem = event.target || event.srcElement;
            while (elem) {
                if (elem.id == currentMenu) return true;
                elem = elem.parentNode;
            }
            showElement(currentMenu, false);
            currentMenu = null;
        }
        return true;
    }

    function commentShowForm() {
        $('.commentToggle').toggle('normal', function() {
            $('html,body').animate({
                scrollTop: $('#commentForm').offset().top
            });
            $('#commentInput').focus();
        });
        return false;
    }

    function commentCancel() {
        // $('#commentInput').val('');
        $('.commentToggle').slideToggle('normal', function() {
            $('.previewToggle').hide();
            $('#pagePreview').html('');
        });
        return false;
    }

    function deleteCommentShow(link) {
        var scratchpad = $(link).nextAll('.commentScratchpad:first');
        scratchpad.next().show();
        scratchpad.html('').hide().load(link.href, { ajax: true }, function() {
            scratchpad.show();
        });
        return false;
    }

    function deleteCommentCancel(link) {
        var parent = $(link).parents('.commentScratchpad');
        if (parent.length > 0) {
            parent.hide();
            $(this).html('');
            return false;
        }
        return true;
    }

    function editCommentShow(link) {
        var scratchpad = $(link).nextAll('.commentScratchpad:first');
        scratchpad.load(link.href, { ajaxedit: true }, function() {
            $('html,body').animate({
                scrollTop: $(link).offset().top
            });
            scratchpad.show().find('textarea').focus();
            scratchpad.next().hide();
        });
        return false;
    }

    function editCommentCancel(link) {
        var parent = $(link).parents('.commentScratchpad');
        if (parent.length > 0) {
            parent.hide().next().show();
            return false;
        }
        return true;
    }


    function pagePreview(form) {
        var input = $(form).find('[name=body]');
        var action = form.action || location.href;
        var preview = $(form).find('.pagePreview:first');
        preview.load(action, {
            ajaxpreview: true,
            name: $(form).find('[name=name]').val(),
            body: input.val(),
            useMarkdown: $(form).find('[name=useMarkdown]').is(':checked') ? "true" : ""
        }, function() {
            $('.previewToggle').show('normal', function() {
                $('html,body').animate({
                    scrollTop: preview.offset().top
                });
            });
        });
        input.focus();
        return false;
    }

    function pageDiff(form) {
        var input = $(form).find('[name=body]');
        var action = form.action || location.href;
        var preview = $(form).find('.pagePreview:first');
        preview.load(action, {
            ajaxdiff: true,
            name: $(form).find('[name=name]').val(),
            body: input.val()
        }, function() {
            $('.previewToggle').show('normal', function() {
                $('html,body').animate({
                    scrollTop: preview.offset().top
                });
            });
        });
        input.focus();
        return false;
    }

    function continueEditing(form) {
        // $('.previewToggle').hide('normal');
        var scrollTarget = $('p#bodylabel');
        $('html,body').animate({
            scrollTop: scrollTarget.offset().top
        });
        scrollTarget.find('[name=body]').focus();
        return false;
    }


  //////////////////////// legacy stuff

  function openPopup(url, name, width, height) {
      if (isNaN(width)) width = 300;
      if (isNaN(height)) height = 350;
      // create reasonable screen location for popup
      var position =  ",left="+
                      Math.floor((screen.availWidth - width) / 2)+
                      ",top="+
                      Math.floor((screen.availHeight - height) / 2)+
                      ",scrollbars=yes,resizable=yes";
      var popup = window.open(url, name, 'width='+width+',height='+height+position); 
      popup.focus();
  }
  
  function getElement(id) {
      return document.getElementById(id);
  }

  function setElementContent(id, html) {
      try{
          getElement(id).innerHTML = html;
      } catch (error) {
          alert("Error in setElementContent for element "+id+": "+error);
      }
  }
  
  function setStyle(id, name, value) {
      try{
          var elem = getElement(id);
          if (elem) {
              elem.style[name] = value;
          }
      } catch (error) {
          alert("Error in setStyleElement for "+id+": "+error);
      }
  }

  function showElement(id, show) {
      try{
          var elem = getElement(id);
          if (elem) {
              elem.style.display = show ? "" : "none";
          }
      } catch (error) {
          alert("Error in showElement for "+id+": "+error);
      }
  }
  
  function toggleElement(id, trigger, show, hide) {
      try{
          var elem = getElement(id);
          if (elem) {
              if (elem.style.display == "none") {
                elem.style.display = "";
                if (trigger) 
                    trigger.innerHTML = hide;
              } else {
                elem.style.display = "none";
                if (trigger) 
                    trigger.innerHTML = show;
              }
          }
      } catch (error) {
          alert("Error in toggleElement for "+id+": "+error);
      }
      return false;
  }

  function toggleMenu(id) {
      currentMenu = currentMenu != id && id;
      return toggleElement(id);
  }

  function toggleCheckbox(checkbox) {
      if (checkbox.checked)
          checkbox.checked = "";
      else
          checkbox.checked = "on";
  }
  
  function toggleAll(name) {
      var list = getElement(name+"_list").childNodes;
      for (var i=0; i<list.length; i++) {
          if (list[i].firstChild) {
              if (list[i].firstChild.checked) 
                  list[i].firstChild.checked = "";
              else 
                  list[i].firstChild.checked = "on";
          }
      }
  }
  
  function addOption(element, text, value, selected) {
      var select = (selected == true);
      var opt = new Option(text, value, false, select);
      element.options[element.length] = opt;
      if (select)
          element.selectedIndex = element.length-1;
  }

  function toggleLink(elem, name) {
      var linkfield = opener.getElement(name+"_links");
      if (linkfield.value.indexOf(":"+elem.getAttribute("name")+":") > -1) {
          // link is currently set - remove
          var re = RegExp(":"+elem.getAttribute("name")+":");
          linkfield.value = linkfield.value.replace(re, ":");
          opener.buildList(name, elem);
          return "linkEditorPlain";
      } else {
          // link isn't set - add
          linkfield.value += elem.getAttribute("name")+":";
          opener.buildList(name, elem);
          return "linkEditorSelected";
      }
  }
  
  function toggleControl() {
     var control = getElement("ctrl");
     if (control) {
         if (control.style.display == "none") {
             control.style.display = "";
             document.cookie = "displayCtrlBar=;path=/";
         } else {
             control.style.display = "none";
             document.cookie = "displayCtrlBar=none;path=/";
         }
     }
     return;
  }

  function buildList(name, link) {
      var safeName = name.replace(/\s/g, "_");
      var value = getElement(name+"_links").value;
      var pages = value.split(":");
      var list = getElement(name+"_list");
      var str = "";
      for (var i in pages) {
          if (!pages[i])
              continue;
          str += "<div name=\"";
          str += pages[i];
          str += "\" style=\"padding: 2px;\">";
          // name_linknames is a client side array set by Page.dynalinkeditor macro
          str += eval(safeName + "_linknames[" + pages[i] + "]");
          str += "</div>";
      }
      setElementContent(name+"_list", str);
  }

  function openLinkPopup(url, name, width, height) {
      url += "&links=";
      var elem =  getElement(name + "_links");
      if (elem) {
          url += elem.value;
      }
      openPopup(url, name, width, height);
  }

  function addClass(elem, clazz) {
      if (elem) {
          var className = elem.className || "";
          var classes = elem.split(" ");
          for (var i = 0; i < classes.length; i++) {
              if (classes[i] == clazz) return;
          }
          elem.className = classes.join(" ");;
      }
  }

  function removeClass(elem, clazz) {
      if (elem) {
          var className = elem.className || "";
          var classes = elem.split(" ");
          for (var i = classes.length - 1; i >= 0; i--) {
              if (classes[i] == clazz) {
                  classes.splice(i, 1);
              };
          }
          elem.className = classes.join(" ");;
      }
  }

    /** 
     * Create a XMLHttpRequest instance
     */
    function createAsyncRequest() {
        if (window.XMLHttpRequest) {
            // branch for native XMLHttpRequest object
            return new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            // branch for IE/Windows ActiveX version
            return new ActiveXObject("Microsoft.XMLHTTP");
        }
        return null;
    }

    /**
     * Send a request to a XMLHttpRequest instance
     */
    function executeAsyncRequest(req, method, url, body) {
        if (!method) {
            method = "GET";
        } 
        req.open(method, url, true);
        if (method == "POST" && body) {
            req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            req.send(body);
        } else {
            try {
                req.send(null);
            } catch (ignore) {}
        }
    }
    
 
    /**
     * Call a XMLHttpRequest asynchronously.
     */
    function callAsyncRequest(url, handler, method, body) {
        var req = createAsyncRequest();
        if (!req) {
            alert("Error loading content: XMLHttpRequest not supported");
            return;
        }
        if (handler) {
            // create a wrapper that calls the request listener with the 
            // request as argument, so we don't have to keep track of it
            req.onreadystatechange = function() {
                handler.apply(null, [req]);
            };
        }
        executeAsyncRequest(req, method, url, body);
    }
  
    /**
     * Call a XMLHttpRequest asynchronously and write the returned body to the 
     * DOM element with the given id.
     */
    function loadContent(url, id, method, body) {
        var req = createAsyncRequest();
        if (!req) {
            alert("Error loading content: XMLHttpRequest not supported");
            return;
        }
        // create a wrapper that calls the request listener with the 
        // request as argument, so we don't have to keep track of it
        req.onreadystatechange = function() {
            if (req.readyState == 4) {
                if (req.status == 200)
                    setElementContent(id, req.responseText);
                else
                    alert("Error loading content: " + req.statusText);
            }
        };
        executeAsyncRequest(req, method, url, body);
        return false;
    }


  /**
   * Catch F2 for asynchronously saving the page. 
   * FIXME: not finished/working, should use async HTTP request.
   */
  function handleKeyPress(event) {
      event = event || window.event;
      var target = event.target || event.srcElement;
      if (event && target && event.keyCode == 113) {
          var text = target.firstChild.nodeValue;
          callAsyncRequest(baseUri + "edit.autosave", null, "POST", 
              target.name + "=" + encodeURIComponent(text));
      }
      return true;
  }

  function initDocument() {
      var tas = document.getElementsByTagName("textarea");
      for (var i=0; i<tas.length; i++) {
          var ta = tas[i];
          addEvent(ta, "keypress", handleKeyPress);
      }
      if (document.edit) {
          var inputs = document.edit.getElementsByTagName("input");
          for (var i=0; i<inputs.length; i++) {
              if (inputs[i].type != "hidden") {
                  inputs[i].focus();
                  // inputs[i].select();
                  break;
              }
          }
      }
  }
