You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

query.js 9.8 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. (function($){
  2. window.initializeFilters = function() {
  3. // Bail early for Konqueror and IE5.2/Mac, which don't fully support dynamic
  4. // creation of form controls
  5. try {
  6. var test = document.createElement("input");
  7. test.type = "button";
  8. if (test.type != "button") throw Error();
  9. } catch (e) {
  10. return;
  11. }
  12. // Removes an existing row from the filters table
  13. function removeRow(button, propertyName) {
  14. var tr = getAncestorByTagName(button, "tr");
  15. var mode = null;
  16. var selects = tr.getElementsByTagName("select");
  17. for (var i = 0; i < selects.length; i++) {
  18. if (selects[i].name == propertyName + "_mode") {
  19. mode = selects[i];
  20. break;
  21. }
  22. }
  23. if (mode && (getAncestorByTagName(mode, "tr") == tr)) {
  24. // Check whether there are more 'or' rows for this filter
  25. var next = tr.nextSibling;
  26. if (next && (next.className == propertyName)) {
  27. function getChildElementAt(e, idx) {
  28. e = e.firstChild;
  29. var cur = 0;
  30. while (cur <= idx) {
  31. while (e && e.nodeType != 1) e = e.nextSibling;
  32. if (cur++ == idx) break;
  33. e = e.nextSibling;
  34. }
  35. return e;
  36. }
  37. var thisTh = getChildElementAt(tr, 0);
  38. var nextTh = getChildElementAt(next, 0);
  39. next.insertBefore(thisTh, nextTh);
  40. nextTh.colSpan = 1;
  41. thisTd = getChildElementAt(tr, 0);
  42. nextTd = getChildElementAt(next, 1);
  43. next.replaceChild(thisTd, nextTd);
  44. }
  45. }
  46. var tBody = tr.parentNode;
  47. tBody.deleteRow(tr.sectionRowIndex);
  48. if (!tBody.rows.length) {
  49. tBody.parentNode.removeChild(tBody);
  50. }
  51. if (propertyName) {
  52. var select = document.forms["query"].elements["add_filter"];
  53. for (var i = 0; i < select.options.length; i++) {
  54. var option = select.options[i];
  55. if (option.value == propertyName) option.disabled = false;
  56. }
  57. }
  58. }
  59. // Initializes a filter row, the 'input' parameter is the submit
  60. // button for removing the filter
  61. function initializeFilter(input) {
  62. var removeButton = document.createElement("input");
  63. removeButton.type = "button";
  64. removeButton.value = input.value;
  65. if (input.name.substr(0, 10) == "rm_filter_") {
  66. removeButton.onclick = function() {
  67. var endIndex = input.name.search(/_\d+$/);
  68. if (endIndex < 0) endIndex = input.name.length;
  69. removeRow(removeButton, input.name.substring(10, endIndex));
  70. return false;
  71. }
  72. } else {
  73. removeButton.onclick = function() {
  74. removeRow(removeButton);
  75. return false;
  76. }
  77. }
  78. input.parentNode.replaceChild(removeButton, input);
  79. }
  80. // Make the submit buttons for removing filters client-side triggers
  81. var filters = document.getElementById("filters");
  82. var inputs = filters.getElementsByTagName("input");
  83. for (var i = 0; i < inputs.length; i++) {
  84. var input = inputs[i];
  85. if (input.type == "submit" && input.name
  86. && input.name.match(/^rm_filter_/)) {
  87. initializeFilter(input);
  88. }
  89. }
  90. // Make the drop-down menu for adding a filter a client-side trigger
  91. var addButton = document.forms["query"].elements["add"];
  92. addButton.parentNode.removeChild(addButton);
  93. var select = document.getElementById("add_filter");
  94. select.onchange = function() {
  95. if (select.selectedIndex < 1) return;
  96. if (select.options[select.selectedIndex].disabled) {
  97. // Neither IE nor Safari supported disabled options at the time this was
  98. // written, so alert the user
  99. alert("A filter already exists for that property");
  100. return;
  101. }
  102. // Convenience function for creating a <label>
  103. function createLabel(text, htmlFor) {
  104. var label = document.createElement("label");
  105. if (text) label.appendChild(document.createTextNode(text));
  106. if (htmlFor) label.htmlFor = htmlFor;
  107. return label;
  108. }
  109. // Convenience function for creating an <input type="checkbox">
  110. function createCheckbox(name, value, id) {
  111. var input = document.createElement("input");
  112. input.type = "checkbox";
  113. if (name) input.name = name;
  114. if (value) input.value = value;
  115. if (id) input.id = id;
  116. return input;
  117. }
  118. // Convenience function for creating an <input type="radio">
  119. function createRadio(name, value, id) {
  120. var str = '<input type="radio"';
  121. if (name) str += ' name="' + name + '"';
  122. if (value) str += ' value="' + value + '"';
  123. if (id) str += ' id="' + id + '"';
  124. str += '/>';
  125. var span = document.createElement('span');
  126. // create radio button with innerHTML to avoid IE mangling it.
  127. span.innerHTML = str;
  128. return span;
  129. }
  130. // Convenience function for creating a <select>
  131. function createSelect(name, options, optional) {
  132. var e = document.createElement("select");
  133. if (name) e.name = name;
  134. if (optional) e.options[0] = new Option();
  135. if (options) {
  136. for (var i = 0; i < options.length; i++) {
  137. var option;
  138. if (typeof(options[i]) == "object") {
  139. option = new Option(options[i].text, options[i].value);
  140. } else {
  141. option = new Option(options[i], options[i]);
  142. }
  143. e.options[e.options.length] = option;
  144. }
  145. }
  146. return e;
  147. }
  148. var propertyName = select.options[select.selectedIndex].value;
  149. var property = properties[propertyName];
  150. var table = document.getElementById("filters").getElementsByTagName("table")[0];
  151. var tr = document.createElement("tr");
  152. tr.className = propertyName;
  153. var alreadyPresent = false;
  154. for (var i = 0; i < table.rows.length; i++) {
  155. if (table.rows[i].className == propertyName) {
  156. var existingTBody = table.rows[i].parentNode;
  157. alreadyPresent = true;
  158. break;
  159. }
  160. }
  161. // Add the row header
  162. var th = document.createElement("th");
  163. th.scope = "row";
  164. if (!alreadyPresent) {
  165. th.appendChild(createLabel(property.label));
  166. } else {
  167. th.colSpan = 2;
  168. th.appendChild(createLabel("or"));
  169. }
  170. tr.appendChild(th);
  171. var td = document.createElement("td");
  172. if (property.type == "radio" || property.type == "checkbox") {
  173. td.colSpan = 2;
  174. td.className = "filter";
  175. if (property.type == "radio") {
  176. for (var i = 0; i < property.options.length; i++) {
  177. var option = property.options[i];
  178. td.appendChild(createCheckbox(propertyName, option,
  179. propertyName + "_" + option));
  180. td.appendChild(createLabel(option ? option : "none",
  181. propertyName + "_" + option));
  182. }
  183. } else {
  184. td.appendChild(createRadio(propertyName, "1", propertyName + "_on"));
  185. td.appendChild(document.createTextNode(" "));
  186. td.appendChild(createLabel("yes", propertyName + "_on"));
  187. td.appendChild(createRadio(propertyName, "0", propertyName + "_off"));
  188. td.appendChild(document.createTextNode(" "));
  189. td.appendChild(createLabel("no", propertyName + "_off"));
  190. }
  191. tr.appendChild(td);
  192. } else {
  193. if (!alreadyPresent) {
  194. // Add the mode selector
  195. td.className = "mode";
  196. var modeSelect = createSelect(propertyName + "_mode",
  197. modes[property.type]);
  198. td.appendChild(modeSelect);
  199. tr.appendChild(td);
  200. }
  201. // Add the selector or text input for the actual filter value
  202. td = document.createElement("td");
  203. td.className = "filter";
  204. if (property.type == "select") {
  205. var element = createSelect(propertyName, property.options, true);
  206. } else if (property.type == "text") {
  207. var element = document.createElement("input");
  208. element.type = "text";
  209. element.name = propertyName;
  210. element.size = 42;
  211. }
  212. td.appendChild(element);
  213. element.focus();
  214. tr.appendChild(td);
  215. }
  216. // Add the add and remove buttons
  217. td = document.createElement("td");
  218. td.className = "actions";
  219. var removeButton = document.createElement("input");
  220. removeButton.type = "button";
  221. removeButton.value = "-";
  222. removeButton.onclick = function() { removeRow(removeButton, propertyName) };
  223. td.appendChild(removeButton);
  224. tr.appendChild(td);
  225. if (alreadyPresent) {
  226. existingTBody.appendChild(tr);
  227. } else {
  228. // Find the insertion point for the new row. We try to keep the filter rows
  229. // in the same order as the options in the 'Add filter' drop-down, because
  230. // that's the order they'll appear in when submitted.
  231. var insertionPoint = getAncestorByTagName(select, "tbody");
  232. outer: for (var i = select.selectedIndex + 1; i < select.options.length; i++) {
  233. for (var j = 0; j < table.tBodies.length; j++) {
  234. if (table.tBodies[j].rows[0].className == select.options[i].value) {
  235. insertionPoint = table.tBodies[j];
  236. break outer;
  237. }
  238. }
  239. }
  240. // Finally add the new row to the table
  241. var tbody = document.createElement("tbody");
  242. tbody.appendChild(tr);
  243. insertionPoint.parentNode.insertBefore(tbody, insertionPoint);
  244. }
  245. // Disable the add filter in the drop-down list
  246. if (property.type == "radio" || property.type == "checkbox") {
  247. select.options[select.selectedIndex].disabled = true;
  248. }
  249. select.selectedIndex = 0;
  250. }
  251. }
  252. })(jQuery);