client/tag-input: extract HTML template
This commit is contained in:
parent
5bcf44aa2d
commit
d0c0652720
2 changed files with 48 additions and 44 deletions
18
client/html/tag_input.tpl
Normal file
18
client/html/tag_input.tpl
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<div class='tag-input'>
|
||||||
|
<input type='text' placeholder='type to add…'/>
|
||||||
|
|
||||||
|
<div class='tag-suggestions'>
|
||||||
|
<div class='wrapper'>
|
||||||
|
<p>
|
||||||
|
<span class='buttons'>
|
||||||
|
<a class='opacity'><i class='fa fa-eye'></i></a>
|
||||||
|
<a class='close'>×</a>
|
||||||
|
</span>
|
||||||
|
Suggested tags
|
||||||
|
</p>
|
||||||
|
<ul></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class='compact-tags'></ul>
|
||||||
|
</div>
|
|
@ -17,6 +17,8 @@ const SOURCE_USER_INPUT = 'user-input';
|
||||||
const SOURCE_SUGGESTION = 'suggestions';
|
const SOURCE_SUGGESTION = 'suggestions';
|
||||||
const SOURCE_CLIPBOARD = 'clipboard';
|
const SOURCE_CLIPBOARD = 'clipboard';
|
||||||
|
|
||||||
|
const template = views.getTemplate('tag-input');
|
||||||
|
|
||||||
function _fadeOutListItemNodeStatus(listItemNode) {
|
function _fadeOutListItemNodeStatus(listItemNode) {
|
||||||
if (listItemNode.classList.length) {
|
if (listItemNode.classList.length) {
|
||||||
if (listItemNode.fadeTimeout) {
|
if (listItemNode.fadeTimeout) {
|
||||||
|
@ -77,22 +79,19 @@ class SuggestionList {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TagInputControl extends events.EventTarget {
|
class TagInputControl extends events.EventTarget {
|
||||||
constructor(sourceInputNode) {
|
constructor(hostNode) {
|
||||||
super();
|
super();
|
||||||
this.tags = [];
|
this.tags = [];
|
||||||
|
this._hostNode = hostNode;
|
||||||
this._suggestions = new SuggestionList();
|
this._suggestions = new SuggestionList();
|
||||||
|
|
||||||
this._sourceInputNode = sourceInputNode;
|
// dom
|
||||||
|
const editAreaNode = template();
|
||||||
|
this._editAreaNode = editAreaNode;
|
||||||
|
this._tagInputNode = editAreaNode.querySelector('input');
|
||||||
|
this._suggestionsNode = editAreaNode.querySelector('.tag-suggestions');
|
||||||
|
this._tagListNode = editAreaNode.querySelector('ul.compact-tags');
|
||||||
|
|
||||||
this._install();
|
|
||||||
}
|
|
||||||
|
|
||||||
_install() {
|
|
||||||
this._editAreaNode = document.createElement('div');
|
|
||||||
this._editAreaNode.classList.add('tag-input');
|
|
||||||
|
|
||||||
this._tagInputNode = views.htmlToDom(
|
|
||||||
'<input type="text" placeholder="type to add…"/>');
|
|
||||||
this._autoCompleteControl = new TagAutoCompleteControl(
|
this._autoCompleteControl = new TagAutoCompleteControl(
|
||||||
this._tagInputNode, {
|
this._tagInputNode, {
|
||||||
getTextToFind: () => {
|
getTextToFind: () => {
|
||||||
|
@ -109,51 +108,28 @@ class TagInputControl extends events.EventTarget {
|
||||||
verticalShift: -2,
|
verticalShift: -2,
|
||||||
isTaggedWith: tagName => this.isTaggedWith(tagName),
|
isTaggedWith: tagName => this.isTaggedWith(tagName),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// dom events
|
||||||
this._tagInputNode.addEventListener(
|
this._tagInputNode.addEventListener(
|
||||||
'keydown', e => this._evtInputKeyDown(e));
|
'keydown', e => this._evtInputKeyDown(e));
|
||||||
this._tagInputNode.addEventListener(
|
this._tagInputNode.addEventListener(
|
||||||
'paste', e => this._evtInputPaste(e));
|
'paste', e => this._evtInputPaste(e));
|
||||||
this._editAreaNode.appendChild(this._tagInputNode);
|
|
||||||
|
|
||||||
this._suggestionsNode = views.htmlToDom(
|
|
||||||
'<div class="tag-suggestions">' +
|
|
||||||
'<div class="wrapper">' +
|
|
||||||
'<p>' +
|
|
||||||
'<span class="buttons">' +
|
|
||||||
'<a class="opacity"><i class="fa fa-eye"></i></a>' +
|
|
||||||
'<a class="close">×</a>' +
|
|
||||||
'</span>' +
|
|
||||||
'Suggested tags' +
|
|
||||||
'</p>' +
|
|
||||||
'<ul></ul>' +
|
|
||||||
'</div>' +
|
|
||||||
'</div>');
|
|
||||||
this._editAreaNode.appendChild(this._suggestionsNode);
|
|
||||||
this._editAreaNode.querySelector('a.opacity').addEventListener(
|
this._editAreaNode.querySelector('a.opacity').addEventListener(
|
||||||
'click', e => {
|
'click', e => this._evtToggleSuggestionsPopupOpacityClick(e));
|
||||||
e.preventDefault();
|
|
||||||
this._toggleSuggestionsPopupOpacity();
|
|
||||||
});
|
|
||||||
this._editAreaNode.querySelector('a.close').addEventListener(
|
this._editAreaNode.querySelector('a.close').addEventListener(
|
||||||
'click', e => {
|
'click', e => this._evtCloseSuggestionsPopupClick(e));
|
||||||
e.preventDefault();
|
|
||||||
this._closeSuggestionsPopup();
|
|
||||||
});
|
|
||||||
|
|
||||||
this._tagListNode = views.htmlToDom('<ul class="compact-tags"></ul>');
|
|
||||||
this._editAreaNode.appendChild(this._tagListNode);
|
|
||||||
|
|
||||||
// show
|
// show
|
||||||
this._sourceInputNode.style.display = 'none';
|
this._hostNode.style.display = 'none';
|
||||||
this._sourceInputNode.parentNode.insertBefore(
|
this._hostNode.parentNode.insertBefore(
|
||||||
this._editAreaNode, this._sourceInputNode.nextSibling);
|
this._editAreaNode, hostNode.nextSibling);
|
||||||
|
|
||||||
this.addEventListener('change', e => this._evtTagsChanged(e));
|
this.addEventListener('change', e => this._evtTagsChanged(e));
|
||||||
this.addEventListener('add', e => this._evtTagAdded(e));
|
this.addEventListener('add', e => this._evtTagAdded(e));
|
||||||
this.addEventListener('remove', e => this._evtTagRemoved(e));
|
this.addEventListener('remove', e => this._evtTagRemoved(e));
|
||||||
|
|
||||||
// add existing tags
|
// add existing tags
|
||||||
this.addMultipleTags(this._sourceInputNode.value, SOURCE_INIT);
|
this.addMultipleTags(this._hostNode.value, SOURCE_INIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
isTaggedWith(tagName) {
|
isTaggedWith(tagName) {
|
||||||
|
@ -214,8 +190,8 @@ class TagInputControl extends events.EventTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
_evtTagsChanged(e) {
|
_evtTagsChanged(e) {
|
||||||
this._sourceInputNode.value = this.tags.join(' ');
|
this._hostNode.value = this.tags.join(' ');
|
||||||
this._sourceInputNode.dispatchEvent(new CustomEvent('change'));
|
this._hostNode.dispatchEvent(new CustomEvent('change'));
|
||||||
}
|
}
|
||||||
|
|
||||||
_evtTagAdded(e) {
|
_evtTagAdded(e) {
|
||||||
|
@ -267,6 +243,16 @@ class TagInputControl extends events.EventTarget {
|
||||||
this._tagInputNode.value = '';
|
this._tagInputNode.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_evtCloseSuggestionsPopupClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
this._closeSuggestionsPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
_evtToggleSuggestionsPopupOpacityClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
this._toggleSuggestionsPopupOpacity();
|
||||||
|
}
|
||||||
|
|
||||||
_evtInputKeyDown(e) {
|
_evtInputKeyDown(e) {
|
||||||
if (e.which == KEY_RETURN || e.which == KEY_SPACE) {
|
if (e.which == KEY_RETURN || e.which == KEY_SPACE) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
Loading…
Reference in a new issue