Skip to content

Instantly share code, notes, and snippets.

@dalgard
Last active December 31, 2015 18:49
Show Gist options
  • Save dalgard/8029759 to your computer and use it in GitHub Desktop.
Save dalgard/8029759 to your computer and use it in GitHub Desktop.
Sync some form controls with an object (http://codepen.io/dalgard/full/CkbKw)
/*
This trick is a lazy way of two-way sync'ing some form controls with an options object.
Actually, the "sync'ing" consists in getting the values when needed and updating the fields
when changing something. It has its limits, but may work quite nicely.
Depends on: jQuery/Zepto
The code below works for checkboxes (boolean), text input (string), number input (number),
select lists (string) and json in textarea (object)
HTML:
<input type="checkbox" data-options="my_options" data-options-key="my_boolean_option">
<input type="text" data-options="my_options" data-options-key="my_string_option">
<input type="number" data-options="my_options" data-options-key="my_numerical_option">
<select data-options="my_options" data-options-key="my_other_option"><option>first</option><option>second</option></select>
<textarea data-options="my_options" data-options-key="my_json_option" data-options-type="json"></textarea>
(<span class="error" data-options="my_options" data-options-error="my_json_option"></span>)
JS:
// on app init (probably should attach to your app's namespace ;))
createOptions(window, "my_options");
// get option value
window.my_options.some_option
// set option value (reflects on form control)
window.my_options = { some_option: "cool option, man" }
*/
// Add options object to namespace[name]
function createOptions(namespace, name) {
// Hooray for ES5!
Object.defineProperty(namespace, name, {
get: function () {
var new_options = {};
// Iterate over elements that belong to this particular collection of options
$("[data-options='" + name + "'][data-options-key]").each(function () {
var input = $(this),
type = input.attr("data-options-type") || input.attr("type"),
key = input.attr("data-options-key"),
value;
try {
if (type === "json") {
var json = JSON.parse(input.val() || "{}");
value = (json instanceof Object ? json : {});
}
else if (type === "checkbox") value = input.prop("checked");
else if (type === "number") value = parseInt(input.val());
else value = input.val();
// Reset error message
input.removeClass("has-error");
$("[data-options='" + name + "'][data-options-error='" + key + "']").text("");
}
catch (e) {
value = (type === "json" ? {} : null);
// Output error message or bubble exception
input.addClass("has-error");
var error_elem = $("[data-options='" + name + "'][data-options-error='" + key + "']");
if (error_elem.length) error_elem.text(e.name + ": " + e.message);
else throw(e);
}
new_options[key] = value;
});
return new_options;
},
set: function (object) {
for (var key in object) {
if (object.hasOwnProperty(key)) {
var input = $("[data-options='" + name + "'][data-options-key='" + key + "']"),
type = input.attr("data-options-type") || input.attr("type"),
value = object[key];
if (type === "json") input.val(JSON.stringify(value, null, 2));
else if (type === "checkbox") input.prop("checked", value);
else input.val(value);
}
}
},
enumerable: true
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment