| Index: gm/rebaseline_server/static/view.html
|
| diff --git a/gm/rebaseline_server/static/view.html b/gm/rebaseline_server/static/view.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f6ebf5a9a4092a28be983a59967063a6d95d1e15
|
| --- /dev/null
|
| +++ b/gm/rebaseline_server/static/view.html
|
| @@ -0,0 +1,417 @@
|
| +<!DOCTYPE html>
|
| +
|
| +<html ng-app="Loader" ng-controller="Loader.Controller">
|
| +
|
| +<head>
|
| + <title ng-bind="windowTitle"></title>
|
| + <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
| + <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.js"></script>
|
| + <script src="constants.js"></script>
|
| + <script src="loader.js"></script>
|
| + <script src="utils.js"></script>
|
| + <link rel="stylesheet" href="view.css">
|
| +</head>
|
| +
|
| +<body>
|
| + <h2>
|
| + Instructions, roadmap, etc. are at
|
| + <a href="http://tinyurl.com/SkiaRebaselineServer">
|
| + http://tinyurl.com/SkiaRebaselineServer
|
| + </a>
|
| + </h2>
|
| +
|
| + <em ng-show="!readyToDisplay">
|
| + Loading results from <a href="{{resultsToLoad}}">{{resultsToLoad}}</a> ...
|
| + {{loadingMessage}}
|
| + </em>
|
| +
|
| + <div ng-show="readyToDisplay">
|
| +
|
| + <div class="warning-div"
|
| + ng-show="urlSchemaVersionLoaded != constants.URL_VALUE__SCHEMA_VERSION__CURRENT">
|
| + WARNING! The URL you loaded used schema version {{urlSchemaVersionLoaded}}, rather than
|
| + the most recent version {{constants.URL_VALUE__SCHEMA_VERSION__CURRENT}}. It has been
|
| + converted to the most recent version on a best-effort basis; you may wish to double-check
|
| + which records are displayed.
|
| + </div>
|
| +
|
| + <div class="warning-div"
|
| + ng-show="header[constants.KEY__HEADER__IS_EDITABLE] && header[constants.KEY__HEADER__IS_EXPORTED]">
|
| + WARNING! These results are editable and exported, so any user
|
| + who can connect to this server over the network can modify them.
|
| + </div>
|
| +
|
| + <div ng-show="header[constants.KEY__HEADER__TIME_UPDATED]">
|
| + These results, from raw JSON file
|
| + <a href="{{resultsToLoad}}">{{resultsToLoad}}</a>, current as of
|
| + {{localTimeString(header[constants.KEY__HEADER__TIME_UPDATED])}}
|
| + <br>
|
| + To see other sets of results (all results, failures only, etc.),
|
| + <a href="/">click here</a>
|
| + </div>
|
| +
|
| + <div class="tab-wrapper"><!-- tabs -->
|
| + <div class="tab-spacer" ng-repeat="tab in tabs">
|
| + <div class="tab tab-{{tab == viewingTab}}"
|
| + ng-click="setViewingTab(tab)">
|
| + {{tab}} ({{numResultsPerTab[tab]}})
|
| + </div>
|
| + <div class="tab-spacer">
|
| +
|
| + </div>
|
| + </div>
|
| + </div><!-- tabs -->
|
| +
|
| + <div class="tab-main"><!-- main display area of selected tab -->
|
| +
|
| + <br>
|
| + <!-- We only show the filters/settings table on the Unfiled tab. -->
|
| + <table ng-show="viewingTab == defaultTab" border="1">
|
| + <tr>
|
| + <th colspan="4">
|
| + Filters
|
| + </th>
|
| + <th>
|
| + Settings
|
| + </th>
|
| + </tr>
|
| + <tr valign="top">
|
| +
|
| + <!-- filters -->
|
| + <td ng-repeat="columnName in orderedColumnNames">
|
| +
|
| + <!-- Only display filterable columns here... -->
|
| + <div ng-if="extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__IS_FILTERABLE]">
|
| + {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}}<br>
|
| +
|
| + <!-- If we filter this column using free-form text match... -->
|
| + <div ng-if="extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__USE_FREEFORM_FILTER]">
|
| + <input type="text"
|
| + ng-model="columnStringMatch[columnName]"
|
| + ng-change="setUpdatesPending(true)"/>
|
| + <br>
|
| + <button ng-click="setColumnStringMatch(columnName, '')"
|
| + ng-disabled="('' == columnStringMatch[columnName])">
|
| + clear (show all)
|
| + </button>
|
| + </div>
|
| +
|
| + <!-- If we filter this column using checkboxes... -->
|
| + <div ng-if="!extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__USE_FREEFORM_FILTER]">
|
| + <label ng-repeat="valueAndCount in extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__VALUES_AND_COUNTS]">
|
| + <input type="checkbox"
|
| + name="resultTypes"
|
| + value="{{valueAndCount[0]}}"
|
| + ng-checked="isValueInSet(valueAndCount[0], showingColumnValues[columnName])"
|
| + ng-click="toggleValueInSet(valueAndCount[0], showingColumnValues[columnName]); setUpdatesPending(true)">
|
| + {{valueAndCount[0]}} ({{valueAndCount[1]}})<br>
|
| + </label>
|
| + <button ng-click="showingColumnValues[columnName] = {}; toggleValuesInSet(allColumnValues[columnName], showingColumnValues[columnName]); updateResults()"
|
| + ng-disabled="!readyToDisplay || allColumnValues[columnName].length == setSize(showingColumnValues[columnName])">
|
| + all
|
| + </button>
|
| + <button ng-click="showingColumnValues[columnName] = {}; updateResults()"
|
| + ng-disabled="!readyToDisplay || 0 == setSize(showingColumnValues[columnName])">
|
| + none
|
| + </button>
|
| + <button ng-click="toggleValuesInSet(allColumnValues[columnName], showingColumnValues[columnName]); updateResults()">
|
| + toggle
|
| + </button>
|
| + </div>
|
| +
|
| + </div>
|
| + </td>
|
| +
|
| + <!-- settings -->
|
| + <td><table>
|
| + <tr><td>
|
| + <input type="checkbox" ng-model="showThumbnailsPending"
|
| + ng-init="showThumbnailsPending = true"
|
| + ng-change="areUpdatesPending = true"/>
|
| + Show thumbnails
|
| + </td></tr>
|
| + <tr><td>
|
| + <input type="checkbox" ng-model="mergeIdenticalRowsPending"
|
| + ng-init="mergeIdenticalRowsPending = true"
|
| + ng-change="areUpdatesPending = true"/>
|
| + Merge identical rows
|
| + </td></tr>
|
| + <tr><td>
|
| + Image width
|
| + <input type="text" ng-model="imageSizePending"
|
| + ng-init="imageSizePending=100"
|
| + ng-change="areUpdatesPending = true"
|
| + maxlength="4"/>
|
| + </td></tr>
|
| + <tr><td>
|
| + Max records to display
|
| + <input type="text" ng-model="displayLimitPending"
|
| + ng-init="displayLimitPending=50"
|
| + ng-change="areUpdatesPending = true"
|
| + maxlength="4"/>
|
| + </td></tr>
|
| + <tr><td>
|
| + <button class="update-results-button"
|
| + ng-click="updateResults()"
|
| + ng-disabled="!areUpdatesPending">
|
| + Update Results
|
| + </button>
|
| + </td></tr>
|
| + </tr></table></td>
|
| + </tr>
|
| + </table>
|
| +
|
| + <p>
|
| +
|
| + <!-- Submission UI that we only show in the Pending Approval tab. -->
|
| + <div ng-show="'Pending Approval' == viewingTab">
|
| + <div style="display:inline-block">
|
| + <button style="font-size:20px"
|
| + ng-click="submitApprovals(filteredImagePairs)"
|
| + ng-disabled="submitPending || (filteredImagePairs.length == 0)">
|
| + Update these {{filteredImagePairs.length}} expectations on the server
|
| + </button>
|
| + </div>
|
| + <div style="display:inline-block">
|
| + <div style="font-size:20px"
|
| + ng-show="submitPending">
|
| + Submitting, please wait...
|
| + </div>
|
| + </div>
|
| + <div>
|
| + Advanced settings...
|
| + <input type="checkbox" ng-model="showSubmitAdvancedSettings">
|
| + show
|
| + <ul ng-show="showSubmitAdvancedSettings">
|
| + <li ng-repeat="setting in [constants.KEY__EXPECTATIONS__REVIEWED, constants.KEY__EXPECTATIONS__IGNOREFAILURE]">
|
| + {{setting}}
|
| + <input type="checkbox" ng-model="submitAdvancedSettings[setting]">
|
| + </li>
|
| + <li ng-repeat="setting in ['bug']">
|
| + {{setting}}
|
| + <input type="text" ng-model="submitAdvancedSettings[setting]">
|
| + </li>
|
| + </ul>
|
| + </div>
|
| + </div>
|
| +
|
| + <p>
|
| +
|
| + <div class="results-header"> <!-- results header -->
|
| + <div class="results-header-actions">
|
| + all tests shown:
|
| + <button ng-click="selectAllImagePairs()">
|
| + select
|
| + </button>
|
| + <button ng-click="clearAllImagePairs()">
|
| + clear
|
| + </button>
|
| + <button ng-click="toggleAllImagePairs()">
|
| + toggle
|
| + </button>
|
| + <div ng-repeat="otherTab in tabs">
|
| + <button ng-click="moveSelectedImagePairsToTab(otherTab)"
|
| + ng-disabled="selectedImagePairs.length == 0"
|
| + ng-show="otherTab != viewingTab">
|
| + move {{selectedImagePairs.length}} selected tests to {{otherTab}} tab
|
| + </button>
|
| + </div>
|
| + </div>
|
| + <div class="results-header-stats">
|
| + Found {{filteredImagePairs.length}} matches;
|
| + <span ng-show="filteredImagePairs.length > limitedImagePairs.length">
|
| + displaying the first {{limitedImagePairs.length}}.
|
| + </span>
|
| + <span ng-show="filteredImagePairs.length <= limitedImagePairs.length">
|
| + displaying them all.
|
| + </span>
|
| + <span ng-show="renderEndTime > renderStartTime">
|
| + Rendered in {{(renderEndTime - renderStartTime).toFixed(0)}} ms.
|
| + </span>
|
| + <br>
|
| + (click on the column header radio buttons to re-sort by that column)
|
| + </div>
|
| + </div> <!-- results header -->
|
| +
|
| + <table border="0"><tr><td> <!-- table holding results header + results table -->
|
| + </td></tr><tr><td>
|
| + <table border="1"> <!-- results -->
|
| + <tr>
|
| + <!-- Most column headers are displayed in a common fashion... -->
|
| + <th ng-repeat="columnName in orderedColumnNames">
|
| + <a ng-class="'sort-' + sortedByColumnsCls(columnName)"
|
| + ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXTRACOLUMNS, columnName)"
|
| + href=""
|
| + class="sortable-header">
|
| + {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}}
|
| + </a>
|
| + </th>
|
| +
|
| + <!-- ... but there are a few columns where we display things differently. -->
|
| + <th>
|
| + <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__EXPECTATIONS__BUGS)"
|
| + ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXPECTATIONS, constants.KEY__EXPECTATIONS__BUGS)"
|
| + href=""
|
| + class="sortable-header">
|
| + bugs
|
| + </a>
|
| + </th>
|
| + <th width="{{imageSize}}">
|
| + <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"
|
| + ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"
|
| + href=""
|
| + class="sortable-header">
|
| + {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
|
| + </a>
|
| + </th>
|
| + <th width="{{imageSize}}">
|
| + <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"
|
| + ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"
|
| + href=""
|
| + class="sortable-header">
|
| + {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
|
| + </a>
|
| + </th>
|
| + <th width="{{imageSize}}">
|
| + <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)"
|
| + ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)"
|
| + href=""
|
| + class="sortable-header">
|
| + differing pixels in white
|
| + </a>
|
| + </th>
|
| + <th width="{{imageSize}}">
|
| + <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)"
|
| + ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)"
|
| + href=""
|
| + class="sortable-header">
|
| + perceptual difference
|
| + </a>
|
| + <br>
|
| + <input type="range" ng-model="pixelDiffBgColorBrightness"
|
| + ng-init="pixelDiffBgColorBrightness=64; pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)"
|
| + ng-change="pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)"
|
| + title="image background brightness"
|
| + min="0" max="255"/>
|
| + </th>
|
| + <th>
|
| + <!-- imagepair-selection checkbox column -->
|
| + </th>
|
| + </tr>
|
| +
|
| + <tr ng-repeat="imagePair in limitedImagePairs" valign="top"
|
| + ng-class-odd="'results-odd'" ng-class-even="'results-even'"
|
| + results-updated-callback-directive>
|
| +
|
| + <td ng-repeat="columnName in orderedColumnNames">
|
| + {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][columnName]}}
|
| + <br>
|
| + <button class="show-only-button"
|
| + ng-show="viewingTab == defaultTab"
|
| + ng-disabled="1 == setSize(showingColumnValues[columnName])"
|
| + ng-click="showOnlyColumnValue(columnName, imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][columnName])"
|
| + title="show only results of {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}} {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][columnName]}}">
|
| + show only
|
| + </button>
|
| + <br>
|
| + <button class="show-all-button"
|
| + ng-show="viewingTab == defaultTab"
|
| + ng-disabled="allColumnValues[columnName].length == setSize(showingColumnValues[columnName])"
|
| + ng-click="showAllColumnValues(columnName)"
|
| + title="show results of all {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}}s">
|
| + show all
|
| + </button>
|
| + </td>
|
| +
|
| + <!-- bugs -->
|
| + <td>
|
| + <a ng-repeat="bug in imagePair[constants.KEY__IMAGEPAIRS__EXPECTATIONS][constants.KEY__EXPECTATIONS__BUGS]"
|
| + href="https://code.google.com/p/skia/issues/detail?id={{bug}}"
|
| + target="_blank">
|
| + {{bug}}
|
| + </a>
|
| + </td>
|
| +
|
| + <!-- image A -->
|
| + <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
|
| + <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] != null">
|
| + <a href="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL]}}" target="_blank">View Image</a><br/>
|
| + <img ng-if="showThumbnails"
|
| + width="{{imageSize}}"
|
| + ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL]}}" />
|
| + </div>
|
| + <div ng-show="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] == null"
|
| + style="text-align:center">
|
| + –none–
|
| + </div>
|
| + </td>
|
| +
|
| + <!-- image B -->
|
| + <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
|
| + <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL] != null">
|
| + <a href="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]}}" target="_blank">View Image</a><br/>
|
| + <img ng-if="showThumbnails"
|
| + width="{{imageSize}}"
|
| + ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]}}" />
|
| + </div>
|
| + <div ng-show="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL] == null"
|
| + style="text-align:center">
|
| + –none–
|
| + </div>
|
| + </td>
|
| +
|
| + <!-- whitediffs: every differing pixel shown in white -->
|
| + <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
|
| + <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
|
| + title="{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS] | number:0}} of {{(100 * imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS] / imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS]) | number:0}} pixels ({{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS].toFixed(4)}}%) differ from expectation.">
|
| +
|
| + <a href="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__WHITE_DIFF_URL]}}" target="_blank">View Image</a><br/>
|
| + <img ng-if="showThumbnails"
|
| + width="{{imageSize}}"
|
| + ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__WHITE_DIFF_URL]}}" />
|
| + <br/>
|
| + {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS].toFixed(4)}}%
|
| + ({{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS]}})
|
| + </div>
|
| + <div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
|
| + style="text-align:center">
|
| + –none–
|
| + </div>
|
| + </td>
|
| +
|
| + <!-- diffs: per-channel RGB deltas -->
|
| + <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
|
| + <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
|
| + title="Perceptual difference measure is {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF].toFixed(4)}}%. Maximum difference per channel: R={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][0]}}, G={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][1]}}, B={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][2]}}">
|
| +
|
| + <a href="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__DIFF_URL]}}" target="_blank">View Image</a><br/>
|
| + <img ng-if="showThumbnails"
|
| + ng-style="{backgroundColor: pixelDiffBgColor}"
|
| + width="{{imageSize}}"
|
| + ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__DIFF_URL]}}" />
|
| + <br/>
|
| + {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF].toFixed(4)}}%
|
| + {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL]}}
|
| + </div>
|
| + <div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
|
| + style="text-align:center">
|
| + –none–
|
| + </div>
|
| + </td>
|
| +
|
| + <td ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
|
| + <br/>
|
| + <input type="checkbox"
|
| + name="rowSelect"
|
| + value="{{imagePair.index}}"
|
| + ng-checked="isValueInArray(imagePair.index, selectedImagePairs)"
|
| + ng-click="toggleSomeImagePairs($index, imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN])">
|
| + </tr>
|
| + </table> <!-- imagePairs -->
|
| + </td></tr></table> <!-- table holding results header + imagePairs table -->
|
| +
|
| + </div><!-- main display area of selected tab -->
|
| + </div><!-- everything: hide until readyToDisplay -->
|
| +
|
| +</body>
|
| +</html>
|
|
|