Skip to content

Commit e00062b

Browse files
committed
Finish basic drag and drop functionality of html elements
1 parent 7feb832 commit e00062b

File tree

8 files changed

+229
-33
lines changed

8 files changed

+229
-33
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@
4040
"prismjs": "^1.26.0",
4141
"quasar": "^2.5.5",
4242
"quasar-dotenv": "^1.0.5",
43-
"vue":"3.2.31",
44-
"vue-router": "4.0.13",
43+
"vue": "3.2.31",
4544
"vue-draggable-resizable": "^2.3.0",
4645
"vue-multiselect": "^3.0.0-alpha.2",
4746
"vue-prism-editor": "^2.0.0-alpha.2",
47+
"vue-router": "4.0.13",
4848
"vue3-tree": "^0.11.0",
4949
"vued3tree": "^5.1.0",
5050
"vuex": "^4.0.2"

src/components/composables/useCreateComponent.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ export function useCreateComponent(importObj) {
4141
state: [],
4242
parent: {},
4343
isActive: false,
44+
idDrag: '',
45+
idDrop: ''
4446
};
4547

4648
if (imported === true){

src/components/left-sidebar/ComponentTab/CreateMenuHTMLQueue.vue

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,28 @@ Description:
55
-->
66

77
<template>
8-
<section class="html-queue">
8+
<section class="html-queue" @dragover="dragOver($event), false">
99
<div
1010
group="people"
1111
class="list-group"
1212
>
1313
<div
14-
:class="activeHTML === element[2] ? 'list-group-item-selected' : 'list-group-item'"
15-
@dblclick.self="setActiveElement(element)"
1614
v-for="(element) in renderList" :key="element[1] + Date.now()"
15+
@dragenter="dragEnter($event, element[2])"
1716
>
18-
<i v-if='activeComponent === "" || exceptions.includes(element[0]) '></i>
19-
<i v-else class="fas fa fa-angle-double-down fa-md" @click="setLayer({text: element[0], id: element[2]})"></i>
20-
{{ element[0] }}
21-
<i class="fas fa fa-trash fa-md" @click.self="deleteElement([element[1],element[2]])"></i>
17+
<div
18+
:class="activeHTML === element[2] ? 'list-group-item-selected' : 'list-group-item'"
19+
@dblclick.self="setActiveElement(element)"
20+
@dragstart="startDrag($event, element[2])"
21+
@dragend="endDrag($event)"
22+
draggable="true"
23+
>
24+
<i v-if='activeComponent === "" || exceptions.includes(element[0]) '></i>
25+
<i v-else class="fas fa fa-angle-double-down fa-md" @click="setLayer({text: element[0], id: element[2]})"></i>
26+
{{ element[0] }}
27+
<i class="fas fa fa-trash fa-md" @click.self="deleteElement([element[1],element[2]])"></i>
28+
</div>
2229
</div>
23-
2430
</div>
2531
</section>
2632
</template>
@@ -78,7 +84,7 @@ export default {
7884
7985
},
8086
methods: {
81-
...mapActions(['setActiveHTML', 'setActiveLayer', 'upOneLayer']),
87+
...mapActions(['setActiveHTML', 'setActiveLayer', 'upOneLayer', 'setSelectedIdDrag', 'setIdDrag', 'setSelectedIdDrop', 'setIdDrop', 'dragDropSortHtmlElements', 'dragDropSortSelectedHtmlElements']),
8288
deleteElement (id) {
8389
if (this.activeComponent === '') this.$store.dispatch(deleteSelectedElement, id[0])
8490
else this.$store.dispatch(deleteFromComponentHtmlList, id[1])
@@ -95,7 +101,33 @@ export default {
95101
if (this.activeLayer.id !== '') {
96102
this.upOneLayer(this.activeLayer.id)
97103
}
98-
}
104+
},
105+
//METHODS FOR DRAG-AND-DROP
106+
startDrag (event, id) {
107+
//add a class of 'currentlyDragging' to the HTML element that you are currently dragging
108+
event.target.classList.add('currentlyDragging')
109+
const dragId = id;
110+
if (this.activeComponent === '') this.setSelectedIdDrag(dragId)
111+
else this.setIdDrag(dragId)
112+
},
113+
dragEnter (event, id) {
114+
event.preventDefault();
115+
const dropId = id;
116+
if (this.activeComponent === '') this.setSelectedIdDrop(dropId)
117+
else this.setIdDrop(dropId)
118+
},
119+
dragOver (event) {
120+
//needed stop the dragend animation so endDrag is invoked automatically
121+
event.preventDefault();
122+
},
123+
endDrag (event) {
124+
//remove the 'currentlyDragging' class after the HTML is dropped
125+
event.preventDefault();
126+
event.target.classList.remove('currentlyDragging')
127+
//invoke the action that will use the idDrag and idDrop to sort the HtmlList
128+
if (this.activeComponent === '') this.dragDropSortSelectedHtmlElements()
129+
else this.dragDropSortHtmlElements()
130+
},
99131
},
100132
watch: {
101133
activeComponent: function () {

src/components/right-sidebar/HTMLQueue.vue

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,42 @@ Description:
55
-->
66

77
<template>
8-
<section class="html-queue">
8+
<section class="html-queue" @dragover="dragOver($event), false">
99
<span class='list-title' v-if='this.activeLayer.id !== ""'>
1010
<i class="fas fa fa-chevron-up fa-md" @click="setParentLayer"></i>
1111
&nbsp; &nbsp; Viewing Elements in {{this.activeComponent}} '{{ depth }}'
12-
<hr>
12+
<hr>
1313
</span>
1414
<span class='list-title' v-else-if='!this.activeComponent'></span>
15-
<div
16-
group="people"
17-
class="list-group"
18-
>
19-
<p v-if='!this.componentMap[this.activeComponent]?.htmlList.length'>No HTML elements in component</p>
20-
<div
21-
:class="activeHTML === element[2] ? 'list-group-item-selected' : 'list-group-item'"
22-
@dblclick.self="setActiveElement(element)"
23-
v-for="(element) in renderList" :key="element[1] + Date.now()"
24-
>
25-
<i v-if='activeComponent === "" || exceptions.includes(element[0]) '></i>
26-
<i v-else class="fas fa fa-angle-double-down fa-md" @click="setLayer({text: element[0], id: element[2]})"></i>
27-
{{ element[0] }}
28-
<i class="fas fa fa-trash fa-md" @click.self="deleteElement([element[1],element[2]])"></i>
29-
</div>
3015

16+
<div group="people" class="list-group">
17+
18+
<p v-if='!this.componentMap[this.activeComponent]?.htmlList.length'>No HTML elements in component</p>
19+
<div
20+
v-for="(element) in renderList" :key="element[1] + Date.now()"
21+
@dragenter="dragEnter($event, element[2])"
22+
>
23+
<div
24+
:class="activeHTML === element[2] ? 'list-group-item-selected' : 'list-group-item'"
25+
@dblclick.self="setActiveElement(element)"
26+
@dragstart="startDrag($event, element[2])"
27+
@dragend="endDrag($event)"
28+
draggable="true"
29+
>
30+
<i v-if='activeComponent === "" || exceptions.includes(element[0]) '></i>
31+
<i v-else class="fas fa fa-angle-double-down fa-md" @click="setLayer({text: element[0], id: element[2]})"></i>
32+
{{ element[0] }}
33+
<i class="fas fa fa-trash fa-md" @click.self="deleteElement([element[1],element[2]])"></i>
34+
</div>
35+
</div>
3136
</div>
37+
3238
</section>
3339
</template>
3440

3541
<script>
3642
43+
import { keys } from 'localforage'
3744
import { mapState, mapActions } from 'vuex'
3845
import { setSelectedElementList, deleteSelectedElement, deleteFromComponentHtmlList } from '../../store/types'
3946
import { breadthFirstSearch } from '../../utils/search.util'
@@ -44,7 +51,7 @@ export default {
4451
name: {
4552
type: String
4653
},
47-
listToRender: {
54+
listToRender:{
4855
type: Array
4956
}
5057
},
@@ -85,7 +92,7 @@ export default {
8592
8693
},
8794
methods: {
88-
...mapActions(['setActiveHTML', 'setActiveLayer', 'upOneLayer']),
95+
...mapActions(['setActiveHTML', 'setActiveLayer', 'upOneLayer', 'setSelectedIdDrag', 'setIdDrag', 'setSelectedIdDrop', 'setIdDrop', 'dragDropSortHtmlElements', 'dragDropSortSelectedHtmlElements']),
8996
deleteElement (id) {
9097
if (this.activeComponent === '') this.$store.dispatch(deleteSelectedElement, id[0])
9198
else this.$store.dispatch(deleteFromComponentHtmlList, id[1])
@@ -102,7 +109,34 @@ export default {
102109
if (this.activeLayer.id !== '') {
103110
this.upOneLayer(this.activeLayer.id)
104111
}
105-
}
112+
},
113+
//METHODS FOR DRAG-AND-DROP
114+
startDrag (event, id) {
115+
//add a class of 'currentlyDragging' to the HTML element that you are currently dragging
116+
event.target.classList.add('currentlyDragging')
117+
const dragId = id;
118+
if (this.activeComponent === '') this.setSelectedIdDrag(dragId)
119+
else this.setIdDrag(dragId)
120+
},
121+
dragEnter (event, id) {
122+
event.preventDefault();
123+
const dropId = id;
124+
if (this.activeComponent === '') this.setSelectedIdDrop(dropId)
125+
else this.setIdDrop(dropId)
126+
},
127+
dragOver (event) {
128+
//needed stop the dragend animation so endDrag is invoked automatically
129+
event.preventDefault();
130+
},
131+
endDrag (event) {
132+
//remove the 'currentlyDragging' class after the HTML is dropped
133+
event.preventDefault();
134+
event.target.classList.remove('currentlyDragging')
135+
//invoke the action that will use the idDrag and idDrop to sort the HtmlList
136+
if (this.activeComponent === '') this.dragDropSortSelectedHtmlElements()
137+
else this.dragDropSortHtmlElements()
138+
},
139+
106140
},
107141
watch: {
108142
activeComponent: function () {
@@ -136,11 +170,12 @@ li {
136170
height: 35px;
137171
padding-top: 6px;
138172
text-align: center;
173+
cursor: move;
139174
}
140175
141176
.list-group-item-selected {
142177
display: inline-block;
143-
margin: 2px 1.5%;
178+
margin: 4px 1.5%;
144179
min-width: 175px;
145180
width: 30%;
146181
border-radius: 0.5cm;
@@ -149,6 +184,7 @@ li {
149184
height: 35px;
150185
padding-top: 6px;
151186
text-align: center;
187+
cursor: move;
152188
}
153189
154190
.fa-trash:hover {
@@ -191,4 +227,12 @@ li {
191227
hr {
192228
border: 1px solid grey
193229
}
230+
231+
.currentlyDragging {
232+
opacity: .5;
233+
}
234+
235+
.ignoreByDragover {
236+
pointer-events: none;
237+
}
194238
</style>

src/store/actions.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,30 @@ const actions = {
292292
[types.upOneLayer]: ({ commit }, payload) => {
293293
commit(types.UP_ONE_LAYER, payload);
294294
},
295+
//FOR MUTATING HTML WITH DRAG AND DROP
296+
[types.setIdDrag]: ({ commit }, payload) => {
297+
commit(types.SET_ID_DRAG, payload)
298+
},
299+
300+
[types.setIdDrop]: ({ commit }, payload) => {
301+
commit(types.SET_ID_DROP, payload)
302+
},
303+
304+
[types.setSelectedIdDrag]: ({ commit }, payload) => {
305+
commit(types.SET_SELECTED_ID_DRAG, payload)
306+
},
307+
308+
[types.setSelectedIdDrop]: ({ commit }, payload) => {
309+
commit(types.SET_SELECTED_ID_DROP, payload)
310+
},
311+
312+
[types.dragDropSortHtmlElements]: ({ commit }, payload) => {
313+
commit(types.DRAG_DROP_SORT_HTML_ELEMENTS)
314+
},
315+
316+
[types.dragDropSortSelectedHtmlElements]: ({ commit }, payload) => {
317+
commit(types.DRAG_DROP_SORT_SELECTED_HTML_ELEMENTS)
318+
},
295319

296320
// end of HTML segment ////////////////////////////////////////////////
297321

src/store/mutations.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,81 @@ const mutations = {
460460
state.activeHTML = "";
461461
},
462462

463+
[types.SET_ID_DRAG]: (state, payload) => {
464+
const componentName = state.activeComponent;
465+
state.componentMap[componentName].idDrag = payload;
466+
},
467+
468+
[types.SET_ID_DROP]: (state, payload) => {
469+
const componentName = state.activeComponent;
470+
state.componentMap[componentName].idDrop = payload;
471+
},
472+
473+
[types.SET_SELECTED_ID_DRAG]: (state, payload) => {
474+
state.selectedIdDrag = payload;
475+
},
476+
477+
[types.SET_SELECTED_ID_DROP]: (state, payload) => {
478+
state.selectedIdDrop = payload;
479+
},
480+
481+
[types.DRAG_DROP_SORT_HTML_ELEMENTS]: (state) => {
482+
const componentName = state.activeComponent;
483+
const idDrag = state.componentMap[componentName].idDrag;
484+
const idDrop = state.componentMap[componentName].idDrop;
485+
486+
if(idDrag !== idDrop && idDrag !== '' && idDrop !== '') {
487+
let indexDrag;
488+
let indexDrop;
489+
const htmlList = state.componentMap[componentName].htmlList.slice(0)
490+
491+
if (state.activeLayer.id === "") {
492+
htmlList.forEach((el, i) => {
493+
if(el.id === idDrag){
494+
indexDrag = i;
495+
} else if (el.id === idDrop){
496+
indexDrop = i;
497+
}
498+
})
499+
const draggedEl = htmlList.splice(indexDrag, 1)[0]
500+
htmlList.splice(indexDrop,0,draggedEl)
501+
} else {
502+
const nestedDrag = breadthFirstSearchParent(htmlList, idDrag);
503+
const nestedDrop = breadthFirstSearchParent(htmlList, idDrop);
504+
let nestedEl =nestedDrag.evaluated.children.splice(nestedDrag.index, 1)[0]
505+
nestedDrop.evaluated.children.splice(nestedDrop.index, 0, nestedEl)
506+
}
507+
state.componentMap[componentName].htmlList = htmlList;
508+
}
509+
state.componentMap[componentName].idDrag = '';
510+
state.componentMap[componentName].idDrop = '';
511+
},
512+
513+
[types.DRAG_DROP_SORT_SELECTED_HTML_ELEMENTS]: (state) => {
514+
const selectedIdDrag = state.selectedIdDrag;
515+
const selectedIdDrop = state.selectedIdDrop;
516+
517+
if(selectedIdDrag !== selectedIdDrop && selectedIdDrag !== '' && selectedIdDrop !== ''){
518+
const htmlList = state.selectedElementList.slice(0)
519+
520+
let indexDrag;
521+
let indexDrop;
522+
523+
htmlList.forEach((el, i) => {
524+
if(el.id === selectedIdDrag){
525+
indexDrag = i;
526+
} else if (el.id === selectedIdDrop){
527+
indexDrop = i;
528+
}
529+
})
530+
531+
const draggedEl = htmlList.splice(indexDrag, 1)[0]
532+
htmlList.splice(indexDrop,0,draggedEl)
533+
state.selectedElementList = htmlList;
534+
}
535+
state.selectedIdDrag = '';
536+
state.selectedIdDrop = '';
537+
},
463538
// *** COMPONENTS *** //////////////////////////////////////////////
464539
// adds the component to the selected route (ex: HomeView)
465540
[types.ADD_COMPONENT_TO_ACTIVE_ROUTE_CHILDREN]: (state, payload) => {
@@ -485,6 +560,8 @@ const mutations = {
485560
isActive,
486561
actions,
487562
props,
563+
idDrag,
564+
idDrop
488565
} = payload;
489566
const s = payload.state;
490567
state.componentMap = {
@@ -503,6 +580,8 @@ const mutations = {
503580
actions,
504581
props,
505582
state: s,
583+
idDrag,
584+
idDrop
506585
},
507586
};
508587
},

src/store/state/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ const newState = {
4747
selectedState: [],
4848
selectedActions: [],
4949
selectedElementList: [],
50+
selectedIdDrag: '',
51+
selectedIdDrop: '',
5052
projectNumber: 2,
5153
activeTab: 0,
5254
componentChildrenMultiselectValue: [],

0 commit comments

Comments
 (0)