Skip to content

Commit 4106691

Browse files
author
Hesam Bahrami
authored
feat: init option (#32)
* add the `init` option and invoke the initDragAndDrop method when instantiating only if init option value equals true or undefined * extend the initDragAndDrop method to set the initialised property value and go through an early return if it equals true * add the init method * extend the destroy method to set the initialised property value to false * update the enable-disable.html sample code to leverage the newly added `init` option * refactor and extend the list item attributes related tests
1 parent 758b371 commit 4106691

File tree

3 files changed

+141
-21
lines changed

3 files changed

+141
-21
lines changed

dev/enable-disable.html

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ <h2>Server rendered list</h2>
3333

3434
<hr>
3535

36-
<h2>Data-driven list</h2>
37-
36+
<h2>Local storage persistent data-driven list</h2>
3837
<button type="button" onclick="initDataDrivenList()">Init / Enable</button>
3938
<button type="button" onclick="destroyDataDrivenList()">Destroy / Disable</button>
4039

@@ -45,16 +44,14 @@ <h2>Data-driven list</h2>
4544
<script src="../dist/nested-sort.umd.js"></script>
4645
<script>
4746
// Server rendered list
48-
const initServerRenderedList = () => {
49-
if (window.serverRenderedList) {
50-
window.serverRenderedList.destroy()
51-
}
47+
const startServerRenderedList = () => {
5248
window.serverRenderedList = new NestedSort({
5349
actions: {
5450
onDrop: function (data) {
5551
console.log(data)
5652
}
5753
},
54+
init: false,
5855
el: '#server-rendered',
5956
droppingEdge: 5,
6057
listClassNames: ['nested-sort']
@@ -64,10 +61,15 @@ <h2>Data-driven list</h2>
6461
const destroyServerRenderedList = () => {
6562
if (window.serverRenderedList) {
6663
window.serverRenderedList.destroy()
67-
delete window.serverRenderedList
6864
}
6965
}
7066

67+
const initServerRenderedList = () => {
68+
window.serverRenderedList.init()
69+
}
70+
71+
startServerRenderedList()
72+
7173
// Local storage persistent data-driven list
7274
const originalData = [
7375
{ item_id: 1, item_title: 'One', position: 5 },
@@ -91,15 +93,13 @@ <h2>Data-driven list</h2>
9193
localStorage.setItem(dataKey, JSON.stringify(newData))
9294
}
9395

94-
const initDataDrivenList = () => {
95-
if (window.dataDrivenList) {
96-
window.dataDrivenList.destroy()
97-
}
96+
const startDataDrivenList = () => {
9897
window.dataDrivenList = new NestedSort({
9998
actions: {
10099
onDrop
101100
},
102101
data: data,
102+
init: false,
103103
propertyMap: {
104104
id: 'item_id',
105105
parent: 'item_parent',
@@ -115,9 +115,14 @@ <h2>Data-driven list</h2>
115115
const destroyDataDrivenList = () => {
116116
if (window.dataDrivenList) {
117117
window.dataDrivenList.destroy()
118-
delete window.dataDrivenList
119118
}
120119
}
120+
121+
const initDataDrivenList = () => {
122+
window.dataDrivenList.init()
123+
}
124+
125+
startDataDrivenList()
121126
</script>
122127
</body>
123128
</html>

src/main.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class NestedSort {
1717
data,
1818
droppingEdge = 15,
1919
el,
20+
init = true,
2021
listClassNames,
2122
listItemClassNames,
2223
propertyMap = {},
@@ -34,7 +35,7 @@ class NestedSort {
3435
this.actions = {
3536
onDrop,
3637
}
37-
38+
this.initialised = false
3839
this.targetNode = {
3940
X: null,
4041
Y: null,
@@ -74,7 +75,7 @@ class NestedSort {
7475

7576
this.maybeInitDataDom()
7677
this.addListAttributes()
77-
this.initDragAndDrop()
78+
if (init) this.initDragAndDrop()
7879
}
7980

8081
getDataEngine() {
@@ -143,15 +144,23 @@ class NestedSort {
143144
}
144145

145146
initDragAndDrop() {
147+
if (this.initialised) return
148+
146149
this.toggleListEventListeners()
147150
this.initPlaceholderList()
148151
this.toggleListItemAttributes()
149152
this.getSortableList().querySelectorAll('li').forEach(this.addListItemStyles.bind(this))
153+
this.initialised = true
154+
}
155+
156+
init() {
157+
this.initDragAndDrop()
150158
}
151159

152160
destroy() {
153161
this.toggleListEventListeners(true)
154162
this.toggleListItemAttributes(false)
163+
this.initialised = false
155164
}
156165

157166
getComputedStyleValue(el, prop) {

test/main.test.js

Lines changed: 113 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,19 @@ describe('NestedSort', () => {
1414
document.body.innerHTML = `<div id="${DYNAMIC_LIST_WRAPPER_ID}"></div>`
1515
})
1616

17-
describe('upon initiation', () => {
18-
describe('list items attributes', () => {
19-
it('should add the draggable attribute to all the list items', () => {
20-
const ns = initDataDrivenList()
21-
Array.from(ns.getSortableList().getElementsByTagName('li')).forEach(li => {
22-
expect(li.getAttribute('draggable')).toBe('true')
23-
})
17+
describe('upon instantiation', () => {
18+
it('should not invoke the initDragAndDrop method when the init option is falsy', () => {
19+
const spy = jest.spyOn(NestedSort.prototype, 'initDragAndDrop')
20+
initDataDrivenList({ init: false })
21+
expect(spy).not.toHaveBeenCalled()
22+
})
23+
24+
it('should invoke the initDragAndDrop method when the init option is true or undefined', () => {
25+
[undefined, true].forEach(init => {
26+
const spy = jest.spyOn(NestedSort.prototype, 'initDragAndDrop')
27+
initDataDrivenList({ init })
28+
expect(spy).toHaveBeenCalledTimes(1)
29+
spy.mockRestore()
2430
})
2531
})
2632
})
@@ -905,6 +911,72 @@ describe('NestedSort', () => {
905911
})
906912
})
907913

914+
describe('initDragAndDrop method', () => {
915+
describe('when drag and drop is already initialised', () => {
916+
let ns
917+
beforeEach(() => {
918+
ns = initDataDrivenList({ init: true })
919+
})
920+
921+
it('should go through the early return', () => {
922+
const spy1 = jest.spyOn(ns, 'toggleListEventListeners')
923+
const spy2 = jest.spyOn(ns, 'initPlaceholderList')
924+
const spy3 = jest.spyOn(ns, 'toggleListItemAttributes')
925+
926+
ns.initDragAndDrop()
927+
928+
expect(spy1).not.toHaveBeenCalled()
929+
expect(spy2).not.toHaveBeenCalled()
930+
expect(spy3).not.toHaveBeenCalled()
931+
})
932+
})
933+
934+
describe('when drag and drop is NOT initialised', () => {
935+
let ns
936+
beforeEach(() => {
937+
ns = initDataDrivenList({ init: false })
938+
})
939+
940+
it('should invoke the toggleListEventListeners method with no arguments', () => {
941+
const spy = jest.spyOn(ns, 'toggleListEventListeners')
942+
ns.initDragAndDrop()
943+
expect(spy).toHaveBeenCalledTimes(1)
944+
expect(spy).toHaveBeenCalledWith()
945+
})
946+
947+
it('should invoke the initPlaceholderList method with no arguments', () => {
948+
const spy = jest.spyOn(ns, 'initPlaceholderList')
949+
ns.initDragAndDrop()
950+
expect(spy).toHaveBeenCalledTimes(1)
951+
expect(spy).toHaveBeenCalledWith()
952+
})
953+
954+
it('should invoke the toggleListItemAttributes method with no arguments', () => {
955+
const spy = jest.spyOn(ns, 'toggleListItemAttributes')
956+
ns.initDragAndDrop()
957+
expect(spy).toHaveBeenCalledTimes(1)
958+
expect(spy).toHaveBeenCalledWith()
959+
})
960+
961+
it('should set the initialised property value to true', () => {
962+
expect(ns.initialised).toBe(false)
963+
ns.initDragAndDrop()
964+
expect(ns.initialised).toBe(true)
965+
})
966+
})
967+
})
968+
969+
describe('init method', () => {
970+
it('should invoke the initDragAndDrop', () => {
971+
const spy = jest.spyOn(NestedSort.prototype, 'initDragAndDrop')
972+
const ns = initDataDrivenList({ init: false })
973+
974+
expect(spy).not.toHaveBeenCalled()
975+
ns.init()
976+
expect(spy).toHaveBeenCalledTimes(1)
977+
})
978+
})
979+
908980
describe('destroy method', () => {
909981
it('should invoke the toggleListEventListeners method with correct arguments', () => {
910982
const ns = initDataDrivenList()
@@ -925,5 +997,39 @@ describe('NestedSort', () => {
925997
expect(spy).toHaveBeenCalledTimes(1)
926998
expect(spy).toHaveBeenCalledWith(false)
927999
})
1000+
1001+
it('should set the initialised property value to false', () => {
1002+
const ns = initDataDrivenList({ init: true })
1003+
ns.destroy()
1004+
expect(ns.initialised).toBe(false)
1005+
})
1006+
})
1007+
1008+
describe('toggleListItemAttributes method', () => {
1009+
it('should set the draggable attribute value to true on all the list items when no argument is passed to it', () => {
1010+
const ns = initDataDrivenList({ init: false })
1011+
Array.from(ns.getSortableList().getElementsByTagName('li')).forEach(li => {
1012+
expect(li.getAttribute('draggable')).toBe(null)
1013+
}) // to make sure instantiation has not set the attribute value
1014+
1015+
ns.toggleListItemAttributes()
1016+
1017+
Array.from(ns.getSortableList().getElementsByTagName('li')).forEach(li => {
1018+
expect(li.getAttribute('draggable')).toBe('true')
1019+
})
1020+
})
1021+
1022+
it('should set the draggable attribute value to false on all the list items when the passed argument equals false', () => {
1023+
const ns = initDataDrivenList({ init: true })
1024+
Array.from(ns.getSortableList().getElementsByTagName('li')).forEach(li => {
1025+
expect(li.getAttribute('draggable')).toBe('true')
1026+
}) // to make sure instantiation has set the attribute value to true
1027+
1028+
ns.toggleListItemAttributes(false)
1029+
1030+
Array.from(ns.getSortableList().getElementsByTagName('li')).forEach(li => {
1031+
expect(li.getAttribute('draggable')).toBe('false')
1032+
})
1033+
})
9281034
})
9291035
})

0 commit comments

Comments
 (0)