챗지피티가 정말 좋아졌다... 불과 2년전까지만 해도 머리털 쥐뜯었는데... 기본으로 짜준 코드를 바탕으로 다듬어봄
Demo
See the Pen Trello by Oh Ikmyeong (@dpffpself) on CodePen.
HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Trello</title>
<link rel="stylesheet" href="./style.css">
<script src="./main.js" type="module"></script>
</head>
<body>
<form id="frm">
<input type="text" name="iptAdd" placeholder="type then enter"/>
</form>
<div class="wrap">
<div id="temp">추가한 아이템은 여기로 옴</div>
<ul class="list">
<li class="item" draggable="true">
<div class="item-content">
Hello World(1)
</div>
</li>
</ul>
<ul class="list">
<li class="item" draggable="true">
<div class="item-content">
Hacked(2)
</div>
</li>
</ul>
<ul class="list">
<li class="item" draggable="true">
<div class="item-content">
Overwatch(3)
</div>
</li>
</ul>
</div>
</body>
</html>
|
cs |
CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
@charset "utf-8";
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
background: #34333f;
}
body {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
min-height: 100vh;
}
[type="text"] {
display: block;
padding: 0 10px;
height: 42px;
width: 300px;
}
.wrap {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 40px;
position: relative;
padding: 40px;
width: 100%;
max-width: 1400px;
}
#temp{
display:flex;flex-flow:column nowrap;
justify-content:flex-start; align-items:flex-start;
gap:10px;
position:relative;
padding:40px;
background:black;
color:#fff;
}
.list {
display: flex;
flex-flow: column nowrap;
justify-content: flex-start;
align-items: flex-start;
gap: 10px;
position: relative; overflow:auto;
width: 100%; max-height:60vh;
background: #eee;
padding: 20px;
border-radius: 12px;
}
.item {
list-style-type: none;
position: relative;
width:100%;
cursor: pointer;
}
.item-content {
width: 100%;
padding: 20px;
background: #fff;
border: 1px solid #ccc;
border-radius: 4px;
color:#000;
pointer-events:none;
user-select: none;
transition:opacity .3s;
}
.item.dragging{
background:rgba(65, 105, 225, 0.265);
border:2px dotted #aaa;
cursor:move;
}
.item.dragging .item-content{opacity:0;}
.item.nextsib{
border-top:2px solid royalblue;
}
|
cs |
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
import { Trello } from "./Trello.js";
import { TrelloView } from "./TrelloView.js";
const $form = document.getElementById("frm");
const TRELLO = new Trello()
.set_lists(document.querySelectorAll(".list"))
.set_items(document.querySelectorAll(".item"))
.init();
$form.addEventListener("submit",(e)=>{
e.preventDefault();
const content = String(e.target.iptAdd.value).trim();
if(!content) return;
e.target.iptAdd.value = "";
const $item = TrelloView.make_item(content);
const $temp = document.getElementById("temp");
$temp.appendChild($item);
TRELLO.add_events_to_item($item);
});
|
cs |
TrelloView.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
export class TrelloView{
static make_item(content){
const $item = document.createElement("LI");
$item.classList.add("item");
$item.draggable = "true";
const $content = document.createElement("DIV");
$content.classList.add("item-content");
$content.textContent = content;
$item.appendChild($content);
return $item;
}//make_item
}//class-TrelloView
|
cs |
Trello.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
export class Trello {
constructor() {
this.$$list = null;
this.$$item = null;
this.$dragging = null;
this.clss = {
on: "dragging",
next: "nextsib"
}
}//constructor
set_lists($$list) {
this.$$list = $$list;
return this;
}//set_lists
set_items($$item) {
this.$$item = $$item;
return this;
}//set_items
init() {
this.$$item.forEach(this.add_events_to_item);
this.$$list.forEach(this.add_events_to_list);
return this;
}//init
/**
*
* @param {*} $item
*/
add_events_to_item = ($item) => {
this.add_drag_start_item($item);
this.add_drag_end_item($item);
}//add_events_to_item
/**
*
* @param {*} $list
*/
add_events_to_list = ($list) => {
this.add_drag_over_list($list);
this.add_drag_leave_list($list);
this.add_drag_drop_list($list);
}//add_events_to_list
/**
* 아이템에 이벤트 추가
*/
add_drag_start_item($item) {
$item.addEventListener("dragstart", () => {
this.$dragging = $item;
$item.classList.add(this.clss.on);
});
}//add_drag_start_item
/**
* 아이템에 이벤트 추가
*/
add_drag_end_item($item) {
$item.addEventListener("dragend", () => {
this.$dragging = null;
$item.classList.remove(this.clss.on);
});
}//add_drag_end_item
/**
*
* @param {*} $list
*/
add_drag_over_list($list) {
$list.addEventListener("dragover", (e) => {
e.preventDefault();
const { clientY } = e;
this.remove_all_nextsib_style($list);
const $afterElem = this.get_drag_after_item({ $list, clientY });
if ($afterElem) { this.nextsib_style($afterElem); }
});
}//add_drag_over_list
/**
*
* @param {*} $list
*/
add_drag_leave_list($list) {
$list.addEventListener("dragleave", () => {
this.remove_all_nextsib_style($list);
});
}//add_drag_leave_list
/**
*
* @param {*} $list
*/
add_drag_drop_list($list) {
$list.addEventListener("drop", (e) => {
e.preventDefault();
const { clientY } = e;
const $afterElem = this.get_drag_after_item({ $list, clientY });
this.remove_all_nextsib_style($list);
if ($afterElem) {
$list.insertBefore(this.$dragging, $afterElem);
} else {
$list.appendChild(this.$dragging);
}
});
}//add_drag_drop_list
/**
*
* @param {*} $list
*/
remove_all_nextsib_style($list) {
const $$item = $list.querySelectorAll(".item");
$$item.forEach($item => { $item.classList.remove(this.clss.next); })
}//remove_all_nextsib_style
/**
*
* @param {*} $item
*/
nextsib_style($item) {
$item.classList.add(this.clss.next);
}//nextsib_style
/**
*
* @param {*} param0
*/
get_drag_after_item({ $list, clientY }) {
const $$item = Array.from($list.querySelectorAll(".item"));
const result = $$item.reduce((prev, $item) => {
const { top, height } = $item.getBoundingClientRect();
const offset = clientY - top - (height / 2);
if (offset < 0 && offset > prev.offset) {
return { offset, element: $item }
} else {
return prev;
}
}, { offset: Number.NEGATIVE_INFINITY });
return result?.element;
}//get_drag_after_item
}//class-Trello
|
cs |
'CSS&JS > 👀Study and Copy' 카테고리의 다른 글
[JS+CSS]Madia님 영상보다가 디자인 예쁜거 구현해보기 (고객의 소리 부분) (0) | 2024.10.04 |
---|---|
[CSS]inverted border-radius 안쪽으로 파인 효과 (0) | 2024.09.30 |
[LunDev]CSS only marquee slider (0) | 2024.09.19 |
[CSS/JS]Lun Dev 쇼핑몰 이미지 줌 효과 (1) | 2024.09.13 |
[JS]팝업창에 함수를 전달하고, 팝업창의 변수를 부모창에 전달하는 방법. (0) | 2024.04.16 |