Skip to content

Commit 44e1e5e

Browse files
committed
added complete functionality to class and id inputs
1 parent c8217f2 commit 44e1e5e

File tree

7 files changed

+151
-58
lines changed

7 files changed

+151
-58
lines changed

src/lib/Modules/helperFunctions.ts

+8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ export function calculateRect(element: HTMLElement, selector: HTMLDivElement) {
77
selector.style.left = rect.left + 'px';
88
}
99

10+
// handle the ghost position + visibility on document as well as the iFrame
11+
export function ghostImageHandler(top: number, left: number, display?: 'block' | 'none') {
12+
const ghost_img = <HTMLDivElement>document.getElementById('ghost_img');
13+
if (display) ghost_img.style.display = display;
14+
ghost_img.style.top = top + 'px';
15+
ghost_img.style.left = left + 'px';
16+
}
17+
1018
// for generating random string
1119
export function random(length: number, numbers: boolean = false, special_char: boolean = false) {
1220
let charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+52-10
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,52 @@
11
<script lang="ts">
22
import Dropdown from '../UI/Dropdown.svelte';
33
import ButtonGroup from '../UI/ButtonGroup.svelte';
4-
import InputBar from '$lib/UI/InputBar.svelte';
5-
import TagInputBar from '$lib/UI/TagInputBar.svelte';
4+
import InputBar from '../UI/InputBar.svelte';
5+
import TagInputBar, { tagifyInstance, tagifyInput } from '../UI/TagInputBar.svelte';
6+
import { clickedElement } from '../../Stores';
67
7-
// show/hide class & ID input on button click
8-
function toggleClassId(e: Event) {
8+
// update the state of each input on clicks
9+
$: {
10+
if ($clickedElement) {
11+
// for class Input
12+
if (tagifyInstance) {
13+
let clickedElementClassArray = Array.from($clickedElement.classList);
14+
15+
tagifyInstance.removeAllTags();
16+
tagifyInstance.addTags(clickedElementClassArray);
17+
18+
// if all the tags have been removed & there's no class to add, then set a placeholder
19+
if (tagifyInstance.getCleanValue().length === 0) {
20+
tagifyInput.setAttribute('data-placeholder', 'Add a new class');
21+
}
22+
}
23+
24+
// for ID input
25+
let idInput = <HTMLInputElement>document.getElementById('id-input');
26+
if (idInput) idInput.value = $clickedElement.id;
27+
}
28+
}
29+
30+
function addClass(e: any) {
31+
if ($clickedElement) $clickedElement.classList.add(e.detail.tagValue);
32+
}
33+
34+
function removeClass(e: any) {
35+
if ($clickedElement) $clickedElement.classList.remove(e.detail.tagValue);
36+
}
37+
38+
function addId() {
39+
const idInput = <HTMLInputElement>document.getElementById('id-input');
40+
if ($clickedElement) $clickedElement.id = idInput.value;
41+
}
42+
43+
function toggleClassIdButtonGroup(e: Event) {
944
let clickedBtn = e.target as HTMLButtonElement;
10-
let classInput = <HTMLInputElement>document.querySelector('#class-input');
11-
let idInput = <HTMLInputElement>document.querySelector('.id-input');
1245
13-
classInput.classList.toggle('hidden', clickedBtn.id === 'selector-id-btn');
46+
let tagifyClassInput = <HTMLInputElement>document.getElementById('class-input');
47+
let idInput = <HTMLInputElement>document.getElementById('id-input');
48+
49+
tagifyClassInput.classList.toggle('hidden', clickedBtn.id === 'selector-id-btn');
1450
idInput.classList.toggle('hidden', clickedBtn.id === 'selector-class-btn');
1551
}
1652
</script>
@@ -20,7 +56,7 @@
2056
<ButtonGroup
2157
ItemsArray={['Class', 'ID']}
2258
IdArray={['selector-class-btn', 'selector-id-btn']}
23-
customFunction={toggleClassId}
59+
customFunction={toggleClassIdButtonGroup}
2460
/>
2561

2662
<Dropdown
@@ -29,6 +65,12 @@
2965
/>
3066
</div>
3167

32-
<TagInputBar placeholder={'Add a new class'} id={'class-input'} />
33-
<InputBar placeholder={'Add a new id'} Class={'id-input hidden'} />
68+
<TagInputBar
69+
on:add={addClass}
70+
on:remove={removeClass}
71+
placeholder={'Add a new class'}
72+
id={'class-input'}
73+
/>
74+
75+
<InputBar customFunction={addId} id={'id-input'} placeholder={'Add an ID'} Class={'hidden'} />
3476
</div>

src/lib/UI/Dropdown.svelte

+1-3
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@
3030
document.body.addEventListener('click', dropdownClose);
3131
}}
3232
on:keydown|stopPropagation={(e) => {
33-
if (e.key === 'Escape') {
34-
dropdownOpen = false;
35-
}
33+
if (e.key === 'Escape') dropdownOpen = false;
3634
}}
3735
>
3836
{DropdownBtnText}

src/lib/UI/InputBar.svelte

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
export let Class: string = '';
44
export let show: boolean = true;
55
export let placeholder: string = 'placeholder';
6+
export let customFunction: ((...args: any[]) => any) | null = null;
67
</script>
78

89
<input
@@ -13,4 +14,8 @@
1314
: 'hidden'}
1415
{placeholder}
1516
spellcheck="false"
17+
on:blur={customFunction}
18+
on:keydown|stopPropagation={(e) => {
19+
if (customFunction && e.key === 'Enter') customFunction();
20+
}}
1621
/>

src/lib/UI/TagInputBar.svelte

+42-12
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,65 @@
1+
<script lang="ts" context="module">
2+
export let tagifyInstance: any;
3+
export let tagifyInput: HTMLElement;
4+
</script>
5+
16
<script lang="ts">
7+
import { onMount } from 'svelte';
8+
import { createEventDispatcher } from 'svelte';
9+
import { random } from '$lib/Modules/helperFunctions';
210
import Tagify from '@yaireo/tagify';
311
import '@yaireo/tagify/dist/tagify.css';
4-
import { random } from '$lib/Modules/helperFunctions';
5-
import { onMount } from 'svelte';
612
713
export let id: string;
814
export let placeholder: string = 'placeholder';
915
1016
let input: HTMLInputElement;
1117
let className: string = random(12);
1218
19+
const dispatch = createEventDispatcher();
20+
21+
function customAddFunction(tagValue: string) {
22+
dispatch('add', {
23+
tagValue
24+
});
25+
}
26+
27+
function customRemoveFunction(tagValue: string) {
28+
dispatch('remove', {
29+
tagValue
30+
});
31+
}
32+
1333
onMount(() => {
14-
let tagify = new Tagify(input);
34+
tagifyInstance = new Tagify(input);
1535
16-
let tagifyInstance = <HTMLElement>document.querySelector(`.tagify.${className}`);
17-
tagifyInstance.setAttribute('id', id);
36+
let tagifyInputBar = <HTMLElement>document.querySelector(`.tagify.${className}`);
37+
tagifyInputBar.id = id;
1838
19-
let tagifiedInput = <HTMLElement>document.querySelector(`.tagify.${className} .tagify__input`);
39+
tagifyInput = <HTMLElement>document.querySelector(`.tagify.${className} .tagify__input`);
2040
21-
tagify.on('add', (e) => {
22-
tagifiedInput.removeAttribute('data-placeholder');
41+
tagifyInstance.on('add', (e: any) => {
42+
tagifyInput.setAttribute('data-placeholder', ' ');
43+
// run custom function if any
44+
const tagValue = e.detail.data!.value;
45+
customAddFunction(tagValue);
2346
});
2447
25-
tagify.on('remove', () => {
26-
if (tagify.getCleanValue().length === 1) {
27-
tagifiedInput.setAttribute('data-placeholder', 'Add a class');
48+
tagifyInstance.on('remove', (e: any) => {
49+
if (tagifyInstance.getCleanValue().length <= 1) {
50+
tagifyInput.setAttribute('data-placeholder', 'Add a class');
2851
}
52+
// run custom function if any
53+
const tagValue = e.detail.data!.value;
54+
customRemoveFunction(tagValue);
2955
});
3056
});
3157
</script>
3258

3359
<input
3460
bind:this={input}
3561
class={className +
36-
' w-full text-[11px] bg-[#404040] font-sans font-semibold placeholder-[#b8b6b6a1] text-[#b8b6b6] border-[2px] border-[#505050] rounded-[5px] px-[10px] py-[7px] outline-none'}
62+
' w-full text-[11px] bg-[#404040] font-sans font-semibold placeholder-[#b8b6b6a1] text-[#b8b6b6] border-[2px] border-[#505050] rounded-[5px] outline-none'}
3763
{placeholder}
3864
spellcheck="false"
3965
/>
@@ -82,4 +108,8 @@
82108
:global(.tagify__tag > div > [contenteditable]) {
83109
text-overflow: clip;
84110
}
111+
112+
:global(.tagify__input::before) {
113+
white-space: pre;
114+
}
85115
</style>

src/routes/MainFrame.svelte

+34-30
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,16 @@
11
<script lang="ts">
22
import { onMount } from 'svelte';
33
import { clickedElement, showPanel } from '../Stores';
4-
import { calculateRect } from '../lib/Modules/helperFunctions';
5-
import { elements } from './Panel.svelte';
4+
import { calculateRect, ghostImageHandler } from '../lib/Modules/helperFunctions';
5+
import { PanelElements } from './Panel.svelte';
66
7-
// type for insertAdjacentHTML on the drop() event
7+
// types for insertAdjacentHTML on the drop() event
88
type InsertPosition = 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend';
99
let position: InsertPosition;
1010
1111
let hoveredElement: HTMLElement;
1212
let draggedElement: HTMLElement | null = null;
1313
14-
// handle the ghost position + visibility
15-
function ghostImageHandler(top: number, left: number, display?: 'block' | 'none') {
16-
const ghost_img = <HTMLDivElement>document.getElementById('ghost_img');
17-
if (display) {
18-
ghost_img.style.display = display;
19-
}
20-
ghost_img.style.top = top + 'px';
21-
ghost_img.style.left = left + 'px';
22-
}
23-
2414
onMount(() => {
2515
const iFrame = <HTMLIFrameElement>document.getElementById('frame');
2616
const ghost_img = <HTMLDivElement>document.getElementById('ghost_img');
@@ -40,31 +30,39 @@
4030
ghost_img.innerText = ghostText;
4131
ghost_img.style.display = 'block';
4232
43-
htmlCode = elements[ghostText].code;
33+
htmlCode = PanelElements[ghostText].code;
4434
});
4535
4636
document.addEventListener('dragover', (e) => {
4737
e.preventDefault();
38+
4839
ghost_img.style.top = e.clientY + 15 + 'px';
4940
ghost_img.style.left = e.clientX + 25 + 'px';
41+
5042
indicator.style.display = 'none';
5143
});
5244
5345
document.addEventListener('drop', (e) => {
5446
e.preventDefault();
47+
5548
ghostImageHandler(60, 75, 'none');
49+
5650
indicator.style.display = 'none';
51+
5752
draggedElement = null;
5853
});
5954
6055
document.addEventListener('dragend', (e) => {
6156
e.preventDefault();
57+
6258
ghostImageHandler(60, 75, 'none');
59+
6360
indicator.style.display = 'none';
61+
6462
draggedElement = null;
6563
});
6664
67-
// make the iframe reload
65+
// make the iframe reload for changes
6866
iFrame.src = 'userFiles/index.html';
6967
7068
iFrame.addEventListener('load', () => {
@@ -74,43 +72,46 @@
7472
e.preventDefault();
7573
e.stopPropagation();
7674
77-
// hide NotSelected panel on click
75+
// hide NotSelected.svelte
7876
let NotSelected = <HTMLDivElement>document.getElementById('not_selected');
7977
NotSelected.style.visibility = 'hidden';
8078
81-
// hide elements panel on click
79+
// hide Panel.svelte
8280
showPanel.update(() => false);
8381
8482
clickedElement.update(() => e.target as HTMLElement);
8583
86-
calculateRect($clickedElement, click_selector);
84+
calculateRect(e.target as HTMLElement, click_selector);
85+
8786
click_selector.style.display = 'block';
8887
});
8988
9089
iFrameDoc.addEventListener('mouseover', (e) => {
9190
hoveredElement = e.target as HTMLElement;
92-
if (hoveredElement.tagName !== 'BODY') {
93-
hoveredElement.draggable = true;
94-
}
91+
if (hoveredElement.tagName !== 'BODY') hoveredElement.draggable = true;
9592
9693
calculateRect(hoveredElement, hover_selector);
94+
9795
hover_selector.style.display = 'block';
9896
});
9997
10098
iFrameDoc.addEventListener('mouseout', (e) => {
101-
let elem = e.target as HTMLElement;
102-
elem.removeAttribute('draggable');
99+
const mouseoutElem = e.target as HTMLElement;
100+
mouseoutElem.removeAttribute('draggable');
101+
103102
hover_selector.style.display = 'none';
104103
});
105104
106105
iFrameDoc.addEventListener('dragstart', (e) => {
107106
e.stopPropagation();
107+
108108
const blank = iFrameDoc.createElement('div');
109109
e.dataTransfer!.setDragImage(blank, 0, 0);
110110
111111
draggedElement = e.target as HTMLElement;
112-
htmlCode = draggedElement!.outerHTML;
113-
ghost_img.style.visibility = 'hidden';
112+
htmlCode = draggedElement.outerHTML;
113+
114+
ghost_img.style.display = 'none';
114115
});
115116
116117
iFrameDoc.addEventListener('dragover', (e) => {
@@ -134,18 +135,21 @@
134135
indicator.style.display = 'none';
135136
indicator.style.borderTop = '';
136137
indicator.style.borderBottom = '';
138+
137139
position = 'beforeend';
138140
} else {
139141
// insert above the the element
140142
if (Math.abs((e as MouseEvent).pageY - rect.top) <= rect.height / 2) {
141143
indicator.style.borderTop = '3px solid #007bfb';
142144
indicator.style.borderBottom = '';
145+
143146
position = 'beforebegin';
144147
}
145148
// insert below the element
146149
else {
147150
indicator.style.borderTop = '';
148151
indicator.style.borderBottom = '3px solid #007bfb';
152+
149153
position = 'afterend';
150154
}
151155
}
@@ -168,24 +172,24 @@
168172
}
169173
170174
indicator.style.display = 'none';
175+
171176
draggedElement = null;
172177
});
173178
174179
iFrameDoc.addEventListener('dragend', (e) => {
175180
e.stopPropagation();
181+
176182
indicator.style.display = 'none';
177183
});
178184
179185
// recalculate selector styles on scroll for smooth experience
180-
iFrameDoc.addEventListener('scroll', (e) => {
181-
if ($clickedElement) {
182-
calculateRect($clickedElement, click_selector);
183-
}
186+
iFrameDoc.addEventListener('scroll', () => {
187+
if ($clickedElement) calculateRect($clickedElement, click_selector);
184188
calculateRect(hoveredElement, hover_selector);
185189
});
186190
});
187191
188-
window.addEventListener('resize', (e) => {
192+
window.addEventListener('resize', () => {
189193
// updating selector styles on resize
190194
if ($clickedElement) {
191195
calculateRect($clickedElement, click_selector);

0 commit comments

Comments
 (0)