a5b512a7a022c72d644b843b88f8d0e6c990a5cf braney Fri Aug 11 14:49:58 2017 -0700 move to jstree, first pass at Cath's spec diff --git src/hg/js/hgCollection.js src/hg/js/hgCollection.js index 3e6b7fb..7f2bcae 100644 --- src/hg/js/hgCollection.js +++ src/hg/js/hgCollection.js @@ -1,359 +1,191 @@ // hgCollection.js - Interactive features for GTEX Body Map version of GTEx Gene track UI page // Copyright (C) 2017 The Regents of the University of California - var collections = (function() { var names = []; // a list of names that have been used var selectedNode = "collections"; // keep track of id of selected row var $tracks; // the #tracks object + var trees = []; - function errorHandler(request, textStatus) { + function customApply() { + // called when the apply button on the track settings dialog is pressed + selectedNode.li_attr.shortlabel = $("#customName").val(); + selectedNode.li_attr.longlabel = $("#customDescription").val(); + selectedNode.li_attr.visibility = $("#customVis").val(); + selectedNode.li_attr.color = $("#customColorInput").val(); } - function updatePage(responseJson) { - if (!responseJson) { - return; - } - var message = responseJson.serverSays; - if (message) { - console.log('server says: ' + JSON.stringify(message)); - } - } - - // make sure name is unique in track hub - function getUniqueName(root) { - if (!names.root) { - names.root = true; - return root; - } else { - var counter = 1; - - for(;;counter++) { - var name = root + counter; - if (!names.name) { - names.name = true; - return name; - } - } - } + function hideAllAttributes() { + // hide all the "set attribute" dialogs + $("#viewOptions").hide(); + $("#CustomCompositeOptions").hide(); + $("#CustomTrackOptions").hide(); + $("#TrackDbOptions").hide(); } - function init() { - // build the tracks tree - $tracks = $("#tracks"); - $tracks.treetable({expandable:true}); - $tracks.show(); - // - // record the names of all the tracks in the collections - $("#tracks .user").each(function() { - var name = $(this).data("ttId"); - names[name] = 1; - }); - - // color pickers - var viewOpt = { - hideAfterPaletteSelect : true, - color : $('#viewColorInput').val(), - showPalette: true, - showInput: true, - preferredFormat: "hex", - change: function() { var color = $("#viewColorPicker").spectrum("get"); $('#viewColorInput').val(color); }, - }; - $("#viewColorPicker").spectrum(viewOpt); + function selectTreeNode(evt, data) { + // called when a node in the collections tree is selected + var color = data.node.li_attr.color; + var name = data.node.li_attr.shortlabel; + var description = data.node.li_attr.longlabel; + var visibility = data.node.li_attr.visibility; + var type = data.node.li_attr.viewtype; + selectedNode = data.node; - var trackOpt = { - hideAfterPaletteSelect : true, - color : $('#customColorInput').val(), - showPalette: true, - showInput: true, - preferredFormat: "hex", - change: function() { var color = $("#customColorPicker").spectrum("get"); $('#customColorInput').val(color); }, - }; - $("#customColorPicker").spectrum(trackOpt); - - // Highlight selected row - $("#tracks tbody").on("mousedown", "tr", function() { - $("#tracks .selected").not(this).removeClass("selected"); - $(this).toggleClass("selected"); - selectedNode = this.getAttribute('data-tt-id'); - var name = this.cells[0].innerText; - var description = this.cells[1].innerText; - var visibility = this.getAttribute("visibility"); - var color = this.getAttribute("color"); - - if ($(this).hasClass("user")) { - if ($(this).hasClass("view")) { + if (!type) { + hideAllAttributes(); $("#viewOptions").show(); - $("#CustomCompositeOptions").hide(); - $("#CustomTrackOptions").hide(); - $("#TrackDbOptions").hide(); - $("#viewName").val(name.slice(1)); + $("#viewName").val(name); $("#viewDescription").val(description); $("#viewVis").val(visibility); $("#viewColorInput").val(color); $("#viewColorPicker").spectrum("set", color); - } else if ($(this).hasClass("ui-droppable")) { + } else if (type == 'collection') { + hideAllAttributes(); $("#CustomCompositeOptions").show(); - $("#viewOptions").hide(); - $("#CustomTrackOptions").hide(); - $("#TrackDbOptions").hide(); - $("#collectionName").val(name.slice(1)); + $("#collectionName").val(name); $("#collectionDescription").val(description); $("#collectionVis").val(visibility); - } else { + } else if (type == 'track') { + hideAllAttributes(); $("#CustomTrackOptions").show(); - $("#CustomCompositeOptions").hide(); - $("#TrackDbOptions").hide(); - $("#viewOptions").hide(); $("#customName").val(name); $("#customDescription").val(description); $("#customVis").val(visibility); $("#customColorInput").val(color); $("#customColorPicker").spectrum("set", color); - } } else { - $("#CustomCompositeOptions").hide(); - $("#CustomTrackOptions").hide(); + hideAllAttributes(); $("#TrackDbOptions").show(); } - }); - - // Drag & Drop - $("#tracks .file, #tracks .folder").draggable({ - helper: "clone", - opacity: 0.75, - refreshPositions: true, - revert: "invalid", - revertDuration: 300, - scroll: true - }); + } - $("#tracks .folder").each(function() { - $(this).parents("#tracks tr").droppable({ - accept: ".file, .folder", - drop: function(e, ui) { - var droppedEl = ui.draggable.parents("tr"); - $("#tracks").treetable("move", droppedEl.data("ttId"), $(this).data("ttId")); - $(droppedEl).addClass("user"); - }, - hoverClass: "accept", - over: function(e, ui) { - var droppedEl = ui.draggable.parents("tr"); - if(this != droppedEl[0] && !$(this).is(".expanded")) { - $("#tracks").treetable("expandNode", $(this).data("ttId")); + function checkCallback( operation, node, node_parent, node_position, more) { + // called during a drag and drop action to see if the target is droppable + if (operation === "move_node") { } } - }); - }); - $('body').on('click','#deleteTrack',function(){ - $("#tracks").treetable("removeNode", selectedNode); - }); + function newCollection() { + // called when the "New Collection" button is pressed + var ourCollectionName = getUniqueName("coll"); + var ourTreeName = getUniqueName("tree"); + var newName = "A New Collection"; + var newDescription = "Description of New Collection"; + var attributes = "shortLabel='" + newName + "' "; + attributes += "longLabel='" + newDescription + "' "; + attributes += "color='" + "0" + "' "; + attributes += "viewType='" + "collection" + "' "; + attributes += "visibility='" + "full" + "' "; - $('body').on('click','#createView',function(){ - var composite = $("#tracks").treetable("node", selectedNode); - var name = "View"; - var description = "Description of View"; - var thisNodeId = getUniqueName("View"); - var contents = "<tr color='#000000' data-tt-id=" + thisNodeId + " data-tt-parent-id=" + selectedNode + " class=\"user ui-droppable view\"><td> <span class='folder'>" + name + "</td><td>" + description +"</td></tr>"; - $("#tracks").treetable("loadBranch", composite, contents); - var newNode = $("#tracks").treetable("node", thisNodeId); - $("#tracks").treetable("move", thisNodeId, selectedNode); - var newNodeTr = newNode.row; - $(newNodeTr).data("visibility","squish"); - newNodeTr.droppable({ - accept: ".file, .folder", - drop: function(e, ui) { - var droppedEl = ui.draggable.parents("tr"); - $("#tracks").treetable("move", droppedEl.data("ttId"), $(this).data("ttId")); - $(droppedEl).addClass("user"); + $('#collections').append("<li " + attributes + "id='"+ourCollectionName+"'>A New Collection</li>"); + $('#collection').append("<div id='"+ourTreeName+"'><ul><li " + attributes+ ">A New Collection</li><ul></div>"); + var newTree = $('#collection div:last'); + trees[ourCollectionName] = newTree; + $(newTree).jstree({ + "core" : { + "check_callback" : checkCallback }, - hoverClass: "accept", - over: function(e, ui) { - var droppedEl = ui.draggable.parents("tr"); - if(this != droppedEl[0] && !$(this).is(".expanded")) { - $("#tracks").treetable("expandNode", $(this).data("ttId")); - } - } + 'plugins' : ['dnd', 'conditionalselect', 'contextmenu'], + 'check_callback' : checkCallback, + 'dnd': {check_while_dragging: true} }); - }); - - $("#newCollection").click ( function () { - var collections = $("#tracks").treetable("node", "coll_collections"); - var name = "Collection"; - var description = "Description of Collection"; - var thisNodeId = getUniqueName("collection"); - var contents = "<tr color='#000000' data-tt-id=" + thisNodeId + " data-tt-parent-id=\"coll_collections\" class=\"user ui-droppable\"><td><span class='folder'>" + name + "</td><td>" + description +"</td></tr>"; - $("#tracks").treetable("loadBranch", collections, contents); - var newNode = $("#tracks").treetable("node", thisNodeId); - var newNodeTr = newNode.row; - $(newNodeTr).data("visibility","squish"); - newNodeTr.droppable({ - accept: ".file, .folder", - drop: function(e, ui) { - var droppedEl = ui.draggable.parents("tr"); - $("#tracks").treetable("move", droppedEl.data("ttId"), $(this).data("ttId")); - $(droppedEl).addClass("user"); - }, - hoverClass: "accept", - over: function(e, ui) { - var droppedEl = ui.draggable.parents("tr"); - if(this != droppedEl[0] && !$(this).is(".expanded")) { - $("#tracks").treetable("expandNode", $(this).data("ttId")); - } + $(newTree).on("select_node.jstree", selectTreeNode); } - }); - }); - - $("#collectionApply").click ( function () { - var view = $("#tracks").treetable("node", selectedNode); - var name = $(view.row).find('td:first'); - name.html( name.html().replace(name.text().slice(1),$("#collectionName").val())); - // resetting the html trashes the event handler. - var target = view.treeCell; - var handler = function(e) { - $(this).parents("table").treetable("node", $(this).parents("tr").data("ttId")).toggle(); - return e.preventDefault(); - }; - target.off("click.treetable").on("click.treetable", handler); - - // now change the description - var description = $(view.row).find('td:last'); - description.html(description.html().replace(description.text(),$("#collectionDescription").val())); - view.row[0].setAttribute("color", $("#collectionColorInput").val()); - view.row[0].setAttribute("visibility", $("#collectionVis").val()); - }); - - $("#collectionReset").click ( function () { - var row = $("#tracks").treetable("node", selectedNode).row[0]; - var name = row.cells[0].innerText.slice(1); - var description = row.cells[1].innerText; - var color = row.getAttribute("color"); - var visibility = row.getAttribute("visibility"); - $("#collectionName").val(name); - $("#collectionDescription").val(description); - $("#collectionVis").val(visibility); - $("#collectionColorInput").val(color); - $("#collectionColorPicker").spectrum("set", color); - }); + function hideAllTrees() { + // hide all the trees in the Collected Tracks window + for(var key in trees) + trees[key].hide(); + } - $("#customApply").click ( function () { - var view = $("#tracks").treetable("node", selectedNode); - var name = $(view.row).find('td:first'); - name.html( name.html().replace(name.text(),$("#customName").val())); + function selectCollection(event, ui ) { + // called with a collection is selected + var id = ui.selected.id; + $('#collectedTracksTitle').text(ui.selected.innerText); + hideAllTrees(); + trees[id].show(); + } - // now change the description - var description = $(view.row).find('td:last'); - description.html(description.html().replace(description.text(),$("#customDescription").val())); + function addCollection(trees, list) { + // called when outputting JSON of all the collections + var collectTree = trees[list.id]; + var v = collectTree.jstree(true).get_json('#', {flat:true, no_data:true, no_state:true, no_a_attr:true}); + var mytext = JSON.stringify(v); + return mytext; + } - view.row[0].setAttribute("color", $("#customColorInput").val()); - view.row[0].setAttribute("visibility", $("#customVis").val()); + function saveCollections(trees) { + // called when the "Save" button is pressed + var json = "["; + $('#collections li').each(function() { + json += addCollection(trees, this ) + ','; }); + json = json.slice(0, -1); + json += ']'; + console.log(json); + } - $("#customReset").click ( function () { - var row = $("#tracks").treetable("node", selectedNode).row[0]; - var name = row.cells[0].innerText.slice(1); - var description = row.cells[1].innerText; - var color = row.getAttribute("color"); - var visibility = row.getAttribute("visibility"); - $("#customName").val(name); - $("#customDescription").val(description); - $("#customVis").val(visibility); - $("#customColorInput").val(color); - $("#customColorPicker").spectrum("set", color); - }); + function init() { + // called at initialization time + $("#saveCollections").click ( function() {saveCollections(trees);} ); + $("#newCollection").click ( newCollection ); + $("#collectionApply").click ( collectionApply ); + $("#customApply").click ( customApply ); + $('#collections').selectable({selected : selectCollection}); - $("#viewApply").click ( function () { - var view = $("#tracks").treetable("node", selectedNode); - var name = $(view.row).find('td:first'); - name.html( name.html().replace(name.text().slice(1),$("#viewName").val())); - // resetting the html trashes the event handler. - var target = view.treeCell; - var handler = function(e) { - $(this).parents("table").treetable("node", $(this).parents("tr").data("ttId")).toggle(); - return e.preventDefault(); + var trackOpt = { + hideAfterPaletteSelect : true, + color : $('#customColorInput').val(), + showPalette: true, + showInput: true, + preferredFormat: "hex", + change: function() { var color = $("#customColorPicker").spectrum("get"); $('#customColorInput').val(color); }, }; - target.off("click.treetable").on("click.treetable", handler); - // now change the description - var description = $(view.row).find('td:last'); - description.html(description.html().replace(description.text(),$("#viewDescription").val())); - - view.row[0].setAttribute("color", $("#viewColorInput").val()); - view.row[0].setAttribute("visibility", $("#viewVis").val()); - }); - - $("#viewReset").click ( function () { - var row = $("#tracks").treetable("node", selectedNode).row[0]; - var name = row.cells[0].innerText.slice(1); - var description = row.cells[1].innerText; - var color = row.getAttribute("color"); - var visibility = row.getAttribute("visibility"); - $("#viewName").val(name); - $("#viewDescription").val(description); - $("#viewVis").val(visibility); - $("#viewColorInput").val(color); - $("#viewColorPicker").spectrum("set", color); - }); - - $("#propsSave").click ( function () { - window.location.reload(); - }); - - $("#propsDiscard").click ( function () { - window.location.reload(); - }); - - $("#discardChanges").click ( function () { - window.location.reload(); - }); - - $("#saveCollections").click ( function () { - var ii = 0; - var values = []; - $("#tracks .user").each(function() { - var jj = 0; - var id = $(this).data("ttId"); - values[ii] = []; - values[ii][jj] = $(this).data("ttParentId"); - - jj++; - $(this).find('td').each(function(){ - values[ii][jj] = $(this).text(); - jj++; + $("#customColorPicker").spectrum(trackOpt); + $.jstree.defaults.core.themes.icons = false; + $.jstree.defaults.core.themes.dots = true; + $.jstree.defaults.contextmenu.show_at_node = false; + treeDiv=$('#collection'); + treeDiv=$('#tracks'); + treeDiv.jstree({ + 'plugins' : ['dnd', 'conditionalselect', 'contextmenu'], + 'always_copy' : true, }); + } - values[ii][jj] = $(this).data("ttId"); - jj++; - - values[ii][jj] = this.getAttribute("visibility"); - if (!values[ii][jj]) { - values[ii][jj] = "hide"; + function updatePage(responseJson) { + // called after AJAX call + if (!responseJson) { + return; + } + var message = responseJson.serverSays; + if (message) { + console.log('server says: ' + JSON.stringify(message)); + } } - jj++; - values[ii][jj] = this.getAttribute("color"); - jj++; + function getUniqueName(root) { + // make sure name is unique in track hub + if (!names[root]) { + names[root] = true; + return root; + } else { + var counter = 1; - ii++; - }); - requestData = 'jsonp=' + JSON.stringify(values); - $.ajax({ - data: requestData , - async: false, - dataType: "JSON", - type: "PUT", - url: "hgCollection?cmd=saveCollection", - trueSuccess: updatePage, - success: catchErrorOrDispatch, - error: errorHandler, - }); - }); + for(;;counter++) { + var name = root + counter; + if (!names[name]) { + names[name] = true; + return name; + } + } + } } return { init: init }; }());