| <!-- The <grid-sk> custom element declaration. |
| |
| Displays thumbnails in a 2-dimensional grid, also responds to mouseover events |
| on each image. The top row and the left most column are the thumbnails of the |
| sources, and the rest of the grid is filled in with the thumbnails of the |
| diffs of the images. The layout looks like: |
| |
| W T T T |
| L D D D |
| L D D D |
| |
| Where: |
| W = A white thumbnail to hold the space. |
| T = A source thumbnail along the top. |
| L = A source thumbnail along the left. |
| D = A diff thumbnail between the top and left source images. |
| |
| Attributes: |
| value - A dictionary of the form: |
| |
| { |
| rows: [img1, img2, ...] |
| columns: [imgA, imgB, ...] |
| cells: [ |
| [diff1A, diff2A, ...], |
| [diff1B, diff2B, ...], |
| ] |
| } |
| |
| Where imgX looks like: |
| |
| { |
| digest: "abc12..." // The image digest. |
| n: 12 // The number of times the image ocurs in the current tile. |
| } |
| |
| And diffXY looks like: |
| |
| { |
| numDiffPixels: 27, // Number of differing pixels. |
| pixelDiffPercent: 1.1, // Percent of differing pixels. |
| maxRGBADiffs: [254, 0, 0, 0], // Max diffs per RGBA channels. |
| diffImgUrl: "/img/abc-def.pgn" // URL of the diff image. |
| } |
| |
| Events: |
| 'diff-click' - Triggered when an image is clicked on. |
| e.detail contains the diffXY info associated with that thumbnail. |
| |
| 'diff-dblclick' - Triggered when an image is double-clicked. |
| e.detail contains the diffXY info associated with that thumbnail. |
| |
| Methods: |
| selectRow(row) - will highlight the row image of the given row index. |
| |
| selectCell(row, column) - will highlight the cell image for the given row |
| index. |
| |
| clearSelection() - clears all selections. |
| --> |
| |
| <link rel="import" href="bower_components/polymer/polymer.html"> |
| <link rel="import" href="bower_components/iron-flex-layout/iron-flex-layout-classes.html"> |
| <link rel="import" href="bower_components/paper-tooltip/paper-tooltip.html"> |
| <link rel="import" href="bower_components/iron-icons/iron-icons.html"> |
| |
| <dom-module id="grid-sk"> |
| <template> |
| <style include="iron-flex iron-flex-alignment"> |
| .imgWrapper { |
| border: solid 2px lightgray; |
| display: block; |
| } |
| |
| img { |
| display: block; |
| max-width:64px; |
| max-height:64px; |
| width: auto; |
| height: auto; |
| } |
| |
| .colHeader { |
| width: 64px; |
| display: block; |
| margin: 5px; |
| padding: 2px; |
| } |
| |
| .emptyCell, .imgWrapper { |
| margin: 5px; |
| width: 64px; |
| } |
| |
| .imgWrapper { |
| height: 64px; |
| } |
| |
| .emptyCell { |
| border: solid 2px white; |
| } |
| |
| .ttTable { |
| font-size: 12px; |
| color: white; |
| } |
| |
| .sortedColsHeader { |
| margin: 0 5px 0 5px; |
| padding: 5px 1em 5px 1em; |
| } |
| |
| .highlight { |
| border-color: red; |
| } |
| </style> |
| <div class="vertical layout"> |
| <div class="horizontal layout end" id="colsContainer"> |
| <div class="emptyCell"></div> |
| <template is="dom-repeat" items="{{_getColsWithHeaders(_value.columns)}}" as="col"> |
| <div class="colHeader">{{_diffTitle(col.type)}}</div> |
| </template> |
| <template is="dom-if" if={{_hasNoHeaderCols(_value.columns)}}> |
| <div class="sortedColsHeader"> |
| Sorted <iron-icon icon="icons:trending-flat"></iron-icon> |
| </div> |
| </template> |
| </div> |
| <div class="horizontal layout"> |
| <div class="vertical layout" id="rowsContainer"> |
| <template is="dom-repeat" items="{{_value.rows}}" as="row" index-as="rowIdx"> |
| <div class="horizontal layout"> |
| <div class="imgWrapper" id$="row-[[rowIdx]]"> |
| <img src$="{{_imgHref(row.digest)}}" data-rowdigest="{{rowIdx}}"> |
| <paper-tooltip> |
| <table class="ttTable" border="0" cellspacing="5" cellpadding="5"> |
| <tr><th>N</th><td>{{row.n}}</td></tr> |
| <tr hidden$="[[!row.summary]]"><th>Test</th><td>{{row.test}}</td></tr> |
| <tr hidden$="[[!row.summary]]"><th>Pos</th><td>{{row.summary.pos}}</td></tr> |
| <tr hidden$="[[!row.summary]]"><th>Neg</th><td>{{row.summary.neg}}</td></tr> |
| <tr hidden$="[[!row.summary]]"><th>Unt</th><td>{{row.summary.untriaged}}</td></tr> |
| </table> |
| </paper-tooltip> |
| </div> |
| |
| <template is="dom-repeat" items="{{row.values}}" as="cell" index-as="colIdx"> |
| <div class="imgWrapper" id$="cell-[[rowIdx]]-[[colIdx]]"> |
| <img src$="{{_diffHref(row, cell)}}" data-row="{{rowIdx}}" data-col="{{colIdx}}"> |
| <paper-tooltip> |
| <table class="ttTable" border="0" cellspacing="5" cellpadding="5"> |
| <tr><th>Diff</th><td>{{cell.diffs.combined}}</td></tr> |
| <tr><th>Pixel Diff (%)</th><td>{{cell.pixelDiffPercent}}</td></tr> |
| <tr><th>Num Diff Pixels</th><td>{{cell.numDiffPixels}}</td></tr> |
| <tr><th>Max RBBA Diffs</th><td>[{{cell.maxRGBADiffs}}]</td></tr> |
| <tr><th>N</th><td>[{{cell.n}}]</td></tr> |
| </table> |
| </paper-tooltip> |
| </div> |
| </template> |
| </div> |
| </template> |
| </div> |
| </div> |
| </div> |
| </template> |
| <script> |
| (function () { |
| |
| Polymer({ |
| is: 'grid-sk', |
| |
| properties: { |
| _value: { |
| type: Object, |
| value: function() { return {}; } |
| } |
| }, |
| |
| ready: function () { |
| this.listen(this.$.rowsContainer, 'click', "_handleCellsClick"); |
| this.listen(this.$.rowsContainer, 'dblclick', "_handleCellsDblClick"); |
| this.clearSelection(); |
| }, |
| |
| _handleCellsClick: function(ev) { |
| this._fireDiffEvent('diff-click', ev); |
| }, |
| |
| _handleCellsDblClick: function(ev) { |
| this._fireDiffEvent('diff-dblclick', ev); |
| }, |
| |
| _fireDiffEvent(evType, ev) { |
| if (ev.target.tagName === 'IMG') { |
| ev.stopPropagation(); |
| if (this._deferredFire) { |
| this.cancelAsync(this._deferredFire); |
| this._deferredFire = null; |
| } |
| |
| if ((ev.type === 'click') && (ev.detail > 1)) { |
| return; |
| } |
| |
| // Fire the event, potentially with a delay. |
| var rowDigest = ev.target.dataRowdigest, |
| row = ev.target.dataRow, |
| col = ev.target.dataCol; |
| |
| var detail = null; |
| if (rowDigest !== undefined) { |
| row = rowDigest; |
| detail = sk.object.shallowCopy(this._value.rows[row]); |
| delete(detail, 'values'); |
| } else if ((row !== undefined) && (col !== undefined)) { |
| detail = sk.object.shallowCopy(this._value.rows[row].values[col]); |
| detail.colDigest = this._value.rows[row].values[col].digest; |
| } |
| |
| if (!detail) { |
| return; |
| } |
| |
| detail.rowDigest = this._value.rows[row].digest; |
| detail.test = this._value.rows[row].test; |
| detail.rowIndex = row; |
| detail.columnIndex = col; |
| |
| var delay = (ev.type === 'click') ? 500 : 0; |
| this._deferredFire = this.async(function() { |
| this.fire(evType, detail); |
| this._deferredFire = null; |
| }.bind(this), delay); |
| } |
| }, |
| |
| setValue: function (value) { |
| this.set("_value", value); |
| }, |
| |
| _highlightClear: function(selector, clear) { |
| var ele = this.$$(selector); |
| if (ele) { |
| this.toggleClass('highlight', !clear, ele); |
| return true; |
| } |
| return false; |
| }, |
| |
| selectCell: function(row, column) { |
| if (this._highlightClear('#cell-'+ row + '-' + column, false)) { |
| this._selectedCellRow = row; |
| this._selectedCellCol = column; |
| } |
| }, |
| |
| selectRow: function(row) { |
| if (this._highlightClear('#row-'+ row, false)) { |
| this._selectedRow = row; |
| } |
| }, |
| |
| clearSelection: function() { |
| if (this._selectedCellRow >= 0) { |
| this._highlightClear('#cell-'+ this._selectedCellRow + '-' + this._selectedCellCol, true); |
| } |
| if (this._selectedRow >= 0) { |
| this._highlightClear('#row-'+ this._selectedRow, true); |
| } |
| this._selectedCellRow = -1; |
| this._selectedCellCol = -1; |
| this._selectedRow = -1; |
| }, |
| |
| _getColsWithHeaders: function(cols) { |
| if (!cols) { |
| return []; |
| } |
| |
| var ret = []; |
| for(var i=0, ilen=cols.length; i<ilen; i++) { |
| if (this._diffTitle(cols[i].type)) { |
| ret.push(cols[i]); |
| } else { |
| return ret; |
| } |
| } |
| return ret; |
| }, |
| |
| _hasNoHeaderCols: function(cols) { |
| if (!cols) { |
| return false; |
| } |
| |
| var withHeaders = this._getColsWithHeaders(cols); |
| return (withHeaders.length < cols.length); |
| }, |
| |
| _diffHref: function(row, cell) { |
| return gold.diffImgHref(row.digest, cell.digest); |
| }, |
| |
| _imgHref: gold.imgHref, |
| _diffTitle: gold.getDiffTitle |
| |
| }); |
| }()); |
| </script> |
| </dom-module> |