4d00ea681ea73ae167fc186557a87b35791e9a2c kate Mon Feb 20 09:28:04 2012 -0800 Layout fixes, especially for IE. Dynamically size row and column headers. Use jQuery cell rotate on headers to achieve vertical text (required for IE, doesn't harm others). Cleanup css with shortcuts. diff --git src/hg/js/encodeDataMatrix.js src/hg/js/encodeDataMatrix.js index 6107bdb..97ce26e 100644 --- src/hg/js/encodeDataMatrix.js +++ src/hg/js/encodeDataMatrix.js @@ -11,167 +11,200 @@ // requests to server API encodeProject.serverRequests.experiment, encodeProject.serverRequests.dataType, encodeProject.serverRequests.cellType, encodeProject.serverRequests.expId ]; var dataTypeLabelHash = {}, dataTypeTermHash = {}, cellTypeHash = {}; var dataType, cellType; var organism, assembly, server, header; var karyotype; var spinner; function rowAddCells(row, dataGroups, matrix, cellType) { // populate a row in the matrix with cells for data groups and data types + // null cellType indicates this is a row for a cell group (tier) $.each(dataGroups, function (i, group) { // skip group header td = $('<td></td>'); td.addClass('matrixCell'); row.append(td); + $.each(group.dataTypes, function (i, dataTypeLabel) { dataType = dataTypeLabelHash[dataTypeLabel].term; // prune out datatypes with no experiments if (dataTypeLabelHash[dataTypeLabel].count === undefined) { return true; } td = $('<td></td>'); td.addClass('matrixCell'); row.append(td); if (cellType === null) { return true; } if (!matrix[cellType][dataType]) { td.addClass('todoExperiment'); return true; } + // this cell represents experiments that // fill in count, mouseover and selection by click td.addClass('experiment'); td.text(matrix[cellType][dataType]); td.data({ 'dataType' : dataType, 'cellType' : cellType }); td.mouseover(function() { $(this).attr('title', 'Click to select: ' + dataTypeTermHash[$(this).data().dataType].label + ' ' + ' in ' + $(this).data().cellType +' cells'); }); td.click(function() { // TODO: base on preview ? var url = encodeProject.getSearchUrl(assembly); // TODO: encapsulate var names url += ('&hgt_mdbVar1=dataType&hgt_mdbVal1=' + $(this).data().dataType + '&hgt_mdbVar2=cell&hgt_mdbVal2=' + $(this).data().cellType + '&hgt_mdbVar3=view&hgt_mdbVal3=Any'); + // specifying window name limits open window glut window.open(url, "searchWindow"); }); }); }); } function addFloatingHeader(table) { // add callback for floating table header feature table.floatHeader({ cbFadeIn: function (header) { // hide axis labels -- a bit tricky to do so // as special handling needed for X axis label $(".floatHeader #headerLabelRow").remove(); $(".floatHeader #cellHeaderLabel").html(''); $(".floatHeader #searchTypePanel").remove(); // Note: user-defined callback requires // default actions from floatHeader plugin // implementation (stop+fadeIn) header.stop(true, true); header.fadeIn(100); } }); } + function rotateCells(table) { + // plugin from David Votrubec, handles IE rotate + // TODO: restrict to IE + table.rotateTableCellContent({ className: 'verticalText'}); + $(this).attr('disabled', 'disabled'); + } + function tableOut(matrix, cellTiers, dataGroups) { // create table with rows for each cell types and columns for each data type var table, thead, tableHeader, row, td; + var maxLen = 0; // fill in column headers from dataTypes returned by server tableHeader = $('#columnHeaders'); table = $('#matrixTable'); thead = $('thead'); + // 1st column is row headers thead.before('<colgroup></colgroup>'); + $.each(dataGroups, function (i, group) { tableHeader.append('<th class="groupType"><div class="verticalText">' + group.label + '</div></th>'); + maxLen = Math.max(maxLen, group.label.length); + // add colgroup element to support cross-hair hover effect thead.before('<colgroup></colgroup>'); $.each(group.dataTypes, function (i, dataTypeLabel) { dataType = dataTypeLabelHash[dataTypeLabel].term; - if (dataTypeLabelHash[dataTypeLabel].count !== undefined) { + // prune out datatypes with no experiments + if (dataTypeLabelHash[dataTypeLabel].count !== undefined) { tableHeader.append('<th class="elementType" title="' + dataTypeLabelHash[dataTypeLabel].description + '"><div class="verticalText">' + dataTypeLabel + '</div></th>'); // add colgroup element to support cross-hair hover effect thead.before('<colgroup class="dataTypeCol"></colgroup>'); + maxLen = Math.max(maxLen, dataTypeLabel.length); } }); }); + + // adjust size of headers based on longest label length + // empirically len/2 em's is right + $('#columnHeaders th').css('height', (String((maxLen/2 + 2)).concat('em'))); + $('#columnHeaders th').css('width', '1em'); + // fill in matrix -- // add rows with cell type labels (column 1) and cells for experiments // add sections for each Tier of cell type $.each(cellTiers, function (i, tier) { //skip bogus 4th tier (not my property ?) if (tier === undefined) { return true; } row = $('<tr class="matrix"><th class="groupType">' + "Tier " + tier.term + '</th></td></tr>'); rowAddCells(row, dataGroups, matrix, null); table.append(row); + maxLen = 0; $.each(tier.cellTypes, function (i, cellType) { if (!cellType) { return true; } if (!matrix[cellType]) { return true; } karyotype = cellTypeHash[cellType].karyotype; // TODO: recognize cancer* // NOTE: coupled to CSS if (karyotype !== 'cancer' && karyotype !== 'normal') { karyotype = 'unknown'; } - row = $('<tr><th class="elementType" title="' + - cellTypeHash[cellType].description + - '"><a href="/cgi-bin/hgEncodeVocab?ra=encode/cv.ra&term=' + cellType + - '">' + cellType + '</a><span title="karyotype: ' + karyotype + - '" class="' + karyotype + '">•</span></th>'); + // note karyotype bullet layout requires non-intuitive placement + // in code before the span that shows to it's left + row = $('<tr>' + + '<th class="elementType">' + + '<span style="float:right; text-align: right;" title="karyotype: ' + karyotype + '" class="karyotype ' + karyotype + '">•</span>' + + '<span title="' + cellTypeHash[cellType].description + '"><a href="/cgi-bin/hgEncodeVocab?ra=encode/cv.ra&term=' + cellType + '">' + cellType + '</a>' + + '</th>' + ); + maxLen = Math.max(maxLen, cellType.length); rowAddCells(row, dataGroups, matrix, cellType); table.append(row); }); + // adjust size of row headers based on longest label length + $('tbody th').css('height', '1em'); + $('tbody th').css('width', (String((maxLen/2 + 2)).concat('em'))); }); $("body").append(table); addFloatingHeader(table); + rotateCells(table); // column and row hover (cross-hair effect) // thanks to Chris Coyier, css-tricks.com // NOTE: acts on colgroups declared at start of table $("#matrixTable, #matrixTableFloatHeaderClone").delegate('.matrixCell, .elementType','mouseover mouseleave', function(e) { if (!$(this).hasClass('experiment') && !$(this).hasClass('todoExperiment') && !$(this).hasClass('elementType') && !$(this).hasClass('groupType')) { return; } if (e.type == 'mouseover') { // refrain from highlighting header row if (!$(this).parent().is("#columnHeaders")) { $(this).parent().addClass("crossHair"); } col = $("colGroup").eq($(this).index());