jQuery UI & Utilities: Color changing

This entry is part 2 of 3 in the series jQuery UI Utilities

jQuery UI Widget – Default functionality

This demo shows a simple custom widget built using the widget factory (jquery.ui.widget.js).

The three boxes are initialized in different ways.

Clicking them changes their background color. View source to see how it works, its heavily commented.

<!doctype html>
<html lang='en'>
<head>
    <meta charset='utf-8'>
    <title>jQuery UI Widget - Default functionality</title>
    <link rel='stylesheet' href='//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css'>
    <script src='//code.jquery.com/jquery-1.10.2.js'></script>
    <script src='//code.jquery.com/ui/1.10.4/jquery-ui.js'></script>
    <link rel='stylesheet' href='https://codecrawl.com/code/jqueryui/jqueryui_style.css'>
    <style>
        .custom-colorize {
            font-size: 20px;
            position: relative;
            width: 75px;
            height: 75px;
        }

        .custom-colorize-changer {
            font-size: 10px;
            position: absolute;
            right: 0;
            bottom: 0;
        }
    </style>
    <script>
        $(function () {
            // the widget definition, where 'custom' is the namespace,
            // 'colorize' the widget name
            $.widget('custom.colorize', {
                // default options
                options: {
                    red: 255,
                    green: 0,
                    blue: 0,

                    // callbacks
                    change: null,
                    random: null
                },

                // the constructor
                _create: function () {
                    this.element
                        // add a class for theming
                            .addClass('custom-colorize')
                        // prevent double click to select text
                            .disableSelection();

                    this.changer = $('<button>', {
                        text: 'change',
                        'class': 'custom-colorize-changer'
                    })
                            .appendTo(this.element)
                            .button();

                    // bind click events on the changer button to the random method
                    this._on(this.changer, {
                        // _on won't call random when widget is disabled
                        click: 'random'
                    });
                    this._refresh();
                },

                // called when created, and later when changing options
                _refresh: function () {
                    this.element.css('background-color', 'rgb(' +
                                    this.options.red + ',' +
                                    this.options.green + ',' +
                                    this.options.blue + ')'
                    );

                    // trigger a callback/event
                    this._trigger('change');
                },

                // a public method to change the color to a random value
                // can be called directly via .colorize( 'random' )
                random: function (event) {
                    var colors = {
                        red: Math.floor(Math.random() * 256),
                        green: Math.floor(Math.random() * 256),
                        blue: Math.floor(Math.random() * 256)
                    };

                    // trigger an event, check if it's canceled
                    if (this._trigger('random', event, colors) !== false) {
                        this.option(colors);
                    }
                },

                // events bound via _on are removed automatically
                // revert other modifications here
                _destroy: function () {
                    // remove generated elements
                    this.changer.remove();

                    this.element
                            .removeClass('custom-colorize')
                            .enableSelection()
                            .css('background-color', 'transparent');
                },

                // _setOptions is called with a hash of all options that are changing
                // always refresh when changing options
                _setOptions: function () {
                    // _super and _superApply handle keeping the right this-context
                    this._superApply(arguments);
                    this._refresh();
                },

                // _setOption is called for each individual option that is changing
                _setOption: function (key, value) {
                    // prevent invalid color values
                    if (/red|green|blue/.test(key) && (value < 0 || value > 255)) {
                        return;
                    }
                    this._super(key, value);
                }
            });

            // initialize with default options
            $('#my-widget1').colorize();

            // initialize with two customized options
            $('#my-widget2').colorize({
                red: 60,
                blue: 60
            });

            // initialize with custom green value
            // and a random callback to allow only colors with enough green
            $('#my-widget3').colorize({
                green: 128,
                random: function (event, ui) {
                    return ui.green > 128;
                }
            });

            // click to toggle enabled/disabled
            $('#disable').click(function () {
                // use the custom selector created for each widget to find all instances
                // all instances are toggled together, so we can check the state from the first
                if ($(':custom-colorize').colorize('option', 'disabled')) {
                    $(':custom-colorize').colorize('enable');
                } else {
                    $(':custom-colorize').colorize('disable');
                }
            });

            // click to set options after initialization
            $('#black').click(function () {
                $(':custom-colorize').colorize('option', {
                    red: 0,
                    green: 0,
                    blue: 0
                });
            });
        });
    </script>
</head>
<body>

<div>
    <div id='my-widget1'>color me</div>
    <div id='my-widget2'>color me</div>
    <div id='my-widget3'>color me</div>
    <button id='disable'>Toggle disabled option</button>
    <button id='black'>Go black</button>
</div>

</body>
</html>
Try The Code

jQuery UI & Utilities: Image cycler

This entry is part 3 of 3 in the series jQuery UI Utilities

jQuery UI Position – Image Cycler

A photoviewer prototype using Position to place images at the center, left and right and cycle them. 
Use the links at the top to cycle, or click on the images on the left and right. 
Note how the images are repositioned when resizing the window.

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>jQuery UI Position - Image Cycler</title>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
    <script src="//code.jquery.com/jquery-1.10.2.js"></script>
    <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
    <link rel='stylesheet' href='https://codecrawl.com/code/jqueryui/jqueryui_style.css'>
    <style>
        body {
            margin: 0;
        }
        #container {
            overflow: hidden;
            position: relative;
            height: 400px;
        }

        img {
            position: absolute;
        }
    </style>
    <script>
        $(function() {
            // TODO refactor into a widget and get rid of these plugin methods
            $.fn.left = function( using ) {
                return this.position({
                    my: "right middle",
                    at: "left+25 middle",
                    of: "#container",
                    collision: "none",
                    using: using
                });
            };
            $.fn.right = function( using ) {
                return this.position({
                    my: "left middle",
                    at: "right-25 middle",
                    of: "#container",
                    collision: "none",
                    using: using
                });
            };
            $.fn.center = function( using ) {
                return this.position({
                    my: "center middle",
                    at: "center middle",
                    of: "#container",
                    using: using
                });
            };

            $( "img:eq(0)" ).left();
            $( "img:eq(1)" ).center();
            $( "img:eq(2)" ).right();

            function animate( to ) {
                $( this ).stop( true, false ).animate( to );
            }
            function next( event ) {
                event.preventDefault();
                $( "img:eq(2)" ).center( animate );
                $( "img:eq(1)" ).left( animate );
                $( "img:eq(0)" ).right().appendTo( "#container" );
            }
            function previous( event ) {
                event.preventDefault();
                $( "img:eq(0)" ).center( animate );
                $( "img:eq(1)" ).right( animate );
                $( "img:eq(2)" ).left().prependTo( "#container" );
            }
            $( "#previous" ).click( previous );
            $( "#next" ).click( next );

            $( "img" ).click(function( event ) {
                $( "img" ).index( this ) === 0 ? previous( event ) : next( event );
            });

            $( window ).resize(function() {
                $( "img:eq(0)" ).left( animate );
                $( "img:eq(1)" ).center( animate );
                $( "img:eq(2)" ).right( animate );
            });
        });
    </script>
</head>
<body>

<div id="container">
    <img src="http://jqueryui.com/resources/demos/position/images/earth.jpg" width="458" height="308" alt="earth">
    <img src="http://jqueryui.com/resources/demos/position/images/flight.jpg" width="512" height="307" alt="flight">
    <img src="http://jqueryui.com/resources/demos/position/images/rocket.jpg" width="300" height="353" alt="rocket">

    <a id="previous" href="#">Previous</a>
    <a id="next" href="#">Next</a>
</div>

</body>
</html>
Try The Code

jQuery UI & Utilities: Position

This entry is part 1 of 3 in the series jQuery UI Utilities

jQuery UI Position – Default functionality

Use the form controls to configure the positioning, or drag the positioned element to modify its offset. 
Drag around the parent element to see collision detection in action.

<!doctype html>
<html lang='en'>
<head>
    <meta charset='utf-8'>
    <title>jQuery UI Position - Default functionality</title>
    <link rel='stylesheet' href='//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css'>
    <script src='//code.jquery.com/jquery-1.10.2.js'></script>
    <script src='//code.jquery.com/ui/1.10.4/jquery-ui.js'></script>
    <link rel='stylesheet' href='https://codecrawl.com/code/jqueryui/jqueryui_style.css'>
    <style>
        #parent {
            width: 60%;
            height: 40px;
            margin: 10px auto;
            padding: 5px;
            border: 1px solid #777;
            background-color: #fbca93;
            text-align: center;
        }

        .positionable {
            position: absolute;
            display: block;
            right: 0;
            bottom: 0;
            background-color: #bcd5e6;
            text-align: center;
        }

        #positionable1 {
            width: 75px;
            height: 75px;
        }

        #positionable2 {
            width: 120px;
            height: 40px;
        }

        select, input {
            margin-left: 15px;
        }
    </style>
    <script>
        $(function () {
            function position() {
                $('.positionable').position({
                    of: $('#parent'),
                    my: $('#my_horizontal').val() + ' ' + $('#my_vertical').val(),
                    at: $('#at_horizontal').val() + ' ' + $('#at_vertical').val(),
                    collision: $('#collision_horizontal').val() + ' ' + $('#collision_vertical').val()
                });
            }

            $('.positionable').css('opacity', 0.5);

            $('select, input').bind('click keyup change', position);

            $('#parent').draggable({
                drag: position
            });

            position();
        });
    </script>
</head>
<body>

<div id='parent'>
    <p>
        This is the position parent element.
    </p>
</div>

<div class='positionable' id='positionable1'>
    <p>
        to position
    </p>
</div>

<div class='positionable' id='positionable2'>
    <p>
        to position 2
    </p>
</div>

<div style='padding: 20px; margin-top: 75px;'>
    position...
    <div style='padding-bottom: 20px;'>
        <b>my:</b>
        <select id='my_horizontal'>
            <option value='left'>left</option>
            <option value='center'>center</option>
            <option value='right'>right</option>
        </select>
        <select id='my_vertical'>
            <option value='top'>top</option>
            <option value='center'>center</option>
            <option value='bottom'>bottom</option>
        </select>
    </div>
    <div style='padding-bottom: 20px;'>
        <b>at:</b>
        <select id='at_horizontal'>
            <option value='left'>left</option>
            <option value='center'>center</option>
            <option value='right'>right</option>
        </select>
        <select id='at_vertical'>
            <option value='top'>top</option>
            <option value='center'>center</option>
            <option value='bottom'>bottom</option>
        </select>
    </div>
    <div style='padding-bottom: 20px;'>
        <b>collision:</b>
        <select id='collision_horizontal'>
            <option value='flip'>flip</option>
            <option value='fit'>fit</option>
            <option value='flipfit'>flipfit</option>
            <option value='none'>none</option>
        </select>
        <select id='collision_vertical'>
            <option value='flip'>flip</option>
            <option value='fit'>fit</option>
            <option value='flipfit'>flipfit</option>
            <option value='none'>none</option>
        </select>
    </div>
</div>

</body>
</html>
Try The Code

jQuery UI & Autocomplete: Scrollable results

This entry is part 2 of 7 in the series jQuery UI Autocomplete

jQuery UI Autocomplete – Scrollable results

When displaying a long list of options, you can simply set the max-height for the autocomplete menu to prevent the menu from growing too large.

Try typing “a” or “s” above to get a long list of results that you can scroll through.

<!doctype html>
<html lang='en'>
<head>
    <meta charset='utf-8'>
    <title>jQuery UI Autocomplete - Scrollable results</title>
    <link rel='stylesheet' href='//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css'>
    <script src='//code.jquery.com/jquery-1.10.2.js'></script>
    <script src='//code.jquery.com/ui/1.10.4/jquery-ui.js'></script>
    <link rel='stylesheet' href='https://codecrawl.com/code/jqueryui/jqueryui_style.css'>
    <style>
        .ui-autocomplete {
            max-height: 100px;
            overflow-y: auto;
            /* prevent horizontal scrollbar */
            overflow-x: hidden;
        }

        /* IE 6 doesnt support max-height
         * we use height instead, but this forces the menu to always be this tall
         */
        * html .ui-autocomplete {
            height: 100px;
        }
    </style>
    <script>
        $(function () {
            var availableTags = [
                'ActionScript',
                'AppleScript',
                'Asp',
                'BASIC',
                'C',
                'C++',
                'Clojure',
                'COBOL',
                'ColdFusion',
                'Erlang',
                'Fortran',
                'Groovy',
                'Haskell',
                'Java',
                'JavaScript',
                'Lisp',
                'Perl',
                'PHP',
                'Python',
                'Ruby',
                'Scala',
                'Scheme'
            ];
            $('#tags').autocomplete({
                source: availableTags
            });
        });
    </script>
</head>
<body>

<div class='ui-widget'>
    <label for='tags'>Tags: </label>
    <input id='tags'>
</div>

</body>
</html>
Try The Code

jQuery UI & Autocomplete: Combo box

This entry is part 4 of 7 in the series jQuery UI Autocomplete

jQuery UI Autocomplete – Combobox

A custom widget built by composition of Autocomplete and Button.

You can either type something into the field to get filtered suggestions based on your input, or use the button to get the full list of selections.

The input is read from an existing select-element for progressive enhancement, passed to Autocomplete with a customized source-option.

This is not a supported or even complete widget. Its purely for demoing what autocomplete can do with a bit of customization.

<!doctype html>
<html lang='en'>
<head>
    <meta charset='utf-8'>
    <title>jQuery UI Autocomplete - Combobox</title>
    <link rel='stylesheet' href='//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css'>
    <script src='//code.jquery.com/jquery-1.10.2.js'></script>
    <script src='//code.jquery.com/ui/1.10.4/jquery-ui.js'></script>
    <link rel='stylesheet' href='https://codecrawl.com/code/jqueryui/jqueryui_style.css'>
    <style>
        .custom-combobox {
            position: relative;
            display: inline-block;
        }

        .custom-combobox-toggle {
            position: absolute;
            top: 0;
            bottom: 0;
            margin-left: -1px;
            padding: 0;
            /* support: IE7 */
            *height: 1.7em;
            *top: 0.1em;
        }

        .custom-combobox-input {
            margin: 0;
            padding: 0.3em;
        }
    </style>
    <script>
        (function ($) {
            $.widget('custom.combobox', {
                _create: function () {
                    this.wrapper = $('<span>')
                            .addClass('custom-combobox')
                            .insertAfter(this.element);

                    this.element.hide();
                    this._createAutocomplete();
                    this._createShowAllButton();
                },

                _createAutocomplete: function () {
                    var selected = this.element.children(':selected'),
                            value = selected.val() ? selected.text() : '';

                    this.input = $('<input>')
                            .appendTo(this.wrapper)
                            .val(value)
                            .attr('title', '')
                            .addClass('custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left')
                            .autocomplete({
                                delay: 0,
                                minLength: 0,
                                source: $.proxy(this, '_source')
                            })
                            .tooltip({
                                tooltipClass: 'ui-state-highlight'
                            });

                    this._on(this.input, {
                        autocompleteselect: function (event, ui) {
                            ui.item.option.selected = true;
                            this._trigger('select', event, {
                                item: ui.item.option
                            });
                        },

                        autocompletechange: '_removeIfInvalid'
                    });
                },

                _createShowAllButton: function () {
                    var input = this.input,
                            wasOpen = false;

                    $('<a>')
                            .attr('tabIndex', -1)
                            .attr('title', 'Show All Items')
                            .tooltip()
                            .appendTo(this.wrapper)
                            .button({
                                icons: {
                                    primary: 'ui-icon-triangle-1-s'
                                },
                                text: false
                            })
                            .removeClass('ui-corner-all')
                            .addClass('custom-combobox-toggle ui-corner-right')
                            .mousedown(function () {
                                wasOpen = input.autocomplete('widget').is(':visible');
                            })
                            .click(function () {
                                input.focus();

                                // Close if already visible
                                if (wasOpen) {
                                    return;
                                }

                                // Pass empty string as value to search for, displaying all results
                                input.autocomplete('search', '');
                            });
                },

                _source: function (request, response) {
                    var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), 'i');
                    response(this.element.children('option').map(function () {
                        var text = $(this).text();
                        if (this.value && ( !request.term || matcher.test(text) ))
                            return {
                                label: text,
                                value: text,
                                option: this
                            };
                    }));
                },

                _removeIfInvalid: function (event, ui) {

                    // Selected an item, nothing to do
                    if (ui.item) {
                        return;
                    }

                    // Search for a match (case-insensitive)
                    var value = this.input.val(),
                            valueLowerCase = value.toLowerCase(),
                            valid = false;
                    this.element.children('option').each(function () {
                        if ($(this).text().toLowerCase() === valueLowerCase) {
                            this.selected = valid = true;
                            return false;
                        }
                    });

                    // Found a match, nothing to do
                    if (valid) {
                        return;
                    }

                    // Remove invalid value
                    this.input
                            .val('')
                            .attr('title', value + ' didnt match any item')
                            .tooltip('open');
                    this.element.val('');
                    this._delay(function () {
                        this.input.tooltip('close').attr('title', '');
                    }, 2500);
                    this.input.data('ui-autocomplete').term = '';
                },

                _destroy: function () {
                    this.wrapper.remove();
                    this.element.show();
                }
            });
        })(jQuery);

        $(function () {
            $('#combobox').combobox();
            $('#toggle').click(function () {
                $('#combobox').toggle();
            });
        });
    </script>
</head>
<body>

<div class='ui-widget'>
    <label>Your preferred programming language: </label>
    <select id='combobox'>
        <option value=''>Select one...</option>
        <option value='ActionScript'>ActionScript</option>
        <option value='AppleScript'>AppleScript</option>
        <option value='Asp'>Asp</option>
        <option value='BASIC'>BASIC</option>
        <option value='C'>C</option>
        <option value='C++'>C++</option>
        <option value='Clojure'>Clojure</option>
        <option value='COBOL'>COBOL</option>
        <option value='ColdFusion'>ColdFusion</option>
        <option value='Erlang'>Erlang</option>
        <option value='Fortran'>Fortran</option>
        <option value='Groovy'>Groovy</option>
        <option value='Haskell'>Haskell</option>
        <option value='Java'>Java</option>
        <option value='JavaScript'>JavaScript</option>
        <option value='Lisp'>Lisp</option>
        <option value='Perl'>Perl</option>
        <option value='PHP'>PHP</option>
        <option value='Python'>Python</option>
        <option value='Ruby'>Ruby</option>
        <option value='Scala'>Scala</option>
        <option value='Scheme'>Scheme</option>
    </select>
</div>
<button id='toggle'>Show underlying select</button>


</body>
</html>
Try The Code