2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

テキストエリアのカーソル位置に画像を挿入したい

2
Posted at

はじめに

現在、社内向け(想定)の質問アプリケーションの開発を個人的に行っています。
開発詳細

こちらのアプリケーションでは、マークダウン記法を用いることができます。
Qiitaのように、非同期で複数画像を投稿できるよう実装をしたのですが現状テキストエリアの文末に画像を挿入するような仕様になっています。
しかし、実際に使ってみて文章の途中に画像を挿入したいシーンもあり使いにくさを感じました。

そこで今回は、テキストエリアのカーソル位置を取得しそこに画像を挿入するような処理を実装したので学習メモとして残します。

 流れ

流れとしては
1.対象の要素(今回はテキストエリア)の取得
2.テキストエリアの文字列をsubstring()でカーソル位置前後の2つの文字列に分割する(カーソル位置より前の文章とカーソル位置より後の文章)
3.あとは、上記の文字列の間に挿入したいもの(今回は画像URL)をいれる

実装

コードはこのようになりました。

let image = "![画像](" + response + ")";

let target = document.getElementById('markdown_editor_textarea');

let beforeCursor = target.value.substring(0, target.selectionStart);
let afterCursor = target.value.substring(target.selectionStart);
let newText = beforeCursor + image + afterCursor;

target.value = newText; 

ひとつひとつ解説。

let image = "![画像](" + response + ")";

こちらは、今回カーソル位置に挿入したい文字列になります。
今回、非同期処理で画像URLをサーバーから受け取っています。そのためこのresponseはAWS S3で保存した画像URLとなります。テキストエリアの横にプレビューがありそこで画像プレビューを表示させるためマークダウンの形式にしています。


let target = document.getElementById('markdown_editor_textarea');

getElementByIdで対象のテキストエリアの要素を取得。
ここで、getElementByIdでできるならgetElementsByClassNameでも出来るのかなと思いgetElementsByClassNameでやろうとしたらうまくいきませんでした(知識不足)。

てっきりgetElementsByClassNameはgetElementByIdのクラス版かと思っていましたが、返り値がそもそも違いました。

◯getElementById
対象要素が存在する場合はElementオブジェクトを返し、ない場合はnullを返す。
参考:特定のID名から要素を取得
※Elementオブジェクトとは、HTML及びXHTMLの要素を表現するオブジェクト

◯getElementsByClassName
対象要素が存在する場合は、1個以上のHTMLCollectionを返し、内場合は0個のHTMLCollectionを返す。
参考:特定のclass名(class属性値)から要素を取得

getElementsByClassNameは名前がElements複数形である通り、配列のように複数返す。
確かにclassはidと違い同一ページに同じ属性値を使用できるため複数返すようになっているのかなと。


let beforeCursor = target.value.substring(0, target.selectionStart);
let afterCursor = target.value.substring(target.selectionStart);

ここでは、テキストエリア内の文字列をカーソルの位置で分割している。
文字列の分割はsubstring()で行っている。
第一引数に分割の開始位置、第二引数に終了位置(指定しなければ文字列の最後まで)を指定できる。

※終了位置は含まれないという点に注意
例)

const str = "hoge";
console.log(str.substring(0,2)); //出力:ho

selectionStartでテキストエリアのカーソル位置を取得しています。
selectionStartは、選択範囲の開始位置のオフセット(つまりテキストエリアの開始位置からカーソルまでの距離)を返す。
これでカーソル位置の前後で分割が出来ます。


let newText = beforeCursor + image + afterCursor;
target.value = newText; 

分割した文字列の間に、挿入したい文字列をいれる。それをテキストエリアに上書きしてあげればOK。

まとめ

今回は、テキストエリアのカーソル位置に画像を挿入するにあたり学習したことをまとめました。
まだJavaScript部分では知識が圧倒的に足りていないので少しずつ理解を深めていきたいと思います。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?