Archive

Archive for the ‘jquery’ Category

JQuery: Button to cycle through select options

November 9, 2014 Leave a comment

I wanted an html drop-down list to automatically appear as a simple button that changes color on every click as it cycles through the option values of the (hidden) select element.

The code sample is in this jsfiddle. It uses JQuery.

For each relevant select element, it styles the associated label so it looks like a button, hides the select element and handles clicks on the label button by cycling through the select options.

The display text of each option is used as a tooltip (‘title’ attribute) of the button which also serves as a css selector to color the button according to currently selected option.

The beauty of this is that the selected values of the hidden drop-downs can be submitted by regular form submit and that the form is fully functional if JavaScript is turned off.

The button styling requires CSS3, so IE8 is not suitable. I have tested this successfully in Firefox 33 and IE11.

Categories: css, html, jquery Tags: , ,

Autocomplete combobox using JQuery UI

July 11, 2012 10 comments

Disclaimer, Sept 2013: The following worked for me with an older JQuery version, but not with 1.9 or later. The code is provided as is and might be useful for some people, but due to time constraints I cannot assist with problems you might run into.

The example at http://jqueryui.com/demos/autocomplete/combobox.html illustrates how you can use JQuery UI to turn any HTML <select> element into an auto-complete combobox.

Auto-complete means in this context that the select options are narrowed down by what the user has typed in so far.

The example has a few bugs and shortcomings, some of which have been fixed here. I build on this work and further fixed it up to support dynamic updates of the options list through event-triggered AJAX calls. You can find the source code of the resulting JQuery UI auto-complete combobox widget at the end of this post.

Expose it to your webapp as includes/js/combobox.js and include it from your HTML or JSP page like this (adjust the path according to your JQuery UI installation):

<script type="text/javascript" src="includes/js/jquery-ui-1.8.4/js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="includes/js/jquery-ui-1.8.4/js/jquery-ui-1.8.4.custom.min.js"></script>
<script type="text/javascript" src="includes/js/combobox.js"></script>

And let’s say your <select> component looks like this:

<select id="mySelect">
  <option value="1">one</option>
  <option value="2">two</option>
  <option value="3">three</option>
  <!-- etc. -->
</select>

Then make it an auto-complete combobox widget like this:

$(document).ready(function() {
   $("#mySelect").combobox();
}

You can update the options dynamically using JQuery’s load() function, typically triggered by an event. The interesting part is that I implemented the internal _create() and _init() functions of the widget so that reinitialization through additional calls to combobox() are supported:

$("#mySelect").load(
    "dataRequest.do", // this has to be your own AJAX handler that generates the new options as HTML
    function() { // this callback function is invoked after the AJAX call has returned
        // then refresh the combobox widget (to use the updated options)
        $("#mySelect").combobox();
    }
);
/*
 Based on code from
 http://www.melrosesolutions.com/blog/index.cfm/2010/7/16/Turn-SELECTs-into-Comboboxes-with-jQuery-UI-Autocomplete
 */

(function($) {

    $.widget("ui.combobox", {

        _create: function() {
            var select = this.element;

            if (select.is(":disabled") 
                    || select.hasClass("inputOverlayCreated")) {
                return;
            }

            select.hide();

            // set up input text element
            var input = $("<input type='text'>");
            input.insertAfter(select);

            // remember that combobox is creates (to avoid odd duplicates)
            select.addClass("inputOverlayCreated");

            // the class ui-combobox-content is required for proper
            // highlighting of data changes
            input.addClass("ui-combobox-content ui-widget ui-corner-left");

            //clear text when user clicks in text input
            input.click(function() {
                $(this).val("");
            });

            input.attr("menustatus", "closed");

            // over-ride form submit, so it can't submit
            // if the menu is open
            var form = $(input).parents('form:first');
            $(form).submit(function(e) {
                return (input.attr('menustatus') == 'closed');
            });

            // set up button for fake 'select'
            var btn = $("<button>&nbsp;</button>");
            btn.attr("tabIndex", -1);
            btn.attr("title", "Show All Items");
            btn.insertAfter(input);
            btn.button({
                icons: {
                    primary: "ui-icon-triangle-1-s"
                },
                text: false
            });
            btn.removeClass("ui-corner-all");
            btn.addClass("ui-corner-right ui-button-icon");
            btn.click(function() {
                //event.preventDefault();
                // close if already visible
                if (input.autocomplete("widget").is(":visible")) {
                    input.autocomplete("close");
                    return false; // return false, so form isn't automatically submitted
                }
                // pass empty string as value to search for, displaying all results
                input.autocomplete("search", "");
                input.focus();
                return false; // return false, so form isn't automatically submitted
            });

            // add some styles
            btn.css("margin-left", "-1px");
            btn.css("padding", 0);
            $('span.ui-button-text', btn).css("padding", 0);

            input.css("margin", 0);
            input.css("padding", "0 0.4em 0 0.4em");
            input.css("width", select.outerWidth() - btn.outerWidth(true) - 10);// match the width
        },

        _init : function() {
            var select = this.element;

            if (select.is(":disabled")) {
                // we don't apply any fancy combobox behaviour at all
                // if the underlying drop-down list is disabled
                return;
            }

            var opts = new Array();
            $('option', select).each(function(index) {
                var opt = new Object();
                opt.val = $(this).val();
                opt.label = $(this).text();
                opts[opts.length] = opt;
            });

            var input = select.next();

            // initialise text with what's currently selected
            input.val($(':selected', select).text());

            input.autocomplete({
                source: opts,
                delay: 0,
                change: function(event, ui) {
                    if (!ui.item) {
                        // user didn't select an option, but what they typed may still match
                        var enteredString = $(this).val();
                        var stringMatch = false;
                        for (var i = 0; i < opts.length; i++) {
                            if (opts[i].label.toLowerCase() == enteredString.toLowerCase()) {
                                select.val(opts[i].val);// update (hidden) select
                                $(this).val(opts[i].label);// corrects any incorrect case
                                select.trigger("change");
                                stringMatch = true;
                                break;
                            }
                        }
                        if (!stringMatch) {
                            // remove invalid value, as it didn't match anything
                            $(this).val($(':selected', select).text());
                        }
                        return true;
                    }
                },
                select: function(event, ui) {
                    select.val(ui.item.val);// update (hidden) select
                    select.trigger("change");
                    return true;
                },
                // stop parent form from being while menu is open
                open: function(event, ui) {
                    input.attr("menustatus", "open");
                },
                close: function(event, ui) {
                    input.attr("menustatus", "closed");
                },
                minLength: 0
            });
        }
    });

})(jQuery);
Categories: jquery

Export HTML table as CSV file using JQuery

April 9, 2012 23 comments

Put this code into a script section into a common HTML head include file:

$(document).ready(function() {

  $('table').each(function() {
    var $table = $(this);

    var $button = $("<button type='button'>");
    $button.text("Export to spreadsheet");
    $button.insertAfter($table);

    $button.click(function() {
      var csv = $table.table2CSV({delivery:'value'});
      window.location.href = 'data:text/csv;charset=UTF-8,'
                            + encodeURIComponent(csv);
    });
  });
})

Note:

Categories: jquery

JQuery DataTables column filters state saving

December 12, 2011 1 comment

The JQuery DataTables plugin supports state saving for column filters. But it does not automatically set the column filter values to the saved values when the user navigates to a page that has saved filter state.

I saw the code suggested here and cleaned it up a little (for example, using the oSettings parameter of the fnInitComplete function).

$(document).ready(function() {

        var oTable = $('#REPLACE_THIS_WITH_TABLE_ID').dataTable({
            "bStateSave": true,
            "fnInitComplete": function(oSettings, json) {
                var cols = oSettings.aoPreSearchCols;
                for (var i = 0; i < cols.length; i++) {
                    var value = cols[i].sSearch;
                    if (value.length > 0) {
                        $("tfoot input")[i].value = value;
                    }
                }
            }
        });

        $("tfoot input").keyup(function () {
            oTable.fnFilter(this.value, $("tfoot input").index(this));
        });
    });

Please note that I completely removed all code that supported initial display texts in the filter fields (because I don’t use that).

Categories: jquery