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