Newer
Older
reroad-test / 2020-ryusei / aframe-master / src / core / a-mixin.js
@ryusei ryusei on 22 Oct 2020 3 KB パノラマ表示
var ANode = require('./a-node');
var registerElement = require('./a-register-element').registerElement;
var components = require('./component').components;
var utils = require('../utils');

var MULTIPLE_COMPONENT_DELIMITER = '__';

/**
 * @member {object} componentCache - Cache of pre-parsed values. An object where the keys
 *         are component names and the values are already parsed by the component.
 */
module.exports = registerElement('a-mixin', {
  prototype: Object.create(ANode.prototype, {
    createdCallback: {
      value: function () {
        this.componentCache = {};
        this.id = this.getAttribute('id');
        this.isMixin = true;
      }
    },

    attributeChangedCallback: {
      value: function (attr, oldVal, newVal) {
        this.cacheAttribute(attr, newVal);
        this.updateEntities();
      }
    },

    attachedCallback: {
      value: function () {
        this.sceneEl = this.closestScene();
        this.cacheAttributes();
        this.updateEntities();
        this.load();
      }
    },

    /**
     * setAttribute that parses and caches component values.
     */
    setAttribute: {
      value: function (attr, value) {
        window.HTMLElement.prototype.setAttribute.call(this, attr, value);
        this.cacheAttribute(attr, value);
      }
    },

    /**
     * If `attr` is a component, then parse the value using the schema and store it.
     */
    cacheAttribute: {
      value: function (attr, value) {
        var component;
        var componentName;

        // Get component data.
        componentName = utils.split(attr, MULTIPLE_COMPONENT_DELIMITER)[0];
        component = components[componentName];
        if (!component) { return; }
        if (value === undefined) {
          value = window.HTMLElement.prototype.getAttribute.call(this, attr);
        }
        this.componentCache[attr] = component.parseAttrValueForCache(value);
      }
    },

    /**
     * If `attr` is a component, then grab pre-parsed value from the cache.
     * Else do a normal getAttribute.
     */
    getAttribute: {
      value: function (attr) {
        return this.componentCache[attr] ||
               window.HTMLElement.prototype.getAttribute.call(this, attr);
      }
    },

    /**
     * Parse and cache every component defined on the mixin.
     */
    cacheAttributes: {
      value: function () {
        var attributes = this.attributes;
        var attrName;
        var i;
        for (i = 0; i < attributes.length; i++) {
          attrName = attributes[i].name;
          this.cacheAttribute(attrName);
        }
      }
    },

    /**
     * For entities that already have been loaded by the time the mixin was attached, tell
     * those entities to register the mixin and refresh their component data.
     */
    updateEntities: {
      value: function () {
        var entity;
        var entities;
        var i;

        if (!this.sceneEl) { return; }

        entities = this.sceneEl.querySelectorAll('[mixin~=' + this.id + ']');
        for (i = 0; i < entities.length; i++) {
          entity = entities[i];
          if (!entity.hasLoaded || entity.isMixin) { continue; }
          entity.mixinUpdate(this.id);
        }
      }
    }
  })
});