メッセージ
メッセージコンポーネントは、アプリでのコメントやメッセージングシステムの視覚化に役立ちます。
メッセージレイアウト
<div class="page">
<div class="page-content messages-content">
<div class="messages">
<!-- Date stamp -->
<div class="messages-title"><b>Sunday, Feb 9</b> 12:58</div>
<!-- Sent message (by default - green and on right side) -->
<div class="message message-sent">
<div class="message-content">
<!-- Bubble with text -->
<div class="message-bubble">
<div class="message-text">Hi, Kate</div>
</div>
</div>
</div>
<!-- Another sent message -->
<div class="message message-sent">
<div class="message-content">
<div class="message-bubble">
<div class="message-text">How are you?</div>
</div>
</div>
</div>
<!-- Received message (by default - grey on left side) -->
<div class="message message-received">
<!-- Sender avatar -->
<div class="message-avatar" style="background-image:url(path/to/avatar.jpg)"></div>
<div class="message-content">
<!-- Sender name -->
<div class="message-name">Blue Ninja</div>
<!-- Bubble with text -->
<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
- バブルの「尻尾」を追加する単一のメッセージ(受信または送信)の追加クラスmessage-same-name
- 前のメッセージと同じ送信者名を持つことを示す追加クラスmessage-same-avatar
- 前のメッセージと同じアバターを持つことを示す追加クラスmessage-same-header
- 前のメッセージと同じmessage-headerを持つことを示す追加クラスmessage-same-footer
- 前のメッセージと同じmessage-footerを持つことを示す追加クラスmessage-last
- 現在の会話で1人の送信者が最後に受信または送信したメッセージを示す単一のメッセージ(受信または送信)の追加クラスmessage-first
- 現在の会話で1人の送信者が最初に受信または送信したメッセージを示す単一のメッセージ(受信または送信)の追加クラス
メッセージのアプリメソッド
さて、メッセージのHTMLができたら、初期化する必要があります。関連するアプリのメソッドを使用する必要があります
app.messages.create(parameters) | パラメータを指定してメッセージを初期化します
|
app.messages.destroy(el) | メッセージインスタンスを破棄します
|
app.messages.get(el) | HTML要素でメッセージインスタンスを取得します
|
メッセージのパラメータ
利用可能なすべてのパラメータのリストを見てみましょう
パラメータ | 型 | デフォルト | 説明 |
---|---|---|---|
autoLayout | boolean | true | 渡された条件に基づいて、必要な追加クラスをすべて自動的に追加する自動レイアウトを有効にします |
newMessagesFirst | boolean | false | 新しいメッセージを下に配置するのではなく、上に表示したい場合は有効にします |
scrollMessages | boolean | true | 新しいメッセージを追加するときにメッセージの自動スクロールを有効/無効にします |
scrollMessagesOnEdge | boolean | true | 有効にすると、メッセージの自動スクロールは、ユーザーがメッセージビューの上/下にある場合にのみ発生します |
messages | 配列 | 初期メッセージの配列。配列内の各メッセージは、単一メッセージパラメータを持つオブジェクトとして表現する必要があります | |
on | オブジェクト | イベントハンドラーを持つオブジェクト。例:
| |
renderMessage | function(message) | 単一のメッセージをレンダリングする関数。完全なメッセージHTML文字列を返す必要があります | |
自動レイアウト条件 | |||
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) | 前後のメッセージに応じた必要な条件に基づいてブール値true またはfalse を返す必要がある関数。一致した場合、message-same-footer クラスがメッセージに追加されます | |
sameAvatarMessageRule | function(message, previousMessage, nextMessage) | 前後のメッセージに応じた必要な条件に基づいてブール値true またはfalse を返す必要がある関数。一致した場合、message-same-avatar クラスがメッセージに追加されます | |
customClassMessageRule | function(message, previousMessage, nextMessage) | 前後のメッセージに応じた必要な条件に基づいて、追加のメッセージクラスを文字列として返す必要がある関数。 |
単一メッセージパラメータ
messages
配列を渡すときに使用する必要がある単一メッセージパラメータオブジェクトを見てみましょう
パラメータ | 型 | デフォルト | 説明 |
---|---|---|---|
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 | オブジェクト | メッセージHTML要素に設定する追加のHTML属性を持つオブジェクト。たとえば、追加のdata 属性を設定するには、次のようにする必要があります
|
メッセージのメソッドとプロパティ
メッセージを作成するには、次を呼び出す必要があります
var messages = app.messages.create({ /* parameters */ })
メッセージを初期化すると、便利なメソッドとプロパティを持つ初期化されたインスタンスが変数(上記の例ではmessages
変数など)に格納されます
プロパティ | |
---|---|
messages.params | 渡された初期化パラメータを持つオブジェクト |
messages.el | メッセージコンテナのHTML要素(<div class="messages"> ) |
messages.$el | メッセージHTML要素を持つDom7要素 |
messages.messages | メッセージを持つ配列 |
メソッド | |
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() | messages 配列に応じてメッセージのHTMLをレンダリングします |
messages.layout(); | メッセージの自動レイアウトを強制します |
messages.clear(); | すべてのメッセージをクリア/削除します |
messages.destroy(); | メッセージインスタンスを破棄します |
メッセージイベント
メッセージは、メッセージ要素上で以下のDOMイベントを、アプリおよびメッセージインスタンス上でイベントを発火します。
DOMイベント
イベント | ターゲット | 説明 |
---|---|---|
messages:beforedestroy | メッセージ要素<div class="messages"> | このイベントは、メッセージインスタンスが破棄される直前にトリガーされます |
アプリおよびメッセージインスタンスのイベント
メッセージインスタンスは、自身のインスタンスとアプリインスタンスの両方でイベントを発行します。アプリインスタンスのイベントには、messages
という接頭辞が付いた同じ名前が付けられます。
イベント | ターゲット | 引数 | 説明 |
---|---|---|---|
beforeDestroy | messages | (messages) | このイベントは、メッセージインスタンスが破棄される直前にトリガーされます |
messagesBeforeDestroy | app |
メッセージの自動初期化
メッセージAPIを使用する必要がなく、メッセージがページの初期化時にDOMに存在する場合、メッセージ要素にmessages-init
クラスを追加するだけで自動的に初期化できます。必要なすべてのパラメータは、data-
属性を使用して渡すことができます。
<div class="messages messages-init" data-new-messages-first="true">
...
</div>
キャメルケースで使用されるパラメータ(例:newMessagesFirst)は、data-属性ではdata-new-messages-firstのようにケバブケースで使用する必要があります。
CSS 変数
以下は、関連するCSS変数(CSSカスタムプロパティ)のリストです。
コメントアウトされた変数はデフォルトでは指定されておらず、その値はこの場合のフォールバック値であることに注意してください。
:root {
--f7-message-text-header-opacity: 0.65;
--f7-message-text-header-font-size: 12px;
--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-typing-indicator-bg-color: #000;
}
:root .dark,
:root.dark {
--f7-message-typing-indicator-bg-color: #fff;
}
.ios {
--f7-message-text-header-text-color: inherit;
--f7-message-text-footer-text-color: inherit;
--f7-messages-title-font-size: 11px;
--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;
/*
--f7-message-sent-bg-color: var(--f7-theme-color);
*/
--f7-message-sent-text-color: #fff;
--f7-messages-content-bg-color: #fff;
--f7-message-received-text-color: #000;
--f7-message-received-bg-color: #e5e5ea;
--f7-messages-title-text-color: rgba(0, 0, 0, 0.45);
--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);
}
.ios .dark,
.ios.dark {
--f7-message-received-bg-color: #252525;
--f7-message-received-text-color: #fff;
--f7-messages-content-bg-color: transparent;
--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);
}
.md {
--f7-messages-content-bg-color: transparent;
--f7-messages-title-font-size: 12px;
--f7-message-avatar-size: 32px;
--f7-message-margin: 16px;
--f7-message-bubble-min-height: 40px;
--f7-message-bubble-font-size: 16px;
--f7-message-bubble-border-radius: 20px;
--f7-message-bubble-padding-vertical: 10px;
--f7-message-bubble-padding-horizontal: 16px;
--f7-message-typing-indicator-opacity: 0.6;
}
.md,
.md .dark,
.md [class*='color-'] {
--f7-message-sent-bg-color: var(--f7-md-primary);
--f7-message-sent-text-color: var(--f7-md-on-primary);
--f7-message-received-bg-color: var(--f7-md-surface-variant);
--f7-message-received-text-color: var(--f7-md-on-surface);
--f7-message-text-header-text-color: var(--f7-md-on-surface-variant);
--f7-message-text-footer-text-color: var(--f7-md-on-surface-variant);
--f7-messages-title-text-color: var(--f7-md-on-surface-variant);
--f7-message-header-text-color: var(--f7-md-on-surface-variant);
--f7-message-footer-text-color: var(--f7-md-on-surface-variant);
--f7-message-name-text-color: var(--f7-md-on-surface-variant);
}
例
<template>
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner sliding">
<div class="title">Messages</div>
</div>
</div>
<div class="toolbar messagebar" @messagebar:attachmentdelete=${deleteAttachment}>
<div class="toolbar-inner">
<a class="link icon-only" @click=${sheetToggle}>
<i class="icon f7-icons if-not-md">camera_fill</i>
<i class="icon material-icons md-only">camera_alt</i>
</a>
<div class="messagebar-area">
<textarea class="resizable" placeholder="Message"></textarea>
</div>
<a class="link icon-only demo-send-message-link" @click=${sendMessage}>
<i class="icon f7-icons if-not-md">arrow_up_circle_fill</i>
<i class="icon material-icons md-only">send</i>
</a>
</div>
<div class="messagebar-sheet">
${images.map((image) => $h`
<label class="checkbox messagebar-sheet-image" @change=${handleAttachment}>
<input type="checkbox" />
<i class="icon icon-checkbox"></i>
<img src=${image} />
</label>
`)}
</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-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, $el, $on, $ }) => {
const images = [
'https://cdn.framework7.io/placeholder/cats-300x300-1.jpg',
'https://cdn.framework7.io/placeholder/cats-200x300-2.jpg',
'https://cdn.framework7.io/placeholder/cats-400x300-3.jpg',
'https://cdn.framework7.io/placeholder/cats-300x150-4.jpg',
'https://cdn.framework7.io/placeholder/cats-150x300-5.jpg',
'https://cdn.framework7.io/placeholder/cats-300x300-6.jpg',
'https://cdn.framework7.io/placeholder/cats-300x300-7.jpg',
'https://cdn.framework7.io/placeholder/cats-200x300-8.jpg',
'https://cdn.framework7.io/placeholder/cats-400x300-9.jpg',
'https://cdn.framework7.io/placeholder/cats-300x150-10.jpg'
];
const 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'
},
];
const 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!!!',
];
let responseInProgress = false;
let messagebar;
let messages;
const sheetToggle = () => {
messagebar.sheetToggle();
}
const deleteAttachment = (e, index) => {
var image = messagebar.attachments.splice(index, 1)[0];
messagebar.renderAttachments();
checkAttachments();
// Uncheck in sheet
var imageIndex = images.indexOf(image);
$el.value.find('.messagebar-sheet .checkbox').eq(imageIndex).find('input').prop('checked', false);
}
const handleAttachment = (e) => {
var index = $(e.target).parents('label.checkbox').index();
var image = images[index];
if (e.target.checked) {
// Add to attachments
messagebar.attachments.unshift(image)
} else {
// Remove from attachments
messagebar.attachments.splice(messagebar.attachments.indexOf(image), 1);
}
messagebar.renderAttachments();
checkAttachments();
}
const checkAttachments = () => {
if (messagebar.attachments.length > 0) {
messagebar.attachmentsShow();
messagebar.setPlaceholder('Add comment or Send');
} else {
messagebar.attachmentsHide();
messagebar.setPlaceholder('Message');
}
}
const sendMessage = () => {
var text = messagebar.getValue().replace(/\n/g, '<br />').trim();
var messagesToSend = [];
messagebar.attachments.forEach(function (attachment) {
var size = attachment.split('placeholder/cats-')[1].split('-')[0].split('x');
messagesToSend.push({
image: '<img src="' + attachment + '" style="width: ' + (size[0] / 2) + 'px; height: ' + (size[1] / 2) + 'px">'
});
});
if (text.trim().length) {
messagesToSend.push({
text: text
});
}
// Reset attachments
messagebar.attachments = [];
checkAttachments();
// Hide sheet
messagebar.sheetHide();
// Uncheck selected images in sheet
messagebar.$sheetEl.find('input').prop('checked', false);
// Clear area
messagebar.clear();
// Focus area
if (text.length) messagebar.focus();
// Exit when nothing to send
if (!messagesToSend.length) return;
// Send message
messages.addMessages(messagesToSend);
// Mock response
if (responseInProgress) return;
responseInProgress = true;
setTimeout(function () {
var answer = answers[Math.floor(Math.random() * answers.length)];
var person = people[Math.floor(Math.random() * people.length)];
messages.showTyping({
header: person.name + ' is typing',
avatar: person.avatar
});
setTimeout(function () {
messages.addMessage({
text: answer,
type: 'received',
name: person.name,
avatar: person.avatar
});
messages.hideTyping();
responseInProgress = false;
}, 4000);
}, 1000);
}
$on('pageInit', () => {
messagebar = $f7.messagebar.create({
el: $el.value.find('.messagebar'),
attachments: []
});
messages = $f7.messages.create({
el: $el.value.find('.messages'),
firstMessageRule: function (message, previousMessage, nextMessage) {
if (message.isTitle) return false;
if (!previousMessage || previousMessage.type !== message.type || previousMessage.name !== message.name) return true;
return false;
},
lastMessageRule: function (message, previousMessage, nextMessage) {
if (message.isTitle) return false;
if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
return false;
},
tailMessageRule: function (message, previousMessage, nextMessage) {
if (message.isTitle) return false;
if (!nextMessage || nextMessage.type !== message.type || nextMessage.name !== message.name) return true;
return false;
}
});
})
$on('pageBeforeRemove', () => {
messagebar.destroy()
messages.destroy()
})
return $render;
};
</script>