Monday, 28 March 2016

Software Review: Sublime Text

Sublime Text is a tool created by Jon Skinner using Python. Sublime is used primarily by coders, the bulk of which are web developers who write scripts in HTML, JavaScript, CSS, PHP, Python and Scalar. At the time of this writing, Sublime is at version 2.0 with the next stable version, 3.0, up and coming. While the trial version is free for use indefinitely (with the odd message encouraging you to cough up for a license), the licensed version is a hefty 70 USD. Purchasing the license also entitles you to an upgrade to 3.0 when it comes out.

Buy now!

The Premise

On the surface, Sublime is a fairly lightweight text editing tool in the realm of Notepad ++, but via its extensibility through the use of numerous plugins, it can also be a decent IDE. I've been using Sublime over a year now, and have yet to use any plugins. Sublime, on its own, is more than adequate for my purposes.

The Aesthetics

The default color scheme, Monokai, is that of a soothing dark grey background with color-coded text. In that vein, it's similar to other tools such as VIM. When Skinner created Sublime, his main purpose was to ensure that the text never got cluttered by toolbars and whatnot, and you can see the results here. This is my standard operating layout, and if this isn't minimal enough, there's still the distraction-free option.

Distraction-free

My usual layout

Multiple-screen layout

The Experience

Sublime loads up fast. And has never crashed on me. Controls are responsive enough, and fairly intuitive.

The Interface

Plenty of standard text-editing tools such as search-and-replace, go to line, zoom in/out, autocomplete, and web snippets. These features are available via shortcut keys as well. If you're a Python nerd, you can even customize these features.

What I liked

Pressing Ctrl P brings up the Go To Anything feature, which takes a little getting used to, but grows on you like moss on lichen.
Go To Anything


Web Snippets are shortcuts used to instantly produce standard code segments. While I can type any of these with my eyes closed, undeniably it's a great pleasure not to have to do it. Just showing two of these.
Type "html"...

And you get a standard HTML snippet!

Type "lorem"...

And you get lorem ipsum text.


The Mini-map gives you a bird's eye view of your code in its entirety, useful if you're a neat freak whose code is identifiable by indentations and placed in well-defined sections. So instead of scrolling painstakingly to the required line, zoom right in on the area.

Mini-map


Simplicity. The required learning curve for this application isn't very steep - if you just want to type code, you can hop right in and feel your way out as you go. Easier as compared to, say, Emacs.

Persisting windows. If I forget to save a file before closing Sublime, the file is still there when I next start it up, right where I left it, in all its unsaved glory.

What I didn't

Some of the autocomplete functions are downright irritating. When, for example, I highlight a row of text and hit the quote key, I expect the line of text to be replaced by quotations, not encircled by them. But this is a minor quibble and your mileage may vary.

Documentation seems woefully inadequate. On the bright side, you probably won't need it.

Also, if you're just using it as a text editor and aren't really interested in the bells and whistles, 70 USD is a heck of a high price to pay considering you can get many of these features for free on other software.

Conclusion

Sublime is a joy to use and is free for life if you don't mind the occasional guilt trip the trial version lays on you. Me? I intend to pay once I've raised the cash - dollar by dollar. The license is by user, not by machine, so you can port it anywhere you want!

My Rating

8.5 / 10


Try Sublime today. It's better than text.
T___T

Friday, 25 March 2016

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

In this final part, we're going to add some gloss over your egg, and a bit of functionality.

Now for the egg itself. It's looking decidedly flat, and we'll be fixing this. Add this to the HTML.
        <div id="egg_wrapper">
            <div id="egg">
                <div id="egg_overlay"></div>

                <div id="band1" class="band"></div>
                <div id="band2" class="band"></div>
                <div id="band3" class="band"></div>


And this to the CSS. This was generated by the CSS Gradient Generator. The opacity has been set to 50%. This gives your egg a fake 3D effect.
            #egg_overlay
            {
                 opacity: 0.5;
                 filter: alpha(opacity=50); /* For IE8 and earlier */
                 -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                 border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                 width:250px;
                 height:350px;
                 position:absolute;
                 z-index:900;
                 background: #feffff; /* Old browsers */
                 background: -moz-radial-gradient(100px 100px, ellipse cover,  #feffff 0%, #444444 58%); /* FF3.6+ */
                 background: -webkit-gradient(radial, 100px 100px, 0px, center center, 100%, color-stop(0%,#feffff), color-stop(58%,#444444)); /* Chrome,Safari4+ */
                 background: -webkit-radial-gradient(100px 100px, ellipse cover,  #feffff 0%,#444444 58%); /* Chrome10+,Safari5.1+ */
                 background: -o-radial-gradient(100px 100px, ellipse cover,  #feffff 0%,#444444 58%); /* Opera 12+ */
                 background: -ms-radial-gradient(100px 100px, ellipse cover,  #feffff 0%,#444444 58%); /* IE10+ */
                 background: radial-gradient(ellipse at 100px 100px,  #feffff 0%,#444444 58%); /* W3C */
                 filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#feffff', endColorstr='#444444',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
            }


So far so good?



Now add this to your HTML. This is meant to add a shadow under your egg.
                <div id="star_wrapper5" class="star_wrapper">
                    <div id="star5_part1" class="star_part1"></div>
                    <div id="star5_part2" class="star_part2"></div>
                    <div id="star5_part3" class="star_part3"></div>
                </div>

                <div id="rainbow_wrapper">
                    <div id="rainbowband1" class="rainbowband"></div>
                    <div id="rainbowband2" class="rainbowband"></div>
                    <div id="rainbowband3" class="rainbowband"></div>
                    <div id="rainbowband4" class="rainbowband"></div>
                    <div id="rainbowband5" class="rainbowband"></div>
                    <div id="rainbowband6" class="rainbowband"></div>
                    <div id="rainbowband7" class="rainbowband"></div>   
                </div>
            </div>

            <div id="egg_shadow"></div>
        </div>
    </body>
</html>


This is the CSS for it.
            #egg_shadow
            {
                border-radius: 50%;
                width:150px;
                height:10px;
                box-shadow: 0px 20px 5px 5px #999999;
                background:none;
                position:absolute;
                z-index:0;
            }


Take another look! But there's a problem - the shadow isn't correctly placed. Also, when you resize the egg, a bit of weirdness appears. You need to resize the egg_overlay div and the egg_shadow div as well.


So modify the setwidth() function to cater to the egg. Note that what we're doing for the egg div and egg_shadow div is basically what we did for rainbow_wrapper div, except that this time the adjustments are made in relation to the egg_wrapper div. Also, note that since the width of the egg is altered and the rainbow is drawn in relation to the egg, you need to fire off the setwidth() function for the rainbow_wrapper.
            function setwidth(varid)
            {
                $("#"+varid).width($("#rng_width_"+varid).val());

                if (varid=="egg")
                {
                    $("#egg_overlay").width($("#rng_width_"+varid).val());
                    $("#egg_shadow").width($("#rng_width_"+varid).val()/1.5);
                    $("#egg").css("margin-left", marginleft+"px");
                    $("#egg_shadow").css("margin-left", (($("#egg_wrapper").width()-$("#egg_shadow").width())/2)+"px");
                    setwidth("rainbow_wrapper");
                }

                if (varid=="rainbow_wrapper")
                {
                    $("#rainbow_wrapper").css("margin-left","-"+(($("#rainbow_wrapper").width()-$("#egg").width())/2)+"px");
                    $(".rainbowband").width($("#rng_width_"+varid).val()-($("#hid_thickness_rainbow").val()*2));
                }
            }


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

                if (varid=="egg")
                {
                    var margintop=($("#egg_wrapper").height()-$("#egg").height())/2;

                    $("#egg_overlay").height($("#rng_height_"+varid).val());
                    $("#egg").css("margin-top", margintop+"px");
                    $("#egg_shadow").css("margin-top",(parseInt($("#rng_height_"+varid).val())+margintop-($("#egg_shadow").height()*2))+"px");
                }

                if (varid=="rainbow_wrapper")
                {
                    $(".rainbowband").height($("#rainbow_wrapper").height()*2);
                    $("#hid_thickness_rainbow").val($("#rainbow_wrapper").height()/20);
                   
                    $(".rainbowband").each(function()
                    {
                        $(this).css("border-width", $("#hid_thickness_rainbow").val()+"px");
                    });

                    $("#rainbowband1").css("margin-top", "0px");
                    $("#rainbowband2").css("margin-top", $("#hid_thickness_rainbow").val()+"px");
                    $("#rainbowband3").css("margin-top", ($("#hid_thickness_rainbow").val()*2)+"px");
                    $("#rainbowband4").css("margin-top", ($("#hid_thickness_rainbow").val()*3)+"px");
                    $("#rainbowband5").css("margin-top", ($("#hid_thickness_rainbow").val()*4)+"px");
                    $("#rainbowband6").css("margin-top", ($("#hid_thickness_rainbow").val()*5)+"px");
                    $("#rainbowband7").css("margin-top", ($("#hid_thickness_rainbow").val()*6)+"px");
                    setwidth("rainbow_wrapper");
                }
            }


Run your code again. Your overlay and shadow should move when you resize your egg now!


The Safari Fix

If you've been running your code so far, you'll realize it works on most other browsers but Safari. The overflow doesn't work and your rainbow, polka dots and whatnot are running out of the egg.


So yes, due to Safari's monkey crap different way of handling round corners and overflow rules in divs, here's a fix.

Add the following to your egg_wrapper div.
        <div id="egg_wrapper">
            <div id="egg">
                <div id="safari_fix"></div>
                <div id="egg_overlay"></div>

                <div id="band1" class="band"></div>
                <div id="band2" class="band"></div>
                <div id="band3" class="band"></div>


And style the safari_fix div. It's almost identical to the egg_overlay div, except that it has no background, its z-index property is set to higher than the egg_overlay's z-index property, and the box-shadow property is set to give the outline a red glow.
            #safari_fix
            {
                 -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                 border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                 width:250px;
                 height:350px;
                 position:absolute;
                 z-index:950;
                 box-shadow: 0px 0px 0px 500px #FF0000;
            }


Why red? Well, so it allows you to see what's going on, of course! See how the red part masks out the parts that are supposed to be hidden?


Change the color to white. Then when you run your code again, the effect should be there. This isn't a great solution (I mean, what if your the background color of your screen isn't white?), but web technology is often about improvisation.
            #safari_fix
            {
                 -webkit-border-radius: 63px 63px 63px 63px / 108px 108px 72px 72px;
                 border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
                 width:250px;
                 height:350px;
                 position:absolute;
                 z-index:950;
                 box-shadow: 0px 0px 0px 500px #FFFFFF;
            }


Of course, you'll have to alter your setheight() and setwidth() functions to reflect this.
            function setwidth(varid)
            {
                $("#"+varid).width($("#rng_width_"+varid).val());

                if (varid=="egg")
                {
                    $("#egg_overlay").width($("#rng_width_"+varid).val());
                    $("#safari_fix").width($("#rng_width_"+varid).val());
                    $("#egg_shadow").width($("#rng_width_"+varid).val()/1.5);
                    $("#egg").css("margin-left", marginleft+"px");
                    $("#egg_shadow").css("margin-left", (($("#egg_wrapper").width()-$("#egg_shadow").width())/2)+"px");
                    setwidth("rainbow_wrapper");
                }

                if (varid=="rainbow_wrapper")
                {
                    $("#rainbow_wrapper").get(0).style.marginLeft="-"+(($("#rainbow_wrapper").width()-$("#egg").width())/2)+"px";
                    $(".rainbowband").width($("#rng_width_"+varid).val()-($("#hid_thickness_rainbow").val()*2));
                }
            }

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

                if (varid=="egg")
                {
                    var margintop=($("#egg_wrapper").height()-$("#egg").height())/2;

                    $("#egg_overlay").height($("#rng_height_"+varid).val());
                    $("#safari_fix").height($("#rng_height_"+varid).val());
                    $("#egg").css("margin-top", margintop+"px");
                    $("#egg_shadow").css("margin-top",(parseInt($("#rng_height_"+varid).val())+margintop-($("#egg_shadow").height()*2))+"px");
                }

                if (varid=="rainbow_wrapper")
                {
                    $(".rainbowband").height($("#rainbow_wrapper").height()*2);
                    $("#hid_thickness_rainbow").val($("#rainbow_wrapper").height()/20);
                   
                    $(".rainbowband").each(function()
                    {
                        $(this).css("border-width", $("#hid_thickness_rainbow").val()+"px");
                    });

                    $("#rainbowband1").css("margin-top", "0px");
                    $("#rainbowband2").css("margin-top", $("#hid_thickness_rainbow").val()+"px");
                    $("#rainbowband3").css("margin-top", ($("#hid_thickness_rainbow").val()*2)+"px");
                    $("#rainbowband4").css("margin-top", ($("#hid_thickness_rainbow").val()*3)+"px");
                    $("#rainbowband5").css("margin-top", ($("#hid_thickness_rainbow").val()*4)+"px");
                    $("#rainbowband6").css("margin-top", ($("#hid_thickness_rainbow").val()*5)+"px");
                    $("#rainbowband7").css("margin-top", ($("#hid_thickness_rainbow").val()*6)+"px");
                    setwidth("rainbow_wrapper");
                }
            }


Print functionality

Now that your egg's looking good, what else could you want? To output your awesome design, of course!

Add this to your CSS. This basically ensures that in a print view, the dashboard_wrapper div turns invisible and the egg_wrapper div takes center stage.
            @media print
            {
                #dashboard_wrapper {display: none;}
                #egg_wrapper
                {
                    display:block;
                    border-width:0px;
                    width:90%;
                    position:relative;
                    margin-left:auto;
                    margin-right:auto;
                }
            }


That's it for your Easter egg generator. And I hoped this helped illustrate how jQuery has its uses. I'm still not overly fond of it, but y'know, it's Easter, keep an open mind.

Have a good Easter Sunday, because He shell rise again!
T___T

Tuesday, 22 March 2016

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

Bands, dots and stars - what could make your Easter egg even more awesome? What's the spirit of Easter? Why, hope and renewal of course. And for that, we need to add a rainbow to your egg.

If you've gone through the web tutorial for the CSS Rainbowlizer, this is pretty similar. One div with seven other divs nested within it. Here's what we add to the egg_wrapper div.
        <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 id="star_wrapper1" class="star_wrapper">
                    <div id="star1_part1" class="star_part1"></div>
                    <div id="star1_part2" class="star_part2"></div>
                    <div id="star1_part3" class="star_part3"></div>
                </div>

                <div id="star_wrapper2" class="star_wrapper">
                    <div id="star2_part1" class="star_part1"></div>
                    <div id="star2_part2" class="star_part2"></div>
                    <div id="star2_part3" class="star_part3"></div>
                </div>

                <div id="star_wrapper3" class="star_wrapper">
                    <div id="star3_part1" class="star_part1"></div>
                    <div id="star3_part2" class="star_part2"></div>
                    <div id="star3_part3" class="star_part3"></div>
                </div>

                <div id="star_wrapper4" class="star_wrapper">
                    <div id="star4_part1" class="star_part1"></div>
                    <div id="star4_part2" class="star_part2"></div>
                    <div id="star4_part3" class="star_part3"></div>
                </div>

                <div id="star_wrapper5" class="star_wrapper">
                    <div id="star5_part1" class="star_part1"></div>
                    <div id="star5_part2" class="star_part2"></div>
                    <div id="star5_part3" class="star_part3"></div>
                </div>

                <div id="rainbow_wrapper">
                    <div id="rainbowband1" class="rainbowband"></div>
                    <div id="rainbowband2" class="rainbowband"></div>
                    <div id="rainbowband3" class="rainbowband"></div>
                    <div id="rainbowband4" class="rainbowband"></div>
                    <div id="rainbowband5" class="rainbowband"></div>
                    <div id="rainbowband6" class="rainbowband"></div>
                    <div id="rainbowband7" class="rainbowband"></div>   
                </div>
            </div>
        </div>


Here are the CSS styles for the rainbow. The rainbow_wrapper div is rotated around its middle and positioned over the egg much the same was as the bands. Each div inside the rainbow_wrapper div is styled by rainbowband. The position property is absolute because they all overlap each other, and the border-radius property is set to 50% because they are all ellipses. However, they will appear only as curved bands because the rest of it is truncated by the rainbow_wrapper div's overflow property, which is set to hidden.

And of course, each individual band's background is transparent and its border set to 10 pixels, each of a different color.
            .star_part1
            {
                 position: absolute;
                 display: block;
                 color: red;
                 width: 0px;
                 height: 0px;
                 border-right: 20px solid transparent;
                 border-bottom: 15px solid red;
                 border-left: 20px solid transparent;
                 -webkit-transform:rotate(0deg);
                 transform:rotate(0deg);
            }

            .star_part2
            {
                 position: absolute;
                 display: block;
                 color: red;
                 width: 0px;
                 height: 0px;
                 border-right: 20px solid transparent;
                 border-bottom: 15px solid red;
                 border-left: 20px solid transparent;
                 -webkit-transform:rotate(70deg);
                 transform:rotate(70deg);
            }

            .star_part3
            {
                 position: absolute;
                 display: block;
                 color: red;
                 width: 0px;
                 height: 0px;
                 border-right: 20px solid transparent;
                 border-bottom: 15px solid red;
                 border-left: 20px solid transparent;
                 -webkit-transform:rotate(-70deg);
                 transform:rotate(-70deg);
            }

            #rainbowband1{background:transparent;border:10px solid #FF0000;}
            #rainbowband2{background:transparent;border:10px solid #FF9900;}
            #rainbowband3{background:transparent;border:10px solid #FFFF00;}
            #rainbowband4{background:transparent;border:10px solid #00FF00;}
            #rainbowband5{background:transparent;border:10px solid #0000FF;}
            #rainbowband6{background:transparent;border:10px solid #440044;}
            #rainbowband7{background:transparent;border:10px solid #FF00FF;}
           
            #rainbow_wrapper
            {
                width:1000px;
                height:100px;
                -webkit-transform-origin:50% 50%;

                transform-origin:50% 50%;
                overflow:hidden;
                position:absolute;
            }

            .rainbowband
            {
                border-radius:50%;
                position:absolute;
            }


You should be seeing this now. The rainbow appears as just a pink dot because we haven't positioned the individual bands properly. This will be fixed via JavaScript.


Hide the rainbow by adding this line.
            #rainbow_wrapper
            {
                width:1000px;
                height:100px;
                -webkit-transform-origin:50% 50%;
                transform-origin:50% 50%;
                overflow:hidden;
                display:none;
                position:absolute;
            }


Then add this code to your dashboard_wrapper div. As with all the others, it's a set of controls to manipulate your rainbow. The functions are pretty much the same as those used for bands. There's a hidden field, hid_thickness_rainbow, which stores the thickness of the rainbow bands.
             <fieldset>
                <legend>Star Settings <input type="checkbox" id="cb_pnlStars" onclick="setvisible('pnlStars');"></legend>
                <div id="pnlStars">
                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_star_wrapper1" onclick="setvisible('star_wrapper1');"><br />
                                <div class="verticaltext">Star 1</div>
                            </td>
                            <td><label for="col_star1">Color</label></td>
                            <td><input type="color" id="col_star1" value="#05F044" onchange="setstar('star1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_size_star1">Size</label></td>
                            <td><input type="range" id="rng_size_star1" class="smallslider" value="20" min="20" max="100" step="20" onchange="setstchaar('star1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_star_wrapper1">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_star_wrapper1" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('star_wrapper1');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_star_wrapper1">X</label></td>
                            <td><input type="range" id="rng_x_star_wrapper1" class="smallslider" value="150" min="0" max="200" step="10" onchange="setx('star_wrapper1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_star_wrapper1">Y</label></td>
                            <td><input type="range" id="rng_y_star_wrapper1" class="smallslider" value="150" min="0" max="200" step="10" onchange="sety('star_wrapper1');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_star_wrapper1">Z</label></td>
                            <td><input type="range" id="rng_z_star_wrapper1" class="smallslider" value="160" min="20" max="500" step="10" onchange="setz('star_wrapper1');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_star_wrapper2" onclick="setvisible('star_wrapper2');"><br />
                                <div class="verticaltext">Star 2</div>
                            </td>
                            <td><label for="col_star2">Color</label></td>
                            <td><input type="color" id="col_star2" value="#EE0088" onchange="setstar('star2');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_size_star2">Size</label></td>
                            <td><input type="range" id="rng_size_star2" class="smallslider" value="40" min="20" max="100" step="20" onchange="setstar('star2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_star_wrapper2">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_star_wrapper2" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('star_wrapper2');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_star_wrapper2">X</label></td>
                            <td><input type="range" id="rng_x_star_wrapper2" class="smallslider" value="150" min="0" max="200" step="10" onchange="setx('star_wrapper2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_star_wrapper2">Y</label></td>
                            <td><input type="range" id="rng_y_star_wrapper2" class="smallslider" value="250" min="0" max="200" step="10" onchange="sety('star_wrapper2');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_star_wrapper2">Z</label></td>
                            <td><input type="range" id="rng_z_star_wrapper2" class="smallslider" value="170" min="20" max="500" step="10" onchange="setz('star_wrapper2');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_star_wrapper3" onclick="setvisible('star_wrapper3');"><br />
                                <div class="verticaltext">Star 3</div>
                            </td>
                            <td><label for="col_star3">Color</label></td>
                            <td><input type="color" id="col_star3" value="#FF9966" onchange="setstar('star3');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_size_star3">Size</label></td>
                            <td><input type="range" id="rng_size_star3" class="smallslider" value="20" min="20" max="100" step="20" onchange="setstar('star3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_star_wrapper3">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_star_wrapper3" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('star_wrapper3');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_star_wrapper3">X</label></td>
                            <td><input type="range" id="rng_x_star_wrapper3" class="smallslider" value="50" min="0" max="200" step="10" onchange="setx('star_wrapper3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_star_wrapper3">Y</label></td>
                            <td><input type="range" id="rng_y_star_wrapper3" class="smallslider" value="280" min="0" max="200" step="10" onchange="sety('star_wrapper3');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_star_wrapper3">Z</label></td>
                            <td><input type="range" id="rng_z_star_wrapper3" class="smallslider" value="180" min="20" max="500" step="10" onchange="setz('star_wrapper3');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_star_wrapper4" onclick="setvisible('star_wrapper4');"><br />
                                <div class="verticaltext">Star 4</div>
                            </td>
                            <td><label for="col_star4">Color</label></td>
                            <td><input type="color" id="col_star4" value="#0055FF" onchange="setstar('star4');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_size_star4">Size</label></td>
                            <td><input type="range" id="rng_size_star4" class="smallslider" value="80" min="20" max="100" step="20" onchange="setstar('star4');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_star_wrapper4">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_star_wrapper4" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('star_wrapper4');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_star_wrapper4">X</label></td>
                            <td><input type="range" id="rng_x_star_wrapper4" class="smallslider" value="150" min="0" max="200" step="10" onchange="setx('star_wrapper4');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_star_wrapper4">Y</label></td>
                            <td><input type="range" id="rng_y_star_wrapper4" class="smallslider" value="50" min="0" max="200" step="10" onchange="sety('star_wrapper4');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_star_wrapper4">Z</label></td>
                            <td><input type="range" id="rng_z_star_wrapper4" class="smallslider" value="190" min="20" max="500" step="10" onchange="setz('star_wrapper4');"></td>
                        </tr>               
                    </table>

                    <table>
                        <tr>
                            <td rowspan="4">
                                <input type="checkbox" id="cb_star_wrapper5" onclick="setvisible('star_wrapper5');"><br />
                                <div class="verticaltext">Star 5</div>
                            </td>
                            <td><label for="col_star5">Color</label></td>
                            <td><input type="color" id="col_star5" value="#040444" onchange="setstar('star5');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_size_star5">Size</label></td>
                            <td><input type="range" id="rng_size_star5" class="smallslider" value="20" min="40" max="100" step="20" onchange="setstar('star5');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_star_wrapper5">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_star_wrapper5" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('star_wrapper5');"></td>
                            <td></td>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                        <tr>
                            <td><label for="rng_x_star_wrapper5">X</label></td>
                            <td><input type="range" id="rng_x_star_wrapper5" class="smallslider" value="50" min="0" max="200" step="10" onchange="setx('star_wrapper5');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_y_star_wrapper5">Y</label></td>
                            <td><input type="range" id="rng_y_star_wrapper5" class="smallslider" value="100" min="0" max="200" step="10" onchange="sety('star_wrapper5');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_star_wrapper5">Z</label></td>
                            <td><input type="range" id="rng_z_star_wrapper5" class="smallslider" value="200" min="20" max="500" step="10" onchange="setz('star_wrapper5');"></td>
                        </tr>               
                    </table>
                </div>
            </fieldset>   

            <fieldset>
                <legend>Rainbow Settings <input type="checkbox" id="cb_pnlRainbow" onclick="setvisible('pnlRainbow');"></legend>
                <div id="pnlRainbow">
                    <table>
                        <tr>
                            <td rowspan="2">
                                <input type="checkbox" id="cb_rainbow_wrapper" onclick="setvisible('rainbow_wrapper');"><br />
                                <div class="verticaltext">Rainbow</div>
                            </td>
                            <td><label for="rng_height_rainbow_wrapper">Height</label><input type="hidden" id="hid_thickness_rainbow" value="10"></td>
                            <td><input type="range" id="rng_height_rainbow_wrapper" class="smallslider" value="100" min="20" max="500" step="20" onchange="setheight('rainbow_wrapper');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_width_rainbow_wrapper">Width</label></td>
                            <td><input type="range" id="rng_width_rainbow_wrapper" class="smallslider" value="500" min="500" max="1500" step="10" onchange="setwidth('rainbow_wrapper');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_rotate_rainbow_wrapper">Rotation</label></td>
                            <td><input type="range" id="rng_rotate_rainbow_wrapper" class="smallslider" value="0" min="-180" max="180" step="10" onchange="setrotation('rainbow_wrapper');"></td>
                        </tr>
                        <tr>
                            <td><label for="rng_y_rainbow_wrapper">Y</label></td>
                            <td><input type="range" id="rng_y_rainbow_wrapper" class="smallslider" value="60" min="0" max="500" step="10" onchange="sety('rainbow_wrapper');"></td>
                            <td>&nbsp;</td>
                            <td><label for="rng_z_rainbow_wrapper">Z</label></td>
                            <td><input type="range" id="rng_z_rainbow_wrapper" class="smallslider" value="150" min="20" max="500" step="10" onchange="setz('rainbow_wrapper');"></td>
                        </tr>           
                    </table>
                </div>
            </fieldset>


Now, modify your JavaScript. The setwidth() function requires some tweaking for the rainbow. When the rainbow_wrapper div's width is changed, its margin-left property needs to be adjusted relative to the width of the egg, so it will always be in the middle of the egg.
            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");
                }

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


Also, each rainbow band's width is adjusted at the same time to cater for the thickness of the rainbow band. Remember each rainbow band is an ellipse? Therefore if the border thickness adds to its width, we have to offset this twice - one time for each side that will be affected.
            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");
                }

                if (varid=="rainbow_wrapper")
                {
                    $("#rainbow_wrapper").css("margin-left","-"+(($("#rainbow_wrapper").width()-$("#egg").width())/2)+"px");
                    $(".rainbowband").width($("#rng_width_"+varid).val()-($("#hid_thickness_rainbow").val()*2));
                }
            }


Next, we modify the setheight() function to cater for the rainbow_wrapper div. Changing the height will affect the height of each rainbow band, which is set at twice the height of the rainbow_wrapper div.
            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");
                }

                if (varid=="rainbow_wrapper")
                {
                    $(".rainbowband").height($("#rainbow_wrapper").height()*2);
                }
            }


The thickness is also affected - and it's set at 1/20th of the rainbow_wrapper div's height.
                if (varid=="rainbow_wrapper")
                {
                    $(".rainbowband").height($("#rainbow_wrapper").height()*2);
                    $("#hid_thickness_rainbow").val($("#rainbow_wrapper").height()/20);
                   
                    $(".rainbowband").each(function()
                    {
                        $(this).css("border-width", $("#hid_thickness_rainbow").val()+"px");
                    });
                }


And after that, each rainbow band's margin-top property needs to be set so that they align on top of each other neatly, taking the border thickness of each rainbow band into account.
                if (varid=="rainbow_wrapper")
                {
                    $(".rainbowband").height($("#rainbow_wrapper").height()*2);
                    $("#hid_thickness_rainbow").val($("#rainbow_wrapper").height()/20);
                   
                    $(".rainbowband").each(function()
                    {
                        $(this).get(0).style.borderWidth=$("#hid_thickness_rainbow").val()+"px";
                    });
                   
                    $("#rainbowband1").css("margin-top", "0px";
                    $("#rainbowband2").css("margin-top", $("#hid_thickness_rainbow").val()+"px");
                    $("#rainbowband3").css("margin-top", ($("#hid_thickness_rainbow").val()*2)+"px");
                    $("#rainbowband4").css("margin-top", ($("#hid_thickness_rainbow").val()*3)+"px");
                    $("#rainbowband5").css("margin-top", ($("#hid_thickness_rainbow").val()*4)+"px");
                    $("#rainbowband6").css("margin-top", ($("#hid_thickness_rainbow").val()*5)+"px");
                    $("#rainbowband7").css("margin-top", ($("#hid_thickness_rainbow").val()*6)+"px");
                }


And of course, since all this has been changed, we'll need to run the setwidth() function to properly align the entire rainbow_wrapper div.
                if (varid=="rainbow_wrapper")
                {
                    $(".rainbowband").height($("#rainbow_wrapper").height()*2);
                    $("#hid_thickness_rainbow").val($("#rainbow_wrapper").height()/20);
                   
                    $(".rainbowband").each(function()
                    {
                        $(this).get(0).style.borderWidth=$("#hid_thickness_rainbow").val()+"px";
                    });
                   
                    $("#rainbowband1").css("margin-top", "0px";
                    $("#rainbowband2").css("margin-top", $("#hid_thickness_rainbow").val()+"px");
                    $("#rainbowband3").css("margin-top", ($("#hid_thickness_rainbow").val()*2)+"px");
                    $("#rainbowband4").css("margin-top", ($("#hid_thickness_rainbow").val()*3)+"px");
                    $("#rainbowband5").css("margin-top", ($("#hid_thickness_rainbow").val()*4)+"px");
                    $("#rainbowband6").css("margin-top", ($("#hid_thickness_rainbow").val()*5)+"px");
                    $("#rainbowband7").css("margin-top", ($("#hid_thickness_rainbow").val()*6)+"px");
                    setwidth("rainbow_wrapper");
                }


Finally, the setvisible() function needs to be tweaked.
            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);
                    }

                    if (varid.indexOf("star")==0)
                    {
                        setstar(varid.replace("_wrapper",""));
                        setx(varid);
                        sety(varid);
                        setz(varid);
                    }

                    if (varid=="rainbow_wrapper")
                    {
                        setheight("rainbow_wrapper");
                        setrotation("rainbow_wrapper");
                        sety("rainbow_wrapper");
                        setz("rainbow_wrapper");
                    }
                }
                else
                {
                    $("#"+varid).hide();
                }
            }


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


Let's take a look at what we have so far. Try the controls. Do they work?


Well, we've added bands, dots, stars and a rainbow. Give yourself a pat on the back; that was an insane amount of work on a text editor! If you set the overflow property of the egg div to hidden, you should see the full effects now.
            #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:hidden;
                 position:absolute;
                 z-index:10;
            }


Now when you add the bands, polkadots, stars and rainbow, they no longer stick out of the egg! You'll also see that when you start expanding all the panels in the dashboard div, the screen expands but the egg stays in one place. That's because of the position propety of the egg_wrapper div, which was set to fixed.



Next

Some final touches, a fix or two. Watch this space!