UNPKG

formstone

Version:

Library of modular front end components.

342 lines (280 loc) 8.72 kB
/* global define */ (function(factory) { if (typeof define === "function" && define.amd) { define([ "jquery", "./core" ], factory); } else { factory(jQuery, Formstone); } }(function($, Formstone) { "use strict"; /** * @method private * @name construct * @description Builds instance. * @param data [object] "Instance data" */ function construct(data) { var $parent = this.closest("label"), $label = $parent.length ? $parent.eq(0) : $("label[for=" + this.attr("id") + "]"), baseClass = [RawClasses.base, data.theme, data.customClass].join(" "), labelClass = [RawClasses.label, data.theme, data.customClass].join(" "), html = ""; data.radio = (this.attr("type") === "radio"); data.group = this.attr("name"); html += '<div class="' + RawClasses.marker + '" aria-hidden="true">'; html += '<div class="' + RawClasses.flag + '"></div>'; if (data.toggle) { baseClass += " " + RawClasses.toggle; labelClass += " " + RawClasses.toggle; html += '<span class="' + [RawClasses.state, RawClasses.state_on].join(" ") + '">' + data.labels.on + '</span>'; html += '<span class="' + [RawClasses.state, RawClasses.state_off].join(" ") + '">' + data.labels.off + '</span>'; } if (data.radio) { baseClass += " " + RawClasses.radio; labelClass += " " + RawClasses.radio; } html += '</div>'; // Modify DOM data.$placeholder = $('<span class="' + RawClasses.element_placeholder + '"></span>'); this.before(data.$placeholder); data.labelParent = ($label.find(this).length); data.labelClass = labelClass; $label.addClass(labelClass); if (data.labelParent) { $label.wrap('<div class="' + baseClass + '"></div>') .before(html); } else { this.before('<div class=" ' + baseClass + '">' + html + '</div>'); } // Store plugin data data.$checkbox = (data.labelParent) ? $label.parents(Classes.base) : this.prev(Classes.base); data.$marker = data.$checkbox.find(Classes.marker); data.$states = data.$checkbox.find(Classes.state); data.$label = $label; data.$classable = $().add(data.$checkbox).add(data.$label); // Check checked if (this.is(":checked")) { data.$classable.addClass(RawClasses.checked); } // Check disabled if (this.is(":disabled") /* || this.is("[readonly]") */ ) { data.$classable.addClass(RawClasses.disabled); } // Move original checkbox this.appendTo(data.$marker); // Bind click events this.on(Events.focus, data, onFocus) .on(Events.blur, data, onBlur) .on(Events.change, data, onChange) .on(Events.click, data, onClick) .on(Events.deselect, data, onDeselect); data.$checkbox.on(Events.click, data, onClick); } /** * @method private * @name destruct * @description Tears down instance. * @param data [object] "Instance data" */ function destruct(data) { data.$checkbox.off(Events.namespace); // .fsTouch("destroy"); data.$marker.remove(); data.$states.remove(); data.$label.removeClass(data.labelClass); if (data.labelParent) { data.$label.unwrap(); } else { this.unwrap(); } data.$placeholder.before(this); data.$placeholder.remove(); this.off(Events.namespace); } /** * @method * @name enable * @description Enables target instance * @example $(".target").checkbox("enable"); */ function enable(data) { this.prop("disabled", false); data.$classable.removeClass(RawClasses.disabled); } /** * @method * @name disable * @description Disables target instance * @example $(".target").checkbox("disable"); */ function disable(data) { this.prop("disabled", true); data.$classable.addClass(RawClasses.disabled); } /** * @method * @name update * @description Updates target instance * @example $(".target").checkbox("update"); */ function update(data) { var disabled = data.$el.is(":disabled") /* || data.$el.is("[readonly]") */ , checked = data.$el.is(":checked"); if (!disabled) { if (checked) { onSelect({ data: data }); } else { onDeselect({ data: data }); } } } /** * @method private * @name onClick * @description Handles click */ function onClick(e) { e.stopPropagation(); var data = e.data; if (!$(e.target).is(data.$el)) { e.preventDefault(); data.$el.trigger("click"); } } /** * @method private * @name onChange * @description Handles external changes * @param e [object] "Event data" */ function onChange(e) { var data = e.data, disabled = data.$el.is(":disabled") /* || data.$el.is("[readonly]") */ , checked = data.$el.is(":checked"); if (!disabled) { if (data.radio) { // radio if (checked) { onSelect(e); } } else { // Checkbox change events fire after state has changed if (checked) { onSelect(e); } else { onDeselect(e); } } } } /* * @method private * @name onSelect * @description Changes input to "checked" * @param e [object] "Event data" */ function onSelect(e) { if (e.data.radio) { $('input[name="' + e.data.group + '"]').not(e.data.$el).trigger("deselect"); } e.data.$el.trigger(Events.focus); e.data.$classable.addClass(RawClasses.checked); } /** * @method private * @name onDeselect * @description Changes input to "checked" * @param e [object] "Event data" */ function onDeselect(e) { e.data.$el.trigger(Events.focus); e.data.$classable.removeClass(RawClasses.checked); } /** * @method private * @name onFocus * @description Handles instance focus * @param e [object] "Event data" */ function onFocus(e) { e.data.$classable.addClass(RawClasses.focus); } /** * @method private * @name onBlur * @description Handles instance blur * @param e [object] "Event data" */ function onBlur(e) { e.data.$classable.removeClass(RawClasses.focus); } /** * @plugin * @name Checkbox * @description A jQuery plugin for replacing checkboxes. * @type widget * @main checkbox.js * @main checkbox.css * @dependency jQuery * @dependency core.js * @__dependency touch.js */ var Plugin = Formstone.Plugin("checkbox", { widget: true, /** * @options * @param customClass [string] <''> "Class applied to instance" * @param toggle [boolean] <false> "Render 'toggle' styles" * @param labels.on [string] <'ON'> "Label for 'On' position; 'toggle' only" * @param labels.off [string] <'OFF'> "Label for 'Off' position; 'toggle' only" * @param theme [string] <"fs-light"> "Theme class name" */ defaults: { customClass: "", toggle: false, labels: { on: "ON", off: "OFF" }, theme: "fs-light" }, classes: [ "element_placeholder", "label", "marker", "flag", "radio", "focus", "checked", "disabled", "toggle", "state", "state_on", "state_off" ], methods: { _construct: construct, _destruct: destruct, // Public Methods enable: enable, disable: disable, update: update }, events: { deselect: "deselect" } }), // Localize References Classes = Plugin.classes, RawClasses = Classes.raw, Events = Plugin.events, Functions = Plugin.functions; }) );