📜 ⬆️ ⬇️

jQuery custom radio and checkbox

As usual, it all started because of the absence or poor search, or the incomplete realization of what I needed.
And I needed custom radio and checkboxes that I could use in my daily work during layout. However, they would have to work in IE6 + and all major browsers.
Also, the elements had to respond by clicking on the label. And one more of them could be on page 1 as many as you like with different styles (yes, sometimes such mego designs occur).
So I decided to take all the best that I met in the implementations of checkboxes and radio bats on JS. And write your own jQuery plugin that would satisfy my needs.

The appearance of the elements was realized using a sprite with 4 states:
- inactive view;
- inactive mouse is pressed;
- active;
- active mouse is pressed.
image

Because You will have to work with the sprite, you need to know the vertical blending of images in it. To do this, you must transfer the height of the element to the plugin, and in the sprite arrange them so that they occupy the same height space.
It is also necessary that when calling the plugin a class is passed, through which I can stylize the element.
After the initial implementation, I realized that a couple more conditions are needed, without which the plugin will not work correctly. This is the ability to change the state of elements (actinous / inactive) and stylize dynamically created elements.

I will give for the beginning all code of a plug-in:
')
(function ($) { $.CustomData = { elements:$() }; $.fn.extend({ Custom:function (options) { var elements = this; $.CustomData.elements = $.CustomData.elements.add(elements); /*  */ var defaults = { customStyleClass:"checkbox", customHeight:"16" }; /*       */ options = $.extend(defaults, options); /*       */ var pushed = function () { var element = $(this).children('input'); if (element.is(':checked')) { /*  */ $(this).css('backgroundPosition', "0px -" + options.customHeight * 3 + "px"); } else { $(this).css('backgroundPosition', "0px -" + options.customHeight + "px"); } }; /*     ,    (radio)*/ var check = function () { var element = $(this).children('input'); if (element.is(':checked') && element.attr('type') === 'checkbox') {/* */ $(this).css('backgroundPosition', '0px 0px'); $(this).children('input').attr('checked', false).change(); /*         */ } else { if (element.attr('type') === 'checkbox') {/* */ $(this).css('backgroundPosition', "0px -" + options.customHeight * 2 + "px"); } else { /**/ $(this).css('backgroundPosition', "0px -" + options.customHeight * 2 + "px"); $('input[name=' + element.attr('name') + ']').not(element).parent().css('backgroundPosition', '0px 0px'); } $(this).children('input').attr('checked', 'checked').change(); } }; /*        */ var update = function () { $.CustomData.elements.each(function () { /*       */ if ($(this).is(':checked')) { $(this).parent().css('backgroundPosition', "0px -" + $(this).attr('data-height') * 2 + "px"); } else { $(this).parent().css('backgroundPosition', "0px 0px"); } }); }; /*    disabled/enabled */ var refresh = function () { if (!$(this).prop('disabled')) { $(this).parent().mousedown(pushed); $(this).parent().mouseup(check); $(this).parent().removeClass('disabled'); } else { $(this).parent().addClass('disabled'); $(this).parent().unbind('mousedown', pushed); $(this).parent().unbind('mouseup', check); } }; return this.each(function () { if ($(this).attr('data-init') != '1') { $(this).attr('data-init', '1'); $(this).attr('data-height', options.customHeight); /*  <span></span>*/ $(this).wrap('<span/>'); /*     */ var span = $(this).parent().addClass(options.customStyleClass); if ($(this).is(':checked') === true) { /*    */ span.css('backgroundPosition', "0px -" + (options.customHeight * 2) + "px"); } /*              */ $(this).bind('change', update); $(this).bind('custom.refresh', refresh); if (!$(this).prop('disabled')) { /*   span*/ span.mousedown(pushed); span.mouseup(check); } else { /*    */ span.addClass('disabled'); } } }); } }); })(jQuery); 

I started with the implementation of the plugin structure, and it looks like this:

 (function ($) { $.fn.extend({ Custom:function (options) { /*  */ var defaults = { customStyleClass:"checkbox", customHeight:"16" }; /*       */ options = $.extend(defaults, options); }; return this.each(function () { }); } }); 

You can find such a description of the above printed - "used to create a typical jQuery add-on."

Let's start from the end:

 return this.each(function () { if ($(this).attr('data-init') != '1') { $(this).attr('data-init', '1'); $(this).attr('data-height', options.customHeight); /*  <span></span>*/ $(this).wrap('<span/>'); /*     */ var span = $(this).parent().addClass(options.customStyleClass); if ($(this).is(':checked') === true) { /*    */ span.css('backgroundPosition', "0px -" + (options.customHeight * 2) + "px"); } /*              */ $(this).bind('change', update); $(this).bind('custom.refresh', refresh); if (!$(this).prop('disabled')) { /*   span*/ span.mousedown(pushed); span.mouseup(check); } else { /*    */ span.addClass('disabled'); } } }); 

In principle, in the comments to the code everything is described, I can add only
 $(this).attr('data-init', '1'); 

I use it in order to know whether the element is already stylized or not (of course you can find out through a parent, but I decided to test such a method).

 $(this).attr('data-height', options.customHeight); 

Here I save the height of the element. I can have as many elements as possible with various sprites.

 $(this).bind('custom.refresh', refresh); 

Also an interesting method, is bound to the custom event “custom.refresh” by calling the refresh function.
For example, the state of an element has changed to inactive, then it is necessary to change the appearance of elements and remove all events from it.
For example:
 $('#radio3').removeAttr('disabled').trigger('custom.refresh'); 

the element became inactive and the custom.refresh event occurred due to which the refresh function was executed.

Next are the functions that are described in this part:
 Custom:function (options) {...}; 

The function pushed - puts the offset in the sprite for the active and inactive view, it is quite simple:

 var pushed = function () { var element = $(this).children('input'); if (element.is(':checked')) { /*  */ $(this).css('backgroundPosition', "0px -" + options.customHeight * 3 + "px"); } else { $(this).css('backgroundPosition', "0px -" + options.customHeight + "px"); } }; 

Check function :

 /*     ,     (radio)*/ var check = function () { var element = $(this).children('input'); if (element.is(':checked') && element.attr('type') === 'checkbox') {/* */ $(this).css('backgroundPosition', '0px 0px'); $(this).children('input').attr('checked', false).change(); /*         */ } else { if (element.attr('type') === 'checkbox') {/* */ $(this).css('backgroundPosition', "0px -" + options.customHeight * 2 + "px"); } else { /**/ $(this).css('backgroundPosition', "0px -" + options.customHeight * 2 + "px"); $('input[name=' + element.attr('name') + ']').not(element).parent().css('backgroundPosition', '0px 0px'); } $(this).children('input').attr('checked', 'checked').change(); } }; 

Also, everything is pretty clear from the comments in the code I will add only about this.
 $(this).children('input').attr('checked', false).change(); 

.attr ('checked', false) .change () - it is necessary that the change () event be fixed and the checked attribute be changed. I had to look for it on stackoverflow.

Update function:

 /*     */ var update = function () { $.CustomData.elements.each(function () { /*       */ if ($(this).is(':checked')) { $(this).parent().css('backgroundPosition', "0px -" + $(this).attr('data-height') * 2 + "px"); } else { $(this).parent().css('backgroundPosition', "0px 0px"); } }); }; 

It did not go without a variable where you could save all the elements on which the plugin is called ($. CustomData.elements). It is described above $ .fn.extend ({...})

 $.CustomData = { elements:$() }; 


and when you call a plugin in it is placed a set of elements

 var elements = this; $.CustomData.elements = $.CustomData.elements.add(elements); 


And the last function that is needed when the state of the refresh element changes:

 /*    disabled/enabled */ var refresh = function () { if (!$(this).prop('disabled')) { $(this).parent().mousedown(pushed); $(this).parent().mouseup(check); $(this).parent().removeClass('disabled'); } else { $(this).parent().addClass('disabled'); $(this).parent().unbind('mousedown', pushed); $(this).parent().unbind('mouseup', check); } }; 


Pretty simple to understand, just remove the handlers or add again and append / remove the class “disabled”, through which you can set the appearance of the element in an inactive state (usually change the transparency).

An example of a class describing the type of radiobath
 .radio { display:block; height: 25px; width: 19px; overflow:hidden; background: url("radio.png") no-repeat 0 0 transparent; position:relative; } .radio.disabled{ opacity:0.5; filter:Alpha(opacity="50"); } .radio input{ position:absolute; right:-400px; top:0px; } 


Plugin call:
 $("input[type='radio']").Custom({ customStyleClass:'radio', customHeight:'25' }); 


I hope this helps people like me in writing my first jQuery plugins.

This is all I wanted to tell in connection with my poor search for the plugin I needed. I thank the good man Andrew for his help in knowing jQuery and writing the plugin as well as the developer of this plugin http://ryanfait.com/resources/custom-checkboxes-and-radio-buttons/ for being on js and not fully finished , giving me the opportunity to write my own with the necessary chips. I would be glad to comment and criticism to improve the work of the planin.

The plugin is here https://github.com/n0r8/Custom-radio-checkbox

Source: https://habr.com/ru/post/142182/


All Articles