Commit 58ee9026 authored by Mark Florian's avatar Mark Florian

Merge branch 'deprecate-droplab' into 'master'

Deprecate DropLab library

See merge request gitlab-org/gitlab!68109
parents c9ec6e4e 85474af9
......@@ -5,8 +5,8 @@ import {
canCreateConfidentialMergeRequest,
} from './confidential_merge_request';
import confidentialMergeRequestState from './confidential_merge_request/state';
import DropLab from './droplab/drop_lab';
import ISetter from './droplab/plugins/input_setter';
import DropLab from './filtered_search/droplab/drop_lab_deprecated';
import ISetter from './filtered_search/droplab/plugins/input_setter';
import createFlash from './flash';
import axios from './lib/utils/axios_utils';
import { __, sprintf } from './locale';
......
import createFlash from '~/flash';
import { __ } from '~/locale';
import AjaxFilter from '../droplab/plugins/ajax_filter';
import AjaxFilter from './droplab/plugins/ajax_filter';
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdown from './filtered_search_dropdown';
import FilteredSearchTokenizer from './filtered_search_tokenizer';
......
import createFlash from '~/flash';
import { __ } from '~/locale';
import Ajax from '../droplab/plugins/ajax';
import Filter from '../droplab/plugins/filter';
import Ajax from './droplab/plugins/ajax';
import Filter from './droplab/plugins/filter';
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdown from './filtered_search_dropdown';
......
import Filter from '~/droplab/plugins/filter';
import { __ } from '~/locale';
import Filter from './droplab/plugins/filter';
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdown from './filtered_search_dropdown';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
......
import createFlash from '~/flash';
import { __ } from '~/locale';
import Ajax from '../droplab/plugins/ajax';
import Filter from '../droplab/plugins/filter';
import Ajax from './droplab/plugins/ajax';
import Filter from './droplab/plugins/filter';
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdown from './filtered_search_dropdown';
......
import Filter from '~/droplab/plugins/filter';
import { __ } from '~/locale';
import Filter from './droplab/plugins/filter';
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdown from './filtered_search_dropdown';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
......
/**
* This library is deprecated and scheduled to be removed once the
* filtered_search component is replaced with GitLab's new Pajamas
* filter vue component.
*
* The documentation has been removed from the gitlab codebase but
* can still be found in the commit history here:
* https://gitlab.com/gitlab-org/gitlab/-/blob/28f20e28/doc/development/fe_guide/droplab/droplab.md
*/
import { DATA_TRIGGER } from './constants';
import HookButton from './hook_button';
import HookInput from './hook_input';
......
/* eslint-disable */
import AjaxCache from '../../lib/utils/ajax_cache';
import AjaxCache from '~/lib/utils/ajax_cache';
const AjaxFilter = {
init: function (hook) {
......
import { last } from 'lodash';
import AvailableDropdownMappings from 'ee_else_ce/filtered_search/available_dropdown_mappings';
import DropLab from '~/droplab/drop_lab';
import DropLab from './droplab/drop_lab_deprecated';
import { DROPDOWN_TYPE } from './constants';
import FilteredSearchContainer from './container';
import DropdownUtils from './dropdown_utils';
......
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# DropLab
A generic dropdown for all of your custom dropdown needs.
## Usage
DropLab can be used by adding a `data-dropdown-trigger` HTML attribute. This
attribute allows us to find the "trigger" _(toggle)_ for the dropdown, whether
it's a button, link or input.
The value of the `data-dropdown-trigger` should be a CSS selector that DropLab
can use to find the trigger's dropdown list.
You should also add the `data-dropdown` attribute to declare the dropdown list.
The value is irrelevant.
The DropLab class has no side effects, so you must always call `.init` when the
DOM is ready. `DropLab.prototype.init` takes the same arguments as `DropLab.prototype.addHook`.
If you don't provide any arguments, it globally queries and instantiates all
DropLab-compatible dropdowns.
```html
<a href="#" data-dropdown-trigger="#list">Toggle</a>
<ul id="list" data-dropdown>
<!-- ... -->
<ul>
```
```javascript
const droplab = new DropLab();
droplab.init();
```
As noted, we have a "Toggle" link that's declared as a trigger. It provides a
selector to find the dropdown list it should control.
### Static data
You can add static list items.
```html
<a href="#" data-dropdown-trigger="#list">Toggle</a>
<ul id="list" data-dropdown>
<li>Static value 1</li>
<li>Static value 2</li>
<ul>
```
```javascript
const droplab = new DropLab();
droplab.init();
```
### Explicit instantiation
You can pass the trigger and list elements as constructor arguments to return a
non-global instance of DropLab using the `DropLab.prototype.init` method.
```html
<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a>
<ul id="list" data-dropdown>
<!-- ... -->
<ul>
```
```javascript
const trigger = document.getElementById('trigger');
const list = document.getElementById('list');
const droplab = new DropLab();
droplab.init(trigger, list);
```
You can also add hooks to an existing DropLab instance using `DropLab.prototype.addHook`.
```html
<a href="#" data-dropdown-trigger="#auto-dropdown">Toggle</a>
<ul id="auto-dropdown" data-dropdown><!-- ... --><ul>
<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a>
<ul id="list" data-dropdown><!-- ... --><ul>
```
```javascript
const droplab = new DropLab();
droplab.init();
const trigger = document.getElementById('trigger');
const list = document.getElementById('list');
droplab.addHook(trigger, list);
```
### Dynamic data
Adding `data-dynamic` to your dropdown element enables dynamic list
rendering.
You can template a list item using the keys of the data object provided. Use the
handlebars syntax `{{ value }}` to HTML escape the value. Use the `<%= value %>`
syntax to interpolate the value. Use the `<%= value %>` syntax to evaluate the
value.
Passing an array of objects to `DropLab.prototype.addData` renders that data
for all `data-dynamic` dropdown lists tracked by that DropLab instance.
```html
<a href="#" data-dropdown-trigger="#list">Toggle</a>
<ul id="list" data-dropdown data-dynamic>
<li><a href="#" data-id="{{id}}">{{text}}</a></li>
</ul>
```
```javascript
const droplab = new DropLab();
droplab.init().addData([{
id: 0,
text: 'Jacob',
}, {
id: 1,
text: 'Jeff',
}]);
```
Alternatively, you can specify a specific dropdown to add this data to by
passing the data as the second argument and the `id` of the trigger element as
the first argument.
```html
<a href="#" data-dropdown-trigger="#list" id="trigger">Toggle</a>
<ul id="list" data-dropdown data-dynamic>
<li><a href="#" data-id="{{id}}">{{text}}</a></li>
</ul>
```
```javascript
const droplab = new DropLab();
droplab.init().addData('trigger', [{
id: 0,
text: 'Jacob',
}, {
id: 1,
text: 'Jeff',
}]);
```
This allows you to mix static and dynamic content, even with one trigger.
Note the use of scoping regarding the `data-dropdown` attribute to capture both
dropdown lists, one of which is dynamic.
```html
<input id="trigger" data-dropdown-trigger="#list">
<div id="list" data-dropdown>
<ul>
<li><a href="#">Static item 1</a></li>
<li><a href="#">Static item 2</a></li>
</ul>
<ul data-dynamic>
<li><a href="#" data-id="{{id}}">{{text}}</a></li>
</ul>
</div>
```
```javascript
const droplab = new DropLab();
droplab.init().addData('trigger', [{
id: 0,
text: 'Jacob',
}, {
id: 1,
text: 'Jeff',
}]);
```
## Internal selectors
DropLab adds some CSS classes to help lower the barrier to integration.
For example:
- The `droplab-item-selected` CSS class is added to items that have been
selected either by a mouse click or by enter key selection.
- The `droplab-item-active` CSS class is added to items that have been selected
using arrow key navigation.
- You can add the `droplab-item-ignore` CSS class to any item that you don't
want to be selectable. For example, an `<li class="divider"></li>` list
divider element that shouldn't be interactive.
## Internal events
DropLab uses some custom events to help lower the barrier to integration.
For example:
- The `click.dl` event is fired when an `li` list item has been clicked. It's
also fired when a list item has been selected with the keyboard. It's also
fired when a `HookButton` button is clicked (a registered `button` tag or `a`
tag trigger).
- The `input.dl` event is fired when a `HookInput` (a registered `input` tag
trigger) triggers an `input` event.
- The `mousedown.dl` event is fired when a `HookInput` triggers a `mousedown`
event.
- The `keyup.dl` event is fired when a `HookInput` triggers a `keyup` event.
- The `keydown.dl` event is fired when a `HookInput` triggers a `keydown` event.
These custom events add a `detail` object to the vanilla `Event` object that
provides some potentially useful data.
## Plugins
Plugins are objects that are registered to be executed when a hook is added (when
a DropLab trigger and dropdown are instantiated).
If no modules API is detected, the library falls back as it does with
`window.DropLab` and adds `window.DropLab.plugins.PluginName`.
### Usage
To use plugins, you can pass them in an array as the third argument of
`DropLab.prototype.init` or `DropLab.prototype.addHook`. Some plugins require
configuration values; the configuration object can be passed as the fourth argument.
```html
<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a>
<ul id="list" data-dropdown><!-- ... --><ul>
```
```javascript
const droplab = new DropLab();
const trigger = document.getElementById('trigger');
const list = document.getElementById('list');
droplab.init(trigger, list, [droplabAjax], {
droplabAjax: {
endpoint: '/some-endpoint',
method: 'setData',
},
});
```
### Documentation
Refer to the list of available [DropLab plugins](plugins/index.md) for
information about their use.
### Development
When plugins are initialised for a DropLab trigger+dropdown, DropLab calls the
plugins' `init` function, so this must be implemented in the plugin.
```javascript
class MyPlugin {
static init() {
this.someProp = 'someProp';
this.someMethod();
}
static someMethod() {
this.otherProp = 'otherProp';
}
}
export default MyPlugin;
```
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Ajax plugin
`Ajax` is a DropLab plugin that allows for retrieving and rendering list data
from a server.
## Usage
Add the `Ajax` object to the plugins array of a `DropLab.prototype.init` or
`DropLab.prototype.addHook` call.
`Ajax` requires 2 configuration values: the `endpoint` and `method`.
- `endpoint`: Should be a URL to the request endpoint.
- `method`: Should be `setData` or `addData`.
- `setData`: Completely replaces the dropdown with the response data.
- `addData`: Appends the response data to the current dropdown list.
```html
<a href="#" id="trigger" data-dropdown-trigger="#list">Toggle</a>
<ul id="list" data-dropdown><!-- ... --><ul>
```
```javascript
const droplab = new DropLab();
const trigger = document.getElementById('trigger');
const list = document.getElementById('list');
droplab.addHook(trigger, list, [Ajax], {
Ajax: {
endpoint: '/some-endpoint',
method: 'setData',
},
});
```
Optionally, you can set `loadingTemplate` to a HTML string. This HTML string
replaces the dropdown list while the request is pending.
Additionally, you can set `onError` to a function to catch any XHR errors.
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Filter plugin
`Filter` is a DropLab plugin that allows for filtering data that has been added
to the dropdown using a simple fuzzy string search of an input value.
## Usage
Add the `Filter` object to the plugins array of a `DropLab.prototype.init` or
`DropLab.prototype.addHook` call.
- `Filter`: Requires a configuration value for `template`.
- `template`: Should be the key of the objects within your data array that you
want to compare to the user input string, for filtering.
```html
<input href="#" id="trigger" data-dropdown-trigger="#list">
<ul id="list" data-dropdown data-dynamic>
<li><a href="#" data-id="{{id}}">{{text}}</a></li>
<ul>
```
```javascript
const droplab = new DropLab();
const trigger = document.getElementById('trigger');
const list = document.getElementById('list');
droplab.init(trigger, list, [Filter], {
Filter: {
template: 'text',
},
});
droplab.addData('trigger', [{
id: 0,
text: 'Jacob',
}, {
id: 1,
text: 'Jeff',
}]);
```
In the previous code, the input string is compared against the `test` key of the
passed data objects.
Optionally you can set `filterFunction` to a function. This function is then
used instead of `Filter`'s built-in string search. `filterFunction` is passed
two arguments: the first is one of the data objects, and the second is the
current input value.
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
description: A list of DropLab plugins.
---
# DropLab plugins
The following plugins are available for use with [DropLab](../droplab.md):
- [Ajax plugin](ajax.md)
- [Filter plugin](filter.md)
- [InputSetter plugin](input_setter.md)
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# InputSetter plugin
`InputSetter` is a DropLab plugin that allows for updating DOM out of the scope
of DropLab when a list item is clicked.
## Usage
Add the `InputSetter` object to the plugins array of a `DropLab.prototype.init`
or `DropLab.prototype.addHook` call.
- `InputSetter`: Requires a configuration value for `input` and `valueAttribute`.
- `input`: The DOM element that you want to manipulate.
- `valueAttribute`: A string that's the name of an attribute on your list items
that's used to get the value to update the `input` element with.
You can also set the `InputSetter` configuration to an array of objects, which
allows you to update multiple elements.
```html
<input id="input" value="">
<div id="div" data-selected-id=""></div>
<input href="#" id="trigger" data-dropdown-trigger="#list">
<ul id="list" data-dropdown data-dynamic>
<li><a href="#" data-id="{{id}}">{{text}}</a></li>
<ul>
```
```javascript
const droplab = new DropLab();
const trigger = document.getElementById('trigger');
const list = document.getElementById('list');
const input = document.getElementById('input');
const div = document.getElementById('div');
droplab.init(trigger, list, [InputSetter], {
InputSetter: [{
input: input,
valueAttribute: 'data-id',
} {
input: div,
valueAttribute: 'data-id',
inputAttribute: 'data-selected-id',
}],
});
droplab.addData('trigger', [{
id: 0,
text: 'Jacob',
}, {
id: 1,
text: 'Jeff',
}]);
```
In the previous code, if the second list item was clicked, it would update the
`#input` element to have a `value` of `1`, it would also update the `#div`
element's `data-selected-id` to `1`.
Optionally, you can set `inputAttribute` to a string that's the name of an
attribute on your `input` element that you want to update. If you don't provide
an `inputAttribute`, `InputSetter` updates the `value` of the `input`
element if it's an `INPUT` element, or the `textContent` of the `input` element
if it isn't an `INPUT` element.
import DropdownUtils from '~/filtered_search/dropdown_utils';
import FilteredSearchDropdown from '~/filtered_search/filtered_search_dropdown';
import CustomNumber from '../droplab/plugins/custom_number';
import CustomNumber from './droplab/plugins/custom_number';
export default class DropdownWeight extends FilteredSearchDropdown {
constructor(options = {}) {
......
import * as constants from '~/droplab/constants';
import * as constants from '~/filtered_search/droplab/constants';
describe('constants', () => {
describe('DATA_TRIGGER', () => {
......
import { SELECTED_CLASS } from '~/droplab/constants';
import DropDown from '~/droplab/drop_down';
import utils from '~/droplab/utils';
import { SELECTED_CLASS } from '~/filtered_search/droplab/constants';
import DropDown from '~/filtered_search/droplab/drop_down';
import utils from '~/filtered_search/droplab/utils';
describe('DropLab DropDown', () => {
let testContext;
......
import DropDown from '~/droplab/drop_down';
import Hook from '~/droplab/hook';
import DropDown from '~/filtered_search/droplab/drop_down';
import Hook from '~/filtered_search/droplab/hook';
jest.mock('~/droplab/drop_down', () => jest.fn());
jest.mock('~/filtered_search/droplab/drop_down', () => jest.fn());
describe('Hook', () => {
let testContext;
......
import AjaxFilter from '~/droplab/plugins/ajax_filter';
import AjaxFilter from '~/filtered_search/droplab/plugins/ajax_filter';
import AjaxCache from '~/lib/utils/ajax_cache';
describe('AjaxFilter', () => {
......
import Ajax from '~/droplab/plugins/ajax';
import Ajax from '~/filtered_search/droplab/plugins/ajax';
import AjaxCache from '~/lib/utils/ajax_cache';
describe('Ajax', () => {
......
import InputSetter from '~/droplab/plugins/input_setter';
import InputSetter from '~/filtered_search/droplab/plugins/input_setter';
describe('InputSetter', () => {
let testContext;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment