diff --git a/lib/widgets.js b/lib/widgets.js
index a22d7b0..07fc961 100644
--- a/lib/widgets.js
+++ b/lib/widgets.js
@@ -105,15 +105,29 @@ exports.select = function (options) {
classes: opt.classes,
type: 'select'
};
+ var choicesHTML;
+ var groupHTML = function (group, label, value) {
+ return tag('optgroup', {
+ label: label
+ }, choicesHTML(group, value));
+ };
+ choicesHTML = function (choices, value) {
+ return Object.keys(choices).reduce(function (html, k) {
+ if (is.object(choices[k])) {
+ return html + groupHTML(choices[k], String(k), value);
+ } else {
+ return html + tag('option', {
+ value: k,
+ selected: !!(value && String(value) === String(k))
+ }, choices[k]);
+ }
+ }, '');
+ };
+
var userAttrs = getUserAttrs(opt);
w.toHTML = function (name, field) {
var f = field || {};
- var optionsHTML = Object.keys(f.choices).reduce(function (html, k) {
- return html + tag('option', {
- value: k,
- selected: !!(f.value && String(f.value) === String(k))
- }, f.choices[k]);
- }, '');
+ var optionsHTML = choicesHTML(f.choices, f.value, '');
var attrs = {
name: name,
id: f.id === false ? false : (f.id || true),
@@ -233,16 +247,33 @@ exports.multipleSelect = function (options) {
classes: opt.classes,
type: 'multipleSelect'
};
+ var choicesHTML;
+ var groupHTML = function (group, label, value) {
+ return tag('optgroup', {
+ label: label
+ }, choicesHTML(group, value));
+ };
+
+ choicesHTML = function (choices, value) {
+ return Object.keys(choices).reduce(function (html, k) {
+ if (is.object(choices[k])) {
+ return html + groupHTML(choices[k], String(k), value);
+ } else {
+ var selected = value && (Array.isArray(value) ? value.some(function (v) {
+ return String(v) === String(k);
+ }) : String(value) === String(k));
+ return html + tag('option', {
+ value: k,
+ selected: !!selected
+ }, choices[k]);
+ }
+ }, '');
+ };
+
var userAttrs = getUserAttrs(opt);
w.toHTML = function (name, field) {
var f = field || {};
- var optionsHTML = Object.keys(f.choices).reduce(function (html, k) {
- var selected = f.value && (Array.isArray(f.value) ? f.value.some(function (v) { return String(v) === String(k); }) : String(f.value) === String(k));
- return html + tag('option', {
- value: k,
- selected: !!selected
- }, f.choices[k]);
- }, '');
+ var optionsHTML = choicesHTML(f.choices, f.value);
var attrs = {
multiple: true,
name: name,
diff --git a/test/test-widgets.js b/test/test-widgets.js
index b9fc323..50180ae 100644
--- a/test/test-widgets.js
+++ b/test/test-widgets.js
@@ -124,7 +124,37 @@ test('select', function (t) {
var expectedHTML = '';
+ '';
+ st.equal(html, expectedHTML);
+ st.end();
+ });
+ t.test('provides option groups', function (st) {
+ var html = widget.toHTML('name', {
+ choices: {
+ regular: 'value',
+ group1: {
+ 1: 'one',
+ 2: 'two'
+ },
+ 'Group Two': {
+ 3: 'three',
+ 4: 'four'
+ }
+ },
+ id: 'someid',
+ value: '3'
+ });
+ var expectedHTML = '';
st.equal(html, expectedHTML);
st.end();
});
@@ -405,7 +435,37 @@ test('multipleSelect', function (t) {
st.end();
});
-
+ t.test('provides option groups', function (st) {
+ var widget = forms.widgets.multipleSelect({ classes: ['one', 'two'] });
+ var html = widget.toHTML('name', {
+ choices: {
+ 'Long groupname': {
+ 1: 'one',
+ 2: 'two'
+ },
+ regular: 'value',
+ Hamster: {
+ 3: 'dance',
+ 4: 'dance!!!'
+ }
+ },
+ id: 'someid',
+ value: ['2', 'regular']
+ });
+ var expectedHTML = '';
+ st.equal(html, expectedHTML);
+ st.end();
+ });
t.end();
});