# Source: ui/condition.reel/condition.js

    /**
     * @module "montage/ui/condition.reel"
     */
    var Component = require("../component").Component,
        logger = require("../../core/logger").logger("condition");

    /**
     * The condition component shows its DOM content when its
     * [condition]{@link Condition#condition} property is `true`, and hides its DOM
     * content when it is `false`.
     *
     * Different strategies can be used to hide the DOM content. By default the
     * condition will remove its content from the DOM but
     * [removalStrategy]{@link Condition#removalStrategy} can be changed to alter
     * this behavior.
     *
     * @class Condition
     * @classdesc A component that shows or hides its inner template in response to
     * changes to some condition.
     * @extends Component
     */
    exports.Condition = Component.specialize( /** @lends Condition.prototype # */ {

        hasTemplate: {
            value: false
        },

        _condition: {
            value: true
        },

        _contents: {
            value: null
        },

        _needsClearDomContent: {
            value: false
        },

        __contentDocumentFragment: {
            value: null
        },

        _contentDocumentFragment: {
            get: function () {
                if (!this.__contentDocumentFragment && this.element) {
                    this.__contentDocumentFragment = document.createDocumentFragment();
                }

                return this.__contentDocumentFragment;
            }
        },

        /**
         * The boolean value that specifies if the contents of the condition are
         * visible (`true`) or hidden (`false`).
         * `null` is equivalent to `false`.
         *
         * @returns {boolean}
         * @default null
         */
        condition: {
            set: function (value) {

                if (value === this._condition) {
                    return;
                }

                this._condition = value;
                this.needsDraw = true;
                // If it is being deserialized element might not been set yet
                if (!this.isDeserializing && this.removalStrategy === "remove") {
                    if (value) {
                        this.domContent = this._contentDocumentFragment.childNodes;

                    } else {
                        this._needsDraw = this._needsClearDomContent = true;
                    }
                }
            },
            get: function () {
                return this._condition;
            }
        },

        _clearDomContent: {
            value: function () {
                if (this.removalStrategy === "remove" && !this._condition) {
                    var childNodes = this.element.childNodes;

                    while (childNodes.length) {
                        this._contentDocumentFragment.appendChild(childNodes[0]);
                    }

                    this.domContent = null;
                    this._shouldClearDomContentOnNextDraw = false;
                    this.needsDraw = false;
                }

                this._needsClearDomContent = false;
            }
        },

        deserializedFromTemplate: {
            value: function () {
                // update the DOM if the condition is false because we're preventing
                // changes at deserialization time.
                if (!this._condition) {
                    this._clearDomContent();
                }
            }
        },

        _removalStrategy:{
            value: "remove"
        },

        // TODO should this strategy be part of another class?
        // TODO expose the options as an exported enum
        /**
         * The removal strategy specifies how the condition should remove its
         * content when [condition]{@link Condition#condition} is `false`.
         *
         * A value of `remove` will make the condition remove its contents from
         * the DOM.
         *
         * A value of `hide` will make the condition hide its contents through CSS
         * using the `montage-invisible` class while keeping them on the DOM. Apps using
         * `hide` should declare the `montage-invisible` class
         * which will be applied to elements.
         *
         * Example:
         *
         * ```css
         * .montage-invisible {
         *   display: none;
         * }
         * ```
         *
         * Possible values are `remove`, `hide`.
         *
         * @type {string}
         * @default "remove"
         */
        removalStrategy:{
            get:function () {
                return this._removalStrategy;
            },
            set:function (value) {
                if (this._removalStrategy !== value) {
                    this._removalStrategy = value;
                    this.needsDraw = true;
                }
            }
        },

        draw: {
            value: function () {
                if (this.condition) {
                    this.element.classList.remove("montage-invisible");
                } else {
                    this.element.classList.add("montage-invisible");
                }

               if (this._needsClearDomContent) {
                   this._clearDomContent();
               }
            }
        }

    });