سؤال

I did mockups in balsamiq & they have this nice widget, which

  • Allowed to select a value, out of two values. Works really nicely on touchscreens
  • Can be used to Display two values & highlighting the selected one

Example: Widget

What the options to implement a widget similar to shown in picture via HTML/CSS & JS?

هل كانت مفيدة؟

المحلول

The approach I present below iterates through all fieldset elements, and if all the inputs therein are of type="radio", hides them and appends span elements (of class="buttonRadio") in their place, using the text from their relevant label elements. It also binds click events to the appended span elements, and triggers the change event on the original inputs and also adds the 'checked' class-name to the clicked/touched element, while removing that class it from its siblings:

$('fieldset').each(
    function() {
        var legend = $(this).find('legend').text();
        if ($(this).find('input').length == $(this).find('input[type="radio"]').length) {
            var that = $(this),
                len = that.find('input[type="radio"]').length;
            for (var i = 0; i < len; i++) {
                $('<span />')
                    .text($('label')
                          .eq(i).text())
                    .addClass('buttonRadio')
                    .attr('data-fromID',that.find('input:eq(' + i + ')').attr('id'))
                    .appendTo(that);
            }
        }
    }).on('click','.buttonRadio',function(){
        var id = $(this).attr('data-fromID');
        $(this).addClass('checked').siblings().removeClass('checked');
        $('#' + id).click().trigger('change');
    }).find('label, input[type="radio"]').css('display','none');​

This uses the following CSS to style those elements:

.buttonRadio {
    background-color: #fff;
    padding: 0.5em 1em;
    border: 1px solid #000;
    margin: 0.5em 0 0 0;
}

.buttonRadio.checked {
    background-color: #ffa;
}​

JS Fiddle demo.


Edited to amend the jQuery a little:

  1. cached the $(this) object a little earlier in this version,
  2. remembered to use the legend variable that I assigned in the first incarnation but forgot to actually use...sigh.
  3. also hid the actual <legend></legend> element:

    $('fieldset').each(
        function() {
            var that = $(this),
                legend = that.find('legend').text();
            $('<span />').text(legend).addClass('legend').appendTo(that);
            if (that.find('input').length == that.find('input[type="radio"]').length) {
                var len = that.find('input[type="radio"]').length;
                for (var i = 0; i < len; i++) {
                    $('<span />')
                        .text($('label')
                          .eq(i).text())
                        .addClass('buttonRadio')
                        .attr('data-fromID',that.find('input:eq(' + i + ')').attr('id'))
                        .appendTo(that);
                }
            }
        }).on('click','.buttonRadio',function(){
            var id = $(this).attr('data-fromID');
            $(this).addClass('checked').siblings().removeClass('checked');
            $('#' + id).click().trigger('change');
        }).find('label, input[type="radio"], legend').css('display','none');​
    

JS Fiddle demo.

References:

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top