bcbb8d33a61ae54020a12b2b34113a34c933eb29
galt
  Tue Feb 14 23:00:00 2017 -0800
Adding convenience var arg functions jsInlineF and jsOnEventByIdF, suggested by Angie.

diff --git src/lib/cheapcgi.c src/lib/cheapcgi.c
index af5ef9a..53d6914 100644
--- src/lib/cheapcgi.c
+++ src/lib/cheapcgi.c
@@ -53,30 +53,40 @@
 /* init if needed */
 {
 if (!jsInlineLines) 
     {
     jsInlineLines = dyStringNew(1024);	
     }
 }
 
 void jsInline(char *javascript)
 /* Add javascript text to output file or memory structure */
 {
 jsInlineInit(); // init if needed
 dyStringAppend(jsInlineLines, javascript);
 }
 
+void jsInlineF(char *format, ...)
+/* Add javascript text to output file or memory structure */
+{
+jsInlineInit(); // init if needed
+va_list args;
+va_start(args, format);
+dyStringVaPrintf(jsInlineLines, format, args);
+va_end(args);
+}
+
 boolean jsInlineFinishCalled = FALSE;
 
 void jsInlineFinish()
 /* finish outputting accumulated inline javascript */
 {
 if (jsInlineFinishCalled)
     {
     // jsInlineFinish can be called multiple times when generating framesets or genomeSpace.
     warn("jsInlineFinish() called already.");  // TODO GALT
     }
 jsInlineInit(); // init if needed
 printf("<script type='text/javascript' nonce='%s'>\n%s</script>\n", getNonce(), jsInlineLines->string);
 dyStringClear(jsInlineLines);
 jsInlineFinishCalled = TRUE;
 }
@@ -196,34 +206,43 @@
 {
 char *temp = cloneString(event);
 tolowers(temp);
 if (!sameString(temp, event))
     warn("jsInline: javascript event %s should be given in lower-case", event);
 event = temp; 
 if (!findJsEvent(event))
     warn("jsInline: unknown javascript event %s", event);
 freeMem (event);
 }
 
 void jsOnEventById(char *event, char *idText, char *jsText)
 /* Add js mapping for inline event */
 {
 checkValidEvent(event);
-struct dyString *javascript = dyStringNew(1024);  // TODO XSS Filter the idText?
-dyStringPrintf(javascript, "document.getElementById('%s').on%s = function() {%s};\n", idText, event, jsText);
-jsInline(javascript->string);
-dyStringFree(&javascript);
+jsInlineF("document.getElementById('%s').on%s = function() {%s};\n", idText, event, jsText);
+}
+
+void jsOnEventByIdF(char *event, char *idText, char *format, ...)
+/* Add js mapping for inline event */
+{
+checkValidEvent(event);
+jsInlineF("document.getElementById('%s').on%s = function() {", idText, event);
+va_list args;
+va_start(args, format);
+dyStringVaPrintf(jsInlineLines, format, args);
+va_end(args);
+jsInlineF("};\n");
 }
 
 
 //============ END of javascript inline-separation routines ===============
 
 
 /* These three variables hold the parsed version of cgi variables. */
 static char *inputString = NULL;
 static unsigned long inputSize;
 static struct hash *inputHash = NULL;
 static struct cgiVar *inputList = NULL;
 
 static boolean haveCookiesHash = FALSE;
 static struct hash *cookieHash = NULL;
 static struct cgiVar *cookieList = NULL;
@@ -1837,31 +1856,31 @@
 if (width==0)
     width=strlen(initialVal)*10;
 if (width==0)
     width = 100;
 
 htmlPrintf("<INPUT TYPE=TEXT class='inputBox' NAME='%s|attr|' id='%s' style='width:%dpx' VALUE='%s|attr|'>\n",
        varName, varName, width, initialVal);
 if (event)
     jsOnEventById(event, varName, javascript);
 }
 
 void cgiMakeIntVarWithExtra(char *varName, int initialVal, int maxDigits, char *extra)
 /* Make a text control filled with initial value and optional extra HTML.  */
 {
 if (maxDigits == 0) maxDigits = 4;
-htmlPrintf("<INPUT TYPE=TEXT NAME='%s|attr|' SIZE=%d VALUE=%d %s|none|>", // TODO XSS extra
+htmlPrintf("<INPUT TYPE=TEXT NAME='%s|attr|' SIZE=%d VALUE=%d %s|none|>", // TODO XSS risk in extra
                 varName, maxDigits, initialVal, extra ? extra : "");
 }
 
 void cgiMakeIntVar(char *varName, int initialVal, int maxDigits)
 /* Make a text control filled with initial value.  */
 {
 cgiMakeIntVarWithExtra(varName, initialVal, maxDigits, NULL);
 }
 
 void cgiMakeIntVarInRange(char *varName, int initialVal, char *title, int width,
                           char *min, char *max)
 /* Make a integer control filled with initial value.
    If min and/or max are non-NULL will enforce range
    Requires utils.js jQuery.js and inputBox class */
 {