Copyright © 2008, Levyco Development, LLC. All rights are reserved.
Multiple Colorpickers With Linked Input Fields All Using A Single Widget...

Intro


The demo is intended to help users get the most out of the YUI Colorpicker control.


What most people find they want to do is have multiple colorpicker popups on a page, and furthermore, have "linked" user input fields for each input (to show the current RGB color, for example). In doing so, it is important to consider the efficiency of the solution, specifically, it is desirable to have a single colorpicker "widget".


This page will show you how to accomplish this goal, with a play-by-play commentary on the code that allows this to happen.


You may want to start by clicking the show demo button above so you can see what we're accomplishing, then you can follow along with the commentary as we show the code.


Some Background


Read the background page for additional details regarding the PHP code used on these pages. None of the PHP code is required to use or understand these demos.


So How's It Done?


The first thing we do is setup a container for the one colorpicker widget that will be created. The following div is included in the body of the page. It is a little different than what's in some of the other demos here because the we want the enclosing div to stay the same size regardless of the widget (or widget state) inside it. That's accomplished with the simple table that has fixed size invisible images in it (this could also have been setup with styles, but...)


<div id="popupColorPickerContainer" class="YPANEL">
<div class="hd">Select A Color...</div>
  <div class="bd">
    <table>
      <tr><td colspan="2"><img src="<?=/images/?>x.gif" height="1" width="350"></td></tr>
      <tr><td><img src="<?=/images/?>x.gif" height="200" width="1"></td><td><div id="ycolorPickerWidget"></div></td></tr>
    </table>
  </div>
</div>
                            

Next we define a dialog that contains our demonstration inputs. It looks like this:



<div id="yfrmDemoContainer" class="YPANEL">

<div id="yfrmDemo">
    <div class="hd">Multiple Colorpickers Inputs/Single Widget...</div>
    <div class="bd">
        <table>
        <tr>
            <td nowrap class="FORMLABEL"><img src="<?echo(/images/)?>t_callout.gif"></td>
            <td class="FORMFIELD">
                Click on a color swatch to select a new color.
            </td>
        </tr>
        <tr>
            <td nowrap class="FORMLABEL">Color #1:</td>
            <td class="FORMFIELD"><?echo(makeInputItem("COLOR1","color","",""))?></td>
        </tr>
        <tr>
            <td nowrap class="FORMLABEL">Color #2:</td>
            <td class="FORMFIELD"><?echo(makeInputItem("COLOR2","color","",""))?></td>
        </tr>
        <tr>
            <td nowrap class="FORMLABEL">Color #3:</td>
            <td class="FORMFIELD"><?echo(makeInputItem("COLOR3","color","",""))?></td>
        </tr>
        <tr>
            <td nowrap class="FORMLABEL">Color #4:</td>
            <td class="FORMFIELD"><?echo(makeInputItem("COLOR4","color","",""))?></td>
        </tr>
        </table>
    </div>
    <div class="ft"></div>
</div>
</div>

This is just a standard div for the most part that will be turned into a nice dialog by YUI. The only two unique things here are the outer "container" div with a class of YPANEL, and the PHP. YPANEL is a CSS rule that simply contains visibility:hidden. The PHP is simply a helper function that produces the the "color swatch" input box that gets linked to the colorpicker widget.


Here is how we tell YUI to make a pretty dialog/panel out of the div.


frmDemo = new YAHOO.widget.Panel("yfrmDemo", { modal:false, draggable:true, x:100, y:100, width:400, zIndex:10, underlay:"shadow", visible:false, fixedcenter:false, constraintoviewport:false, close:true } );
frmDemo.render();                            

Let's look at the actual input field and the button that pops up the colorpicker. The PHP function makeInputItem is being told to generate a "color" input item. For example, the first call results in the following HTML:


<input type="text" readonly name="COLOR1_swatch" id="COLOR1_swatch" value="" class="FORMINPUTXS" style="color:#FF0000; background-color:#FF0000"><button id="COLOR1_b" onclick="popupColorPicker('COLOR1_swatch','COLOR1_swatch','COLOR1_b');return(false);"><img src="/images/t_colors.gif"></button>                            

Now the real interesting stuff starts happening. The button that gets generated with the input field calls the popupColorPicker function when clicked. This function is in the global helper function script module included by the page (yuihelp.js).


var colorInit = true;
var colorWidgetInit = true;
var colorForm;
var colorObj;
var colorElV;
var colorElC;

function popupColorPicker (elV, elC, elBut) {

    if (!YAHOO.util.Dom.inDocument('popupColorPickerContainer')) return;

    colorElV = elV;
    colorElC = elC;

    var hex = getElement(elV).value;
    if (hex.length = 0) hex = "#000000";
    var r = hex2int(hex.length>=2?hex.substr(1,2):"0");
    var g = hex2int(hex.length>=4?hex.substr(3,2):"0");
    var b = hex2int(hex.length>=6?hex.substr(5,2):"0");
    var rgb = [r, g, b];

    if (colorInit) {
        colorInit = false;
	    colorForm = new YAHOO.widget.Panel("popupColorPickerContainer", { modal:false, draggable:false, x:50, y:150, height:150, width:350, zIndex:200, underlay:"shadow", visible:false, fixedcenter:false, constraintoviewport:true, close:true } );
        colorForm.render();
    }

    var xy = YAHOO.util.Dom.getXY(elBut);
    xy[0] += 20;
    xy[1] += 10;
    colorForm.show();
    YAHOO.util.Dom.setXY ('popupColorPickerContainer', xy, false);

    if (colorWidgetInit) {
        colorWidgetInit = false;
        var cpEl = getElement('ycolorPickerWidget');
        if (cpEl) {
            cpEl.innerHTML = '';
            colorObj = new YAHOO.widget.ColorPicker ('ycolorPickerWidget', { container:colorForm, showcontrols:false, images: { PICKER_THUMB: "/yui260/build/colorpicker/assets/picker_thumb.png", HUE_THUMB: "/yui260/build/colorpicker/assets/hue_thumb.png" } });
            colorObj.on ('rgbChange', popupColorPickerHandler);
        }
    }

    colorObj.setValue (rgb, true);

}

function popupColorPickerHandler (obj) {

    var rgb = '#' + int2hex(obj.newValue[0],2) + int2hex(obj.newValue[1],2) + int2hex(obj.newValue[2],2);
    var fg = '#' + int2hex(obj.newValue[0]^0xFF,2) + int2hex(obj.newValue[1]^0xFF,2) + int2hex(obj.newValue[2]^0xFF,2);
    getElement(colorElV).value = rgb;
    getRef(colorElC).backgroundColor = rgb;
    getRef(colorElC).color = fg;

}                            

After getting the current color from the associated input field, this function decides if the container panel widget needs to be created, or if we can just reuse the one we already built. Next, the panel widget gets moved to be close to the button that was pressed. Note how the object is rendered and shown before the XY location is set. This is necessary or the widget may (or may not) move to the desired location. Similarly, the function decides if it needs a colorpicker widget. If so, it creates it and puts it on the panel. Finally, the function defaults to the current swatch color. Note how the function first tests to make sure that the target div is actually in the page before it does anything.


The popupColorPickerHandler function gets called when a color selection is made, and it synchronizes the user input field with the selected value and hides the popup. This field could show the actual color, the RGB value, or both (I'm showing both) (or anything else). The fuction calls some additional functions in yuihelp.js. There are YUI equivalents of these functions, but I wrote these before I found them! I should standardize on the YUI functions because there is no need to have two...


That's it! By modularizing your code and building reusable tools, you can generate some really sophisticated web applications with very little effort. A lot of what we looked at here is part of the global functions script (which should be taken out of the global namespace really), and are therefore not dealt with on a page-by-page basis. For example, here is the entire source code for this page (with this help commentary removed). Nice and short!



<?


    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //      demos/colorpicker/multi_colorpickers_on_a_page_help.php
    //      =======================================================
    //
    //      this is the "help" page for multi colorpickers on a page
    //
    //      COPYRIGHT (C) 2008, Levyco Development, LLC.  All Rights Are Reserved.
    //
    //      ver 1.0.0 2008-11-12 BLevy
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    // master include

    
include_once("yuihelpglobal.php");

    
// set the YUI requirements

    
$YUI = array("container""button""calendar");

    
// draw the user interface

    
$UI->pageTop(""$YUI);

?>

    <div id="yfrmDemoContainer" class="YPANEL">
    <div id="yfrmDemo">
        <div class="hd">Multiple Colorpickers Inputs/Single Widget...</div>
        <div class="bd">
            <table>
            <tr>
                <td nowrap class="FORMLABEL"><img src="<?echo($IMGDIR)?>t_callout.gif"></td>
                <td class="FORMFIELD">
                    Click on a color swatch to select a new color.
                </td>
            </tr>
            <tr>
                <td nowrap class="FORMLABEL">Color #1:</td>
                <td class="FORMFIELD"><?echo(makeInputItem("COLOR1","color","",""))?></td>
            </tr>
            <tr>
                <td nowrap class="FORMLABEL">Color #2:</td>
                <td class="FORMFIELD"><?echo(makeInputItem("COLOR2","color","",""))?></td>
            </tr>
            <tr>
                <td nowrap class="FORMLABEL">Color #3:</td>
                <td class="FORMFIELD"><?echo(makeInputItem("COLOR3","color","",""))?></td>
            </tr>
            <tr>
                <td nowrap class="FORMLABEL">Color #4:</td>
                <td class="FORMFIELD"><?echo(makeInputItem("COLOR4","color","",""))?></td>
            </tr>
            </table>
        </div>
        <div class="ft"></div>
    </div>
    </div>

    <div id="popupColorPickerContainer" class="YPANEL"><div class="hd">Select A Color...</div><div class="bd"><table><tr><td colspan="2"><img src="<?=$IMGDIR?>x.gif" height="1" width="350"></td></tr><tr><td><img src="<?=$IMGDIR?>x.gif" height="200" width="1"></td><td><div id="ycolorPickerWidget"></div></td></tr></table></div></div>

<? $UI->pageBottom(); ?>

<script type="text/javascript">
<!--

    var frmHelp;
    var frmDemo;
    var resizer = { frm:{h:0,w:0}, div:{h:0,w:0}, scr:{h:0,w:0}, delta:{h:0,w:0}, target:{h:0,w:0} };

    function init () {

        frmHelp = new YAHOO.widget.Panel("yfrmHelp", { modal:false, draggable:true, x:20, y:75, width:740, zIndex:10, underlay:"shadow", visible:true, fixedcenter:false, constraintoviewport:false, close:false } );
        frmHelp.render();
        frmHelp.show();

        frmDemo = new YAHOO.widget.Panel("yfrmDemo", { modal:false, draggable:true, x:100, y:100, width:400, zIndex:10, underlay:"shadow", visible:false, fixedcenter:false, constraintoviewport:false, close:true } );
        frmDemo.render();

        YAHOO.util.Event.addListener("cmdShowDemo", "click", function(){frmDemo.show();});

        // resize the help container

        with (resizer) {

            frm.w = parseInt(frmHelp.cfg.getProperty('width'));
            div.w = parseInt(getElement('helptext').style.width);
            div.h = parseInt(getElement('helptext').style.height);
            scr.w = parseInt(YAHOO.util.Dom.getViewportWidth());
            scr.h = parseInt(YAHOO.util.Dom.getViewportHeight());
            target.w = Math.floor(scr.w * 0.75);
            target.h = Math.floor(scr.h * 0.75);
            delta.w = frm.w - div.w;

            if (target.w > frm.w) {
                frmHelp.cfg.setProperty('width', target.w);
                getElement('helptext').style.width = (target.w - delta.w) + 'px';
            }

            getElement('helptext').style.height = target.h + 'px';

        }

    }

    YAHOO.util.Event.onDOMReady (init);

//-->
</script>

Multiple Colorpicker Inputs/Single Widget...
Click on a color swatch to select a new color.
Color #1:
Color #2:
Color #3:
Color #4:
Select A Color...