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 | } |
---|