[1482] | 1 | customMetaTagsFunctions = new Object() |
---|
| 2 | |
---|
| 3 | customMetaTagsFunctions.getInputOrSelect = function(node) { |
---|
| 4 | /* Get the (first) input or select form element under the given node */ |
---|
| 5 | |
---|
| 6 | var inputs = node.getElementsByTagName("input"); |
---|
| 7 | if(inputs.length > 0) { |
---|
| 8 | return inputs[0]; |
---|
| 9 | } |
---|
| 10 | |
---|
| 11 | var selects = node.getElementsByTagName("select"); |
---|
| 12 | if(selects.length > 0) { |
---|
| 13 | return selects[0]; |
---|
| 14 | } |
---|
| 15 | |
---|
| 16 | return null; |
---|
| 17 | } |
---|
| 18 | |
---|
| 19 | customMetaTagsFunctions.getWidgetRows = function(currnode) { |
---|
| 20 | /* Return primary <tr>s of current node's parent DGW */ |
---|
| 21 | tbody = this.getParentElementById(currnode, "datagridwidget-tbody"); |
---|
| 22 | return this.getRows(tbody); |
---|
| 23 | } |
---|
| 24 | |
---|
| 25 | customMetaTagsFunctions.getRows = function(tbody) { |
---|
| 26 | /* Return <tr> rows of <table> element */ |
---|
| 27 | |
---|
| 28 | var rows = new Array() |
---|
| 29 | |
---|
| 30 | child = tbody.firstChild; |
---|
| 31 | while(child != null) { |
---|
| 32 | if(child.tagName != null) { |
---|
| 33 | if(child.tagName.toLowerCase() == "tr") { |
---|
| 34 | rows = rows.concat(child); |
---|
| 35 | } |
---|
| 36 | } |
---|
| 37 | child = child.nextSibling; |
---|
| 38 | } |
---|
| 39 | |
---|
| 40 | return rows; |
---|
| 41 | } |
---|
| 42 | |
---|
| 43 | customMetaTagsFunctions.autoInsertRow = function(e) { |
---|
| 44 | /* Add a new row when changing the last row |
---|
| 45 | (i.e. the infamous auto insert feature) |
---|
| 46 | |
---|
| 47 | Check that if this onchange event handler was |
---|
| 48 | called from the last row. In this case, |
---|
| 49 | add a new row for DGF. |
---|
| 50 | |
---|
| 51 | */ |
---|
| 52 | |
---|
| 53 | var currnode = window.event ? window.event.srcElement : e.currentTarget; |
---|
| 54 | |
---|
| 55 | // fetch required data structure |
---|
| 56 | var tbody = this.getParentElement(currnode, "TBODY"); |
---|
| 57 | var rows = this.getRows(tbody); |
---|
| 58 | var lastRow = rows[rows.length-1]; |
---|
| 59 | |
---|
| 60 | var thisRow = this.getParentElementById(currnode, "datagridwidget-row"); |
---|
| 61 | |
---|
| 62 | /* Skip the very last row which is a hidden template row */ |
---|
| 63 | if(rows.length-1 ==(thisRow.rowIndex)) { |
---|
| 64 | // Create a new row |
---|
| 65 | var newtr = this.createNewRow(lastRow); |
---|
| 66 | |
---|
| 67 | // Put new row to DOM tree before template row |
---|
| 68 | lastRow.parentNode.insertBefore(newtr, lastRow); |
---|
| 69 | |
---|
| 70 | // update orderindex hidden fields |
---|
| 71 | this.updateOrderIndex(tbody); |
---|
| 72 | } |
---|
| 73 | } |
---|
| 74 | |
---|
| 75 | customMetaTagsFunctions.addRowAfter = function(currnode) { |
---|
| 76 | /* |
---|
| 77 | Creates a new row before the clicked row |
---|
| 78 | */ |
---|
| 79 | |
---|
| 80 | // fetch required data structure |
---|
| 81 | var tbody = this.getParentElementById(currnode, "datagridwidget-tbody"); |
---|
| 82 | var thisRow = this.getParentElementById(currnode, "datagridwidget-row"); |
---|
| 83 | |
---|
| 84 | var newtr = this.createNewRow(thisRow); |
---|
| 85 | |
---|
| 86 | thisRow.parentNode.insertBefore(newtr, thisRow); |
---|
| 87 | |
---|
| 88 | // update orderindex hidden fields |
---|
| 89 | this.updateOrderIndex(tbody); |
---|
| 90 | |
---|
| 91 | } |
---|
| 92 | |
---|
| 93 | customMetaTagsFunctions.addRow = function(id) { |
---|
| 94 | /* Explitcly add row for given DataGridField |
---|
| 95 | |
---|
| 96 | @param id Archetypes field id for the widget |
---|
| 97 | */ |
---|
| 98 | |
---|
| 99 | // fetch required data structure |
---|
| 100 | var tbody = document.getElementById("datagridwidget-tbody-" + id); |
---|
| 101 | var rows = this.getRows(tbody); |
---|
| 102 | var lastRow = rows[rows.length-1]; |
---|
| 103 | |
---|
| 104 | var oldRows = rows.length; |
---|
| 105 | |
---|
| 106 | // Create a new row |
---|
| 107 | var newtr = this.createNewRow(lastRow); |
---|
| 108 | |
---|
| 109 | // Put new row to DOM tree before template row |
---|
| 110 | newNode = lastRow.parentNode.insertBefore(newtr, lastRow); |
---|
| 111 | |
---|
| 112 | // update orderindex hidden fields |
---|
| 113 | this.updateOrderIndex(tbody); |
---|
| 114 | |
---|
| 115 | } |
---|
| 116 | |
---|
| 117 | customMetaTagsFunctions.createNewRow = function(tr) { |
---|
| 118 | /* Creates a new row |
---|
| 119 | |
---|
| 120 | @param tr A row in a table where we'll be adding the new row |
---|
| 121 | */ |
---|
| 122 | |
---|
| 123 | var tbody = this.getParentElementById(tr, "datagridwidget-tbody"); |
---|
| 124 | var rows = this.getRows(tbody); |
---|
| 125 | |
---|
| 126 | // hidden template row |
---|
| 127 | var lastRow = rows[rows.length-1]; |
---|
| 128 | |
---|
| 129 | var newtr = document.createElement("tr"); |
---|
| 130 | newtr.setAttribute("id", "datagridwidget-row"); |
---|
| 131 | newtr.setAttribute("class", "datagridwidget-row"); |
---|
| 132 | |
---|
| 133 | // clone template contents from the last row to the newly created row |
---|
| 134 | // HOX HOX HOX |
---|
| 135 | // If f****ng IE clones lastRow directly it doesn't work. |
---|
| 136 | // lastRow is in hidden state and no matter what you do it remains hidden. |
---|
| 137 | // i.e. overriding class doesn't bring it visible. |
---|
| 138 | // In Firefox everything worked like a charm. |
---|
| 139 | // So the code below is really a hack to satisfy Microsoft codeborgs. |
---|
| 140 | // keywords: IE javascript clone clonenode hidden element render visibility visual |
---|
| 141 | child = lastRow.firstChild; |
---|
| 142 | while(child != null) { |
---|
| 143 | newchild = child.cloneNode(true); |
---|
| 144 | newtr.appendChild(newchild); |
---|
| 145 | child = child.nextSibling; |
---|
| 146 | } |
---|
| 147 | |
---|
| 148 | return newtr; |
---|
| 149 | } |
---|
| 150 | |
---|
| 151 | |
---|
| 152 | customMetaTagsFunctions.removeFieldRow = function(node) { |
---|
| 153 | /* Remove the row in which the given node is found */ |
---|
| 154 | |
---|
| 155 | var row = this.getParentElementById(node, 'datagridwidget-row'); |
---|
| 156 | var tbody = this.getParentElementById(node, 'datagridwidget-tbody'); |
---|
| 157 | tbody.removeChild(row); |
---|
| 158 | } |
---|
| 159 | |
---|
| 160 | customMetaTagsFunctions.moveRowDown = function(currnode){ |
---|
| 161 | /* Move the given row down one */ |
---|
| 162 | |
---|
| 163 | var tbody = this.getParentElementById(currnode, "datagridwidget-tbody"); |
---|
| 164 | |
---|
| 165 | var rows = this.getWidgetRows(currnode); |
---|
| 166 | |
---|
| 167 | var row = this.getParentElementById(currnode, "datagridwidget-row"); |
---|
| 168 | if(row == null) { |
---|
| 169 | alert("Couldn't find DataGridWidget row"); |
---|
| 170 | return; |
---|
| 171 | } |
---|
| 172 | |
---|
| 173 | var idx = null |
---|
| 174 | |
---|
| 175 | // We can't use nextSibling because of blank text nodes in some browsers |
---|
| 176 | // Need to find the index of the row |
---|
| 177 | for(var t = 0; t < rows.length; t++) { |
---|
| 178 | if(rows[t] == row) { |
---|
| 179 | idx = t; |
---|
| 180 | break; |
---|
| 181 | } |
---|
| 182 | } |
---|
| 183 | |
---|
| 184 | // Abort if the current row wasn't found |
---|
| 185 | if(idx == null) |
---|
| 186 | return; |
---|
| 187 | |
---|
| 188 | // If this was the last row (before the blank row at the end used to create |
---|
| 189 | // new rows), move to the top, else move down one. |
---|
| 190 | if(idx + 2 == rows.length) { |
---|
| 191 | var nextRow = rows.item[0] |
---|
| 192 | this.shiftRow(row, nextRow) |
---|
| 193 | } else { |
---|
| 194 | var nextRow = rows[idx+1] |
---|
| 195 | this.shiftRow(nextRow, row) |
---|
| 196 | } |
---|
| 197 | |
---|
| 198 | this.updateOrderIndex(tbody) |
---|
| 199 | |
---|
| 200 | } |
---|
| 201 | |
---|
| 202 | customMetaTagsFunctions.moveRowUp = function(currnode){ |
---|
| 203 | /* Move the given row up one */ |
---|
| 204 | |
---|
| 205 | var tbody = this.getParentElementById(currnode, "datagridwidget-tbody"); |
---|
| 206 | var rows = this.getWidgetRows(currnode); |
---|
| 207 | |
---|
| 208 | var row = this.getParentElementById(currnode, "datagridwidget-row"); |
---|
| 209 | if(row == null) { |
---|
| 210 | alert("Couldn't find DataGridWidget row"); |
---|
| 211 | return; |
---|
| 212 | } |
---|
| 213 | |
---|
| 214 | var idx = null |
---|
| 215 | |
---|
| 216 | // We can't use nextSibling because of blank text nodes in some browsers |
---|
| 217 | // Need to find the index of the row |
---|
| 218 | for(var t = 0; t < rows.length; t++) { |
---|
| 219 | if(rows[t] == row) { |
---|
| 220 | idx = t; |
---|
| 221 | break; |
---|
| 222 | } |
---|
| 223 | } |
---|
| 224 | |
---|
| 225 | // Abort if the current row wasn't found |
---|
| 226 | if(idx == null) |
---|
| 227 | return; |
---|
| 228 | |
---|
| 229 | // If this was the first row, move to the end (i.e. before the blank row |
---|
| 230 | // at the end used to create new rows), else move up one |
---|
| 231 | if(idx == 0) { |
---|
| 232 | var previousRow = rows[rows.length - 1] |
---|
| 233 | this.shiftRow(row, previousRow); |
---|
| 234 | } else { |
---|
| 235 | var previousRow = rows[idx-1]; |
---|
| 236 | this.shiftRow(row, previousRow); |
---|
| 237 | } |
---|
| 238 | |
---|
| 239 | this.updateOrderIndex(tbody); |
---|
| 240 | } |
---|
| 241 | |
---|
| 242 | customMetaTagsFunctions.shiftRow = function(bottom, top){ |
---|
| 243 | /* Put node top before node bottom */ |
---|
| 244 | |
---|
| 245 | bottom.parentNode.insertBefore(bottom, top) |
---|
| 246 | } |
---|
| 247 | |
---|
| 248 | customMetaTagsFunctions.updateOrderIndex = function (tbody) { |
---|
| 249 | |
---|
| 250 | /* Update the hidden orderindex fields to be in the right order */ |
---|
| 251 | |
---|
| 252 | var xre = new RegExp(/^orderindex__/) |
---|
| 253 | var idx = 0; |
---|
| 254 | var cell; |
---|
| 255 | |
---|
| 256 | var rows = this.getRows(tbody); |
---|
| 257 | |
---|
| 258 | /* Make sure that updateOrderIndex doesn't touch |
---|
| 259 | the template (last) row */ |
---|
| 260 | for(var i=0; i<rows.length-1; i++) { |
---|
| 261 | |
---|
| 262 | for (var c = 0; (cell = rows[i].getElementsByTagName('INPUT').item(c)); c++) { |
---|
| 263 | |
---|
| 264 | if (cell.getAttribute('id')) { |
---|
| 265 | if (xre.exec(cell.id)) { |
---|
| 266 | cell.value = idx; |
---|
| 267 | } |
---|
| 268 | } |
---|
| 269 | this.updateRadioButtonGroupName(this.getParentElement(cell, "TR"), idx); |
---|
| 270 | idx++; |
---|
| 271 | } |
---|
| 272 | } |
---|
| 273 | } |
---|
| 274 | |
---|
| 275 | |
---|
| 276 | customMetaTagsFunctions.updateRadioButtonGroupName = function (row, newIndex) { |
---|
| 277 | /* Adjust radio button group names after reordering |
---|
| 278 | |
---|
| 279 | Why we do this, see RadioColumn class comments |
---|
| 280 | |
---|
| 281 | TODO: If chain onchange -> updateOrderIndex -> updaterRadioButtonGroupName |
---|
| 282 | is triggered on Firefox, the value of checked radio button is put to the |
---|
| 283 | newly generated row instead of clicked row. |
---|
| 284 | */ |
---|
| 285 | |
---|
| 286 | var cell; |
---|
| 287 | var xre = new RegExp(/^radio/) |
---|
| 288 | var xre2 = new RegExp(/^checkbox/) |
---|
| 289 | |
---|
| 290 | for (var c = 0; (cell = row.getElementsByTagName('INPUT').item(c)); c++) { |
---|
| 291 | |
---|
| 292 | if(cell.getAttribute('type')) { |
---|
| 293 | var type = cell.getAttribute('type'); |
---|
| 294 | if (xre.exec(type) || xre2.exec(type)) { |
---|
| 295 | |
---|
| 296 | var name = cell.getAttribute("NAME") |
---|
| 297 | if(name == null) continue; |
---|
| 298 | |
---|
| 299 | // save fieldId + columnId part |
---|
| 300 | var baseLabel = name.substring(0, name.lastIndexOf(".")); |
---|
| 301 | // update per row running id |
---|
| 302 | cell.setAttribute("NAME", baseLabel + "." + newIndex); |
---|
| 303 | } |
---|
| 304 | } |
---|
| 305 | } |
---|
| 306 | } |
---|
| 307 | |
---|
| 308 | customMetaTagsFunctions.getParentElement = function(currnode, tagname) { |
---|
| 309 | /* Find the first parent node with the given tag name */ |
---|
| 310 | |
---|
| 311 | tagname = tagname.toUpperCase(); |
---|
| 312 | var parent = currnode.parentNode; |
---|
| 313 | |
---|
| 314 | while(parent.tagName.toUpperCase() != tagname) { |
---|
| 315 | parent = parent.parentNode; |
---|
| 316 | // Next line is a safety belt |
---|
| 317 | if(parent.tagName.toUpperCase() == "BODY") |
---|
| 318 | return null; |
---|
| 319 | } |
---|
| 320 | |
---|
| 321 | return parent; |
---|
| 322 | } |
---|
| 323 | |
---|
| 324 | customMetaTagsFunctions.getParentElementById = function(currnode, id) { |
---|
| 325 | /* Find the first parent node with the given id |
---|
| 326 | |
---|
| 327 | Id is partially matched: the beginning of |
---|
| 328 | an element id matches parameter id string. |
---|
| 329 | |
---|
| 330 | Currnode: Node where ascending in DOM tree beings |
---|
| 331 | Id: Id string to look for. |
---|
| 332 | |
---|
| 333 | */ |
---|
| 334 | |
---|
| 335 | id = id.toLowerCase(); |
---|
| 336 | var parent = currnode.parentNode; |
---|
| 337 | |
---|
| 338 | while(true) { |
---|
| 339 | |
---|
| 340 | var parentId = parent.getAttribute("id"); |
---|
| 341 | if(parentId != null) { |
---|
| 342 | if(parentId.toLowerCase().substring(0, id.length) == id) break; |
---|
| 343 | } |
---|
| 344 | |
---|
| 345 | parent = parent.parentNode; |
---|
| 346 | // Next line is a safety belt |
---|
| 347 | if(parent.tagName.toUpperCase() == "BODY") |
---|
| 348 | return null; |
---|
| 349 | } |
---|
| 350 | |
---|
| 351 | return parent; |
---|
| 352 | } |
---|