Skip to content

Commit a359a41

Browse files
committed
Initial commit
Signed-off-by: Oleg Bulatov <[email protected]>
0 parents  commit a359a41

File tree

6 files changed

+366
-0
lines changed

6 files changed

+366
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/

LICENSE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright (C) 2013-2014 Oleg Bulatov
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the
5+
"Software"), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject
9+
to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be
12+
included in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18+
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19+
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# CheckBox Group
2+
3+
Allows to construct analog of `<select multiple>` using sequence of `<input type="checkbox">`.
4+
5+
**Demo** available at <http://dmage.github.io/checkboxgroup/>.
6+
7+
## Usage
8+
9+
$(function () {
10+
$('.checkboxes').checkboxgroup();
11+
});
12+
13+
<div class="checkboxes">
14+
<label><input type="checkbox"> Hello</label>
15+
<label><input type="checkbox"> World</label>
16+
</div>

checkboxgroup.jquery.js

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/*global document, define, jQuery */
2+
'use strict';
3+
(function (factory) {
4+
if (typeof define === 'function' && define.amd) {
5+
define(['jquery'], factory);
6+
} else {
7+
factory(jQuery);
8+
}
9+
}(function ($) {
10+
var doIt = function (opts) {
11+
var $box = $(this),
12+
$items = $('input[type="checkbox"]', $box),
13+
labels = [],
14+
topLevelObjects = [],
15+
$labels,
16+
$topLevelObjects,
17+
prevIdx = 0,
18+
setChecked,
19+
getInputForObject,
20+
mouseActive = false,
21+
mouseMoved,
22+
mouseChecked,
23+
startIdx;
24+
25+
if (!opts) {
26+
opts = {};
27+
}
28+
29+
$items.each(function () {
30+
var $this = $(this),
31+
$label;
32+
33+
if (this.id) {
34+
$label = $('label[for="' + this.id + '"]');
35+
}
36+
if (!$label) {
37+
$label = $this.closest('label');
38+
}
39+
if ($label) {
40+
labels.push($label);
41+
topLevelObjects.push($label);
42+
if ($this.parents().index($label) === -1) {
43+
topLevelObjects.push($this);
44+
}
45+
} else {
46+
topLevelObjects.push($this);
47+
}
48+
});
49+
$labels = $(labels).map(function () { return this.toArray(); });
50+
$topLevelObjects = $(topLevelObjects).map(function () { return this.toArray(); });
51+
52+
setChecked = function (begin, end, checked) {
53+
$items.slice(begin, end).each(function () {
54+
if (this.checked !== checked) {
55+
$(this).trigger('click');
56+
}
57+
});
58+
};
59+
60+
getInputForObject = function (obj) {
61+
if (obj.nodeName === "INPUT") {
62+
return $(obj);
63+
}
64+
65+
var forAttr = $(obj).attr('for'),
66+
input = document.getElementById(forAttr);
67+
if (!input) {
68+
input = $('input[type="checkbox"]', obj).get(0);
69+
}
70+
return $(input);
71+
};
72+
73+
$items.click(function (e) {
74+
var idx = $items.index(this),
75+
a,
76+
b;
77+
78+
if (e.shiftKey) {
79+
if (idx <= prevIdx) {
80+
a = idx;
81+
b = prevIdx;
82+
} else {
83+
a = prevIdx;
84+
b = idx;
85+
}
86+
setChecked(a, b + 1, this.checked);
87+
}
88+
prevIdx = idx;
89+
90+
e.stopPropagation();
91+
});
92+
93+
$labels.click(function (e) {
94+
if (e.originalEvent.detail <= 1) {
95+
return;
96+
}
97+
98+
getInputForObject(this).click();
99+
e.preventDefault();
100+
});
101+
102+
$topLevelObjects.mousedown(function (e) {
103+
var $input = getInputForObject(this),
104+
idx = $items.index($input);
105+
106+
startIdx = idx;
107+
108+
mouseChecked = !$input.get(0).checked;
109+
mouseMoved = false;
110+
mouseActive = true;
111+
112+
e.preventDefault();
113+
});
114+
115+
$box.mouseover(function (e) {
116+
if (!mouseActive) {
117+
return;
118+
}
119+
120+
var $target = $(e.target),
121+
idx = $items.index($target),
122+
findRelated,
123+
$input,
124+
$label,
125+
inputIdx,
126+
labelIdx;
127+
128+
findRelated = function ($target, $items) {
129+
var $ret = $target.find($items).add($target.closest($items));
130+
if ($ret.length === 0 && opts.itemSelector) {
131+
$ret = $target.closest(opts.itemSelector).find($items);
132+
}
133+
return $ret;
134+
};
135+
136+
if (idx === -1) {
137+
$input = findRelated($target, $items);
138+
$label = findRelated($target, $labels);
139+
if ($input.length > 1 || $label.length > 1) {
140+
return; // ambiguous target
141+
}
142+
if ($input.length === 1 && $label.length === 1) {
143+
inputIdx = $items.index($input);
144+
labelIdx = $labels.index($label);
145+
if (inputIdx === labelIdx) {
146+
idx = inputIdx;
147+
}
148+
} else if ($input.length === 1) {
149+
idx = $items.index($input);
150+
} else if ($label.length === 1) {
151+
idx = $labels.index($label);
152+
}
153+
}
154+
if (idx === -1) {
155+
return;
156+
}
157+
158+
if (!mouseMoved) {
159+
prevIdx = startIdx;
160+
mouseMoved = true;
161+
}
162+
163+
if (prevIdx >= startIdx && idx >= prevIdx) {
164+
// console.log('move down');
165+
setChecked(prevIdx, idx + 1, mouseChecked);
166+
} else if (prevIdx <= startIdx && idx < prevIdx) {
167+
// console.log('move up');
168+
setChecked(idx, prevIdx + 1, mouseChecked);
169+
} else if (prevIdx >= startIdx && idx < prevIdx) {
170+
// console.log('recover up');
171+
if (idx >= startIdx) {
172+
setChecked(idx + 1, prevIdx + 1, !mouseChecked);
173+
} else {
174+
setChecked(startIdx + 1, prevIdx + 1, !mouseChecked);
175+
setChecked(idx, startIdx + 1, mouseChecked);
176+
}
177+
} else if (prevIdx <= startIdx && idx > prevIdx) {
178+
// console.log('recover down');
179+
if (idx <= startIdx) {
180+
setChecked(prevIdx, idx, !mouseChecked);
181+
} else {
182+
setChecked(prevIdx, startIdx, !mouseChecked);
183+
setChecked(startIdx, idx + 1, mouseChecked);
184+
}
185+
}
186+
187+
prevIdx = idx;
188+
});
189+
190+
$(document).mouseup(function () {
191+
if (!mouseActive) {
192+
return;
193+
}
194+
195+
mouseActive = false;
196+
});
197+
};
198+
199+
$.fn.checkboxgroup = function (opts) {
200+
return this.each(function () {
201+
doIt.call(this, opts);
202+
});
203+
};
204+
}));

index.html

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<script src="https://yastatic.net/jquery/2.1.1/jquery.min.js"></script>
7+
<script src="checkboxgroup.jquery.js"></script>
8+
<style>
9+
.tag {
10+
background: rgba(0, 255, 0, 0.05);
11+
padding: 3px;
12+
display: inline-block;
13+
border: 1px solid rgba(0, 51, 0, 0.3);
14+
}
15+
.multiselect .group > div {
16+
padding: 5px 7px;
17+
}
18+
.multiselect input {
19+
margin: 0.2em 0.5em 0.2em 0.2em;
20+
}
21+
.multiselect label {
22+
background: rgba(0, 0, 0, 0.1);
23+
}
24+
.group {
25+
margin: 0 0 1em 2em;
26+
border: 1px solid #ccc;
27+
}
28+
.highlight {
29+
background: #cfc;
30+
}
31+
</style>
32+
<script>
33+
$(function() {
34+
$('.multiselect').checkboxgroup();
35+
36+
// example of click handler: highlight selected rows
37+
$('.multiselect input').click(function() {
38+
$(this).closest('div')[this.checked ? 'addClass' : 'removeClass']('highlight');
39+
});
40+
41+
// checkbox may be checked after page refresh, add corresponding class
42+
$('.multiselect input').each(function() {
43+
if (this.checked) {
44+
$(this).closest('div').addClass('highlight');
45+
}
46+
});
47+
});
48+
</script>
49+
</head>
50+
51+
<body>
52+
<h1><span class="tag">&lt;label&gt;<span class="tag">&lt;input&gt;</span> ...&lt;/label&gt;</span></h1>
53+
<div class="multiselect">
54+
<div class="group">
55+
<div><label><input type="checkbox">Lorem <b>ipsum</b> dolor sit amet,</label></div>
56+
<div><label><input type="checkbox">consectetuer adipiscing elit,</label></div>
57+
<div><label><input type="checkbox">sed diam nonummy nibh euismod tincidunt ut laoreet</label></div>
58+
<div><label><input type="checkbox">dolore magna aliquam erat volutpat.</label></div>
59+
<div><label><input type="checkbox">Ut wisi enim ad minim veniam,</label></div>
60+
<div><label><input type="checkbox">quis nostrud exerci tation ullamcorper suscipit</label></div>
61+
</div>
62+
<div class="group">
63+
<div><label><input type="checkbox">lobortis nisl ut aliquip ex ea commodo consequat.</label></div>
64+
<div><label><input type="checkbox">Duis autem vel eum iriure dolor in hendrerit</label></div>
65+
<div><label><input type="checkbox">in vulputate velit esse molestie consequat,</label></div>
66+
<div><label><input type="checkbox">vel illum dolore eu feugiat nulla facilisis at vero</label></div>
67+
<div><label><input type="checkbox">eros et accumsan et iusto odio dignissim qui blandit</label></div>
68+
<div><label><input type="checkbox">praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.</label></div>
69+
</div>
70+
</div>
71+
72+
<h1><span class="tag">&lt;input&gt;</span> <span class="tag">&lt;label&gt;...&lt;/label&gt;</span></h1>
73+
<div class="multiselect">
74+
<div class="group">
75+
<div><input id="v1_01" type="checkbox"> ... <label for="v1_01">Lorem <b>ipsum</b> dolor sit amet,</label></div>
76+
<div><input id="v1_02" type="checkbox"> ... <label for="v1_02">consectetuer adipiscing elit,</label></div>
77+
<div><input id="v1_03" type="checkbox"> ... <label for="v1_03">sed diam nonummy nibh euismod tincidunt ut laoreet</label></div>
78+
<div><input id="v1_04" type="checkbox"> ... <label for="v1_04">dolore magna aliquam erat volutpat.</label></div>
79+
<div><input id="v1_05" type="checkbox"> ... <label for="v1_05">Ut wisi enim ad minim veniam,</label></div>
80+
<div><input id="v1_06" type="checkbox"> ... <label for="v1_06">quis nostrud exerci tation ullamcorper suscipit</label></div>
81+
</div>
82+
<div class="group">
83+
<div><input id="v1_07" type="checkbox"> ... <label for="v1_07">lobortis nisl ut aliquip ex ea commodo consequat.</label></div>
84+
<div><input id="v1_08" type="checkbox"> ... <label for="v1_08">Duis autem vel eum iriure dolor in hendrerit</label></div>
85+
<div><input id="v1_09" type="checkbox"> ... <label for="v1_09">in vulputate velit esse molestie consequat,</label></div>
86+
<div><input id="v1_10" type="checkbox"> ... <label for="v1_10">vel illum dolore eu feugiat nulla facilisis at vero</label></div>
87+
<div><input id="v1_11" type="checkbox"> ... <label for="v1_11">eros et accumsan et iusto odio dignissim qui blandit</label></div>
88+
<div><input id="v1_12" type="checkbox"> ... <label for="v1_12">praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.</label></div>
89+
</div>
90+
</div>
91+
</body>
92+
93+
</html>

package.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"name": "checkboxgroup",
3+
"version": "1.0.0",
4+
"description": "jQuery plugin for constructing analog of multiselect using checkboxes.",
5+
"keywords": [
6+
"jquery-plugin",
7+
"multiselect",
8+
"checkbox"
9+
],
10+
"homepage": "https://github.com/dmage/checkboxgroup",
11+
"bugs": {
12+
"url": "https://github.com/dmage/checkboxgroup/issues"
13+
},
14+
"license": "MIT",
15+
16+
"author": {
17+
"name": "Oleg Bulatov",
18+
"email": "[email protected]"
19+
},
20+
21+
"repository": {
22+
"type": "git",
23+
"url" : "https://github.com/dmage/checkboxgroup"
24+
},
25+
26+
"dependencies": {
27+
"jquery": ">=1.9.0"
28+
},
29+
"devDependencies": {
30+
"jslint": ">=0.3.0"
31+
}
32+
}

0 commit comments

Comments
 (0)