From d1c9a251298c4d1afb8a296a2b44c8e3ee489909 Mon Sep 17 00:00:00 2001 From: Eduard Kuzmenko Date: Fri, 18 Dec 2020 18:43:17 +0200 Subject: [PATCH] Refactor legacy input fields Added missed length restrictions on input fields --- src/components/inputField.ts | 4 ++ src/components/sidebarLeft/tabs/editFolder.ts | 40 +++++++---- src/components/sidebarLeft/tabs/newChannel.ts | 57 +++++++++++---- src/components/sidebarLeft/tabs/newGroup.ts | 30 +++++--- src/index.hbs | 36 ---------- src/lib/richtextprocessor.ts | 5 +- src/pages/pageSignUp.ts | 72 ++++++++++++------- src/scss/partials/_input.scss | 1 + src/scss/partials/_leftSidebar.scss | 1 + src/scss/style.scss | 2 +- 10 files changed, 146 insertions(+), 102 deletions(-) diff --git a/src/components/inputField.ts b/src/components/inputField.ts index c8c0000b..8a4d9207 100644 --- a/src/components/inputField.ts +++ b/src/components/inputField.ts @@ -54,6 +54,8 @@ class InputField { public container: HTMLElement; public input: HTMLElement; + //public onLengthChange: (length: number, isOverflow: boolean) => void; + constructor(private options: { placeholder?: string, label?: string, @@ -116,6 +118,8 @@ class InputField { const isError = diff < 0; input.classList.toggle('error', isError); + //this.onLengthChange && this.onLengthChange(inputLength, isError); + if(isError || diff <= showLengthOn) { labelEl.innerText = label + ` (${maxLength - inputLength})`; if(!showingLength) showingLength = true; diff --git a/src/components/sidebarLeft/tabs/editFolder.ts b/src/components/sidebarLeft/tabs/editFolder.ts index 0c93067e..2b229d33 100644 --- a/src/components/sidebarLeft/tabs/editFolder.ts +++ b/src/components/sidebarLeft/tabs/editFolder.ts @@ -9,6 +9,8 @@ import { SliderTab } from "../../slider"; import { toast } from "../../toast"; import appMessagesManager from "../../../lib/appManagers/appMessagesManager"; import { attachClickEvent } from "../../../helpers/dom"; +import InputField from "../../inputField"; +import RichTextProcessor from "../../../lib/richtextprocessor"; const MAX_FOLDER_NAME_LENGTH = 12; @@ -22,7 +24,8 @@ export default class AppEditFolderTab implements SliderTab { private confirmBtn: HTMLElement; private menuBtn: HTMLElement; private deleteFolderBtn: HTMLElement; - private nameInput: HTMLInputElement; + private nameInput: HTMLElement; + private nameInputField: InputField; private include_peers: HTMLElement; private exclude_peers: HTMLElement; @@ -44,7 +47,19 @@ export default class AppEditFolderTab implements SliderTab { this.confirmBtn = this.container.querySelector('.btn-confirm'); this.menuBtn = this.container.querySelector('.btn-menu-toggle'); this.deleteFolderBtn = this.menuBtn.querySelector('.menu-delete'); - this.nameInput = this.container.querySelector('#folder-name'); + + const inputWrapper = document.createElement('div'); + inputWrapper.classList.add('input-wrapper'); + + this.nameInputField = new InputField({ + label: 'Folder Name', + maxLength: MAX_FOLDER_NAME_LENGTH + }); + this.nameInput = this.nameInputField.input; + + inputWrapper.append(this.nameInputField.container); + + this.caption.parentElement.insertBefore(inputWrapper, this.caption.nextSibling); this.include_peers = this.container.querySelector('.folder-list-included'); this.exclude_peers = this.container.querySelector('.folder-list-excluded'); @@ -84,8 +99,12 @@ export default class AppEditFolderTab implements SliderTab { }); this.confirmBtn.addEventListener('click', () => { - if(!this.nameInput.value.trim()) { - this.nameInput.classList.add('error'); + if(this.nameInputField.input.classList.contains('error')) { + return; + } + + if(!this.nameInputField.value.trim()) { + this.nameInputField.input.classList.add('error'); return; } @@ -122,14 +141,7 @@ export default class AppEditFolderTab implements SliderTab { }); this.nameInput.addEventListener('input', () => { - if(this.nameInput.value.length > MAX_FOLDER_NAME_LENGTH) { - this.nameInput.value = this.nameInput.value.slice(0, MAX_FOLDER_NAME_LENGTH); - return; - } - - this.filter.title = this.nameInput.value; - this.nameInput.classList.remove('error'); - + this.filter.title = this.nameInputField.value; this.editCheckForChange(); }); } @@ -154,7 +166,7 @@ export default class AppEditFolderTab implements SliderTab { this.title.innerText = 'New Folder'; this.menuBtn.classList.add('hide'); this.confirmBtn.classList.remove('hide'); - this.nameInput.value = ''; + this.nameInputField.value = ''; for(const flag in this.flags) { // @ts-ignore @@ -172,7 +184,7 @@ export default class AppEditFolderTab implements SliderTab { } const filter = this.filter; - this.nameInput.value = filter.title; + this.nameInputField.value = RichTextProcessor.wrapEmojiText(filter.title); for(const flag in this.flags) { // @ts-ignore diff --git a/src/components/sidebarLeft/tabs/newChannel.ts b/src/components/sidebarLeft/tabs/newChannel.ts index 1c4b1f17..0c2e71ae 100644 --- a/src/components/sidebarLeft/tabs/newChannel.ts +++ b/src/components/sidebarLeft/tabs/newChannel.ts @@ -1,37 +1,64 @@ import appSidebarLeft, { AppSidebarLeft } from ".."; import { InputFile } from "../../../layer"; import appChatsManager from "../../../lib/appManagers/appChatsManager"; +import Button from "../../button"; +import InputField from "../../inputField"; import PopupAvatar from "../../popups/avatar"; import { SliderTab } from "../../slider"; export default class AppNewChannelTab implements SliderTab { private container = document.querySelector('.new-channel-container') as HTMLDivElement; private canvas = this.container.querySelector('.avatar-edit-canvas') as HTMLCanvasElement; - private channelNameInput = this.container.querySelector('.new-channel-name') as HTMLInputElement; - private channelDescriptionInput = this.container.querySelector('.new-channel-description') as HTMLInputElement; - private nextBtn = this.container.querySelector('.btn-corner') as HTMLButtonElement; - private backBtn = this.container.querySelector('.sidebar-close-button') as HTMLButtonElement; private uploadAvatar: () => Promise = null; + private channelNameInputField: InputField; + private channelDescriptionInputField: InputField; + private nextBtn: HTMLButtonElement; + constructor() { + const content = this.container.querySelector('.sidebar-content'); + this.container.querySelector('.avatar-edit').addEventListener('click', () => { new PopupAvatar().open(this.canvas, (_upload) => { this.uploadAvatar = _upload; }); }); - this.channelNameInput.addEventListener('input', () => { - let value = this.channelNameInput.value; - if(value.length) { - this.nextBtn.classList.add('is-visible'); - } else { - this.nextBtn.classList.remove('is-visible'); - } + const inputWrapper = document.createElement('div'); + inputWrapper.classList.add('input-wrapper'); + + this.channelNameInputField = new InputField({ + label: 'Channel Name', + maxLength: 128 + }); + + this.channelDescriptionInputField = new InputField({ + label: 'Description (optional)', + maxLength: 255 }); + inputWrapper.append(this.channelNameInputField.container, this.channelDescriptionInputField.container); + + const onLengthChange = () => { + this.nextBtn.classList.toggle('is-visible', !!this.channelNameInputField.value.length && + !this.channelNameInputField.input.classList.contains('error') && + !this.channelDescriptionInputField.input.classList.contains('error')); + }; + + this.channelNameInputField.input.addEventListener('input', onLengthChange); + this.channelDescriptionInputField.input.addEventListener('input', onLengthChange); + + const caption = document.createElement('div'); + caption.classList.add('caption'); + caption.innerText = 'You can provide an optional description for your channel.'; + + this.nextBtn = Button('btn-corner btn-circle', {icon: 'next'}); + + content.append(inputWrapper, caption, this.nextBtn); + this.nextBtn.addEventListener('click', () => { - let title = this.channelNameInput.value; - let about = this.channelDescriptionInput.value; + const title = this.channelNameInputField.value; + const about = this.channelDescriptionInputField.value; this.nextBtn.disabled = true; appChatsManager.createChannel(title, about).then((channelId) => { @@ -52,8 +79,8 @@ export default class AppNewChannelTab implements SliderTab { ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); this.uploadAvatar = null; - this.channelNameInput.value = ''; - this.channelDescriptionInput.value = ''; + this.channelNameInputField.value = ''; + this.channelDescriptionInputField.value = ''; this.nextBtn.disabled = false; } } \ No newline at end of file diff --git a/src/components/sidebarLeft/tabs/newGroup.ts b/src/components/sidebarLeft/tabs/newGroup.ts index 7ae2502f..9941991e 100644 --- a/src/components/sidebarLeft/tabs/newGroup.ts +++ b/src/components/sidebarLeft/tabs/newGroup.ts @@ -4,6 +4,8 @@ import appChatsManager from "../../../lib/appManagers/appChatsManager"; import appDialogsManager from "../../../lib/appManagers/appDialogsManager"; import appUsersManager from "../../../lib/appManagers/appUsersManager"; import { SearchGroup } from "../../appSearch"; +import Button from "../../button"; +import InputField from "../../inputField"; import PopupAvatar from "../../popups/avatar"; import Scrollable from "../../scrollable"; import { SliderTab } from "../../slider"; @@ -12,11 +14,11 @@ export default class AppNewGroupTab implements SliderTab { private container = document.querySelector('.new-group-container') as HTMLDivElement; private contentDiv = this.container.querySelector('.sidebar-content') as HTMLDivElement; private canvas = this.container.querySelector('.avatar-edit-canvas') as HTMLCanvasElement; - private groupNameInput = this.container.querySelector('.new-group-name') as HTMLInputElement; - private nextBtn = this.container.querySelector('.btn-corner') as HTMLButtonElement; private searchGroup = new SearchGroup(' ', 'contacts', true, 'new-group-members disable-hover', false); private uploadAvatar: () => Promise = null; private userIds: number[]; + private nextBtn: HTMLButtonElement; + private groupNameInputField: InputField; constructor() { this.container.querySelector('.avatar-edit').addEventListener('click', () => { @@ -25,13 +27,25 @@ export default class AppNewGroupTab implements SliderTab { }); }); - this.groupNameInput.addEventListener('input', () => { - const value = this.groupNameInput.value; - this.nextBtn.classList.toggle('is-visible', !!value.length); + const inputWrapper = document.createElement('div'); + inputWrapper.classList.add('input-wrapper'); + + this.groupNameInputField = new InputField({ + label: 'Group Name', + maxLength: 128 }); + inputWrapper.append(this.groupNameInputField.container); + + this.groupNameInputField.input.addEventListener('input', () => { + const value = this.groupNameInputField.value; + this.nextBtn.classList.toggle('is-visible', !!value.length && !this.groupNameInputField.input.classList.contains('error')); + }); + + this.nextBtn = Button('btn-corner btn-circle', {icon: 'next'}); + this.nextBtn.addEventListener('click', () => { - const title = this.groupNameInput.value; + const title = this.groupNameInputField.value; this.nextBtn.disabled = true; appChatsManager.createChat(title, this.userIds).then((chatId) => { @@ -51,7 +65,7 @@ export default class AppNewGroupTab implements SliderTab { const scrollable = new Scrollable(chatsContainer); - this.contentDiv.append(chatsContainer); + this.contentDiv.append(inputWrapper, chatsContainer, this.nextBtn); } public onClose() { @@ -65,7 +79,7 @@ export default class AppNewGroupTab implements SliderTab { ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); this.uploadAvatar = null; - this.groupNameInput.value = ''; + this.groupNameInputField.value = ''; this.nextBtn.disabled = false; this.searchGroup.clear(); } diff --git a/src/index.hbs b/src/index.hbs index 21e94a06..4068345b 100644 --- a/src/index.hbs +++ b/src/index.hbs @@ -109,17 +109,6 @@

Your Name

Enter your name and add
a profile picture

-
-
- - -
-
- - -
- -
@@ -208,18 +197,6 @@ -
-
- - -
-
- - -
-
-
You can provide an optional description for your channel.
- -
-
- - -
-
-