virtual-excel-table 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,233 @@
1
+ <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
2
+ <!DOCTYPE html>
3
+ <html lang="ko">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>VirtualExcelTable 데모</title>
8
+ <style>
9
+ body {
10
+ margin: 0;
11
+ background: #f5f7fb;
12
+ color: #1f2937;
13
+ font-family: Arial, "Malgun Gothic", sans-serif;
14
+ }
15
+
16
+ .page {
17
+ max-width: 1100px;
18
+ margin: 40px auto;
19
+ padding: 0 20px;
20
+ }
21
+
22
+ .panel {
23
+ padding: 24px;
24
+ border: 1px solid #d9e0e8;
25
+ border-radius: 8px;
26
+ background: #fff;
27
+ box-shadow: 0 4px 16px rgba(15, 23, 42, 0.06);
28
+ }
29
+
30
+ h1 {
31
+ margin: 0 0 12px;
32
+ font-size: 26px;
33
+ }
34
+
35
+ .usage {
36
+ margin: 0 0 18px;
37
+ padding-left: 22px;
38
+ color: #4b5563;
39
+ line-height: 1.7;
40
+ }
41
+
42
+ .toolbar {
43
+ display: flex;
44
+ flex-wrap: wrap;
45
+ gap: 8px;
46
+ margin-bottom: 12px;
47
+ }
48
+
49
+ .toolbar button {
50
+ padding: 8px 14px;
51
+ border: 1px solid #b8c2cf;
52
+ border-radius: 5px;
53
+ background: #fff;
54
+ color: #1f2937;
55
+ cursor: pointer;
56
+ }
57
+
58
+ .toolbar button:hover {
59
+ background: #eef4ff;
60
+ }
61
+
62
+ .table-wrap {
63
+ overflow-x: auto;
64
+ }
65
+
66
+ #excelTable {
67
+ width: 100%;
68
+ min-width: 760px;
69
+ border-collapse: collapse;
70
+ table-layout: fixed;
71
+ }
72
+
73
+ #excelTable caption {
74
+ padding: 0 0 10px;
75
+ color: #6b7280;
76
+ text-align: left;
77
+ }
78
+
79
+ #excelTable th,
80
+ #excelTable td {
81
+ height: 42px;
82
+ padding: 0;
83
+ border: 1px solid #cfd7e3;
84
+ }
85
+
86
+ #excelTable th {
87
+ padding: 0 10px;
88
+ background: #eef2f7;
89
+ font-weight: 600;
90
+ text-align: center;
91
+ }
92
+
93
+ #excelTable tbody th {
94
+ width: 46px;
95
+ color: #6b7280;
96
+ }
97
+
98
+ #excelTable input {
99
+ box-sizing: border-box;
100
+ width: 100%;
101
+ height: 100%;
102
+ padding: 8px 10px;
103
+ border: 0;
104
+ outline: 0;
105
+ background: transparent;
106
+ color: inherit;
107
+ font: inherit;
108
+ }
109
+
110
+ #excelTable input:focus {
111
+ box-shadow: inset 0 0 0 2px #60a5fa;
112
+ }
113
+
114
+ .binding-note {
115
+ margin: 14px 0 0;
116
+ color: #6b7280;
117
+ font-size: 13px;
118
+ }
119
+ </style>
120
+ </head>
121
+ <body>
122
+ <main class="page">
123
+ <section class="panel">
124
+ <h1>엑셀 붙여넣기 테이블</h1>
125
+ <ol class="usage">
126
+ <li>셀을 한 번 클릭하거나 input 위에서 마우스로 끌어 범위를 선택합니다. 바로 타이핑하면 새 값 입력, F2/더블클릭은 기존 값 편집입니다.</li>
127
+ <li>Excel, LibreOffice 또는 Google Sheets에서 범위를 복사한 뒤 Ctrl+V(Mac은 Cmd+V)를 누릅니다.</li>
128
+ <li>선택 삭제 버튼 또는 Delete 키로 값을 지우고, Ctrl+Z / Ctrl+Y로 되돌리기 / 다시 실행합니다.</li>
129
+ </ol>
130
+
131
+ <div class="toolbar" role="toolbar" aria-label="테이블 편집 도구">
132
+ <button type="button" onclick="excelTable.addRow();">행 추가</button>
133
+ <button type="button" onclick="excelTable.copy();">선택 복사</button>
134
+ <button type="button" onclick="excelTable.undo();">되돌리기</button>
135
+ <button type="button" onclick="excelTable.redo();">다시 실행</button>
136
+ <button type="button" onclick="excelTable.deleteSelection();">선택 값 삭제</button>
137
+ <button type="button" onclick="excelTable.deleteRows();">선택 행 삭제</button>
138
+ <button type="button" onclick="excelTable.selectAll();">전체 선택</button>
139
+ </div>
140
+
141
+ <form id="excelForm" method="post">
142
+ <div class="table-wrap">
143
+ <table id="excelTable">
144
+ <caption>각 input의 name은 Spring MVC 목록 바인딩용 0 기반 인덱스를 사용합니다.</caption>
145
+ <colgroup>
146
+ <col style="width: 54px;">
147
+ <col style="width: 180px;">
148
+ <col style="width: 260px;">
149
+ <col style="width: 120px;">
150
+ <col style="width: 140px;">
151
+ </colgroup>
152
+ <thead>
153
+ <tr>
154
+ <th scope="col" data-excel-corner>#</th>
155
+ <th scope="col" data-excel-column="0" data-excel-key="productCode">상품 코드</th>
156
+ <th scope="col" data-excel-column="1" data-excel-key="productName">상품명</th>
157
+ <th scope="col" data-excel-column="2" data-excel-key="quantity">수량</th>
158
+ <th scope="col" data-excel-column="3" data-excel-key="unitPrice">단가</th>
159
+ </tr>
160
+ </thead>
161
+ <tbody>
162
+ <tr>
163
+ <th scope="row" data-excel-row-header>1</th>
164
+ <td><input type="text" name="items[0].productCode" data-excel-target aria-label="1행 상품 코드"></td>
165
+ <td><input type="text" name="items[0].productName" data-excel-target aria-label="1행 상품명"></td>
166
+ <td><input type="text" name="items[0].quantity" data-excel-target inputmode="numeric" aria-label="1행 수량"></td>
167
+ <td><input type="text" name="items[0].unitPrice" data-excel-target inputmode="decimal" aria-label="1행 단가"></td>
168
+ </tr>
169
+ <tr>
170
+ <th scope="row" data-excel-row-header>2</th>
171
+ <td><input type="text" name="items[1].productCode" data-excel-target aria-label="2행 상품 코드"></td>
172
+ <td><input type="text" name="items[1].productName" data-excel-target aria-label="2행 상품명"></td>
173
+ <td><input type="text" name="items[1].quantity" data-excel-target inputmode="numeric" aria-label="2행 수량"></td>
174
+ <td><input type="text" name="items[1].unitPrice" data-excel-target inputmode="decimal" aria-label="2행 단가"></td>
175
+ </tr>
176
+ <tr>
177
+ <th scope="row" data-excel-row-header>3</th>
178
+ <td><input type="text" name="items[2].productCode" data-excel-target aria-label="3행 상품 코드"></td>
179
+ <td><input type="text" name="items[2].productName" data-excel-target aria-label="3행 상품명"></td>
180
+ <td><input type="text" name="items[2].quantity" data-excel-target inputmode="numeric" aria-label="3행 수량"></td>
181
+ <td><input type="text" name="items[2].unitPrice" data-excel-target inputmode="decimal" aria-label="3행 단가"></td>
182
+ </tr>
183
+ <tr>
184
+ <th scope="row" data-excel-row-header>4</th>
185
+ <td><input type="text" name="items[3].productCode" data-excel-target aria-label="4행 상품 코드"></td>
186
+ <td><input type="text" name="items[3].productName" data-excel-target aria-label="4행 상품명"></td>
187
+ <td><input type="text" name="items[3].quantity" data-excel-target inputmode="numeric" aria-label="4행 수량"></td>
188
+ <td><input type="text" name="items[3].unitPrice" data-excel-target inputmode="decimal" aria-label="4행 단가"></td>
189
+ </tr>
190
+ <tr>
191
+ <th scope="row" data-excel-row-header>5</th>
192
+ <td><input type="text" name="items[4].productCode" data-excel-target aria-label="5행 상품 코드"></td>
193
+ <td><input type="text" name="items[4].productName" data-excel-target aria-label="5행 상품명"></td>
194
+ <td><input type="text" name="items[4].quantity" data-excel-target inputmode="numeric" aria-label="5행 수량"></td>
195
+ <td><input type="text" name="items[4].unitPrice" data-excel-target inputmode="decimal" aria-label="5행 단가"></td>
196
+ </tr>
197
+ </tbody>
198
+ </table>
199
+ </div>
200
+ </form>
201
+
202
+ <p class="binding-note">
203
+ 서버에서는 items[0].productCode, items[0].productName 같은 이름을 커맨드 객체의 List 필드에 바인딩할 수 있습니다.
204
+ </p>
205
+ </section>
206
+ </main>
207
+
208
+ <script src="${pageContext.request.contextPath}/resources/js/virtual-excel-table.js"></script>
209
+ <script>
210
+ function reindexItemRows(table) {
211
+ var rows = table.querySelectorAll('tbody tr');
212
+ var fields;
213
+ var i;
214
+ var j;
215
+
216
+ for (i = 0; i < rows.length; i += 1) {
217
+ rows[i].getElementsByTagName('th')[0].innerHTML = i + 1;
218
+ fields = rows[i].querySelectorAll('[name]');
219
+ for (j = 0; j < fields.length; j += 1) {
220
+ fields[j].name = fields[j].name.replace(
221
+ /^items\[\d+\]/,
222
+ 'items[' + i + ']'
223
+ );
224
+ }
225
+ }
226
+ }
227
+
228
+ var excelTable = VirtualExcelTable('#excelTable', {
229
+ reindexRows: reindexItemRows
230
+ });
231
+ </script>
232
+ </body>
233
+ </html>