Blame Identity/Models/Html/Trac/htdocs/js/query.js

d6e8d8
function initializeFilters() {
d6e8d8
d6e8d8
  // Bail early for Konqueror and IE5.2/Mac, which don't fully support dynamic
d6e8d8
  // creation of form controls
d6e8d8
  try {
d6e8d8
    var test = document.createElement("input");
d6e8d8
    test.type = "button";
d6e8d8
    if (test.type != "button") throw Error();
d6e8d8
  } catch (e) {
d6e8d8
    return;
d6e8d8
  }
d6e8d8
d6e8d8
  // Removes an existing row from the filters table
d6e8d8
  function removeRow(button, propertyName) {
d6e8d8
    var tr = getAncestorByTagName(button, "tr");
d6e8d8
d6e8d8
    var mode = null;
d6e8d8
    var selects = tr.getElementsByTagName("select");
d6e8d8
    for (var i = 0; i < selects.length; i++) {
d6e8d8
      if (selects[i].name == propertyName + "_mode") {
d6e8d8
        mode = selects[i];
d6e8d8
        break;
d6e8d8
      }
d6e8d8
    }
d6e8d8
    if (mode && (getAncestorByTagName(mode, "tr") == tr)) {
d6e8d8
      // Check whether there are more 'or' rows for this filter
d6e8d8
      var next = tr.nextSibling;
d6e8d8
      if (next && (next.className == propertyName)) {
d6e8d8
        function getChildElementAt(e, idx) {
d6e8d8
          e = e.firstChild;
d6e8d8
          var cur = 0;
d6e8d8
          while (cur <= idx) {
d6e8d8
            while (e && e.nodeType != 1) e = e.nextSibling;
d6e8d8
            if (cur++ == idx) break;
d6e8d8
            e = e.nextSibling;
d6e8d8
          }
d6e8d8
          return e;
d6e8d8
        }
d6e8d8
d6e8d8
        var thisTh = getChildElementAt(tr, 0);
d6e8d8
        var nextTh = getChildElementAt(next, 0);
d6e8d8
        next.insertBefore(thisTh, nextTh);
d6e8d8
        nextTh.colSpan = 1;
d6e8d8
d6e8d8
        thisTd = getChildElementAt(tr, 0);
d6e8d8
        nextTd = getChildElementAt(next, 1);
d6e8d8
        next.replaceChild(thisTd, nextTd);
d6e8d8
      }
d6e8d8
    }
d6e8d8
d6e8d8
    var tBody = tr.parentNode;
d6e8d8
    tBody.deleteRow(tr.sectionRowIndex);
d6e8d8
    if (!tBody.rows.length) {
d6e8d8
        tBody.parentNode.removeChild(tBody);
d6e8d8
    }
d6e8d8
    
d6e8d8
    if (propertyName) {
d6e8d8
      var select = document.forms["query"].elements["add_filter"];
d6e8d8
      for (var i = 0; i < select.options.length; i++) {
d6e8d8
        var option = select.options[i];
d6e8d8
        if (option.value == propertyName) option.disabled = false;
d6e8d8
      }
d6e8d8
    }
d6e8d8
  }
d6e8d8
d6e8d8
  // Initializes a filter row, the 'input' parameter is the submit
d6e8d8
  // button for removing the filter
d6e8d8
  function initializeFilter(input) {
d6e8d8
    var removeButton = document.createElement("input");
d6e8d8
    removeButton.type = "button";
d6e8d8
    removeButton.value = input.value;
d6e8d8
    if (input.name.substr(0, 10) == "rm_filter_") {
d6e8d8
      removeButton.onclick = function() {
d6e8d8
        var endIndex = input.name.search(/_\d+$/);
d6e8d8
        if (endIndex < 0) endIndex = input.name.length;
d6e8d8
        removeRow(removeButton, input.name.substring(10, endIndex));
d6e8d8
        return false;
d6e8d8
      }
d6e8d8
    } else {
d6e8d8
      removeButton.onclick = function() {
d6e8d8
        removeRow(removeButton);
d6e8d8
        return false;
d6e8d8
      }
d6e8d8
    }
d6e8d8
    input.parentNode.replaceChild(removeButton, input);
d6e8d8
  }
d6e8d8
d6e8d8
  // Make the submit buttons for removing filters client-side triggers
d6e8d8
  var filters = document.getElementById("filters");
d6e8d8
  var inputs = filters.getElementsByTagName("input");
d6e8d8
  for (var i = 0; i < inputs.length; i++) {
d6e8d8
    var input = inputs[i];
d6e8d8
    if (input.type == "submit" && input.name
d6e8d8
     && input.name.match(/^rm_filter_/)) {
d6e8d8
      initializeFilter(input);
d6e8d8
    }
d6e8d8
  }
d6e8d8
d6e8d8
  // Make the drop-down menu for adding a filter a client-side trigger
d6e8d8
  var addButton = document.forms["query"].elements["add"];
d6e8d8
  addButton.parentNode.removeChild(addButton);
d6e8d8
  var select = document.getElementById("add_filter");
d6e8d8
  select.onchange = function() {
d6e8d8
    if (select.selectedIndex < 1) return;
d6e8d8
d6e8d8
    if (select.options[select.selectedIndex].disabled) {
d6e8d8
      // Neither IE nor Safari supported disabled options at the time this was
d6e8d8
      // written, so alert the user
d6e8d8
      alert("A filter already exists for that property");
d6e8d8
      return;
d6e8d8
    }
d6e8d8
d6e8d8
    // Convenience function for creating a <label>
d6e8d8
    function createLabel(text, htmlFor) {
d6e8d8
      var label = document.createElement("label");
d6e8d8
      if (text) label.appendChild(document.createTextNode(text));
d6e8d8
      if (htmlFor) label.htmlFor = htmlFor;
d6e8d8
      return label;
d6e8d8
    }
d6e8d8
d6e8d8
    // Convenience function for creating an <input type="checkbox">
d6e8d8
    function createCheckbox(name, value, id) {
d6e8d8
      var input = document.createElement("input");
d6e8d8
      input.type = "checkbox";
d6e8d8
      if (name) input.name = name;
d6e8d8
      if (value) input.value = value;
d6e8d8
      if (id) input.id = id;
d6e8d8
      return input;
d6e8d8
    }
d6e8d8
d6e8d8
    // Convenience function for creating an <input type="radio">
d6e8d8
    function createRadio(name, value, id) {
d6e8d8
      var input = document.createElement("input");
d6e8d8
      input.type = "radio";
d6e8d8
      if (name) input.name = name;
d6e8d8
      if (value) input.value = value;
d6e8d8
      if (id) input.id = id;
d6e8d8
      return input;
d6e8d8
    }
d6e8d8
d6e8d8
    // Convenience function for creating a <select>
d6e8d8
    function createSelect(name, options, optional) {
d6e8d8
      var e = document.createElement("select");
d6e8d8
      if (name) e.name = name;
d6e8d8
      if (optional) e.options[0] = new Option();
d6e8d8
      if (options) {
d6e8d8
        for (var i = 0; i < options.length; i++) {
d6e8d8
          var option;
d6e8d8
          if (typeof(options[i]) == "object") {
d6e8d8
            option = new Option(options[i].text, options[i].value);
d6e8d8
          } else {
d6e8d8
            option = new Option(options[i], options[i]);
d6e8d8
          }
d6e8d8
          e.options[e.options.length] = option;
d6e8d8
        }
d6e8d8
      }
d6e8d8
      return e;
d6e8d8
    }
d6e8d8
d6e8d8
    var propertyName = select.options[select.selectedIndex].value;
d6e8d8
    var property = properties[propertyName];
d6e8d8
    var table = document.getElementById("filters").getElementsByTagName("table")[0];
d6e8d8
    var tr = document.createElement("tr");
d6e8d8
    tr.className = propertyName;
d6e8d8
d6e8d8
    var alreadyPresent = false;
d6e8d8
    for (var i = 0; i < table.rows.length; i++) {
d6e8d8
      if (table.rows[i].className == propertyName) {
d6e8d8
        var existingTBody = table.rows[i].parentNode;
d6e8d8
        alreadyPresent = true;
d6e8d8
        break;
d6e8d8
      }
d6e8d8
    }
d6e8d8
d6e8d8
    // Add the row header
d6e8d8
    var th = document.createElement("th");
d6e8d8
    th.scope = "row";
d6e8d8
    if (!alreadyPresent) {
d6e8d8
      th.appendChild(createLabel(property.label));
d6e8d8
    } else {
d6e8d8
      th.colSpan = 2;
d6e8d8
      th.appendChild(createLabel("or"));
d6e8d8
    }
d6e8d8
    tr.appendChild(th);
d6e8d8
d6e8d8
    var td = document.createElement("td");
d6e8d8
    if (property.type == "radio" || property.type == "checkbox") {
d6e8d8
      td.colSpan = 2;
d6e8d8
      td.className = "filter";
d6e8d8
      if (property.type == "radio") {
d6e8d8
        for (var i = 0; i < property.options.length; i++) {
d6e8d8
          var option = property.options[i];
d6e8d8
          td.appendChild(createCheckbox(propertyName, option,
d6e8d8
            propertyName + "_" + option));
d6e8d8
          td.appendChild(document.createTextNode(" "));
d6e8d8
          td.appendChild(createLabel(option ? option : "none",
d6e8d8
            propertyName + "_" + option));
d6e8d8
        }
d6e8d8
      } else {
d6e8d8
        td.appendChild(createRadio(propertyName, "1", propertyName + "_on"));
d6e8d8
        td.appendChild(document.createTextNode(" "));
d6e8d8
        td.appendChild(createLabel("yes", propertyName + "_on"));
d6e8d8
        td.appendChild(createRadio(propertyName, "!1", propertyName + "_off"));
d6e8d8
        td.appendChild(document.createTextNode(" "));
d6e8d8
        td.appendChild(createLabel("no", propertyName + "_off"));
d6e8d8
      }
d6e8d8
      tr.appendChild(td);
d6e8d8
    } else {
d6e8d8
      if (!alreadyPresent) {
d6e8d8
        // Add the mode selector
d6e8d8
        td.className = "mode";
d6e8d8
        var modeSelect = createSelect(propertyName + "_mode",
d6e8d8
                                      modes[property.type]);
d6e8d8
        td.appendChild(modeSelect);
d6e8d8
        tr.appendChild(td);
d6e8d8
      }
d6e8d8
d6e8d8
      // Add the selector or text input for the actual filter value
d6e8d8
      td = document.createElement("td");
d6e8d8
      td.className = "filter";
d6e8d8
      if (property.type == "select") {
d6e8d8
        var element = createSelect(propertyName, property.options, true);
d6e8d8
      } else if (property.type == "text") {
d6e8d8
        var element = document.createElement("input");
d6e8d8
        element.type = "text";
d6e8d8
        element.name = propertyName;
d6e8d8
        element.size = 42;
d6e8d8
      }
d6e8d8
      td.appendChild(element);
d6e8d8
      element.focus();
d6e8d8
      tr.appendChild(td);
d6e8d8
    }
d6e8d8
d6e8d8
    // Add the add and remove buttons
d6e8d8
    td = document.createElement("td");
d6e8d8
    td.className = "actions";
d6e8d8
    var removeButton = document.createElement("input");
d6e8d8
    removeButton.type = "button";
d6e8d8
    removeButton.value = "-";
d6e8d8
    removeButton.onclick = function() { removeRow(removeButton, propertyName) };
d6e8d8
    td.appendChild(removeButton);
d6e8d8
    tr.appendChild(td);
d6e8d8
d6e8d8
    if (alreadyPresent) {
d6e8d8
      existingTBody.appendChild(tr);
d6e8d8
    } else {
d6e8d8
      // Find the insertion point for the new row. We try to keep the filter rows
d6e8d8
      // in the same order as the options in the 'Add filter' drop-down, because
d6e8d8
      // that's the order they'll appear in when submitted.
d6e8d8
      var insertionPoint = getAncestorByTagName(select, "tbody");
d6e8d8
      outer: for (var i = select.selectedIndex + 1; i < select.options.length; i++) {
d6e8d8
        for (var j = 0; j < table.tBodies.length; j++) {
d6e8d8
          if (table.tBodies[j].rows[0].className == select.options[i].value) {
d6e8d8
            insertionPoint = table.tBodies[j];
d6e8d8
            break outer;
d6e8d8
          }
d6e8d8
        }
d6e8d8
      }
d6e8d8
      // Finally add the new row to the table
d6e8d8
      var tbody = document.createElement("tbody");
d6e8d8
      tbody.appendChild(tr);
d6e8d8
      insertionPoint.parentNode.insertBefore(tbody, insertionPoint);
d6e8d8
    }
d6e8d8
d6e8d8
    // Disable the add filter in the drop-down list
d6e8d8
    if (property.type == "radio" || property.type == "checkbox") {
d6e8d8
      select.options[select.selectedIndex].disabled = true;
d6e8d8
    }
d6e8d8
    select.selectedIndex = 0;
d6e8d8
  }
d6e8d8
}