color-picker

simple pure-JS color picker

by Lorraine Lee

HTML

<h1 id="heading">Experimental color picker</h1>
 <div class="picker">
  <canvas id="panel" width="256" height="256"></canvas>
  <form id="control">
   <label for="level">Adjust <span id="channel">saturation</span> level
   </label>
   <input min="0" max="100" step="1" id="level" name="which" type="range"
   value="100" onChange="colorPicker.setIntensity()" />
   <fieldset>
    <legend>Set color of:</legend>
    <label for="color">text</label>
    <input type="radio" name="domain" id="color"
    onChange="colorPicker.setDomain()" />
    <label for="background">background</label>
    <input type="radio" name="domain" id="background"
    onChange="colorPicker.setDomain()" checked />
   </fieldset>
   <fieldset>
    <legend>Hold which channel constant?</legend>
    <label for="channel0" id="label0">hue</label>
    <input type="radio" name="which" id="channel0" value="0"
    onChange="colorPicker.setChannel()" />
    <label for="channel1" id="label1">saturation</label>
    <input type="radio" name="which" id="channel1" value="1"
    onChange="colorPicker.setChannel()" checked />
    <label for="channel2"  id="label2">luminance</label>
    <input type="radio" name="which" id="channel2" value="2"
    onChange="colorPicker.setChannel()" />
   </fieldset>
   <fieldset>
    <legend>Color representation mode:</legend>
    <label for="rgb">rgb</label>
    <input name="mode" id="rgb" value="rgb" type="radio"
    onChange="colorPicker.setMode()" />
    <label for="hsl">hsl</label>
    <input name="mode" id="hsl" value="hsl" type="radio"
    onChange="colorPicker.setMode()" checked />
   </fieldset>
  </form>
 </div>

CSS

#panel {
 position: absolute;
 top: 100px;
 left: 100px;
}
#control {
 position: absolute;
 top: 400px;
}

JavaScript

var colorPicker = {

 // This table maps the channels of the two color systems to their appropriate
 // ranges and identifies which use '%' in their CSS representations
 MASTER_TABLE: {
  hsl: [
   {
    channelName: "hue",
    rangeMin: 0,
    rangeMax: 360,
    suffix: ""
   },
   {
    channelName: "saturation",
    rangeMin: 0,
    rangeMax: 100,
    suffix: "%"
   },
   {
    channelName: "luminance",
    rangeMin: 0,
    rangeMax: 100,
    suffix: "%"
   }
  ],
  rgb: [
   {
    channelName: "red",
    rangeMin: 0,
    rangeMax: 255,
    suffix: ""
   },
   {
    channelName: "green",
    rangeMin: 0,
    rangeMax: 255,
    suffix: ""
   },
   {
    channelName: "blue",
    rangeMin: 0,
    rangeMax: 255,
    suffix: ""
   }
  ]
 },

 // Set default values for public members:

 currentMode: "hsl",

 xChannel: 0,

 fixedChannel: 1,

 yChannel: 2,

 fixedChannelIntensity: 100,

 currentDomain: "background",

 canvasElement: document.getElementById("panel"),

 // setters for public members:

/*
 * Sets value of this.currentDomain based on radio inputs named "domain"
 *  (options are text and background).  Either the text or background color of
 *  the #heading element will be set by the color ultimately selected.
 * @this {ColorPicker}
 */
 setDomain: function () {
  this.currentDomain = document.getElementById("color").checked ? "color" :
   "background";
 },

/*
 * Return modeTables value corresponding to whichever key is stored in
 *  this.currentMode.
 * @return an array of three elements, each describing the parameters of one of
 *  the three channels apropos this.currentMode
 */
 currentModeTable: function () {
  return this.MASTER_TABLE[this.currentMode];
 },

/*
 * Sets value of this.currentMode based on radio inputs named "mode" (options
 *  are rgb and hsl)
 */
 setMode: function () {
  this.currentMode = document.getElementById("hsl").checked ? "hsl" : "rgb";
  for (var i = 0; i < 3; i++) {
   document.getElementById("label"+i).textContent =...