Index: /quintagroup.referencedatagridfield/branches/plone4/quintagroup/referencedatagridfield/skins/referencedatagridfield/datagridwidget_manipulators.pt
===================================================================
--- /quintagroup.referencedatagridfield/branches/plone4/quintagroup/referencedatagridfield/skins/referencedatagridfield/datagridwidget_manipulators.pt	(revision 2310)
+++ /quintagroup.referencedatagridfield/branches/plone4/quintagroup/referencedatagridfield/skins/referencedatagridfield/datagridwidget_manipulators.pt	(revision 2311)
@@ -8,5 +8,6 @@
 
     <metal:define define-macro="edit_manipulators"
-        tal:define="helper nocall:here/refbrowserhelper;">
+        tal:define="helper nocall:here/refbrowserhelper;
+                    overlay_id string:atrb_${fieldName}">
     
      	 <tal:manipulator-cells>
@@ -22,21 +23,28 @@
 
 		<td class="datagridwidget-manipulator"
-		    tal:define="multiVal      python:0;
-				fieldRealName field/getName;
-				">
-		    <div style="clear: both"
-			 tal:define="startup_directory python:helper.getStartupDirectory(field);
-				     global at_url at_url|python:'/'.join(here.getPhysicalPath());
-				     field_id string:uid_${fieldId};
-				     field_link_id string:link_${fieldId};
-				     field_title_id string:title_${fieldId};
-				     ">
-			<input type="button"
-			       class="searchButton"
-			       value="Select"
-			       onClick=""
-			       i18n:attributes="value label_select;"
-			       tal:attributes="onClick string:javascript:referencebrowser_openBrowser('${startup_directory}','${field_id}', '${at_url}', '${fieldRealName}', '${field_title_id}', '${field_link_id}', this)" />
-                    </div>
+		    tal:define="multiValued python:0;">
+
+		  <div style="clear: both"
+		      tal:define="
+			  global at_url at_url|python:'/'.join(here.getPhysicalPath());
+			  startup_directory python:helper.getStartupDirectory(field);
+			  field_id string:uid_${fieldId};
+			  field_link_id string:link_${fieldId};
+			  field_title_id string:title_${fieldId};
+			  ">
+		    <input type="button" class="searchButton addreference" value="Add..."
+			   i18n:attributes="value label_add;"
+			   tal:define="popup_width widget/popup_width|string:500;
+				       popup_height widget/popup_height|string:550;"
+			   tal:attributes="src string:${startup_directory}/refdatagridbrowser_popup?fieldName=${fieldName}&fieldRealName=${field/getName}&at_url=${at_url};
+				       rel string:#${overlay_id}" />            
+		       </div><div id="atrb" tal:attributes="id overlay_id" class="overlay overlay-ajax">
+		       <div class="pb-ajax">
+			 <!-- <a href="" i18n:translate="referencebrowser_back" class="refbrowser_back">Back</a> -->
+			 <div class="overlaycontent" style="font-size: 125%"></div>
+			 <!-- <a href="" i18n:translate="referencebrowser_back" class="refbrowser_back">Back</a> -->
+		       </div>
+		       </div>
+
 		</td>
 
Index: /quintagroup.referencedatagridfield/branches/plone4/quintagroup/referencedatagridfield/skins/referencedatagridfield/referencebrowser.js
===================================================================
--- /quintagroup.referencedatagridfield/branches/plone4/quintagroup/referencedatagridfield/skins/referencedatagridfield/referencebrowser.js	(revision 2310)
+++ /quintagroup.referencedatagridfield/branches/plone4/quintagroup/referencedatagridfield/skins/referencedatagridfield/referencebrowser.js	(revision 2311)
@@ -1,212 +1,183 @@
-// Crossbrowser event listeners adder
-function addEvent(obj, evType, fn, useCap) {
-    var r = false;
-    if (obj.addEventListener){
-        if (typeof(useCap) == 'undefined')
-	    useCap = false;
-        obj.addEventListener(evType, fn, useCap);
-        r = true;
-     }
-     else if (obj.attachEvent) {
-	 var id = obj.sourceIndex || -1;
-
-	 if (!fn[evType + id]) {
-	     var f = fn[evType + id] = function(e) {
-		 var o = document.all[id] || document;
-		 o._f = fn;
-		 var s = o._f(e);
-		 o._f = null;
-		 return s;
-	     };
-
-	     r = obj.attachEvent("on" + evType, f);
-	     obj = null;
-	 }
-     }
-     return r;
- };
-
-function triggerTitleClass(e) {
-    var currnode = window.event ? window.event.srcElement : e.currentTarget;
-    
-	// fetch required data structure   
-    var element = getThisOrParentElement(currnode, "INPUT");
-    // If no input tag found - leave function
-    if (element == null || element.tagName.toUpperCase() == "BODY")
-	return;
-    
-    var current = element.value;
-    var initial = element.getAttribute("default_value");
-    if (initial == null || current == null)
-	return;
-
-    if (initial == current) {
-       setClassAttr(element, "not-changed-title-field")
-    } else {
-       setClassAttr(element, "changed-title-field")
-    }
-}
-
-function setClassAttr(element, value) {
-    if (element.className) {
-        element.className = value
-    } else {
-        element.setAttribute("CLASS", value)
-    } 
-}
-// Trigger styles on focusing on the element
-function triggerOnFocusStyles(e) {
-    var currnode = window.event ? window.event.srcElement : e.currentTarget;
-    
-	// fetch required data structure   
-    var element = getThisOrParentElement(currnode, "INPUT");
-    // If no input tag found - leave function
-    if (element == null || element.tagName.toUpperCase() == "BODY")
-	return;
-    setClassAttr(element, "changed-title-field")
-}
-
-function getThisOrParentElement(currnode, tagname) {
-    /* Find the first parent node with the given tag name */
-
-    tagname = tagname.toUpperCase();
-    var parent = currnode;
-
-    while(parent.tagName.toUpperCase() != tagname) {
-        parent = parent.parentNode;
-        // Next line is a safety belt
-        if(parent.tagName.toUpperCase() == "BODY") 
-            return null;
-    }
-
-    return parent;
-}
-
-
-// function to open the popup window
-function getOrderIndex(currnode) {
-    if (typeof(dataGridFieldFunctions) == "object") {
-        var rows = dataGridFieldFunctions.getWidgetRows(currnode);
-	var row = dataGridFieldFunctions.getParentElementById(currnode, "datagridwidget-row");      
-	if(row == null) {
-	    alert("Couldn't find DataGridWidget row");
-	    return;
-	}
-
-	var idx = null
-
-	// We can't use nextSibling because of blank text nodes in some browsers
-	// Need to find the index of the row
-	for(var t = 0; t < rows.length; t++) {
-	    if(rows[t] == row) {
-		idx = t;
-		break;
-	    }
-	}
-
-	// Abort if the current row wasn't found
-	if(idx == null)
-	    return;
-        return idx;
-    }
-    return;
-}
-
-function getOrderedElement(widget_id, order_idx) {
-    // First get first element for the current field
-    var element=document.getElementById(widget_id);
-
-    // If it is about DataGridField use it to chose correct element
-    if (typeof(dataGridFieldFunctions) == "object" && order_idx >= 0) {
-        var rows = dataGridFieldFunctions.getWidgetRows(element);
-        if (rows.length >= order_idx) {
-            var row = rows[order_idx]
-            var inputs = row.getElementsByTagName("input")
-            for (var i=0;i<=inputs.length;i++) {
-		if (inputs[i].id == widget_id) {
-		    element = inputs[i];
-                    break;
-		}
+jq(function() {
+
+  // the overlay itself
+  jq('.addreference').overlay({
+       closeOnClick: false,
+       onBeforeLoad: function() {
+           ov = jq('div#content').data('overlay');
+           // close overlay, if there is one already
+           // we only allow one referencebrowser per time
+           if (ov) {ov.close(); }
+           var wrap = this.getContent().find('.overlaycontent');
+           var src = this.getTrigger().attr('src');
+           var srcfilter = src + ' >*';
+           wrap.data('srcfilter', srcfilter);
+           jq('div#content').data('overlay', this);
+           resetHistory();
+           wrap.load(srcfilter);
+           },
+       onLoad: function() {
+           widget_id = this.getTrigger().attr('rel').substring(6);
+           disablecurrentrelations(widget_id);
+       }});
+
+  // the breadcrumb-links and the links of the 'tree'-navigation
+  jq('[id^=atrb_] a.browsesite').live('click', function(event) {
+      var target = jq(this);
+      var src = target.attr('href');
+      var wrap = target.parents('.overlaycontent');
+      var srcfilter = src + ' >*';
+      pushToHistory(wrap.data('srcfilter'));
+      wrap.data('srcfilter', srcfilter);
+      // the history we are constructing here is destinct from the
+      // srcfilter-history. here we construct a selection-widget, which
+      // is available, if the history_length-parameter is set on the widget
+      // the srcfilter-history is used for storing the URLs to make the
+      // 'Back'-link work.
+      var newoption = '<option value="' + src + '">' + target.attr('rel') + '</option>';
+      refreshOverlay(wrap, srcfilter, newoption);
+      return false;
+      });
+
+  // the links for inserting referencens
+  jq('[id^=atrb_] input.insertreference').live('click', function(event) {
+      var target = jq(this);
+      var wrap = target.parents('.overlaycontent');
+      var fieldname = wrap.find('input[name=fieldName]').attr('value');
+      var multi = wrap.find('input[name=multiValued]').attr('value');
+      var close_window = wrap.find('input[name=close_window]').attr('value');
+      var title = target.parents('tr').find('img').attr('alt');
+      var uid = target.attr('rel');
+      refbrowser_setReference(fieldname, uid, title, parseInt(multi));
+      if (close_window === '1') {
+          overlay = jq('div#content').data('overlay');
+          overlay.close();
+      } else {
+          showMessage(title);
+      };
+      jq(this).attr('disabled', 'disabled');
+      });
+
+
+  // the history menu
+  jq('[id^=atrb_] form#history select[name=path]').live('change', function(event) {
+      var target = jq(this);
+      var wrap = target.parents('.overlaycontent');
+      src = jq('[id^=atrb_] form#history select[name=path] :selected').attr('value');
+      var srcfilter = src + ' >*';
+      refreshOverlay(wrap, srcfilter, '');
+      return false;
+      });
+
+  // the search form
+  jq('[id^=atrb_] form#search input[name=submit]').live('click', function(event) {
+      var target = jq(this);
+      var src = target.parents('form').attr('action');
+      var wrap = target.parents('.overlaycontent');
+      var fieldname = wrap.find('input[name=fieldName]').attr('value');
+      var fieldrealname = wrap.find('input[name=fieldRealName]').attr('value');
+      var at_url = wrap.find('input[name=at_url]').attr('value');
+      var searchvalue = wrap.find('input[name=searchValue]').attr('value');
+      var multi = wrap.find('input[name=multiValued]').attr('value');
+      var close_window = wrap.find('input[name=close_window]').attr('value');
+      qs = 'searchValue=' + searchvalue + '&fieldRealName=' + fieldrealname +
+        '&fieldName=' + fieldname + '&multiValued=' + multi +
+        '&close_window' + close_window + '&at_url=' + at_url;
+      var srcfilter = src + '?' + qs + ' >*';
+      pushToHistory(wrap.data('srcfilter'));
+      wrap.data('srcfilter', srcfilter);
+      refreshOverlay(wrap, srcfilter, '');
+      return false;
+      });
+
+});
+
+function disablecurrentrelations (widget_id) {
+   jq('ul#' + widget_id + ' :input').each(
+       function (intIndex) {
+         uid = jq(this).attr('value');
+         cb = jq('input[rel=' + uid + ']');
+         cb.attr('disabled', 'disabled');
+         cb.attr('checked', 'checked');
+       });
+}
+
+// function to return a reference from the popup window back into the widget
+function refbrowser_setReference(widget_id, uid, label, multi)
+{
+    var element = null,
+        label_element = null,
+        current_values = null,
+        i = null,
+        list = null,
+        li = null,
+        input = null,
+        up_element = null,
+        down_element = null,
+        container = null;
+    // differentiate between the single and mulitselect widget
+    // since the single widget has an extra label field.
+    if (multi === 0) {
+        jq('#' + widget_id).attr('value', uid);
+        jq('#' + widget_id + '_label').attr('value', label);
+    }  else {
+        // check if the item isn't already in the list
+        current_values = jq('#' + widget_id + ' input');
+        for (i = 0; i < current_values.length; i++) {
+            if (current_values[i].value === uid) {
+                return false;
             }
         }
-    }
-    return element;
-}
-
-
-function referencebrowser_openBrowser(path, fieldName, at_url, fieldRealName, fieldTitleName, fieldLinkName, currnode) {
-    var url = path + '/referencebrowser_popup?fieldName=' + fieldName + '&fieldRealName=' + fieldRealName +'&at_url=' + at_url;
-
-    var order_idx = getOrderIndex(currnode);
-    url += (order_idx)? '&order_idx=' + order_idx: "";
-    url += (typeof(fieldTitleName) != 'undefined')? '&fieldTitleName=' + fieldTitleName: "";
-    url += (typeof(fieldLinkName) != 'undefined')? '&fieldLinkName=' + fieldLinkName: "";
-
-    atrefpopup = window.open(url, 'referencebrowser_popup','toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=500,height=550');
-}
-
-// function for Array detecting
-function typeOf(value) {
-    var s = typeof value;
-    if (s === 'object') {
-        if (value) {
-            if (value instanceof Array) {
-                s = 'array';
+        // now add the new item
+        list = document.getElementById(widget_id);
+        // add ul-element to DOM, if it is not there
+        if (list === null) {
+            container = jq('#archetypes-fieldname-' + widget_id + ' input + div');
+            if (!container.length) {
+                // fix for Plone 3.3 collections, with a weird widget-id
+                container = jq('#archetypes-fieldname-value input + div');
             }
-        } else {
-            s = 'null';
-        }
-    }
-    return s;
-}
-
-// function to return a reference from the popup window back into the widget
-function referencebrowser_setReference(widget_id, uid, label, multi, order_idx, widget_title_id, link_title, widget_link_id, link_path)
-{
-    if (order_idx >= 0) {
-        // process ReferenceDataGridField
-        uid_element=getOrderedElement(widget_id, order_idx);
-        uid_element.value=uid;
-        title_element=getOrderedElement(widget_title_id, order_idx);
-        title_element.value=link_title;
-        title_element.className="not-changed-title-field";
-        title_element.setAttribute("default_value", link_title);
-        addEvent(title_element, 'blur', triggerTitleClass, false)
-        addEvent(title_element, 'focus', triggerOnFocusStyles, false)
-        link_element=getOrderedElement(widget_link_id, order_idx);
-        link_element.readOnly=false;
-        link_element.value=link_path;
-        link_element.readOnly=true;
-        link_element.className="hidden-field"
-    } else if (multi==0) {
-	// differentiate between the single and mulitselect widget
-	// since the single widget has an extra label field.
-        element=document.getElementById(widget_id);
-        label_element=document.getElementById(widget_id + '_label');
-        element.value=uid;
-        label_element.value=label;
-    } else {
-         // check if the item isn't already in the list
-         var current_values = cssQuery('#' + widget_id + ' input');
-         for (var i=0; i < current_values.length; i++) {
-            if (current_values[i].value == uid) {
+            container.after(
+               '<ul class="visualNoMarker" id="' + widget_id + '"></ul>');
+            list = document.getElementById(widget_id);
+        }
+        li = document.createElement('li');
+        label_element = document.createElement('label');
+        input = document.createElement('input');
+        input.type = 'checkbox';
+        input.value = uid;
+        input.checked = true;
+        input.name = widget_id + ':list';
+        label_element.appendChild(input);
+        label_element.appendChild(document.createTextNode(' ' + label));
+        li.appendChild(label_element);
+        li.id = 'ref-' + widget_id + '-' + current_values.length;
+
+        sortable = jq('input[name=' + widget_id + '-sortable]').attr('value');
+        if (sortable === '1') {
+          up_element = document.createElement('a');
+          up_element.title = 'Move Up';
+          up_element.innerHTML = '&#x25b2;';
+          up_element.onclick = function () {
+              refbrowser_moveReferenceUp(this);
               return false;
-            }
-          }         
-          // now add the new item
-          list=document.getElementById(widget_id);
-          li = document.createElement('li');
-          label_element = document.createElement('label');
-          input = document.createElement('input');
-          input.type = 'checkbox';
-          input.value = uid;
-          input.checked = true;
-          input.name = widget_id + ':list';
-          label_element.appendChild(input);
-          label_element.appendChild(document.createTextNode(label));
-          li.appendChild(label_element);
-          list.appendChild(li);
-          // fix on IE7 - check *after* adding to DOM
-          input.checked = true;
+          };
+
+          li.appendChild(up_element);
+
+          down_element = document.createElement('a');
+          down_element.title = 'Move Down';
+          down_element.innerHTML = '&#x25bc;';
+          down_element.onclick = function () {
+              refbrowser_moveReferenceDown(this);
+              return false;
+          };
+
+          li.appendChild(down_element);
+        }
+        list.appendChild(li);
+
+        // fix on IE7 - check *after* adding to DOM
+        input.checked = true;
     }
 }
@@ -214,23 +185,155 @@
 // function to clear the reference field or remove items
 // from the multivalued reference list.
-function referencebrowser_removeReference(widget_id, multi)
+function refbrowser_removeReference(widget_id, multi)
 {
+    var x = null,
+        element = null,
+        label_element = null,
+        list = null;
+
     if (multi) {
-        list=document.getElementById(widget_id)
-        for (var x=list.length-1; x >= 0; x--) {
-          if (list[x].selected) {
-            list[x]=null;
-          }
-        }
-        for (var x=0; x < list.length; x++) {
-            list[x].selected='selected';
-          }        
+        list = document.getElementById(widget_id);
+        for (x = list.length - 1; x >= 0; x--) {
+            if (list[x].selected) {
+                list[x] = null;
+            }
+        }
+        for (x = 0; x < list.length; x++) {
+            list[x].selected = 'selected';
+        }
     } else {
-        element=document.getElementById(widget_id);
-        label_element=document.getElementById(widget_id + '_label');
-        label_element.value = "";
-        element.value="";
-    }
-}
-
-
+        jq('#' + widget_id).attr('value', "");
+        jq('#' + widget_id + '_label').attr('value', "");
+    }
+}
+
+function refbrowser_moveReferenceUp(self)
+{
+    var elem = self.parentNode,
+        eid = null,
+        pos = null,
+        widget_id = null,
+        newelem = null,
+        prevelem = null,
+        arrows = null,
+        cbs = null;
+    if (elem === null) {
+        return false;
+    }
+    eid = elem.id.split('-');
+    pos = eid.pop();
+    if (pos === 0) {
+        return false;
+    }
+    widget_id = eid.pop();
+    newelem = elem.cloneNode(true);
+
+    //Fix: (IE keep the standard value)
+    cbs = newelem.getElementsByTagName("input");
+    if (cbs.length > 0) {
+        cbs[0].checked = elem.getElementsByTagName("input")[0].checked;
+    }
+
+    prevelem = document.getElementById('ref-' + widget_id + '-' + (pos - 1));
+
+    // up arrow
+    arrows = newelem.getElementsByTagName("a");
+    arrows[0].onclick = function () {
+        refbrowser_moveReferenceUp(this);
+    };
+    // down arrow
+    arrows[1].onclick = function () {
+        refbrowser_moveReferenceDown(this);
+    };
+
+    elem.parentNode.insertBefore(newelem, prevelem);
+    elem.parentNode.removeChild(elem);
+    newelem.id = 'ref-' + widget_id + '-' + (pos - 1);
+    prevelem.id = 'ref-' + widget_id + '-' + pos;
+}
+
+function refbrowser_moveReferenceDown(self)
+{
+    var elem = self.parentNode,
+        eid = null,
+        pos = null,
+        widget_id = null,
+        current_values = null,
+        newelem = null,
+        nextelem = null,
+        cbs = null,
+        arrows = null;
+    if (elem === null) {
+        return false;
+    }
+    eid = elem.id.split('-');
+    pos = parseInt(eid.pop(), 10);
+    widget_id = eid.pop();
+    current_values = jq('#' + widget_id + ' input');
+    if ((pos + 1) === current_values.length) {
+        return false;
+    }
+
+    newelem = elem.cloneNode(true);
+    //Fix: (IE keep the standard value)
+    cbs = newelem.getElementsByTagName("input");
+    if (cbs.length > 0) {
+        cbs[0].checked = elem.getElementsByTagName("input")[0].checked;
+    }
+
+    // up img
+    arrows = newelem.getElementsByTagName("a");
+    arrows[0].onclick = function () {
+        refbrowser_moveReferenceUp(this);
+    };
+    // down img
+    arrows[1].onclick = function () {
+        refbrowser_moveReferenceDown(this);
+    };
+
+    nextelem = document.getElementById('ref-' + widget_id + '-' + (pos + 1));
+
+    elem.parentNode.insertBefore(newelem, nextelem.nextSibling);
+    elem.parentNode.removeChild(elem);
+    newelem.id = 'ref-' + widget_id + '-' + (pos + 1);
+    nextelem.id = 'ref-' + widget_id + '-' + pos;
+}
+
+function showMessage(message) {
+    jq('#messageTitle').text(message);
+    jq('#message').show();
+}
+
+function submitHistoryForm() {
+     var form = document.history;
+     var path = form.path.options[form.path.selectedIndex].value;
+     form.action = path;
+     form.submit();
+}
+
+function pushToHistory(url) {
+  var history = jq(document).data('atrb_history');
+  history.push(url);
+  jq(document).data('atrb_history', history);
+}
+
+function resetHistory() {
+  jq(document).data('atrb_history', []);
+}
+
+function popFromHistory() {
+  var history = jq(document).data('atrb_history');
+  value = history.pop();
+  jq(document).data('atrb_history', history);
+  return value;
+}
+
+function refreshOverlay(wrap, srcfilter, newoption) {
+    var oldhistory = jq('[id^=atrb_] form#history select');
+    wrap.load(srcfilter, function() { 
+        jq('[id^=atrb_] form#history select').append(newoption + oldhistory.html());
+        ov = jq('div#content').data('overlay');
+        widget_id = ov.getTrigger().attr('rel').substring(6);
+        disablecurrentrelations(widget_id);
+        });
+}
