<commit_before>const IGNORE_PROTOTYPE = true
const IS_SORT_BY_PERCENT = true
const DEFAULT_FILTER_LENGTH = 66
const DEFAULT_CATEGORY = 'N/A'
const SIMILAR_PAGE_SIZE = 10

const regexWholeWord = /^\w+$/i
const globalDictionary = {}
const globalPhrases = {}
let globalData
let maxSimilarPageCount

const vm = new Vue({
  el: '#app',
  data: {
    searchForm: {
      category: DEFAULT_CATEGORY,
      text: '',
      isWord: false,
      type: 'text',
      filterLength: DEFAULT_FILTER_LENGTH,
      similarPageNumber: 0
    },
    category: {
      show: false,
      totalPercent: 0,
      items: []
    },
    dialog: {
      show: false,
      title: '',
      newKey: '',
      newValue: '',
      items: []
    }
  },
  computed: {
    section() {
      return this.dialog.title.toLowerCase()
    }
  },
  methods: {
    showCategory() {
      this.category.show = !this.category.show
    },
    search(event) {
      this.category.show = false
      this.dialog.show = false
      this.searchForm.similarPageNumber = 0

      if (event.target.tagName === 'A') {
        this.searchForm.category = event.target.textContent
        this.searchForm.text = ''
      } else if (event.target.name !== 'filterLength') {
        this.searchForm.category = DEFAULT_CATEGORY
      }

      searchInternal(this.searchForm)
    },
    showDialog(event) {
      const title = event.target.textContent

      if (this.dialog.title === title && this.dialog.show) {
        this.dialog.show = false
      } else {
        this.dialog.show = true
        this.dialog.title = title
        this.dialog.newKey = ''
        this.dialog.newValue = ''
        this.dialog.items = objectToItems(globalData[this.section])

        Vue.nextTick(() => document.getElementById('newKey').focus())
      }
    },
    closeDialog() {
      this.dialog.show = false

      forEachTextBoxes('dialogList', textBox => resetTextBoxStyle(textBox))
    },
    addRow() {
      const key = this.section === 'dictionary' ? this.dialog.newKey.toLowerCase() : this.dialog.newKey
      const value = this.dialog.newValue

      if (key === '') return

      if (globalData[this.section][key] !== undefined) {
        alert(`Duplicated item: '${key}'!`)
      } else {
        saveItem(this.section, key, value)
          .then(() => {
            this.dialog.newKey = ''
            this.dialog.newValue = ''

            const items = objectToItems(globalData[this.section])

            items.unshift({
              key: key,
              value: value
            })

            this.dialog.items = items

            refreshSuggestion()
          })
          .catch(error => {
            console.error(error)
          })
      }
    },
    deleteRow(event) {
      if (confirm('Are you sure want to delete this item?')) {
        const ctx = getRowContext(event.target)

        deleteItem(this.section, ctx.key)
          .then(() => {
            ctx.row.remove()
            refreshSuggestion()
          })
          .catch(error => {
            console.error(error)
          })
      }
    },
    saveAllTranslationValues() {
      saveAllTranslationValuesInternal()
        .then(() => {
          forEachTextBoxes('translationList', textBox => {
            if (!textBox.classList.contains('changed') || textBox.value === '') return

            setTextBoxUpdatedStyle(textBox)

            updateStatusNode(textBox)

            const ctx = getRowContext(textBox)

            refreshTranslation(ctx.key, ctx.value)
          })

          refreshSuggestion()
        })
        .catch(error => {
          console.error(error)
        })
    },
    input(event) {
      inputInternal(event, this.section)
    },
    processValueKey(event) {
      processValueKeyInternal(event, this.section)
    },
    loadSimilarPage(delta) {
      if (this.searchForm.similarPageNumber + delta === 0) return
      if (this.searchForm.similarPageNumber + delta === maxSimilarPageCount) return

      this.searchForm.similarPageNumber += delta
      this.searchForm.text = ''

      searchInternal(this.searchForm)
    }
  },
  created() {
    fetch('/data')
      .then(response => response.json())
      .then(data => {
        globalData = data
        maxSimilarPageCount = Math.ceil(globalData.similars.length / SIMILAR_PAGE_SIZE)

        setGlobalDictionary(globalData.translations, globalData.dictionary, globalData.terminology)

        let {totalPercent, items} = getCategories(globalData.categories, globalData.translations)
<commit_msg>Fixed: Invalid pager logic of similar items.<commit_after>const IGNORE_PROTOTYPE = true
const IS_SORT_BY_PERCENT = true
const DEFAULT_FILTER_LENGTH = 66
const DEFAULT_CATEGORY = 'N/A'
const SIMILAR_PAGE_SIZE = 10

const regexWholeWord = /^\w+$/i
const globalDictionary = {}
const globalPhrases = {}
let globalData
let maxSimilarPageCount

const vm = new Vue({
  el: '#app',
  data: {
    searchForm: {
      category: DEFAULT_CATEGORY,
      text: '',
      isWord: false,
      type: 'text',
      filterLength: DEFAULT_FILTER_LENGTH,
      similarPageNumber: 0
    },
    category: {
      show: false,
      totalPercent: 0,
      items: []
    },
    dialog: {
      show: false,
      title: '',
      newKey: '',
      newValue: '',
      items: []
    }
  },
  computed: {
    section() {
      return this.dialog.title.toLowerCase()
    }
  },
  methods: {
    showCategory() {
      this.category.show = !this.category.show
    },
    search(event) {
      this.category.show = false
      this.dialog.show = false
      this.searchForm.similarPageNumber = 0

      if (event.target.tagName === 'A') {
        this.searchForm.category = event.target.textContent
        this.searchForm.text = ''
      } else if (event.target.name !== 'filterLength') {
        this.searchForm.category = DEFAULT_CATEGORY
      }

      searchInternal(this.searchForm)
    },
    showDialog(event) {
      const title = event.target.textContent

      if (this.dialog.title === title && this.dialog.show) {
        this.dialog.show = false
      } else {
        this.dialog.show = true
        this.dialog.title = title
        this.dialog.newKey = ''
        this.dialog.newValue = ''
        this.dialog.items = objectToItems(globalData[this.section])

        Vue.nextTick(() => document.getElementById('newKey').focus())
      }
    },
    closeDialog() {
      this.dialog.show = false

      forEachTextBoxes('dialogList', textBox => resetTextBoxStyle(textBox))
    },
    addRow() {
      const key = this.section === 'dictionary' ? this.dialog.newKey.toLowerCase() : this.dialog.newKey
      const value = this.dialog.newValue

      if (key === '') return

      if (globalData[this.section][key] !== undefined) {
        alert(`Duplicated item: '${key}'!`)
      } else {
        saveItem(this.section, key, value)
          .then(() => {
            this.dialog.newKey = ''
            this.dialog.newValue = ''

            const items = objectToItems(globalData[this.section])

            items.unshift({
              key: key,
              value: value
            })

            this.dialog.items = items

            refreshSuggestion()
          })
          .catch(error => {
            console.error(error)
          })
      }
    },
    deleteRow(event) {
      if (confirm('Are you sure want to delete this item?')) {
        const ctx = getRowContext(event.target)

        deleteItem(this.section, ctx.key)
          .then(() => {
            ctx.row.remove()
            refreshSuggestion()
          })
          .catch(error => {
            console.error(error)
          })
      }
    },
    saveAllTranslationValues() {
      saveAllTranslationValuesInternal()
        .then(() => {
          forEachTextBoxes('translationList', textBox => {
            if (!textBox.classList.contains('changed') || textBox.value === '') return

            setTextBoxUpdatedStyle(textBox)

            updateStatusNode(textBox)

            const ctx = getRowContext(textBox)

            refreshTranslation(ctx.key, ctx.value)
          })

          refreshSuggestion()
        })
        .catch(error => {
          console.error(error)
        })
    },
    input(event) {
      inputInternal(event, this.section)
    },
    processValueKey(event) {
      processValueKeyInternal(event, this.section)
    },
    loadSimilarPage(delta) {
      if (this.searchForm.similarPageNumber + delta === 0) return
      if (this.searchForm.similarPageNumber + delta >= maxSimilarPageCount) {
        if (delta < 0) {
          this.searchForm.similarPageNumber += delta
        }

        return
      }

      this.searchForm.similarPageNumber += delta
      this.searchForm.text = ''

      searchInternal(this.searchForm)
    }
  },
  created() {
    fetch('/data')
      .then(response => response.json())
      .then(data => {
        globalData = data
        maxSimilarPageCount = Math.ceil(globalData.similars.length / SIMILAR_PAGE_SIZE)

        setGlobalDictionary(globalData.translations, globalData.dictionary, globalData.terminology)

        let {totalPercent, items} = getCategories(globalData.categories, globalData.translations)

{'fraction_non_alphanumeric': 0.12476824081142981, 'fraction_numerical': 0.0018540735085614572, 'mean_word_length': 2.110583446404342, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 26, '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': '4693633', 'n_tokens_mistral': 2714, 'n_tokens_neox': 2620, 'n_words': 471}