<commit_before><link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../iron-collapse/iron-collapse.html">

<dom-module id="brainy-tree-node">
  <template>
    <style>
      :host {
        display: block;
      }

      :host ::content iron-collapse {
        padding-left: 1em;
        @apply(--brainy-tree-node-children);
      }

      :host ::content #content {
        position: relative;
        margin: .1rem 0 .2rem;
        @apply(--brainy-tree-node-content);
      }
    </style>

    <content></content>

  </template>
  <script>
    (function() {
      'use strict';

      Polymer({
        is: 'brainy-tree-node',

        behaviors: [
          Polymer.Templatizer
        ],

        properties: {
          data: Object,
          _children: {
            type: Array
          },
          opened: {
            type: Boolean,
            value: false,
            observer: '_openedChanged'
          },
          _template: Object
        },

        observers: [
          '_renderNodeContent(data)'
        ],

        toggle: function() {
          if (this._updated) {
            this.opened = !this.opened;
          } else {
            this._fetchChildren();
            this.opened = true;
          }
        },

        open: function() {
          this.opened = true;
          if (!this._updated) {
            return this._fetchChildren();
          }
          return Promise.resolve();
        },

        close: function() {
          this.opened = false;
        },

        _renderNodeContent: function() {
          if (this._template) {
            if (this._instance) {
              // re-render if data changes
              this._teardownInstance();
              this._fetchChildren();
            }
            var data = this.data;
            // templatize must be called once before stamp is called
            this.templatize(this._template);
            // stamp and prepare bindings
            this._instance = this.stamp({});
            this._instance.item = data;
            this._instance.opened = this.opened;
            this._instance.isLeaf = !data.children || data.children.length === 0;
            this._instance.isRoot = data.id === Brainy.Tree.ROOT_ID;
            this.dataset.id = data.id;
            var content = document.createElement('div');
            content.id = 'content';
            Polymer.dom(content).appendChild(this._instance.root);
            Polymer.dom(this).appendChild(content);
            var children = document.createElement('iron-collapse');
            children.id = 'children';
            children.opened = this.opened;
            children.noAnimation = true;
            Polymer.dom(this).appendChild(children);
            Polymer.dom.flush();
            this._setupToggleListener();
          }
        },

        _renderChildNodes: function() {
          if (this._template) {
            return new Promise(function(resolve) {
              // clear <iron-collapse> content in case we are re-rendering
              var children = this._getChildrenContainer();
              while (children.hasChildNodes()) {
                children.removeChild(children.lastChild);
              }
              var items = this._children || [];
              for (var i = 0; i < items.length; i++) {
                var el = document.createElement('brainy-tree-node');
                el.controller = this.controller;
                el._template = this._template;
                el.dataHost = this._instance._rootDataHost;
                el.data = items[i];
                children.appendChild(el);
              }
              resolve();
            }.bind(this));
          }
        },

        _fetchChildren: function() {
          this._children = this.data.children;
          this._updated = true;
          return this._renderChildNodes();
        },

        _getChildrenContainer: function() {
          return Polymer.dom(this).querySelector('#children');
        },

        _setupToggleListener: function() {
          this._flushTemplates();
          var toggleEls = Polymer.dom(this).querySelector('#content').querySelectorAll('[toggle]');
          for (var i = 0; i < toggleEls.length; i++) {
            this.listen(toggleEls[i], 'tap', 'toggle');
          }
        },

        // Implements extension point from Templatizer mixin
        // Called as side-effect of a host property change, responsible for
        // notifying parent.<prop> path change on instance
        _forwardParentProp: function(prop, value) {
          if (this._instance) {
            this._instance[prop] = value;
          }
        },

        _teardownInstance: function() {
          var children = this._instance._children;
          if (children && children.length) {
            var parent = Polymer.dom(Polymer.dom(children[0]).parentNode);
            for (var i = 0; i < children.length; i++) {
              parent.removeChild(children[i]);
            }
          }
          this._instance = null;
          this._updated = false;
        },

        _openedChanged: function() {
          if (this._instance) {
            this._getChildrenContainer().opened = this.opened;
            this._instance.notifyPath('opened', this.opened);
            this._setupToggleListener();
          }
        }
      });
    })();
  </script>
</dom-module><commit_msg>Make forwarding parent props work. Describe templatizer instance props<commit_after><link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../iron-collapse/iron-collapse.html">

<dom-module id="brainy-tree-node">
  <template>
    <style>
      :host {
        display: block;
      }

      :host ::content iron-collapse {
        padding-left: 1em;
        @apply(--brainy-tree-node-children);
      }

      :host ::content #content {
        position: relative;
        margin: .1rem 0 .2rem;
        @apply(--brainy-tree-node-content);
      }
    </style>

    <content></content>

  </template>
  <script>
    (function() {
      'use strict';

      Polymer({
        is: 'brainy-tree-node',

        behaviors: [
          Polymer.Templatizer
        ],

        properties: {
          data: Object,
          _children: {
            type: Array
          },
          // singleton
          _instances: {
            type: Array,
            value: []
          },
          _instance: Object,
          opened: {
            type: Boolean,
            value: false,
            observer: '_openedChanged'
          },
          _template: Object
        },

        observers: [
          '_renderNodeContent(data)'
        ],

        created: function() {
          this._instanceProps = {
            id: true,
            isLeaf: true,
            isRoot: true,
            item: true,
            opened: true
          };
        },

        attached: function() {
          this._instances.push(this);
        },

        detached: function() {
          this._instances.splice(this._instances.indexOf(this), 1);
        },

        toggle: function() {
          if (this._updated) {
            this.opened = !this.opened;
          } else {
            this._fetchChildren();
            this.opened = true;
          }
        },

        open: function() {
          this.opened = true;
          if (!this._updated) {
            return this._fetchChildren();
          }
          return Promise.resolve();
        },

        close: function() {
          this.opened = false;
        },

        // this overrides the default from Polymer.Templatizer
        stamp: function(model) {
          model = model || {};

          if (this._parentProps) {
            var templatized = this._templatized;
            for (var prop in this._parentProps) {
              if (model[prop] === undefined) {
                model[prop] = templatized[this._parentPropPrefix + prop];

                // this is a fix for missing initial bindings on subsequent stamps
                // https://github.com/Polymer/polymer/issues/3755
                if (model[prop] === undefined) {
                  model[prop] = this._getBinding(prop, this.dataHost);
                }
              }
            }
          }
          return new this.ctor(model, this);
        },

        _getBinding: function(prop, dataHost) {
          var data = dataHost && dataHost.__data__;

          if (!data) {
            return undefined;
          }

          if (prop in data) {
            return data[prop];
          }

          return this._getBinding(prop, dataHost.dataHost);
        },

        _renderNodeContent: function() {
          if (this._template) {
            if (this._instance) {
              // re-render if data changes
              this._teardownInstance();
              this._fetchChildren();
            }
            var data = this.data;
            // templatize must be called once before stamp is called
            this.templatize(this._template);
            // stamp and prepare bindings
            this._instance = this.stamp({});
            this._instance.item = data;
            this._instance.opened = this.opened;
            this._instance.isLeaf = !data.children || data.children.length === 0;
            this._instance.isRoot = data.id === Brainy.Tree.ROOT_ID;
            this.dataset.id = data.id;
            var content = document.createElement('div');
            content.id = 'content';
            Polymer.dom(content).appendChild(this._instance.root);
            Polymer.dom(this).appendChild(content);
            var children = document.createElement('iron-collapse');
            children.id = 'children';
            children.opened = this.opened;
            children.noAnimation = true;
            Polymer.dom(this).appendChild(children);
            Polymer.dom.flush();
            this._setupToggleListener();
          }
        },

        _renderChildNodes: function() {
          if (this._template) {
            return new Promise(function(resolve) {
              // clear <iron-collapse> content in case we are re-rendering
              var children = this._getChildrenContainer();
              while (children.hasChildNodes()) {
                children.removeChild(children.lastChild);
              }
              var items = this._children || [];
              for (var i = 0; i < items.length; i++) {
                var el = document.createElement('brainy-tree-node');
                el.controller = this.controller;
                el._template = this._template;
                el.dataHost = this._instance._rootDataHost;
                el.data = items[i];
                children.appendChild(el);
              }
              resolve();
            }.bind(this));
          }
        },

        _fetchChildren: function() {
          this._children = this.data.children;
          this._updated = true;
          return this._renderChildNodes();
        },

        _getChildrenContainer: function() {
          return Polymer.dom(this).querySelector('#children');
        },

        _setupToggleListener: function() {
          this._flushTemplates();
          var toggleEls = Polymer.dom(this).querySelector('#content').querySelectorAll('[toggle]');
          for (var i = 0; i < toggleEls.length; i++) {
            this.listen(toggleEls[i], 'tap', 'toggle');
          }
        },

        // Implements extension point from Templatizer mixin
        // Called as side-effect of a host property change, responsible for
        // notifying parent.<prop> path change on instance
        _forwardParentProp: function(prop, value) {
          this._instances.forEach(function(instance) {
            if (instance._instance) {
              instance._instance[prop] = value;
            }
          });
        },

        _teardownInstance: function() {
          var children = this._instance._children;
          if (children && children.length) {
            var parent = Polymer.dom(Polymer.dom(children[0]).parentNode);
            for (var i = 0; i < children.length; i++) {
              parent.removeChild(children[i]);
            }
          }
          this._instance = null;
          this._updated = false;
        },

        _openedChanged: function() {
          if (this._instance) {
            this._getChildrenContainer().opened = this.opened;
            this._instance.notifyPath('opened', this.opened);
            this._setupToggleListener();
          }
        }
      });
    })();
  </script>
</dom-module>
{'fraction_non_alphanumeric': 0.11975141422994184, 'fraction_numerical': 0.001832523304915943, 'mean_word_length': 1.516439454691259, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 31, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6847760', 'n_tokens_mistral': 3317, 'n_tokens_neox': 3189, 'n_words': 665}