Rebaseline-server: sorting of columns in asc/desc order in frontend.

NOTRY=true

BUG=skia:1907
R=epoger@google.com

Author: stephana@google.com

Review URL: https://codereview.chromium.org/449843002
This commit is contained in:
stephana 2014-08-08 07:21:00 -07:00 коммит произвёл Commit bot
Родитель be129b26f1
Коммит d9bf7dbf09
6 изменённых файлов: 163 добавлений и 121 удалений

Просмотреть файл

@ -80,5 +80,9 @@ module.constant('constants', (function() {
KEY__IMAGEPAIRS__ROWSPAN: 'rowspan', KEY__IMAGEPAIRS__ROWSPAN: 'rowspan',
URL_KEY__SCHEMA_VERSION: 'urlSchemaVersion', URL_KEY__SCHEMA_VERSION: 'urlSchemaVersion',
URL_VALUE__SCHEMA_VERSION__CURRENT: 1, URL_VALUE__SCHEMA_VERSION__CURRENT: 1,
// Utility constants only used on the client side.
ASC: 'asc',
DESC: 'desc',
} }
})()) })())

Просмотреть файл

@ -133,6 +133,9 @@ Loader.controller(
$scope.setBSection = $location.search().setBSection; $scope.setBSection = $location.search().setBSection;
$scope.loadingMessage = "please wait..."; $scope.loadingMessage = "please wait...";
var currSortAsc = true;
/** /**
* On initial page load, load a full dictionary of results. * On initial page load, load a full dictionary of results.
* Once the dictionary is loaded, unhide the page elements so they can * Once the dictionary is loaded, unhide the page elements so they can
@ -175,8 +178,11 @@ Loader.controller(
$scope.orderedColumnNames = data[constants.KEY__ROOT__EXTRACOLUMNORDER]; $scope.orderedColumnNames = data[constants.KEY__ROOT__EXTRACOLUMNORDER];
$scope.imagePairs = data[constants.KEY__ROOT__IMAGEPAIRS]; $scope.imagePairs = data[constants.KEY__ROOT__IMAGEPAIRS];
$scope.imageSets = data[constants.KEY__ROOT__IMAGESETS]; $scope.imageSets = data[constants.KEY__ROOT__IMAGESETS];
// set the default sort column and make it ascending.
$scope.sortColumnSubdict = constants.KEY__IMAGEPAIRS__DIFFERENCES; $scope.sortColumnSubdict = constants.KEY__IMAGEPAIRS__DIFFERENCES;
$scope.sortColumnKey = constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF; $scope.sortColumnKey = constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF;
currSortAsc = true;
$scope.showSubmitAdvancedSettings = false; $scope.showSubmitAdvancedSettings = false;
$scope.submitAdvancedSettings = {}; $scope.submitAdvancedSettings = {};
@ -610,14 +616,7 @@ Loader.controller(
// array copies? (For better performance.) // array copies? (For better performance.)
if ($scope.viewingTab == $scope.defaultTab) { if ($scope.viewingTab == $scope.defaultTab) {
var doReverse = !currSortAsc;
// TODO(epoger): Until we allow the user to reverse sort order,
// there are certain columns we want to sort in a different order.
var doReverse = (
($scope.sortColumnKey ==
constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS) ||
($scope.sortColumnKey ==
constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF));
$scope.filteredImagePairs = $scope.filteredImagePairs =
$filter("orderBy")( $filter("orderBy")(

Просмотреть файл

@ -5,7 +5,7 @@
<head> <head>
<title ng-bind="windowTitle"></title> <title ng-bind="windowTitle"></title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <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.1.5/angular.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.js"></script>
<script src="constants.js"></script> <script src="constants.js"></script>
<script src="live-loader.js"></script> <script src="live-loader.js"></script>
<script src="utils.js"></script> <script src="utils.js"></script>
@ -246,53 +246,54 @@
<tr> <tr>
<!-- Most column headers are displayed in a common fashion... --> <!-- Most column headers are displayed in a common fashion... -->
<th ng-repeat="columnName in orderedColumnNames"> <th ng-repeat="columnName in orderedColumnNames">
<input type="radio" <a ng-class="'sort-' + sortedByColumnsCls(columnName)"
name="sortColumnRadio" ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXTRACOLUMNS, columnName)"
value="{{columnName}}" href=""
ng-checked="(sortColumnKey == columnName)" class="sortable-header">
ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXTRACOLUMNS, columnName)"> {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}}
{{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}} </a>
</th> </th>
<!-- ... but there are a few columns where we display things differently. --> <!-- ... but there are a few columns where we display things differently. -->
<th> <th>
<input type="radio" <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__EXPECTATIONS__BUGS)"
name="sortColumnRadio" ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXPECTATIONS, constants.KEY__EXPECTATIONS__BUGS)"
value="bugs" href=""
ng-checked="(sortColumnKey == constants.KEY__EXPECTATIONS__BUGS)" class="sortable-header">
ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXPECTATIONS, constants.KEY__EXPECTATIONS__BUGS)"> bugs
</a>
bugs bugs
</th> </th>
<th width="{{imageSize}}"> <th width="{{imageSize}}">
<input type="radio" <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"
name="sortColumnRadio" ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"
value="imageA" href=""
ng-checked="(sortColumnKey == constants.KEY__IMAGEPAIRS__IMAGE_A_URL)" class="sortable-header">
ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"> {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}} </a>
</th> </th>
<th width="{{imageSize}}"> <th width="{{imageSize}}">
<input type="radio" <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"
name="sortColumnRadio" ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"
value="imageB" href=""
ng-checked="(sortColumnKey == constants.KEY__IMAGEPAIRS__IMAGE_B_URL)" class="sortable-header">
ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"> {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}} </a>
</th> </th>
<th width="{{imageSize}}"> <th width="{{imageSize}}">
<input type="radio" <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)"
name="sortColumnRadio" ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)"
value="percentDifferingPixels" href=""
ng-checked="(sortColumnKey == constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)" class="sortable-header">
ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)"> differing pixels in white
differing pixels in white </a>
</th> </th>
<th width="{{imageSize}}"> <th width="{{imageSize}}">
<input type="radio" <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)"
name="sortColumnRadio" ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)"
value="perceptualDiff" href=""
ng-checked="(sortColumnKey == constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)" class="sortable-header">
ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)"> perceptual difference
perceptual difference </a>
<br> <br>
<input type="range" ng-model="pixelDiffBgColorBrightness" <input type="range" ng-model="pixelDiffBgColorBrightness"
ng-init="pixelDiffBgColorBrightness=64; pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)" ng-init="pixelDiffBgColorBrightness=64; pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)"

Просмотреть файл

@ -130,6 +130,9 @@ Loader.controller(
$scope.resultsToLoad = $location.search().resultsToLoad; $scope.resultsToLoad = $location.search().resultsToLoad;
$scope.loadingMessage = "please wait..."; $scope.loadingMessage = "please wait...";
var currSortAsc = true;
/** /**
* On initial page load, load a full dictionary of results. * On initial page load, load a full dictionary of results.
* Once the dictionary is loaded, unhide the page elements so they can * Once the dictionary is loaded, unhide the page elements so they can
@ -167,8 +170,11 @@ Loader.controller(
$scope.orderedColumnNames = data[constants.KEY__ROOT__EXTRACOLUMNORDER]; $scope.orderedColumnNames = data[constants.KEY__ROOT__EXTRACOLUMNORDER];
$scope.imagePairs = data[constants.KEY__ROOT__IMAGEPAIRS]; $scope.imagePairs = data[constants.KEY__ROOT__IMAGEPAIRS];
$scope.imageSets = data[constants.KEY__ROOT__IMAGESETS]; $scope.imageSets = data[constants.KEY__ROOT__IMAGESETS];
// set the default sort column and make it ascending.
$scope.sortColumnSubdict = constants.KEY__IMAGEPAIRS__DIFFERENCES; $scope.sortColumnSubdict = constants.KEY__IMAGEPAIRS__DIFFERENCES;
$scope.sortColumnKey = constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF; $scope.sortColumnKey = constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF;
currSortAsc = true;
$scope.showSubmitAdvancedSettings = false; $scope.showSubmitAdvancedSettings = false;
$scope.submitAdvancedSettings = {}; $scope.submitAdvancedSettings = {};
@ -320,7 +326,7 @@ Loader.controller(
$scope.toggleValueInArray(index, $scope.selectedImagePairs); $scope.toggleValueInArray(index, $scope.selectedImagePairs);
} }
} }
} };
/** /**
* Deselect all currently showing tests. * Deselect all currently showing tests.
@ -333,7 +339,7 @@ Loader.controller(
$scope.toggleValueInArray(index, $scope.selectedImagePairs); $scope.toggleValueInArray(index, $scope.selectedImagePairs);
} }
} }
} };
/** /**
* Toggle selection of all currently showing tests. * Toggle selection of all currently showing tests.
@ -344,7 +350,7 @@ Loader.controller(
var index = $scope.limitedImagePairs[i].index; var index = $scope.limitedImagePairs[i].index;
$scope.toggleValueInArray(index, $scope.selectedImagePairs); $scope.toggleValueInArray(index, $scope.selectedImagePairs);
} }
} };
/** /**
* Toggle selection state of a subset of the currently showing tests. * Toggle selection state of a subset of the currently showing tests.
@ -359,7 +365,7 @@ Loader.controller(
var index = $scope.limitedImagePairs[i].index; var index = $scope.limitedImagePairs[i].index;
$scope.toggleValueInArray(index, $scope.selectedImagePairs); $scope.toggleValueInArray(index, $scope.selectedImagePairs);
} }
} };
// //
@ -374,7 +380,7 @@ Loader.controller(
$scope.setViewingTab = function(tab) { $scope.setViewingTab = function(tab) {
$scope.viewingTab = tab; $scope.viewingTab = tab;
$scope.updateResults(); $scope.updateResults();
} };
/** /**
* Move the imagePairs in $scope.selectedImagePairs to a different tab, * Move the imagePairs in $scope.selectedImagePairs to a different tab,
@ -386,7 +392,7 @@ Loader.controller(
$scope.moveImagePairsToTab($scope.selectedImagePairs, newTab); $scope.moveImagePairsToTab($scope.selectedImagePairs, newTab);
$scope.selectedImagePairs = []; $scope.selectedImagePairs = [];
$scope.updateResults(); $scope.updateResults();
} };
/** /**
* Move a subset of $scope.imagePairs to a different tab. * Move a subset of $scope.imagePairs to a different tab.
@ -404,7 +410,7 @@ Loader.controller(
$scope.imagePairs[imagePairIndex].tab = newTab; $scope.imagePairs[imagePairIndex].tab = newTab;
} }
$scope.numResultsPerTab[newTab] += numImagePairs; $scope.numResultsPerTab[newTab] += numImagePairs;
} };
// //
@ -597,16 +603,8 @@ Loader.controller(
// another copy of the array. Is there a way we can filter out // another copy of the array. Is there a way we can filter out
// the imagePairs as they are displayed, rather than storing multiple // the imagePairs as they are displayed, rather than storing multiple
// array copies? (For better performance.) // array copies? (For better performance.)
if ($scope.viewingTab == $scope.defaultTab) { if ($scope.viewingTab == $scope.defaultTab) {
var doReverse = !currSortAsc;
// TODO(epoger): Until we allow the user to reverse sort order,
// there are certain columns we want to sort in a different order.
var doReverse = (
($scope.sortColumnKey ==
constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS) ||
($scope.sortColumnKey ==
constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF));
$scope.filteredImagePairs = $scope.filteredImagePairs =
$filter("orderBy")( $filter("orderBy")(
@ -616,7 +614,8 @@ Loader.controller(
$scope.showingColumnValues, $scope.showingColumnValues,
$scope.viewingTab $scope.viewingTab
), ),
[$scope.getSortColumnValue, $scope.getSecondOrderSortValue], // [$scope.getSortColumnValue, $scope.getSecondOrderSortValue],
$scope.getSortColumnValue,
doReverse); doReverse);
$scope.limitedImagePairs = $filter("mergeAndLimit")( $scope.limitedImagePairs = $filter("mergeAndLimit")(
$scope.filteredImagePairs, $scope.displayLimit, $scope.mergeIdenticalRows); $scope.filteredImagePairs, $scope.displayLimit, $scope.mergeIdenticalRows);
@ -628,7 +627,8 @@ Loader.controller(
{tab: $scope.viewingTab}, {tab: $scope.viewingTab},
true true
), ),
[$scope.getSortColumnValue, $scope.getSecondOrderSortValue]); // [$scope.getSortColumnValue, $scope.getSecondOrderSortValue]);
$scope.getSortColumnValue);
$scope.limitedImagePairs = $filter("mergeAndLimit")( $scope.limitedImagePairs = $filter("mergeAndLimit")(
$scope.filteredImagePairs, -1, $scope.mergeIdenticalRows); $scope.filteredImagePairs, -1, $scope.mergeIdenticalRows);
} }
@ -645,7 +645,7 @@ Loader.controller(
$scope.resultsUpdatedCallback = function() { $scope.resultsUpdatedCallback = function() {
$scope.renderEndTime = window.performance.now(); $scope.renderEndTime = window.performance.now();
$log.debug("renderEndTime: " + $scope.renderEndTime); $log.debug("renderEndTime: " + $scope.renderEndTime);
} };
/** /**
* Re-sort the displayed results. * Re-sort the displayed results.
@ -656,10 +656,33 @@ Loader.controller(
* @param key (string): sort by value associated with this key in subdict * @param key (string): sort by value associated with this key in subdict
*/ */
$scope.sortResultsBy = function(subdict, key) { $scope.sortResultsBy = function(subdict, key) {
$scope.sortColumnSubdict = subdict; // if we are already sorting by this column then toggle between asc/desc
$scope.sortColumnKey = key; if ((subdict === $scope.sortColumnSubdict) && ($scope.sortColumnKey === key)) {
currSortAsc = !currSortAsc;
} else {
$scope.sortColumnSubdict = subdict;
$scope.sortColumnKey = key;
currSortAsc = true;
}
$scope.updateResults(); $scope.updateResults();
} };
/**
* Returns ASC or DESC (from constants) if currently the data
* is sorted by the provided column.
*
* @param colName: name of the column for which we need to get the class.
*/
$scope.sortedByColumnsCls = function (colName) {
if ($scope.sortColumnKey !== colName) {
return '';
}
var result = (currSortAsc) ? constants.ASC : constants.DESC;
console.log("sort class:", result);
return result;
};
/** /**
* For a particular ImagePair, return the value of the column we are * For a particular ImagePair, return the value of the column we are
@ -676,7 +699,7 @@ Loader.controller(
} else { } else {
return undefined; return undefined;
} }
} };
/** /**
* For a particular ImagePair, return the value we use for the * For a particular ImagePair, return the value we use for the
@ -691,7 +714,7 @@ Loader.controller(
$scope.getSecondOrderSortValue = function(imagePair) { $scope.getSecondOrderSortValue = function(imagePair) {
return imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" + return imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" +
imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]; imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL];
} };
/** /**
* Set $scope.columnStringMatch[name] = value, and update results. * Set $scope.columnStringMatch[name] = value, and update results.
@ -702,7 +725,7 @@ Loader.controller(
$scope.setColumnStringMatch = function(name, value) { $scope.setColumnStringMatch = function(name, value) {
$scope.columnStringMatch[name] = value; $scope.columnStringMatch[name] = value;
$scope.updateResults(); $scope.updateResults();
} };
/** /**
* Update $scope.showingColumnValues[columnName] and $scope.columnStringMatch[columnName] * Update $scope.showingColumnValues[columnName] and $scope.columnStringMatch[columnName]
@ -717,7 +740,7 @@ Loader.controller(
$scope.showingColumnValues[columnName] = {}; $scope.showingColumnValues[columnName] = {};
$scope.toggleValueInSet(columnValue, $scope.showingColumnValues[columnName]); $scope.toggleValueInSet(columnValue, $scope.showingColumnValues[columnName]);
$scope.updateResults(); $scope.updateResults();
} };
/** /**
* Update $scope.showingColumnValues[columnName] and $scope.columnStringMatch[columnName] * Update $scope.showingColumnValues[columnName] and $scope.columnStringMatch[columnName]
@ -732,7 +755,7 @@ Loader.controller(
$scope.toggleValuesInSet($scope.allColumnValues[columnName], $scope.toggleValuesInSet($scope.allColumnValues[columnName],
$scope.showingColumnValues[columnName]); $scope.showingColumnValues[columnName]);
$scope.updateResults(); $scope.updateResults();
} };
// //
@ -842,7 +865,7 @@ Loader.controller(
"Please see server-side log for details."); "Please see server-side log for details.");
$scope.submitPending = false; $scope.submitPending = false;
}); });
} };
// //
@ -860,7 +883,7 @@ Loader.controller(
*/ */
$scope.setSize = function(set) { $scope.setSize = function(set) {
return Object.keys(set).length; return Object.keys(set).length;
} };
/** /**
* Returns true if value "value" is present within set "set". * Returns true if value "value" is present within set "set".
@ -871,7 +894,7 @@ Loader.controller(
*/ */
$scope.isValueInSet = function(value, set) { $scope.isValueInSet = function(value, set) {
return (true == set[value]); return (true == set[value]);
} };
/** /**
* If value "value" is already in set "set", remove it; otherwise, add it. * If value "value" is already in set "set", remove it; otherwise, add it.
@ -885,7 +908,7 @@ Loader.controller(
} else { } else {
set[value] = true; set[value] = true;
} }
} };
/** /**
* For each value in valueArray, call toggleValueInSet(value, set). * For each value in valueArray, call toggleValueInSet(value, set).
@ -898,7 +921,7 @@ Loader.controller(
for (var i = 0; i < arrayLength; i++) { for (var i = 0; i < arrayLength; i++) {
$scope.toggleValueInSet(valueArray[i], set); $scope.toggleValueInSet(valueArray[i], set);
} }
} };
// //
@ -915,7 +938,7 @@ Loader.controller(
*/ */
$scope.isValueInArray = function(value, array) { $scope.isValueInArray = function(value, array) {
return (-1 != array.indexOf(value)); return (-1 != array.indexOf(value));
} };
/** /**
* If value "value" is already in array "array", remove it; otherwise, * If value "value" is already in array "array", remove it; otherwise,
@ -931,7 +954,7 @@ Loader.controller(
} else { } else {
array.splice(i, 1); array.splice(i, 1);
} }
} };
// //
@ -959,7 +982,7 @@ Loader.controller(
slice.push(array[row][column]); slice.push(array[row][column]);
} }
return slice; return slice;
} };
/** /**
* Returns a human-readable (in local time zone) time string for a * Returns a human-readable (in local time zone) time string for a
@ -970,7 +993,7 @@ Loader.controller(
$scope.localTimeString = function(secondsPastEpoch) { $scope.localTimeString = function(secondsPastEpoch) {
var d = new Date(secondsPastEpoch * 1000); var d = new Date(secondsPastEpoch * 1000);
return d.toString(); return d.toString();
} };
/** /**
* Returns a hex color string (such as "#aabbcc") for the given RGB values. * Returns a hex color string (such as "#aabbcc") for the given RGB values.
@ -993,7 +1016,7 @@ Loader.controller(
bString = "0" + bString; bString = "0" + bString;
} }
return '#' + rString + gString + bString; return '#' + rString + gString + bString;
} };
/** /**
* Returns a hex color string (such as "#aabbcc") for the given brightness. * Returns a hex color string (such as "#aabbcc") for the given brightness.
@ -1006,7 +1029,7 @@ Loader.controller(
$scope.brightnessStringToHexColor = function(brightnessString) { $scope.brightnessStringToHexColor = function(brightnessString) {
var v = parseInt(brightnessString); var v = parseInt(brightnessString);
return $scope.hexColorString(v, v, v); return $scope.hexColorString(v, v, v);
} };
/** /**
* Returns the last path component of image diff URL for a given ImagePair. * Returns the last path component of image diff URL for a given ImagePair.
@ -1024,7 +1047,7 @@ Loader.controller(
imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" + imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" +
imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]; imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL];
return before.replace(/[^\w\-]/g, "_") + ".png"; return before.replace(/[^\w\-]/g, "_") + ".png";
} };
} }
); );

Просмотреть файл

@ -88,3 +88,17 @@
padding: 10px; padding: 10px;
border: 2px solid #222; border: 2px solid #222;
} }
.sort-desc {
background:no-repeat left center url(data:image/gif;base64,R0lGODlhCgAKALMAAHFxcYKCgp2dnaampq+vr83NzeHh4f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAAAgAIf/8SUNDUkdCRzEwMTIAAAUwYXBwbAIgAABtbnRyUkdCIFhZWiAH2QACABkACwAaAAthY3NwQVBQTAAAAABhcHBsAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWFwcGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtkc2NtAAABCAAAAvJkZXNjAAAD/AAAAG9nWFlaAAAEbAAAABR3dHB0AAAEgAAAABRyWFlaAAAElAAAABRiWFlaAAAEqAAAABRyVFJDAAAEvAAAAA5jcHJ0AAAEzAAAADhjaGFkAAAFBAAAACxn/1RSQwAABLwAAAAOYlRSQwAABLwAAAAObWx1YwAAAAAAAAARAAAADGVuVVMAAAAmAAACfmVzRVMAAAAmAAABgmRhREsAAAAuAAAB6mRlREUAAAAsAAABqGZpRkkAAAAoAAAA3GZyRlUAAAAoAAABKml0SVQAAAAoAAACVm5sTkwAAAAoAAACGG5iTk8AAAAmAAABBHB0QlIAAAAmAAABgnN2U0UAAAAmAAABBGphSlAAAAAaAAABUmtvS1IAAAAWAAACQHpoVFcAAAAWAAABbHpoQ04AAAAWAAAB1HJ1UlUAAAAiAAACpHBsUEwAAAAsAAACxgBZAGwAZQBpAG4AZf8AbgAgAFIARwBCAC0AcAByAG8AZgBpAGkAbABpAEcAZQBuAGUAcgBpAHMAawAgAFIARwBCAC0AcAByAG8AZgBpAGwAUAByAG8AZgBpAGwAIABHAOkAbgDpAHIAaQBxAHUAZQAgAFIAVgBCTgCCLAAgAFIARwBCACAw1zDtMNUwoTCkMOuQGnUoACAAUgBHAEIAIIJyX2ljz4/wAFAAZQByAGYAaQBsACAAUgBHAEIAIABHAGUAbgDpAHIAaQBjAG8AQQBsAGwAZwBlAG0AZQBpAG4AZQBzACAAUgBHAEIALQBQAHIAbwBmAGkAbGZukBoAIABSAEcAQgAgY8+P8GX/h072AEcAZQBuAGUAcgBlAGwAIABSAEcAQgAtAGIAZQBzAGsAcgBpAHYAZQBsAHMAZQBBAGwAZwBlAG0AZQBlAG4AIABSAEcAQgAtAHAAcgBvAGYAaQBlAGzHfLwYACAAUgBHAEIAINUEuFzTDMd8AFAAcgBvAGYAaQBsAG8AIABSAEcAQgAgAEcAZQBuAGUAcgBpAGMAbwBHAGUAbgBlAHIAaQBjACAAUgBHAEIAIABQAHIAbwBmAGkAbABlBB4EMQRJBDgEOQAgBD8EQAQ+BEQEOAQ7BEwAIABSAEcAQgBVAG4AaQB3AGUAcgBzAGEAbABuAHkAIABwAHIAbwBm/wBpAGwAIABSAEcAQgAAZGVzYwAAAAAAAAAUR2VuZXJpYyBSR0IgUHJvZmlsZQAAAAAAAAAAAAAAFEdlbmVyaWMgUkdCIFByb2ZpbGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABadQAArHMAABc0WFlaIAAAAAAAAPNSAAEAAAABFs9YWVogAAAAAAAAdE0AAD3uAAAD0FhZWiAAAAAAAAAoGgAAFZ8AALg2Y3VydgAAAAAAAAABAc0AAHRleHQAAAAAQ29weXJpZ2h0IDIwMDcgQXBwbGUgSW5jLkMsIGFsbCByaWdodHMgcmVzZXJ2ZWQuAHNmMzIAAAAAAAEMQgAABd7///MmAAAHkgAA/ZH///ui///9owAAA9wAAMBsACwAAAAACgAKAAAEJZAMIcakQZjNtyhFxwEIIRofAookUnapu26t+6KFLYe1TgQ5VwQAOw%3D%3D);
}
.sort-asc {
background:no-repeat left center url(data:image/gif;base64,R0lGODlhCgAKALMAAHFxcYKCgp2dnaampq+vr83NzeHh4f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAAAgAIf/8SUNDUkdCRzEwMTIAAAUwYXBwbAIgAABtbnRyUkdCIFhZWiAH2QACABkACwAaAAthY3NwQVBQTAAAAABhcHBsAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWFwcGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtkc2NtAAABCAAAAvJkZXNjAAAD/AAAAG9nWFlaAAAEbAAAABR3dHB0AAAEgAAAABRyWFlaAAAElAAAABRiWFlaAAAEqAAAABRyVFJDAAAEvAAAAA5jcHJ0AAAEzAAAADhjaGFkAAAFBAAAACxn/1RSQwAABLwAAAAOYlRSQwAABLwAAAAObWx1YwAAAAAAAAARAAAADGVuVVMAAAAmAAACfmVzRVMAAAAmAAABgmRhREsAAAAuAAAB6mRlREUAAAAsAAABqGZpRkkAAAAoAAAA3GZyRlUAAAAoAAABKml0SVQAAAAoAAACVm5sTkwAAAAoAAACGG5iTk8AAAAmAAABBHB0QlIAAAAmAAABgnN2U0UAAAAmAAABBGphSlAAAAAaAAABUmtvS1IAAAAWAAACQHpoVFcAAAAWAAABbHpoQ04AAAAWAAAB1HJ1UlUAAAAiAAACpHBsUEwAAAAsAAACxgBZAGwAZQBpAG4AZf8AbgAgAFIARwBCAC0AcAByAG8AZgBpAGkAbABpAEcAZQBuAGUAcgBpAHMAawAgAFIARwBCAC0AcAByAG8AZgBpAGwAUAByAG8AZgBpAGwAIABHAOkAbgDpAHIAaQBxAHUAZQAgAFIAVgBCTgCCLAAgAFIARwBCACAw1zDtMNUwoTCkMOuQGnUoACAAUgBHAEIAIIJyX2ljz4/wAFAAZQByAGYAaQBsACAAUgBHAEIAIABHAGUAbgDpAHIAaQBjAG8AQQBsAGwAZwBlAG0AZQBpAG4AZQBzACAAUgBHAEIALQBQAHIAbwBmAGkAbGZukBoAIABSAEcAQgAgY8+P8GX/h072AEcAZQBuAGUAcgBlAGwAIABSAEcAQgAtAGIAZQBzAGsAcgBpAHYAZQBsAHMAZQBBAGwAZwBlAG0AZQBlAG4AIABSAEcAQgAtAHAAcgBvAGYAaQBlAGzHfLwYACAAUgBHAEIAINUEuFzTDMd8AFAAcgBvAGYAaQBsAG8AIABSAEcAQgAgAEcAZQBuAGUAcgBpAGMAbwBHAGUAbgBlAHIAaQBjACAAUgBHAEIAIABQAHIAbwBmAGkAbABlBB4EMQRJBDgEOQAgBD8EQAQ+BEQEOAQ7BEwAIABSAEcAQgBVAG4AaQB3AGUAcgBzAGEAbABuAHkAIABwAHIAbwBm/wBpAGwAIABSAEcAQgAAZGVzYwAAAAAAAAAUR2VuZXJpYyBSR0IgUHJvZmlsZQAAAAAAAAAAAAAAFEdlbmVyaWMgUkdCIFByb2ZpbGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABadQAArHMAABc0WFlaIAAAAAAAAPNSAAEAAAABFs9YWVogAAAAAAAAdE0AAD3uAAAD0FhZWiAAAAAAAAAoGgAAFZ8AALg2Y3VydgAAAAAAAAABAc0AAHRleHQAAAAAQ29weXJpZ2h0IDIwMDcgQXBwbGUgSW5jLkMsIGFsbCByaWdodHMgcmVzZXJ2ZWQuAHNmMzIAAAAAAAEMQgAABd7///MmAAAHkgAA/ZH///ui///9owAAA9wAAMBsACwAAAAACgAKAAAEJRBJREKZsxQDsCSGIVzZFnYTGIqktp7fG46uzAn2TAyCMPC9QAQAOw%3D%3D);
}
.sortable-header {
padding-right: 3px;
padding-left: 13px;
margin-left: 4px;
}

Просмотреть файл

@ -5,7 +5,7 @@
<head> <head>
<title ng-bind="windowTitle"></title> <title ng-bind="windowTitle"></title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <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.1.5/angular.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.js"></script>
<script src="constants.js"></script> <script src="constants.js"></script>
<script src="loader.js"></script> <script src="loader.js"></script>
<script src="utils.js"></script> <script src="utils.js"></script>
@ -235,57 +235,58 @@
<table border="0"><tr><td> <!-- table holding results header + results table --> <table border="0"><tr><td> <!-- table holding results header + results table -->
</td></tr><tr><td> </td></tr><tr><td>
<table border="1" ng-app="diff_viewer"> <!-- results --> <table border="1"> <!-- results -->
<tr> <tr>
<!-- Most column headers are displayed in a common fashion... --> <!-- Most column headers are displayed in a common fashion... -->
<th ng-repeat="columnName in orderedColumnNames"> <th ng-repeat="columnName in orderedColumnNames">
<input type="radio" <a ng-class="'sort-' + sortedByColumnsCls(columnName)"
name="sortColumnRadio" ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXTRACOLUMNS, columnName)"
value="{{columnName}}" href=""
ng-checked="(sortColumnKey == columnName)" class="sortable-header">
ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXTRACOLUMNS, columnName)"> {{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}}
{{extraColumnHeaders[columnName][constants.KEY__EXTRACOLUMNHEADERS__HEADER_TEXT]}} </a>
</th> </th>
<!-- ... but there are a few columns where we display things differently. --> <!-- ... but there are a few columns where we display things differently. -->
<th> <th>
<input type="radio" <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__EXPECTATIONS__BUGS)"
name="sortColumnRadio" ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXPECTATIONS, constants.KEY__EXPECTATIONS__BUGS)"
value="bugs" href=""
ng-checked="(sortColumnKey == constants.KEY__EXPECTATIONS__BUGS)" class="sortable-header">
ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__EXPECTATIONS, constants.KEY__EXPECTATIONS__BUGS)"> bugs
bugs </a>
</th> </th>
<th width="{{imageSize}}"> <th width="{{imageSize}}">
<input type="radio" <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"
name="sortColumnRadio" ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"
value="imageA" href=""
ng-checked="(sortColumnKey == constants.KEY__IMAGEPAIRS__IMAGE_A_URL)" class="sortable-header">
ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"> {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}} </a>
</th> </th>
<th width="{{imageSize}}"> <th width="{{imageSize}}">
<input type="radio" <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"
name="sortColumnRadio" ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"
value="imageB" href=""
ng-checked="(sortColumnKey == constants.KEY__IMAGEPAIRS__IMAGE_B_URL)" class="sortable-header">
ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"> {{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}} </a>
</th> </th>
<th width="{{imageSize}}"> <th width="{{imageSize}}">
<input type="radio" <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)"
name="sortColumnRadio" ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)"
value="percentDifferingPixels" href=""
ng-checked="(sortColumnKey == constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)" class="sortable-header">
ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS)"> differing pixels in white
differing pixels in white </a>
</th> </th>
<th width="{{imageSize}}"> <th width="{{imageSize}}">
<input type="radio" <a ng-class="'sort-' + sortedByColumnsCls(constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)"
name="sortColumnRadio" ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)"
value="perceptualDiff" href=""
ng-checked="(sortColumnKey == constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)" class="sortable-header">
ng-click="sortResultsBy(constants.KEY__IMAGEPAIRS__DIFFERENCES, constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF)"> perceptual difference
perceptual difference </a>
<br> <br>
<input type="range" ng-model="pixelDiffBgColorBrightness" <input type="range" ng-model="pixelDiffBgColorBrightness"
ng-init="pixelDiffBgColorBrightness=64; pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)" ng-init="pixelDiffBgColorBrightness=64; pixelDiffBgColor=brightnessStringToHexColor(pixelDiffBgColorBrightness)"