123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- /* ShiftCheckbox jQuery plugin
- *
- * Copyright (C) 2011-2012 James Nylen
- *
- * Released under MIT license
- * For details see:
- * https://github.com/nylen/shiftcheckbox
- *
- * Requires jQuery v1.7 or higher.
- */
- (function($) {
- var ns = '.shiftcheckbox';
- $.fn.shiftcheckbox = function(opts) {
- opts = $.extend({
- checkboxSelector : null,
- selectAll : null,
- onChange : null,
- ignoreClick : null
- }, opts);
- if (typeof opts.onChange != 'function') {
- opts.onChange = function(checked) { };
- }
- $.fn.scb_changeChecked = function(opts, checked) {
- this.prop('checked', checked);
- opts.onChange.call(this, checked);
- return this;
- }
- var $containers,
- $checkboxes,
- $containersSelectAll,
- $checkboxesSelectAll,
- $otherSelectAll,
- $containersAll,
- $checkboxesAll;
- if (opts.selectAll) {
- // We need to set up a "select all" control
- $containersSelectAll = $(opts.selectAll);
- if ($containersSelectAll && !$containersSelectAll.length) {
- $containersSelectAll = false;
- }
- }
- if ($containersSelectAll) {
- $checkboxesSelectAll = $containersSelectAll
- .filter(':checkbox')
- .add($containersSelectAll.find(':checkbox'));
- $containersSelectAll = $containersSelectAll.not(':checkbox');
- $otherSelectAll = $containersSelectAll.filter(function() {
- return !$(this).find($checkboxesSelectAll).length;
- });
- $containersSelectAll = $containersSelectAll.filter(function() {
- return !!$(this).find($checkboxesSelectAll).length;
- }).each(function() {
- $(this).data('childCheckbox', $(this).find($checkboxesSelectAll)[0]);
- });
- }
- if (opts.checkboxSelector) {
- // checkboxSelector means that the elements we need to attach handlers to
- // ($containers) are not actually checkboxes but contain them instead
- $containersAll = this.filter(function() {
- return !!$(this).find(opts.checkboxSelector).filter(':checkbox').length;
- }).each(function() {
- $(this).data('childCheckbox', $(this).find(opts.checkboxSelector).filter(':checkbox')[0]);
- }).add($containersSelectAll);
- $checkboxesAll = $containersAll.map(function() {
- return $(this).data('childCheckbox');
- });
- } else {
- $checkboxesAll = this.filter(':checkbox');
- }
- if ($checkboxesSelectAll && !$checkboxesSelectAll.length) {
- $checkboxesSelectAll = false;
- } else {
- $checkboxesAll = $checkboxesAll.add($checkboxesSelectAll);
- }
- if ($otherSelectAll && !$otherSelectAll.length) {
- $otherSelectAll = false;
- }
- if ($containersAll) {
- $containers = $containersAll.not($containersSelectAll);
- }
- $checkboxes = $checkboxesAll.not($checkboxesSelectAll);
- if (!$checkboxes.length) {
- return;
- }
- var lastIndex = -1;
- var checkboxClicked = function(e) {
- var checked = !!$(this).prop('checked');
- var curIndex = $checkboxes.index(this);
- if (curIndex < 0) {
- if ($checkboxesSelectAll.filter(this).length) {
- $checkboxesAll.scb_changeChecked(opts, checked);
- }
- return;
- }
- if (e.shiftKey && lastIndex != -1) {
- var di = (curIndex > lastIndex ? 1 : -1);
- for (var i = lastIndex; i != curIndex; i += di) {
- $checkboxes.eq(i).scb_changeChecked(opts, checked);
- }
- }
- if ($checkboxesSelectAll) {
- if (checked && !$checkboxes.not(':checked').length) {
- $checkboxesSelectAll.scb_changeChecked(opts, true);
- } else if (!checked) {
- $checkboxesSelectAll.scb_changeChecked(opts, false);
- }
- }
- lastIndex = curIndex;
- };
- if ($checkboxesSelectAll) {
- $checkboxesSelectAll
- .prop('checked', !$checkboxes.not(':checked').length)
- .filter(function() {
- return !$containersAll.find(this).length;
- }).on('click' + ns, checkboxClicked);
- }
- if ($otherSelectAll) {
- $otherSelectAll.on('click' + ns, function() {
- var checked;
- if ($checkboxesSelectAll) {
- checked = !!$checkboxesSelectAll.eq(0).prop('checked');
- } else {
- checked = !!$checkboxes.eq(0).prop('checked');
- }
- $checkboxesAll.scb_changeChecked(opts, !checked);
- });
- }
- if (opts.checkboxSelector) {
- $containersAll.on('click' + ns, function(e) {
- if ($(e.target).closest(opts.ignoreClick).length) {
- return;
- }
- var $checkbox = $($(this).data('childCheckbox'));
- $checkbox.not(e.target).each(function() {
- var checked = !$checkbox.prop('checked');
- $(this).scb_changeChecked(opts, checked);
- });
- $checkbox[0].focus();
- checkboxClicked.call($checkbox, e);
- // If the user clicked on a label inside the row that points to the
- // current row's checkbox, cancel the event.
- var $label = $(e.target).closest('label');
- var labelFor = $label.attr('for');
- if (labelFor && labelFor == $checkbox.attr('id')) {
- if ($label.find($checkbox).length) {
- // Special case: The label contains the checkbox.
- if ($checkbox[0] != e.target) {
- return false;
- }
- } else {
- return false;
- }
- }
- }).on('mousedown' + ns, function(e) {
- if (e.shiftKey) {
- // Prevent selecting text by Shift+click
- return false;
- }
- });
- } else {
- $checkboxes.on('click' + ns, checkboxClicked);
- }
- return this;
- };
- })(jQuery);
|