Skip to content

Instantly share code, notes, and snippets.

@shawnbot
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shawnbot/bb167c3c33b36c52b162 to your computer and use it in GitHub Desktop.
Save shawnbot/bb167c3c33b36c52b162 to your computer and use it in GitHub Desktop.

Stateful Checkboxes

This quick little hack creates a global function named checkboxes() that uses [localStorage] to remember the state of checkboxes on the host page. Usage:

var boxes = checkboxes({
    // the checkbox selector (always prefixed with 'input[type=checkbox]')
    selector:   '.stateful',
    // the storage engine (only 'localStorage' is supported here)
    storage:    'localStorage',
    // the prefix for all storage keys
    namespace:  'stateful.checkboxes:' + location.pathname,
    // elements matching this selector will clear the checkboxes when clicked
    clear:      'button.stateful-clear'
});
(function(exports) {
var defaults = {
selector: '.stateful',
storage: 'localStorage',
namespace: 'stateful.checkboxes:' + location.pathname,
clear: 'button.stateful-clear'
};
exports.checkboxes = function(options) {
options = extend({}, defaults, options);
var selector = 'input[type=checkbox]' + (options.selector || ''),
storage = getEngine(options.storage),
boxes = selectAll(selector),
prefix = options.namespace;
boxes.forEach(function(box, i) {
var key = getKey(box, i),
val = storage.get(key);
box.__key__ = key;
box.__checked__ = box.checked;
if (val !== null) {
box.checked = val === 'true';
}
box.addEventListener('change', function() {
storage.set(key, box.checked);
});
});
if (options.clear) {
selectAll(options.clear).forEach(function(button) {
button.addEventListener('click', clear);
});
}
function getKey(box, i) {
return prefix + (box.id || box.name || '@' + i);
}
function getData() {
var data = {};
forEach(boxes, function(box, i) {
data[box.__key__] = box.checked;
});
return data;
}
function clear() {
forEach(boxes, function(box, i) {
box.checked = box.__checked__;
storage.rem(box.__key__);
});
}
return {
data: getData,
clear: clear
};
};
function selectAll(selector) {
return [].slice.call(document.querySelectorAll(selector));
}
function getEngine(name) {
switch (name) {
case 'cookie':
throw 'cookie engine not implemented';
case 'localStorage':
case null:
var ls = window.localStorage;
return {
get: ls.getItem.bind(ls),
set: ls.setItem.bind(ls),
rem: ls.removeItem.bind(ls)
};
}
throw 'no such storage engine: ' + name;
}
function forEach(list, fn, context) {
return Array.prototype.forEach.call(list, fn, context || this);
}
function extend(obj) {
[].slice.call(arguments, 1).forEach(function(arg) {
if (!arg) return;
for (var key in arg) {
obj[key] = arg[key];
}
});
return obj;
}
})(this);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Stateful Checkboxes</title>
<script src="checkboxes.js"></script>
<style>
html {
padding: 1em
}
body {
font-family: 'Helvetica Neue', helvetica, arial, sans-serif;
}
h1 {
margin: 0;
}
</style>
</head>
<body>
<h1>Stateful Checkboxes</h1>
<ol>
<li><input type="checkbox"> add some checkboxes</li>
<li><input type="checkbox"> make them stateful</li>
<li><input type="checkbox"> profit?</li>
</ol>
<p><input type="checkbox" checked> this should be checked by default</p>
<p><button id="clear">clear</button></p>
</body>
<script>
checkboxes({
selector: '', // all checkboxes
clear: '#clear' // clear button
});
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment