Skip to main content
Code Review

Return to Question

replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link

To illustrate some algorithmic problems I found while writing this code review this code review, I needed to include a live demonstration, which I implemented using a Stack Snippet with Angular.js.

To illustrate some algorithmic problems I found while writing this code review, I needed to include a live demonstration, which I implemented using a Stack Snippet with Angular.js.

To illustrate some algorithmic problems I found while writing this code review, I needed to include a live demonstration, which I implemented using a Stack Snippet with Angular.js.

Tweeted twitter.com/#!/StackCodeReview/status/539892286809976833
Better grammar; clarified purpose; added CSS question
Source Link
200_success
  • 145.5k
  • 22
  • 190
  • 478

WhileTo illustrate some algorithmic problems I found while writing this code review, I found it necessaryneeded to include a live demonstration to illustrate the problems I found, which I implemented using a Stack Snippet with Angular.js.

The demonstration takes a color input and a scalar parameter, and produces two read-only color outputs. The "Original" output is known to behave erratically (which is the point of the demo).

I also think that the CSS is sloppy and not robust to various sizing conditions. Recommendations in that area would also be appreciated.

While writing this code review, I found it necessary to include a live demonstration to illustrate the problems I found, which I implemented using a Stack Snippet with Angular.js.

The demonstration takes a color input and a scalar parameter, and produces two read-only color outputs.

To illustrate some algorithmic problems I found while writing this code review, I needed to include a live demonstration, which I implemented using a Stack Snippet with Angular.js.

The demonstration takes a color input and a scalar parameter, and produces two read-only color outputs. The "Original" output is known to behave erratically (which is the point of the demo).

I also think that the CSS is sloppy and not robust to various sizing conditions. Recommendations in that area would also be appreciated.

Reordered functions to emphasize the focus of the review
Source Link
200_success
  • 145.5k
  • 22
  • 190
  • 478
var ColorTweakerCtrl = function ColorTweakerCtrl($scope) {
 $scope.inColor = new RGBColor(234, 150, 0);
 $scope.diff = 127;
 
 $scope.tweak = function tweak() {
 $scope.inColor.r = Math.round($scope.inColor.r);
 $scope.inColor.g = Math.round($scope.inColor.g);
 $scope.inColor.b = Math.round($scope.inColor.b);
 $scope.diff = Math.round($scope.diff);
 $scope.outColor = tweakColor($scope.inColor, $scope.diff);
 $scope.newColor = newTweakColor($scope.inColor, $scope.diff);
 };
 $scope.tweak();
};
function RGBColor(r, g, b) {
 this.r = r; this.g = g; this.b = b;
}
RGBColor.prototype.toString = function() {
 return 'rgb(' + Math.round(this.r) + ',' + Math.round(this.g) + ',' + Math.round(this.b) + ')';
};
/* Based on formulas from http://www.rapidtables.com/convert/color/rgb-to-hsv.htm */
RGBColor.prototype.toHSV = function toHSV() {
 var r = this.r / 255,
 g = this.g / 255,
 b = this.b / 255;
 var cMax = Math.max(r, g, b),
 cMin = Math.min(r, g, b);
 var Δ = cMax - cMin;
 var hue = 60 * ( (cMax == r) ? ((g - b) / Δ) % 6
 : (cMax == g) ? ((b - r) / Δ) + 2
 : ((r - g) / Δ) + 4 );
 var sat = cMax == 0 ? 0 : Δ / cMax;
 var val = cMax;
 return new HSVColor((hue + 360) % 360, sat, val);
}
function HSVColor(h, s, v) {
 this.h = h; this.s = s; this.v = v;
}
HSVColor.prototype.toString = function() {
 return 'hsl(' + Math.round(this.h) + ',' + Math.round(100 * this.s) + '%,' + Math.round(100 * this.v) + '%)';
};
/* http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV */
HSVColor.prototype.toRGB = function toRGB() {
 var c = this.v * this.s;
 var h = this.h / 60;
 var x = c * (1 - Math.abs(h % 2 - 1));
 var r1 = (h < 1 || h >= 5) ? c
 : (h < 2 || h >= 4) ? x : 0;
 var g1 = (h >= 1 && h < 3) ? c
 : (h >= 0 && h < 4) ? x : 0;
 var b1 = (h >= 3 && h < 5) ? c
 : (h >= 2 && h < 6) ? x : 0;
 var m = this.v - c;
 return new RGBColor(Math.round(255 * (r1 + m)),
 Math.round(255 * (g1 + m)),
 Math.round(255 * (b1 + m)));
};
var ColorTweakerCtrl = function ColorTweakerCtrl($scope) {
 $scope.inColor = new RGBColor(234, 150, 0);
 $scope.diff = 127;
 
 $scope.tweak = function tweak() {
 $scope.inColor.r = Math.round($scope.inColor.r);
 $scope.inColor.g = Math.round($scope.inColor.g);
 $scope.inColor.b = Math.round($scope.inColor.b);
 $scope.diff = Math.round($scope.diff);
 $scope.outColor = tweakColor($scope.inColor, $scope.diff);
 $scope.newColor = newTweakColor($scope.inColor, $scope.diff);
 };
 $scope.tweak();
};
function tweakColor(aColor, aDiff) {
 function intRange(value, min, max) {
 return value < min ? min
 : value > max ? max
 : value;
 }
 var r = aColor.r,
 g = aColor.g,
 b = aColor.b;
 var d = (r + g + b) / 3;
 var dir = (d >= (256 / 2)) ? -aDiff : aDiff;
 r = intRange(r + dir, 0, 255);
 g = intRange(g + dir, 0, 255);
 b = intRange(b + dir, 0, 255);
 return new RGBColor(r, g, b);
}
function newTweakColor(aColor, aDiff) {
 var hsv = aColor.toHSV();
 var vAdj = (aDiff / 128) * (hsv.v - 0.5);
 return (new HSVColor(hsv.h, hsv.s, hsv.v - vAdj)).toRGB();
}
fieldset {
 display: inline-block;
 width: 25%;
}
fieldset#tweak {
 display: block;
 width: 100%;
 border-width: 0;
}
label {
 display: block;
}
.swatch {
 border: 1px solid grey;
 width: 100%;
 height: 1em;
}
input[type=range] {
 width: 40%;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
 <form ng-controller="ColorTweakerCtrl">
 <fieldset id="tweak">
 <label>Diff
 <input ng-model="diff" type="range" min="0" max="255" ng-change="tweak()">
 <input ng-model="diff" type="number" min="0" max="255" ng-change="tweak()">
 </label>
 </fieldset>
 
 <fieldset>
 <legend>Input Color</legend>
 <div class="swatch" style="background-color: {{ inColor.toString() }}"></div>
 <label>R
 <input ng-model="inColor.r" type="range" min="0" max="255" ng-change="tweak()">
 <input ng-model="inColor.r" type="number" min="0" max="255" ng-change="tweak()">
 </label>
 <label>G
 <input ng-model="inColor.g" type="range" min="0" max="255" ng-change="tweak()">
 <input ng-model="inColor.g" type="number" min="0" max="255" ng-change="tweak()">
 </label>
 <label>B
 <input ng-model="inColor.b" type="range" min="0" max="255" ng-change="tweak()">
 <input ng-model="inColor.b" type="number" min="0" max="255" ng-change="tweak()">
 </label>
 </fieldset>
 <fieldset>
 <legend>Output (Original)</legend>
 <div class="swatch" style="background-color: {{ outColor.toString() }}"></div>
 <label>R
 <input ng-model="outColor.r" type="range" min="0" max="255" disabled>
 <input ng-model="outColor.r" type="number" min="0" max="255" disabled>
 </label>
 <label>G
 <input ng-model="outColor.g" type="range" min="0" max="255" disabled>
 <input ng-model="outColor.g" type="number" min="0" max="255" disabled>
 </label>
 <label>B
 <input ng-model="outColor.b" type="range" min="0" max="255" disabled>
 <input ng-model="outColor.b" type="number" min="0" max="255" disabled>
 </label>
 </fieldset>
 <fieldset>
 <legend>Output (Suggested)</legend>
 <div class="swatch" style="background-color: {{ newColor.toString() }}"></div>
 <label>R
 <input ng-model="newColor.r" type="range" min="0" max="255" disabled>
 <input ng-model="newColor.r" type="number" min="0" max="255" disabled>
 </label>
 <label>G
 <input ng-model="newColor.g" type="range" min="0" max="255" disabled>
 <input ng-model="newColor.g" type="number" min="0" max="255" disabled>
 </label>
 <label>B
 <input ng-model="newColor.b" type="range" min="0" max="255" disabled>
 <input ng-model="newColor.b" type="number" min="0" max="255" disabled>
 </label>
 </fieldset>
 </form>
</div>
function RGBColor(r, g, b) {
 this.r = r; this.g = g; this.b = b;
}
RGBColor.prototype.toString = function() {
 return 'rgb(' + Math.round(this.r) + ',' + Math.round(this.g) + ',' + Math.round(this.b) + ')';
};
/* Based on formulas from http://www.rapidtables.com/convert/color/rgb-to-hsv.htm */
RGBColor.prototype.toHSV = function toHSV() {
 var r = this.r / 255,
 g = this.g / 255,
 b = this.b / 255;
 var cMax = Math.max(r, g, b),
 cMin = Math.min(r, g, b);
 var Δ = cMax - cMin;
 var hue = 60 * ( (cMax == r) ? ((g - b) / Δ) % 6
 : (cMax == g) ? ((b - r) / Δ) + 2
 : ((r - g) / Δ) + 4 );
 var sat = cMax == 0 ? 0 : Δ / cMax;
 var val = cMax;
 return new HSVColor((hue + 360) % 360, sat, val);
}
function HSVColor(h, s, v) {
 this.h = h; this.s = s; this.v = v;
}
HSVColor.prototype.toString = function() {
 return 'hsl(' + Math.round(this.h) + ',' + Math.round(100 * this.s) + '%,' + Math.round(100 * this.v) + '%)';
};
/* http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV */
HSVColor.prototype.toRGB = function toRGB() {
 var c = this.v * this.s;
 var h = this.h / 60;
 var x = c * (1 - Math.abs(h % 2 - 1));
 var r1 = (h < 1 || h >= 5) ? c
 : (h < 2 || h >= 4) ? x : 0;
 var g1 = (h >= 1 && h < 3) ? c
 : (h >= 0 && h < 4) ? x : 0;
 var b1 = (h >= 3 && h < 5) ? c
 : (h >= 2 && h < 6) ? x : 0;
 var m = this.v - c;
 return new RGBColor(Math.round(255 * (r1 + m)),
 Math.round(255 * (g1 + m)),
 Math.round(255 * (b1 + m)));
};
var ColorTweakerCtrl = function ColorTweakerCtrl($scope) {
 $scope.inColor = new RGBColor(234, 150, 0);
 $scope.diff = 127;
 
 $scope.tweak = function tweak() {
 $scope.inColor.r = Math.round($scope.inColor.r);
 $scope.inColor.g = Math.round($scope.inColor.g);
 $scope.inColor.b = Math.round($scope.inColor.b);
 $scope.diff = Math.round($scope.diff);
 $scope.outColor = tweakColor($scope.inColor, $scope.diff);
 $scope.newColor = newTweakColor($scope.inColor, $scope.diff);
 };
 $scope.tweak();
};
function tweakColor(aColor, aDiff) {
 function intRange(value, min, max) {
 return value < min ? min
 : value > max ? max
 : value;
 }
 var r = aColor.r,
 g = aColor.g,
 b = aColor.b;
 var d = (r + g + b) / 3;
 var dir = (d >= (256 / 2)) ? -aDiff : aDiff;
 r = intRange(r + dir, 0, 255);
 g = intRange(g + dir, 0, 255);
 b = intRange(b + dir, 0, 255);
 return new RGBColor(r, g, b);
}
function newTweakColor(aColor, aDiff) {
 var hsv = aColor.toHSV();
 var vAdj = (aDiff / 128) * (hsv.v - 0.5);
 return (new HSVColor(hsv.h, hsv.s, hsv.v - vAdj)).toRGB();
}
fieldset {
 display: inline-block;
 width: 25%;
}
fieldset#tweak {
 display: block;
 width: 100%;
 border-width: 0;
}
label {
 display: block;
}
.swatch {
 border: 1px solid grey;
 width: 100%;
 height: 1em;
}
input[type=range] {
 width: 40%;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
 <form ng-controller="ColorTweakerCtrl">
 <fieldset id="tweak">
 <label>Diff
 <input ng-model="diff" type="range" min="0" max="255" ng-change="tweak()">
 <input ng-model="diff" type="number" min="0" max="255" ng-change="tweak()">
 </label>
 </fieldset>
 
 <fieldset>
 <legend>Input Color</legend>
 <div class="swatch" style="background-color: {{ inColor.toString() }}"></div>
 <label>R
 <input ng-model="inColor.r" type="range" min="0" max="255" ng-change="tweak()">
 <input ng-model="inColor.r" type="number" min="0" max="255" ng-change="tweak()">
 </label>
 <label>G
 <input ng-model="inColor.g" type="range" min="0" max="255" ng-change="tweak()">
 <input ng-model="inColor.g" type="number" min="0" max="255" ng-change="tweak()">
 </label>
 <label>B
 <input ng-model="inColor.b" type="range" min="0" max="255" ng-change="tweak()">
 <input ng-model="inColor.b" type="number" min="0" max="255" ng-change="tweak()">
 </label>
 </fieldset>
 <fieldset>
 <legend>Output (Original)</legend>
 <div class="swatch" style="background-color: {{ outColor.toString() }}"></div>
 <label>R
 <input ng-model="outColor.r" type="range" min="0" max="255" disabled>
 <input ng-model="outColor.r" type="number" min="0" max="255" disabled>
 </label>
 <label>G
 <input ng-model="outColor.g" type="range" min="0" max="255" disabled>
 <input ng-model="outColor.g" type="number" min="0" max="255" disabled>
 </label>
 <label>B
 <input ng-model="outColor.b" type="range" min="0" max="255" disabled>
 <input ng-model="outColor.b" type="number" min="0" max="255" disabled>
 </label>
 </fieldset>
 <fieldset>
 <legend>Output (Suggested)</legend>
 <div class="swatch" style="background-color: {{ newColor.toString() }}"></div>
 <label>R
 <input ng-model="newColor.r" type="range" min="0" max="255" disabled>
 <input ng-model="newColor.r" type="number" min="0" max="255" disabled>
 </label>
 <label>G
 <input ng-model="newColor.g" type="range" min="0" max="255" disabled>
 <input ng-model="newColor.g" type="number" min="0" max="255" disabled>
 </label>
 <label>B
 <input ng-model="newColor.b" type="range" min="0" max="255" disabled>
 <input ng-model="newColor.b" type="number" min="0" max="255" disabled>
 </label>
 </fieldset>
 </form>
</div>
var ColorTweakerCtrl = function ColorTweakerCtrl($scope) {
 $scope.inColor = new RGBColor(234, 150, 0);
 $scope.diff = 127;
 
 $scope.tweak = function tweak() {
 $scope.inColor.r = Math.round($scope.inColor.r);
 $scope.inColor.g = Math.round($scope.inColor.g);
 $scope.inColor.b = Math.round($scope.inColor.b);
 $scope.diff = Math.round($scope.diff);
 $scope.outColor = tweakColor($scope.inColor, $scope.diff);
 $scope.newColor = newTweakColor($scope.inColor, $scope.diff);
 };
 $scope.tweak();
};
function RGBColor(r, g, b) {
 this.r = r; this.g = g; this.b = b;
}
RGBColor.prototype.toString = function() {
 return 'rgb(' + Math.round(this.r) + ',' + Math.round(this.g) + ',' + Math.round(this.b) + ')';
};
/* Based on formulas from http://www.rapidtables.com/convert/color/rgb-to-hsv.htm */
RGBColor.prototype.toHSV = function toHSV() {
 var r = this.r / 255,
 g = this.g / 255,
 b = this.b / 255;
 var cMax = Math.max(r, g, b),
 cMin = Math.min(r, g, b);
 var Δ = cMax - cMin;
 var hue = 60 * ( (cMax == r) ? ((g - b) / Δ) % 6
 : (cMax == g) ? ((b - r) / Δ) + 2
 : ((r - g) / Δ) + 4 );
 var sat = cMax == 0 ? 0 : Δ / cMax;
 var val = cMax;
 return new HSVColor((hue + 360) % 360, sat, val);
}
function HSVColor(h, s, v) {
 this.h = h; this.s = s; this.v = v;
}
HSVColor.prototype.toString = function() {
 return 'hsl(' + Math.round(this.h) + ',' + Math.round(100 * this.s) + '%,' + Math.round(100 * this.v) + '%)';
};
/* http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV */
HSVColor.prototype.toRGB = function toRGB() {
 var c = this.v * this.s;
 var h = this.h / 60;
 var x = c * (1 - Math.abs(h % 2 - 1));
 var r1 = (h < 1 || h >= 5) ? c
 : (h < 2 || h >= 4) ? x : 0;
 var g1 = (h >= 1 && h < 3) ? c
 : (h >= 0 && h < 4) ? x : 0;
 var b1 = (h >= 3 && h < 5) ? c
 : (h >= 2 && h < 6) ? x : 0;
 var m = this.v - c;
 return new RGBColor(Math.round(255 * (r1 + m)),
 Math.round(255 * (g1 + m)),
 Math.round(255 * (b1 + m)));
};
function tweakColor(aColor, aDiff) {
 function intRange(value, min, max) {
 return value < min ? min
 : value > max ? max
 : value;
 }
 var r = aColor.r,
 g = aColor.g,
 b = aColor.b;
 var d = (r + g + b) / 3;
 var dir = (d >= (256 / 2)) ? -aDiff : aDiff;
 r = intRange(r + dir, 0, 255);
 g = intRange(g + dir, 0, 255);
 b = intRange(b + dir, 0, 255);
 return new RGBColor(r, g, b);
}
function newTweakColor(aColor, aDiff) {
 var hsv = aColor.toHSV();
 var vAdj = (aDiff / 128) * (hsv.v - 0.5);
 return (new HSVColor(hsv.h, hsv.s, hsv.v - vAdj)).toRGB();
}
fieldset {
 display: inline-block;
 width: 25%;
}
fieldset#tweak {
 display: block;
 width: 100%;
 border-width: 0;
}
label {
 display: block;
}
.swatch {
 border: 1px solid grey;
 width: 100%;
 height: 1em;
}
input[type=range] {
 width: 40%;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
 <form ng-controller="ColorTweakerCtrl">
 <fieldset id="tweak">
 <label>Diff
 <input ng-model="diff" type="range" min="0" max="255" ng-change="tweak()">
 <input ng-model="diff" type="number" min="0" max="255" ng-change="tweak()">
 </label>
 </fieldset>
 
 <fieldset>
 <legend>Input Color</legend>
 <div class="swatch" style="background-color: {{ inColor.toString() }}"></div>
 <label>R
 <input ng-model="inColor.r" type="range" min="0" max="255" ng-change="tweak()">
 <input ng-model="inColor.r" type="number" min="0" max="255" ng-change="tweak()">
 </label>
 <label>G
 <input ng-model="inColor.g" type="range" min="0" max="255" ng-change="tweak()">
 <input ng-model="inColor.g" type="number" min="0" max="255" ng-change="tweak()">
 </label>
 <label>B
 <input ng-model="inColor.b" type="range" min="0" max="255" ng-change="tweak()">
 <input ng-model="inColor.b" type="number" min="0" max="255" ng-change="tweak()">
 </label>
 </fieldset>
 <fieldset>
 <legend>Output (Original)</legend>
 <div class="swatch" style="background-color: {{ outColor.toString() }}"></div>
 <label>R
 <input ng-model="outColor.r" type="range" min="0" max="255" disabled>
 <input ng-model="outColor.r" type="number" min="0" max="255" disabled>
 </label>
 <label>G
 <input ng-model="outColor.g" type="range" min="0" max="255" disabled>
 <input ng-model="outColor.g" type="number" min="0" max="255" disabled>
 </label>
 <label>B
 <input ng-model="outColor.b" type="range" min="0" max="255" disabled>
 <input ng-model="outColor.b" type="number" min="0" max="255" disabled>
 </label>
 </fieldset>
 <fieldset>
 <legend>Output (Suggested)</legend>
 <div class="swatch" style="background-color: {{ newColor.toString() }}"></div>
 <label>R
 <input ng-model="newColor.r" type="range" min="0" max="255" disabled>
 <input ng-model="newColor.r" type="number" min="0" max="255" disabled>
 </label>
 <label>G
 <input ng-model="newColor.g" type="range" min="0" max="255" disabled>
 <input ng-model="newColor.g" type="number" min="0" max="255" disabled>
 </label>
 <label>B
 <input ng-model="newColor.b" type="range" min="0" max="255" disabled>
 <input ng-model="newColor.b" type="number" min="0" max="255" disabled>
 </label>
 </fieldset>
 </form>
</div>
Source Link
200_success
  • 145.5k
  • 22
  • 190
  • 478
Loading
default

AltStyle によって変換されたページ (->オリジナル) /