Proper approach for complex / nested JavaScript-object creation within another object - javascript

The following code is meant to be a short example for a simple construct of a reusable object. This is a very simple, one level depth object, put as many props and methods as you like and just assign them.
function someDesiredReusableType(optionally, pass, ctor, pars, here) {
//core obj to return
var DesiredTypeCrtor = {
propSkiingLocation: "canada",
OrderTickets: function(optionally){
var tryRoomWView = optionaly;
print(
"Dear " + ctor +", your request for " +
propSkiingLocation + " is now being processed: an " +
tryRoomWView + " request was notified, we understand you have " + pars + " for cross country transportation, confirmation email will be sent " + here + " as soon as we process your order. }
}
};
return DesiredTypeCrtor
}
Here is an example of this use:
var DesrVacSkC = someDesiredReusableType("could really help!",null, "mr. Bean", "my mini", "Fun#bbc.co.uk")
//oh..almost forgot
DesrVacSkC.OrderTickets();
As this imaginative object, is actually not as simple as I did use in my code, it does work as is (didn't try this actual one, as it's just an example.)
But this next setup that is similarly using the same approach is buggy somewhat.
This is an example for an object I have successfully and in a blink of an eye implemented as a nested object using the exact same approach as the buggy object, which I do not understand why they Applied the not with same approach by the browser.
//this is an important one, a smart property / value holder I came up with and does work perfectly, as a nested member.
function Rprp(parVal) {
var cretdprp = {
propVal: parVal,
propValAsint: parseInt(parVal)
};
return cretdprp;
}
But the next one, here below, does not, as it lacks the proper approach for the initialization of ownedFefCollCore
Uncaught TypeError: Cannot read property 'HElmTColl' of undefined
//this is an important one, that was started as a very good one, with adding it to the object below, up until I have added ownedFefCollCore member.
function CreateFileEditForm_Manager() {
//as i do usually base/inner/creator and a return obj
var Repo = {
CsDataLocals:
{
GetCurLastfileId:Rprp($("#HLocModelData_LastFileId").val())
},
FormFldNames:
{ JRdrData_FileName: "JRdrData_FileName" },
//this is my bugg ! with and without new keyword & as function or Object!!
ownedFefCollCore: new FefCollCore(),
//and this is the line that chrome get's is anger on --> all day long
FeFDivWFldsColl: this.ownedFefCollCore.HElmTColl,
FeFDivWFlds_IdColl: this.ownedFefCollCore.HElmT_IdColl,
FeFDivWFldsCollAdd: function (parId, parFefDivWrpDivflds) {
this.ownedFefCollCore.CollAdd(parId, parFefDivWrpDivflds);
},
/ ........
//some more code was removed trying to keep it as short as possible
}
//fefa stands for fileRecord Edit Form , core just says nothing, is there to imply the 'thing' is to be shared between variation of instances from the base object
I found the following approach in my research for less error prone constructs, but even this one does not correct the bug. And it was found among some others, such as this Object.create()
var FefCore = JClassProto({
initialize: function () {
this.HElmTColl = new Array();//was originally [] ...
//i changed because i wanted to eliminate any doubt that it's one of the reasons my code is ... Somewhere undefined , now i know (pretty sure they might be little different but both are ok.) it's not it.
this.HElmT_IdColl = new Array();
this.CollAdd = function (parId, parHElmT) {
this.HElmTColl.push(parHElmT);
this.HElmT_IdColl.push(parId);
}
this.Coll_Remove = function (parHElmT) {
this.HElmTColl.pop(parHElmT);
}
// this is the first move, if a new object(which is an element in the array) about to be created,
// call this to make sure not exist for i create do
this.ElmObjCanCreate = function (parId) {
return this.getIndexOfValuInDivWFldsColl(parId) < 0;
}
this.HElmTColl_FindById = function (parId) {
var collindexofCurFileReadyDivWrpFlds = this.getIndexOfValuInDivWFldsColl(parId);
return this.HElmTColl[collindexofCurFileReadyDivWrpFlds];
}
this.getIndexOfValuInHElmTColl = function (parId) {
return $.inArray(parId, this.HElmT_IdColl);
}
}
});
And last but not least, my original code (right after the attempt to create it as a base /shared object).
function FefCollCore() {
this.Cr = {
HElmTColl: new Array(),
HElmT_IdColl: new Array(),
CollAdd: function (parId, parHElmT) {
this.HElmTColl.push(parHElmT);
this.HElmT_IdColl.push(parId);
},
Coll_Remove: function (parHElmT) {
this.HElmTColl.pop(parHElmT);
},
CollNeedCreate: function (parId) {
return this.getIndexOfValuInDivWFldsColl(parId) < 0;
},
HElmTColl_FindById: function (parId) {
var collindexofCurFileReadyDivWrpFlds = this.getIndexOfValuInDivWFldsColl(parId);
return this.HElmTColl[collindexofCurFileReadyDivWrpFlds];
},
getIndexOfValuInHElmTColl: function (parId) {
return $.inArray(parId, this.HElmT_IdColl);
}
};
return this.Cr;
}

//and this is the line that chrome get's is anger on --> all day long
FeFDivWFldsColl: this.ownedFefCollCore.HElmTColl,
If interpret Question correctly, you could try to set FeFDivWFldsColl as a function that returns this.ownedFefCollCore.HElmTColl
var FefCore = function() {
this.e = new Array();
this.e.push(2);
}
function CreateFileEditForm_Manager() {
var Repo = {
a: 0,
b: 1,
c: new FefCore(),
// set `FeFDivWFldsColl` value as a function
d: function() {
// `this.c` : `new FefCore()` , `this.c.e` : `new Array()`
return this.c.e
}
};
return Repo
}
var Fef = new CreateFileEditForm_Manager();
console.log(Fef.d())

var cont = "...see console";
var DivEmptyhtml = document.createElement('div');
var elmst = document.createElement('style');
function stringcss (){
return ".cssEmptyhtml{ \r\n\tmargin:auto; margin-top:10px; margin-bottom:20px;"+
" text-align:center; top:10px;"+
" width:40%; padding: 5px; height: 100px; " +
"background-color:rgb(96,116,243); "+
"color: #B5fee8; "+
"background-image:" +
" linear-gradient(to right bottom, #2983bC 24%, #284a4b 77%);"+
" box-shadow: 8px 10px 50px 20px rgb(55, 55, 55); "+
" -webkit-border-radius:10px;border-radius:10px; }";
}
//elmst.innerHTML = stringcss();
DivEmptyhtml.innerHTML = cont;
DivEmptyhtml.className = "cssEmptyhtml";
DivEmptyhtml.attributes["id"] ="DivEmptyhtml";
$("head").append(elmst);
$("body").append(DivEmptyhtml);
$(elmst).attr("id","elmst");
//$(".cssEmptyhtml").attr("style",stringcss());
$(elmst).text(stringcss());
var strS, strF, message;
var indx = 123;
var count = 135;
indx = ++count - 1;
var init = true;
//now me
var programSteps = 0;
var starting = "starting";
console.log(starting);
function Log(strLine) {
var d = new Date,
DS = d.getSeconds(),
Dms = d.getMilliseconds().toString();
console.log("[step#" + (++programSteps) + "] " + DS + "." + Dms.substring(0, 2) + "> " + strLine);
}
//...see console
function LogObj(p_type) {
function Fnl_t_t() {
this.obj = "\r\n\t\t";
}
function Fnl_5xt() {
this.obj = "\r\n\t\t\t\t";
}
var obj = {
doNewLineBold: function(boolPrint, value, value2, value3, value4) {
var nlttcopy = this.backnl_t_t.obj;
this._nl_t_t = lnobj1.backnl_5xt.obj+ "|========> [ " + value;
this._nl_t_t += value2 != "" ? " " + value2 : "";
this._nl_t_t += value3 != "" ? " " + value3 : "";
this._nl_t_t += value4 != "" ? " " + value4 : "";
this._nl_t_t += " ] <=============|" + nlttcopy;
if (boolPrint) {
Log(this._nl_t_t);
return "";
} else return this._nl_t_t;
},
doLineBold: function(boolPrint, value, value2, value3, value4) {
var nlttcopy = this.backnl_t_t.obj;
this._nl_t_t = "|========> [ " + value;
this._nl_t_t += value2 != "" ? " " + value2 : "";
this._nl_t_t += value3 != "" ? " " + value3 : "";
this._nl_t_t += value4 != "" ? " " + value4 : "";
this._nl_t_t += " ] <=============|" + nlttcopy;
if (boolPrint) {
Log(this._nl_t_t);
return "";
} else return this._nl_t_t;
},
_type: {
val: p_type,
formated: ""
},
doformatedHeader: function() {
var splts = this._type.val.split(' ');
for (var i = 0; i < splts.length; i++) {
this._type.formated += splts[i] + this.ErowR;
}
return "|========> [ " + this._type.formated +
" ] <=============|" + this.backnl_5xt.obj;
},
doformatedTail: function() {
return this.backnl_5xt.obj + "|========> [ END_ " + this._type.formated + "_END] <=============|" + this.backnl_t_t.obj;
},
_nl_t_t: function() {
return "\r\n\t\t";
},
backnl_5xt: new Fnl_5xt(),
backnl_t_t: new Fnl_t_t(),
ErowR: ">",
nlArowR : new Fnl_5xt().obj + ">"
};
return obj;
}
var lnobj1 = LogObj("listWcounter1() arr"); //create object #1
var lnobj2 = LogObj("listWcounter2() arr"); //make sure #2 is not a-copy
var header1 = lnobj1.doformatedHeader();
var Tail1 = lnobj1.doformatedTail();
var header2 = lnobj2.doformatedHeader();
var Tail2 = lnobj2.doformatedTail();
var nlarowR1 = lnobj1.backnl_5xt.obj + lnobj1.ErowR;
var nlarowR2 = lnobj2.backnl_t_t.obj + lnobj2.ErowR;
Log(header1 + lnobj1.ErowR + " starting1... " + nlarowR1 + " is init1 ok?, and index1 is Ok? " + indx + Tail1);
Log(header2 + lnobj2.ErowR + " starting2... " + nlarowR1 + " is init2 ok?, and index2 is Ok? " + indx + Tail2);
var newbold = lnobj1.doLineBold(0, "a", "b", "c", "d") + lnobj1.backnl_5xt.obj;
Log("newbold looks Like: " + newbold);
lnobj1.doLineBold(1, "A", "B", "C", "D");
lnobj1.doNewLineBold(1, "e", "f", "g", "h");
Log(lnobj1.nlArowR);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

Related

Is it possible to load build result in VS Output window?

I was been trying to switch IDEs.
What if I will want to load MISRA check result file to Visual Studio.
Is there any direct or simpler way?
Made indirect workaround:
var fso = new ActiveXObject("Scripting.FileSystemObject");
var rootPath = fso.GetFolder(".");
var cStat = rootPath.files;
for(var objEnum = new Enumerator(cStat); !objEnum.atEnd(); objEnum.moveNext()) {
var strFileName = objEnum.item();
if (strFileName.ShortName.length - strFileName.ShortName.toUpperCase().indexOf(".TXT") != 4) continue;
//WScript.Echo(strFileName);
break;
}
var ts = strFileName.OpenAsTextStream(1);
while(!ts.AtEndOfStream) {
var textLine = ts.ReadLine();
textLine = textLine.split('\t'); // IAR MISRA line: Description Rule Severity File:Line
if (textLine[3])
{
var res = textLine[3].replace(/(.+):(\d+)/g, "$1($2)");
if (textLine[2] == "Low")
{
res += ": warning " + textLine[1] + ": " + textLine[0];
}
else
{
res += ": error " + textLine[1] + ": " + textLine[0] + ' ' + textLine[2];
}
WScript.Echo(res);
}
}
ts.Close();
Using fake NMAKE project with build command like cscript /NoLogo PrintLog.js.
Now I can open files reported by MISRA in VS by copying export txt file to this project and running build.
Similar older IAR warning(s) filter used as pipe by command:
...\iarbuild "project.ewp" ReleaseCfg | cscript /NoLogo IARfilterPipe.js.
var fso = new ActiveXObject("Scripting.FileSystemObject");
var rootPath = fso.GetFolder(".") + '\\';
var x = oldBad(), skip = {};
for (i in x) skip[x[i]] = 1;
var stat = [0, 0], all = [], newWarnings = [];
do {
var line = WScript.StdIn.ReadLine();
if (line.indexOf('[') > 0) // possible warning line
{
all.push(line);
line = line.replace(rootPath, "");
var fit = 0;
if (line.indexOf("Remark[") > -1)
{
fit++;
stat[0]++;
line = line
.replace(/\d+>\s+/g, "")
.replace(/Remark\[(\S+)\]:/g, "Warning $1:");
}
else if (line.indexOf("Error[") > -1)
{
fit++;
stat[1]++;
line = line
.replace(/\d+>\s+/g, "")
.replace(/Error\[(\S+)\]:/g, "Error $1:");
}
if (skip[line] != 1 && fit)
{
newWarnings.push(line);
WScript.Echo('!' + line);
var m = line.match(/\s*[^\s.]+\.(s|cpp|c)/g)
} else {
WScript.Echo('_' + line);
}
}
else {
var m = line.match(/\s*[^\s.]+\.(s|cpp|c)/g)
if (m == null) // no name.ext
{
WScript.Echo(line);
}
else if (m.length == 1) // single filename
{
all.push(line);
}
}
} while (!WScript.StdIn.AtEndOfStream);
if (all.length)
{
all = all.sort();
writeFile("buildFiles.txt", all.join('\n'));
}
if (newWarnings.length)
{
writeFile("newWarnings.txt", newWarnings.join('\n'));
WScript.Echo("========== New warnings: ==========");
}
for(var l in newWarnings)
{
WScript.Echo(newWarnings[l]);
}
if (stat[0] + stat[1])
{
WScript.Echo("========== Build Result - Warnings " + stat[0] + " Errors " + stat[1] + " ==========");
}
WScript.Quit(0); // (do not work from file after Echo => -1)
function writeFile(filename, content)
{
var TextStream = fso.CreateTextFile(filename);
TextStream.Write(content);
TextStream.Close()
}
function oldBad()
{
return [
'somefile.cpp(42) : Warning Pe340: value copied to temporary, reference to temporary used', ...
];
}

javascript error in nifi executeScript

I am having an issue getting the javascript script for the executeScript nifi process to work and would appreciate help with this. The goal is to pass a flowfile which will contain a json object. I need to parse this json without knowing the content/fields prior and pass this along to write it out to the flowfile that is being passed out to the next process that is MergeContent and counts the number flowfiles.
Tried testing the script and got the following error:
nifi.script.ExecuteScript - ExecuteScript[id=bd6842e9-e3a4-4d88-a59d-
7da1d74d109b] ExecuteScript[id=bd6842e9-e3a4-4d88-a59d-7da1d74d109b]
failed to process due to
org.apache.nifi.processor.exception.ProcessException:
javax.script.ScriptException: <eval>:21:17 Expected : but found value
let value = json[key];
^ in <eval> at line number 21 at column number 17; rolling
back session: org.apache.nifi.processor.exception.ProcessException:
javax.script.ScriptException: <eval>:21:17 Expected : but found value
I am not very familiar with javascript so would appreciate the help.
flowFile = session.get();
if (flowFile != null) {
var StreamCallback =
Java.type("org.apache.nifi.processor.io.StreamCallback");
var IOUtils = Java.type("org.apache.commons.io.IOUtils");
var StandardCharsets = Java.type("java.nio.charset.StandardCharsets");
var transformed_message = {};
var error = false;
var line = "ops_testQueue";
flowFile = session.write(flowFile, new StreamCallback(function
(inputStream, outputStream) {
var content = IOUtils.toString(inputStream,
StandardCharsets.UTF_8); // message or content
var message_content = {};
try {
message_content = JSON.parse(content);
if(Array.isArray(message_content)){
}
Object.keys(message_content).forEach((key) => {
var value = json[key];
result.push(key + '=' + value);
var jkey = "," + "\"" + key + "\"" + '=' + value
});
line = line + jkey +
" value=" + "1"
+ " " + Date.now() * 1000000;
// Write output content
if (transformed_message) {
outputStream.write(line.getBytes(StandardCharsets.UTF_8));
}
} catch (e) {
error = true;
outputStream.write(content.getBytes(StandardCharsets.UTF_8));
}
}));
if (transformed_message.post_state) {
flowFile = session.putAttribute(flowFile, "type",
transformed_message.type);
}
if (error) {
session.transfer(flowFile, REL_FAILURE)
} else {
session.transfer(flowFile, REL_SUCCESS)
}
}
EDIT:
input to executeScript:
{"pID":"1029409411108724738",
"contentType":"text",
"published":"2018-08-14 16:48:23Z",
"crawled":"2018-08-14 12:48:33-04:00",
"ID":"765"}
output from executeScript:
ops_testQueue,"ID"=765 value=1 1534265314969999870
Am I missing something?
I saw a couple of things here:
I don't know if Nashorn (Java's JS Engine) supports the full lambda
syntax, I was able to get it to work by making the lambda a function
(see script below).
You refer to a json variable to get the value from a key, but I think you want message_content.
result is not defined, so you get an error when you push to it.
Here's an edited version of your script that I got to work the way I think you want it (but please correct me if I'm wrong):
flowFile = session.get();
if (flowFile != null) {
var StreamCallback =
Java.type("org.apache.nifi.processor.io.StreamCallback");
var IOUtils = Java.type("org.apache.commons.io.IOUtils");
var StandardCharsets = Java.type("java.nio.charset.StandardCharsets");
var transformed_message = {};
var error = false;
var line = "ops_testQueue";
flowFile = session.write(flowFile, new StreamCallback(function
(inputStream, outputStream) {
var content = IOUtils.toString(inputStream,
StandardCharsets.UTF_8); // message or content
var message_content = {};
try {
message_content = JSON.parse(content);
if(Array.isArray(message_content)){
}
var jkey = "";
Object.keys(message_content).forEach(function(key) {
var value = message_content[key];
//result.push(key + '=' + value);
jkey = "," + "\"" + key + "\"" + '=' + value
});
line = line + jkey +
" value=" + "1"
+ " " + Date.now() * 1000000;
// Write output content
if (transformed_message) {
outputStream.write(line.getBytes(StandardCharsets.UTF_8));
}
} catch (e) {
error = true;
log.error(e);
outputStream.write(content.getBytes(StandardCharsets.UTF_8));
}
}));
if (transformed_message.post_state) {
flowFile = session.putAttribute(flowFile, "type",
transformed_message.type);
}
if (error) {
session.transfer(flowFile, REL_FAILURE)
} else {
session.transfer(flowFile, REL_SUCCESS)
}
}

Splitting out xml result into dropdownlist

Hope someone can help - I'm new to js/jQuery so I'm hoping it's something really simple I'm missing here.
I'm trying to populate a dropdownlist with the xml result from below. The parseXML function works great and the result.push(valueid + "," + value) leaves me with the following:
1,Service
2,Breakdown
How do I get this into a dropdownlist please? Using the below, I get the error "Object doesn't support property or method 'split'"
Many thanks
leddy
function testFunction() {
var jobresults = "<resultset morerecords='0'> " +
"<result> " +
"<itt_jobtypeid>1</itt_jobtypeid> " +
"<itt_name>Service</itt_name> " +
"</result> " +
"<result> " +
"<itt_jobtypeid>2</itt_jobtypeid> " +
"<itt_name>Breakdown</itt_name> " +
"</result> " +
"</resultset> ";
var xml = parseXML(jobresults);
var jobid = xml.getElementsByTagName("itt_jobtypeid");
var jobname = xml.getElementsByTagName("itt_name");
var result = [];
for (var i = 0; i < jobid.length; i++) {
var valueid = jobid[i].childNodes[0].nodeValue;
var value = jobname[i].childNodes[0].nodeValue;
// add longitude value to "result" array
result.push(valueid + "," + value);
}
var jobtype = $("#ddlJobType");
$.each(result, function () {
var arr = result.split(',');
for (var i = 0; i < arr.length; i++) {
jobtype.append($("<option />").val(arr[0]).text(arr[1]));
}
});
}
function parseXML(text) {
if (window.DOMParser) {
parser = new DOMParser();
doc = parser.parseFromString(text, "text/xml");
}
else { // Internet Explorer
doc = new ActiveXObject("Microsoft.XMLDOM");
doc.async = "false";
doc.loadXML(text);
}
return doc;
}
It can be simpler and cleaner if you optimize data structure for result array. Push an object with value and label so that you can simply use attr method directly after:
for (var i = 0; i < jobid.length; i++) {
var valueid = jobid[i].childNodes[0].nodeValue;
var value = jobname[i].childNodes[0].nodeValue;
// add longitude value to "result" array
result.push({value: valueid, label: value});
}
var jobtype = $("#ddlJobType");
$.each(result, function (i, obj) {
$('<option>').attr(obj).appendTo(jobtype);
});
See https://api.jquery.com/jquery.each/. The callback function gets each jobtype as parameter to the function.
Try changing the code to:
$.each(result, function (idx, value) {
var arr = value.split(',');
for (var i = 0; i < arr.length; i++) {
jobtype.append($("<option />").val(arr[0]).text(arr[1]));
}
});

Closure inside loop - not sure how to address

for (var i = 0; i < stops.length; i++) {
var code = stops[i].atcocode;
var name = stops[i].common;
var direction = stops[i].direction;
var alertMessage = "View departures for " + stops[i].common + (directionText !== 'Unknown' ? (" (facing " + directionText + ")") : "") + "?";
this.map.addMarker({
icon: icon,
position: new plugin.google.maps.LatLng(stops[i].latitude, stops[i].longitude)
}, function(markerCallback) {
markerCallback.code = code;
markerCallback.name = name;
markerCallback.direction = direction;
markerCallback.alert = alertMessage;
markerCallback.addEventListener(plugin.google.maps.event.MARKER_CLICK, function(clickedMarker) {
alert(markerCallback.name);
});
_this.busStopMarkers.push(markerCallback);
});
}
JavaScript closure inside loops – simple practical example
I have viewed the question above and am not sure how to apply the same answer logic into my scenario. Could somebody please show me an example as to how I can make the alert show the indexed item in the array rather than the last one?
Create a callback factory:
function createCallback(_this, code, name, direction, alertMessage) {
return function(markerCallback) {
markerCallback.code = code;
markerCallback.name = name;
markerCallback.direction = direction;
markerCallback.alert = alertMessage;
markerCallback.addEventListener(plugin.google.maps.event.MARKER_CLICK, function(clickedMarker) {
alert(markerCallback.name);
});
_this.busStopMarkers.push(markerCallback);
};
}
Then use it to create a function inside your loop:
for (var i = 0; i < stops.length; i++) {
var code = stops[i].atcocode;
var name = stops[i].common;
var direction = stops[i].direction;
var alertMessage = "View departures for " + stops[i].common + (directionText !== 'Unknown' ? (" (facing " + directionText + ")") : "") + "?";
var callback = createCallback(_this, code, name, direction, alertMessage);
this.map.addMarker({
icon: icon,
position: new plugin.google.maps.LatLng(stops[i].latitude, stops[i].longitude)
}, callback);
}
You can create an anonymous function like this:
for (var i = 0; i < stops.length; i++) {
(function(me, stop){ // Use the stop as an argument, this function is directly called
var code = stop.atcocode;
var name = stop.common;
var direction = stop.direction;
var alertMessage = "View departures for " + stop.common + (directionText !== 'Unknown' ? (" (facing " + directionText + ")") : "") + "?";
me.map.addMarker({
icon: icon,
position: new plugin.google.maps.LatLng(stop.latitude, stop.longitude)
}, function(markerCallback) {
markerCallback.code = code;
markerCallback.name = name;
markerCallback.direction = direction;
markerCallback.alert = alertMessage;
markerCallback.addEventListener(plugin.google.maps.event.MARKER_CLICK, function(clickedMarker) {
alert(markerCallback.name);
});
_this.busStopMarkers.push(markerCallback);
});
})(this, stops[i]); // Pass the stop
}

building a database string

I'm trying to build a database based on some arbitrary data on a website. It's complex and changes for each site so I'll spare the details. Here's basically what I'm trying to do
function level0(arg) { textarea.innerHTML += arg + ' = {'; }
function level1(arg) { textarea.innerHTML += '\n\t' + arg + ': ['; }
function level2(arg) { textarea.innerHTML += arg + ', '; }
And so on. The thing is some level1's don't have any children and I can't get the formatting right.
My three problems are as follows.
The ending commas are going to break in IE (thank you MS)
Empty level1's shouldn't be printed if they don't have any children
Closing /curly?brackets/
HERE'S A DEMO of what I have so far. Notice the ending commas, the empty sub2 which shouldn't be printed, and no closing brackets or braces
Do I need to redesign the entire thing?
Is there also a way to have this all in one function so I don't have to worry if I add another layer?
EDIT
This needs to be done in a string format, I can't build an object and then stringify it, mostly because I need to know which element I'm in the middle of adding to.
Overall it looks that you still might want to build an object, but in case you insist on not building it - here is some sample solution:
function Printer() {
var result = '',
lastLevel = null,
close = {0:'\n}', 1:']', 2:''},
delimiter = {0: ',\n', 1:',\n', 2:','};
function closeLevel(level, noDelimiter) {
if(lastLevel === null)
return;
var l = lastLevel, d = level == lastLevel;
while(l >= level) {
result += close[l] + (l == level && !noDelimiter ? delimiter[l]:'');
l--;
}
}
this.level0 = function(arg) {
closeLevel(0);
result += arg + ' = {\n';
lastLevel = 0;
};
this.level1 = function(arg) {
closeLevel(1);
result += '\t' + arg + ': [';
lastLevel = 1;
};
this.level2 = function(arg) {
closeLevel(2);
result += arg;
lastLevel = 2;
};
this.getResult = function() {
closeLevel(lastLevel, true);
return result;
}
}
var p = new Printer();
p.level0('head');
p.level1('sub1');
p.level2('item1');p.level2('item2');p.level2('item3');
p.level1('sub2');
p.level1('sub3');
p.level2('newthing');
p.level0('head2');
document.getElementById('textarea').value = p.getResult();
You could see it in action here.
I'm not sure why you're building what looks like objects with nested arrays, using string concatenation. Something like this would be much simpler, since it wouldn't require fixing trailing commas, etc:
Edit: I've updated the code to make it keep track of the last level put in.
function Db() {
var level0, level1;
var data = new Object();
this.level0 = function(arg) {
level0 = new Object();
data[arg] = level0;
}
this.level1 = function(arg) {
level1 = new Array();
level0[arg] = level1;
}
this.level2 = function(arg) {
level1.push(arg);
}
this.toString = function() {
var s = '';
for(i in data) {
s += i + '\n';
for(j in data[i]) {
if(data[i][j].length>0) {
s += '\t' + j + ': [' + data[i][j] + ']\n' ;
}
}
}
return s;
}
}
Use like this:
var db = new Db();
db.level0('head');
db.level1('sub1');
db.level2('item1');db.level2('item2');db.level2('item3');
I've tested this in the demo you linked and it works just fine.

Categories