テキストエディタ
Framework7 には、タッチフレンドリーなリッチテキストエディタコンポーネントが付属しています。最新の "contenteditable" API に基づいているため、そのままどこでも動作するはずです。
基本的なフォーマット機能が付属しています。ただし、その機能は、あらゆる要件に合わせて簡単に拡張およびカスタマイズできます。
テキストエディタのレイアウト
<div class="text-editor">
<div class="text-editor-content" contenteditable></div>
</div>
エディタのサイズを変更可能にするには (高さがコンテンツに合わせて調整される場合)、エディタ要素に text-editor-resizable
クラスを追加する必要があります
<!-- additional "text-editor-resizable" class -->
<div class="text-editor text-editor-resizable">
<div class="text-editor-content" contenteditable></div>
</div>
テキストエディタアプリメソッド
テキストエディタを操作するための関連アプリメソッドを見てみましょう
app.textEditor.create(パラメータ)- テキストエディタインスタンスを作成します
- パラメータ - オブジェクト。テキストエディタパラメータを持つオブジェクト
メソッドは、作成されたテキストエディタインスタンスを返します
app.textEditor.destroy(el)- テキストエディタインスタンスを破棄します
- el - HTMLElement または 文字列 (CSS セレクター付き) または オブジェクト。破棄するテキストエディタ要素またはテキストエディタインスタンス。
app.textEditor.get(el)- HTML 要素によってテキストエディタインスタンスを取得します
- el - HTMLElement または 文字列 (CSS セレクター付き)。テキストエディタ要素。
メソッドはテキストエディタのインスタンスを返します
例えば
var textEditor = app.textEditor.create({
el: '#my-text-editor',
value: <code><p>Hello</p></code>,
});
テキストエディタパラメータ
利用可能なすべてのテキストエディタパラメータのリストを見てみましょう
パラメータ | タイプ | デフォルト | 説明 |
---|---|---|---|
el | HTMLElement 文字列 | テキストエディタ要素。 HTMLElement またはエディタ要素の CSS セレクターを持つ文字列 | |
value | 文字列 | テキストエディタの初期 HTML コンテンツ値。初期値は、
| |
placeholder | 文字列 | エディタプレースホルダーコンテンツは、空の場合に表示されます。デフォルトでは指定されていません | |
mode | 文字列 | toolbar | テキストエディタボタンモード。次のいずれかになります
|
buttons | 配列 | エディタボタンの配列、またはエディタボタンを含む配列 (グループ) の配列。デフォルトではすべてのボタンが有効になっており、そのデフォルト値は次のとおりです
| |
dividers | 真偽値 | true | ボタングループの間に視覚的な区切り線を追加します |
imageUrlText | 文字列 | 画像 URL を挿入する | 画像 URL リクエストに表示されるプロンプトテキスト |
linkUrlText | 文字列 | リンク URL を挿入する | リンク URL リクエストに表示されるプロンプトテキスト |
clearFormattingOnPaste | 真偽値 | true | 有効にすると、クリップボードから貼り付けるときにフォーマットがクリアされます |
customButtons | オブジェクト | カスタムボタン付きのオブジェクト。オブジェクトプロパティキーは、有効にするために 例えば、
| |
on | オブジェクト | イベントハンドラを持つオブジェクト。例えば
|
次のすべてのパラメータは、textEditor
プロパティの下のグローバルアプリパラメータで使用して、すべてのテキストエディタのデフォルトを設定できることに注意してください。例えば
var app = new Framework7({
textEditor: {
buttons: ['bold', 'italic'],
}
});
テキストエディタメソッドとプロパティ
テキストエディタを初期化すると、初期化されたインスタンスが変数 (上記の例の textEditor
変数など) に格納され、便利なメソッドとプロパティが使用できます
プロパティ | |
---|---|
textEditor.app | グローバルアプリインスタンスへのリンク |
textEditor.el | テキストエディタコンテナ HTML 要素 |
textEditor.$el | テキストエディタコンテナ HTML 要素を含む Dom7 インスタンス |
textEditor.contentEl | テキストエディタコンテンツ (contenteditalbe ) HTML 要素 |
textEditor.$contentEl | テキストエディタコンテンツ (contenteditalbe ) HTML 要素を含む Dom7 インスタンス |
textEditor.value | テキストエディタの HTML 値 |
textEditor.params | 初期化パラメータを含むオブジェクト |
メソッド | |
textEditor.setValue(値) | 新しいテキストエディタ値を設定します。 値 は HTML 文字列です。 |
textEditor.getValue() | 現在のテキストエディタ値を返します |
textEditor.clearValue() | テキストエディタ値をクリアします |
textEditor.getSelectionRange() | 現在の選択範囲を返します |
textEditor.setSelectionRange(範囲) | 渡された範囲に基づいて選択を設定します |
textEditor.destroy() | テキストエディタインスタンスを破棄し、すべてのイベントを削除します |
textEditor.on(イベント, ハンドラ) | イベントハンドラを追加します |
textEditor.once(イベント, ハンドラ) | 起動後に削除されるイベントハンドラを追加します |
textEditor.off(イベント, ハンドラ) | イベントハンドラを削除します |
textEditor.off(イベント) | 指定されたイベントのすべてのハンドラを削除します |
textEditor.emit(イベント, ...args) | インスタンスでイベントを発生させます |
テキストエディタイベント
テキストエディタは、テキストエディタ要素で次の DOM イベントを発生させ、アプリとテキストエディタインスタンスでイベントを発生させます
DOM イベント
イベント | 説明 |
---|---|
texteditor:init | エディタの初期化時にイベントがトリガーされます |
texteditor:change | エディタ値が変更されたときにイベントがトリガーされます |
texteditor:input | エディタのコンテンツ "input" イベントでイベントがトリガーされます |
texteditor:focus | エディタのコンテンツフォーカスでイベントがトリガーされます |
texteditor:blur | エディタのコンテンツぼかしでイベントがトリガーされます |
texteditor:buttonclick | エディタボタンのクリックでイベントがトリガーされます |
texteditor:keyboardopen | エディタキーボードツールバーが表示されたときにイベントがトリガーされます |
texteditor:keyboardclose | エディタキーボードツールバーが消えたときにイベントがトリガーされます |
texteditor:popoveropen | エディタポップオーバーが開いたときにイベントがトリガーされます |
texteditor:popoverclose | エディタポップオーバーが閉じたときにイベントがトリガーされます |
texteditor:beforedestroy | Text Editor インスタンスが破棄される直前にイベントがトリガーされます |
アプリとテキストエディタインスタンスイベント
Text Editor インスタンスは、自身とアプリインスタンスの両方でイベントを発行します。アプリインスタンスイベントの名前は、textEditor
というプレフィックスが付いた同じ名前です。
イベント | ターゲット | 引数 | 説明 |
---|---|---|---|
init | textEditor | (editor) | エディタの初期化時にイベントがトリガーされます。 |
textEditorInit | app | ||
change | textEditor | (editor) | エディタの初期化時にイベントがトリガーされます。 |
textEditorChange | app | ||
input | textEditor | (editor) | エディタのコンテンツの「入力」イベントでイベントがトリガーされます。 |
textEditorInput | app | ||
focus | textEditor | (editor) | エディタのコンテンツフォーカスでイベントがトリガーされます。 |
textEditorFocus | app | ||
blur | textEditor | (editor) | エディタのコンテンツぼかしでイベントがトリガーされます。 |
textEditorBlur | app | ||
buttonClick | textEditor | (editor, button) | エディタボタンのクリックでイベントがトリガーされます。 2 番目の引数として、イベントハンドラはクリックされたボタンの ID を受け取ります。例: bold |
textEditorButtonClick | app | ||
keyboardOpen | textEditor | (editor) | エディタキーボードツールバーが表示されたときにイベントがトリガーされます。 |
textEditorKeyboardOpen | app | ||
keyboardClose | textEditor | (editor) | エディタキーボードツールバーが消えたときにイベントがトリガーされます。 |
textEditorKeyboardClose | app | ||
popoverOpen | textEditor | (editor) | エディタポップオーバーが開いたときにイベントがトリガーされます。 |
textEditorPopoverOpen | app | ||
popoverClose | textEditor | (editor) | エディタポップオーバーが閉じたときにイベントがトリガーされます。 |
textEditorPopoverClose | app | ||
beforeDestroy | textEditor | (editor) | Text Editor インスタンスが破棄される直前にイベントがトリガーされます。 |
textEditorBeforeDestroy | app |
テキストエディタの自動初期化
Text Editor APIを使用する必要がなく、Text Editorがページ内にあり、ページ初期化時にDOMに存在する場合、追加のtext-editor-init
クラスを追加するだけで自動的に初期化できます。
<!-- Add text-editor-init class -->
<div class="text-editor text-editor-init">
<div class="text-editor-content" contenteditable></div>
</div>
この場合、作成されたText Editorインスタンスにアクセスする必要がある場合は、app.textEditor.get
アプリメソッドを使用できます。
var textEditor = app.textEditor.get('.my-text-editor');
if (!textEditor.value) {
// do something
}
自動初期化を使用する場合、追加のパラメータを渡す必要がある場合があります。これは、パネル要素のdata-
属性を使用して行うことができます。
<!-- parameters set via data- attributes -->
<div
class="text-editor text-editor-init"
data-mode="popover"
data-placeholder="Description"
>
...
</div>
パラメータはcamelCase(例:imageUrlText)を使用しますが、data-属性ではkebab-case(例:data-image-url-text)を使用する必要があります。
CSS変数
以下は、関連するCSS変数(CSSカスタムプロパティ)のリストです。
:root {
--f7-text-editor-font-size: inherit;
--f7-text-editor-font-weight: inherit;
--f7-text-editor-border-width: 1px;
--f7-text-editor-height: 250px;
--f7-text-editor-margin: 16px;
--f7-text-editor-padding: 8px;
--f7-text-editor-button-bg-color: transparent;
--f7-text-editor-button-size: 28px;
--f7-text-editor-button-icon-size: 20px;
--f7-text-editor-button-margin: 2px;
--f7-text-editor-text-color: #000;
--f7-text-editor-bg-color: #fff;
--f7-text-editor-button-divider-color: rgba(0, 0, 0, 0.15);
}
:root .dark,
:root.dark {
--f7-text-editor-bg-color: #121212;
--f7-text-editor-text-color: #fff;
--f7-text-editor-button-divider-color: rgba(255, 255, 255, 0.15);
}
.ios {
--f7-text-editor-toolbar-padding: 6px;
--f7-text-editor-button-border-radius: 2px;
--f7-text-editor-placeholder-color: rgba(0, 0, 0, 0.35);
--f7-text-editor-toolbar-border-color: rgba(0, 0, 0, 0.25);
--f7-text-editor-toolbar-bg-color: #fff;
--f7-text-editor-border-color: rgba(0, 0, 0, 0.1);
--f7-text-editor-button-text-color: #333;
}
.ios .dark,
.ios.dark {
--f7-text-editor-placeholder-color: rgba(255, 255, 255, 0.35);
--f7-text-editor-toolbar-bg-color: #121212;
--f7-text-editor-toolbar-border-color: rgba(255, 255, 255, 0.1);
--f7-text-editor-toolbar-bg-color: #202020;
--f7-text-editor-border-color: rgba(255, 255, 255, 0.1);
--f7-text-editor-button-text-color: #fff;
}
.md {
--f7-text-editor-button-border-radius: 8px;
--f7-text-editor-toolbar-padding: 8px;
}
.md,
.md .dark,
.md [class*='color-'] {
--f7-text-editor-placeholder-color: var(--f7-md-on-surface-variant);
--f7-text-editor-toolbar-bg-color: var(--f7-md-surface-1);
--f7-text-editor-border-color: var(--f7-md-outline);
--f7-text-editor-button-text-color: var(--f7-md-on-surface);
}
例
<template>
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner sliding">
<div class="title">Text Editor</div>
</div>
</div>
<div class="page-content">
<div class="block">
<p>Framework7 comes with a touch-friendly Rich Text Editor component. It is based on modern "contenteditable"
API so it should work everywhere as is.</p>
<p>It comes with the basic set of formatting features. But its functionality can be easily extended and
customized to fit any requirements.</p>
</div>
<div class="block-title">Default Setup</div>
<div class="text-editor text-editor-init">
<div class="text-editor-content" contenteditable></div>
</div>
<div class="block-title">With Placeholder</div>
<div class="text-editor text-editor-init" data-placeholder="Enter text...">
<div class="text-editor-content" contenteditable></div>
</div>
<div class="block-title">With Default Value</div>
<div class="text-editor text-editor-init" data-placeholder="Enter text...">
<div class="text-editor-content" contenteditable>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Consequatur sunt, sapiente quis eligendi
consectetur hic asperiores assumenda quidem dolore quasi iusto tenetur commodi qui ullam sint sed alias!
Consequatur, dolor!</p>
<p>Provident reiciendis exercitationem reprehenderit amet repellat laborum, sequi id quam quis quo quos facere
veniam ad libero dolorum animi. Nobis, illum culpa explicabo dolorem vitae ut dolor at reprehenderit magnam?
</p>
<p>Qui, animi. Dolores dicta, nobis aut expedita enim eum assumenda modi, blanditiis voluptatibus excepturi
non pariatur. Facilis fugit facere sequi molestias nemo in, suscipit inventore consequuntur, repellat
perferendis, voluptas odit.</p>
<p>Tempora voluptates, doloribus architecto eligendi numquam facilis perspiciatis autem quam voluptas maxime
ratione harum laudantium cum deleniti. In, alias deserunt voluptatibus eligendi libero nobis est unde et
perspiciatis cumque voluptatum.</p>
<p>Quam error doloribus qui laboriosam eligendi. Aspernatur quam pariatur perspiciatis reprehenderit atque
dicta culpa, aut rem? Assumenda, quibusdam? Reprehenderit necessitatibus facere nemo iure maiores porro
voluptates accusamus quibusdam. Nesciunt, assumenda?</p>
</div>
</div>
<div class="block-title">Specific Buttons</div>
<div class="block-header">It is possible to customize which buttons (commands) to show.</div>
<div class="text-editor text-editor-init" data-placeholder="Enter text..."
data-buttons='[["bold", "italic", "underline", "strikeThrough"], ["orderedList", "unorderedList"]]'>
<div class="text-editor-content" contenteditable></div>
</div>
<div class="block-title">Custom Button</div>
<div class="block-header">It is possible to create custom editor buttons. Here is the custom "hr" button that adds
horizontal rule:</div>
<div class="text-editor text-editor-custom-buttons">
<div class="text-editor-content" contenteditable></div>
</div>
<div class="block-title">Resizable</div>
<div class="block-header">Editor will be resized based on its content.</div>
<div class="text-editor text-editor-init text-editor-resizable" data-placeholder="Enter text..."
data-buttons='["bold", "italic", "underline", "strikeThrough"]'>
<div class="text-editor-content" contenteditable></div>
</div>
<div class="block-title">Popover Mode</div>
<div class="block-header">In this mode, there is no toolbar with buttons, but they appear as popover when you
select any text in editor.</div>
<div class="text-editor text-editor-init" data-placeholder="Enter text..."
data-buttons='["bold", "italic", "underline", "strikeThrough"]' data-mode="popover"
style="--f7-text-editor-height: 150px">
<div class="text-editor-content" contenteditable></div>
</div>
<div class="block-title">Keyboard Toolbar Mode</div>
<div class="block-header">In this mode, toolbar with buttons will appear on top of virtual keyboard when editor is
in the focus. It is supported only in iOS, Android cordova apps and in Android Chrome. When not supported it
will fallback to "popover" mode.</div>
<div class="text-editor text-editor-init" data-placeholder="Enter text..." data-mode="keyboard-toolbar"
style="--f7-text-editor-height: 150px">
<div class="text-editor-content" contenteditable></div>
</div>
<div class="block-title">As List Input</div>
<div class="block-header">Text editor can be used in list with other inputs. In this example it is enabled with
"keyboard-toolbar"/"popover" type for "About" field.</div>
<div class="list list-strong-ios list-dividers-ios list-outline-ios">
<ul>
<li class="item-content item-input">
<div class="item-media">
<i class="icon demo-list-icon"></i>
</div>
<div class="item-inner">
<div class="item-title item-label">Name</div>
<div class="item-input-wrap">
<input type="text" placeholder="Your name" />
</div>
</div>
</li>
<li class="item-content item-input">
<div class="item-media">
<i class="icon demo-list-icon"></i>
</div>
<div class="item-inner">
<div class="item-title item-label">About</div>
<div class="item-input-wrap">
<div class="text-editor text-editor-init text-editor-resizable" data-placeholder="About"
data-buttons='["bold", "italic", "underline", "strikeThrough"]' data-mode="popover">
<div class="text-editor-content" contenteditable></div>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
export default (props, { $f7, $el, $on }) => {
let textEditorCustomButtons;
$on('pageInit', () => {
textEditorCustomButtons = $f7.textEditor.create({
el: $el.value.find('.text-editor-custom-buttons'),
// define custom "hr" button
customButtons: {
hr: {
content: '<hr>',
onClick(editor, buttonEl) {
document.execCommand('insertHorizontalRule', false);
},
},
},
buttons: [["bold", "italic", "underline", "strikeThrough"], "hr"],
});
});
$on('pageBeforeRemove', () => {
textEditorCustomButtons.destroy()
});
return $render;
};
</script>