tabularForm.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /*##############################################################################
  2. # HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. ############################################################################## */
  16. var command;
  17. var component;
  18. var xmlDoc;
  19. var schemaNode;
  20. var objNode;
  21. var bAdd;
  22. function onLoad()
  23. {
  24. var form = document.forms[0];
  25. component = form.component.value;
  26. command = form.command.value;
  27. schemaNode = xmlSchema.documentElement.selectSingleNode('//Arguments');
  28. if (schemaNode == null)
  29. {
  30. alert('No arguments node found in XML schema!');
  31. return;
  32. }
  33. var prevArgsDoc = document.all.xmlPrevArgsDoc;
  34. if (prevArgsDoc != undefined && prevArgsDoc != null)
  35. {
  36. xmlDoc = prevArgsDoc;
  37. objNode = prevArgsDoc.documentElement;
  38. if (objNode == null)
  39. {
  40. bAdd = true;
  41. objNode = xmlDoc.createElement('Arguments');
  42. xmlDoc.documentElement.appendChild(objNode);
  43. }
  44. else
  45. {
  46. bAdd = false;
  47. initializeHtmlObjects(objNode, schemaNode);
  48. }
  49. }
  50. else
  51. {
  52. bAdd = true;
  53. //create xml fragment that would be passed to any child dialogs for them to fill in
  54. //and is sent back as hidden input field 'xmlArgs'
  55. xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
  56. xmlDoc.async = false;
  57. xmlDoc.loadXML('<Arguments/>');
  58. objNode = xmlDoc.documentElement.selectSingleNode('//Arguments');
  59. }
  60. }
  61. function onSubmit()
  62. {
  63. /*
  64. if (bAdd)
  65. {
  66. //add immediate children to our data island. Note that nested data is updated
  67. //as a result of add/delete handlers
  68. //
  69. if (!addImmediateChildrenFromHtmlObjects(schemaNode, objNode, xmlDoc))
  70. return false;
  71. }
  72. else
  73. replaceImmediateChildrenFromHtmlObjects(objNode. schemaNode);
  74. //update the value of our hidden HTML control that gets sent back with the submission
  75. //
  76. document.forms[0].xmlArgs.value = xmlDoc.xml;
  77. alert(xmlDoc.xml);
  78. */
  79. //alert(document.forms[0].outerHTML);
  80. return true;
  81. }
  82. function initializeHtmlObjects(objNode, schemaNode)
  83. {
  84. for (var childSchemaNode = schemaNode.firstChild;
  85. childSchemaNode != null;
  86. childSchemaNode = childSchemaNode.nextSibling)
  87. {
  88. var name = childSchemaNode.nodeName;
  89. var maxOccursAttr = childSchemaNode.attributes.getNamedItem('maxOccurs');
  90. var maxOccurs = maxOccursAttr ? maxOccursAttr.nodeValue : null;
  91. if (maxOccurs == "unbounded")
  92. {
  93. var argsTableObj = document.all.ArgumentsTable;
  94. var tableObj = argsTableObj.all[name];
  95. var targetNodes = objNode.selectNodes(name);
  96. //append rows in table
  97. var nNodes = targetNodes.length;
  98. var rowId = tableObj.rows.length;
  99. for (var i=0; i<nNodes; i++)
  100. insertRowInTable(tableObj, rowId++, targetNodes[i], childSchemaNode, name, true, false);
  101. }
  102. else
  103. {
  104. var htmlObj = document.forms[0].elements[name];
  105. var targetNode = objNode.selectSingleNode(name);
  106. var dataTypeAttr = childSchemaNode.attributes.getNamedItem('dataType');
  107. var dataType = dataTypeAttr ? dataTypeAttr.nodeValue : null;
  108. if (dataType)
  109. {
  110. if (dataType == 'boolean')
  111. {
  112. var checked = targetNode.text == '1';
  113. htmlObj.value = checked ? 1 : 0;
  114. if (checked)
  115. htmlObj.checked = 'true';
  116. }
  117. }
  118. else
  119. htmlObj.value = targetNode.text;
  120. }
  121. }
  122. }
  123. function addImmediateChildrenFromHtmlObjects(schemaNode, objNode, xmlDoc)
  124. {
  125. //keep xmlDoc in sync with contents of this page
  126. //so create elements corresponding to all immediate input fields
  127. for (var childSchemaNode = schemaNode.firstChild;
  128. childSchemaNode != null;
  129. childSchemaNode = childSchemaNode.nextSibling)
  130. {
  131. //only process nodes which don't have children since those would be processed
  132. //by add/delete/edit button handlers
  133. if (!childSchemaNode.hasChildNodes())
  134. {
  135. var name = childSchemaNode.nodeName;
  136. var newNode = xmlDoc.createElement(name);
  137. var htmlObj = document.forms[0].elements[name];
  138. //we may have already added this node if we had errored out
  139. //in last try. So only add if it does not exist.
  140. //
  141. if (!objNode.selectSingleNode(name))
  142. {
  143. newNode.text = htmlObj.value;
  144. objNode.appendChild(newNode);
  145. }
  146. }
  147. }
  148. return true;
  149. }
  150. function replaceImmediateChildrenFromHtmlObjects(objNode, schemaNode)
  151. {
  152. for (var childNode = objNode.firstChild;
  153. childNode != null;
  154. childNode = childNode.nextSibling)
  155. {
  156. var name = childNode.nodeName;
  157. if (childNode.selectSingleNode('*') == null)
  158. {
  159. var htmlObj = document.forms[0].elements[name];
  160. var schemaChildNode = schemaNode.selectSingleNode(name);
  161. var dataTypeAttr = schemaChildNode.attributes.getNamedItem('dataType');
  162. var dataType = dataTypeAttr ? dataTypeAttr.nodeValue : null;
  163. if (dataType)
  164. {
  165. if (dataType == 'boolean')
  166. childNode.text = htmlObj.checked ? '1' : '0';
  167. else
  168. childNode.text = htmlObj.value;
  169. }
  170. else
  171. childNode.text = htmlObj.value;
  172. }
  173. }
  174. }
  175. function isNumber(str)
  176. {
  177. return parseInt(str).toString()==str;
  178. }
  179. function updateNestedData(operation, strXPath, index)
  180. {
  181. //Get a pointer to the specific note to pass to the modal dialog.
  182. var targetNode;
  183. if (operation == "add")
  184. {
  185. var tokens = new Array();
  186. tokens = strXPath.split('.');
  187. //find out child node in xmlSchema (our schema) corresponding to the
  188. //node for which we would add the table row:
  189. //
  190. var childSchemaNode = schemaNode;
  191. var targetNode = objNode;
  192. for (var i=0; i<tokens.length; i++)
  193. if (!isNumber(tokens[i]))
  194. {
  195. childSchemaNode = childSchemaNode.selectSingleNode(tokens[i]);
  196. var newNode = xmlDoc.createElement(tokens[i]);
  197. targetNode = targetNode.appendChild(newNode);
  198. }
  199. var nodeName = targetNode.nodeName;
  200. var argsTableObj = document.all.ArgumentsTable;
  201. var tableName = strXPath;
  202. var tableObj = argsTableObj.all[tableName];
  203. var rowId = tableObj.rows.length;//row 0 is header
  204. insertRowInTable(tableObj, rowId, targetNode, childSchemaNode, strXPath, true, false);
  205. }
  206. else//delete
  207. {
  208. var objNodes = objNode.selectNodes(strXPath);
  209. targetNode = objNodes.item(index);
  210. if (targetNode == null)
  211. alert('No matching data available!');
  212. if (confirm('Are you sure you want to delete this item?'))
  213. {
  214. deleteRowFromTable(index+1, targetNode); //row 0 is header
  215. targetNode.parentNode.removeChild(targetNode);
  216. enableDeleteButton(strXPath+".Delete", false);
  217. }
  218. }
  219. return true;
  220. }
  221. function createTable(domNodes, schemaNode)
  222. {
  223. tableObj = document.createElement('table');
  224. tableObj.border = 1;
  225. //make header
  226. var rowId = 0;
  227. var row = tableObj.insertRow(rowId++);
  228. //insert checkbox header
  229. //col = row.insertCell();
  230. for (var childSchemaNode = schemaNode.firstChild;
  231. childSchemaNode != null;
  232. childSchemaNode = childSchemaNode.nextSibling)
  233. {
  234. var targetNode = domNodes[0].selectSingleNode(childSchemaNode.nodeName);
  235. var thObj = document.createElement('th');
  236. thObj.innerText = targetNode.nodeName;
  237. col = row.insertCell();
  238. col.appendChild(thObj);
  239. }
  240. var nNodes = domNodes.length;
  241. for (var i=0; i<nNodes; i++)
  242. insertRowInTable(tableObj, rowId++, domNodes[i], schemaNode, false, false);
  243. return tableObj;
  244. }
  245. function insertRowInTable(tableObj, rowId, domNode, schemaNode, strXPath, bDrawCheckBox, bChecked)
  246. {
  247. var nodeName = domNode.nodeName;
  248. var row = tableObj.insertRow(rowId);//insert after last row
  249. var lastRowIndex = tableObj.lastRowIndex ? parseInt(tableObj.lastRowIndex) + 1 : 0;
  250. tableObj.lastRowIndex = lastRowIndex.toString();
  251. row.id = strXPath + '.' + tableObj.lastRowIndex;
  252. updateItemList(tableObj, tableObj.lastRowIndex, null);
  253. if (bDrawCheckBox == true)
  254. {
  255. //insert checkbox
  256. var col = row.insertCell();
  257. //it isn't funny. better leave that trailing space if you wish to get
  258. //the checkbox created:
  259. var cbName = strXPath + ".checkbox";
  260. col.innerHTML = '<input type="checkbox" id="' + cbName + '" name="' + cbName + '" value=""' + (bChecked ? ' checked="true"' : '') + ' onclick="onCheck(this)"> ';
  261. }
  262. for (var childSchemaNode = schemaNode.firstChild;
  263. childSchemaNode != null;
  264. childSchemaNode = childSchemaNode.nextSibling)
  265. {
  266. var targetNode = domNode.selectSingleNode(childSchemaNode.nodeName);
  267. if (targetNode == null)
  268. {
  269. targetNode = xmlDoc.createElement(childSchemaNode.nodeName);
  270. domNode.appendChild(targetNode);
  271. }
  272. insertCellsInRow(row, targetNode, childSchemaNode, strXPath + '.' + tableObj.lastRowIndex);
  273. }
  274. return row;
  275. }
  276. function updateItemList(tableObj, addItem, delItem)
  277. {
  278. var id = tableObj.id + ".itemlist";
  279. var itemListInput = document.forms[0].all[id];
  280. if (itemListInput == null)
  281. {
  282. itemListInput = document.createElement("input");
  283. itemListInput.type = "hidden";
  284. itemListInput.id = id;
  285. itemListInput.name = id;
  286. itemListInput.value = "+";
  287. document.forms[0].appendChild( itemListInput );
  288. }
  289. if (addItem)
  290. itemListInput.value += addItem + '+';
  291. else
  292. {
  293. var list = itemListInput.value;
  294. var begin = list.indexOf('+' + delItem + '+');
  295. if (begin == -1)
  296. alert("Item list management error!");
  297. begin++;
  298. var end = list.indexOf('+', begin);
  299. if (end == -1)
  300. alert("Item list management error!");
  301. itemListInput.value = list.substring(0, begin) + list.substring(end+1);
  302. }
  303. }
  304. function insertCellsInRow(row, targetNode, schemaNode, strXPath)
  305. {
  306. var maxOccursAttr = schemaNode.attributes.getNamedItem('maxOccurs');
  307. var maxOccurs = maxOccursAttr ? maxOccursAttr.nodeValue : null;
  308. if (maxOccurs == "unbounded")
  309. {
  310. var targetNodes = domNode.selectNodes(childSchemaNode.nodeName);
  311. if (targetNodes != null && targetNodes.length > 0)
  312. {
  313. var tableObj = createTable(targetNodes, childSchemaNode);
  314. cell.appendChild(tableObj);
  315. }
  316. }
  317. else
  318. if (maxOccurs == "1" && schemaNode.selectNodes("*"))
  319. {
  320. var xpath = strXPath + '.' + schemaNode.nodeName;
  321. for (var childSchemaNode = schemaNode.firstChild;
  322. childSchemaNode != null;
  323. childSchemaNode = childSchemaNode.nextSibling)
  324. {
  325. var name = childSchemaNode.nodeName;
  326. var targetNode2 = targetNode.selectSingleNode(name);
  327. if (targetNode2 == null)
  328. {
  329. targetNode2 = xmlDoc.createElement(name);
  330. targetNode.appendChild(targetNode2);
  331. }
  332. insertCellsInRow(row, targetNode2, childSchemaNode, xpath);
  333. }
  334. }
  335. else
  336. {
  337. //create an HTML object corresponding to this element
  338. //
  339. var cell = row.insertCell();
  340. var input = createInputControlForNode(cell, strXPath, targetNode, schemaNode);
  341. cell.appendChild(input);
  342. }
  343. }
  344. function createInputControlForNode(cell, idPrefix, node, schemaNode)
  345. {
  346. var id = node.nodeName;
  347. var dataTypeAttr = schemaNode.attributes.getNamedItem('dataType');
  348. var dataType = dataTypeAttr ? dataTypeAttr.nodeValue : null;
  349. var value = node.text;
  350. if (value == null)
  351. {
  352. var defaultAttr = schemaNode.attributes.getNamedItem('default');
  353. value = defaultAttr ? defaultAttr.nodeValue : "";
  354. }
  355. var type;
  356. var checked = false;
  357. if (dataType == "boolean")
  358. {
  359. type = "checkbox";
  360. //debugger;
  361. if (value == "1" || value == "yes" || value=="true")
  362. {
  363. checked = true;
  364. value = "1";
  365. }
  366. else
  367. value = "0";
  368. }
  369. else
  370. {
  371. type = "text";
  372. value = value;
  373. }
  374. var input = document.createElement("input");
  375. input.name = idPrefix + '.' + id;
  376. input.type = type;
  377. input.value = value;
  378. if (type == "checkbox")
  379. {
  380. if (checked)
  381. input.checked = "true";
  382. input.onclick=function(){this.value=1-this.value;};
  383. }
  384. else
  385. input.width=cell.clientWidth ? cell.clientWidth-2 : 70;
  386. return input;
  387. }
  388. function deleteRowFromTable(rowId, domNode)
  389. {
  390. var argsTableObj = document.all.ArgumentsTable;
  391. var tableName = domNode.nodeName;
  392. var tableObj = argsTableObj.all[tableName];
  393. var id = tableObj.rows[rowId].id;
  394. var pos = id.lastIndexOf('.');
  395. if (pos == -1)
  396. alert('Invalid row id!');
  397. updateItemList(tableObj, null, id.substring(pos+1));
  398. tableObj.deleteRow(rowId);
  399. }
  400. function onAdd(nodeSetName)
  401. {
  402. //if (!addImmediateChildrenFromHtmlObjects(schemaNode, objNode, xmlDoc))
  403. // return;
  404. updateNestedData("add", nodeSetName, -1);
  405. //alert(document.all.ArgumentsTable.outerHTML);
  406. }
  407. function onDelete(nodeSetName)
  408. {
  409. var nSelectedRow = getCheckedBoxWithId(nodeSetName+".checkbox");
  410. updateNestedData("delete", nodeSetName, nSelectedRow);
  411. }
  412. function onCheck(cb)
  413. {
  414. //the user checked on one so we have at least one checkbox
  415. //However, we may have only that checkbox and length is 0 in that case
  416. checkBoxes = document.forms[0].all[ cb.id ];
  417. //if we have only one checkbox then length is undefined in that case
  418. if (checkBoxes.length != undefined)
  419. {
  420. //uncheck any previously selected checkbox
  421. var nCheckBoxes = checkBoxes.length;
  422. for (var i=0; i<nCheckBoxes; i++)
  423. if (checkBoxes[i].checked && checkBoxes[i] != cb)
  424. {
  425. checkBoxes[i].checked = false;
  426. break;
  427. }
  428. }
  429. //enable delete and edit buttons
  430. var pos = cb.id.lastIndexOf(".checkbox");
  431. var delId = cb.id.substring(0, pos) + ".Delete";
  432. enableDeleteButton(delId, cb.checked);
  433. }
  434. function getCheckedBoxWithId(id)
  435. {
  436. var checkBoxes = document.forms[0].all[id];
  437. //if we have only one checkbox then length is undefined in that case
  438. if (checkBoxes.length == undefined)
  439. {
  440. //we (un)checked the same checkbox so toggle selection
  441. return checkBoxes.checked ? 0 : -1;
  442. }
  443. else
  444. {
  445. var nCheckBoxes = checkBoxes.length;
  446. for (var i=0; i<nCheckBoxes; i++)
  447. if (checkBoxes[i].checked)
  448. return i;
  449. return -1;
  450. }
  451. }
  452. function enableDeleteButton(id, enable)
  453. {
  454. var btn = document.all[id];
  455. btn.disabled = !enable;
  456. }