Skip to content

Instantly share code, notes, and snippets.

@lstrrs
Forked from mike-north/controllers.application.js
Last active August 9, 2017 21:23
Show Gist options
  • Save lstrrs/5f269cf49f0fe62c7b08f7335558032d to your computer and use it in GitHub Desktop.
Save lstrrs/5f269cf49f0fe62c7b08f7335558032d to your computer and use it in GitHub Desktop.
EL - Computed
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')}`.htmlSafe();
})
});
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 Ember from 'ember';
export default function destroyApp(application) {
Ember.run(application, 'destroy');
}
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 Ember from 'ember';
import Application from '../../app';
import config from '../../config/environment';
const { run } = Ember;
const assign = Ember.assign || Ember.merge;
export default function startApp(attrs) {
let application;
let attributes = assign({rootElement: "#test-root"}, config.APP);
attributes = assign(attributes, attrs); // use defaults, but you can override;
run(() => {
application = Application.create(attributes);
application.setupForTesting();
application.injectTestHelpers();
});
return application;
}
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": false
},
"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';
function formatHexString(hexString) {
return hexString.length === 1 ? `0${hexString}` : hexString;
}
/**
* 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((val) => Number(val).toString(16))
.map((hex) => hex.length === 1 ? `0${hex}` : hex)
.join('');
*/
const redHex = formatHexString(Number(r).toString(16));
const greenHex = formatHexString(Number(g).toString(16));
const blueHex = formatHexString(Number(b).toString(16));
return `${redHex}${greenHex}${blueHex}`;
}
/**
* 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) {
/*
const [r, g, b] = [0, 2, 4]
.map((offset) => hex.substring(offset, offset + 2))
.map((hexCh) => parseInt(hexCh, 16).toString());
return { r, g, b };
*/
const defaultRGB = {
r: '0',
b: '0',
g: '0'
};
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: `${parseInt(result[1], 16)}`,
g: `${parseInt(result[2], 16)}`,
b: `${parseInt(result[3], 16)}`
} : defaultRGB;
}
/**
* 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 Ember.computed(rPropName, gPropName, bPropName, {
get() {
return rgbToHex(this.get(rPropName),this.get(gPropName), this.get(bPropName));
},
set(key, newVal) {
let rgbValues = hexToRgb(newVal);
this.set(rPropName, rgbValues.r);
this.set(gPropName, rgbValues.g);
this.set(bPropName, rgbValues.b);
return newVal;
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment