corrade-nucleus-nucleons – Rev 26
?pathlinks?
/**
* Defaults
*/
var formRef = null;
// Experimental. Don't rely on them yet.
var settings = {
includeEmptyValuedElements: false,
w3cSuccessfulControlsOnly: false
};
// Currently matching only '[]'.
var keyRegex = /[^\[\]]+|\[\]/g;
var $form = null;
var $formElements = [];
/**
* Private methods
*/
/**
* Check to see if the object is a HTML node.
*
* @param {object} node
* @returns {boolean}
*/
function isDomElementNode(node) {
return !!(node &&
typeof node === 'object' &&
'nodeType' in node &&
node.nodeType === 1);
}
/**
* Check for last numeric key.
*
* @param o object
* @return mixed (string|undefined)
*/
function checkForLastNumericKey(o) {
if (!o || typeof o !== 'object') {
return undefined;
}
return Object.keys(o).filter(function(elem) {
return !isNaN(parseInt(elem, 10));
}).splice(-1)[0];
}
/**
* Get last numeric key from an object.
* @param o object
* @return int
*/
function getLastIntegerKey(o) {
var lastKeyIndex = checkForLastNumericKey(o);
if (typeof lastKeyIndex === 'string') {
return parseInt(lastKeyIndex, 10);
} else {
return 0;
}
}
/**
* Get the next numeric key (like the index from a PHP array)
* @param o object
* @return int
*/
function getNextIntegerKey(o) {
var lastKeyIndex = checkForLastNumericKey(o);
if (typeof lastKeyIndex === 'string') {
return parseInt(lastKeyIndex, 10) + 1;
} else {
return 0;
}
}
/**
* Get the real number of properties from an object.
*
* @param {object} o
* @returns {number}
*/
function getObjLength(o) {
if (typeof o !== 'object' || o === null) {
return 0;
}
var l = 0;
var k;
if (typeof Object.keys === 'function') {
l = Object.keys(o).length;
} else {
for (k in o) {
if (o.hasOwnProperty(k)) {
l++;
}
}
}
return l;
}
/**
* Simple extend of own properties.
* Needed for our settings.
*
* @param {object} destination The object we want to extend.
* @param {object} sources The object with new properties that we want to add the the destination.
* @return {object}
*/
function extend(destination, sources) {
var i;
for (i in sources) {
if (sources.hasOwnProperty(i)) {
destination[i] = sources[i];
}
}
return destination;
}
// Iteration through arrays and objects. Compatible with IE.
function forEach(arr, callback) {
if ([].forEach) {
return [].forEach.call(arr, callback);
}
var i;
for (i in arr) {
// Using Object.prototype.hasOwnProperty instead of
// arr.hasOwnProperty for IE8 compatibility.
if (Object.prototype.hasOwnProperty.call(arr, i)) {
callback.call(arr, arr[i]);
}
}
return;
}
// Constructor
function init(options) {
// Assign the current form reference.
if (!options || typeof options !== 'object' || !options[0]) {
return false;
}
// The form reference is always the first parameter of the method.
// Eg: formToObject('myForm')
formRef = options[0];
// Override current settings.
// Eg. formToObject('myForm', {mySetting: true})
if (typeof options[1] !== 'undefined' && getObjLength(options[1]) > 0) {
extend(settings, options[1]);
}
if (!setForm()) {
return false;
}
if (!setFormElements()) {
return false;
}
return convertToObj();
}
// Set the main form object we are working on.
function setForm() {
switch (typeof formRef){
case 'string':
$form = document.getElementById(formRef);
break;
case 'object':
if (isDomElementNode(formRef)) {
$form = formRef;
}
break;
}
return $form;
}
function isUploadForm() {
return ($form.enctype && $form.enctype === 'multipart/form-data' ? true : false);
}
// Set the elements we need to parse.
function setFormElements() {
$formElements = $form.querySelectorAll('input, textarea, select');
return $formElements.length;
}
function isRadio($domNode) {
return $domNode.nodeName === 'INPUT' && $domNode.type === 'radio';
}
function isCheckbox($domNode) {
return $domNode.nodeName === 'INPUT' && $domNode.type === 'checkbox';
}
function isFileField($domNode) {
return $domNode.nodeName === 'INPUT' && $domNode.type === 'file';
}
function isTextarea($domNode) {
return $domNode.nodeName === 'TEXTAREA';
}
function isSelectSimple($domNode) {
return $domNode.nodeName === 'SELECT' && $domNode.type === 'select-one';
}
function isSelectMultiple($domNode) {
return $domNode.nodeName === 'SELECT' && $domNode.type === 'select-multiple';
}
function isSubmitButton($domNode) {
return $domNode.nodeName === 'BUTTON' && $domNode.type === 'submit';
}
function isChecked($domNode) {
return $domNode.checked;
}
//function isMultiple($domNode){
// return ($domNode.multiple ? true : false);
//}
function isFileList($domNode) {
return (window.FileList && $domNode.files instanceof window.FileList);
}
function getNodeValues($domNode) {
// We're only interested in the radio that is checked.
if (isRadio($domNode)) {
return isChecked($domNode) ? $domNode.value : false;
}
// We're only interested in the checkbox that is checked.
if (isCheckbox($domNode)) {
return isChecked($domNode) ? $domNode.value : false;
}
// File inputs are a special case.
// We have to grab the .files property of the input, which is a FileList.
if (isFileField($domNode)) {
// Ignore input file fields if the form is not encoded properly.
if (isUploadForm()) {
// HTML5 compatible browser.
if (isFileList($domNode) && $domNode.files.length > 0) {
return $domNode.files;
} else {
return ($domNode.value && $domNode.value !== '' ? $domNode.value : false);
}
} else {
return false;
}
}
// We're only interested in textarea fields that have values.
if (isTextarea($domNode)) {
return ($domNode.value && $domNode.value !== '' ? $domNode.value : false);
}
if (isSelectSimple($domNode)) {
if ($domNode.value && $domNode.value !== '') {
return $domNode.value;
} else if ($domNode.options && $domNode.options.length && $domNode.options[0].value !== '') {
return $domNode.options[0].value;
} else {
return false;
}
}
// We're only interested in multiple selects that have at least one option selected.
if (isSelectMultiple($domNode)) {
if ($domNode.options && $domNode.options.length > 0) {
var values = [];
forEach($domNode.options, function($option) {
if ($option.selected) {
values.push($option.value);
}
});
if (settings.includeEmptyValuedElements) {
return values;
} else {
return (values.length ? values : false);
}
} else {
return false;
}
}
// We're only interested if the button is type="submit"
if (isSubmitButton($domNode)) {
if ($domNode.value && $domNode.value !== '') {
return $domNode.value;
}
if ($domNode.innerText && $domNode.innerText !== '') {
return $domNode.innerText;
}
return false;
}
// Fallback or other non special fields.
if (typeof $domNode.value !== 'undefined') {
if (settings.includeEmptyValuedElements) {
return $domNode.value;
} else {
return ($domNode.value !== '' ? $domNode.value : false);
}
} else {
return false;
}
}
function processSingleLevelNode($domNode, arr, domNodeValue, result) {
// Get the last remaining key.
var key = arr[0];
// We're only interested in the radio that is checked.
if (isRadio($domNode)) {
if (domNodeValue !== false) {
result[key] = domNodeValue;
return domNodeValue;
} else {
return;
}
}
// Checkboxes are a special case.
// We have to grab each checked values
// and put them into an array.
if (isCheckbox($domNode)) {
if (domNodeValue !== false) {
if (!result[key]) {
result[key] = [];
}
return result[key].push(domNodeValue);
} else {
return;
}
}
// Multiple select is a special case.
// We have to grab each selected option and put them into an array.
if (isSelectMultiple($domNode)) {
if (domNodeValue !== false) {
result[key] = domNodeValue;
} else {
return;
}
}
// Fallback or other cases that don't
// need special treatment of the value.
result[key] = domNodeValue;
return domNodeValue;
}
function processMultiLevelNode($domNode, arr, value, result) {
var keyName = arr[0];
if (arr.length > 1) {
if (keyName === '[]') {
//result.push({});
result[getNextIntegerKey(result)] = {};
return processMultiLevelNode(
$domNode,
arr.splice(1, arr.length),
value,
result[getLastIntegerKey(result)]
);
} else {
if (result[keyName] && getObjLength(result[keyName]) > 0) {
//result[keyName].push(null);
return processMultiLevelNode(
$domNode,
arr.splice(1, arr.length),
value,
result[keyName]
);
} else {
result[keyName] = {};
}
return processMultiLevelNode($domNode, arr.splice(1, arr.length), value, result[keyName]);
}
}
// Last key, attach the original value.
if (arr.length === 1) {
if (keyName === '[]') {
//result.push(value);
result[getNextIntegerKey(result)] = value;
return result;
} else {
processSingleLevelNode($domNode, arr, value, result);
// result[keyName] = value;
return result;
}
}
}
function convertToObj() {
var i = 0;
var objKeyNames;
var $domNode;
var domNodeValue;
var result = {};
var resultLength;
for (i = 0; i < $formElements.length; i++) {
$domNode = $formElements[i];
// Skip the element if the 'name' attribute is empty.
// Skip the 'disabled' elements.
// Skip the non selected radio elements.
if (
!$domNode.name ||
$domNode.name === '' ||
$domNode.disabled ||
(isRadio($domNode) && !isChecked($domNode))
) {
continue;
}
// Get the final processed domNode value.
domNodeValue = getNodeValues($domNode);
// Exclude empty valued nodes if the settings allow it.
if (domNodeValue === false && !settings.includeEmptyValuedElements) {
continue;
}
// Extract all possible keys
// Eg. name="firstName", name="settings[a][b]", name="settings[0][a]"
objKeyNames = $domNode.name.match(keyRegex);
if (objKeyNames.length === 1) {
processSingleLevelNode(
$domNode,
objKeyNames,
(domNodeValue ? domNodeValue : ''),
result
);
}
if (objKeyNames.length > 1) {
processMultiLevelNode(
$domNode,
objKeyNames,
(domNodeValue ? domNodeValue : ''),
result
);
}
}
// Check the length of the result.
resultLength = getObjLength(result);
return resultLength > 0 ? result : false;
}