メッセージ
メッセージコンポーネントは、アプリ内のコメントやメッセージングシステムの視覚化に役立ちます。
メッセージのレイアウト
<div class="page">
<div class="page-content messages-content">
<div class="messages">
<!-- 日付スタンプ -->
<div class="messages-title"><b>Sunday, Feb 9</b> 12:58</div>
<!-- 送信済みメッセージ(デフォルトでは緑色で右側に表示されています -->
<div class="message message-sent">
<div class="message-content">
<!-- テキストの入った泡 -->
<div class="message-bubble">
<div class="message-text">Hi, Kate</div>
</div>
</div>
</div>
<!-- 別の送信済みメッセージ -->
<div class="message message-sent">
<div class="message-content">
<div class="message-bubble">
<div class="message-text">How are you?</div>
</div>
</div>
</div>
<!-- 受信したメッセージ(デフォルトでは、左側にグレーで表示されます -->
<div class="message message-received">
<!-- 送信者のアバター -->
<div class="message-avatar" style="background-image:url(path/to/avatar.jpg)"></div>
<div class="message-content">
<!-- 送信者の名前 -->
<div class="message-name">Blue Ninja</div>
<!-- テキスト付きバブル -->
<div class="message-bubble">
<div class="message-text">Hi there, I am also fine, thanks! And how are you?</div>
</div>
</div>
</div>
</div>
</div>
</div>
メッセージページのレイアウト。
messages-content
- メッセージラッパーの必須追加クラスです。page-content` に追加する必要があります。messages
- メッセージバブルのための必須の追加ラッパーです。必須の要素です。messages-title
- メッセージのタイトルです。message
- シングルメッセージ
シングルメッセージのレイアウト
以下はシングルメッセージの完全なレイアウトです。
<div class="message">
<div class="message-avatar" style="background-image:url(path/to/avatar)"></div>
<div class="message-content">
<div class="message-name">John Doe</div>
<div class="message-header">Message header</div>
<div class="message-bubble">
<div class="message-text-header">Text header</div>
<div class="message-image">
<img src="path/to/image" />
</div>
<div class="message-text">Hello world!</div>
<div class="message-text-footer">Text footer</div>
</div>
<div class="message-footer">Message footer</div>
</div>
</div>
message-avatar
- 送信者のアバター、オプションで指定します。message-name
- 送信者の名前、オプションです。message-header
- 単一のメッセージヘッダ、オプションです。message-text-header
- バブルの中のテキストヘッダー、オプションです。message-image
- メッセージのイメージ、オプションです。message-text
- メッセージのテキスト、オプションです。message-text-footer
- バブルの中のテキストフッター、オプションです。message-footer
- バブルの後に表示されるフッターテキスト、オプション。
シングルメッセージコンテナの追加クラス
message-sent
- シングルメッセージ用の追加クラスで、このメッセージがユーザーによって送信されたことを示します。右側に緑の背景色で表示されます。message-received
- 単一のメッセージのための追加クラスで、このメッセージがユーザーによって受信されたことを示します。左側にグレーの背景色で表示されます。message-tail
- 単一のメッセージ (受信または送信) に対して、バブルの "tail" を追加するクラスです。message-same-name
- メッセージの送信者が、前のメッセージと同じ名前であることを示す追加クラスです。message-same-avatar
- メッセージが前のメッセージと同じアバターを持っていることを示すための追加クラスです。message-same-header
- メッセージが以前のメッセージと同じメッセージヘッダーを持つことを示すための追加クラスです。message-same-footer
- メッセージが前のメッセージと同じメッセージフッターを持つことを示すための追加クラスです。message-last
- 単一のメッセージ (受信または送信) に対する追加クラスで、現在の会話において一人の送信者が最後に受信した、または最後に送信したメッセージを示します。message-first
- 現在の会話において、ある送信者が最初に受信した、または最初に送信したメッセージを示す、単一のメッセージ(受信または送信)用の追加クラス。
メッセージアプリのメソッド
さて、メッセージのHTMLができたら、それを初期化する必要があります。関連するAppのメソッドを使用します。
app.messages.create(parameters) | パラメータ付きメッセージの初期化
|
app.messages.destroy(el) | メッセージインスタンスの破棄
|
app.messages.get(el) | HTML要素でメッセージのインスタンスを取得
|
メッセージのパラメータ
利用可能なパラメータの一覧を見てみましょう。
Parameter | Type | Default | Description |
---|---|---|---|
autoLayout | boolean | true | 自動レイアウトを有効にすると、渡された条件に基づいて必要なすべての追加クラスが自動的に追加されます。 |
newMessagesFirst | boolean | false | 新しいメッセージを下に表示するのではなく、上に表示したい場合に有効にします。 |
scrollMessages | boolean | true | 新しいメッセージを追加する際のメッセージの自動スクロールを有効/無効にする。 |
scrollMessagesOnEdge | boolean | true | 有効にした場合、メッセージの自動スクロールは、ユーザーがメッセージビューの上部または下部にいるときにのみ行われます。 |
messages | array | 初期メッセージの配列。配列内の各メッセージは、単一のメッセージパラメータを持つオブジェクトとして表示されます。 | |
on | object | イベントハンドラーを持つオブジェクト。例えば
| |
renderMessage | function(message) | 単一のメッセージをレンダリングする関数。完全なメッセージの HTML 文字列を返さなければならない | |
Autolayout Conditions | |||
firstMessageRule | function(message, previousMessage, nextMessage) | 前後のメッセージに応じて、要求された条件に基づいて true または false のブール値を返さなければならない関数です。一致した場合には、メッセージに message-first クラスが追加されます。 | |
lastMessageRule | function(message, previousMessage, nextMessage) | 前後のメッセージに応じて、要求された条件に基づいて、true またはfalse のブール値を返さなければならない関数です。一致した場合には、メッセージに message-last クラスが追加されます。 | |
tailMessageRule | function(message, previousMessage, nextMessage) | 前後のメッセージに応じて、要求された条件に基づいて、true またはfalse のブール値を返さなければならない関数です。一致した場合には、メッセージに message-tail クラスが追加されます。 | |
sameNameMessageRule | function(message, previousMessage, nextMessage) | 前後のメッセージに応じて、要求された条件に基づいて、true またはfalse のブール値を返さなければならない関数です。一致した場合には、メッセージに message-same-name クラスが追加されます。 | |
sameHeaderMessageRule | function(message, previousMessage, nextMessage) | 前後のメッセージに応じて、要求された条件に基づいて、真偽値 true または false を返さなければならない関数です。一致した場合には、メッセージに message-same-header クラスが追加されます。 | |
sameFooterMessageRule | function(message, previousMessage, nextMessage) | 前後のメッセージに応じて、要求された条件に基づいて真偽値を返さなければならない関数です。一致した場合には、メッセージに message-same-footer クラスが追加されます。 | |
sameAvatarMessageRule | function(message, previousMessage, nextMessage) | 前後のメッセージに応じて、要求された条件に基づいて、真偽値 true または false を返さなければならない関数です。一致した場合には、メッセージに message-same-avatar クラスが追加されます。 | |
customClassMessageRule | function(message, previousMessage, nextMessage) | 前後のメッセージに応じて、要求された条件に基づいて、追加のメッセージクラスを文字列として返す関数です。 |
シングルメッセージのパラメータ
ここでは、messages
配列を渡す際に使用する、単一のメッセージパラメータオブジェクトについて説明します。
Parameter | Type | Default | Description |
---|---|---|---|
text | string | メッセージのテキスト | |
header | string | 単一メッセージのヘッダ | |
footer | string | シングルメッセージのフッター | |
name | string | 送信者名 | |
avatar | string | 送信者アバターの URL 文字列 | |
type | string | sent | メッセージの種類 - sent または `received' |
textHeader | string | メッセージのテキストヘッダ | |
textFooter | string | メッセージテキストフッター | |
image | string | メッセージ画像のHTML文字列(例:<img src="path/to/image" /> )。imageSrc`パラメータの代わりに使うことができます。 | |
imageSrc | string | メッセージ画像のURL文字列。image`パラメータの代わりに使うことができます。 | |
isTitle | boolean | メッセージとして表示されるか、メッセージのタイトルとして表示されるかを定義します。 | |
cssClass | string | メッセージのHTML要素に設定する追加のCSSクラス | |
attrs | object | メッセージのHTML要素に設定される追加のHTML属性を持つオブジェクトです。例えば、追加の data 属性を設定する場合は、以下のようになります。
|
メッセージのメソッドとプロパティ
メッセージを作成するためには、メッセージを呼び出す必要があります。
var messages = app.messages.create({ /* parameters */ })
メッセージを初期化すると、その初期化されたインスタンスが変数(上記の例では messages
変数)に格納され、便利なメソッドやプロパティが用意されます。
Properties | |
---|---|
messages.params | 初期化パラメータが渡されたオブジェクト |
messages.el | メッセージコンテナ HTML 要素 (<div class="messages"> ) |
messages.$el | メッセージを持つHTML要素を持つDom7要素 |
messages.messages | メッセージを含む配列 |
Methods | |
messages.showTyping(message) | 入力中のメッセージを表示する
|
messages.hideTyping() | 入力中のメッセージ表示を隠す |
messages.addMessage(message, method, animate); | methodパラメータに応じて、新しいメッセージを最後または最初に追加する
|
messages.addMessages(messages, method, animate); | 一度に複数のメッセージを追加することができます。
|
messages.removeMessage(message); | メッセージの削除
|
messages.removeMessages(messages); | 複数のメッセージの削除
|
messages.scroll(duration, position); | newMessagesFirst`パラメータに応じてメッセージを上下にスクロールする
|
messages.renderMessages() | メッセージをHTMLで表示する |
messages.layout(); | メッセージの自動レイアウトを強制する |
messages.clear(); | すべてのメッセージを消去/削除する |
messages.destroy(); | メッセージインスタンスの破棄 |
メッセージのイベント
メッセージは以下のDOMイベントをmessages要素に、イベントをappとmessagesインスタンスに発行します。
DOMイベント
Event | Target | Description |
---|---|---|
messages:beforedestroy | Messages Element<div class="messages"> | Event will be triggered right before Messages instance will be destroyed |
アプリとメッセージ・インスタンスのイベント
Messages インスタンスは、self インスタンスと app インスタンスの両方に対してイベントを発行します。App インスタンスのイベントは、同じ名前でプレフィックスとして messages
が付きます。
Event | Target | Arguments | Description |
---|---|---|---|
beforeDestroy | messages | (messages) | イベントは、メッセージのインスタンスが破棄される直前に発生します。 |
messagesBeforeDestroy | app |
メッセージの自動初期化
メッセージ API を使用する必要がなく、メッセージがページ内にあり、ページの初期化時に DOM に表示される場合は、messages 要素に messages-init
クラスを追加するだけで、自動初期化が可能です。
<div class="messages messages-init" data-new-messages-first="true">
...
</div>
キャメルケースで使われているパラメータ、例えばnewMessagesFirstは、data-属性ではdata-new-messages-firstとしてケバブケースで使われます。
CSS Variables
Below is the list of related CSS variables (CSS custom properties).
Note that commented variables are not specified by default and their values is what they fallback to in this case.
:root {
--f7-message-text-header-text-color: inherit;
--f7-message-text-header-opacity: 0.65;
--f7-message-text-header-font-size: 12px;
--f7-message-text-footer-text-color: inherit;
--f7-message-text-footer-opacity: 0.65;
--f7-message-text-footer-font-size: 12px;
--f7-message-bubble-line-height: 1.2;
--f7-message-header-font-size: 12px;
--f7-message-footer-font-size: 11px;
--f7-message-name-font-size: 12px;
--f7-message-name-font-weight: inherit;
--f7-message-avatar-border-radius: 50%;
--f7-messages-title-font-weight: inherit;
/*
--f7-message-sent-bg-color: var(--f7-theme-color);
*/
--f7-message-sent-text-color: #fff;
--f7-messages-content-bg-color: #fff;
--f7-message-typing-indicator-bg-color: #000;
--f7-message-received-bg-color: #e5e5ea;
--f7-message-received-text-color: #000;
}
:root .theme-dark,
:root.theme-dark {
--f7-messages-title-text-color: rgba(255, 255, 255, 0.54);
--f7-message-header-text-color: rgba(255, 255, 255, 0.54);
--f7-message-name-text-color: rgba(255, 255, 255, 0.54);
--f7-message-footer-text-color: rgba(255, 255, 255, 0.54);
--f7-messages-content-bg-color: transparent;
--f7-message-received-bg-color: #252525;
--f7-message-received-text-color: #fff;
--f7-message-typing-indicator-bg-color: #fff;
}
.ios {
--f7-messages-title-text-color: rgba(0, 0, 0, 0.45);
--f7-messages-title-font-size: 11px;
--f7-message-header-text-color: rgba(0, 0, 0, 0.45);
--f7-message-footer-text-color: rgba(0, 0, 0, 0.45);
--f7-message-name-text-color: rgba(0, 0, 0, 0.45);
--f7-message-avatar-size: 29px;
--f7-message-margin: 10px;
--f7-message-bubble-min-height: 32px;
--f7-message-bubble-font-size: 17px;
--f7-message-bubble-border-radius: 16px;
--f7-message-bubble-padding-vertical: 6px;
--f7-message-bubble-padding-horizontal: 16px;
--f7-message-typing-indicator-opacity: 0.35;
}
.md {
--f7-messages-title-font-size: 12px;
--f7-message-avatar-size: 32px;
--f7-message-margin: 16px;
--f7-message-bubble-min-height: 32px;
--f7-message-bubble-font-size: 16px;
--f7-message-bubble-border-radius: 4px;
--f7-message-bubble-padding-vertical: 6px;
--f7-message-bubble-padding-horizontal: 8px;
--f7-message-typing-indicator-opacity: 0.6;
--f7-messages-title-text-color: rgba(0, 0, 0, 0.51);
--f7-message-header-text-color: rgba(0, 0, 0, 0.51);
--f7-message-footer-text-color: rgba(0, 0, 0, 0.51);
--f7-message-name-text-color: rgba(0, 0, 0, 0.51);
}
.aurora {
--f7-messages-title-font-size: 14px;
--f7-message-avatar-size: 32px;
--f7-message-margin: 16px;
--f7-message-bubble-min-height: 34px;
--f7-message-bubble-font-size: 16px;
--f7-message-bubble-line-height: 1.4;
--f7-message-bubble-border-radius: 16px;
--f7-message-bubble-padding-vertical: 6px;
--f7-message-bubble-padding-horizontal: 10px;
--f7-message-typing-indicator-opacity: 0.5;
--f7-message-header-font-size: 14px;
--f7-message-footer-font-size: 12px;
--f7-message-name-font-size: 14px;
--f7-messages-title-text-color: rgba(0, 0, 0, 0.51);
--f7-message-header-text-color: rgba(0, 0, 0, 0.51);
--f7-message-footer-text-color: rgba(0, 0, 0, 0.51);
--f7-message-name-text-color: rgba(0, 0, 0, 0.51);
}
Examples
<template>
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner">
<div class="title">Messages</div>
</div>
</div>
<div class="toolbar messagebar">
<div class="toolbar-inner">
<div class="messagebar-area">
<textarea class="resizable" placeholder="Message"></textarea>
</div>
<a class="link send-link" href="#" @click=${sendMessage}>Send</a>
</div>
</div>
<div class="page-content messages-content">
<div class="messages">
<div class="messages-title"><b>Sunday, Feb 9,</b> 12:58</div>
<div class="message message-sent">
<div class="message-avatar"
style="background-image:url(https://cdn.framework7.io/placeholder/people-100x100-7.jpg)"></div>
<div class="message-content">
<div class="message-name">John Doe</div>
<div class="message-header">Message header</div>
<div class="message-bubble">
<div class="message-text-header">Text header</div>
<div class="message-text">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</div>
<div class="message-text-footer">Text footer</div>
</div>
<div class="message-footer">Message footer</div>
</div>
</div>
<div class="message message-received">
<div class="message-avatar"
style="background-image:url(https://cdn.framework7.io/placeholder/people-100x100-7.jpg)"></div>
<div class="message-content">
<div class="message-name">John Doe</div>
<div class="message-header">Message header</div>
<div class="message-bubble">
<div class="message-text-header">Text header</div>
<div class="message-text">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</div>
<div class="message-text-footer">Text footer</div>
</div>
<div class="message-footer">Message footer</div>
</div>
</div>
<div class="message message-sent">
<div class="message-content">
<div class="message-bubble">
<div class="message-text">Hi, Kate</div>
</div>
</div>
</div>
<div class="message message-sent">
<div class="message-content">
<div class="message-bubble">
<div class="message-text">How are you?</div>
</div>
</div>
</div>
<div class="message message-received">
<div class="message-avatar"
style="background-image:url(https://cdn.framework7.io/placeholder/people-100x100-9.jpg)"></div>
<div class="message-content">
<div class="message-name">Kate</div>
<div class="message-bubble">
<div class="message-text">Hi, I am good!</div>
</div>
</div>
</div>
<div class="message message-received">
<div class="message-avatar"
style="background-image:url(https://cdn.framework7.io/placeholder/people-100x100-7.jpg)"></div>
<div class="message-content">
<div class="message-name">Blue Ninja</div>
<div class="message-bubble">
<div class="message-text">Hi there, I am also fine, thanks! And how are you?</div>
</div>
</div>
</div>
<div class="message message-sent">
<div class="message-content">
<div class="message-bubble">
<div class="message-text">Hey, Blue Ninja! Glad to see you ;)</div>
</div>
</div>
</div>
<div class="message message-sent">
<div class="message-content">
<div class="message-bubble">
<div class="message-text">Hey, look, cutest kitten ever!</div>
</div>
</div>
</div>
<div class="message message-sent">
<div class="message-content">
<div class="message-bubble">
<div class="message-image">
<img src="https://cdn.framework7.io/placeholder/cats-200x260-4.jpg"
style="width:200px; height: 260px" />
</div>
</div>
</div>
</div>
<div class="message message-received">
<div class="message-avatar"
style="background-image:url(https://cdn.framework7.io/placeholder/people-100x100-9.jpg)"></div>
<div class="message-content">
<div class="message-name">Kate</div>
<div class="message-bubble">
<div class="message-text">Nice!</div>
</div>
</div>
</div>
<div class="message message-received">
<div class="message-avatar"
style="background-image:url(https://cdn.framework7.io/placeholder/people-100x100-9.jpg)"></div>
<div class="message-content">
<div class="message-name">Kate</div>
<div class="message-bubble">
<div class="message-text">Like it very much!</div>
</div>
</div>
</div>
<div class="message message-received">
<div class="message-avatar"
style="background-image:url(https://cdn.framework7.io/placeholder/people-100x100-7.jpg)"></div>
<div class="message-content">
<div class="message-name">Blue Ninja</div>
<div class="message-bubble">
<div class="message-text">Awesome!</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default (props, { $f7, $, $on }) => {
let messages;
let messagebar;
// Response flag
var responseInProgress = false;
// Dummy response
var answers = [
'Yes!',
'No',
'Hm...',
'I am not sure',
'And what about you?',
'May be ;)',
'Lorem ipsum dolor sit amet, consectetur',
'What?',
'Are you sure?',
'Of course',
'Need to think about it',
'Amazing!!!'
]
var people = [
{
name: 'Kate Johnson',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-9.jpg'
},
{
name: 'Blue Ninja',
avatar: 'https://cdn.framework7.io/placeholder/people-100x100-7.jpg'
}
];
// Receive Message
const receiveMessage = () => {
responseInProgress = true;
setTimeout(function () {
// Get random answer and random person
var answer = answers[Math.floor(Math.random() * answers.length)];
var person = people[Math.floor(Math.random() * people.length)];
// Show typing indicator
messages.showTyping({
header: person.name + ' is typing',
avatar: person.avatar
});
setTimeout(function () {
// Add received dummy message
messages.addMessage({
text: answer,
type: 'received',
name: person.name,
avatar: person.avatar
});
// Hide typing indicator
messages.hideTyping();
responseInProgress = false;
}, 4000);
}, 1000);
}
// Send Message
const sendMessage = () => {
var text = messagebar.getValue().replace(/\n/g, '<br>').trim();
// return if empty message
if (!text.length) return;
// Clear area
messagebar.clear();
// Return focus to area
messagebar.focus();
// Add message to messages
messages.addMessage({
text: text,
});
if (responseInProgress) return;
// Receive dummy message
receiveMessage();
}
$on('pageInit', () => {
// Init Messages
messages = app.messages.create({
el: '.messages',
// First message rule
firstMessageRule: function (message, previousMessage, nextMessage) {
// Skip if title
if (message.isTitle) return false;
/* if:
- there is no previous message
- or previous message type (send/received) is different
- or previous message sender name is different
*/
if (!previousMessage || previousMessage.type !== message.type || previousMessage.name !== message.name) return true;
return false;
},
// Last message rule
lastMessageRule: function (message, previousMessage, nextMessage) {
// Skip if title
if (message.isTitle) return false;
/* if:
- there is no next message
- or next message type (send/received) is different
- or next message sender name is different
*/
if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
return false;
},
// Last message rule
tailMessageRule: function (message, previousMessage, nextMessage) {
// Skip if title
if (message.isTitle) return false;
/* if (basically same as lastMessageRule):
- there is no next message
- or next message type (send/received) is different
- or next message sender name is different
*/
if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
return false;
}
});
// Init Messagebar
messagebar = app.messagebar.create({
el: '.messagebar'
});
});
return $render;
}
</script>