<commit_before>import Component from 'ember-component';
import layout from '../templates/components/ivy-tree';
import { readOnly } from 'ember-computed';

function traverse(node, callback, thisArg) {
  let child = node.get('firstChild');

  while (child) {
    callback.call(thisArg, child);
    traverse(child, callback, thisArg);
    child = child.get('nextSibling');
  }
}

export default Component.extend({
  activate(treeitem) {
    this.set('activeDescendant', treeitem);
  },

  ariaActiveDescendant: readOnly('activeDescendant.elementId'),

  ariaRole: 'tree',

  attributeBindings: [
    'ariaActiveDescendant:aria-activedescendant',
    'tabindex'
  ],

  expandAll() {
    traverse(this, function(node) {
      node.expand();
    });
  },

  keyDown(event) {
    switch (event.keyCode) {
      case 13:
        this.toggleExpanded(event);
        break;
      case 35:
        this.moveEnd(event);
        break;
      case 36:
        this.moveHome(event);
        break;
      case 37:
        this.moveLeft(event);
        break;
      case 38:
        this.moveUp(event);
        break;
      case 39:
        this.moveRight(event);
        break;
      case 40:
        this.moveDown(event);
        break;
      case 56:
        if (event.shiftKey) {
          this.expandAll();
          event.preventDefault();
          event.stopPropagation();
        }
        break;
    }
  },

  layout,

  moveDown(event) {
    const activeDescendant = this.get('activeDescendant');

    if (!activeDescendant) {
      return;
    }

    if (activeDescendant.get('hasChildren') && activeDescendant.get('isExpanded')) {
      activeDescendant.get('firstChild').activate();
    } else {
      let node = null;
      let parent = activeDescendant;

      while (!node && parent) {
        node = parent.get('nextSibling');
        parent = parent.get('parent');
      }

      if (node) {
        node.activate();
      }
    }

    event.preventDefault();
    event.stopPropagation();
  },

  moveEnd(event) {
    let node = this.get('lastChild');

    while (node && node.get('hasChildren') && node.get('isExpanded')) {
      node = node.get('lastChild');
    }

    if (node) {
      node.activate();
    }

    event.preventDefault();
    event.stopPropagation();
  },

  moveHome(event) {
    const node = this.get('firstChild');

    if (!node) {
      return;
    }

    node.activate();
    event.preventDefault();
    event.stopPropagation();
  },<commit_msg>Allow down arrow to scroll if at end of the tree<commit_after>import Component from 'ember-component';
import layout from '../templates/components/ivy-tree';
import { readOnly } from 'ember-computed';

function traverse(node, callback, thisArg) {
  let child = node.get('firstChild');

  while (child) {
    callback.call(thisArg, child);
    traverse(child, callback, thisArg);
    child = child.get('nextSibling');
  }
}

export default Component.extend({
  activate(treeitem) {
    this.set('activeDescendant', treeitem);
  },

  ariaActiveDescendant: readOnly('activeDescendant.elementId'),

  ariaRole: 'tree',

  attributeBindings: [
    'ariaActiveDescendant:aria-activedescendant',
    'tabindex'
  ],

  expandAll() {
    traverse(this, function(node) {
      node.expand();
    });
  },

  keyDown(event) {
    switch (event.keyCode) {
      case 13:
        this.toggleExpanded(event);
        break;
      case 35:
        this.moveEnd(event);
        break;
      case 36:
        this.moveHome(event);
        break;
      case 37:
        this.moveLeft(event);
        break;
      case 38:
        this.moveUp(event);
        break;
      case 39:
        this.moveRight(event);
        break;
      case 40:
        this.moveDown(event);
        break;
      case 56:
        if (event.shiftKey) {
          this.expandAll();
          event.preventDefault();
          event.stopPropagation();
        }
        break;
    }
  },

  layout,

  moveDown(event) {
    const activeDescendant = this.get('activeDescendant');

    if (!activeDescendant) {
      return;
    }

    if (activeDescendant.get('hasChildren') && activeDescendant.get('isExpanded')) {
      activeDescendant.get('firstChild').activate();
      event.preventDefault();
      event.stopPropagation();
    } else {
      let node = null;
      let parent = activeDescendant;

      while (!node && parent) {
        node = parent.get('nextSibling');
        parent = parent.get('parent');
      }

      if (node) {
        node.activate();
        event.preventDefault();
        event.stopPropagation();
      }
    }
  },

  moveEnd(event) {
    let node = this.get('lastChild');

    while (node && node.get('hasChildren') && node.get('isExpanded')) {
      node = node.get('lastChild');
    }

    if (node) {
      node.activate();
    }

    event.preventDefault();
    event.stopPropagation();
  },

  moveHome(event) {
    const node = this.get('firstChild');

    if (!node) {
      return;
    }

    node.activate();
    event.preventDefault();
    event.stopPropagation();
  },
{'fraction_non_alphanumeric': 0.14056622450999803, 'fraction_numerical': 0.006335379132844981, 'mean_word_length': 2.336856010568032, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, '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': '897086', 'n_tokens_mistral': 1590, 'n_tokens_neox': 1538, 'n_words': 292}