The problem that I had with laying down javascript functions in c++ was very similar in nature to the problem one of html; i.e. having escape characters all over the place or producing virtually unreadable code. Thankfully the problem was much easier to solve with a class of less than 100 lines of code; And while it is fairly dumb, it will suffice for what I need to do with it.
#include "jsfunction.h"
#include "ic_core.h"
using std::string;
jsfunction::jsfunction(string fcnDeclaration)
:
m_fcnDeclaration(fcnDeclaration) {
}
void jsfunction::add_line(std::string lineString) { m_fcnLines.push_back(lineString);}
void jsfunction::add_line_break() { m_fcnLines.push_back("");}
string jsfunction::js_function(int indent, bool appendNewLine) {
string jFcn("\n");
int tabstops = 0;
if(indent)
jFcn.append(indent, '\t');
jFcn.append("function " + m_fcnDeclaration + " {\n\n");
for(string &it : m_fcnLines) {
it = cleanstring(it);
//SORT OUT INDENTATION
if((it.back() == '}') && (it.front() != '{')) --tabstops;
if(indent) {
jFcn.append(indent + tabstops +1, '\t');
jFcn.append(it + "\n");
}
else {
jFcn.append("\t" +it + "\n");
}
if(it.back() == '{') ++tabstops;
}
jFcn.append("\n");
if(indent)
jFcn.append(indent, '\t');
jFcn.append("}");
if(appendNewLine)
jFcn.append("\n\n");
return(jFcn);
}
This is quite literally it, and to use it you simply create an instance with a javascript function name, add lines with the add_line() method and add line brakes using the add_line_break() method. When you are done you call js_function() with the desired number of indents and you have a string that you can put in a node of your formatted html_tree.
The add_line() method adds each line literally, this class purely handles the formatting so
jsfunction nav("nav(name, value, url)");
nav.add_line("var form = document.createElement(\"form\");");
nav.add_line("form.setAttribute(\"method\", \"post\");");
nav.add_line("form.setAttribute(\"action\", url);");
nav.add_line_break();
nav.add_line("var jobId = document.createElement(\"input\");");
nav.add_line_break();
nav.add_line("jobId.setAttribute(\"type\", \"hidden\");");
nav.add_line("jobId.setAttribute(\"name\", name);");
nav.add_line("jobId.setAttribute(\"value\", value);");
nav.add_line_break();
nav.add_line("form.appendChild(jobId);");
nav.add_line("document.body.appendChild(form);");
nav.add_line("form.submit();");
nav.jsfunction();
will create a function that will look like:
function nav(name, value, url) {
var form = document.createElement("form");
form.setAttribute("method", "post");
form.setAttribute("action", url);
var jobId = document.createElement("input");
jobId.setAttribute("type", "hidden");
jobId.setAttribute("name", name);
jobId.setAttribute("value", value);
form.appendChild(jobId);
document.body.appendChild(form);
form.submit();
}
The class can easily handle more complex function with brackets “{” and “}” and will indent your code in a reasonable manner. without the need for spacing.
jsfunction cbState("resolved_state()");
cbState.add_line("var resolved = \""+ std::to_string(faults::PENDING) + "\";");
cbState.add_line("if(document.getElementById(\"faultstat\").checked) {");
cbState.add_line("resolved = \"" + std::to_string(faults::RESOLVED_EXT) + "\";");
cbState.add_line("}");
cbState.add_line_break();
cbState.add_line("return(resolved);");
will produce
function resolved_state() {
var resolved = "pending";
if(document.getElementById(\"faultstat\").checked) {
resolved = resolved;
}
return(resolved);
}
It is not idea, but then again, I don’t suppose writing javascript functions in c++ could ever be ideal and it is a little better than the alternatives of raw strings containing c++ variables, or strings littered with escape characters.
Event Listeners:
This is a function that was thrown together that has not been exhaustively tested. it is not part of the jsfunction class although it does rely on it. jsevent takes a number of arguments in order to create an event listener.
string jsevent::jsevent(
std::string element,
std::string event,
jsfunction &function,
bool useCapture,
unsigned indent
) {
string strEvent(element + ".addEventListener(\n");
strEvent.append(indent + 1, '\t');
strEvent.append("'" + event + "',\n");
strEvent.append(function.js_function(indent +1, false) + ",\n");
strEvent.append(indent + 1, '\t');
strEvent.append(useCapture ? "true\n" : "false\n");
strEvent.append(indent, '\t');
strEvent.append(");\n\n");
return(strEvent);
}
In order to create an event, first you need to create the event function using the jsfunction class eg.
jsfunction e("(event)");
e.add_line("if (event.target.id.toLowerCase() !== 'faulttext') {");
e.add_line("return;");
e.add_line("}");
e.add_line("autoExpand(event.target);");
Then all you need to do is call jsevent in order to grab the event string
string onInput = jsevent::jsevent(
"document",
"input",
e,
false,
2
);
Will create an event listener like
document.addEventListener(
'input',
function (event) {
if (event.target.id.toLowerCase() !== 'faulttext') {
return;
}
autoExpand(event.target);
},
false
);

Recent Comments