Skip to content

Commit 01418c2

Browse files
authored
[#57] Fix form2js issue (#58)
2 parents c70cfac + 919df7b commit 01418c2

File tree

4 files changed

+379
-8
lines changed

4 files changed

+379
-8
lines changed

openidm-ui/Gruntfile-common.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717
module.exports = function(grunt, options) {
1818
var buildCompositionDirs = [
19-
"target/dependencies",
2019
"target/dependency",
20+
"target/dependencies",
2121
"target/classes"
2222
],
2323
watchCompositionDirs = options.watchCompositionDirs.concat([

openidm-ui/extlib/form2js.js

Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
/**
2+
* Copyright (c) 2010 Maxim Vasiliev
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
* THE SOFTWARE.
21+
*
22+
* @author Maxim Vasiliev
23+
* Date: 09.09.2010
24+
* Time: 19:02:33
25+
*/
26+
27+
28+
(function (root, factory)
29+
{
30+
if (typeof exports !== 'undefined' && typeof module !== 'undefined' && module.exports) {
31+
// NodeJS
32+
module.exports = factory();
33+
}
34+
else if (typeof define === 'function' && define.amd)
35+
{
36+
// AMD. Register as an anonymous module.
37+
define(factory);
38+
}
39+
else
40+
{
41+
// Browser globals
42+
root.form2js = factory();
43+
}
44+
}(this, function ()
45+
{
46+
"use strict";
47+
48+
/**
49+
* Returns form values represented as Javascript object
50+
* "name" attribute defines structure of resulting object
51+
*
52+
* @param rootNode {Element|String} root form element (or it's id) or array of root elements
53+
* @param delimiter {String} structure parts delimiter defaults to '.'
54+
* @param skipEmpty {Boolean} should skip empty text values, defaults to true
55+
* @param nodeCallback {Function} custom function to get node value
56+
* @param useIdIfEmptyName {Boolean} if true value of id attribute of field will be used if name of field is empty
57+
*/
58+
function form2js(rootNode, delimiter, skipEmpty, nodeCallback, useIdIfEmptyName, getDisabled)
59+
{
60+
getDisabled = getDisabled ? true : false;
61+
if (typeof skipEmpty == 'undefined' || skipEmpty == null) skipEmpty = true;
62+
if (typeof delimiter == 'undefined' || delimiter == null) delimiter = '.';
63+
if (arguments.length < 5) useIdIfEmptyName = false;
64+
65+
rootNode = typeof rootNode == 'string' ? document.getElementById(rootNode) : rootNode;
66+
67+
var formValues = [],
68+
currNode,
69+
i = 0;
70+
71+
/* If rootNode is array - combine values */
72+
if (rootNode.constructor == Array || (typeof NodeList != "undefined" && rootNode.constructor == NodeList))
73+
{
74+
while(currNode = rootNode[i++])
75+
{
76+
formValues = formValues.concat(getFormValues(currNode, nodeCallback, useIdIfEmptyName, getDisabled));
77+
}
78+
}
79+
else
80+
{
81+
formValues = getFormValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled);
82+
}
83+
84+
return processNameValues(formValues, skipEmpty, delimiter);
85+
}
86+
87+
/**
88+
* Processes collection of { name: 'name', value: 'value' } objects.
89+
* @param nameValues
90+
* @param skipEmpty if true skips elements with value == '' or value == null
91+
* @param delimiter
92+
*/
93+
function processNameValues(nameValues, skipEmpty, delimiter)
94+
{
95+
var result = {},
96+
arrays = {},
97+
i, j, k, l,
98+
value,
99+
nameParts,
100+
currResult,
101+
arrNameFull,
102+
arrName,
103+
arrIdx,
104+
namePart,
105+
name,
106+
_nameParts;
107+
108+
for (i = 0; i < nameValues.length; i++)
109+
{
110+
value = nameValues[i].value;
111+
112+
if (skipEmpty && (value === '' || value === null)) continue;
113+
114+
name = nameValues[i].name;
115+
116+
function replacer(match, p1, p2, p3, p4, offset, string) {
117+
// p1 is non-digits, p2 digits, and p3 non-alphanumerics
118+
return "." + p2;
119+
}
120+
var name = name.replace(/(\[)([a-z][a-z0-9_]+)(\])/i, replacer);
121+
122+
_nameParts = name.split(delimiter);
123+
nameParts = [];
124+
currResult = result;
125+
arrNameFull = '';
126+
127+
for(j = 0; j < _nameParts.length; j++)
128+
{
129+
namePart = _nameParts[j].split('][');
130+
if (namePart.length > 1)
131+
{
132+
for(k = 0; k < namePart.length; k++)
133+
{
134+
if (k == 0)
135+
{
136+
namePart[k] = namePart[k] + ']';
137+
}
138+
else if (k == namePart.length - 1)
139+
{
140+
namePart[k] = '[' + namePart[k];
141+
}
142+
else
143+
{
144+
namePart[k] = '[' + namePart[k] + ']';
145+
}
146+
147+
arrIdx = namePart[k].match(/([a-z_]+)?\[([a-z_][a-z0-9_]+?)\]/i);
148+
if (arrIdx)
149+
{
150+
for(l = 1; l < arrIdx.length; l++)
151+
{
152+
if (arrIdx[l]) nameParts.push(arrIdx[l]);
153+
}
154+
}
155+
else{
156+
nameParts.push(namePart[k]);
157+
}
158+
}
159+
}
160+
else
161+
nameParts = nameParts.concat(namePart);
162+
}
163+
164+
for (j = 0; j < nameParts.length; j++)
165+
{
166+
namePart = nameParts[j];
167+
168+
if (namePart.indexOf('[]') > -1 && j == nameParts.length - 1)
169+
{
170+
arrName = namePart.substr(0, namePart.indexOf('['));
171+
arrNameFull += arrName;
172+
173+
if (!currResult[arrName]) currResult[arrName] = [];
174+
currResult[arrName].push(value);
175+
}
176+
else if (namePart.indexOf('[') > -1)
177+
{
178+
arrName = namePart.substr(0, namePart.indexOf('['));
179+
arrIdx = namePart.replace(/(^([a-z_]+)?\[)|(\]$)/gi, '');
180+
181+
/* Unique array name */
182+
arrNameFull += '_' + arrName + '_' + arrIdx;
183+
184+
/*
185+
* Because arrIdx in field name can be not zero-based and step can be
186+
* other than 1, we can't use them in target array directly.
187+
* Instead we're making a hash where key is arrIdx and value is a reference to
188+
* added array element
189+
*/
190+
191+
if (!arrays[arrNameFull]) arrays[arrNameFull] = {};
192+
if (arrName != '' && !currResult[arrName]) currResult[arrName] = [];
193+
194+
if (j == nameParts.length - 1)
195+
{
196+
if (arrName == '')
197+
{
198+
currResult.push(value);
199+
arrays[arrNameFull][arrIdx] = currResult[currResult.length - 1];
200+
}
201+
else
202+
{
203+
currResult[arrName].push(value);
204+
arrays[arrNameFull][arrIdx] = currResult[arrName][currResult[arrName].length - 1];
205+
}
206+
}
207+
else
208+
{
209+
if (!arrays[arrNameFull][arrIdx])
210+
{
211+
if ((/^[0-9a-z_]+\[?/i).test(nameParts[j+1])) currResult[arrName].push({});
212+
else currResult[arrName].push([]);
213+
214+
arrays[arrNameFull][arrIdx] = currResult[arrName][currResult[arrName].length - 1];
215+
}
216+
}
217+
218+
currResult = arrays[arrNameFull][arrIdx];
219+
}
220+
else
221+
{
222+
arrNameFull += namePart;
223+
224+
if (j < nameParts.length - 1) /* Not the last part of name - means object */
225+
{
226+
if (!currResult[namePart]) currResult[namePart] = {};
227+
currResult = currResult[namePart];
228+
}
229+
else
230+
{
231+
currResult[namePart] = value;
232+
}
233+
}
234+
}
235+
}
236+
237+
return result;
238+
}
239+
240+
function getFormValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled)
241+
{
242+
var result = extractNodeValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled);
243+
return result.length > 0 ? result : getSubFormValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled);
244+
}
245+
246+
function getSubFormValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled)
247+
{
248+
var result = [],
249+
currentNode = rootNode.firstChild;
250+
251+
while (currentNode)
252+
{
253+
result = result.concat(extractNodeValues(currentNode, nodeCallback, useIdIfEmptyName, getDisabled));
254+
currentNode = currentNode.nextSibling;
255+
}
256+
257+
return result;
258+
}
259+
260+
function extractNodeValues(node, nodeCallback, useIdIfEmptyName, getDisabled) {
261+
if (node.disabled && !getDisabled) return [];
262+
263+
var callbackResult, fieldValue, result, fieldName = getFieldName(node, useIdIfEmptyName);
264+
265+
callbackResult = nodeCallback && nodeCallback(node);
266+
267+
if (callbackResult && callbackResult.name) {
268+
result = [callbackResult];
269+
}
270+
else if (fieldName != '' && node.nodeName.match(/INPUT|TEXTAREA/i)) {
271+
fieldValue = getFieldValue(node, getDisabled);
272+
if (null === fieldValue) {
273+
result = [];
274+
} else {
275+
result = [ { name: fieldName, value: fieldValue} ];
276+
}
277+
}
278+
else if (fieldName != '' && node.nodeName.match(/SELECT/i)) {
279+
fieldValue = getFieldValue(node, getDisabled);
280+
result = [ { name: fieldName.replace(/\[\]$/, ''), value: fieldValue } ];
281+
}
282+
else {
283+
result = getSubFormValues(node, nodeCallback, useIdIfEmptyName, getDisabled);
284+
}
285+
286+
return result;
287+
}
288+
289+
function getFieldName(node, useIdIfEmptyName)
290+
{
291+
if (node.name && node.name != '') return node.name;
292+
else if (useIdIfEmptyName && node.id && node.id != '') return node.id;
293+
else return '';
294+
}
295+
296+
297+
function getFieldValue(fieldNode, getDisabled)
298+
{
299+
if (fieldNode.disabled && !getDisabled) return null;
300+
301+
switch (fieldNode.nodeName) {
302+
case 'INPUT':
303+
case 'TEXTAREA':
304+
switch (fieldNode.type.toLowerCase()) {
305+
case 'radio':
306+
if (fieldNode.checked && fieldNode.value === "false") return false;
307+
case 'checkbox':
308+
if (fieldNode.checked && fieldNode.value === "true") return true;
309+
if (!fieldNode.checked && fieldNode.value === "true") return false;
310+
if (fieldNode.checked) return fieldNode.value;
311+
break;
312+
313+
case 'button':
314+
case 'reset':
315+
case 'submit':
316+
case 'image':
317+
return '';
318+
break;
319+
320+
default:
321+
return fieldNode.value;
322+
break;
323+
}
324+
break;
325+
326+
case 'SELECT':
327+
return getSelectedOptionValue(fieldNode);
328+
break;
329+
330+
default:
331+
break;
332+
}
333+
334+
return null;
335+
}
336+
337+
function getSelectedOptionValue(selectNode)
338+
{
339+
var multiple = selectNode.multiple,
340+
result = [],
341+
options,
342+
i, l;
343+
344+
if (!multiple) return selectNode.value;
345+
346+
for (options = selectNode.getElementsByTagName("option"), i = 0, l = options.length; i < l; i++)
347+
{
348+
if (options[i].selected) result.push(options[i].value);
349+
}
350+
351+
return result;
352+
}
353+
354+
return form2js;
355+
356+
}));

openidm-ui/openidm-ui-admin/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@
112112
<type>js</type>
113113
</dependency>
114114

115+
<dependency>
116+
<groupId>org.openidentityplatform.commons.ui.libs</groupId>
117+
<artifactId>form2js</artifactId>
118+
<version>2.0-769718a</version>
119+
<type>js</type>
120+
</dependency>
121+
115122
<dependency>
116123
<groupId>org.openidentityplatform.commons.ui.libs</groupId>
117124
<artifactId>CodeMirror</artifactId>

0 commit comments

Comments
 (0)