text:
import {
  Component,
  OnInit
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Location } from '@angular/common';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { AppSettings } from '..';
import { ApiService, DataService, PromptModalComponent, Chart, TextService, NavigateService } from '../common';
import { DialogService } from "ng2-bootstrap-modal";

@Component({
  selector: 'benefits-table',
  styleUrls: ['./benefits-table.component.scss'],
  templateUrl: './benefits-table.component.html'
})
export class BenefitsTableComponent implements OnInit {
  private hideUnpopularThreshold: number;
  private selected: Array<string>;
  private selectedHeadings: Array<{ heading: string, displayText: string, displayTextLeft: string, displayTextRight: string, splitText: boolean }>;
  private view: string;
  private itemPopularity: any = {};
  private dataArray: Array<TableItem>;
  private dataArraySortedPopularity: Array<TableItem>;
  private currentSort: { type: string, asc: boolean };
  private filterOptions: Array<{ name: string, checked: boolean }> = [];
  private selectedItems: Array<number> = [];
  private customHiddenItems: Array<string> = [];
  private hiddenByColumnFilter: any = {};
  private sub: any;
  private pageText: any = {};
  private itemCount: number;
  private filteredColumns: any = {};
  private translatedItems: any = {};
  private translatedSelections: any = {};
  private tableView: { selection: string, items: string };
  private currentSessionFilters: SessionFilters;
  private tabs: Array<PulloutTab> = [];
  private hidingUnpopular: boolean;
  private images: Array<string> = [];
  private imageCount: number = 2;

  constructor(private navigateService: NavigateService, private dataService: DataService, private apiService: ApiService,
    private dialogService: DialogService, private route: ActivatedRoute, private textService: TextService, private location: Location) { }

  public ngOnDestroy() {
    this.dataService.adDiv = document.body.lastElementChild;
    this.dataService.adDiv.setAttribute("hidden", "true");
  }

  public ngOnInit() {
    this.createTabs();
    window.scrollTo(0, 0);
    this.dataService.page = {
      text: 'Table of Health Effects',
      name: 'Benefits Matrix',
      footerMargin: false
    }
    this.sub = this.route
      .queryParams
      .subscribe(params => {
        if (params['table']) {
          this.dataService.showGiahDarmani = true;
          this.apiService.get(AppSettings.API_ROUTES.AD_PAGES + '?name=' + params['table'], true)
            .subscribe(
              data => { console.log(data); this.loadPresetTable(data) },
              error => {
                let customTable = params['customtable'] || '';
                if (customTable) {
                  try {
                    let parsedChart = <Chart>JSON.parse(atob(customTable));
                    this.dataService.selectedChart = parsedChart;
                  } catch (e) {
                    console.error('Could not load custom chart, data malformed.');
                    this.navigateService.navigateTo('home');
                  }
                }
                this.initNoParams();
              }
            );
        } else {
          let customTable = params['customtable'] || '';
          if (customTable) {
            try {
              let parsedChart = <Chart>JSON.parse(atob(customTable));
              this.dataService.selectedChart = parsedChart;
            } catch (e) {
              console.error('Could not load custom chart, data malformed.');
              this.navigateService.navigateTo('home');
            }
          }
          this.initNoParams();
        }
      });

  }

  private initNoParams() {
    //check if it's a custom MyChart
    if (this.dataService.selectedChart && this.dataService.selectedChart.selected) {
      this.init();
      this.view = this.dataService.selectedChart.view;
      this.selected = this.dataService.selectedChart.selected;
      sessionStorage.setItem('view', this.view);
      sessionStorage.setItem('selected', JSON.stringify(this.selected));
      sessionStorage.setItem('currentFilter', JSON.stringify(this.dataService.selectedChart.filters));
      this.dataService.selectedChart = null;
      this.initServiceCall();
    } else {
      //get state of this page
      this.view = sessionStorage.getItem('view');
      let selectedString: string = sessionStorage.getItem('selected' + this.view);
      this.selected = JSON.parse(selectedString);

      if (!this.selected || !this.view) {
        this.navigateService.navigateTo('home');
      } else {
        this.init();
        this.initServiceCall();
      }
    }
  }

  private init = function () {
    this.heading = '';
    this.currentSort = {
      type: '',
      asc: true
    };
    this.filterOptions = [
      { name: 'Beneficial Effect', checked: false },
      { name: 'Assists', checked: false },
      { name: 'Mixed Effects', checked: false },
      { name: 'Inhibits', checked: false },
      { name: 'Negative Effect', checked: false },
      { name: 'Less Popular Items', checked: false },
    ];
    this.textService.getMiscTranslations().subscribe(
      data => this.setTranslations(data),
      error => console.error('Error getting translations: ' + error)
    );
    this.tableView = {
      selection: this.view,
      items: this.view === 'food' ? 'condition' : 'food'
    };
  };

  private setTranslations(data: any) {
    this.pageText.emphasized = data["emphasized"] || "Emphasized";
    this.pageText.beneficial = data["benefits"] || "Benefits";
    this.pageText.assists = data["assists"] || "Assists";
    this.pageText.mixed = data["mixed_effects"] || "Mixed";
    this.pageText.inhibits = data["inhibits"] || "Inhibits";
    this.pageText.negative = data["side_effect"] || "Side Effect";
    this.pageText.helperTitle1 = data["table_help_title_1"] || "Details?";
    this.pageText.helperTitle2 = data["table_help_title_2"] || "References?";
    this.pageText.helperText = data["table_help_text"] || "Click on Green or Red Symbols";
    this.pageText.seeMore = data["table_see_more"] || "Click to see more...";
    this.pageText.seeLess = data["table_see_less"] || "Click to see less...";
    this.dataService.page.text = data["effects_table"] || "Table of Health Effects";
  }

  private initServiceCall = function () {
    // if only 1 column, load images
    if (this.selected.length === 1) {
      for (var i = 0; i < this.imageCount; i++) {
        this.images.push("https://health-foods-matrix.s3.us-west-2.amazonaws.com/images/" + this.selected + "-" + (i + 1) + ".jpg");
      }
    }
    let query: string = '';
    if (this.view === 'food') {
      query = 'foods=' + encodeURIComponent(this.selected.join());
    } else if (this.view === 'condition') {
      query = 'conditions=' + encodeURIComponent(this.selected.join());
    }

    this.textService.getTranslation(this.tableView.selection).subscribe(translatedSelections => {
      this.translatedSelections = translatedSelections;
      this.textService.getTranslation(this.tableView.items).subscribe(translatedItems => {
        this.translatedItems = translatedItems;
        this.apiService.get(AppSettings.API_ROUTES.COMPACT + '?' + query, true)
        .subscribe(data => this.processData(data),
          error => console.error('Error getting all items: ' + error)
        );
      });
    });
    this.loadAd();
  }

  private loadPresetTable(data: PresetTable) {
    // validate table
    if (!data.type || data.items.length < 1) {
      this.initNoParams();
    } else {
      if (AppSettings.LANGUAGE_CODE_MAP[data.language.toLowerCase()]) {
        this.textService.language = data.language;
        if (data.language.toLowerCase() === "persian") {
          this.dataService.showAd = true;
        }
      }
      this.view = data.type.toLowerCase();
      this.selected = data.items;
      sessionStorage.setItem('view', this.view);
      sessionStorage.setItem('selected', JSON.stringify(this.selected));
      sessionStorage.setItem('selected' + this.view, JSON.stringify(this.selected));
      this.location.go("/benefits");
      this.initNoParams();
    }
  }

  private processData(data: Array<any>) {
    this.processSelected();
    let hIndex: number = (this.view === 'food') ? 0 : 1;
    let dIndex: number = (this.view === 'food') ? 1 : 0;
    let dataHash = {};
    this.dataArray = [];
    for (let i = 1; i < data.length; i++) {
      dataHash[data[i][dIndex]] = dataHash[data[i][dIndex]] || {};
      dataHash[data[i][dIndex]][data[i][hIndex]] = {
        effect: data[i][2],
        top: data[i][3]
      };
      this.itemPopularity[data[i][dIndex]] = data[i][4];
    }
    // convert hash to array so we can sort/filter/manipulate easier
    this.itemCount = Object.keys(dataHash).length;

    //get session filter and sort data
    let sessionFilterString: string = sessionStorage.getItem('currentFilter');
    this.currentSessionFilters = (sessionFilterString) ? JSON.parse(sessionFilterString) : {};
    this.currentSessionFilters.hidden = this.currentSessionFilters.hidden || [];
    this.currentSessionFilters.filters = this.currentSessionFilters.filters || [5]; // default filter to 5 (hide unpopular)
    this.currentSessionFilters.columns = this.currentSessionFilters.columns || [];
    this.customHiddenItems = this.currentSessionFilters.hidden;

    for (let item in dataHash) {
      let hidden = false;
      let hiddenIndex = this.currentSessionFilters.hidden.indexOf(item);
      if (hiddenIndex > -1) {
        hidden = true;
      }
      this.dataArray.push({ item: item, displayText: this.translatedItems[item.toLowerCase()] || item, values: dataHash[item], hidden: hidden, selected: false});
    }
    // if conditions view (so data items are foods)
    if (this.view === "condition") {
      let warningQuery = 'foods=';
      this.apiService.get(AppSettings.API_ROUTES.WARNINGS + '?' + warningQuery, true)
        .subscribe(
          data => this.processWarningsData(data),
          error => console.error('Error getting warnings data: ' + error)
        );
    }
    this.hideUnpopularThreshold = this.dataArray.length <= 100 ? 10 : this.dataArray.length * 0.10;
    this.dataArraySortedPopularity = Object.assign([], this.dataArray);
    this.dataArraySortedPopularity.sort(this.popularitySort(1));

    for (let i = 0; i < this.currentSessionFilters.filters.length; i++) {
      this.onFilterChange(this.currentSessionFilters.filters[i], true);
    }
    for (let i = 0; i < this.currentSessionFilters.columns.length; i++) {
      this.columnFilter(this.currentSessionFilters.columns[i]);
    }

    let sort = sessionStorage.getItem('currentSort');
    let sortParsed = JSON.parse(sort);
    if (sortParsed && sortParsed.type) {
      this.currentSort = sortParsed;
      this.currentSort.asc = !sortParsed.asc;
      this.sort(sortParsed.type);
    } else {
      this.sort('popularity');
    }

    this.hidingUnpopular = this.currentSessionFilters.filters.indexOf(5) > -1;
  }

  private processSelected() {
    this.selectedHeadings = [];
    let center = this.textService.rightJustify ? 18 : 15;
    for (let s = 0; s < this.selected.length; s++) {
      let selected = {
        heading: this.selected[s],
        displayText: this.translatedSelections[this.selected[s].toLowerCase()] || this.selected[s],
        displayTextRight: this.translatedSelections[this.selected[s].toLowerCase()] || this.selected[s],
        displayTextLeft: '',
        splitText: false
      };
      this.selectedHeadings.push(selected);
      if (selected.displayText.length > center) {
        let spaces = [], i = -1, closestToCenter = 0;
        while ((i = selected.displayText.indexOf(' ', i+1)) != -1) {
          spaces.push(i);
          closestToCenter = (Math.abs(center - i) < Math.abs(center - closestToCenter)) ? i : closestToCenter;
        }
        //if there are any spaces, break on space closest to center
        if (spaces.length > 0) {
          // let left = selected.displayText.slice(0, closestToCenter);
          // let right = selected.displayText.slice(closestToCenter + 1);
          // this.selectedHeadings[s].displayText = left + this.getSeparator() + right;
          this.selectedHeadings[s].displayTextLeft = selected.displayText.slice(0, closestToCenter);
          this.selectedHeadings[s].displayTextRight = selected.displayText.slice(closestToCenter + 1);
          this.selectedHeadings[s].splitText = true;
        }
        //otherwise hyphenate
        else {
        }
      }
    }
  }

  private processWarningsData(data) {
    for (let item of this.dataArray) {
      item.hasWarning = data[item.item];
    }
  }

  private getIcon = function (benefit): string {
    let icon = '../../assets/img/';
    if (benefit === '1') {
      icon += 'beneficial.png';
    } else if (benefit === '-1') {
      icon += 'negative.png';
    } else if (benefit === '2') {
      icon += 'assist.png';
    } else if (benefit === '-2') {
      icon += 'inhibit.png';
    } else if (benefit === 0) {
      icon += 'mixed.png';
    }
    return icon;
  };

  private getTableHeadingClass = function (splitText: boolean): string {
    let className: string = "table-headings";
    if (this.textService.rightJustify) {
      className += '-rtl';
    }
    if (splitText) {
      className += '-two-line';
    }

    // if (this.selected.length > 1) {
    //   let numbers: string[] = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
    //   className += ' ' + numbers[this.selected.length] + '-col';
    // }
    className += ' ' + "six-col";
    return className;
  };

  private selectItem(item: any, index: number) {
    item.selected = !item.selected;

    if (item.selected) {
      this.selectedItems.push(index);
    } else {
      let i = this.selectedItems.indexOf(index);
      this.selectedItems.splice(i, 1);
    }
  }

  private resetSelection() {
    for (let i of this.selectedItems) {
      this.dataArray[i].selected = false;
    }
    this.selectedItems = [];
  }

  private removeRows() {
    if (this.selectedItems.length > 0) {
      for (let i of this.selectedItems) {
        this.dataArray[i].selected = false;
        this.dataArray[i].hidden = true;
        this.customHiddenItems.push(this.dataArray[i].item);
        if (this.currentSessionFilters.hidden.indexOf(this.dataArray[i].item) === -1) {
          this.currentSessionFilters.hidden.push(this.dataArray[i].item);
        }
      }
      this.selectedItems = [];
      sessionStorage.setItem('currentFilter', JSON.stringify(this.currentSessionFilters));
    }
  }

  private removeRowsBelow() {
    if (this.selectedItems.length > 0) {
      let lowestSelected = 0;
      for (let i of this.selectedItems) {
        lowestSelected = (i > lowestSelected) ? i : lowestSelected;
      }

      for (let i = lowestSelected + 1; i < this.dataArray.length; i++) {
        this.dataArray[i].selected = false;
        this.dataArray[i].hidden = true;
        this.customHiddenItems.push(this.dataArray[i].item);
        if (this.currentSessionFilters.hidden.indexOf(this.dataArray[i].item) === -1) {
          this.currentSessionFilters.hidden.push(this.dataArray[i].item);
        }
      }
      sessionStorage.setItem('currentFilter', JSON.stringify(this.currentSessionFilters));
    }
  }

  private showAllRows() {
    for (let item of this.dataArray) {
      item.hidden = false;
    }
    // this.dataArray = this.dataArray;
    for (let filter of this.filterOptions) {
      filter.checked = false;
    }
    this.customHiddenItems = [];
    this.filteredColumns = {};
    this.currentSessionFilters.hidden = [];
    this.currentSessionFilters.filters = [];
    this.currentSessionFilters.columns = [];
    sessionStorage.setItem('currentFilter', JSON.stringify(this.currentSessionFilters));
  }

  private getSortOrderIcon = function (sortType): string {
    if (this.currentSort && this.currentSort.type === sortType) {
      if (this.currentSort.asc) {
        return '↑';
      } else {
        return '↓';
      }
    }
    return '';
  };

  private sort(sortType: string, column?: string) {
    this.resetSelection();
    this.currentSort.asc = (this.currentSort.type === sortType) ? !this.currentSort.asc : true;
    this.currentSort.type = sortType;
    let orderFactor = (this.currentSort.asc) ? 1 : -1;

    switch (sortType) {
      case 'az':
        this.dataArray.sort(this.alphabeticSort(orderFactor));
        break;

      case 'benefit':
        this.dataArray.sort(this.benefitSort(orderFactor));
        break;

      case 'effect':
        this.dataArray.sort(this.effectSort(orderFactor));
        break;

      case 'popularity':
        this.dataArray.sort(this.popularitySort(orderFactor));
        break;

      case 'column':
        this.dataArray.sort(this.columnSort(orderFactor, column));
        break;
      default:
        this.currentSort.type = 'popularity';
        this.dataArray.sort(this.popularitySort(orderFactor));
        break;
    }
    sessionStorage.setItem('currentSort', JSON.stringify(this.currentSort));
  }

  private alphabeticSort(orderFactor: number): any {
    return function (a, b) {
      if (a.displayText.toLowerCase() < b.displayText.toLowerCase()) {
        return -1 * orderFactor;
      } else if (a.displayText.toLowerCase() > b.displayText.toLowerCase()) {
        return 1 * orderFactor;
      }
      return 0;
    }
  }

  private benefitSort(orderFactor: number): any {
    return function (a, b) {
      let aCount: number = 0, bCount: number = 0;
      for (let item in a.values) {
        if (Number(a.values[item].effect) !== NaN && Number(a.values[item].effect) !== 0) {
          aCount += (Number(a.values[item].effect) > 0) ? 1 : -1;
          aCount += Number(a.values[item].top);
        }
      }
      for (let item in b.values) {
        if (Number(b.values[item].effect) !== NaN && Number(b.values[item].effect) !== 0) {
          bCount += (Number(b.values[item].effect) > 0) ? 1 : -1;
          bCount += Number(b.values[item].top);
        }
      }
      if (aCount > bCount) {
        return -1 * orderFactor;
      } else if (aCount < bCount) {
        return 1 * orderFactor;
      }
      return 0;
    }
  }

  private effectSort(orderFactor: number): any {
    return function (a, b) {
      let aHighlighted: number = 0, bHighlighted: number = 0;
      let aKeys = Object.keys(a.values);
      let bKeys = Object.keys(b.values);
      for (let item in a.values) {
        aHighlighted += Number(a.values[item].top);
      }
      for (let item in b.values) {
        bHighlighted += Number(b.values[item].top);
      }
      if (aKeys.length + aHighlighted > bKeys.length + bHighlighted) {
        return -1 * orderFactor;
      } else if (aKeys.length + aHighlighted < bKeys.length + bHighlighted) {
        return 1 * orderFactor;
      } else {
        let aCount: number = 0, bCount: number = 0;
        for (let item in a.values) {
          if (Number(a.values[item].effect) !== NaN && Number(a.values[item].effect) !== 0) {
            aCount += (Number(a.values[item].effect) > 0) ? 1 : -1;
            aCount += Number(a.values[item].top);
          }
        }
        for (let item in b.values) {
          if (Number(b.values[item].effect) !== NaN && Number(b.values[item].effect) !== 0) {
            bCount += (Number(b.values[item].effect) > 0) ? 1 : -1;
            bCount += Number(b.values[item].top);
          }
        }
        if (aCount > bCount) {
          return -1 * orderFactor;
        } else if (aCount < bCount) {
          return 1 * orderFactor;
        }
        return 0;
      }
    }
  }
  private popularitySort(orderFactor: number): any {
    return (a, b) => {
      if (Number(this.itemPopularity[a.item]) < Number(this.itemPopularity[b.item])) {
        return 1 * orderFactor;
      } else if (Number(this.itemPopularity[a.item]) > Number(this.itemPopularity[b.item])) {
        return -1 * orderFactor;
      }
      return 0;
    }
  }

  private columnSort(orderFactor: number, column: string): any {
    orderFactor = 1;
    return function (a, b) {
      let aValue = a.values[column].effect || -3;
      let bValue = b.values[column].effect || -3;
      if (aValue > bValue) {
        return -1 * orderFactor;
      } else if (aValue < bValue) {
        return 1 * orderFactor;
      }
      return 0;
    }
  }

  private columnFilter(column: string): any {
    // if filter already exists, unfilter
    if (this.hiddenByColumnFilter[column] && this.hiddenByColumnFilter[column].length > 0) {
      for (let i = 0; i < this.hiddenByColumnFilter[column].length; i++) {
        let item = this.hiddenByColumnFilter[column][i];
        if (this.currentSessionFilters.hidden.indexOf(this.dataArray[item].item) === -1) {
          this.dataArray[item].hidden = false;
        }
      }
      this.filteredColumns[column] = false;

      //re-apply all other filters
      this.hiddenByColumnFilter = {};
      for (let col in this.filteredColumns) {
        if (this.filteredColumns[col]) {
          this.columnFilter(col);
        }
      }
      for (let i = 0; i < this.currentSessionFilters.filters.length; i++) {
        this.onFilterChange(this.currentSessionFilters.filters[i], true);
      }

      if (this.currentSessionFilters.columns.indexOf(column) > -1) {
        this.currentSessionFilters.columns.splice(this.currentSessionFilters.columns.indexOf(column), 1);
      }
    }
    //else filter by column
    else {
      this.hiddenByColumnFilter[column] = [];
      for (let i = 0; i < this.dataArray.length; i++) {
        if (this.dataArray[i].values[column] == undefined) {
          this.dataArray[i].selected = false;
          this.dataArray[i].hidden = true;
          this.hiddenByColumnFilter[column].push(i);
        }
      }
      this.selectedItems = [];
      this.filteredColumns[column] = true;
      if (this.currentSessionFilters.columns.indexOf(column) === -1) {
        this.currentSessionFilters.columns.push(column);
      }
    }
    sessionStorage.setItem('currentFilter', JSON.stringify(this.currentSessionFilters));
  }

  private onFilterChange(index: number, newValue: boolean): void {
    this.resetSelection();
    this.filterOptions[index].checked = newValue;
    let beneficial: boolean = this.filterOptions[0].checked;
    let assist: boolean = this.filterOptions[1].checked;
    let mixed: boolean = this.filterOptions[2].checked;
    let inhibits: boolean = this.filterOptions[3].checked;
    let negative: boolean = this.filterOptions[4].checked;
    let unpopular: boolean = this.filterOptions[5].checked;
    this.hidingUnpopular = unpopular;

    for (let item of this.dataArray) {
      let matchCount: number = 0;
      let valuesCount: number = 0;
      for (let value in item.values) {
        valuesCount++;
        let itemVal = Number(item.values[value].effect);
        if (itemVal !== NaN) {
          if ((beneficial && itemVal === 1) ||
            (assist && itemVal === 2) ||
            (mixed && itemVal === 0) ||
            (inhibits && itemVal === -2) ||
            (negative && itemVal === -1) ||
            (unpopular && this.shouldHideUnpopular(item))) {
            matchCount++;
          }
        }
      }
    //  let hiddenItems: Array<string> = this.currentSessionFilters.hidden || [];
      if (matchCount === valuesCount) {
        item.hidden = true;
      } else {
        item.hidden = false;
      }
      for (let i = 0; i < this.currentSessionFilters.hidden.length; i++) {
        if (this.currentSessionFilters.hidden[i] === item.item) {
          item.hidden = true;
          break;
        }
      }
    // let hiddenIndex: number =  this.customHiddenItems.indexOf(item.item);
      // if (item.hidden && hiddenIndex === -1) {
      //   this.customHiddenItems.push(item.item);
      // } else if (!item.hidden && hiddenIndex > -1) {
      //  this.customHiddenItems.splice(hiddenIndex, 1);
      // }
      // this.currentSessionFilters.hidden =  this.customHiddenItems;

    }
      //update session filters
      if (newValue && this.currentSessionFilters.filters.indexOf(index) === -1) {
        this.currentSessionFilters.filters.push(index);
      } else if (!newValue && this.currentSessionFilters.filters.indexOf(index) > -1) {
        this.currentSessionFilters.filters.splice(this.currentSessionFilters.filters.indexOf(index), 1)
      }
      sessionStorage.setItem('currentFilter', JSON.stringify(this.currentSessionFilters));
  }

  private shouldHideUnpopular(tableItem: TableItem): boolean {
    //HACK - using duplicated array, find a better way
    // if table length < 100, show 20 items (or all items if less than 20)
    // otherwise only return top 20% popular items
    for (let i = 0; i < this.hideUnpopularThreshold; i++) {
      if (this.dataArraySortedPopularity[i].item == tableItem.item) {
        return false;
      }
    }

    return true;
  };

  private saveChart() {
    let disposable = this.dialogService.addDialog(PromptModalComponent, {
      title: 'Save Chart',
      question: 'Chart Name:'
    })
      .subscribe((message) => {
        if (message) {
          let c: string = localStorage.getItem('myCharts');
          let charts: Array<Chart> = [];
          if (c) {
            charts = JSON.parse(c);
          }
          let chartData = {
            name: message,
            filters: this.currentSessionFilters,
            selected: this.selected,
            view: this.view
          };
          charts.push(chartData);
          localStorage.setItem('myCharts', JSON.stringify(charts));
        }
      })
  }

  private goToDetails(selection, i) {
    if (this.view === 'food') {
      let details = { food: selection, condition: this.dataArray[i].item };
      sessionStorage.setItem('details', JSON.stringify(details));
    }
    else {
      let details = { food: this.dataArray[i].item, condition: selection };
      sessionStorage.setItem('details', JSON.stringify(details));
    }
    this.navigateService.navigateTo('details');
  }

  private showEnglish() {
    for (let index of this.selectedItems) {
      this.dataArray[index].showEnglish = true;
    }
  }

  private removeAllEnglish() {
    for (let item of this.dataArray) {
      item.showEnglish = false;
    }
  }

  private toggleSeeMore() {
    this.hidingUnpopular = !this.hidingUnpopular;
    this.onFilterChange(5, this.hidingUnpopular);
  }

  private createTabs(): void {
    let tabNames: Array<string> = [
      "Help", "Sort", "Filter", "Save", "Icons", "Translate"
    ];
    let tabHeight: number = 1. / tabNames.length * 85;

    for (let i = 0; i < tabNames.length; i++) {
      this.tabs.push({
        name: tabNames[i],
        image: "../../assets/img/tab-" + tabNames[i].toLowerCase() + ".png",
        height: tabHeight,
        top: tabHeight * i + 1 * i,
        hidden: tabNames[i] === this.textService.language
      });
    }
    console.log(this.tabs);
  }

  private openTab(tab: PulloutTab): void {
    if (tab.name === "Save") {
      this.saveChart();
      return;
    }
    if (tab.name === "Translate") {
      this.navigateService.navigateTo('language');
    }
    if (tab.active) {
      tab.active = false;
      return;
    }
    for (let t of this.tabs) {
      t.active = false;
    }
    tab.active = true;
  }

  private loadAd(): void {
    // if (this.dataService.adDiv) {
    //   this.dataService.adDiv.removeAttribute("hidden");
    //   return;
    // }

    // if (this.dataService.showAd) {
    //   var slotDom: Element = document.getElementById("ad-slot");
    //   for (var keys = Object.keys(window["clickyab_ad"]), i = 0; i < keys.length; i++) {
    //     window["clickyab_ad"][keys[i]] && slotDom.setAttribute("clickyab-" + keys[i], window["clickyab_ad"][keys[i]]);
    //   }
    //   // window["addEventListener("DOMContentLoaded", function() {
    //   window["totalOfClickyabShowAd"] = window["totalOfClickyabShowAd"] || 1;
    //   window["countOfClickyabShowAd"] = window["countOfClickyabShowAd"] ? window["countOfClickyabShowAd"] + 1 : 1;
    //   window["totalOfClickyabShowAd"] === window["countOfClickyabShowAd"] && (i = 0);
    //   window["clickyabParams"] = {
    //     id: window["clickyab_ad"].id,
    //     domain: window["clickyab_ad"].domain
    //   };
    //   if (!document.getElementById("clickyab-show-js-v2")) {
    //     window["injectClickyabMultiJs"] = !0;
    //     var s = document.createElement("script");
    //     s.async = true;
    //     s.type = "text/javascript";
    //     s.id = "clickyab-show-js-v2";
    //     s.src = "//supplier.clickyab.com/api/multi.js";
    //     document.body.appendChild(s);
    //   }
    //   // }, !1),
    // }
  }
}

export interface PulloutTab {
  name: string;
  image: string;
  height: number;
  top: number;
  active?: boolean;
  hidden?: boolean;
}

export interface TableItem {
  item: string,
  displayText: string,
  values: Array<{
    effect: string,
    top: string,
  }>,
  hidden: boolean,
  selected: boolean,
  showEnglish?: boolean,
  hasWarning?: boolean
}

export interface SessionFilters {
  hidden: Array<any>;
  filters: Array<any>;
  columns: Array<any>;
}

export interface PresetTable {
  name: string;
  language: string;
  type: string;
  items: Array<string>;
}


text:
<?php $this->beginContent('application.modules_core.notification.views.notificationLayoutMail', array('notification' => $notification, 'showSpace' => true)); ?>
<?php

echo Yii::t('TasksModule.views_notifications_taskAssigned', '{userName} assigned you to the task {task}.', array(
    '{userName}' => '' . CHtml::encode($creator->displayName) . '',
    '{task}' => '' . NotificationModule::formatOutput($targetObject->getContentTitle()) . ''
));
?>
<?php $this->endContent(); ?>

redpajama_set_name: RedPajamaGithub


text:
package org.apache.camel.spring.handler;

import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.apache.camel.spring.CamelRedeliveryPolicyFactoryBean;
import org.apache.camel.spring.ErrorHandlerType;
import org.apache.camel.util.ObjectHelper;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
 * The DefinitionParser to deal with the ErrorHandler
 */
public class ErrorHandlerDefinitionParser extends BeanDefinitionParser {
    protected BeanDefinitionParser redeliveryPolicyParser = new RedeliveryPolicyDefinitionParser(CamelRedeliveryPolicyFactoryBean.class);

    public ErrorHandlerDefinitionParser() {
        // need to override the default
        super(null, false);
    }

    protected Class<?> getBeanClass(Element element) {
        ErrorHandlerType type = ErrorHandlerType.DefaultErrorHandler;

        if (ObjectHelper.isNotEmpty(element.getAttribute("type"))) {
            type = ErrorHandlerType.valueOf(element.getAttribute("type"));
        }
        return type.getTypeAsClass();
    }

    protected boolean isEligibleAttribute(String attributeName) {
        if (attributeName == null || ID_ATTRIBUTE.equals(attributeName)) {
            return false;
        }
        if (attributeName.equals("xmlns") || attributeName.startsWith("xmlns:")) {
            return false;
        }
        return  !attributeName.equals("type")
                && !attributeName.equals("onRedeliveryRef")
                && !attributeName.equals("onRetryWhileRef")
                && !attributeName.equals("redeliveryPolicyRef")
                && !attributeName.equals("transactionTemplateRef")
                && !attributeName.equals("transactionManagerRef");
    }

    @Override
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
        super.doParse(element, parserContext, builder);

        String id = element.getAttribute("id");

        ErrorHandlerType type = ErrorHandlerType.DefaultErrorHandler;
        if (ObjectHelper.isNotEmpty(element.getAttribute("type"))) {
            type = ErrorHandlerType.valueOf(element.getAttribute("type"));
        }
        if (type.equals(ErrorHandlerType.DefaultErrorHandler)
            || type.equals(ErrorHandlerType.DeadLetterChannel)
            || type.equals(ErrorHandlerType.TransactionErrorHandler)) {
            NodeList list = element.getChildNodes();
            int size = list.getLength();
            for (int i = 0; i < size; i++) {
                Node child = list.item(i);
                if (child instanceof Element) {
                    Element childElement = (Element)child;
                    String localName = child.getLocalName();
                    // set the redeliveryPolicy
                    if (localName.equals("redeliveryPolicy")) {
                        // cannot have redeliveryPolicyRef attribute as well, only one is allowed
                        if (ObjectHelper.isNotEmpty(element.getAttribute("redeliveryPolicyRef"))) {
                            throw new IllegalArgumentException("Cannot set both redeliveryPolicyRef and redeliveryPolicy,"
                                    + " only one allowed, in error handler with id: " + id);
                        }
                        BeanDefinition redeliveryPolicyDefinition = redeliveryPolicyParser.parse(childElement, parserContext);
                        builder.addPropertyValue(localName, redeliveryPolicyDefinition);
                    }
                }
            }
            parserRefAttribute(element, "onRedeliveryRef", "onRedelivery", builder);
            parserRefAttribute(element, "onRetryWhileRef", "onRetryWhile", builder);
            parserRefAttribute(element, "redeliveryPolicyRef", "redeliveryPolicy", builder);
            if (type.equals(ErrorHandlerType.TransactionErrorHandler)) {
                parserRefAttribute(element, "transactionTemplateRef", "transactionTemplate", builder);
                parserRefAttribute(element, "transactionManagerRef", "transactionManager", builder);
            }
        }

        // validate attributes according to type

        String deadLetterUri = element.getAttribute("deadLetterUri");
        if (ObjectHelper.isNotEmpty(deadLetterUri) && !type.equals(ErrorHandlerType.DeadLetterChannel)) {
            throw new IllegalArgumentException("Attribute deadLetterUri can only be used if type is "
                    + ErrorHandlerType.DeadLetterChannel.name() + ", in error handler with id: " + id);
        }
        String transactionTemplateRef = element.getAttribute("transactionTemplateRef");
        if (ObjectHelper.isNotEmpty(transactionTemplateRef) && !type.equals(ErrorHandlerType.TransactionErrorHandler)) {
            throw new IllegalArgumentException("Attribute transactionTemplateRef can only be used if type is "
                    + ErrorHandlerType.TransactionErrorHandler.name() + ", in error handler with id: " + id);
        }
        String transactionManagerRef = element.getAttribute("transactionManagerRef");
        if (ObjectHelper.isNotEmpty(transactionManagerRef) && !type.equals(ErrorHandlerType.TransactionErrorHandler)) {
            throw new IllegalArgumentException("Attribute transactionManagerRef can only be used if type is "
                    + ErrorHandlerType.TransactionErrorHandler.name() + ", in error handler with id: " + id);
        }
        String rollbackLoggingLevel = element.getAttribute("rollbackLoggingLevel");
        if (ObjectHelper.isNotEmpty(rollbackLoggingLevel) && (!type.equals(ErrorHandlerType.TransactionErrorHandler))) {
            throw new IllegalArgumentException("Attribute rollbackLoggingLevel can only be used if type is "
                    + ErrorHandlerType.TransactionErrorHandler.name() + ", in error handler with id: " + id);
        }
        String useOriginalMessage = element.getAttribute("useOriginalMessage");
        if (ObjectHelper.isNotEmpty(useOriginalMessage) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
            throw new IllegalArgumentException("Attribute useOriginalMessage is not supported by error handler type: "
                    + type.name() + ", in error handler with id: " + id);
        }
        String onRedeliveryRef = element.getAttribute("onRedeliveryRef");
        if (ObjectHelper.isNotEmpty(onRedeliveryRef) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
            throw new IllegalArgumentException("Attribute onRedeliveryRef is not supported by error handler type: "
                    + type.name() + ", in error handler with id: " + id);
        }
        String retryWhileRef = element.getAttribute("retryWhileRef");
        if (ObjectHelper.isNotEmpty(retryWhileRef) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
            throw new IllegalArgumentException("Attribute retryWhileRef is not supported by error handler type: "
                    + type.name() + ", in error handler with id: " + id);
        }
        String redeliveryPolicyRef = element.getAttribute("redeliveryPolicyRef");
        if (ObjectHelper.isNotEmpty(redeliveryPolicyRef) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
            throw new IllegalArgumentException("Attribute redeliveryPolicyRef is not supported by error handler type: "
                    + type.name() + ", in error handler with id: " + id);
        }
        String executorServiceRef = element.getAttribute("executorServiceRef");
        if (ObjectHelper.isNotEmpty(executorServiceRef) && (type.equals(ErrorHandlerType.LoggingErrorHandler) || type.equals(ErrorHandlerType.NoErrorHandler))) {
            throw new IllegalArgumentException("Attribute executorServiceRef is not supported by error handler type: "
                    + type.name() + ", in error handler with id: " + id);
        }
        String logName = element.getAttribute("logName");
        if (ObjectHelper.isNotEmpty(logName) && (!type.equals(ErrorHandlerType.LoggingErrorHandler))) {
            throw new IllegalArgumentException("Attribute logName is not supported by error handler type: "
                    + type.name() + ", in error handler with id: " + id);
        }
        String level = element.getAttribute("level");
        if (ObjectHelper.isNotEmpty(level) && (!type.equals(ErrorHandlerType.LoggingErrorHandler))) {
            throw new IllegalArgumentException("Attribute level is not supported by error handler type: "
                    + type.name() + ", in error handler with id: " + id);
        }
    }

    private void parserRefAttribute(Element element, String attributeName, String propertyName, BeanDefinitionBuilder builder) {
        NamedNodeMap attributes = element.getAttributes();
        for (int x = 0; x < attributes.getLength(); x++) {
            Attr attribute = (Attr) attributes.item(x);
            String name = attribute.getLocalName();
            if (name.equals(attributeName)) {
                Assert.state(StringUtils.hasText(propertyName),
                        "Illegal property name returned from 'extractPropertyName(String)': cannot be null or empty.");
                builder.addPropertyReference(propertyName, attribute.getValue());
            }
        }
    }

    protected class RedeliveryPolicyDefinitionParser extends BeanDefinitionParser {

        public RedeliveryPolicyDefinitionParser(Class<?> type) {
            super(type, false);
        }

        protected boolean shouldGenerateId() {
            return true;
        }
    }

}


text:
import { createSelector } from 'reselect';

const emptyObj = {};

export const areTagsLoading = state => state.tags.didInvalidate;
export const getTagIds = state => state.tags.items.result;
export const getTagEntities = state => state.tags.items.entities.tags || emptyObj;

export const getTags = createSelector(
  [getTagIds, getTagEntities],
  (tagIds, tagEntities) => tagIds.map(id => tagEntities[id])
);

export const getTagById = (state, props) => getTagEntities(state)[typeof props === 'object' ? props.tagId : props];


text:
package io.enmasse.controller.standard;

/**
 * Template parameters that are dynamically set by the standard controller.
 */
public interface TemplateParameter {
    String NAME = "NAME";
    String ADDRESS = "ADDRESS";
    String INFRA_UUID = "INFRA_UUID";
    String ADDRESS_SPACE = "ADDRESS_SPACE";
    String CLUSTER_ID = "CLUSTER_ID";

    String AUTHENTICATION_SERVICE_HOST = "AUTHENTICATION_SERVICE_HOST";
    String AUTHENTICATION_SERVICE_PORT = "AUTHENTICATION_SERVICE_PORT";
    String AUTHENTICATION_SERVICE_CA_SECRET = "AUTHENTICATION_SERVICE_CA_SECRET";
    String AUTHENTICATION_SERVICE_CLIENT_SECRET = "AUTHENTICATION_SERVICE_CLIENT_SECRET";
    String AUTHENTICATION_SERVICE_SASL_INIT_HOST = "AUTHENTICATION_SERVICE_SASL_INIT_HOST";
    String REPLICAS = "REPLICAS";

    String BROKER_MEMORY_LIMIT = "BROKER_MEMORY_LIMIT";
    String BROKER_ADDRESS_FULL_POLICY = "BROKER_ADDRESS_FULL_POLICY";
    String BROKER_STORAGE_CAPACITY = "BROKER_STORAGE_CAPACITY";
    String BROKER_GLOBAL_MAX_SIZE = "BROKER_GLOBAL_MAX_SIZE";
    String BROKER_CONNECTOR_NETTY_THREADS = "BROKER_CONNECTOR_NETTY_THREADS";
    String BROKER_CONNECTOR_IDLE_TIMEOUT_MS = "BROKER_CONNECTOR_IDLE_TIMEOUT_MS";
    String BROKER_JAVA_OPTS = "BROKER_JAVA_OPTS";

    String IMAGE_PULL_POLICY = "IMAGE_PULL_POLICY";
    String BROKER_IMAGE = "BROKER_IMAGE";
    String BROKER_PLUGIN_IMAGE = "BROKER_PLUGIN_IMAGE";
    String TOPIC_FORWARDER_IMAGE = "TOPIC_FORWARDER_IMAGE";

    String BROKER_TREAT_REJECT_AS_UNMODIFIED_DELIVERY_FAILED = "BROKER_TREAT_REJECT_AS_UNMODIFIED_DELIVERY_FAILED";
    String BROKER_USE_MODIFIED_FOR_TRANSIENT_DELIVERY_ERRORS = "BROKER_USE_MODIFIED_FOR_TRANSIENT_DELIVERY_ERRORS";
    String BROKER_MIN_LARGE_MESSAGE_SIZE = "BROKER_MIN_LARGE_MESSAGE_SIZE";

    String ENABLE_GLOBAL_DLQ = "ENABLE_GLOBAL_DLQ";
}


text:
//  This example shows how to create a simple lexer recognizing a couple of
//  different tokens aimed at a simple language and how to use this lexer with
//  a grammar. It shows how to associate attributes to tokens and how to access
//  the token attributes from inside the grammar.
//
//  We use explicit token attribute types, making the corresponding token instances
//  carry convert the matched input into an instance of that type. The token
//  attribute is exposed as the parser attribute if this token is used as a
//  parser component somewhere in a grammar.
//
//  Additionally, this example demonstrates, how to define a token set usable
//  as the skip parser during parsing, allowing to define several tokens to be
//  ignored.
//
//  This example recognizes a very simple programming language having
//  assignment statements and if and while control structures. Look at the file
//  example4.input for an example.

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

#include <iostream>
#include <fstream>
#include <string>

#include "example.hpp"

using namespace boost::spirit;
using boost::phoenix::val;

///////////////////////////////////////////////////////////////////////////////
//  Token definition
///////////////////////////////////////////////////////////////////////////////
template <typename Lexer>
struct example4_tokens : lex::lexer<Lexer>
{
    example4_tokens()
    {
        // define the tokens to match
        identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
        constant = "[0-9]+";
        if_ = "if";
        else_ = "else";
        while_ = "while";

        // associate the tokens and the token set with the lexer
        this->self = lex::token_def<>('(') | ')' | '{' | '}' | '=' | ';' | constant;
        this->self += if_ | else_ | while_ | identifier;

        // define the whitespace to ignore (spaces, tabs, newlines and C-style
        // comments)
        this->self("WS")
            =   lex::token_def<>("[ \\t\\n]+")
            |   "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"
            ;
    }

//[example4_token_def
    // these tokens expose the iterator_range of the matched input sequence
    lex::token_def<> if_, else_, while_;

    // The following two tokens have an associated attribute type, 'identifier'
    // carries a string (the identifier name) and 'constant' carries the
    // matched integer value.
    //
    // Note: any token attribute type explicitly specified in a token_def<>
    //       declaration needs to be listed during token type definition as
    //       well (see the typedef for the token_type below).
    //
    // The conversion of the matched input to an instance of this type occurs
    // once (on first access), which makes token attributes as efficient as
    // possible. Moreover, token instances are constructed once by the lexer
    // library. From this point on tokens are passed by reference only,
    // avoiding them being copied around.
    lex::token_def<std::string> identifier;
    lex::token_def<unsigned int> constant;
//]
};

///////////////////////////////////////////////////////////////////////////////
//  Grammar definition
///////////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Lexer>
struct example4_grammar
  : qi::grammar<Iterator, qi::in_state_skipper<Lexer> >
{
    template <typename TokenDef>
    example4_grammar(TokenDef const& tok)
      : example4_grammar::base_type(program)
    {
        using boost::spirit::_val;

        program
            =  +block
            ;

        block
            =   '{' >> *statement >> '}'
            ;

        statement
            =   assignment
            |   if_stmt
            |   while_stmt
            ;

        assignment
            =   (tok.identifier >> '=' >> expression >> ';')
                [
                    std::cout << val("assignment statement to: ") << _1 << "\n"
                ]
            ;

        if_stmt
            =   (   tok.if_ >> '(' >> expression >> ')' >> block
                    >> -(tok.else_ >> block)
                )
                [
                    std::cout << val("if expression: ") << _2 << "\n"
                ]
            ;

        while_stmt
            =   (tok.while_ >> '(' >> expression >> ')' >> block)
                [
                    std::cout << val("while expression: ") << _2 << "\n"
                ]
            ;

        //  since expression has a variant return type accommodating for
        //  std::string and unsigned integer, both possible values may be
        //  returned to the calling rule
        expression
            =   tok.identifier [ _val = _1 ]
            |   tok.constant   [ _val = _1 ]
            ;
    }

    typedef boost::variant<unsigned int, std::string> expression_type;

    qi::rule<Iterator, qi::in_state_skipper<Lexer> > program, block, statement;
    qi::rule<Iterator, qi::in_state_skipper<Lexer> > assignment, if_stmt;
    qi::rule<Iterator, qi::in_state_skipper<Lexer> > while_stmt;

    //  the expression is the only rule having a return value
    qi::rule<Iterator, expression_type(), qi::in_state_skipper<Lexer> >  expression;
};

///////////////////////////////////////////////////////////////////////////////
int main()
{
    // iterator type used to expose the underlying input stream
    typedef std::string::iterator base_iterator_type;

//[example4_token
    // This is the lexer token type to use. The second template parameter lists
    // all attribute types used for token_def's during token definition (see
    // calculator_tokens<> above). Here we use the predefined lexertl token
    // type, but any compatible token type may be used instead.
    //
    // If you don't list any token attribute types in the following declaration
    // (or just use the default token type: lexertl_token<base_iterator_type>)
    // it will compile and work just fine, just a bit less efficient. This is
    // because the token attribute will be generated from the matched input
    // sequence every time it is requested. But as soon as you specify at
    // least one token attribute type you'll have to list all attribute types
    // used for token_def<> declarations in the token definition class above,
    // otherwise compilation errors will occur.
    typedef lex::lexertl::token<
        base_iterator_type, boost::mpl::vector<unsigned int, std::string>
    > token_type;
//]
    // Here we use the lexertl based lexer engine.
    typedef lex::lexertl::lexer<token_type> lexer_type;

    // This is the token definition type (derived from the given lexer type).
    typedef example4_tokens<lexer_type> example4_tokens;

    // this is the iterator type exposed by the lexer
    typedef example4_tokens::iterator_type iterator_type;

    // this is the type of the grammar to parse
    typedef example4_grammar<iterator_type, example4_tokens::lexer_def> example4_grammar;

    // now we use the types defined above to create the lexer and grammar
    // object instances needed to invoke the parsing process
    example4_tokens tokens;                         // Our lexer
    example4_grammar calc(tokens);                  // Our parser

    std::string str (read_from_file("example4.input"));

    // At this point we generate the iterator pair used to expose the
    // tokenized input stream.
    std::string::iterator it = str.begin();
    iterator_type iter = tokens.begin(it, str.end());
    iterator_type end = tokens.end();

    // Parsing is done based on the token stream, not the character
    // stream read from the input.
    // Note how we use the lexer defined above as the skip parser. It must
    // be explicitly wrapped inside a state directive, switching the lexer
    // state for the duration of skipping whitespace.
    bool r = qi::phrase_parse(iter, end, calc, qi::in_state("WS")[tokens.self]);

    if (r && iter == end)
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing succeeded\n";
        std::cout << "-------------------------\n";
    }
    else
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing failed\n";
        std::cout << "-------------------------\n";
    }

    std::cout << "Bye... :-) \n\n";
    return 0;
}


text:
!function()
{"use strict";root.define("atomic.html.multiselect", function htmlMultiSelect(base)
{
    function setSelectListValues(values)
    {
        if (typeof values === "function")   values = values();
        if ( !Array.isArray(values)) values  = [values];
        this.__rawValue = values;
        if (this.__element.options.length > 0) for(var counter=0;counter<this.__element.options.length;counter++) this.__element.options[counter].selected = values.indexOf(this.__element.options[counter].rawValue) > -1;
    }
    function getSelectListValues()
    {
        if (this.__element.options.length == 0) return this.__rawValue;
        var values  = [];
        if (this.__element.options.length > 0) for(var counter=0;counter<this.__element.options.length;counter++) if (this.__element.options[counter].selected)   values.push(this.__element.options[counter].rawValue);
        return this.__rawValue = values;
    }
    function multiselect(elements, selector, parent)
    {
        base.call(this, elements, selector, parent);
        this.__binder.defineDataProperties(this,
        {
            value:  {get: function(){return getSelectListValues.call(this);}, set: function(value){setSelectListValues.call(this, value===undefined?null:value);},  onchange: this.getEvents("change")}
        });
    }
    Object.defineProperty(multiselect, "prototype", {value: Object.create(base.prototype)});
    Object.defineProperties(multiselect.prototype,
    {
        constructor:        {value: multiselect},
        __createNode:       {value: function(){var element = document.createElement("select"); element.multiple="multiple"; return element;}, configurable: true},
        count:              {get:   function(){ return this.__element.options.length; }},
        selectedIndexes:    {get:   function(){ return this.__element.selectedIndex; },   set: function(value){ this.__element.selectedIndex=value; }},
        size:               {get:   function(){ return this.__element.size; },            set: function(value){ this.__elements[0].size=value; }},
        __isValueSelected:  {value: function(value){return Array.isArray(this.__rawValue) && this.__rawValue.indexOf(value) > -1;}}
    });
    return multiselect;
});}();


text:
from logging import getLogger
from pyprol.measurement import measurement

import importlib

log = getLogger('pyprol.instrumentations.paste')

def inject(config):
    try:
        paste_httpserver = importlib.import_module('paste.httpserver')

        _org_wsgi_start_respone = paste_httpserver.WSGIHandlerMixin.wsgi_start_response

        def wsgi_start_response(self, status, response_headers, exc_info=None):
            measure = measurement.enable(
                    "paste.httpserver.WSGIHandlerMixin.wsgi_start_response")
            result = _org_wsgi_start_respone(self, status, response_headers,
                    exc_info)
            measurement.disable(measure)
            return result

        paste_httpserver.WSGIHandlerMixin.wsgi_start_response = wsgi_start_response
        log.info("injected into paste.httpserver.WSGIHandlerMixin.wsgi_start_response")

    except ImportError:
        log.info("No `paste` in current context.")


text:
import { Injectable } from '@angular/core';
import { Action, Selector, State, StateContext } from '@ngxs/store';

import { AppAboutDetails } from '../../interfaces/about/about-details.interface';
import { aboutActions } from './about.actions';
import { ABOUT_STATE_TOKEN, IAppAboutStateModel, TAppAboutPayload } from './about.interface';

@State<IAppAboutStateModel>({
  name: ABOUT_STATE_TOKEN,
  defaults: {
    details: new AppAboutDetails(),
  },
})
@Injectable()
export class AppAboutState {
  @Selector()
  public static getState(state: IAppAboutStateModel) {
    return state;
  }

  @Selector()
  public static getDetails(state: IAppAboutStateModel) {
    return state.details;
  }

  @Action(aboutActions.setAppAboutState)
  public setAppAboutState(ctx: StateContext<IAppAboutStateModel>, { payload }: TAppAboutPayload) {
    return ctx.patchState(payload);
  }
}