milo

ComponentInfo

constructor
 ComponentInfo() 

Option name Type Description
scope Scope

scope object the component belogs to, usually either top level scope that will be returned by milo.binder or scope property of Container facet of containing component

el Element

DOM element the component is attached to

attr BindAttribute

BindAttribute instance that the component was created with

throwOnErrors Boolean

If set to false, then errors will only be logged to console. True by default.

return ComponentInfo

Simple class to hold information allowing to create/copy component using Component.create and Component.copy.

function ComponentInfo(scope, el, attr, throwOnErrors) {
    attr.parse().validate();

    this.scope = scope;
    this.el = el;
    this.attr = attr;
    this.name = attr.compName;
    this.ComponentClass = getComponentClass(attr, throwOnErrors);
    this.extraFacetsClasses = getComponentExtraFacets(this.ComponentClass, attr, throwOnErrors);

    if (this.ComponentClass
            && hasContainerFacet(this.ComponentClass, this.extraFacetsClasses)) {
        this.container = {};
    }
}

####ComponentInfo instance methods####

_.extendProto(ComponentInfo, {
    destroy: ComponentInfo$destroy,
    rename: ComponentInfo$rename
});

ComponentInfo$destroy

function
 ComponentInfo$destroy() 

ComponentInfo instance method
Destroys ComponentInfo by removing the references to DOM element

function ComponentInfo$destroy() {
    delete this.el;
    this.attr.destroy();
}

ComponentInfo$rename

function
 ComponentInfo$rename() 

Option name Type Description
[name] String

optional new component name, generated from timestamp by default

[renameInScope] Boolean

optional false to not rename ComponentInfo object in its scope, true by default

ComponentInfo instance method
Renames ComponentInfo object

function ComponentInfo$rename(name, renameInScope) {
    name = name || componentName();
    Scope.rename(this, name, renameInScope);
    this.attr.compName = name;
    this.attr.decorate();
}


function getComponentClass(attr, throwOnErrors) {
    var ComponentClass = componentsRegistry.get(attr.compClass);
    if (! ComponentClass)
        reportBinderError(throwOnErrors, 'class ' + attr.compClass + ' is not registered');
    return ComponentClass;
}


function getComponentExtraFacets(ComponentClass, attr, throwOnErrors) {
    var facets = attr.compFacets
        , extraFacetsClasses = {};

    if (Array.isArray(facets))
        facets.forEach(function(fctName) {
            fctName = _.firstUpperCase(fctName);
            if (ComponentClass.hasFacet(fctName))
                reportBinderError(throwOnErrors, 'class ' + ComponentClass.name
                                      + ' already has facet ' + fctName);
            if (extraFacetsClasses[fctName])
                reportBinderError(throwOnErrors, 'component ' + attr.compName
                                      + ' already has facet ' + fctName);
            var FacetClass = facetsRegistry.get(fctName);
            extraFacetsClasses[fctName] = FacetClass;
        });

    return extraFacetsClasses;
}


function reportBinderError(throwOnErrors, message) {
    if (throwOnErrors === false)
        logger.error('ComponentInfo binder error:', message);
    else
        throw new Error(message);
}


function hasContainerFacet(ComponentClass, extraFacetsClasses) {
    return (ComponentClass.hasFacet('container')
        || 'Container' in extraFacetsClasses
        || _.someKey(extraFacetsClasses, facetRequiresContainer)
        || classHasFacetThatRequiresContainer());

    function classHasFacetThatRequiresContainer() {
        return (ComponentClass.prototype.facetsClasses
            && _.someKey(ComponentClass.prototype.facetsClasses, facetRequiresContainer));
    }

    function facetRequiresContainer(FacetClass) {
        return FacetClass.requiresFacet('container');
    }
}