Skip to content

Instantly share code, notes, and snippets.

@ernestom
Created August 23, 2013 19:27
Show Gist options
  • Save ernestom/6323055 to your computer and use it in GitHub Desktop.
Save ernestom/6323055 to your computer and use it in GitHub Desktop.
weird checkboxes
<html>
<head></head>
<body>
<form>
<dl id="f_audio">
<dd>
<label for="subtitled">
<input type="checkbox" name="subtitled" id="subtitled" value="1" />Subtitulada
</label>
</dd>
<dd>
<label for="dubbed">
<input type="checkbox" name="dubbed" id="dubbed" value="1" />Doblada
</label>
</dd>
</dl>
<dl id="f_flags">
<dd>
<label for="sd">
<input type="checkbox" name="sd" id="sd" value="1" />Funciones normales
</label>
</dd>
<dd>
<label for="threeD">
<input type="checkbox" name="threeD" id="threeD" value="1" />3D
</label>
</dd>
<dd>
<label for="fourD">
<input type="checkbox" name="fourD" id="fourD" value="1" />4D
</label>
</dd>
<dd>
<label for="imax">
<input type="checkbox" name="imax" id="imax" value="1" />IMAX
</label>
</dd>
<dd>
<label for="jumbo">
<input type="checkbox" name="jumbo" id="jumbo" value="1" />Macro pantallas
</label>
</dd>
<dd>
<label for="digital">
<input type="checkbox" name="digital" id="digital" value="1" />Calidad digital
</label>
</dd>
</dl>
</form>
<script src="weirdcheckboxeslib.js"></script>
<script>
// HTML IDs
var showtimeTypeFilters = $$('#sd, #threeD, #fourD, #imax, #jumbo, #digital');
var audioTypeFilters = $$('#subtitled, #dubbed');
// event callbacks
showtimeTypeFilters.addEvent('change', function(event) {
Enelcine.Showtime.disableIncompatibleTypeFilters({
element: event.target,
rules: Enelcine.Showtime.filterRules.byShowtimeType
});
});
audioTypeFilters.addEvent('change', function(event) {
Enelcine.Showtime.disableIncompatibleTypeFilters({
element: event.target,
rules: Enelcine.Showtime.filterRules.byAudioType
});
});
</script>
</body>
</html>
var Enelcine = {Showtime: {}};
/*
TODO: Improve documentation.
Rule structure inside the "bySomething" keys:
// exclusion object
{
// elementId whose rules will be evaluated upon the user
// checking/unchecking the checkbox.
elementId: [ // array of two rules
// rule when elementId is CHECKED:
// element ids or exclusion objects to disable
[],
// rule when elementId is UNCHECKED:
// element ids or exclusion objects to disable
[]
],
}
*/
Enelcine.Showtime.filterRules = {
byShowtimeType: {
sd: [
// unchecked
null,
// checked
['threeD', 'fourD', 'imax', 'jumbo', 'digital']
],
threeD: [
// unchecked
[
{imax: [
// unchecked
null,
// checked
['sd', 'jumbo', 'fourD', 'digital']
]},
{jumbo: [
// unchecked
null,
// checked
['sd', 'fourD', 'imax']
]}
],
// checked
['sd', 'fourD', 'digital',
{jumbo: [
// unchecked
[
{imax: [
// unchecked
null,
// checked
['jumbo']
]}
],
// checked
['imax']
]}
]
],
fourD: [
// unchecked
null,
// checked
['sd', 'threeD', 'imax', 'digital', 'jumbo']
],
jumbo: [
// unchecked
[
{threeD: [
// unchecked
[
{digital: [
// unchecked
null,
// checked
['threeD']
]}
],
// checked
['sd', 'fourD', 'digital']
]},
{digital: [
null,
['imax', 'threeD', 'fourD', 'sd']
]}
],
// checked
['sd', 'fourD', 'imax', {
threeD: [
// unchecked
[{digital: [
// unchecked
null,
// checked
['threeD']
]}],
// checked
['digital']
]
}]
],
imax: [
// unchecked
[{threeD: [
// unchecked
null,
// checked
['sd', 'fourD', 'digital']
]}],
// checked
['sd', 'jumbo', 'fourD', 'digital']
],
digital: [
// unchecked
[{jumbo: [
// unchecked
null,
// checked
['sd', 'fourD', 'imax']
]}],
// checked
['sd', 'fourD', 'imax', 'threeD',
{jumbo: [
// unchecked
['imax', 'threeD', 'fourD', 'sd'],
// checked
null
]}
]
]
},
byAudioType: {
subtitled: [
// unchecked
null,
// checked
['dubbed']
],
dubbed: [
// unchecked
null,
// checked
['subtitled']
]
}
};
Enelcine.Showtime.disableIncompatibleTypeFilters = function(options) {
options = options || {};
options.element = options.element ? options.element : this;
var logPrefix = 'Enelcine.Showtime.disableIncompatibleTypeFilters: ';
var elementId = options.element.id;
var isChecked = options.element.checked;
var disabledClass = options.disabledClass || 'disabled';
var selectedClass = options.selectedClass || 'selected';
var excludingCheckboxesIds = Object.keys(options.rules);
var excludingCheckboxes = {};
console.info(logPrefix + 'Disabling/highlighting incompatible filters from ' + elementId);
if (excludingCheckboxesIds.indexOf(elementId) < 0) {
console.log(logPrefix + 'Caller #' + elementId + ' is not an excludingCheckbox');
return;
}
var total = 0;
excludingCheckboxesIds.forEach(function(ec) {
// object as a default to avoid TypeErrors
var elem = $(ec)
excludingCheckboxes[ec] = elem || {};
if (elem) {
total++;
// prevent the ugly text selection over the parent label when clicking a checkbox
var parentLabel = elem.getParent('label');
parentLabel.setStyle('-webkit-user-select', 'none');
parentLabel.setStyle('-moz-user-select', 'none');
parentLabel.setStyle('user-select', 'none');
}
});
if (!total) {
console.log(logPrefix + 'No incompatible filters found');
return;
}
// sets the .checked attribute of the given element
// and adds or removes the disabled and selected classes
function setChecked(elem, checked, disable) {
if (!elem) {
console.log(logPrefix + 'Trying to disable unexistent element');
return;
}
try {
if (checked !== null) {
elem.checked = checked;
}
elem.getParent('label')[elem.checked ? 'addClass' : 'removeClass'](selectedClass);
elem.getParent('label')[disable ? 'addClass' : 'removeClass'](disabledClass);
} catch (e) {
console.log(logPrefix + 'ERROR in ' + elem.id + ': ' + e);
}
}
// sets all checkboxes as visually enabled, without modifying its checked state
function reset() {
Object.each(excludingCheckboxes, function(checkbox) {
// do not modify the checked state, only remove the disabled class
setChecked(checkbox, null, false);
})
}
function disableByIds() {
if (arguments) {
reset();
Array.each(arguments, function(checkboxId) {
setChecked(excludingCheckboxes[checkboxId], false, true);
});
}
}
function processRule(elementId, rules) {
if (rules === null) {
console.log(logPrefix + 'No rules given for elementId ' + elementId);
return;
}
var ids = [];
var element = $(elementId);
if (!element || element.type != 'checkbox') {
throw logPrefix + 'Provided elementId ' + elementId + ' is not a checkbox';
}
var index = +element.checked;
if ($type(rules) != 'array' || rules.length != 2
|| (rules[index] !== null && $type(rules[index]) != 'array')) {
throw logPrefix + 'The rules must be an array with 2 items, each item being either an array or null';
}
if (rules[index] === null) {
console.log(logPrefix + 'No rule ' + index + ' given for elementId ' + elementId);
return;
}
rules[index].forEach(function(item) {
var i = ['string', 'object'].indexOf($type(item));
if (i < 0) {
throw logPrefix + 'Malformed rule: expecting array of strings or objects';
} else if (i === 0) {
ids.push(item);
} else if (i === 1) {
var keys = Object.keys(item);
if (keys.length > 1) {
throw logPrefix + 'Malformed rule: objects must have an elementId as its only key';
}
var nestedElementId = keys[0];
var nestedIds = processRule(nestedElementId, item[nestedElementId]);
if (!nestedIds) {
console.log(logPrefix + 'Nested elementId ' + nestedElementId + ' returns no ids');
return;
}
//console.log(logPrefix + 'Nested elementId "' + nestedElementId + '" returns ' + nestedIds.join(', '));
nestedIds.forEach(function(id) {
ids.push(id);
});
}
});
return ids;
}
var ids = processRule(elementId, options.rules[elementId]);
console.info(
logPrefix + 'Unchecking invalid showtime checkboxes with ids: ' +
(ids ? ids.join(', ') : 'NO IDS')
);
disableByIds.apply(null, ids);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment