
    // == replicator for fragments ==
    // scans through all nodes of the new fragment 
    // and tries to ensure that attributes aren't going crazy...
    // returns new fragment, or false on error
    // - id's must be unique
    // - for attributes must correspond to id's
    // - name attributes are rewritten according to "rule" (see below)
    function cloneFragment(fragment)
    {
      if (!fragment) { return false; }
    
      // generate a new fragment
      var _new = fragment.cloneNode(true);
      
      // or _new.all if you're not using Simon Willison's getElementsBySelector
      var _elms = getAllChildren(_new);  
      var _ctab = {};

      // give new id's to elements
      if (_new.id) 
      {
        _ctab[_new.id] = DOM.aquireId();
        _new.id = _ctab[_new.id];
      }
      var i = 0;
      while (_elm = _elms[i++]) 
      {
        if (_elm.id) 
        {
          _ctab[_elm.id] = DOM.aquireId();
          _elm.id = _ctab[_elm.id];
        }
      }
      // correct other attributes
      var i = 0;
      while (_elm = _elms[i++]) 
      {
        if (_elm.getAttribute("for")) 
        {
          _newid = _ctab[_elm.getAttribute("for")];
          _elm.setAttribute("for", _newid);
        }
        if (_elm.name) 
        {
          _elm.name = _elm.name.replace(/\[(\d)+\]/g, function (str, p1, offset, s) { return "["+ (parseInt(p1)+1) +"]"; } );
        }
        // attempt to reset input values to default
        // this doesn't quite work for passwords or hiddens, and shouldn't
        switch (_elm.type) 
        {
          case 'radio':
          case 'checkbox':
            _elm.checked = _elm.defaultChecked;
            break;
          case 'text':
          case 'password':
          case 'file': // untested ??
          case 'textarea':
          case 'hidden':
            _elm.value = _elm.defaultValue;
            break;
          case 'select-one':
          case 'select-multiple':
            for (var n = 0; n < _elm.options.length; n++) 
            {
              _elm.options[n].selected = _elm.options[n].defaultSelected;
            }
            break;
        }
      }
      return _new;
    }
    
    // 
    function replicate(e) {
      var _new = cloneFragment(this);
      Event.remove(this, e.type, replicate); // ie may need "window.event.type" here? 
      if (_new) {
        // append the new fragment after the source fragment 
        DOM.insertAfter(_new, this);
        Event.add(_new, e.type, replicate);
//        zebraLists.init();
      }
    }

/*
    var reqtext = "Þarf að fylla út";
    var _elms = DOM.get("form .req label");
    for (var i = 0; i < _elms.length; i++) 
    {
      _elms[i].innerHTML = "<acronym title=\"" + reqtext + "\" class=\"req\">*</acronym>" + _elms[i].innerHTML;
    }
*/
  function copylast(e) {
    var _tid = this.href.match(/#([a-z][a-z0-9_.:-]*)$/i);
    if (_tid) {
      var _table = $(_tid[1]);
      var _elms = DOM.get("tr", _table);
      if (_elms.length > 0) {
        var _new = cloneFragment(_elms[_elms.length-1]);
        if (_new) {
          // append the new fragment after the source fragment 
          DOM.insertAfter(_new, _elms[_elms.length-1]);
        }
      } 
    } 
    return false;
  }
  
  
  // init - 
  var _elms = DOM.get("table");
  for (var i = 0; i < _elms.length; i++) 
  {
    var _n = document.createElement("a");
    _n.href = "#" + DOM.aquireId(_elms[i]);
    _n.className = "addrow";
    _n.innerHTML = "Ný röð";
    _n.title = "Bæta við nýrri röð";
    DOM.insertAfter(_n, _elms[i]);
    Event.add(_n, 'click', copylast);
  }



/*
  
  else
  {
    // normal browsers
    _elms = DOM.get("table tr.lastrow");
    for (var i = 0; i < _elms.length; i++) 
    {
      Event.add(_elms[i], 'click', replicate);
    }
  }

*/


