Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 20.03.2019, 21:52
Новичок на форуме
Отправить личное сообщение для gunner17 Посмотреть профиль Найти все сообщения от gunner17
 
Регистрация: 06.03.2019
Сообщений: 9

Как сделать поле ввода тегов\меток на чистом js
Нужно сделать поле ввода тегов на чистом js без библиотек как в данном примере https://ruseller.com/lessons.php?id=992&rub=32 При вводе запятой или нажатии клавиши Enter весь введённый текст должен превратиться в тег. После можно продолжить вводить следующий тег и т.д. По клику на тег, он должен удалиться из текстового поля. Поле для тегов должно создаваться программно следующим образом:



let tagField = createTagsField();
document.body.append(tagField.element);
Ответить с цитированием
  #2 (permalink)  
Старый 21.03.2019, 08:32
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Сообщение от gunner17
При вводе запятой или нажатии клавиши Enter весь введённый текст должен превратиться в тег.
Смотрите пример ниже.

Сообщение от gunner17
По клику на тег, он должен удалиться из текстового поля.
Сделал, чтобы удалялся при долгом нажатии на экран или вызове контекстного меню вторичной кнопкой мыши, поскольку очень легко удаляется при обычном нажатии.

Также можно перемещаться между тегами при помощи стрелок и теги удаляются, как обычный текст, при помощи клавиш BackSpace и Delete.

<body><script>

class TagsField extends HTMLElement {
	constructor() {
		super();
		this.attachShadow({ mode: "open" });
		this.shadowRoot.innerHTML = `
			<style>
				span {
					background-color: #4CAF50;
					color: white;
					text-shadow: 0 1px rgba(0, 0, 0, 0.5);
					box-shadow: 0 0.1em 0.1em rgba(0, 0, 0, 0.2);
					border-radius: 1em;
					padding: 0.45em 0.8em;
					margin: 0.1em;
					display: inline-block;
				}

				label {
					border: 1px solid #ccc;
					border-radius: .5em;
					padding: .5em;
					display: inline-flex;
					font: bolder 100% sans-serif;
					flex-wrap: wrap;
					position: relative;
				}

				label::before {
					content: "Input tags";
					position: absolute;
					pointer-events: none;
					line-height: 0;
					top: 0;
					text-shadow: 2px 0 white, -2px 0 white;
				}

				input {
					all: unset;
					min-width: 5em;
					width: 0;
					padding: 0.45em 0.8em;
					margin: 0.1em;
				}
			</style>
			<label>
				<input>
			</label>
		`;
		this.input = this.shadowRoot.querySelector("input");
		this.label = this.shadowRoot.querySelector("label");
		this.input.value = "\u200b\u200b";

		this.inputHandler = this.inputHandler.bind(this);
		this.contextMenuHandler = this.contextMenuHandler.bind(this);

		"input focus keydown keyup touchstart touchmove click".split(" ").forEach(type => {
			this.input.addEventListener(type, this.inputHandler);
		});
		
		this.label.addEventListener("contextmenu", this.contextMenuHandler);
	}

	inputHandler(event) {		
		if(event.type !== "focus" && event.type !== "click") {
			if(
				this.input.selectionStart === 0 &&
				this.input.selectionEnd === 0
			) {

				if(this.input.previousElementSibling) {
					if(this.input.value.length === 1 || !this.input.value.startsWith("\u200b"))
						this.label.removeChild(this.input.previousElementSibling);
					else
						this.label.insertBefore(
							this.input.previousElementSibling,
							this.input.nextElementSibling
						);
				}
			}

			if(
				this.input.selectionStart === this.input.value.length &&
				this.input.selectionEnd === this.input.value.length
			) {
				if(this.input.nextElementSibling) {
					if(this.input.value.length === 1 || !this.input.value.endsWith("\u200b"))
						this.label.removeChild(this.input.nextElementSibling);
					else
						this.label.insertBefore(
							this.input.nextElementSibling,
							this.input
						);
				}
			}
		}

		var rawTags = this.input.value.slice(1, -1);

		if(event.type === "keyup" && event.key === "Enter") {
			rawTags += ",";
		}

		const tags = rawTags.split(",");
		const editableTag = tags.pop();

		tags.filter(tag => tag).map(this.constructor.createTag).forEach(tag => {
			this.label.insertBefore(tag, this.input);
		});

		this.input.value = `\u200b${editableTag}\u200b`;
		this.input.style.width = "0";
		this.input.style.width = this.input.scrollWidth + "px";
		this.input.selectionStart = Math.max(1, Math.min(this.input.selectionStart, this.input.value.length - 1));
		this.input.selectionEnd = Math.max(1, Math.min(this.input.selectionEnd, this.input.value.length - 1));
	}
	
	contextMenuHandler(event) {
		if(event.target.nodeName === "SPAN") {
			if(confirm("Remove tag?")) {
				event.preventDefault();
				this.label.removeChild(event.target);
			}
		}
	}

	static createTag(tag) {
		const element = document.createElement("span");
		element.textContent = tag;
		return element;
	}

	get tags() {
		return Array.from(this.label.querySelectorAll("span")).map(element => element.textContent);
	}
}

customElements.define("tags-field", TagsField);

// Поле для тегов создаётся программно следующим образом:
let tagField = document.createElement("tags-field");
document.body.append(tagField);

</script>

Последний раз редактировалось Malleys, 23.03.2019 в 01:25.
Ответить с цитированием
  #3 (permalink)  
Старый 21.03.2019, 09:01
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,126

Malleys,
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как сделать такую страницу mortido Элементы интерфейса 11 02.10.2014 07:20
jqGrid - как сделать поле редактируемым? demoniqus Библиотеки/Тулкиты/Фреймворки 0 30.08.2012 13:38
Как сделать как в JQ? faforty Общие вопросы Javascript 8 14.11.2011 01:35
Как сделать поле активным при клике на элемент dimaan777 Javascript под браузер 1 24.07.2011 21:16
Вставка блока php в js...Как сделать? reup Общие вопросы Javascript 2 30.07.2009 11:02