12b9c036ada723b623e3b66cd0b0c85e0328df9c
braney
  Mon Aug 14 21:45:24 2017 -0700
add AJAX store.

diff --git src/hg/hgCollection/hgCollection.c src/hg/hgCollection/hgCollection.c
index 63992af..8bcf6b5 100644
--- src/hg/hgCollection/hgCollection.c
+++ src/hg/hgCollection/hgCollection.c
@@ -104,30 +104,31 @@
 
 static void printGroup(char *parent, struct trackDb *tdb, boolean folder, boolean user)
 // output list elements for a group
 {
 char *userString = "";
 char *prefix = "";
 
 //if (user)
     {
     //prefix = "coll_";
     if (tdb->parent && tdb->subtracks) 
         userString = "viewType='view'";
     else
         userString = "viewType='track'";
     }
+        //userString = "viewType='track data-jstree='{'icon':'images/folderC.png'}''";
     
 #define IMAKECOLOR_32(r,g,b) ( ((unsigned int)b<<0) | ((unsigned int)g << 8) | ((unsigned int)r << 16))
 
 jsInlineF("<li shortLabel='%s' longLabel='%s' color='#%06x' visibility='%s'  name='%s%s' %s><span class='%s'>%s</span>",  tdb->shortLabel, tdb->longLabel,IMAKECOLOR_32(tdb->colorR,tdb->colorG,tdb->colorB), hStringFromTv(tdb->visibility), prefix,  trackHubSkipHubName(tdb->track),   userString, folder ? "folder" : "file", tdb->shortLabel );
 jsInlineF("%s", tdb->longLabel);
 
 
 if (tdb->subtracks)
     {
     struct trackDb *subTdb;
 
     jsInlineF("<ul>");
     for(subTdb = tdb->subtracks; subTdb; subTdb = subTdb->next)
         printGroup(trackHubSkipHubName(tdb->track), subTdb, user && (subTdb->subtracks != NULL), user);
     jsInlineF("</ul>");
@@ -234,50 +235,69 @@
 printf("<tr name='visible' ><td><span class='file'>All Visible</td><td>All the tracks visible in hgTracks</td></tr>\n");
 struct trackDb *tdb;
 for(tdb = fullTrackList; tdb; tdb = tdb->next)
     {
     if (isParentVisible(tdb) &&  isSubtrackVisible(tdb))
         {
         printGroup("visible", tdb, FALSE, FALSE);
         }
     }
 }
 
 void doTable()
 // output the tree table
 {
 char *hubName = hubNameFromUrl(getHubName(database));
-jsInlineF("$('#tracks').append(\"");
 struct grp *curGroup;
 for(curGroup = fullGroupList; curGroup;  curGroup = curGroup->next)
     {
     if ((hubName != NULL) && sameString(curGroup->name, hubName))
         break;
     }
 if (curGroup != NULL)
     {
     // print out all the tracks in this group
     struct trackDb *tdb;
-    jsInlineF("<ul>");
+    jsInlineF("$('#startCollections').append(\"");
     for(tdb = fullTrackList; tdb;  tdb = tdb->next)
         {
         if (sameString(tdb->grp, hubName))
+            {
+            //jsInlineF("<li name='%s'><span class='file'>%s</span></li>", tdb->track, tdb->shortLabel);
+            jsInlineF("<div id='%s' shortLabel='%s'>", trackHubSkipHubName(tdb->track), tdb->shortLabel);
+            jsInlineF("<ul>");
             printGroup("collections", tdb, TRUE, TRUE);
+            jsInlineF("<ul>");
+            jsInlineF("</div>");
             }
-    jsInlineF("</ul>");
+        }
+    jsInlineF("\");\n");
+    
+    // print out all the tracks in this group
+    jsInlineF("$('#collections').append(\"");
+    for(tdb = fullTrackList; tdb;  tdb = tdb->next)
+        {
+        if (sameString(tdb->grp, hubName))
+            {
+            jsInlineF("<li id='%s'  name='%s'><span class='file'>%s</span></li>", trackHubSkipHubName(tdb->track),trackHubSkipHubName(tdb->track), tdb->shortLabel);
+            //printGroup("collections", tdb, TRUE, TRUE);
+            }
+        }
+    jsInlineF("\");\n");
     }
 //addVisibleTracks();
+jsInlineF("$('#tracks').append(\"");
 for(curGroup = fullGroupList; curGroup;  curGroup = curGroup->next)
     {
     if ((hubName != NULL) && sameString(curGroup->name, hubName))
         continue;
     jsInlineF("<ul>");
     jsInlineF("<li name='%s'><span class='file'>%s</span>", curGroup->name, curGroup->label );
     struct trackDb *tdb;
     jsInlineF("<ul>");
     for(tdb = fullTrackList; tdb;  tdb = tdb->next)
         {
         if ( sameString(tdb->grp, curGroup->name))
             {
             printGroup(curGroup->name, tdb, FALSE, FALSE);
             }
         }
@@ -418,55 +438,55 @@
 }
 
 static void outComposite(FILE *f, struct track *collection)
 // output a composite header for user composite
 {
 char *parent = collection->name;
 char *shortLabel = collection->shortLabel;
 char *longLabel = collection->longLabel;
 fprintf(f,"track %s\n\
 shortLabel %s\n\
 compositeTrack on\n\
 aggregate none\n\
 longLabel %s\n\
 %s on\n\
 type wig \n\
-visibility full\n\n", parent, &shortLabel[2], longLabel, CUSTOM_COMPOSITE_SETTING);
+visibility full\n\n", parent, shortLabel, longLabel, CUSTOM_COMPOSITE_SETTING);
 }
 
 int snakePalette2[] =
 {
 0x1f77b4, 0xaec7e8, 0xff7f0e, 0xffbb78, 0x2ca02c, 0x98df8a, 0xd62728, 0xff9896, 0x9467bd, 0xc5b0d5, 0x8c564b, 0xc49c94, 0xe377c2, 0xf7b6d2, 0x7f7f7f, 0xc7c7c7, 0xbcbd22, 0xdbdb8d, 0x17becf, 0x9edae5
 };
 
 static char *skipColl(char *str)
 {
 if (startsWith("coll_", str))
     return &str[5];
 return str;
 }
 
 static void outView(FILE *f, struct sqlConnection *conn, char *db, struct track *view, char *parent, struct hash *nameHash, struct hash *collectionNameHash)
 // output a view to a trackhub
 {
 fprintf(f,"\ttrack %s\n\
 \tshortLabel %s\n\
 \tlongLabel %s\n\
 \tview %s \n\
 \tparent %s \n\
 \tcolor %ld,%ld,%ld \n\
-\tvisibility %s\n", view->name, &view->shortLabel[2], view->longLabel, view->name, parent, 0xff& (view->color >> 16),0xff& (view->color >> 8),0xff& (view->color), view->visibility);
+\tvisibility %s\n", view->name, view->shortLabel, view->longLabel, view->name, parent, 0xff& (view->color >> 16),0xff& (view->color >> 8),0xff& (view->color), view->visibility);
 //fprintf(f,"\tequation +\n");
 fprintf(f, "\n");
 
 //int useColor = 0;
 struct track *track = view->trackList;
 for(; track; track = track->next)
     {
     struct trackDb *tdb = hashMustFindVal(nameHash, skipColl(track->name));
 
     outTdb(conn, db, f, skipColl(track->name),tdb, view->name, track->visibility, track->color, track,  nameHash, collectionNameHash, 2);
     //useColor++;
     }
 
 }
 
@@ -499,92 +519,112 @@
             tdb = hashMustFindVal(nameHash, track->name);
 
             outTdb(conn, db, f, track->name,tdb, collection->name, track->visibility, track->color, track,  nameHash, collectionNameHash, 1);
             /*
             useColor++;
             if (useColor == (sizeof snakePalette2 / sizeof(int)))
                 useColor = 0;
                 */
             }
         }
     }
 fclose(f);
 hFreeConn(&conn);
 }
 
-static unsigned long hexStringToLong(char *str)
+unsigned long hexStringToLong(char *str)
 {
 /*
 char buffer[1024];
 
 strcpy(buffer, "0x");
 strcat(buffer, &str[1]);
 */
 
 return strtol(&str[1], NULL, 16);
 }
 
-static struct track *parseJson(char *jsonText)
-// parse the JSON returned from the ap
+struct jsonParseData
 {
-struct hash *trackHash = newHash(5);
-struct track *collectionList = NULL;
+struct track **collectionList;
+struct hash *trackHash;
+};
+
+void jsonObjStart(struct jsonElement *ele, char *name,
+    boolean isLast, void *context)
+{
+struct jsonParseData *jpd = (struct jsonParseData *)context;
+struct track **collectionList = jpd->collectionList;
+struct hash *trackHash = jpd->trackHash;
 struct track *track;
-char *ptr = jsonText;
-if (*ptr != '[')
-    errAbort("element didn't start with [");
-ptr++;
 
-do
+if ((name == NULL) && (ele->type == jsonObject))
     {
-    if (*ptr != '[')
-        errAbort("element didn't start with [");
-    ptr++;
+    struct hash *objHash = jsonObjectVal(ele, "name");
+
+    struct jsonElement *parentEle = hashFindVal(objHash, "id");
+    char *parentId = jsonStringEscape(parentEle->val.jeString);
+    parentEle = hashFindVal(objHash, "parent");
+    char *parentName = jsonStringEscape(parentEle->val.jeString);
 
     AllocVar(track);
-    char *parentName = getString(&ptr);
-    if (sameString(parentName, "collections"))
-        slAddHead(&collectionList, track);
+    if (sameString(parentName, "#"))
+        slAddHead(collectionList, track);
     else
         {
         struct track *parent = hashMustFindVal(trackHash, parentName);
         slAddTail(&parent->trackList, track);
         }
 
-    track->shortLabel = getString(&ptr);
-    track->longLabel = getString(&ptr);
-    track->name = getString(&ptr);
-    track->visibility = getString(&ptr);
-    char *colorString = getString(&ptr);
+    struct jsonElement *attEle = hashFindVal(objHash, "li_attr");
+    if (attEle)
+        {
+        struct hash *attrHash = jsonObjectVal(attEle, "name");
+        struct jsonElement *strEle = (struct jsonElement *)hashMustFindVal(attrHash, "name");
+        track->name = jsonStringEscape(strEle->val.jeString);
+        hashAdd(trackHash, parentId, track);
 
-    track->color = hexStringToLong(colorString);
-    hashAdd(trackHash, track->name, track);
-    if (*ptr != ']')
-        errAbort("element didn't end with ]");
-    ptr++;
-    if (*ptr == ',')
-        ptr++;
-    } while (*ptr != ']');
+        strEle = (struct jsonElement *)hashMustFindVal(attrHash, "shortlabel");
+        track->shortLabel = jsonStringEscape(strEle->val.jeString);
+        strEle = (struct jsonElement *)hashMustFindVal(attrHash, "longlabel");
+        track->longLabel = jsonStringEscape(strEle->val.jeString);
+        strEle = (struct jsonElement *)hashMustFindVal(attrHash, "visibility");
+        track->visibility = jsonStringEscape(strEle->val.jeString);
+        strEle = (struct jsonElement *)hashMustFindVal(attrHash, "color");
+        track->color = hexStringToLong(jsonStringEscape(strEle->val.jeString));
+        }
+    }
+}
+
+static struct track *parseJsonElements( struct jsonElement *collectionElements)
+// parse the JSON returned from the ap
+{
+struct track *collectionList = NULL;
+struct hash *trackHash = hashNew(5);
+struct jsonParseData jpd = {&collectionList, trackHash};
+jsonElementRecurse(collectionElements, NULL, FALSE, jsonObjStart, NULL, &jpd);
 
 slReverse(&collectionList);
 return collectionList;
 }
 
 void doAjax(char *db, char *jsonText, struct hash *nameHash)
 // Save our state
 {
-struct track *collectionList = parseJson(jsonText);
+cgiDecodeFull(jsonText, jsonText, strlen(jsonText));
+struct jsonElement *collectionElements = jsonParse(jsonText);
+struct track *collectionList = parseJsonElements(collectionElements);
 
 updateHub(db, collectionList, nameHash);
 }
 
 static void buildNameHash(struct hash *nameHash, struct trackDb *list)
 {
 if (list == NULL)
     return;
 
 struct trackDb *tdb;
 for(tdb = list; tdb;  tdb = tdb->next)
     {
     hashAdd(nameHash, trackHubSkipHubName(tdb->track), tdb);
     buildNameHash(nameHash, tdb->subtracks);
     }