<commit_before>import CategoricalColumn from '../model/CategoricalColumn';
import AFilterDialog, {filterMissingMarkup} from './AFilterDialog';
import {sortByProperty} from './ADialog';

export default class CategoricalFilterDialog extends AFilterDialog<CategoricalColumn> {

  /**
   * opens a dialog for filtering a categorical column
   * @param column the column to rename
   * @param header the visual header element of this column
   * @param title optional title
   */
  constructor(column: CategoricalColumn, header: HTMLElement, title: string = 'Filter') {
    super(column, header, title);
  }

  openDialog() {
    const bakOri = this.column.getFilter() || {filter: this.column.categories.slice(), filterMissing: false};
    const bak = <string[]>bakOri.filter || this.column.categories.slice();
    const bakMissing = bakOri.filterMissing;
    const popup = this.makePopup(`<div class="selectionTable"><table><thead><th class="selectAll"></th><th>Category</th></thead><tbody></tbody></table></div>
        ${filterMissingMarkup(bakMissing)}<br>`);

    // list all data rows !
    const colors = this.column.categoryColors,
      labels = this.column.categoryLabels;
    const trData = this.column.categories.map(function (d, i) {
      return {cat: d, label: labels[i]!, isChecked: bak.indexOf(d) >= 0, color: colors[i]!};
    }).sort(sortByProperty('label'));

    const base = popup.querySelector('table')!;
    const rows = trData.map((d) => {
      base.insertAdjacentHTML('beforeend', `<tr>
          <td class="checkmark"></td>
          <td class="datalabel">${d.label}</td>
         </tr>`);
      const row = <HTMLElement>base.lastElementChild!;
      row.querySelector('td.checkmark')!.addEventListener('click', () => {
        d.isChecked = !d.isChecked;
        redraw();
      });
      return row;
    });

    function redraw() {
      rows.forEach((row, i) => {
        const d = trData[i];
        (<HTMLElement>row.querySelector('.checkmark')).innerHTML = `<i class="fa fa-${(d.isChecked) ? 'check-' : ''}square-o"></i>`;
        (<HTMLElement>row.querySelector('.datalabel')).style.opacity = d.isChecked ? '1.0' : '.8';
      });
    }

    redraw();

    let isCheckedAll = true;

    function redrawSelectAll() {
      (<HTMLElement>popup.querySelector('.selectAll')).innerHTML = `<i class="fa fa-${(isCheckedAll) ? 'check-' : ''}square-o"></i>`;
    }
    popup.querySelector('thead')!.addEventListener('click', () => {
      isCheckedAll = !isCheckedAll;
      trData.forEach((row) => row.isChecked = isCheckedAll);
      redraw();
      redrawSelectAll();
    });

    const updateData = (filter: string[] | null, filterMissing: boolean) => {
      const noFilter = filter === null && filterMissing === false;
      this.markFiltered(!noFilter);
      this.column.setFilter(noFilter ? null : {filter: filter!, filterMissing});
    };

    this.onButton(popup, {
      cancel: () => updateData(bak, bakMissing),
      reset: () => {
        trData.forEach((d) => d.isChecked = true);
        redraw();
        updateData(null, false);
      },
      submit: () => {<commit_msg>fix #494 hidden selectall checkbox<commit_after>import CategoricalColumn from '../model/CategoricalColumn';
import AFilterDialog, {filterMissingMarkup} from './AFilterDialog';
import {sortByProperty} from './ADialog';

export default class CategoricalFilterDialog extends AFilterDialog<CategoricalColumn> {

  /**
   * opens a dialog for filtering a categorical column
   * @param column the column to rename
   * @param header the visual header element of this column
   * @param title optional title
   */
  constructor(column: CategoricalColumn, header: HTMLElement, title: string = 'Filter') {
    super(column, header, title);
  }

  openDialog() {
    const bakOri = this.column.getFilter() || {filter: this.column.categories.slice(), filterMissing: false};
    const bak = <string[]>bakOri.filter || this.column.categories.slice();
    const bakMissing = bakOri.filterMissing;
    const popup = this.makePopup(`<div class="selectionTable"><table><thead><th class="selectAll"></th><th>Category</th></thead><tbody></tbody></table></div>
        ${filterMissingMarkup(bakMissing)}<br>`);

    // list all data rows !
    const colors = this.column.categoryColors,
      labels = this.column.categoryLabels;
    const trData = this.column.categories.map(function (d, i) {
      return {cat: d, label: labels[i]!, isChecked: bak.indexOf(d) >= 0, color: colors[i]!};
    }).sort(sortByProperty('label'));

    const base = popup.querySelector('table')!;
    const rows = trData.map((d) => {
      base.insertAdjacentHTML('beforeend', `<tr>
          <td class="checkmark"></td>
          <td class="datalabel">${d.label}</td>
         </tr>`);
      const row = <HTMLElement>base.lastElementChild!;
      row.querySelector('td.checkmark')!.addEventListener('click', () => {
        d.isChecked = !d.isChecked;
        redraw();
      });
      return row;
    });

    function redraw() {
      rows.forEach((row, i) => {
        const d = trData[i];
        (<HTMLElement>row.querySelector('.checkmark')).innerHTML = `<i class="fa fa-${(d.isChecked) ? 'check-' : ''}square-o"></i>`;
        (<HTMLElement>row.querySelector('.datalabel')).style.opacity = d.isChecked ? '1.0' : '.8';
      });
    }

    redraw();

    let isCheckedAll = true;

    function redrawSelectAll() {
      (<HTMLElement>popup.querySelector('.selectAll')).innerHTML = `<i class="fa fa-${(isCheckedAll) ? 'check-' : ''}square-o"></i>`;
    }
    popup.querySelector('thead')!.addEventListener('click', () => {
      isCheckedAll = !isCheckedAll;
      trData.forEach((row) => row.isChecked = isCheckedAll);
      redraw();
      redrawSelectAll();
    });
    redrawSelectAll();

    const updateData = (filter: string[] | null, filterMissing: boolean) => {
      const noFilter = filter === null && filterMissing === false;
      this.markFiltered(!noFilter);
      this.column.setFilter(noFilter ? null : {filter: filter!, filterMissing});
    };

    this.onButton(popup, {
      cancel: () => updateData(bak, bakMissing),
      reset: () => {
        trData.forEach((d) => d.isChecked = true);
        redraw();
        updateData(null, false);
      },
      submit: () => {
{'fraction_non_alphanumeric': 0.17070835992342054, 'fraction_numerical': 0.0017549457562220803, 'mean_word_length': 3.3777932960893855, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 83, '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': '511038', 'n_tokens_mistral': 1939, 'n_tokens_neox': 1893, 'n_words': 389}