Riot.jsでタグエディターのサンプルを作ってみた
Riot.js
Riot.jsについてはRiot.js 2.0 情報まとめ - Qiitaに良いまとめがありますのでそちらをどうぞ。良いまとめをありがとうございます。
本家が提供しているToDoアプリをgoemonでライブリロードして開発を高速化するサンプル
今回のタグエディターの前に、環境整備ということで本家が提供しているToDoアプリをgoemonでライブリロードして開発を高速化するサンプルを作ってみました。
hnakamur/riotjs-todo-goemon-livereload-example
Riot developer guideにあるアプリからどのように変更したかはgitのコミットを小分けにしてあるので、そちらをご参照ください。 Commits · hnakamur/riotjs-todo-goemon-livereload-example
タグエディターのサンプルをRiot.jsでも作ってみた
で、本題のタグエディターのサンプルです。以前にjQuery, Backbone.js, Vue.jsで同じものを作っていました。
今回はRiot.jsで作ってみました。
ソース: hnakamur/riot-tag-editor-live-reload-example-with-goemon コンパイル済みのデモ: Riot tag editor example
セットアップ手順はソースのREADMEを参照してください。
タグエディターのタグのソースはtag-editor.tagです。
<tag-editor>
<div class="tag-editor-field" onclick={ click }>
<div class="tag-editor-tag tag-editor-tag-measure">
<div id="measure" class="tag-editor-text"></div>
<a class="tag-editor-delete">x</a>
</div>
<div each={ tags } class="tag-editor-tag">
<div class="tag-editor-text">{ name }</div>
<a class="tag-editor-delete" onclick={ parent.clickDelete }>x</a>
</div>
<input name="editor" class="tag-editor-input" style="width: 0" onkeyup={ keyup } onkeydown={ keydown } onblur={ blur }>
</div>
<script>
this.tags = opts.tags
this.separator = /[, ]+/
click(e) {
adjustEditorWidth(this)
this.editor.focus()
return false
}
keyup(e) {
var val = this.editor.value
if (this.separator.test(val)) {
mayInsertTags(this)
} else {
adjustEditorWidth(this)
}
return false
}
keydown(e) {
if (e.which == 13 /* Enter */ && this.editor.value !== '') {
mayInsertTags(this)
return true
} else if (e.which == 8 /* Backspace */ && this.editor.value === '' && this.tags.length > 0) {
this.tags.pop()
}
return true
}
blur(e) {
mayInsertTags(this)
return true
}
clickDelete(e) {
e.stopPropagation()
this.tags.splice(this.tags.indexOf(e.item), 1)
return false
}
function adjustEditorWidth(elem) {
elem.measure.innerText = elem.editor.value + 'WW'
elem.editor.style.width = elem.measure.offsetWidth + 'px'
}
function mayInsertTags(elem) {
var values = elem.editor.value.split(elem.separator),
i = 0,
len = values.length,
value
elem.editor.value = ''
adjustEditorWidth(elem)
for (; i < len; i++) {
value = values[i]
if (value !== '' && !containsTag(elem, value)) {
elem.tags.push({name: value})
}
}
}
function containsTag(elem, tag) {
var i = 0,
len = elem.tags.length
for (; i < len; i++) {
if (elem.tags[i].name === tag) {
return true
}
}
return false
}
</script>
</tag-editor>
HTMLのタグとJavaScriptのコードを一箇所にかけて、イベントもonclickとかで書くので、コンパクトで見やすいです。
onclickとかに指定した関数は function
なしで書けるようになっていますが、そうでない関数には function
を明記する必要がありました。
タグエディターを利用する側のHTMLのコードは以下の様な感じで、こちらもシンプルです。
<script src="tag-editor.tag" type="riot/tag"></script>
<script src="https://cdn.jsdelivr.net/g/riot@2.0(riot.min.js+compiler.min.js)"></script>
<script>
riot.mount('tag-editor', {
tags: [
{name: 'foo'},
{name: 'bar'},
]
})
</script>
プリコンパイル済みのソースの作成
riot assets/ demo/
で assets/tag-editor.tag
から demo/tag-editor.js
が生成されます。
利用する側のHTMLは以下のようにします。 riot.jsの読み込み方法と、タグエディターのソースを読み込む順番が開発時とは違うので要注意です。
<script src="https://cdn.jsdelivr.net/riot/2.0/riot.min.js"></script>
<script src="tag-editor.js"></script>
<script>
riot.mount('tag-editor', {
tags: [
{name: 'foo'},
{name: 'bar'},
]
})
</script>
Riot.jsの魅力
Riot vs React vs Polymerを見ても、riot.min.jsは6.7KBとコンパクトなのが魅力です。それでいてカスタムタグもすっきりシンプルに書けますし。これは今後に期待ですね!