Skip to content

Instantly share code, notes, and snippets.

@mike-north
Created March 27, 2017 17:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mike-north/69331b7c9b621a02bbe296fb91013ddb to your computer and use it in GitHub Desktop.
Save mike-north/69331b7c9b621a02bbe296fb91013ddb to your computer and use it in GitHub Desktop.
EL - Computed - SOLUTION
import Ember from 'ember';
import hexColor from '../utils/hex-color';
const {
Controller,
computed
} = Ember;
export default Controller.extend({
/**
* Our red, green and blue color channels.
* Remember that these are STRINGS,
* because everything is a string
* when it comes from an <input>
*/
r: '100',
g: '200',
b: '255',
/**
* Here we're using a computed property
* macro defined in the utils/hex-color.js
* file, to transform the three decimal
* color channels into a single hex color
* value, and back again into integer values!
*/
hex: hexColor('r', 'g', 'b'),
/**
* Another computed property to calculate
* the style attribute of the sample div
*/
_sampleStyle: computed('hex', function() {
return `background-color: #${this.get('hex')}`;
})
});
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
.color-sample {
height: 60px;
width: 60px;
border: 1px black solid;
padding: 10px;
text-align: center;
}
<h1>An amazing color picker!</h1>
{{!-- RED input --}}
<p>
<b>r:</b>
<input
type='number'
value={{r}}
min='0'
max='255'
onInput={{action (mut r) value='target.value'}} />
</p>
{{!-- GREEN input --}}
<p>
<b>g:</b>
<input
value={{g}}
type='number'
min=0
max=255
onInput={{action (mut g) value='target.value'}} />
</p>
{{!-- BLUE input --}}
<p>
<b>b:</b>
<input
value={{b}}
type='number'
min=0
max=255
onInput={{action (mut b) value='target.value'}} />
</p>
<hr>
{{!-- HEX input --}}
<p>
<b>hex:</b>
<input
value={{hex}}
onInput={{action (mut hex) value='target.value'}} />
</p>
{{!-- Sample square --}}
<div class='color-sample' style={{_sampleStyle}}>Sample</div>
import Resolver from '../../resolver';
import config from '../../config/environment';
const resolver = Resolver.create();
resolver.namespace = {
modulePrefix: config.modulePrefix,
podModulePrefix: config.podModulePrefix
};
export default resolver;
import resolver from './helpers/resolver';
import {
setResolver
} from 'ember-qunit';
setResolver(resolver);
import Ember from 'ember';
import { default as hexColor, rgbToHex, hexToRgb } from 'twiddle/utils/hex-color';
import { module, test } from 'qunit';
module('Computed properties | hex-to-rgb color picker');
function valAsString(x) {
if (arguments.length > 1) {
let args = Array.prototype.slice.call(arguments);
args.splice(0, 1);
return `${x}(${args.map((x) => valAsString(x)).join(', ')})`;
}
switch (typeof x) {
case 'string': return `"${x.toString ? x.toString() : x}"`;
case 'object': return JSON.stringify(x, null, ' ');
default: return `${x.toString ? x.toString() : x}`;
}
}
// Replace this with your real tests.
test('JavaScript module exports the correct things', function(assert) {
assert.ok(hexColor, 'Default export should exist');
assert.ok(rgbToHex, 'Named export rgbToHex should exist');
assert.ok(hexToRgb, 'Named export hexToRgb should exist');
assert.equal(typeof rgbToHex, 'function', 'Named export rgbToHex should be a function');
assert.equal(typeof hexToRgb, 'function', 'Named export hexToRgb should be a function');
assert.equal(typeof hexColor, 'function', 'Default export should be a function');
assert.throws(function() {
hexColor();
}, /computed property key must be a string/, 'Default export should be a function that returns a computed property');
});
test('rgbToHex returns the correct results', function(assert) {
function rgbTest(r, g, b, expected) {
let result = rgbToHex(r, g, b);
if (result.toString && typeof result.toString === 'function') {
result = result.toString();
}
assert.equal(result, expected, `${valAsString('rgbToHex', r, g, b)} should equal ${valAsString(expected)}`);
}
rgbTest(200, 100, 100, 'c86464');
rgbTest(200, 100, '100', 'c86464');
rgbTest('200', '100', '100', 'c86464');
rgbTest(0, 100, 100, '006464');
});
test('hexToRgb returns the correct results', function(assert) {
function hexTest(hex, expected) {
let result = hexToRgb(hex);
assert.deepEqual(result, expected, `${valAsString('hexToRgb', hex)} should equal ${valAsString(expected)}`);
}
let tempResult = hexToRgb('c86464');
assert.equal(typeof tempResult, 'object', 'hexToRgb should return an object');
assert.deepEqual(Object.keys(tempResult), ['r', 'g', 'b'], 'hexToRgb should return object with keys: "r", "g" and "b"');
assert.equal(typeof tempResult.r, 'string', 'hexToRgb should return an object with property "r", whose value is a string');
assert.equal(typeof tempResult.g, 'string', 'hexToRgb should return an object with property "g", whose value is a string');
assert.equal(typeof tempResult.b, 'string', 'hexToRgb should return an object with property "b", whose value is a string');
hexTest('c86464', { r: '200', g: '100', b: '100' });
hexTest('ff0000', { r: '255', g: '0', b: '0' });
});
test('computed property (default export) operates properly', function(assert) {
let MyObj = Ember.Object.extend({
hexx: hexColor('rr', 'gg', 'bb')
});
let obj = MyObj.create({
rr: '0',
gg: '123',
bb: '91'
});
assert.equal(`${obj.get('hexx')}`, '007b5b', 'Computed property calculates the initial value properly');
obj.set('rr', 100);
assert.equal(`${obj.get('hexx')}`, '647b5b', 'Re-calculates properly in response to changes in red channel property');
obj.set('gg', 100);
assert.equal(`${obj.get('hexx')}`, '64645b', 'Re-calculates properly in response to changes in red channel property');
obj.set('bb', 100);
assert.equal(`${obj.get('hexx')}`, '646464', 'Re-calculates properly in response to changes in red channel property');
});
{
"version": "0.12.1",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": true
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.12.0",
"ember-template-compiler": "2.12.0",
"ember-testing": "2.12.0"
},
"addons": {
"ember-data": "2.12.1"
}
}
import Ember from 'ember';
const { computed } = Ember;
/**
* Transform a triplet of r, g, b color values
* (each of which can have a value from 0 - 255),
* into a single hex color string. r, g and b
* may be either strings or integers.
*
* Example: rgbToHex(255, 255, 0) === 'ffff00'
*/
export function rgbToHex(r, g, b) {
return [r, g, b]
.map((c) => parseInt(c, 10).toString(16))
.map((c) => c.length < 2 ? `0${c}` : c)
.join('')
}
/**
* Transform a hex color string into an object
* containing three 8-bit (0 - 255) color values
* (converted to strings) for red, green and blue.
*
* Example: JSON.stringify(hexToRgb('ff0000')) === {r: '255', g: '0', b: '0'}
*/
export function hexToRgb(hex) {
return {
r: parseInt(hex.substring(0, 2), 16).toString(),
g: parseInt(hex.substring(2, 4), 16).toString(),
b: parseInt(hex.substring(4, 6), 16).toString()
};
}
/**
* A settable computed property macro that
* allows us to represent three 8-bit (0 - 255)
* color channels as a single hex color value.
*
* Example:
*
* let ColorPicker = Ember.Object.extend({
* hex: hexColor('red', 'green', 'blue')
* });
*
* let myPicker = ColorPicker.create({
* red: '255',
* green: '0',
* blue: '0'
* });
* myPicker.get('hex') === 'ff0000';
* myPicker.set('green', '255');
* myPicker.get('hex') === 'ffff00';
*
*/
export default function hexColor(rPropName, gPropName, bPropName) {
// This is a temporary value. Replace this with a computed property
return computed(rPropName, gPropName, bPropName, {
get() {
return rgbToHex(this.get(rPropName), this.get(gPropName), this.get(bPropName));
},
set(key, hex) {
let { r, g, b } = hexToRgb(hex);
this.set(rPropName, r);
this.set(gPropName, g);
this.set(bPropName, b);
return hex;
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment