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