Source: ui/base/abstract-checkbox.js

/*global require, exports, document, Error*/
var AbstractControl = require("./abstract-control").AbstractControl,
    PressComposer = require("../../composer/press-composer").PressComposer;

var CLASS_PREFIX = "montage-Checkbox";

/**
 * @class AbstractCheckbox
 * @extends AbstractControl
 */
var AbstractCheckbox = exports.AbstractCheckbox = AbstractControl.specialize( /** @lends AbstractCheckbox# */ {

    /**
     * Dispatched when the checkbox is activated through a mouse click,
     * finger tap, or when focused and the spacebar is pressed.
     * @event action
     * @memberof AbstractCheckbox
     * @param {Event} event
     */

    constructor: {
        value: function AbstractCheckbox() {
            if(this.constructor === AbstractCheckbox) {
                throw new Error("AbstractCheckbox cannot be instantiated.");
            }

            this._pressComposer = new PressComposer();
            this.addComposer(this._pressComposer);

            this.defineBindings({
                // classList management
                "classList.has('montage--disabled')": {
                    "<-": "!enabled"
                },
                "classList.has('montage--active')": {
                    "<-": "active"
                },
                "classList.has('montage-Checkbox--checked')": {
                    "<-": "checked"
                }
            });
        }
    },

    hasTemplate: {
        value: false
    },

    /**
     * This property is true when the checkbox is being interacted with, either through mouse click or touch event, otherwise false.
     * @type {boolean}
     * @default false
     */
    active: {
        value: false
    },

    value: {
        value: null
    },

    _checked: {
        value: false
    },

    /**
     * This property reflect the checked state of the checkbox.
     * @type {boolean}
     * @default false
     */
    checked: {
        set: function (value) {
            this._checked = value;
        },
        get: function () {
            return this._checked;
        }
    },

    /**
     * Enables or disables the checkbox from user input. When this property is set to ```false```,
     * the "montage--disabled" CSS class is applied to the checkbox's DOM element during the next draw cycle. When set to
     * ```true``` the "montage--disabled" CSS class is removed from the element's class list.
     * @type {boolean}
     */
    enabled: {
        value: true
    },

    _pressComposer: {
        value: null
    },

    enterDocument: {
        value: function (firstTime) {
            if (firstTime) {
                this.element.setAttribute("role", "checkbox");
            }
        }
    },

    draw: {
        value: function () {
            if (this.checked) {
                this.element.setAttribute("aria-checked", "true");
            } else {
                this.element.setAttribute("aria-checked", "false");
            }
        }
    },

    toggleChecked: {
        value: function () {
            if (!this.enabled) {
                return;
            }
            this.checked = !this.checked;
            this.dispatchActionEvent();
        }
    },

    handlePressStart: {
        value: function (event) {
            this.active = true;

            if (event.touch) {
                // Prevent default on touchmove so that if we are inside a scroller,
                // it scrolls and not the webpage
                document.addEventListener("touchmove", this, false);
            }
        }
    },

    /**
     * Handle press event from press composer
     */
    handlePress: {
        value: function (/* event */) {
            this.active = false;
            this.toggleChecked();
        }
    },

    /**
     * Called when all interaction is over.
     * @private
     */
    handlePressCancel: {
        value: function (/* event */) {
            this.active = false;
            document.removeEventListener("touchmove", this, false);
        }
    },

    prepareForActivationEvents: {
        value: function () {
            this._pressComposer.addEventListener("pressStart", this, false);
            this._pressComposer.addEventListener("press", this, false);
            this._pressComposer.addEventListener("pressCancel", this, false);
        }
    },

    activate: {
        value: function () {
            this.toggleChecked();
        }
    }

});