contenteditable="true"
を付与した要素を編集可能にする属性で、Dropbox Paperやcacooなど、主にオンラインエディタ的なサービスでよく使われている。「contenteditableを使った何かをつくる」という目標を掲げて、Vue.js使って1時間弱で100マス計算アプリをつくってみた!v-modelが使えなかったり、テストに手間取ったりで時間かかっちゃったけどなんとか完成した! pic.twitter.com/Q4wkmsCRjO— ダーシノ (@bc_rikko) 2017年12月9日
「contenteditable属性を使った何かをつくる」という目標を掲げて、100マス計算アプリを作ったので、それをサンプルにcontenteditableについて書こうと思う。
contenteditable属性について
contenteditable属性はグローバル属性なので、すべてのHTML要素で使える。
この属性に設定できるのは、以下の2つのみ。省略形は使えない。
- true or 空文字: 要素は編集可能
- false: 要素は編集不可
contenteditable="true"
を指定すると、すべての要素が編集可能になる。100マス計算アプリをつくる
<main id="game">
<table>
<tr>
<th>\</th>
<th v-for="n in cols" :key="n">
{{ n }}
</th>
</tr>
<tr v-for="(m, i) in rows" :key="m">
<th>{{ m }}</th>
<td v-for="(_, j) in boxes" :key="j">
<div contenteditable="true" @blur="onBlur($event, i, j)"></div>
</td>
</tr>
</table>
<button type="button" @click="finish">Finish</button>
</main>
table {
text-align: center;
border-collapse: collapse;
}
table tr {
height: 40px;
}
table th, td {
border: 3px solid #39B885;
width: 40px;
}
table th {
background-color: #39B885;
color: white;
}
new Vue({
el: '#game',
data() {
return {
boxes: 10,
rows: [], // 1〜10までのランダムな配列
cols: [], // 1〜10までのランダムな配列
result: []
}
},
created() {
this.rows = this.randomNumbers();
this.cols = this.randomNumbers();
// 0で初期化された10x10の2次元配列(結果格納用)
let rows = new Array(this.boxes);
[...Array(this.boxes)].forEach((_, i) => rows[i] = new Array(this.boxes).fill(0));
this.result = rows;
},
methods: {
/**
* 1〜10までのランダムな配列を返す
* computedだと再計算されないためmethodsで定義
* @return {Array<Number>}
*/
randomNumbers() {
const nums = [...Array(this.boxes)].map((_, a) => a + 1);
for (let i = nums.length - 1; 0 < i; i--) {
let r = Math.floor(Math.random() * (i + 1));
// nums[i] <-> nums[r]
[nums[i], nums[r]] = [nums[r], nums[i]];
}
return nums;
},
/**
* 入力した値を結果用配列に格納する
* @param e イベント
* @param i 行のインデックス
* @param j 列のインデックス
*/
onBlur(e, i, j) {
this.result[i][j] = /^[0-9]+$/.test(e.target.innerText) ? +e.target.innerText : 0;
},
/**
* 正誤判定
*/
finish() {
const result = !this.cols.some((v, i) => {
return this.rows.some((w, j) => {
return this.result[i][j] !== v + w;
});
});
alert(result ? '正解' : '不正解');
}
}
});
contenteditable属性を付与することで、input要素がなくても要素の変更&値の入力・取得ができる。ただし、v-modelでdataオブジェクトにバインドできないので、blurイベントを利用している。1〜10までのランダムな配列を取得する詳しい方法は、以下の記事を参照してほしい。
正誤判定はArray.prototype.some()を使うことで、1つでも間違っていたら「不正解」と表示している。Array.prototype.every()という関数もあるが、こちらは全ての要素をチェックするため、今回の例でいうと100ループすることになる。どのマスが間違っているか表示したい場合はevery()を使うのが良さそう。
以上
written by @bc_rikko
0 件のコメント :
コメントを投稿