59c4b5446987113a20a88c2860c469ae14dcc0b9
larrym
  Thu Jul 28 21:39:44 2011 -0700
switch to using in-memory json; refactor trackDbJson so it is part of hgTracks global in the client (redmine #4550)
diff --git src/hg/hgTracks/imageV2.c src/hg/hgTracks/imageV2.c
index 09ecbf2..b515bde 100644
--- src/hg/hgTracks/imageV2.c
+++ src/hg/hgTracks/imageV2.c
@@ -234,95 +234,101 @@
 {
 enum kindOfChild kindOfChild = kocOrphan;
 if (tdbIsFolderContent(tdb))
     kindOfChild = kocFolderContent;
 else if (tdbIsCompositeChild(tdb))
     kindOfChild = kocCompositeChild;
 else if (tdbIsMultiTrackChild(tdb))
     kindOfChild = kocMultiTrackChild;
 return kindOfChild;
 }
 
 /////////////////////////
 // JSON support.  Eventually the whole imgTbl could be written out as JSON
 
 
-static void jsonTdbSettingsInit(struct dyString **jsonTdbSettingsString)
+static void jsonTdbSettingsInit(struct jsonHashElement *settings)
 // Inititializes trackDbJson
 {
-*jsonTdbSettingsString = newDyString(1024);
-dyStringPrintf(*jsonTdbSettingsString, "<script type='text/javascript'>\n// START trackDbJson\nvar trackDbJson = {\n\"ruler\": {\"shortLabel\": \"ruler\", \"longLabel\": \"Base Position Controls\", \"canPack\": 0, \"visibility\": %d, \"configureBy\": \"popup\", \"kindOfParent\": 0}", rulerMode);
+struct jsonHashElement *ele = newJsonHash(newHash(8));
+jsonHashAddString(ele, "shortLabel", "ruler");
+jsonHashAddString(ele, "longLabel", "Base Position Controls");
+jsonHashAddNumber(ele, "canPack", 0);
+jsonHashAddNumber(ele, "visibility", rulerMode);
+jsonHashAddString(ele, "configureBy", "popup");
+jsonHashAddNumber(ele, "kindOfParent", 0);
+jsonHashAdd(settings, "ruler", (struct jsonElement *) ele);
 }
 
-void jsonTdbSettingsBuild(struct dyString **jsonTdbSettingsString, struct track *track, boolean configurable)
-// Creates then successively adds trackDb settings to the jsonTdbSettingsString
-// Initially pass in NULL pointer to a dyString to properly begin building
+void jsonTdbSettingsBuild(struct jsonHashElement *settings, struct track *track, boolean configurable)
+// Adds trackDb settings to the jsonTdbSettings
 {
-if(*jsonTdbSettingsString == NULL)
-    jsonTdbSettingsInit(jsonTdbSettingsString);
-dyStringAppend(*jsonTdbSettingsString, ", \n");
-
+struct jsonHashElement *ele = newJsonHash(newHash(8));
+jsonHashAdd(settings, track->track, (struct jsonElement *) ele);
 // track name and type
-dyStringPrintf(*jsonTdbSettingsString, "\t\"%s\": {", track->track);
-dyStringPrintf(*jsonTdbSettingsString, "\n\t\t\"type\": \"%s\",", track->tdb->type);
+jsonHashAddString(ele, "type", track->tdb->type);
 
 // Tell which kind of parent and which kind of child
 enum kindOfParent kindOfParent = tdbKindOfParent(track->tdb);
 enum kindOfChild  kindOfChild  = tdbKindOfChild(track->tdb);
-dyStringPrintf(*jsonTdbSettingsString, "\n\t\t\"kindOfParent\": %d,\n\t\t\"kindOfChild\": %d,",kindOfParent,kindOfChild);
+jsonHashAddNumber(ele, "kindOfParent", kindOfParent);
+jsonHashAddNumber(ele, "kindOfChild", kindOfChild);
 
 // Tell something about the parent and/or children
 if (kindOfChild != kocOrphan)
     {
     struct trackDb *parentTdb = (kindOfChild == kocFolderContent ? track->tdb->parent :tdbGetContainer(track->tdb));
 
-    dyStringPrintf(*jsonTdbSettingsString, "\n\t\t\"parentTrack\": \"%s\",\n\t\t\"parentLabel\": \"%s\",",
-                    parentTdb->track, javaScriptLiteralEncode(parentTdb->shortLabel));
+    jsonHashAddString(ele, "parentTrack", parentTdb->track);
+    jsonHashAddString(ele, "parentLabel", parentTdb->shortLabel);
     if (kindOfChild != kocFolderContent && !track->canPack)
         {
-        dyStringPrintf(*jsonTdbSettingsString, "\n\t\t\"shouldPack\": 0,"); // default vis is full, but pack is an option
+        jsonHashAddNumber(ele, "shouldPack", 0); // default vis is full, but pack is an option
         track->canPack = parentTdb->canPack;
         }
     }
-dyStringPrintf(*jsonTdbSettingsString, "\n\t\t\"hasChildren\": %d,", slCount(track->tdb->subtracks));
+
+// XXXX really s/d be numChildren
+jsonHashAddNumber(ele, "hasChildren", slCount(track->tdb->subtracks));
 
 // Configuring?
 if (!configurable || track->hasUi == FALSE)
-    dyStringPrintf(*jsonTdbSettingsString, "\n\t\t\"configureBy\": \"none\",");
+    jsonHashAddString(ele, "configureBy", "none");
 else if (sameString(trackDbSettingClosestToHomeOrDefault(track->tdb, "configureByPopup",
     regexMatch(track->track, "^snp[0-9]+") || regexMatch(track->track, "^cons[0-9]+way") || regexMatch(track->track, "^multiz") ? "off" : "on"), "off"))
-    dyStringPrintf(*jsonTdbSettingsString, "\n\t\t\"configureBy\": \"clickThrough\",");
+    jsonHashAddString(ele, "configureBy", "clickThrough");
 else
-    dyStringPrintf(*jsonTdbSettingsString, "\n\t\t\"configureBy\": \"popup\",");
+    jsonHashAddString(ele, "configureBy", "popup");
 
 // Remote access by URL?
 if (sameWord(track->tdb->type, "remote") && trackDbSetting(track->tdb, "url") != NULL)
-    dyStringPrintf(*jsonTdbSettingsString, "\n\t\t\"url\": \"%s\",", trackDbSetting(track->tdb, "url"));
+    jsonHashAddString(ele, "url", trackDbSetting(track->tdb, "url"));
 
 // Close with some standard vars
-dyStringPrintf(*jsonTdbSettingsString, "\n\t\t\"shortLabel\": \"%s\",\n\t\t\"longLabel\": \"%s\",\n\t\t\"canPack\": %d,",
-    javaScriptLiteralEncode(track->shortLabel), javaScriptLiteralEncode(track->longLabel), track->canPack);
+jsonHashAddString(ele, "shortLabel", track->shortLabel);
+jsonHashAddString(ele, "longLabel", track->longLabel);
+jsonHashAddNumber(ele, "canPack", track->canPack);
+
 if(track->limitedVis != track->visibility)
-    dyStringPrintf(*jsonTdbSettingsString, "\n\t\t\"limitedVis\": %d,", track->limitedVis);
-dyStringPrintf(*jsonTdbSettingsString, "\n\t\t\"visibility\": %d\n\t}", track->visibility);
+    jsonHashAddNumber(ele, "limitedVis", track->limitedVis);
+jsonHashAddNumber(ele, "visibility", track->visibility);
 }
 
-char *jsonTdbSettingsUse(struct dyString **jsonTdbSettingsString)
-// Closes and returns the contents of the jsonTdbSettingsString
+void jsonTdbSettingsUse(struct jsonHashElement *settings)
 {
-dyStringAppend(*jsonTdbSettingsString, "};\n// END trackDbJson\n</script>\n");
-return dyStringCannibalize(jsonTdbSettingsString);
+// add the settings to the hgTracks output object
+jsonHashAdd(jsonForClient, "trackDb", (struct jsonElement *) settings);
 }
 
 /////////////////////////
 // IMAGEv2
 // The new way to do images: PLEASE REFER TO imageV2.h FOR A DETAILED DESCRIPTION
 /////////////////////////
 
 
 
 /////////////////////// Maps
 
 struct mapSet *mapSetStart(char *name,struct image *img,char *linkRoot)
 /* Starts a map (aka mapSet) which is the seet of links and image locations used in HTML.
    Complete a map by adding items with mapItemAdd() */
 {
@@ -1870,41 +1876,41 @@
     hPrintf("var imgBoxChromStart=%d;var imgBoxChromEnd=%d;var imgBoxWidth=%d;",
             imgBox->chromStart, imgBox->chromEnd,(imgBox->width - imgBox->sideLabelWidth));
     hPrintf("var imgBoxPortalStart=%d;var imgBoxPortalEnd=%d;var imgBoxPortalWidth=%d;",
             imgBox->portalStart, imgBox->portalEnd, imgBox->portalWidth);
     hPrintf("var imgBoxLeftLabel=%d;var imgBoxPortalOffsetX=%d;var imgBoxBasesPerPixel=%lf;</script>\n",
             (imgBox->plusStrand?imgBox->sideLabelWidth:0),
             (int)((imgBox->portalStart - imgBox->chromStart) / imgBox->basesPerPixel),imgBox->basesPerPixel);
     }
 #endif//def IMAGEv2_DRAG_SCROLL
 
 hPrintf("<TABLE id='imgTbl' border=0 cellspacing=0 cellpadding=0 BGCOLOR='%s'",COLOR_WHITE);//COLOR_RED); // RED to help find bugs
 hPrintf(" width=%d",imgBox->showPortal?(imgBox->portalWidth+imgBox->sideLabelWidth):imgBox->width);
 hPrintf(" class='tableWithDragAndDrop'");
 hPrintf(" style='border:1px solid blue;border-collapse:separate;'>\n");
 
-struct dyString *jsonTdbVars = NULL;
-jsonTdbSettingsInit(&jsonTdbVars);
+struct jsonHashElement *jsonTdbVars = newJsonHash(newHash(8));
+jsonTdbSettingsInit(jsonTdbVars);
 
 char *newLine = NEWLINE_TO_USE(cgiClientBrowser(NULL,NULL,NULL));
 struct imgTrack *imgTrack = imgBox->imgTracks;
 for(;imgTrack!=NULL;imgTrack=imgTrack->next)
     {
     char *trackName = (imgTrack->name != NULL ? imgTrack->name : imgTrack->tdb->track );
     struct track *track = hashFindVal(trackHash, trackName);
     if(track)
-        jsonTdbSettingsBuild(&jsonTdbVars, track, TRUE);
+        jsonTdbSettingsBuild(jsonTdbVars, track, TRUE);
     hPrintf("<TR id='tr_%s' abbr='%d' class='imgOrd%s%s%s'>\n",trackName,imgTrack->order,
         (imgTrack->reorderable?" trDraggable":" nodrop nodrag"),
         (imgTrack->centerLabelSeen != clAlways?" clOpt":""),
         (imgTrack->ajaxRetrieval ?" mustRetrieve":""));
 
     if(imgBox->showSideLabel && imgBox->plusStrand)
         {
         // button
         safef(name, sizeof(name), "btn_%s", trackName);
         hPrintf(" <TD id='td_%s'%s>\n",name,(imgTrack->reorderable?" class='dragHandle'":""));
         sliceAndMapDraw(imgBox,imgTrack,stButton,name,FALSE);
         hPrintf("</TD>\n");
         // leftLabel
         safef(name,sizeof(name),"side_%s",trackName);
         if (imgTrack->reorderable)
@@ -1937,19 +1943,17 @@
             hPrintf(" <TD id='td_%s' class='dragHandle' title='%s%sdrag to reorder'>\n",name,htmlEncode(imgTrack->tdb->longLabel),newLine);
         else
             hPrintf(" <TD id='td_%s'>\n",name);
         sliceAndMapDraw(imgBox,imgTrack,stSide,name,FALSE);
         hPrintf("</TD>\n");
         // button
         safef(name, sizeof(name), "btn_%s", trackName);
         hPrintf(" <TD id='td_%s'%s>\n",name,(imgTrack->reorderable?" class='dragHandle'":""));
         sliceAndMapDraw(imgBox,imgTrack,stButton, name,FALSE);
         hPrintf("</TD>\n");
         }
     hPrintf("</TR>\n");
     }
 hPrintf("</TABLE>\n");
 hPrintf("<!-- - - - - - - - ^^^ IMAGEv2 ^^^ - - - - - - - -->\n");  // DANGER FF interprets '--' as end of comment, not '-->'
-
-if (jsonTdbVars != NULL)
-    hWrites(jsonTdbSettingsUse(&jsonTdbVars));
+jsonTdbSettingsUse(jsonTdbVars);
 }