diff options
| author | spiderr <spiderr@bitweaver.org> | 2025-11-24 12:14:19 -0500 |
|---|---|---|
| committer | spiderr <spiderr@bitweaver.org> | 2025-11-24 12:14:19 -0500 |
| commit | 4f8f464db8f781e5a7f5b02812fed64e290fbf45 (patch) | |
| tree | 0bf2cbae0eb918d615e096c18a90aff9e75ed024 /javascript | |
| parent | 052c30d4a6076e803bbb7e78fc785513e9c931f2 (diff) | |
| download | util-4f8f464db8f781e5a7f5b02812fed64e290fbf45.tar.gz util-4f8f464db8f781e5a7f5b02812fed64e290fbf45.tar.bz2 util-4f8f464db8f781e5a7f5b02812fed64e290fbf45.zip | |
add shiftcheckbox multi select to jquery forms
Diffstat (limited to 'javascript')
| -rw-r--r-- | javascript/jquery/plugins/shiftcheckbox/jquery.shiftcheckbox.js | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/javascript/jquery/plugins/shiftcheckbox/jquery.shiftcheckbox.js b/javascript/jquery/plugins/shiftcheckbox/jquery.shiftcheckbox.js new file mode 100644 index 0000000..f2d0121 --- /dev/null +++ b/javascript/jquery/plugins/shiftcheckbox/jquery.shiftcheckbox.js @@ -0,0 +1,196 @@ +/* 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); |
