Skip to content

Instantly share code, notes, and snippets.

@gpbmike
Created August 25, 2012 00:06
Show Gist options
  • Save gpbmike/3457592 to your computer and use it in GitHub Desktop.
Save gpbmike/3457592 to your computer and use it in GitHub Desktop.
<div class='col'>
<input id='canonical'><br>
<select name="categories" id="fake-categories" multiple="multiple">
<option value="1">Food</option>
<option value="2" data-parent-id='1'>Baby Food</option>
<option value="3" data-parent-id='1' selected="selected">Health</option>
<option value="4" data-parent-id='1' selected="selected">McDonalds</option>
<option value="5">Fun</option>
<option value="6" data-parent-id='5'>Potty Training</option>
<option value="7" data-parent-id='5'>Poop Central</option>
<option value="8" data-parent-id='5'>Pool Party</option>
<option value="9" data-parent-id='8'>Wut</option>
<option value="10" data-parent-id='9' selected="selected">Wha</option>
</select>
</div>
<div class='col'>
<h2>Menu</h2>
<ul id='menu'></ul>
</div>
<div class='col'>
<h2>Tree</h2>
<ul id='tree'></ul>
</div>
<button id='test'>alert select value</button>
(function () {
var select = $('#fake-categories'),
tree = $('#tree'),
tree_on = {},
radio_name = 'canonical_' + new Date().getTime();
var addOption = function (id) {
// already selected
if (!id || tree_on[id]) {
return;
}
// find the requested option
var option = select.find('[value=' + id + ']');
// can't find option
if (option.length === 0) {
return;
}
// add to the tree
tree_on[id] = $('<li><ul></ul></li>');
$('<a/>').text(option.text()).prependTo(tree_on[id]).click(function () {
removeOption(id);
});
// walk up the parents and add them all
var parent_id = option.data('parent-id');
if (parent_id) {
addOption(parent_id);
tree_on[id].appendTo(tree_on[parent_id].find('> ul'));
} else {
tree_on[id].appendTo(tree);
}
// signal that id has been added
select.trigger('addOption', id);
};
var removeOption = function (id) {
// not already selected
if (!id || !tree_on[id]) {
return;
}
// remove options that are children
select.find('[data-parent-id=' + id + ']').each(function () {
removeOption($(this).attr('value'));
});
tree_on[id].remove();
delete tree_on[id];
// signal that id has been removed
select.trigger('removeOption', id);
};
// build menu
var menu_item = {};
// build flat menu
select.find('option').each(function () {
var option = $(this),
id = option.attr('value');
menu_item[id] = $('<li><ul></ul></li>').appendTo(menu);
$('<a/>').text(option.text()).prependTo(menu_item[id]).click(function () {
addOption(id);
});
});
// nest children
select.find('[data-parent-id]').each(function () {
var option = $(this),
id = option.attr('value'),
parent_id = option.data('parent-id');
menu_item[id].appendTo(menu_item[parent_id].find('> ul'));
});
// update the select menu when you add and remove options
select.on({
'addOption': function (event, id) {
var option = select.find('[value=' + id + ']').attr('selected', 'selected');
select.find('[value=' + option.data('parent-id') + ']').removeAttr('selected');
},
'removeOption': function (event, id) {
var option = select.find('[value=' + id + ']').removeAttr('selected'),
parent_id = option.data('parent-id');
if (parent_id) {
var siblings = select.find('[data-parent-id=' + option.data('parent-id') + ']:selected');
if (siblings.length === 0) {
select.find('[value=' + parent_id + ']').attr('selected', 'selected');
}
}
}
});
// toggle menu option state when you add and remove options
select.on({
'addOption': function (event, id) {
// highlight menu option
},
'removeOption': function (event, id) {
// turn off highlight for menu option
}
});
// if the canonical option is set, add radio buttons
select.on('addOption', function (event, id) {
var radio = $('<input type="radio" name="' + radio_name + '" value="' + id + '" />');
radio.change(function () {
$('#canonical').val(id);
});
tree_on[id].prepend(radio);
});
// add all items that are selected already
select.find('[selected]').each(function () {
addOption(this.value);
});
})();
$('#test').click(function () {
alert($('select').val());
});
@import "compass"
.col
float: left
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment