Serializing form with nested paths and arrays to JSON in javascript - javascript

A similar question is addressed here: Convert form data to JavaScript object with jQuery with the following solution:
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
However that doesn't work when you want to have JSON with nested objects. For instance, for this form:
Employee name: <input type="text" id="employee" name="name"/>
Department name: <input type="text" id="department" name="department.name"/>
Department chief1: <input type="text" id="chief1" name="department.chief[0]"/>
Department chief2: <input type="text" id="chief2" name="department.chief[1]"/>
I am getting: {"name":"John","department.name":"IT" , "department.chief[0]":"Mike" "department.chief[1]":"Lucas"}
but what I do need is {"name":"John","department" : {"name":"IT"}, "chief" : [ "Mike", "Lucas" }
Is there any adaptation of serializeObject that does it this way?
To provide some background: I need this because I am submitting an AJAX call to a Spring MVC controller and Jackson expects that format to create the nested objects.

This is my modified version of serializeObject supporting both nested objects and arrays:
$.fn.serializeObject = function() {
var arrayData, objectData;
arrayData = this.serializeArray();
objectData = {};
$.each(arrayData, function() {
this.value = !this.value ? '' : this.value;
processObject(objectData, this.name, this.value);
});
return objectData;
};
function processObject(obj, key, value){
if(key.indexOf('.') != -1) {
var attrs = key.split('.');
var tx = obj;
for (var i = 0; i < attrs.length - 1; i++) {
var isArray = attrs[i].indexOf('[') != -1;
var isNestedArray = isArray && (i != attrs.length-1);
var nestedArrayIndex = null;
if(isArray){
nestedArrayIndex = attrs[i].substring(attrs[i].indexOf('[') +1 , attrs[i].indexOf(']'));
attrs[i] = attrs[i].substring(0, attrs[i].indexOf('['));
if (tx[attrs[i]] == undefined){
tx[attrs[i]] = [];
}
tx = tx[attrs[i]];
if(isNestedArray){
if(tx[nestedArrayIndex] == undefined){
tx[nestedArrayIndex] = {};
}
tx = tx[nestedArrayIndex];
}
}else{
if (tx[attrs[i]] == undefined){
tx[attrs[i]] = {};
}
tx = tx[attrs[i]];
}
}
processObject(tx, attrs[attrs.length - 1], value);
}else{
var finalArrayIndex = null;
if(key.indexOf('[') != -1){
finalArrayIndex = key.substring(key.indexOf('[') +1 , key.indexOf(']'));
key = key.substring(0, key.indexOf('['));
}
if(finalArrayIndex == null){
obj[key] = value;
}else{
if(obj[key] == undefined){
obj[key] = [];
}
obj[key][finalArrayIndex] = value;
}
}
}

unflatten from the (npm) "flat" module should do the trick:
var data = {"name":"John","department.name":"IT"}
var nested = flat.unflatten(data)
Live example
https://tonicdev.com/lipp/unflatten
Just replace return o with return flat.unlatten(o) in your case.
This is the unflatten method for the browser extracted and un-noded from repo(https://github.com/hughsk/flat/blob/master/index.js):
function unflatten(target, opts) {
opts = opts || {}
var delimiter = opts.delimiter || '.'
var overwrite = opts.overwrite || false
var result = {}
// safely ensure that the key is
// an integer.
function getkey(key) {
var parsedKey = Number(key)
return (
isNaN(parsedKey) ||
key.indexOf('.') !== -1
) ? key
: parsedKey
}
Object.keys(target).forEach(function(key) {
var split = key.split(delimiter)
var key1 = getkey(split.shift())
var key2 = getkey(split[0])
var recipient = result
while (key2 !== undefined) {
var type = Object.prototype.toString.call(recipient[key1])
var isobject = (
type === "[object Object]" ||
type === "[object Array]"
)
// do not write over falsey, non-undefined values if overwrite is false
if (!overwrite && !isobject && typeof recipient[key1] !== 'undefined') {
return
}
if ((overwrite && !isobject) || (!overwrite && recipient[key1] == null)) {
recipient[key1] = (
typeof key2 === 'number' &&
!opts.object ? [] : {}
)
}
recipient = recipient[key1]
if (split.length > 0) {
key1 = getkey(split.shift())
key2 = getkey(split[0])
}
}
// unflatten again for 'messy objects'
recipient[key1] = unflatten(target[key], opts)
})
return result
}

Related

JavaScript to check which CSS classes are NOT in use on a page

I am building a JavaScript snippet that I am using to check which CSS classes are NOT in use on a page. Here is the code:
function httpGet(theUrl) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false ); // false for synchronous request
xmlHttp.send( null );
return xmlHttp.responseText;
}
function getAllClasses() {
//get inline css classes
let headContent = document.getElementsByTagName('head')[0].innerHTML;
let classes = getAllCSSClasses(headContent);
//get external linraties
let csses = document.querySelectorAll('link[rel="stylesheet"]');
for (i = 0; i < csses.length; ++i) {
if (csses[i].href && csses[i].href.indexOf("cookieconsent") == -1){
let styledata = httpGet(csses[i].href);
let cclasses = getAllCSSClasses(styledata);
if ( cclasses instanceof Array )
classes = classes.concat( cclasses );
else
classes.push( cclasses );
//console.log(csses[i].href)
//classes = Object.assign([], classes, cclasses);
//console.log(classes)
//classes.concat(cclasses);
}
}
return classes;
}
function getAllCSSClasses(cssdata) {
var re = /\.[a-zA-Z_][\w-_]*[^\.\s\{#:\,;]/g;
var m;
let classes = [];
do {
m = re.exec(cssdata);
if (m) {
for(let key in m) {
if(
(typeof m[key] == "string") &&
(classes.indexOf(m[key]) == -1) &&
(m[key].indexOf(".") == 0)
)
classes.push(m[key].replace(/\s/g, " "));
}
}
} while (m);
return classes;
}
function getHTMLUsedClasses() {
var elements = document.getElementsByTagName('*');
var unique = function (list, x) {
if (x != "" && list.indexOf(x) === -1) {
list.push(x);
}
return list;
};
var htmlclasses = [].reduce.call(elements, function (acc, e) {
if (typeof e.className == "string"){
return [].slice.call(e.classList).reduce(unique, acc);
} else {
return [];
}
}, []);
return htmlclasses;
}
function getUndefinedClasses(cssclasses, htmlclasses) {
var undefinedclasses = [];
for (let key in htmlclasses) {
if(cssclasses.indexOf("." + htmlclasses[key]) == -1 ) {
undefinedclasses.push(htmlclasses[key]);
}
}
return undefinedclasses;
}
var cssclasses = getAllClasses();
var htmlclasses = getHTMLUsedClasses();
var un = getUndefinedClasses(cssclasses, htmlclasses);
console.log(un )
//copy(un);
Now, the problem is in getHTMLUsedClasses, it doesn't work well.
For example, HTML has an 'img-responsive' class, but the output doesn't show it
var unique = function (list, x) {
if (x != "" && list.indexOf(x) === -1) {
//img-responsive here exists
list.push(x);
}
return list;
};
but:
var htmlclasses = [].reduce.call(elements, function (acc, e) {
if (typeof e.className == "string"){
return [].slice.call(e.classList).reduce(unique, acc);
} else {
return [];
}
}, []);
//doesn't exists in the final htmlclasses
return htmlclasses;
So I am guessing that [].slice.call(e.classList).reduce(unique, acc) is not working well. I don't quite understand what 'reduce' is doing here (I took this from another example). Can anyone explain?
I think I've found what was the issue. I read that "reduce() does not execute the function for array elements without values." and some classes can come empty so "return [];" will destroy all that is in the array so far. And instead I think that I have to return accumulator like this:
function getHTMLUsedClasses() {
var elements = document.getElementsByTagName('*');
var unique = function (list, x) {
if (x && list.indexOf(x) === -1) {
list.push(x);
}
return list;
};
var htmlclasses = [].reduce.call(elements, function (acc, e) {
if (e.classList.length > 0){
return [].slice.call(e.classList).reduce(unique, acc);
} else {
return acc;
}
}, []);
return htmlclasses;
}
Now the resulting array looks much better, I have in it "img-responsive".
Here is the whole code again:
function httpGet(theUrl) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false ); // false for synchronous request
xmlHttp.send( null );
return xmlHttp.responseText;
}
function getAllClasses() {
//get inline css classes
let headContent = document.getElementsByTagName('head')[0].innerHTML;
let classes = getAllCSSClasses(headContent);
//get external linraties
let csses = document.querySelectorAll('link[rel="stylesheet"]');
for (i = 0; i < csses.length; ++i) {
if (csses[i].href && csses[i].href.indexOf("cookieconsent") == -1){
let styledata = httpGet(csses[i].href);
let cclasses = getAllCSSClasses(styledata);
if ( cclasses instanceof Array )
classes = classes.concat( cclasses );
else
classes.push( cclasses );
}
}
return classes;
}
function getAllCSSClasses(cssdata) {
var re = /\.[a-zA-Z_][\w-_]*[^\.\s\{#:\,;]/g;
var m;
let classes = [];
do {
m = re.exec(cssdata);
if (m) {
for(let key in m) {
if(
(typeof m[key] == "string") &&
(classes.indexOf(m[key]) == -1) &&
(m[key].indexOf(".") == 0)
)
classes.push(m[key].replace(/\s/g, " "));
}
}
} while (m);
return classes;
}
function getHTMLUsedClasses() {
var elements = document.getElementsByTagName('*');
var unique = function (list, x) {
if (x && list.indexOf(x) === -1) {
list.push(x);
}
return list;
};
var htmlclasses = [].reduce.call(elements, function (acc, e) {
if (e.classList.length > 0){
return [].slice.call(e.classList).reduce(unique, acc);
} else {
return acc;
}
}, []);
return htmlclasses;
}
function getUndefinedClasses(cssclasses, htmlclasses) {
var undefinedclasses = [];
for (let key in htmlclasses) {
if(cssclasses.indexOf("." + htmlclasses[key]) == -1 ) {
undefinedclasses.push(htmlclasses[key]);
}
}
return undefinedclasses;
}
//console.log(cssclasses)
var cssclasses = getAllClasses();
var htmlclasses = getHTMLUsedClasses();
var un = getUndefinedClasses(cssclasses, htmlclasses);
console.log(un )
//copy(un);

Change select list to ul list.

I have a filterscript that is displayed as select dropdown. I would transform this to regular clickable text in a ul list. Is it possible to replace the select selector in the script somehow and keep the script intact?
<select id="ram" name="ram" class="select single" onchange="location.href=this.options[this.selectedIndex].value">
<option value="" selected="selected">Select / Reset</option>
<option value="2GB">2 GB</option>
<option value="4GB">4 GB</option>
<option value="8GB">8 GB</option>
</select>
Script:
$(document).ready(function(){
new function(settings) {
var $separator = settings.separator || '&';
var $spaces = settings.spaces === false ? false : true;
var $suffix = settings.suffix === false ? '' : '[]';
var $prefix = settings.prefix === false ? false : true;
var $hash = $prefix ? settings.hash === true ? "#" : "?" : "";
var $numbers = settings.numbers === false ? false : true;
jQuery.query = new function() {
var is = function(o, t) {
return o != undefined && o !== null && (!!t ? o.constructor == t : true);
};
var parse = function(path) {
var m, rx = /\[([^[]*)\]/g, match = /^([^[]+)(\[.*\])?$/.exec(path),base = match[1], tokens = [];
while (m = rx.exec(match[2])) tokens.push(m[1]);
return [base, tokens];
};
var set = function(target, tokens, value) {
var o, token = tokens.shift();
if (typeof target != 'object') target = null;
if (token === "") {
if (!target) target = [];
if (is(target, Array)) {
target.push(tokens.length == 0 ? value : set(null, tokens.slice(0), value));
} else if (is(target, Object)) {
var i = 0;
while (target[i++] != null);
target[--i] = tokens.length == 0 ? value : set(target[i], tokens.slice(0), value);
} else {
target = [];
target.push(tokens.length == 0 ? value : set(null, tokens.slice(0), value));
}
} else if (token && token.match(/^\s*[0-9]+\s*$/)) {
var index = parseInt(token, 10);
if (!target) target = [];
target[index] = tokens.length == 0 ? value : set(target[index], tokens.slice(0), value);
} else if (token) {
var index = token.replace(/^\s*|\s*$/g, "");
if (!target) target = {};
if (is(target, Array)) {
var temp = {};
for (var i = 0; i < target.length; ++i) {
temp[i] = target[i];
}
target = temp;
}
target[index] = tokens.length == 0 ? value : set(target[index], tokens.slice(0), value);
} else {
return value;
}
return target;
};
var queryObject = function(a) {
var self = this;
self.keys = {};
if (a.queryObject) {
jQuery.each(a.get(), function(key, val) {
self.SET(key, val);
});
} else {
self.parseNew.apply(self, arguments);
}
return self;
};
queryObject.prototype = {
queryObject: true,
parseNew: function(){
var self = this;
self.keys = {};
jQuery.each(arguments, function() {
var q = "" + this;
q = q.replace(/^[?#]/,''); // remove any leading ? || #
q = q.replace(/[;&]$/,''); // remove any trailing & || ;
if ($spaces) q = q.replace(/[+]/g,' '); // replace +'s with spaces
jQuery.each(q.split(/[&;]/), function(){
var key = decodeURIComponent(this.split('=')[0] || "");
var val = decodeURIComponent(this.split('=')[1] || "");
if (!key) return;
if ($numbers) {
if (/^[+-]?[0-9]+\.[0-9]*$/.test(val)) // simple float regex
val = parseFloat(val);
else if (/^[+-]?[0-9]+$/.test(val)) // simple int regex
val = parseInt(val, 10);
}
val = (!val && val !== 0) ? true : val;
self.SET(key, val);
});
});
return self;
},
has: function(key, type) {
var value = this.get(key);
return is(value, type);
},
GET: function(key) {
if (!is(key)) return this.keys;
var parsed = parse(key), base = parsed[0], tokens = parsed[1];
var target = this.keys[base];
while (target != null && tokens.length != 0) {
target = target[tokens.shift()];
}
return typeof target == 'number' ? target : target || "";
},
get: function(key) {
var target = this.GET(key);
if (is(target, Object))
return jQuery.extend(true, {}, target);
else if (is(target, Array))
return target.slice(0);
return target;
},
SET: function(key, val) {
var value = !is(val) ? null : val;
var parsed = parse(key), base = parsed[0], tokens = parsed[1];
var target = this.keys[base];
this.keys[base] = set(target, tokens.slice(0), value);
return this;
},
set: function(key, val) {
return this.copy().SET(key, val);
},
REMOVE: function(key) {
return this.SET(key, null).COMPACT();
},
remove: function(key) {
return this.copy().REMOVE(key);
},
EMPTY: function() {
var self = this;
jQuery.each(self.keys, function(key, value) {
delete self.keys[key];
});
return self;
},
load: function(url) {
var hash = url.replace(/^.*?[#](.+?)(?:\?.+)?$/, "$1");
var search = url.replace(/^.*?[?](.+?)(?:#.+)?$/, "$1");
return new queryObject(url.length == search.length ? '' : search, url.length == hash.length ? '' : hash);
},
empty: function() {
return this.copy().EMPTY();
},
copy: function() {
return new queryObject(this);
},
COMPACT: function() {
function build(orig) {
var obj = typeof orig == "object" ? is(orig, Array) ? [] : {} : orig;
if (typeof orig == 'object') {
function add(o, key, value) {
if (is(o, Array))
o.push(value);
else
o[key] = value;
}
jQuery.each(orig, function(key, value) {
if (!is(value)) return true;
add(obj, key, build(value));
});
}
return obj;
}
this.keys = build(this.keys);
return this;
},
compact: function() {
return this.copy().COMPACT();
},
toString: function() {
var i = 0, queryString = [], chunks = [], self = this;
var encode = function(str) {
str = str + "";
if ($spaces) str = str.replace(/ /g, "+");
return encodeURIComponent(str);
};
var addFields = function(arr, key, value) {
if (!is(value) || value === false) return;
var o = [encode(key)];
if (value !== true) {
o.push("=");
o.push(encode(value));
}
arr.push(o.join(""));
};
var build = function(obj, base) {
var newKey = function(key) {
return !base || base == "" ? [key].join("") : [base, "[", key, "]"].join("");
};
jQuery.each(obj, function(key, value) {
if (typeof value == 'object')
build(value, newKey(key));
else
addFields(chunks, newKey(key), value);
});
};
build(this.keys);
if (chunks.length > 0) queryString.push($hash);
queryString.push(chunks.join($separator));
return queryString.join("");
}
};
return new queryObject(location.search, location.hash);
};
}(jQuery.query || {}); // Pass in jQuery.query as settings object
function removeFSS() {
ga("send", "event", "button", "click", "filter-clear");
var t = encodeURI(unescape($.query.set("fss", '')));
var n = window.location.href.split("?")[0]; window.location.href = n + t
}
function getFSS() {
var D = jQuery('.filterGenius input, .filterGenius select').serializeArray();
var O = {};
jQuery.each(D, function(_, kv) {
if (O.hasOwnProperty(kv.name)) {
O[kv.name] = jQuery.makeArray(O[kv.name]);
O[kv.name].push(clean(kv.value, ""));
}
else {
O[kv.name] =kv.value;
}
});
var V = [];
for(var i in O)
if(jQuery.isArray(O[i]))
V.push(O[i].join("+"));
else
V.push(O[i]);
V = jQuery.grep(V,function(n){ return(n) });
return V.join("+");
}
$(document).ready(function () {
$(".filterGenius input").each(function () {
if (window.location.href.indexOf($(this).val()) >= 0) {
$(this).attr("checked", "checked")
}
});
$(".filterGenius select option").each(function () {
if (window.location.href.indexOf($(this).val()) >= 0) {
$(this).attr('selected', true);
}
});
$(".filterGenius input, .filterGenius select").change(function () {
var s = encodeURI(unescape(jQuery.query.set("fss", getFSS())));
var o = window.location.href.split("?")[0];
$(".filterGenius input, .filterGenius select").attr("disabled", true);
window.location.href = o + s
});
});
});
try to this way
$(function() {
$("<ul />").appendTo("nav");
$("nav select option").each(function() {
var el = $(this);
var li = $("<li />", {
"text" : el.text(),
}).appendTo("nav ul");
$(li).html('' + $(li).html() + '');
});
});
https://jsfiddle.net/99sgm51y/3/

How to filter multiple values (OR operation) in angularJS (continued)

I can across this very useful angular filter. I wanted to alter it so it removes any items that aren't explicitly filtered for. Right now if any key has a property which isn't recognized it ignores they key entirely. Essentially I want items filtered out if a key's property isn't present. For instance if $scope.searchName doesn't match it should be removed by the filter.
I got the filter here.
https://stackoverflow.com/a/21169596/2292822
<div ng-repeat="item in filtered = (items | filterMultiple:queryBy)>
Here is the relevant scope variables and filter
$scope.queryBy = {name:$scope.searchName, y1:$scope.selectedYear,y2:$scope.selectedYear,y3:$scope.selectedYear,y4:$scope.selectedYear};
myApp.filter('filterMultiple',['$filter',function ($filter) {return function (items, keyObj) {
var filterObj = {
data:items,
filteredData:[],
applyFilter : function(obj,key){
var fData = [];
if (this.filteredData.length == 0)
this.filteredData = this.data;
if (obj){
var fObj = {};
if (!angular.isArray(obj)){
fObj[key] = obj;
fData = fData.concat($filter('filter')(this.filteredData,fObj));
} else if (angular.isArray(obj)){
if (obj.length > 0){
for (var i=0;i<obj.length;i++){
if (angular.isDefined(obj[i])){
fObj[key] = obj[i];
fData = fData.concat($filter('filter')(this.filteredData,fObj));
}
}
}
}
if (fData.length > 0){
this.filteredData = fData;
}
}
}
};
if (keyObj){
angular.forEach(keyObj,function(obj,key){
filterObj.applyFilter(obj,key);
});
}
return filterObj.filteredData;}}]);
I made a few changes to the code, it works for me now, hopefully it works for you too!
myApp.filter('filterMultiple',['$filter',function ($filter) {return function (items, keyObj) {
var x = false;
var filterObj = {
data:items,
filteredData:[],
applyFilter : function(obj,key){
var fData = [];
if (this.filteredData.length == 0 && x == false)
this.filteredData = this.data;
if (obj){
var fObj = {};
if (!angular.isArray(obj)){
fObj[key] = obj;
fData = fData.concat($filter('filter')(this.filteredData,fObj));
} else if (angular.isArray(obj)){
if (obj.length > 0){
for (var i=0;i<obj.length;i++){
if (angular.isDefined(obj[i])){
fObj[key] = obj[i];
fData = fData.concat($filter('filter')(this.filteredData,fObj));
}
}
}
}
if (fData.length > 0){
this.filteredData = fData;
}
if (fData.length == 0) {
if(obj!= "" && obj!= undefined)
{
this.filteredData = fData;
x = true;
}
}
}
}
};
if (keyObj){
angular.forEach(keyObj,function(obj,key){
filterObj.applyFilter(obj,key);
});
}
return filterObj.filteredData;}}]);

An alternative method for JSON.stringify()

I want an alternative method for JSON.stringify().
I am using JSON.stringify and I got error like cyclic object value. I don't know how to remove this error so I'd like to know if there's an alternative method.
DCSSPACE.SaveAndOpenJSONWriter = function(canvas) {
//multiple tab.....
var mydata = [];
var area = {}, DCS = {}, workspace = {};
var len = DCSSPACE.collection.length;
for (var k = 0; k < len; k++) {
var result = [];
var tabid = DCSSPACE.collection.models[k].id;
var canvas = DCSSPACE.collection.get(tabid).get("workflow");
//for node
var figures = canvas.getFigures();
for (var i = 0; i < figures.getSize(); i++) {
if (figures.get(i).type == "draw2d.Node") {
var node = {};
node.blockType = getBlockType(figures.get(i));
node.x = figures.get(i).getX();
node.y = figures.get(i).getY();
node.id = figures.get(i).getId();
node.type = figures.get(i).type;
node.width = figures.get(i).getWidth();
node.height = figures.get(i).getHeight();
node.label = figures.get(i).getLabel();
node.sequenceNo = figures.get(i).getSequenceNo();
node.model = figures.get(i).model;
result.push(node);
}
}
//for lines
var lines = canvas.getLines();
for (var j = 0; j < lines.getSize(); j++) {
if (lines.get(j).type == "draw2d.nodeConnetion") {
var nodeConnection = lines.get(j).getConnectionAttrubutes();
nodeConnection.source = lines.get(j).getSource();
nodeConnection.target = lines.get(j).getTarget();
result.push(nodeConnection);
}
}
area = {
tabid : tabid,
attr : result
};
mydata.push(area);
result=[];
workspace = {
DCS : mydata
};
}
//console.log(mydata);
var arr = JSON.stringify(workspace, null, 4);
console.log(arr);
DCSSPACE.SaveAndLoadFigure = result;
return workspace;
};
If won't to use stringify you can reproduce it, like this:
OBJtoString(object [,n]) accempt 2 args:
object (needed) the object you need to log (in my release array and object is the same)
n numbero of space that indent every new line inside object aruments.
var OBJtoString = function(_o,_m,_rf,_dep,_res){
_dep = [],
_rf = function(obj,n,_n,_a,_k,_i,_ws,_f,_e){
if(typeof obj != "object") return false;
if(typeof _a === "undefined") _a = "FIRST PARENT OBJECT";
_dep.push(obj),
_f = (_dep.length < 1) ? function(){} : function(_z,_x){
for(_x = 0; _x <= _dep.length; _x++){
if(obj[_z] == _dep[_x]) return true;
}
return false;
}
_ws = "";
if(typeof n === "undefined") n = 1;
if(typeof _n === "undefined") _n = n;
for(_k = 0; _k <= n; _k++){
_ws += " ";
}
var response ="{ \n";
for(var _i in obj){
if(typeof obj[_i] !== "object"){
if(typeof obj[_i] === "string") obj[_i] = "'"+obj[_i].toString()+"'";
if(typeof obj[_i] === "boolean") obj[_i] = obj[_i].toString() + " (boolean)";
response += _ws + _i + " : " + obj[_i].toString();
response += "\n";
continue;
}
response += (_f(_i)) ? _ws + _i + " : "+ _a +" (prevent loop)\n" : _ws + _i + " : " + _rf(obj[_i],n+_n,_n,_a);
}
if(_n != n) response += _ws;
return response +="} \n";
}
_res = _rf(_o,_m);
_dep = [];
return _res;
}
Uses Example:
var example = {ciao : "hellow", saluto : {ciao : "ciao", dam : true}};
example.parentObj = example;
console.log(OBJtoString(example,4));
return:
{
ciao : 'hellow'
saluto : {
ciao : 'ciao'
dam : true (boolean)
}
parentObj : FIRST PARENT OBJECT (prevent loop)
}
Other Example:
var example = {ciao : "hellow", saluto : {ciao : "ciao", dam : true}};
example.parentObj = example;
example.f = {
g : example
}
console.log(OBJtoString(example,4));
Return:
{
ciao : 'hellow'
saluto : {
ciao : 'ciao'
dam : true (boolean)
}
parentObj : FIRST PARENT OBJECT (prevent loop)
f : {
g : FIRST PARENT OBJECT (prevent loop)
}
}
I found util.inspect() pretty helpful.
You can print entire object
console.log(util.inspect(myObj))
Or with optional arguments
util.inspect(object, showHidden=false, depth=2, colorize=true)
Documentation:
https://nodejs.org/en/knowledge/getting-started/how-to-use-util-inspect/

special case of serializing form to a javascript object

building upon the $.fn.serializeObject() function from this question, i'd like to be able to support "dot notation" in my form names, like so:
<form>
<input name="Property.Items[0].Text" value="item 1" />
<input name="Property.Items[0].Value" value="1" />
<input name="Property.Items[1].Text" value="item 2" />
<input name="Property.Items[1].Value" value="2" />
</form>
given that $('form').serializeArray() produces the following:
[{"name":"Property.Items[0].Text","value":"item 1"},
{"name":"Property.Items[0].Value","value":"1"},
{"name":"Property.Items[1].Text","value":"item 2"},
{"name":"Property.Items[1].Value","value":"2"}]
how could i achieve the desired result below:
{Property: {Items: [{Text: 'item 1', Value: '1'},
{Text: 'item 2', Value: '2'}]} }
any help would be appreciated.
EDIT:
to be specific, the desired code would be added to the serializeObject extension so that in addition to the way it works now, it would also support the above convention. here's the existing method for convenience.
$.fn.serializeObject = function() {
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name]) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
EDIT 2:
feeding off the answer provided, here's my current implementation:
$.fn.serializeObject = function() {
var o = {};
var a = this.serializeArray();
var regArray = /^([^\[\]]+)\[(\d+)\]$/;
$.each(a, function(i) {
var name = this.name;
var value = this.value;
// let's also allow for "dot notation" in the input names
var props = name.split('.');
var position = o;
while (props.length) {
var key = props.shift();
var matches;
if (matches = regArray.exec(key)) {
var p = matches[1];
var n = matches[2];
if (!position[p]) position[p] = [];
if (!position[p][n]) position[p][n] = {};
position = position[p][n];
} else {
if (!props.length) {
if (!position[key]) position[key] = value || '';
else if (position[key]) {
if (!position[key].push) position[key] = [position[key]];
position[key].push(value || '');
}
} else {
if (!position[key]) position[key] = {};
position = position[key];
}
}
}
});
return o;
};
you can see it in action here
This solution is a bit static. But it should do the trick:
var serialized = $.fn.serializeObject(),
properties = {},
property = [],
position = {},
key = '',
n = 0,
matchName = '',
i = 0;
for (i = 0; i < serialized.length; i += 1) {
property = serialized[i].name.split('.');
position = properties;
while (property.length) {
key = property.shift();
if (key.match(/\[\d+\]/) && key.match(/\[\d+\]/).join().match(/\d+/g) ) {
matchName = key.match(/\w+/)[0]
n = parseInt(key.match(/\[\d+\]/).join().match(/\d+/g), 10);
if (!position[matchName]) {
position[matchName] = [];
}
if (!position[matchName][n]) {
position[matchName][n] = {}
}
position = position[matchName][n]
} else {
if (!property.length) {
position[key] = serialized[i].value
} else {
if (!position[key]) {
position[key] = {};
}
position = position[key]
}
}
}
}
console.log(properties);

Categories

Resources