Sankaku Tag Popularity Autocompletion

Makes the default autocompletion pick the most popular tag. Borders are added to the currently selected autocompletion. Arrow keys can also pick completions in textareas.

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name        Sankaku Tag Popularity Autocompletion
// @namespace   SankakuTagPopularityAutocompletion
// @match       https://chan.sankakucomplex.com/*
// @match       https://legacy.sankakucomplex.com/*
// @match       https://idol.sankakucomplex.com/*
// @noframes
// @grant       GM.addStyle
// @version     1.1.0
// @author      epair
// @description Makes the default autocompletion pick the most popular tag. Borders are added to the currently selected autocompletion. Arrow keys can also pick completions in textareas.
// ==/UserScript==

var selected_index = -1

function add_style(css) {
  if(GM.addStyle) {
    return Promise.resolve(GM.addStyle(css))
    //Violentmonkey returns a style element whereas Tampermonkey returns a Promise
  } else {
    const sheet = document.createElement('STYLE')
    sheet.innerText = css
    document.head.appendChild(sheet)
    return Promise.resolve(sheet)
  }
}

{
  //set style based on dark/light theme
  let theme = document.cookie
    .split('; ')
    .find((row) => row.startsWith('theme='))
    ?.split('=')[1];

  let is_dark_mode = theme !== undefined && Number(theme) !== 0

  let bg = is_dark_mode ? '#000' : '#aaa'
  let fg = is_dark_mode ? '#aaa' : '#000'

  add_style(`
  #autocomplete li {
    border: 2px dotted ${bg};
  }
  #autocomplete li.autocomplete-select {
    border: 2px solid ${fg};
  }`)
}

//parse number from human readable suffix
function num_from_suffix(n) {
  let base = 1
  if(n.charAt(n.length-1) === 'M')
    base = 1000000
  else if(n.charAt(n.length-1) === 'K')
    base = 1000
  else
    return Number.parseFloat(n)
  return Number.parseFloat(n.substring(0, n.length-1)) * base
}

//prevent tag edit textarea default events from hiding autocomplete
function key_up(e) {
  switch(e.key) {
    case 'ArrowDown':
    case 'PageDown':
    case 'PageUp':
    case 'ArrowUp':
      if(document.querySelector("#autocomplete").style.display !== 'block')
        break
      e.preventDefault()
      e.stopImmediatePropagation()
  }
}

function key_down(e) {
  switch(e.key) {
    case 'Tab':
    case 'Enter':
      let counts = document.querySelectorAll('#autocomplete span.item-count')
			if(counts.length < 1) {				document.querySelector('#autocomplete').children.item(selected_index || 0).click()

			}

      let greatest = 0
      let first = num_from_suffix(counts.item(0).innerText)
      let second = num_from_suffix(counts.item(1).innerText)

      if(first < second)
        greatest = 1

      if(selected_index > -1 || first < 1)
        greatest = selected_index
			//alert(counts.length + ' ' + first)
      //complete selected tag or greatest post count if unselected
      counts.item(greatest).parentNode.click()

      e.preventDefault()
      e.stopImmediatePropagation()
      break
    case 'ArrowDown':
    case 'PageDown':
    case 'PageUp':
    case 'ArrowUp':
      //break to allow cursor and selection movement when autocomplete is hidden
      if(document.querySelector("#autocomplete").style.display !== 'block')
        break
      let completions = document.querySelectorAll('#autocomplete li')

      selected_index += (e.key === 'ArrowUp' || e.key === 'PageUp') ? -1 : 1
      if(selected_index < 0)
        selected_index = completions.length - 1
      if(selected_index >= completions.length)
        selected_index = 0

      for(let c of completions)
        c.classList.remove('autocomplete-select')
      completions.item(selected_index).classList.add('autocomplete-select')
      e.preventDefault()
      e.stopImmediatePropagation()
      break
    default:
      selected_index = -1
      break
  }
}

function query_add_event(selector, event, func, cap=false){
  let q = document.querySelector(selector)
  if(q !== null)
    q.addEventListener(event, func, cap)
}

query_add_event("#tags", "keydown", key_down)
query_add_event("#post_tags", "keydown", key_down, true)
query_add_event("#post_tags", "keyup", key_up, true)