Friday, 18 March 2016

Web Tutorial: The Easter Egg Generator (Part 1/4)

Easter is here, along with the promise of fresh and exciting things to come!

With that cliche out of the way, let's get to this month's web tutorial. Last Easter, we created an Easter egg. This Easter, we'll create an interface which creates an Easter egg. Fun, huh?

Tools you'll need

As usual, just any old text editor and a browser will do. But the tutorial will be in HTML5, CSS3 and jQuery. The jQuery repository we'll be using is at the following link.

Hold on. Don't you, like, hate jQuery?

"Hate" is a strong word. I'll confess to not liking to use it. However, that doesn't mean I won't use it when the situation calls for it. As it is, the situation isn't exactly screaming for it - "vanilla" JavaScript will do in a pinch - but jQuery sure makes our lives easier at this point. You'll see why as we progress! Here we don't fully harness the power of jQuery. Most of the mojo comes from CSS3.

First things first!

The basic layout. Here, we have two rectangles. The left one (dashboard_wrapper) contains the controls, and the right one (egg_wrapper) contains the result. There are going to be quite a few controls in the dashboard_wrapper div and the height will grow. Thus the egg_wrapper div's position property has been set to fixed. This way, no matter how big dashboard_wrapper becomes and how much you need to scroll, egg_wrapper always remains on screen at that position. The rest of the CSS here is mostly window dressing.
<!DOCTYPE html>
<html>
    <head>
        <title>Easter 2016</title>
        <style>
            #dashboard_wrapper
            {
                width:45%;
                height:auto;
                float:left;
                margin-left:2%;
                margin-top:2%;
                border:1px solid #999999;
            }

            #egg_wrapper
            {
                width:45%;
                height:85%;
                margin-left:50%;
                margin-top:2%;
                border:1px solid #999999;
                position:fixed;
            }
        </style>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <script>

        </script>
    </head>
    <body>
        <div id="dashboard_wrapper">

        </div>

        <div id="egg_wrapper">

        </div>
    </body>
</html>


The result is going to look boring so far. No worries, we're just getting started!


We begin by adding an egg in the egg_wrapper div.
        <div id="egg_wrapper">
            <div id="egg">

            </div>
        </div>


Add this style to your CSS.
            #dashboard_wrapper
            {
                width:45%;
                height:auto;
                float:left;
                margin-left:2%;
                margin-top:2%;
                border:1px solid #999999;
            }

            #egg_wrapper
            {
                width:45%;
                height:85%;
                margin-left:50%;
                margin-top:2%;
                border:1px solid #999999;
                position:fixed;
            }

            #egg
            {
                width:250px;
                height:350px;
                border:1px solid #888888;
                -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                overflow:visible;
                position:absolute;
                z-index:10;
            }


The basic shape for egg was taken from CSS Tricks and largely mirrors the implementation from last Easter. We start with a width of 250 pixels and a height of 350 pixels, but these values will of course be changed later. The overflow property is set to visible because we want to see what's going on. It'll be changed to hidden for the final touch.

So far so good? Egg-cellent. (hur hur)


Next we'll put some controls in the dashboard_wrapper div to modify the egg. Basically, we'll be adding functionality in the user interface to change the egg's color, height and width.
        <div id="dashboard_wrapper">
            <fieldset>
                <legend>Egg Settings</legend>
                <table>
                    <tr>
                        <td><label>Egg Color</label></td>
                    </tr>
                    <tr>
                        <td><label>Egg Height</label></td>
                    </tr>
                    <tr>
                        <td><label>Egg Width</label></td>
                    </tr>
                </table>               
            </fieldset>


Add this CSS so that the fieldset, legend and label elements fit nicely in the div. This is purely and aesthetic choice and should not affect the functionality of your code in the slightest.
        <style>
            fieldset
            {
                border:1px solid #999999;
                font-family:arial;
                font-size:12px;
            }

            legend
            {
                font-weight:bold;
            }

            label
            {
                font-family:arial;
                font-size:12px;
            }

            #dashboard_wrapper
            {
                width:45%;
                height:auto;
                float:left;
                margin-left:2%;
                margin-top:2%;
                border:1px solid #999999;
            }


And the result is here. These are just labels. We'll be adding actual controls soon!


Add this to your HTML. Here, we'll use the HTML5 color picker as an input. The initial value has been set to a light creamy yellow. When the color picker's value is changed, the setcolor() function is triggered. That's what we're going to write next.
            <fieldset>
                <legend>Egg Settings</legend>
                <table>
                    <tr>
                        <td><label for="col_egg">Egg Color</label></td>
                        <td><input type="color" id="col_egg" value="#FFFFAA" onchange="setcolor('egg');"></td>
                    </tr>
                    <tr>
                        <td><label>Egg Height</label></td>
                    </tr>
                    <tr>
                        <td><label>Egg Width</label></td>
                    </tr>
                </table>               
            </fieldset>


Now add this function to your JavaScript. See the jQuery? It saves us from having to use the getElementById() method. Seems like a small thing now, but this is going to add up because we have tons more of these little functions to create. In this case, the variable varid is passed into the setcolor() function. In the function, all it takes is one line to persuade the element identified by varid to change its background to the corresponding color picker's value. This function will be reused for other elements. jQuery's css() method gives us a short and sweet way to modify the style of a DOM object, something we'll be thankful for as we progress.
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <script>
            function setcolor(varid)
            {
                $("#"+varid).css("background-color", $("#col_"+varid).val());
            }
        </script>


Try it! Does the color change when you pick another color?


Now add these range inputs. Range inputs are particular to HTML5, just like color pickers. They'll appear like a slider. Note that for the rng_height_egg and rng_width_egg sliders, the maximum values are different. You can set these so that the user doesn't enter any funny input that you then have to handle.
            <fieldset>
                <legend>Egg Settings</legend>
                <table>
                    <tr>
                        <td><label for="col_egg">Egg Color</label></td>
                        <td><input type="color" id="col_egg" value="#FFFFAA" onchange="setcolor('egg');"></td>
                    </tr>
                    <tr>
                        <td><label for="rng_height_egg">Egg Height</label></td>
                        <td><input type="range" id="rng_height_egg" value="350" min="150" max="400" step="10" onchange="setheight('egg');"></td>
                    </tr>
                    <tr>
                        <td><label for="rng_width_egg">Egg Width</label></td>
                        <td><input type="range" id="rng_width_egg" value="250" min="100" max="300" step="10" onchange="setwidth('egg');"></td>
                    </tr>
                </table>               
            </fieldset>


This is what it should look like now.


Now at the setheight() and setwidth() functions. They're analogous to the setcolor() function.
        <script>
            function setcolor(varid)
            {
                $("#"+varid).css("background-color", $("#col_"+varid).val());
            }

            function setwidth(varid)
            {
                $("#"+varid).width($("#rng_width_"+varid).val());
            }

            function setheight(varid)
            {
                $("#"+varid).height($("#rng_height_"+varid).val());
            }
        </script>


Are you able to change the color, height and width of the egg? Give yourself a pat on the back, champ!


But wait...

Something's not quite right here. The egg would look better dead center of the egg_wrapper div, don't you think? So let's modify the position every time the height or width of the egg div is changed.

The setwidth() and setheight() functions are general-purpose functions which will be reused for all the other cool objects we're going to add in the course of this web tutorial. So with that in mind, we'll create special cases for the egg div. The position of the egg is offset by its width and height in relation to the egg_wrapper's width and height. Note that the egg_wrapper's width and height are expressed in percentages, but jQuery computes the height for us in pixels, making our lives a whole lot easier. Good thing too, because this web tutorial doesn't need to get any more calculation-intensive than it's going to be.
        <script>
            function setcolor(varid)
            {
                $("#"+varid).css("background-color", $("#col_"+varid).val());
            }

            function setwidth(varid)
            {
                $("#"+varid).width($("#rng_width_"+varid).val());

                if (varid=="egg")
                {
                    var marginleft=($("#egg_wrapper").width()-$("#egg").width())/2;
                    $("#egg").css("margin-left", marginleft+"px");
                }
            }

            function setheight(varid)
            {
                $("#"+varid).height($("#rng_height_"+varid).val());

                if (varid=="egg")
                {
                    var margintop=($("#egg_wrapper").height()-$("#egg").height())/2;
                    $("#egg").css("margin-top", margintop+"px");
                }
            }
        </script>


See? Now when you change the height and width of the egg, it goes dead center and stays there no matter how many times you change it.


But it goes back to the top left once I refresh my browser...

That's easily taken care of. Add this to your body tag. Now whenever you refresh your browser, after the HTML loads, the first thing it does is set the color, width and height of your egg. Now instead of a ghostly white, your egg starts off with a... not-so-ghostly beige.
    <body onload="setcolor('egg');setheight('egg');setwidth('egg');">


Bands and Dots

What we've accomplished here will set the template for the rest of it. We've succeeded in creating the egg layout and giving the user controls to modify it. So now let's decorate! We'll add user-editable color bands and polka dots.

In preparation for this, add the following HTML in the dashbboard_wrapper div.
            <fieldset>
                <legend>Egg Settings</legend>
                <table>
                    <tr>
                        <td><label for="col_egg">Egg Color</label></td>
                        <td><input type="color" id="col_egg" value="#FFFFAA" onchange="setcolor('egg');"></td>
                    </tr>
                    <tr>
                        <td><label for="rng_height_egg">Egg Height</label></td>
                        <td><input type="range" id="rng_height_egg" value="350" min="150" max="400" step="10" onchange="setheight('egg');"></td>
                    </tr>
                    <tr>
                        <td><label for="rng_width_egg">Egg Width</label></td>
                        <td><input type="range" id="rng_width_egg" value="250" min="100" max="300" step="10" onchange="setwidth('egg');"></td>
                    </tr>
                </table> 
            </fieldset>

            <fieldset>
                <legend>Band Settings <input type="checkbox" id="cb_pnlBands"></legend>
                <div id="pnlBands">
                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_band1"><br />
                                <div>Band 1</div>
                            </td>
                            <td><label for="col_band1">Color</label></td>
                            <td><input type="color" id="col_band1" value="#FF55EE" onchange="setcolor('band1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_band1">Height</label></td>
                            <td><input type="range" id="rng_height_band1" class="smallslider" value="50" min="1" max="500" step="10"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_band1">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_band1" class="smallslider" value="0" min="-180" max="180" step="10"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_y_band1">Y</label></td>
                            <td><input type="range" id="rng_y_band1" class="smallslider" value="10" min="0" max="500" step="10"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_band1">Z</label></td>
                            <td><input type="range" id="rng_z_band1" class="smallslider" value="20" min="20" max="500" step="10"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>               
                    </table>
                </div>
            </fieldset>


Then add the following HTML in the egg_wrapper div. Here we add a div within the egg div with a CSS class of band.
        <div id="egg_wrapper">
            <div id="egg">
                <div id="band1" class="band"></div>
            </div>
        </div>


Then the CSS. Each band is set to 1000 pixels width and positioned so that the middle coincides with that of the egg div. Since they're meant to overlap, position has been set to absolute. There will be a rotation function later on, so to prepare for that, we set transform-origin to the center point.
            #egg
            {
                width:250px;
                height:350px;
                border:1px solid #888888;
                 -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                 border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                 overflow:visible;
                 position:absolute;
                 z-index:10;
            }

            #pnlBands{display:none;}

            .band
            {
                width:1000px;
                margin-left:-350px;                -webkit-transform-origin:50% 50%;
                transform-origin:50% 50%;
                display:none;
                position:absolute;
            }


There you are! But hold on, you can't see the controls you added other than the checkbox. That's because you set the pnlBands div's display property to none in the CSS, remember?


Change this line.
            <legend>Band Settings <input type="checkbox" id="cb_pnlBands" onclick="setvisible('pnlBands');"></legend>


Then add the setvisible() function to your script. This function checks for element's checkbox id, and sets the visibility according to its checked status. The show() and hide() methods are from the jQuery library. Take a closer look here.
            function setheight(varid)
            {
                $("#"+varid).height($("#rng_height_"+varid).val());

                if (varid=="egg")
                {
                    var margintop=($("#egg_wrapper").height()-$("#egg").height())/2;
                    $("#egg").css("margin-top", margintop+"px");
                }
            }

            function setvisible(varid)
            {
                if ($("#cb_"+varid).prop("checked"))
                {
                    $("#"+varid).show();
                }
                else
                {
                    $("#"+varid).hide();
                }
            }


Now refresh your browser and click on the Band Settings checkbox. This should appear!


The "Band 1" text takes up too much space, so modify it like so...
            <div class="verticaltext">Band 1</div>


And add this CSS Class.
            fieldset
            {
                border:1px solid #999999;
                font-family:arial;
                font-size:12px;
            }

            legend
            {
                font-weight:bold;
            }

            label
            {
                font-family:arial;
                font-size:12px;
            }

            .verticaltext
            {
                -webkit-transform:rotate(-90deg);
                -webkit-transform-origin:left top;
                transform:rotate(-90deg);
                transform-origin:left top;
                margin-top:100%;
            }


It's a minor change, but these things add up!


Now we're going to add more functionality. Make the following changes. You'll see that we've added triggers for the new setrotation(), sety() and setz() functions, as well as the existing functions.
                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_band1" onclick="setvisible('band1');"><br />
                                <div class="verticaltext">Band 1</div>
                            </td>
                            <td><label for="col_band1">Color</label></td>
                            <td><input type="color" id="col_band1" value="#FF55EE" onchange="setcolor('band1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_band1">Height</label></td>
                            <td><input type="range" id="rng_height_band1" class="smallslider" value="50" min="1" max="500" step="10" onchange="setheight('band1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_band1">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_band1" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('band1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_y_band1">Y</label></td>
                            <td><input type="range" id="rng_y_band1" class="smallslider" value="10" min="0" max="500" step="10" onchange="sety('band1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_band1">Z</label></td>
                            <td><input type="range" id="rng_z_band1" class="smallslider" value="20" min="20" max="500" step="10" onchange="setz('band1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>               
                    </table>


And now, of course, to create those functions in your JavaScript. You'll realize that these functions are all just variants on the earlier functions setcolor() and setwidth(). The appropriate CSS properties of the specified element are set to the values of the controls, in this case "Band1".
            function setcolor(varid)
            {
                $("#"+varid).css("background-color", $("#col_"+varid).val());
            }

            function setwidth(varid)
            {
                $("#"+varid).width($("#rng_width_"+varid).val());

                if (varid=="egg")
                {
                    var marginleft=($("#egg_wrapper").width()-$("#egg").width())/2;
                    $("#egg").css("margin-left", marginleft+"px");
                }
            }

            function setheight(varid)
            {
                $("#"+varid).height($("#rng_height_"+varid).val());

                if (varid=="egg")
                {
                    var margintop=($("#egg_wrapper").height()-$("#egg").height())/2;
                    $("#egg").css("margin-top", margintop+"px");
                }
            }

            function setrotation(varid)
            {
                $("#"+varid).css("transform", "rotate("+$("#rng_rotate_"+varid).val()+"deg)");
                $("#"+varid).css("-webkit-transform", "rotate("+$("#rng_rotate_"+varid).val()+"deg)");
            }

            function sety(varid)
            {
                $("#"+varid).css("margin-top", $("#rng_y_"+varid).val()+"px");
            }

            function setz(varid)
            {
                $("#"+varid).css("z-index", $("#rng_z_"+varid).val());
            }

            function setvisible(varid)
            {
                if ($("#cb_"+varid).prop("checked"))
                {
                    $("#"+varid).show();
                }
                else
                {
                    $("#"+varid).hide();
                }
            }


Also, add this to your setvisible() function. If the element to be shown is a "band", automatically set its other properties as well.
            function setvisible(varid)
            {
                if ($("#cb_"+varid).prop("checked"))
                {
                    $("#"+varid).show();

                    if (varid.indexOf("band")==0)
                    {
                        setcolor(varid);
                        setheight(varid);
                        setrotation(varid);
                        sety(varid);
                        setz(varid);
                    }
                }
                else
                {
                    $("#"+varid).hide();
                }
            }


Now test! Does the band respond to your dashboard controls?


There's more, you know. We'll start by adding two more bands, and giving them different ids from the first.
        <div id="egg_wrapper">
            <div id="egg">
                <div id="band1" class="band"></div>
                <div id="band2" class="band"></div>
                <div id="band3" class="band"></div>
            </div>
        </div>


Then we add the controls in your dashboard_wrapper, to control those bands! It's basically a copy-paste job, and you'll change the arguments of the functions to "band2" and "band3", etc.
            <fieldset>
                <legend>Band Settings <input type="checkbox" id="cb_pnlBands" onclick="setvisible('pnlBands');"></legend>
                <div id="pnlBands">
                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_band1" onclick="setvisible('band1');"><br />
                                <div class="verticaltext">Band 1</div>
                            </td>
                            <td><label for="col_band1">Color</label></td>
                            <td><input type="color" id="col_band1" value="#FF55EE" onchange="setcolor('band1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_band1">Height</label></td>
                            <td><input type="range" id="rng_height_band1" class="smallslider" value="50" min="1" max="500" step="10" onchange="setheight('band1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_band1">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_band1" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('band1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_y_band1">Y</label></td>
                            <td><input type="range" id="rng_y_band1" class="smallslider" value="10" min="0" max="500" step="10" onchange="sety('band1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_band1">Z</label></td>
                            <td><input type="range" id="rng_z_band1" class="smallslider" value="20" min="20" max="500" step="10" onchange="setz('band1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_band2" onclick="setvisible('band2');"><br />
                                <div class="verticaltext">Band 2</div>
                            </td>
                            <td><label for="col_band2">Color</label></td>
                            <td><input type="color" id="col_band2" value="#00FF44" onchange="setcolor('band2');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_band2">Height</label></td>
                            <td><input type="range" id="rng_height_band2" class="smallslider" value="80" min="1" max="500" step="10" onchange="setheight('band2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_band2">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_band2" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('band2');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_y_band2">Y</label></td>
                            <td><input type="range" id="rng_y_band2" class="smallslider" value="30" min="0" max="500" step="10" onchange="sety('band2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_band2">Z</label></td>
                            <td><input type="range" id="rng_z_band2" class="smallslider" value="30" min="20" max="500" step="10" onchange="setz('band2');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_band3" onclick="setvisible('band3');"><br />
                                <div class="verticaltext">Band 3</div>
                            </td>
                            <td><label for="col_band3">Color</label></td>
                            <td><input type="color" id="col_band3" value="#44AAFF" onchange="setcolor('band3');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_band3">Height</label></td>
                            <td><input type="range" id="rng_height_band3" class="smallslider" value="20" min="1" max="500" step="10" onchange="setheight('band3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_band3">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_band3" class="smallslider" value="20" min="-180" max="180" step="10" onchange="setrotation('band3');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_y_band3">Y</label></td>
                            <td><input type="range" id="rng_y_band3" class="smallslider" value="60" min="0" max="500" step="10" onchange="sety('band3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_band3">Z</label></td>
                            <td><input type="range" id="rng_z_band3" class="smallslider" value="40" min="20" max="500" step="10" onchange="setz('band3');"></td>
                        </tr>               
                    </table>
                </div>
            </fieldset>


Have fun with your three bands! Don't worry about the unsightly way these bands are sticking out of the egg. That will be addressed later.


Polka Dots

Now we're going to add user-customizable polka dots to the egg. The functionality behind this is pretty much the same. We'll modify existing Javascript functions and add new ones as required.

Yep, this time, we'll add five polka dots to the egg.
        <div id="egg_wrapper">
            <div id="egg">
                <div id="band1" class="band"></div>
                <div id="band2" class="band"></div>
                <div id="band3" class="band"></div>

                <div id="polkadot1" class="polkadot"></div>
                <div id="polkadot2" class="polkadot"></div>
                <div id="polkadot3" class="polkadot"></div>
                <div id="polkadot4" class="polkadot"></div>
                <div id="polkadot5" class="polkadot"></div>
            </div>
        </div>


Add this CSS style. This being a polka dot and therefore an ellipse, the border-radius property is set to 50%.
            #egg
            {
                width:250px;
                height:350px;
                border:1px solid #888888;
                 -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                 border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                 overflow:visible;
                 position:absolute;
                 z-index:10;
            }

            #pnlBands{display:none;}

            .band
            {
                width:1000px;
                margin-left:-350px;
                -webkit-transform-origin:50% 50%;
                transform-origin:50% 50%;
                display:none;
                position:absolute;
            }

            .polkadot
            {
                border-radius:50%;
                display:none;
                position:absolute;
            }


And add the HTML for the polka dot settings to the dashboard_wrapper div. I'm not even going to walk you through this one - it's basically a rehash of the code we wrote for bands, with a few extra controls. For polka dots, we have the setwidth() and setx() functions added.
            <fieldset>
                <legend>Band Settings <input type="checkbox" id="cb_pnlBands" onclick="setvisible('pnlBands');"></legend>
                <div id="pnlBands">
                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_band1" onclick="setvisible('band1');"><br />
                                <div class="verticaltext">Band 1</div>
                            </td>
                            <td><label for="col_band1">Color</label></td>
                            <td><input type="color" id="col_band1" value="#FF55EE" onchange="setcolor('band1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_band1">Height</label></td>
                            <td><input type="range" id="rng_height_band1" class="smallslider" value="50" min="1" max="500" step="10" onchange="setheight('band1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_band1">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_band1" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('band1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_y_band1">Y</label></td>
                            <td><input type="range" id="rng_y_band1" class="smallslider" value="10" min="0" max="500" step="10" onchange="sety('band1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_band1">Z</label></td>
                            <td><input type="range" id="rng_z_band1" class="smallslider" value="20" min="20" max="500" step="10" onchange="setz('band1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_band2" onclick="setvisible('band2');"><br />
                                <div class="verticaltext">Band 2</div>
                            </td>
                            <td><label for="col_band2">Color</label></td>
                            <td><input type="color" id="col_band2" value="#00FF44" onchange="setcolor('band2');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_band2">Height</label></td>
                            <td><input type="range" id="rng_height_band2" class="smallslider" value="80" min="1" max="500" step="10" onchange="setheight('band2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_band2">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_band2" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('band2');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_y_band2">Y</label></td>
                            <td><input type="range" id="rng_y_band2" class="smallslider" value="30" min="0" max="500" step="10" onchange="sety('band2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_band2">Z</label></td>
                            <td><input type="range" id="rng_z_band2" class="smallslider" value="30" min="20" max="500" step="10" onchange="setz('band2');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_band3" onclick="setvisible('band3');"><br />
                                <div class="verticaltext">Band 3</div>
                            </td>
                            <td><label for="col_band3">Color</label></td>
                            <td><input type="color" id="col_band3" value="#44AAFF" onchange="setcolor('band3');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_band3">Height</label></td>
                            <td><input type="range" id="rng_height_band3" class="smallslider" value="20" min="1" max="500" step="10" onchange="setheight('band3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_band3">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_band3" class="smallslider" value="20" min="-180" max="180" step="10" onchange="setrotation('band3');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_y_band3">Y</label></td>
                            <td><input type="range" id="rng_y_band3" class="smallslider" value="60" min="0" max="500" step="10" onchange="sety('band3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_band3">Z</label></td>
                            <td><input type="range" id="rng_z_band3" class="smallslider" value="40" min="20" max="500" step="10" onchange="setz('band3');"></td>
                        </tr>               
                    </table>
                </div>
            </fieldset>

            <fieldset>
                <legend>Polkadot Settings <input type="checkbox" id="cb_pnlPolkadots" onclick="setvisible('pnlPolkadots');"></legend>
                <div id="pnlPolkadots">
                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_polkadot1" onclick="setvisible('polkadot1');"><br />
                                <div class="verticaltext">Polkadot 1</div>
                            </td>
                            <td><label for="col_polkadot1">Color</label></td>
                            <td><input type="color" id="col_polkadot1" value="#04EE04" onchange="setcolor('polkadot1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_polkadot1">Height</label></td>
                            <td><input type="range" id="rng_height_polkadot1" class="smallslider" value="20" min="10" max="200" step="10" onchange="setheight('polkadot1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_width_polkadot1">Width</label></td>
                            <td><input type="range" id="rng_width_polkadot1" class="smallslider" value="20" min="10" max="200" step="10" onchange="setwidth('polkadot1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_polkadot1">X</label></td>
                            <td><input type="range" id="rng_x_polkadot1" class="smallslider" value="50" min="0" max="200" step="10" onchange="setx('polkadot1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_polkadot1">Y</label></td>
                            <td><input type="range" id="rng_y_polkadot1" class="smallslider" value="50" min="0" max="200" step="10" onchange="sety('polkadot1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_polkadot1">Z</label></td>
                            <td><input type="range" id="rng_z_polkadot1" class="smallslider" value="50" min="20" max="500" step="10" onchange="setz('polkadot1');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_polkadot2" onclick="setvisible('polkadot2');"><br />
                                <div class="verticaltext">Polkadot 2</div>
                            </td>
                            <td><label for="col_polkadot2">Color</label></td>
                            <td><input type="color" id="col_polkadot2" value="#44EEFF" onchange="setcolor('polkadot2');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_polkadot2">Height</label></td>
                            <td><input type="range" id="rng_height_polkadot2" class="smallslider" value="30" min="10" max="200" step="10" onchange="setheight('polkadot2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_width_polkadot2">Width</label></td>
                            <td><input type="range" id="rng_width_polkadot2" class="smallslider" value="30" min="10" max="200" step="10" onchange="setwidth('polkadot2');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_polkadot2">X</label></td>
                            <td><input type="range" id="rng_x_polkadot2" class="smallslider" value="50" min="0" max="200" step="10" onchange="setx('polkadot2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_polkadot2">Y</label></td>
                            <td><input type="range" id="rng_y_polkadot2" class="smallslider" value="80" min="0" max="200" step="10" onchange="sety('polkadot2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_polkadot2">Z</label></td>
                            <td><input type="range" id="rng_z_polkadot2" class="smallslider" value="60" min="20" max="500" step="10" onchange="setz('polkadot2');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_polkadot3" onclick="setvisible('polkadot3');"><br />
                                <div class="verticaltext">Polkadot 3</div>
                            </td>
                            <td><label for="col_polkadot3">Color</label></td>
                            <td><input type="color" id="col_polkadot3" value="#004499" onchange="setcolor('polkadot3');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_polkadot3">Height</label></td>
                            <td><input type="range" id="rng_height_polkadot3" class="smallslider" value="10" min="10" max="200" step="10" onchange="setheight('polkadot3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_width_polkadot3">Width</label></td>
                            <td><input type="range" id="rng_width_polkadot3" class="smallslider" value="10" min="10" max="200" step="10" onchange="setwidth('polkadot3');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_polkadot3">X</label></td>
                            <td><input type="range" id="rng_x_polkadot3" class="smallslider" value="150" min="0" max="200" step="10" onchange="setx('polkadot3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_polkadot3">Y</label></td>
                            <td><input type="range" id="rng_y_polkadot3" class="smallslider" value="150" min="0" max="200" step="10" onchange="sety('polkadot3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_polkadot3">Z</label></td>
                            <td><input type="range" id="rng_z_polkadot3" class="smallslider" value="70" min="20" max="500" step="10" onchange="setz('polkadot3');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_polkadot4" onclick="setvisible('polkadot4');"><br />
                                <div class="verticaltext">Polkadot 4</div>
                            </td>
                            <td><label for="col_polkadot4">Color</label></td>
                            <td><input type="color" id="col_polkadot4" value="#FFFF00" onchange="setcolor('polkadot4');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_polkadot4">Height</label></td>
                            <td><input type="range" id="rng_height_polkadot4" class="smallslider" value="30" min="10" max="200" step="10" onchange="setheight('polkadot4');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_width_polkadot4">Width</label></td>
                            <td><input type="range" id="rng_width_polkadot4" class="smallslider" value="30" min="10" max="200" step="10" onchange="setwidth('polkadot4');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_polkadot4">X</label></td>
                            <td><input type="range" id="rng_x_polkadot4" class="smallslider" value="120" min="0" max="200" step="10" onchange="setx('polkadot4');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_polkadot4">Y</label></td>
                            <td><input type="range" id="rng_y_polkadot4" class="smallslider" value="90" min="0" max="200" step="10" onchange="sety('polkadot4');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_polkadot4">Z</label></td>
                            <td><input type="range" id="rng_z_polkadot4" class="smallslider" value="80" min="20" max="500" step="10" onchange="setz('polkadot4');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_polkadot5" onclick="setvisible('polkadot5');"><br />
                                <div class="verticaltext">Polkadot 5</div>
                            </td>
                            <td><label for="col_polkadot5">Color</label></td>
                            <td><input type="color" id="col_polkadot5" value="#AA0544" onchange="setcolor('polkadot5');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_height_polkadot5">Height</label></td>
                            <td><input type="range" id="rng_height_polkadot5" class="smallslider" value="50" min="10" max="200" step="10" onchange="setheight('polkadot5');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_width_polkadot5">Width</label></td>
                            <td><input type="range" id="rng_width_polkadot5" class="smallslider" value="50" min="10" max="200" step="10" onchange="setwidth('polkadot5');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_polkadot5">X</label></td>
                            <td><input type="range" id="rng_x_polkadot5" class="smallslider" value="80" min="0" max="200" step="10" onchange="setx('polkadot5');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_polkadot5">Y</label></td>
                            <td><input type="range" id="rng_y_polkadot5" class="smallslider" value="10" min="0" max="200" step="10" onchange="sety('polkadot5');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_polkadot5">Z</label></td>
                            <td><input type="range" id="rng_z_polkadot5" class="smallslider" value="90" min="20" max="500" step="10" onchange="setz('polkadot5');"></td>
                        </tr>               
                    </table>               
                </div>
            </fieldset>   


Those functions, of course, will be added to your Javascript here.
            function setwidth(varid)
            {
                $("#"+varid).width($("#rng_width_"+varid).val());
            }

            function setheight(varid)
            {
                $("#"+varid).height($("#rng_height_"+varid).val());
            }

            function setrotation(varid)
            {
                $("#"+varid).css("transform", "rotate("+$("#rng_rotate_"+varid).val()+"deg)");
                $("#"+varid).css("-webkit-transform", "rotate("+$("#rng_rotate_"+varid).val()+"deg)");
            }

            function setx(varid)
            {
                $("#"+varid).css("margin-left", $("#rng_x_"+varid).val()+"px");
            }

            function sety(varid)
            {
                $("#"+varid).css("margin-top", $("#rng_y_"+varid).val()+"px");
            }

            function setz(varid)
            {
                $("#"+varid).css("z-index", $("#rng_z_"+varid).val());
            }


For the setvisible() function, there's some extra code to cater for polka dots. The functionality of the code is analogous to that of the code written for bands, ie. it initializes the properties of each polka dot upon rendering it visible.
            function setvisible(varid)
            {
                if ($("#cb_"+varid).prop("checked"))
                {
                    $("#"+varid).show();

                    if (varid.indexOf("band")==0)
                    {
                        setcolor(varid);
                        setheight(varid);
                        setrotation(varid);
                        sety(varid);
                        setz(varid);
                    }

                    if (varid.indexOf("polkadot")==0)
                    {
                        setcolor(varid);
                        setheight(varid);
                        setwidth(varid);
                        setx(varid);
                        sety(varid);
                        setz(varid);
                    }
                }
                else
                {
                    $("#"+varid).hide();
                }
            }


Modify as shown to hide the controls initially.
            #pnlBands,#pnlPolkadots{display:none;}


Run your code!


Hope you had fun there. This is a safe stopping point, but if you're up for a challenge, we can add even cooler stuff to this little application.

Next

We move beyond bands and dots, and start adding more interesting shapes. Stay tuned!

No comments:

Post a Comment