From 5ad2834cc8b03e547e49125234abfe1eed5a11fe Mon Sep 17 00:00:00 2001 From: Keegan Date: Fri, 12 Feb 2016 16:38:06 -0800 Subject: [PATCH] add sunlight colors to color picker and tests --- .eslintrc | 6 +- dev/config.js | 12 +++- dev/dev.js | 1 + gulpfile.js | 2 +- src/scripts/components/color.js | 123 +++++++++++++++++++++++++++----- src/scripts/config-page.js | 3 + src/scripts/lib/manipulators.js | 16 +++++ test/spec/components/color.js | 108 ++++++++++++++++++++++++++++ test/spec/lib/manipulators.js | 23 +++++- 9 files changed, 267 insertions(+), 27 deletions(-) create mode 100644 test/spec/components/color.js diff --git a/.eslintrc b/.eslintrc index 35fc665..fa3171c 100755 --- a/.eslintrc +++ b/.eslintrc @@ -1,15 +1,15 @@ { "extends": "pebble", - "env" : { + "env": { "node": true, "browser": true }, "globals": { "Pebble": true }, - "rules" : { + "rules": { "new-cap": [0], - "max-params": [1], + "max-params": [2, 4], "require-jsdoc": [2, { "require": { "FunctionDeclaration": true, diff --git a/dev/config.js b/dev/config.js index bb272e7..02e1bb5 100644 --- a/dev/config.js +++ b/dev/config.js @@ -41,8 +41,16 @@ module.exports = [ { "type": "color", "appKey": "background", - "value": "0xFF0000", - "label": "Background Color" + "value": "FF0000", + "label": "Background Color", + "sunlight": false + }, + { + "type": "color", + "appKey": "background", + "value": "00FF00", + "label": "Sunny Color", + "sunlight": true } ] }, diff --git a/dev/dev.js b/dev/dev.js index 19bc3ea..83bf9c3 100644 --- a/dev/dev.js +++ b/dev/dev.js @@ -4,6 +4,7 @@ window.returnTo = '$$RETURN_TO$$'; window.clayConfig = require('./config.js'); window.claySettings = {}; window.customFn = require('./custom-fn.js'); +window.clayComponents = require('../src/scripts/components'); var platform = window.navigator.userAgent.match(/Android/) ? 'android' : 'ios'; document.documentElement.classList.add('platform-' + platform); diff --git a/gulpfile.js b/gulpfile.js index 0403284..4441081 100755 --- a/gulpfile.js +++ b/gulpfile.js @@ -104,5 +104,5 @@ gulp.task('default', ['clay']); gulp.task('dev', ['dev-js'], function() { gulp.watch('src/styles/**/*.scss', ['sass']); gulp.watch(['src/scripts/**/*.js', 'src/templates/**/*.tpl'], ['js']); - gulp.watch(['dev/**/*.js'], ['dev-js']); + gulp.watch(['src/scripts/**/*.js', 'dev/**/*.js'], ['dev-js']); }); diff --git a/src/scripts/components/color.js b/src/scripts/components/color.js index dabc272..d12932c 100644 --- a/src/scripts/components/color.js +++ b/src/scripts/components/color.js @@ -4,26 +4,109 @@ module.exports = { name: 'color', template: require('../../templates/components/color.tpl'), style: require('../../styles/clay/components/color.scss'), - manipulator: 'val', + manipulator: 'color', defaults: { label: '' }, initialize: function(minified) { var HTML = minified.HTML; var self = this; + var useSunlight = self.config.sunlight !== false; + var sunlightColorMap = { + '000000': '000000', + '000055': '001e41', + '0000aa': '004387', + '0000ff': '0068ca', + '005500': '2b4a2c', + '005555': '27514f', + '0055aa': '16638d', + '0055ff': '007dce', + '00aa00': '5e9860', + '00aa55': '5c9b72', + '00aaaa': '57a5a2', + '00aaff': '4cb4db', + '00ff00': '8ee391', + '00ff55': '8ee69e', + '00ffaa': '8aebc0', + '00ffff': '84f5f1', + '550000': '4a161b', + '550055': '482748', + '5500aa': '40488a', + '5500ff': '2f6bcc', + '555500': '564e36', + '555555': '545454', + '5555aa': '4f6790', + '5555ff': '4180d0', + '55aa00': '759a64', + '55aa55': '759d76', + '55aaaa': '71a6a4', + '55aaff': '69b5dd', + '55ff00': '9ee594', + '55ff55': '9de7a0', + '55ffaa': '9becc2', + '55ffff': '95f6f2', + 'aa0000': '99353f', + 'aa0055': '983e5a', + 'aa00aa': '955694', + 'aa00ff': '8f74d2', + 'aa5500': '9d5b4d', + 'aa5555': '9d6064', + 'aa55aa': '9a7099', + 'aa55ff': '9587d5', + 'aaaa00': 'afa072', + 'aaaa55': 'aea382', + 'aaaaaa': 'ababab', + 'ffffff': 'ffffff', + 'aaaaff': 'a7bae2', + 'aaff00': 'c9e89d', + 'aaff55': 'c9eaa7', + 'aaffaa': 'c7f0c8', + 'aaffff': 'c3f9f7', + 'ff0000': 'e35462', + 'ff0055': 'e25874', + 'ff00aa': 'e16aa3', + 'ff00ff': 'de83dc', + 'ff5500': 'e66e6b', + 'ff5555': 'e6727c', + 'ff55aa': 'e37fa7', + 'ff55ff': 'e194df', + 'ffaa00': 'f1aa86', + 'ffaa55': 'f1ad93', + 'ffaaaa': 'efb5b8', + 'ffaaff': 'ecc3eb', + 'ffff00': 'ffeeab', + 'ffff55': 'fff1b5', + 'ffffaa': 'fff6d3' + }; + + /** + * @param {string|boolean|number} color + * @returns {string} + */ + function cssColor(color) { + if (color === false) { return 'transparent'; } + if (typeof color === 'number') { + color = color.toString(16); + } + while (color.length < 6) { + color = '0' + color; + } + + return '#' + (useSunlight ? sunlightColorMap[color] : color); + } /* eslint-disable comma-spacing, no-multi-spaces, max-len, standard/array-bracket-even-spacing */ var layout = self.config.layout || [ - [false , false , '#55FF00', '#AAFF55', false , '#FFFF55', '#FFFFAA', false , false ], - [false , '#AAFFAA', '#55FF55', '#00FF00', '#AAFF00', '#FFFF00', '#FFAA55', '#FFAAAA', false ], - ['#55FFAA', '#00FF55', '#00AA00', '#55AA00', '#AAAA55', '#AAAA00', '#FFAA00', '#FF5500', '#FF5555'], - ['#AAFFFF', '#00FFAA', '#00AA55', '#55AA55', '#005500', '#555500', '#AA5500', '#FF0000', '#FF0055'], - [false , '#55AAAA', '#00AAAA', '#005555', '#FFFFFF', '#000000', '#AA5555', '#AA0000', false ], - ['#55FFFF', '#00FFFF', '#00AAFF', '#0055AA', '#AAAAAA', '#555555', '#550000', '#AA0055', '#FF55AA'], - ['#55AAFF', '#0055FF', '#0000FF', '#0000AA', '#000055', '#550055', '#AA00AA', '#FF00AA', '#FFAAFF'], - [false , '#5555AA', '#5555FF', '#5500FF', '#5500AA', '#AA00FF', '#FF00FF', '#FF55FF', false ], - [false , false , false , '#AAAAFF', '#AA55FF', '#AA55AA', false , false , false ] + [false , false , '55ff00', 'aaff55', false , 'ffff55', 'ffffaa', false , false ], + [false , 'aaffaa', '55ff55', '00ff00', 'aaff00', 'ffff00', 'ffaa55', 'ffaaaa', false ], + ['55ffaa', '00ff55', '00aa00', '55aa00', 'aaaa55', 'aaaa00', 'ffaa00', 'ff5500', 'ff5555'], + ['aaffff', '00ffaa', '00aa55', '55aa55', '005500', '555500', 'aa5500', 'ff0000', 'ff0055'], + [false , '55aaaa', '00aaaa', '005555', 'ffffff', '000000', 'aa5555', 'aa0000', false ], + ['55ffff', '00ffff', '00aaff', '0055aa', 'aaaaaa', '555555', '550000', 'aa0055', 'ff55aa'], + ['55aaff', '0055ff', '0000ff', '0000aa', '000055', '550055', 'aa00aa', 'ff00aa', 'ffaaff'], + [false , '5555aa', '5555ff', '5500ff', '5500aa', 'aa00ff', 'ff00ff', 'ff55ff', false ], + [false , false , false , 'aaaaff', 'aa55ff', 'aa55aa', false , false , false ] ]; /* eslint-enable */ @@ -35,8 +118,8 @@ module.exports = { for (var i = 0; i < layout.length; i++) { for (var j = 0; j < layout[i].length; j++) { - var color = layout[i][j] || 'transparent'; - var selectable = (color !== 'transparent' ? ' selectable' : ''); + var color = layout[i][j]; + var selectable = (color ? ' selectable' : ''); var roundedTL = (i === 0 && j === 0) || i === 0 && !layout[i][j - 1] || !layout[i][j - 1] && !layout[i - 1][j] ? @@ -62,11 +145,11 @@ module.exports = { grid += '' + + 'background:' + cssColor(color) + ';">' + ''; } } @@ -84,14 +167,18 @@ module.exports = { }); self.on('change', function() { - var value = self.get().replace(/^0x/, '').toLowerCase(); - $valueDisplay.set('$background-color', '#' + value); + var value = self.get(); + $valueDisplay.set('$background-color', cssColor(value)); $elem.select('.color-box').set('-selected'); - $elem.select('.color-box[data-value="0x' + value + '"]').set('+selected'); + $elem.select('.color-box[data-value="' + value + '"]').set('+selected'); }); $elem.select('.color-box.selectable').on('click', function(ev) { - self.set(ev.target.dataset.value); + self.set(parseInt(ev.target.dataset.value, 10)); + $picker.set('-show'); + }); + + $picker.on('click', function() { $picker.set('-show'); }); diff --git a/src/scripts/config-page.js b/src/scripts/config-page.js index edbfdd5..82011da 100755 --- a/src/scripts/config-page.js +++ b/src/scripts/config-page.js @@ -12,6 +12,9 @@ var returnTo = window.returnTo || 'pebblejs://close#'; var customFn = window.customFn || function() {}; var clayComponents = window.clayComponents || {}; +var platform = window.navigator.userAgent.match(/Android/) ? 'android' : 'ios'; +document.documentElement.classList.add('platform-' + platform); + // Register the passed components _.eachObj(clayComponents, function(key, component) { ClayConfig.registerComponent(component); diff --git a/src/scripts/lib/manipulators.js b/src/scripts/lib/manipulators.js index 15738fa..17c366f 100755 --- a/src/scripts/lib/manipulators.js +++ b/src/scripts/lib/manipulators.js @@ -47,5 +47,21 @@ module.exports = { }, disable: disable, enable: enable + }, + color: { + get: function() { + return parseInt(this.$manipulatorTarget.get('value'), 16); + }, + set: function(value) { + switch (typeof value) { + case 'number': value = value.toString(16); break; + case 'string': value = value.replace(/^#|^0x/, ''); break; + } + + this.$manipulatorTarget.set('value', value || '000000'); + return this.trigger('change'); + }, + disable: disable, + enable: enable } }; diff --git a/test/spec/components/color.js b/test/spec/components/color.js new file mode 100644 index 0000000..2557d0e --- /dev/null +++ b/test/spec/components/color.js @@ -0,0 +1,108 @@ +'use strict'; + +var assert = require('chai').assert; +var fixture = require('../../fixture'); + +/** + * @param {ClayItem} colorItem + * @returns {void} + */ +function openPicker(colorItem) { + colorItem.$element.select('label')[0].click(); +} + +describe('component - color', function() { + it('shows the sunlit colors in the value display', function() { + var clayConfig = fixture.clayConfig([ + { + type: 'color', + sunlight: true, + id: '1', + value: 'ff0000' + } + ]); + var colorItem = clayConfig.getItemById('1'); + + assert.strictEqual(colorItem.get(), 0xff0000); + assert.strictEqual( + colorItem.$element.select('.value')[0].style.backgroundColor, + 'rgb(227, 84, 98)' + ); + colorItem.set('0000FF'); + assert.strictEqual( + colorItem.$element.select('.value')[0].style.backgroundColor, + 'rgb(0, 104, 202)' + ); + }); + + it('shows the normal colors in the value display', function() { + var clayConfig = fixture.clayConfig([ + { + type: 'color', + sunlight: false, + id: '1', + value: 'ff0000' + } + ]); + var colorItem = clayConfig.getItemById('1'); + + assert.strictEqual(colorItem.get(), 0xff0000); + assert.strictEqual( + colorItem.$element.select('.value')[0].style.backgroundColor, + 'rgb(255, 0, 0)' + ); + colorItem.set('0000FF'); + assert.strictEqual( + colorItem.$element.select('.value')[0].style.backgroundColor, + 'rgb(0, 0, 255)' + ); + }); + + it('shows the picker when the label is clicked', function() { + var clayConfig = fixture.clayConfig(['color']); + var colorItem = clayConfig.getItemsByType('color')[0]; + var $picker = colorItem.$element.select('.picker-wrap'); + assert.strictEqual($picker.get('classList').contains('show'), false); + openPicker(colorItem); + assert.strictEqual($picker.get('classList').contains('show'), true); + }); + + it('only shows the picker if the item is enabled', function() { + var clayConfig = fixture.clayConfig(['color']); + var colorItem = clayConfig.getItemsByType('color')[0]; + var $picker = colorItem.$element.select('.picker-wrap'); + colorItem.disable(); + assert.strictEqual($picker.get('classList').contains('show'), false); + openPicker(colorItem); + assert.strictEqual($picker.get('classList').contains('show'), false); + colorItem.enable(); + openPicker(colorItem); + assert.strictEqual($picker.get('classList').contains('show'), true); + }); + + it('sets the value and closes picker when the user makes a selection', function() { + var clayConfig = fixture.clayConfig([{type: 'color', sunlight: false}]); + var colorItem = clayConfig.getItemsByType('color')[0]; + var $picker = colorItem.$element.select('.picker-wrap'); + assert.strictEqual(colorItem.get(), 0x000000); + openPicker(colorItem); + colorItem.$element.select('[data-value="16711680"]')[0].click(); + assert.strictEqual(colorItem.get(), 0xff0000); + assert.strictEqual( + colorItem.$element.select('.value')[0].style.backgroundColor, + 'rgb(255, 0, 0)' + ); + assert.strictEqual($picker.get('classList').contains('show'), false); + }); + + it('closes the picker if a user clicks the background', function() { + var clayConfig = fixture.clayConfig([{type: 'color', sunlight: false}]); + var colorItem = clayConfig.getItemsByType('color')[0]; + var $picker = colorItem.$element.select('.picker-wrap'); + assert.strictEqual(colorItem.get(), 0x000000); + openPicker(colorItem); + assert.strictEqual($picker.get('classList').contains('show'), true); + $picker[0].click(); + assert.strictEqual($picker.get('classList').contains('show'), false); + }); +}); diff --git a/test/spec/lib/manipulators.js b/test/spec/lib/manipulators.js index ace3b9f..c886d62 100644 --- a/test/spec/lib/manipulators.js +++ b/test/spec/lib/manipulators.js @@ -9,17 +9,21 @@ describe('manipulators', function() { /** * @param {string} itemType * @param {*} value + * @param {*} expected * @return {void} */ - function testSetGet(itemType, value) { + function testSetGet(itemType, value, expected) { + expected = typeof expected === 'undefined' ? value : expected; + describe('.set() and .get()', function() { - it('sets and gets the value then triggers a "change" event', function() { + it('sets: "' + value + '" and gets: "' + expected + '" then triggers "change"', + function() { var handlerSpy = sinon.spy(); var clayItem = fixture.clayItem(itemType); clayItem.on('change', handlerSpy); clayItem.set(value); - assert.strictEqual(clayItem.get(), value); + assert.strictEqual(clayItem.get(), expected); assert.strictEqual(handlerSpy.callCount, 1, 'handler not called once'); assert(handlerSpy.calledOn(clayItem), 'handler not called on clayItem'); }); @@ -80,4 +84,17 @@ describe('manipulators', function() { testDisable('toggle'); testEnable('toggle'); }); + + describe('color', function() { + testSetGet('color', 'FF0000', 0xff0000); + testSetGet('color', '#FF0000', 0xff0000); + testSetGet('color', '0xFF0000', 0xff0000); + testSetGet('color', '#ff0000', 0xff0000); + testSetGet('color', 0xff0000, 0xff0000); + testSetGet('color', '', 0x000000); + testSetGet('color', false, 0x000000); + testSetGet('color', undefined, 0x000000); + testDisable('color'); + testEnable('color'); + }); });