Source: svg-container.js

(function (svgext) {
    'use strict';

    svgext.SVGContainer = inherit([svgext.SVGElement, svgext.SVGBlock], /** @lends svgext.SVGContainer.prototype  */ {

        /**
         * Creates svgext.SVGContainer instance
         *
         * @constructs svgext.SVGContainer
         * @classdesc Root svg element class
         * @augments svgext.SVGElement
         * @mixes svgext.SVGBlock
         * @param {Object} [opts]
         * @param {String} [opts.cssClass]
         * @param {SVGSVGElement} [opts.node] existing svg element
         */
        __constructor: function (opts) {
            opts = opts || {};
            opts.isDraggable = false;
            opts.cssClass = opts.cssClass || 'svg-container_fluid';
            this.__base(opts, opts.node || 'svg');
            this._offWindowResize = svgext._throttleEventListener('resize', this._onWindowResize.bind(this));
        },

        /**
         * Instances getter
         *
         * @param {SVGElement} [elemClass]
         * @returns {Array.<SVGElement>}
         */
        getInstances: function (elemClass) {
            return elemClass ? this._filterChildren(elemClass) : this.children;
        },

        /**
         * Current active element getter
         *
         * @returns {SVGElement|null}
         */
        getActiveElement: function () {
            return this.activeElement;
        },

        /**
         * Toggles elements
         *
         * @param {Boolean} visible
         * @param {SVGElement} [elemClass]
         * @returns {SVGContainer}
         */
        toggleAllInstances: function (visible, elemClass) {
            this.getInstances(elemClass)
                .forEach(function (svgElement) {
                    if (!visible) {
                        svgElement.deactivate().hide();
                    } else {
                        svgElement.show();
                    }
                });

            return this;
        },

        /**
         * Sets an active element
         *
         * @param {SVGElement} svgElement
         */
        setActiveElement: function (svgElement) {
            if (svgElement && svgElement instanceof svgext.SVGElement && !svgElement.isActive) {
                this.deactivateActiveElement();
                svgElement.activate();
                this.activeElement = svgElement;
            }
        },

        /**
         * Deactivates active element if it exists
         *
         * @returns {SVGContainer}
         */
        deactivateActiveElement: function () {
            if (this.activeElement) {
                this.activeElement.deactivate();
                this.activeElement = null;
            }

            return this;
        },

        /**
         * Removes an active instance based on passed constructor
         *
         * @param {SVGElement} [elemClass]
         */
        removeActiveInstance: function (elemClass) {
            if (!this.activeElement) {
                return;
            }
            if (!elemClass || (elemClass && this.activeElement instanceof elemClass)) {
                this.remove(this.activeElement);
                this.activeElement = null;
            }
        },

        /**
         * Removes all instances based on passed constructor
         *
         * @param {SVGElement} [elemClass]
         */
        removeAllInstances: function (elemClass) {
            var children = this.children;

            if (elemClass) {
                this.removeActiveInstance(elemClass);
                return this.getInstances(elemClass).forEach(this.remove, this);
            }

            this.activeElement = null;
            while (children.length) {
                this.remove(children[0]);
            }
        },

        /**
         * Removes svg container
         *
         * @override {SVGBlock}
         */
        destroy: function () {
            this._offWindowResize();
            this.__base();
        },

        /**
         * Fetches all instances from the containers
         *
         * @param {instance} elemClass
         * @private
         * @returns {Array.<SVGElement>}
         */
        _filterChildren: function (elemClass) {
            return this.children.filter(function (child) {
                return child instanceof elemClass;
            });
        },

        /**
         * Window resize handler
         *
         * @private
         */
        _onWindowResize: function () {
            var containerRect = this.getRect();
            if (this._prevContainerWidth === undefined) {
                this._prevContainerWidth = containerRect.width;
                this._prevContainerHeight = containerRect.height;
                return;
            }
            if (containerRect.width !== this._prevContainerWidth
                || containerRect.height !== this._prevContainerHeight) {
                this._resizeChildren(
                    containerRect.width / this._prevContainerWidth,
                    containerRect.height / this._prevContainerHeight
                );
                this._prevContainerWidth = containerRect.width;
                this._prevContainerHeight = containerRect.height;
            }
        },

        /**
         * Resizes all resizable children
         *
         * @param {Number} widthFactor width resize factor
         * @param {Number} heightFactor height resize factor
         * @private
         */
        _resizeChildren: function (widthFactor, heightFactor) {
            this.children.forEach(function (child) {
                if (child && child.resize) {
                    child.resize(widthFactor, heightFactor);
                }
            });
        }
    });
}(svgext));