summaryrefslogtreecommitdiff
path: root/src/web/app/desktop/scripts/autocomplete.ls
blob: 636bb7f27792e0a85c0067c9e96b728164b46673 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# Autocomplete
#================================

get-caret-coordinates = require 'textarea-caret-position'
riot = require 'riot'

# オートコンプリートを管理するクラスです。
class Autocomplete

	@textarea = null
	@suggestion = null

	# 対象のテキストエリアを与えてインスタンスを初期化します。
	(textarea) ~>
		@textarea = textarea

	# このインスタンスにあるテキストエリアの入力のキャプチャを開始します。
	attach: ~>
		@textarea.add-event-listener \input @on-input

	# このインスタンスにあるテキストエリアの入力のキャプチャを解除します。
	detach: ~>
		@textarea.remove-event-listener \input @on-input
		@close!

	# テキスト入力時
	on-input: ~>
		@close!

		caret = @textarea.selection-start
		text = @textarea.value.substr 0 caret

		mention-index = text.last-index-of \@

		if mention-index == -1
			return

		username = text.substr mention-index + 1

		if not username.match /^[a-zA-Z0-9-]+$/
			return

		@open \user username

	# サジェストを提示します。
	open: (type, q) ~>
		# 既に開いているサジェストは閉じる
		@close!

		# サジェスト要素作成
		suggestion = document.create-element \mk-autocomplete-suggestion

		# ~ サジェストを表示すべき位置を計算 ~

		caret-position = get-caret-coordinates @textarea, @textarea.selection-start

		rect = @textarea.get-bounding-client-rect!

		x = rect.left + window.page-x-offset + caret-position.left
		y = rect.top + window.page-y-offset + caret-position.top

		suggestion.style.left = x + \px
		suggestion.style.top = y + \px

		# 要素追加
		el = document.body.append-child suggestion

		# マウント
		mounted = riot.mount el, do
			textarea: @textarea
			complete: @complete
			close: @close
			type: type
			q: q

		@suggestion = mounted.0

	# サジェストを閉じます。
	close: ~>
		if !@suggestion?
			return

		@suggestion.unmount!
		@suggestion = null

		@textarea.focus!

	# オートコンプリートする
	complete: (user) ~>
		@close!
		value = user.username

		caret = @textarea.selection-start
		source = @textarea.value

		before = source.substr 0 caret
		trimed-before = before.substring 0 before.last-index-of \@
		after = source.substr caret

		# 結果を挿入する
		@textarea.value = trimed-before + \@ + value + ' ' + after

		# キャレットを戻す
		@textarea.focus!
		pos = caret + value.length
		@textarea.set-selection-range pos, pos

module.exports = Autocomplete