2017-10-24 20:15:35 +02:00
|
|
|
# UI: Input Pills
|
|
|
|
|
|
|
|
This is a high level and API explanation of the input pill interface in the
|
|
|
|
frontend of the Zulip web application.
|
|
|
|
|
2017-11-29 06:45:11 +01:00
|
|
|
## Setup
|
2017-10-24 20:15:35 +02:00
|
|
|
|
|
|
|
A pill container should have the following markup:
|
|
|
|
|
|
|
|
```html
|
|
|
|
<div class="pill-container">
|
|
|
|
<div class="input" contenteditable="true"></div>
|
|
|
|
</div>
|
|
|
|
```
|
|
|
|
|
|
|
|
The pills will automatically be inserted in before the ".input" in order.
|
|
|
|
|
2018-03-06 15:03:20 +01:00
|
|
|
## Basic Usage
|
2017-10-24 20:15:35 +02:00
|
|
|
|
|
|
|
```js
|
2018-03-06 15:03:20 +01:00
|
|
|
var pill_containter = $("#input_container");
|
|
|
|
var pills = input_pill.create({
|
|
|
|
container: pill_container,
|
|
|
|
create_item_from_text: user_pill.create_item_from_email,
|
|
|
|
get_text_from_item: user_pill.get_email_from_item,
|
2017-10-24 20:15:35 +02:00
|
|
|
});
|
|
|
|
```
|
2017-10-25 01:05:47 +02:00
|
|
|
|
2018-03-06 15:03:20 +01:00
|
|
|
You can look at `static/js/user_pill.js` to see how the above
|
|
|
|
methods are implemented. Essentially you just need to convert
|
|
|
|
from raw data (like an email) to structured data (like an object
|
|
|
|
with display_value, email, and user_id for a user), and vice
|
|
|
|
versa. The most important field to supply is `display_value`.
|
|
|
|
For user pills `pill_item.display_value === user.full_name`.
|
2017-10-25 01:05:47 +02:00
|
|
|
|
2018-03-06 15:03:20 +01:00
|
|
|
## Typeahead
|
2017-10-25 01:05:47 +02:00
|
|
|
|
2018-03-06 15:03:20 +01:00
|
|
|
Pills almost always work in conjunction with typeahead, and
|
|
|
|
you will want to provide a `source` function to typeahead
|
|
|
|
that can exclude items from the prior pills. Here is an
|
|
|
|
example snippet from our user group settings code.
|
2017-10-25 01:05:47 +02:00
|
|
|
|
|
|
|
```js
|
2018-03-06 15:03:20 +01:00
|
|
|
source: function () {
|
|
|
|
return user_pill.typeahead_source(pills);
|
|
|
|
},
|
|
|
|
```
|
2017-10-25 01:05:47 +02:00
|
|
|
|
2018-03-06 15:03:20 +01:00
|
|
|
And then in `user_pill.js`...
|
2017-10-25 01:05:47 +02:00
|
|
|
|
2018-03-06 15:03:20 +01:00
|
|
|
```js
|
|
|
|
exports.typeahead_source = function (pill_widget) {
|
2020-03-21 19:53:16 +01:00
|
|
|
const persons = people.get_realm_users();
|
2020-01-08 15:51:04 +01:00
|
|
|
return exports.filter_taken_users(persons, pill_widget);
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.filter_taken_users = function (items, pill_widget) {
|
|
|
|
const taken_user_ids = exports.get_user_ids(pill_widget);
|
2020-02-08 03:33:46 +01:00
|
|
|
items = items.filter(item => !taken_user_ids.includes(item.user_id));
|
2018-03-06 15:03:20 +01:00
|
|
|
return items;
|
|
|
|
};
|
2017-10-25 01:05:47 +02:00
|
|
|
```
|
|
|
|
|
2018-03-06 15:03:20 +01:00
|
|
|
### `onPillCreate` and `onPillRemove` methods
|
2017-10-25 01:05:47 +02:00
|
|
|
|
2018-03-06 15:03:20 +01:00
|
|
|
You can get notifications from the pill code that pills have been
|
|
|
|
created/remove.
|
2017-10-25 01:05:47 +02:00
|
|
|
|
|
|
|
|
2018-03-06 15:03:20 +01:00
|
|
|
```js
|
|
|
|
pills.onPillCreate(function () {
|
|
|
|
update_save_state();
|
|
|
|
});
|
2017-10-25 01:05:47 +02:00
|
|
|
|
2018-03-06 15:03:20 +01:00
|
|
|
pills.onPillRemove(function () {
|
|
|
|
update_save_state();
|
2017-10-25 01:05:47 +02:00
|
|
|
});
|
|
|
|
```
|