Home | History | Annotate | Download | only in static
      1 <!DOCTYPE html>
      2 
      3 <html ng-app="Loader" ng-controller="Loader.Controller">
      4 
      5 <head>
      6   <title ng-bind="windowTitle"></title>
      7   <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
      8   <script src="constants.js"></script>
      9   <script src="loader.js"></script>
     10   <link rel="stylesheet" href="view.css">
     11 </head>
     12 
     13 <body>
     14   <h2>
     15     Instructions, roadmap, etc. are at
     16     <a href="http://tinyurl.com/SkiaRebaselineServer">
     17       http://tinyurl.com/SkiaRebaselineServer
     18     </a>
     19   </h2>
     20 
     21   <em ng-show="!extraColumnHeaders"><!-- show until data is loaded -->
     22     Loading results from <a href="{{resultsToLoad}}">{{resultsToLoad}}</a> ...
     23     {{loadingMessage}}
     24   </em>
     25 
     26   <div ng-show="extraColumnHeaders"><!-- everything: hide until data is loaded -->
     27 
     28     <div class="warning-div"
     29          ng-show="header[constants.KEY__HEADER__IS_EDITABLE] && header[constants.KEY__HEADER__IS_EXPORTED]">
     30       WARNING!  These results are editable and exported, so any user
     31       who can connect to this server over the network can modify them.
     32     </div>
     33 
     34     <div ng-show="header[constants.KEY__HEADER__TIME_UPDATED]">
     35       These results, from raw JSON file
     36       <a href="{{resultsToLoad}}">{{resultsToLoad}}</a>, current as of
     37       {{localTimeString(header[constants.KEY__HEADER__TIME_UPDATED])}}
     38       <br>
     39       To see other sets of results (all results, failures only, etc.),
     40       <a href="/">click here</a>
     41     </div>
     42 
     43     <div class="tab-wrapper"><!-- tabs -->
     44       <div class="tab-spacer" ng-repeat="tab in tabs">
     45         <div class="tab tab-{{tab == viewingTab}}"
     46              ng-click="setViewingTab(tab)">
     47           &nbsp;{{tab}} ({{numResultsPerTab[tab]}})&nbsp;
     48         </div>
     49         <div class="tab-spacer">
     50           &nbsp;
     51         </div>
     52       </div>
     53     </div><!-- tabs -->
     54 
     55     <div class="tab-main"><!-- main display area of selected tab -->
     56 
     57     <br>
     58     <!-- We only show the filters/settings table on the Unfiled tab. -->
     59     <table ng-show="viewingTab == defaultTab" border="1">
     60     <tr>
     61       <th colspan="4">
     62         Filters
     63       </th>
     64       <th>
     65         Settings
     66       </th>
     67     </tr>
     68     <tr valign="top">
     69       <td>
     70         resultType<br>
     71         <label ng-repeat="valueAndCount in extraColumnHeaders[constants.KEY__EXTRACOLUMNS__RESULT_TYPE][constants.KEY__EXTRACOLUMNHEADERS__VALUES_AND_COUNTS]">
     72           <input type="checkbox"
     73                  name="resultTypes"
     74                  value="{{valueAndCount[0]}}"
     75                  ng-checked="!isValueInSet(valueAndCount[0], hiddenResultTypes)"
     76                  ng-click="toggleValueInSet(valueAndCount[0], hiddenResultTypes); setUpdatesPending(true)">
     77           {{valueAndCount[0]}} ({{valueAndCount[1]}})<br>
     78         </label>
     79         <button ng-click="hiddenResultTypes = {}; updateResults()">
     80           all
     81         </button>
     82         <button ng-click="hiddenResultTypes = {}; toggleValuesInSet(allResultTypes, hiddenResultTypes); updateResults()">
     83           none
     84         </button>
     85         <button ng-click="toggleValuesInSet(allResultTypes, hiddenResultTypes); updateResults()">
     86           toggle
     87         </button>
     88       </td>
     89       <td ng-repeat="category in [constants.KEY__EXTRACOLUMNS__BUILDER, constants.KEY__EXTRACOLUMNS__TEST]">
     90         {{category}}
     91         <br>
     92         <input type="text"
     93                ng-model="categoryValueMatch[category]"
     94                ng-change="setUpdatesPending(true)"/>
     95         <br>
     96         <button ng-click="setCategoryValueMatch(category, '')"
     97                 ng-disabled="('' == categoryValueMatch[category])">
     98           clear (show all)
     99         </button>
    100       </td>
    101       <td>
    102         config<br>
    103         <label ng-repeat="valueAndCount in extraColumnHeaders[constants.KEY__EXTRACOLUMNS__CONFIG][constants.KEY__EXTRACOLUMNHEADERS__VALUES_AND_COUNTS]">
    104           <input type="checkbox"
    105                  name="configs"
    106                  value="{{valueAndCount[0]}}"
    107                  ng-checked="!isValueInSet(valueAndCount[0], hiddenConfigs)"
    108                  ng-click="toggleValueInSet(valueAndCount[0], hiddenConfigs); setUpdatesPending(true)">
    109           {{valueAndCount[0]}} ({{valueAndCount[1]}})<br>
    110         </label>
    111         <button ng-click="hiddenConfigs = {}; updateResults()">
    112           all
    113         </button>
    114         <button ng-click="hiddenConfigs = {}; toggleValuesInSet(allConfigs, hiddenConfigs); updateResults()">
    115           none
    116         </button>
    117         <button ng-click="toggleValuesInSet(allConfigs, hiddenConfigs); updateResults()">
    118           toggle
    119         </button>
    120       </td>
    121       <td><table>
    122         <tr><td>
    123           <input type="checkbox" ng-model="showThumbnailsPending"
    124                  ng-init="showThumbnailsPending = true"
    125                  ng-change="areUpdatesPending = true"/>
    126           Show thumbnails
    127         </td></tr>
    128         <tr><td>
    129           <input type="checkbox" ng-model="mergeIdenticalRowsPending"
    130                  ng-init="mergeIdenticalRowsPending = true"
    131                  ng-change="areUpdatesPending = true"/>
    132           Merge identical rows
    133         </td></tr>
    134         <tr><td>
    135           Image width
    136           <input type="text" ng-model="imageSizePending"
    137                  ng-init="imageSizePending=100"
    138                  ng-change="areUpdatesPending = true"
    139                  maxlength="4"/>
    140         </td></tr>
    141         <tr><td>
    142           Max records to display
    143           <input type="text" ng-model="displayLimitPending"
    144                  ng-init="displayLimitPending=50"
    145                  ng-change="areUpdatesPending = true"
    146                  maxlength="4"/>
    147         </td></tr>
    148         <tr><td>
    149           <button class="update-results-button"
    150                   ng-click="updateResults()"
    151                   ng-disabled="!areUpdatesPending">
    152             Update Results
    153           </button>
    154         </td></tr>
    155       </tr></table></td>
    156     </tr>
    157   </table>
    158 
    159       <p>
    160 
    161       <!-- Submission UI that we only show in the Pending Approval tab. -->
    162       <div ng-show="'Pending Approval' == viewingTab">
    163         <div style="display:inline-block">
    164           <button style="font-size:20px"
    165                   ng-click="submitApprovals(filteredImagePairs)"
    166                   ng-disabled="submitPending || (filteredImagePairs.length == 0)">
    167             Update these {{filteredImagePairs.length}} expectations on the server
    168           </button>
    169         </div>
    170         <div style="display:inline-block">
    171           <div style="font-size:20px"
    172                ng-show="submitPending">
    173             Submitting, please wait...
    174           </div>
    175         </div>
    176         <div>
    177           Advanced settings...
    178           <input type="checkbox" ng-model="showSubmitAdvancedSettings">
    179           show
    180           <ul ng-show="showSubmitAdvancedSettings">
    181             <li ng-repeat="setting in [constants.KEY__EXPECTATIONS__REVIEWED, constants.KEY__EXPECTATIONS__IGNOREFAILURE]">
    182               {{setting}}
    183               <input type="checkbox" ng-model="submitAdvancedSettings[setting]">
    184             </li>
    185             <li ng-repeat="setting in ['bug']">
    186               {{setting}}
    187               <input type="text" ng-model="submitAdvancedSettings[setting]">
    188             </li>
    189           </ul>
    190         </div>
    191       </div>
    192 
    193       <p>
    194 
    195     <table border="0"><tr><td> <!-- table holding results header + results table -->
    196       <table border="0" width="100%"> <!-- results header -->
    197         <tr>
    198           <td>
    199             Found {{filteredImagePairs.length}} matches;
    200             <span ng-show="filteredImagePairs.length > limitedImagePairs.length">
    201               displaying the first {{limitedImagePairs.length}}.
    202             </span>
    203             <span ng-show="filteredImagePairs.length <= limitedImagePairs.length">
    204               displaying them all.
    205             </span>
    206             <span ng-show="renderEndTime > renderStartTime">
    207               Rendered in {{(renderEndTime - renderStartTime).toFixed(0)}} ms.
    208             </span>
    209             <br>
    210             (click on the column header radio buttons to re-sort by that column)
    211           </td>
    212           <td align="right">
    213             <div>
    214               all tests shown:
    215               <button ng-click="selectAllImagePairs()">
    216                 select
    217               </button>
    218               <button ng-click="clearAllImagePairs()">
    219                 clear
    220               </button>
    221               <button ng-click="toggleAllImagePairs()">
    222                 toggle
    223               </button>
    224             </div>
    225             <div ng-repeat="otherTab in tabs">
    226               <button ng-click="moveSelectedImagePairsToTab(otherTab)"
    227                       ng-disabled="selectedImagePairs.length == 0"
    228                       ng-show="otherTab != viewingTab">
    229                 move {{selectedImagePairs.length}} selected tests to {{otherTab}} tab
    230               </button>
    231             </div>
    232           </td>
    233         </tr>
    234       </table> <!-- results header -->
    235       </td></tr><tr><td>
    236       <table border="1" ng-app="diff_viewer"> <!-- results -->
    237         <tr>
    238           <!-- Most column headers are displayed in a common fashion... -->
    239           <th ng-repeat="categoryName in [constants.KEY__EXTRACOLUMNS__RESULT_TYPE, constants.KEY__EXTRACOLUMNS__BUILDER, constants.KEY__EXTRACOLUMNS__TEST, constants.KEY__EXTRACOLUMNS__CONFIG]">
    240             <input type="radio"
    241                    name="sortColumnRadio"
    242                    value="{{categoryName}}"
    243                    ng-checked="(sortColumnKey == categoryName)"
    244                    ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXTRACOLUMNS, categoryName)">
    245             {{categoryName}}
    246           </th>
    247           <!-- ... but there are a few columns where we display things differently. -->
    248           <th>
    249             <input type="radio"
    250                    name="sortColumnRadio"
    251                    value="bugs"
    252                    ng-checked="(sortColumnKey == constants.KEY__EXPECTATIONS__BUGS)"
    253                    ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXPECTATIONS, constants.KEY__EXPECTATIONS__BUGS)">
    254             bugs
    255           </th>
    256           <th width="{{imageSize}}">
    257             <input type="radio"
    258                    name="sortColumnRadio"
    259                    value="imageA"
    260                    ng-checked="(sortColumnKey == constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"
    261                    ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_A_URL)">
    262             {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
    263           </th>
    264           <th width="{{imageSize}}">
    265             <input type="radio"
    266                    name="sortColumnRadio"
    267                    value="imageB"
    268                    ng-checked="(sortColumnKey == constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"
    269                    ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_B_URL)">
    270             {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
    271           </th>
    272           <th width="{{imageSize}}">
    273             <input type="radio"
    274                    name="sortColumnRadio"
    275                    value="percentDifferingPixels"
    276                    ng-checked="(sortColumnKey == constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)"
    277                    ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)">
    278             differing pixels in white
    279           </th>
    280           <th width="{{imageSize}}">
    281             <input type="radio"
    282                    name="sortColumnRadio"
    283                    value="perceptualDiff"
    284                    ng-checked="(sortColumnKey == constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)"
    285                    ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)">
    286             perceptual difference
    287             <br>
    288             <input type="range" ng-model="pixelDiffBgColorBrightness"
    289                    ng-init="pixelDiffBgColorBrightness=64; pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)"
    290                    ng-change="pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)"
    291                    title="image background brightness"
    292                    min="0" max="255"/>
    293           </th>
    294           <th>
    295             <!-- imagepair-selection checkbox column -->
    296           </th>
    297         </tr>
    298 
    299         <tr ng-repeat="imagePair in limitedImagePairs" valign="top"
    300             ng-class-odd="'results-odd'" ng-class-even="'results-even'"
    301             results-updated-callback-directive>
    302           <td>
    303             {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__RESULT_TYPE]}}
    304             <br>
    305             <button class="show-only-button"
    306                     ng-show="viewingTab == defaultTab"
    307                     ng-click="showOnlyResultType(imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__RESULT_TYPE])"
    308                     title="show only results of type {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__RESULT_TYPE]}}">
    309               show only
    310             </button>
    311             <br>
    312             <button class="show-all-button"
    313                     ng-show="viewingTab == defaultTab"
    314                     ng-disabled="0 == setSize(hiddenResultTypes)"
    315                     ng-click="showAllResultTypes()"
    316                     title="show results of all types">
    317               show all
    318             </button>
    319           </td>
    320           <td ng-repeat="categoryName in [constants.KEY__EXTRACOLUMNS__BUILDER, constants.KEY__EXTRACOLUMNS__TEST]">
    321             {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][categoryName]}}
    322             <br>
    323             <button class="show-only-button"
    324                     ng-show="viewingTab == defaultTab"
    325                     ng-disabled="imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][categoryName] == categoryValueMatch[categoryName]"
    326                     ng-click="setCategoryValueMatch(categoryName, imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][categoryName])"
    327                     title="show only results of {{categoryName}} {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][categoryName]}}">
    328               show only
    329             </button>
    330             <br>
    331             <button class="show-all-button"
    332                     ng-show="viewingTab == defaultTab"
    333                     ng-disabled="'' == categoryValueMatch[categoryName]"
    334                     ng-click="setCategoryValueMatch(categoryName, '')"
    335                     title="show results of all {{categoryName}}s">
    336               show all
    337             </button>
    338           </td>
    339           <td>
    340             {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__CONFIG]}}
    341             <br>
    342             <button class="show-only-button"
    343                     ng-show="viewingTab == defaultTab"
    344                     ng-click="showOnlyConfig(imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__CONFIG])"
    345                     title="show only results of config {{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__CONFIG]}}">
    346               show only
    347             </button>
    348             <br>
    349             <button class="show-all-button"
    350                     ng-show="viewingTab == defaultTab"
    351                     ng-disabled="0 == setSize(hiddenConfigs)"
    352                     ng-click="showAllConfigs()"
    353                     title="show results of all configs">
    354               show all
    355             </button>
    356           </td>
    357           <td>
    358             <a ng-repeat="bug in imagePair[constants.KEY__IMAGEPAIRS__EXPECTATIONS][constants.KEY__EXPECTATIONS__BUGS]"
    359                href="https://code.google.com/p/skia/issues/detail?id={{bug}}"
    360                target="_blank">
    361               {{bug}}
    362             </a>
    363           </td>
    364 
    365           <!-- image A -->
    366           <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
    367             <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] != null">
    368               <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/>
    369               <img ng-if="showThumbnails"
    370                    width="{{imageSize}}"
    371                    ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL]}}" />
    372             </div>
    373             <div ng-show="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] == null"
    374                  style="text-align:center">
    375               &ndash;none&ndash;
    376             </div>
    377           </td>
    378 
    379           <!-- image B -->
    380           <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
    381             <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL] != null">
    382               <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/>
    383               <img ng-if="showThumbnails"
    384                    width="{{imageSize}}"
    385                    ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]}}" />
    386             </div>
    387             <div ng-show="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL] == null"
    388                  style="text-align:center">
    389               &ndash;none&ndash;
    390             </div>
    391           </td>
    392 
    393           <!-- whitediffs: every differing pixel shown in white -->
    394           <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
    395             <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
    396                  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.">
    397 
    398               <a href="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
    399               <img ng-if="showThumbnails"
    400                    width="{{imageSize}}"
    401                    ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" />
    402               <br/>
    403               {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS].toFixed(4)}}%
    404               ({{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS]}})
    405             </div>
    406             <div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
    407                  style="text-align:center">
    408               &ndash;none&ndash;
    409             </div>
    410           </td>
    411 
    412           <!-- diffs: per-channel RGB deltas -->
    413           <td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
    414             <div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
    415                  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]}}">
    416 
    417               <a href="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
    418               <img ng-if="showThumbnails"
    419                    ng-style="{backgroundColor: pixelDiffBgColor}"
    420                    width="{{imageSize}}"
    421                    ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" />
    422               <br/>
    423               {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF].toFixed(4)}}%
    424               {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL]}}
    425             </div>
    426             <div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
    427                  style="text-align:center">
    428               &ndash;none&ndash;
    429             </div>
    430           </td>
    431 
    432           <td ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
    433             <br/>
    434             <input type="checkbox"
    435                    name="rowSelect"
    436                    value="{{imagePair.index}}"
    437                    ng-checked="isValueInArray(imagePair.index, selectedImagePairs)"
    438                    ng-click="toggleSomeImagePairs($index, imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN])">
    439         </tr>
    440       </table> <!-- imagePairs -->
    441     </td></tr></table> <!-- table holding results header + imagePairs table -->
    442 
    443   </div><!-- main display area of selected tab -->
    444   </div><!-- everything: hide until data is loaded -->
    445 
    446 </body>
    447 </html>
    448