-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.html
291 lines (273 loc) · 19.9 KB
/
index.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
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta property="og:title" content="">
<meta property="og:type" content="">
<meta property="og:url" content="">
<meta property="og:image" content="">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" href="icon.png">
<!-- Place favicon.ico in the root directory -->
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/main.css">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<meta name="theme-color" content="#fafafa">
</head>
<body>
<div class="container my-3 mb-5">
<!-- Add your site or application content here -->
<h1 class="mb-3">Timetable-to-wallpaper</h1>
<div class="mb-3">
<label for="table_import_paste_target" class="form-label">Paste (Ctrl + V) below an timetable copied (Ctrl + C) from your MIS timetable page.</label>
<div id="table_import_paste_target" class="form-control" contenteditable="true" autocomplete="off" spellcheck="false"></div>
<div id="emailHelp" class="form-text">Please make sure you have copied the whole table (including the table head and the cells without course).</div>
</div>
<!--<div id="table_import_paste_target" contenteditable="true" autocomplete="off" spellcheck="false"><meta charset="utf-8"><table cellspacing="0" id="mytimetable" style="font-family: Times; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><th class="socketfirst">Time</th><th class="sockettop">Mon</th><th class="sockettop">Tue</th><th class="sockettop">Wed</th><th class="sockettop">Thu</th><th class="sockettop">Fri</th><th class="sockettop">Sat</th></tr><tr><th class="socketleft">8:00 - 8:50</th><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">9:00 - 9:50</th><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">10:00 - 10:50</th><td class="socketspace">Computer Graphics (1001)<br>T7-203<br> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">11:00 - 11:50</th><td class="socketspace">Computer Graphics (1001)<br>T7-203<br> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">12:00 - 12:50</th><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">13:00 - 13:50</th><td class="socketspace">Digital Media (1001)<br>CC-414<br> </td><td class="socketspace"> </td><td class="socketspace">Computer Graphics (1001)<br>T29-505<br> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">14:00 - 14:50</th><td class="socketspace">Digital Media (1001)<br>CC-414<br> </td><td class="socketspace">Advertising and Society (1001)<br>T7-304<br> </td><td class="socketspace"> </td><td class="socketspace">Digital Media (1001)<br>T4-303<br> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">15:00 - 15:50</th><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace">Advertising and Society (1001)<br>T7-503<br> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">16:00 - 16:50</th><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace">Advertising and Society (1001)<br>T7-503<br> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">17:00 - 17:50</th><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">18:00 - 18:50</th><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">19:00 - 19:50</th><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">20:00 - 20:50</th><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr><tr><th class="socketleft">21:00 - 21:50</th><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td><td class="socketspace"> </td></tr></tbody></table></div>-->
<button onclick="parseTable()" type="button" class="btn btn-primary">Step 1: Parse</button>
<p id="parse_result" class="my-5"></p>
<hr>
<div class="mb-3">
<h2 class="mb-3">Aesthetics Customization</h2>
<h3>1. Size & Resolution</h3>
<div class="row">
<div class="col-md">
<label for="aspect-ratio-dropdown" class="form-label"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-aspect-ratio" viewBox="0 0 16 16">
<path d="M0 3.5A1.5 1.5 0 0 1 1.5 2h13A1.5 1.5 0 0 1 16 3.5v9a1.5 1.5 0 0 1-1.5 1.5h-13A1.5 1.5 0 0 1 0 12.5v-9zM1.5 3a.5.5 0 0 0-.5.5v9a.5.5 0 0 0 .5.5h13a.5.5 0 0 0 .5-.5v-9a.5.5 0 0 0-.5-.5h-13z"/>
<path d="M2 4.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1H3v2.5a.5.5 0 0 1-1 0v-3zm12 7a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1 0-1H13V8.5a.5.5 0 0 1 1 0v3z"/>
</svg> Screen Aspect Ratio</label>
<select id="aspect-ratio-dropdown" class="form-select form-select mb-3" id="size-selector">
<option value="16:9" selected>16:9</option>
<option value="2:1">2:1 - e.g.: Moto, Google, Smartisan</option>
<option value="18.5:9">18.5:9 - e.g.: Samsung</option>
<option value="19:9">19:9 - e.g.: iPhone, Samsung</option>
<option value="19.5:9">19.5:9 - e.g.: OnePlus, Huawei, Oppo, Xiaomi</option>
<option value="20:9">20:9</option>
</select>
</div>
<div class="col">
<label for="aspect-ratio-dropdown" class="form-label"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-badge-hd" viewBox="0 0 16 16">
<path d="M7.396 11V5.001H6.209v2.44H3.687V5H2.5v6h1.187V8.43h2.522V11h1.187zM8.5 5.001V11h2.188c1.811 0 2.685-1.107 2.685-3.015 0-1.894-.86-2.984-2.684-2.984H8.5zm1.187.967h.843c1.112 0 1.622.686 1.622 2.04 0 1.353-.505 2.02-1.622 2.02h-.843v-4.06z"/>
<path d="M14 3a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h12zM2 2a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H2z"/>
</svg> Screen Resolution</label>
<div class="mb-3">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="ResolutionOptions" id="res-720" value="720">
<label class="form-check-label" for="res-720">720P</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="ResolutionOptions" id="res-1080" value="1080" checked>
<label class="form-check-label" for="res-1080">1080P</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="ResolutionOptions" id="res-1440" value="1440">
<label class="form-check-label" for="res-1440">2K</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="ResolutionOptions" id="res-2160" value="2160">
<label class="form-check-label" for="res-2160">4K</label>
</div>
</div>
</div>
</div>
<h3>2. Background Image</h3>
<div class="row">
<div class="col-md-8">
<div class="row">
<div class='col text-center'>
<input type="radio" name="imgBackgroundOption" id="img1" class="d-none imgbgchk" value="img/john-fowler-RsRTIofe0HE-unsplash.jpg" checked>
<label for="img1">
<img class="rounded" src="img/john-fowler-RsRTIofe0HE-unsplash.jpg" alt="Image 1">
<div class="tick_container">
<div class="tick"><svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg></div>
</div>
</label>
</div>
<div class='col text-center'>
<input type="radio" name="imgBackgroundOption" id="img2" class="d-none imgbgchk" value="img/jonny-gios-HdK_fBPoWGE-unsplash.jpg">
<label for="img2">
<img class="rounded" src="img/jonny-gios-HdK_fBPoWGE-unsplash.jpg" alt="Image 2">
<div class="tick_container">
<div class="tick"><svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg></div>
</div>
</label>
</div>
<div class='col text-center'>
<input type="radio" name="imgBackgroundOption" id="img3" class="d-none imgbgchk" value="img/bernd-dittrich-fiXjuBOECs4-unsplash.jpg">
<label for="img3">
<img class="rounded" src="img/bernd-dittrich-fiXjuBOECs4-unsplash.jpg" alt="Image 3">
<div class="tick_container">
<div class="tick"><svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg></div>
</div>
</label>
</div>
<div class='col text-center'>
<input type="radio" name="imgBackgroundOption" id="img4" class="d-none imgbgchk" value="img/maeva-vigier-2fa1zztCgBQ-unsplash.jpg">
<label for="img4">
<img class="rounded" src="img/maeva-vigier-2fa1zztCgBQ-unsplash.jpg" alt="Image 4">
<div class="tick_container">
<div class="tick"><svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg></div>
</div>
</label>
</div>
</div>
</div>
<div class="col-md-4">
<label for="bg_url" class="form-label">Or Provides a Picture URL:</label>
<input id="bg_url" class="form-control">
<div id="bgHelp" class="form-text">A non-blank field will ignore your checked image.</div>
</div>
</div>
</div>
<h3 class="text-muted">3. Theme and Color <span><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-tools" viewBox="0 0 16 16">
<path d="M1 0 0 1l2.2 3.081a1 1 0 0 0 .815.419h.07a1 1 0 0 1 .708.293l2.675 2.675-2.617 2.654A3.003 3.003 0 0 0 0 13a3 3 0 1 0 5.878-.851l2.654-2.617.968.968-.305.914a1 1 0 0 0 .242 1.023l3.356 3.356a1 1 0 0 0 1.414 0l1.586-1.586a1 1 0 0 0 0-1.414l-3.356-3.356a1 1 0 0 0-1.023-.242L10.5 9.5l-.96-.96 2.68-2.643A3.005 3.005 0 0 0 16 3c0-.269-.035-.53-.102-.777l-2.14 2.141L12 4l-.364-1.757L13.777.102a3 3 0 0 0-3.675 3.68L7.462 6.46 4.793 3.793a1 1 0 0 1-.293-.707v-.071a1 1 0 0 0-.419-.814L1 0zm9.646 10.646a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708zM3 11l.471.242.529.026.287.445.445.287.026.529L5 13l-.242.471-.026.529-.445.287-.287.445-.529.026L3 15l-.471-.242L2 14.732l-.287-.445L1.268 14l-.026-.529L1 13l.242-.471.026-.529.445-.287.287-.445.529-.026L3 11z"/>
</svg> Coming Soon</span></h3>
</span>
<button onclick="triggerModel()" type="button" class="btn btn-success">Step 2: Generate <span class="hidden" id="generation_loading"><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
<span class="visually-hidden">Loading...</span></span></button>
<div class="modal fade" id="canvasModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="canvasModalLabel">Your Wallpaper: Long press the image to save</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<!-- <canvas id="target-bg-canvas" width="1080" height="1920"></canvas>-->
<canvas id="bg-canvas" width="1080" height="1920"></canvas>
</div>
<!-- <div class="modal-footer">-->
<!-- <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>-->
<!-- <button type="button" class="btn btn-primary" onclick="saveImage()">Download Image</button>-->
<!-- </div>-->
</div>
</div>
</div>
<hr>
<h2>Bonus Tool: <code>.ics</code> file Generator</h2>
<div class="mb-3">
<label for="dateField" class="form-label">Start and End Date (Format: 2022-02-02)</label>
<div class="row" id="dateField">
<div class="col">
<input id="startDate" type="text" class="form-control" placeholder="Start Date" aria-label="Start Date">
</div>
<div class="col">
<input id="endDate" type="text" class="form-control" placeholder="End Date" aria-label="End Date">
</div>
</div>
<div id="dateHelp" class="form-text">Input the start and ending date for the repeating course. <span class="fw-bold">Date checking has not been implemented, and a wrong input will lead to a corrupted file.</span></div>
</div>
<button onclick="get_ics_material()" type="button" class="btn btn-warning">Get .ics</button>
<hr class="mt-4 mb-4">
<span>Hosting on <a href="https://pages.github.com/">GitHub Pages</a> , content delivered by <a href="https://www.cloudflare.com/">Cloudflare</a> and <a href="https://www.jsdelivr.com/">jsDelivr</a>.</span>
<p class="mb-5">Project by <a href="https://uichcc.com">UICHCC</a>, <a href="https://github.com/UICHCC/timetable-to-bg">Open Source at GitHub</a>; Current Version: <span class="text-success">v1.7</span> </p>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<script src="js/ics.deps.min.js"></script>
<script src="js/ics.min.js"></script>
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
<script>
document.getElementById('table_import_paste_target').addEventListener('paste', function (e) {
e.preventDefault();
var pastedText = ''
if (window.clipboardData && window.clipboardData.getData) { // IE
pastedText = window.clipboardData.getData('text/html');
} else if (e.clipboardData && e.clipboardData.getData) {
pastedText = e.clipboardData.getData('text/html');
}
document.getElementById('table_import_paste_target').innerHTML = pastedText
});
</script>
<script>
// get start and end date
function get_ics_material(){
var startDate = document.getElementById('startDate').value;
var endDate = document.getElementById('endDate').value;
if (course_ds.length == 0){
alert('No course data found. Please parse the table first.');
return;
}
if (startDate == '' || endDate == ''){
alert('Please input the start and end date.');
return;
}
startDate = startDate + " 08:00:00 CST"
endDate = endDate + " 23:00:00 CST"
// enforce timezone
function getAllDate(weekday, startD, endD){
var start = new Date(startD);
var end = new Date(endD);
var dates = [];
for (var day = 0; day < 7; day++) {
if (start.getDay() == (weekday + 1) % 6) {
dates.push(start.toISOString().slice(0,10));
}
start.setDate(start.getDate() + 1);
}
return dates;
}
function toStartEndTime(time){
if (typeof time === 'number'){
let range = timeRange[time].split('-');
return [range[0].substring(0,2) + ':' + range[0].substring(2,4), range[1].substring(0,2) + ':' + range[1].substring(2,4) + ':00'];
}else{
let start_index = time[0];
if (typeof start_index === 'object') {
start_index = time[0][0];
}
let start = timeRange[start_index].split('-')[0];
let end = timeRange[time[time.length - 1]].split('-')[1];
return [start.substring(0,2) + ':' + start.substring(2,4), end.substring(0,2) + ':' + end.substring(2,4) + ':00'];
}
}
var course_ds_date = []
for (var i = 0; i < course_ds.length; i++) {
course_ds_date.push([course_ds[i][0], getAllDate(course_ds[i][1], startDate, endDate), toStartEndTime(course_ds[i][2])])
}
// adding time to date
function mergeDateTime(date, time){
var date_time = new Date(date + 'T' + time);
return date_time;
}
var cal = ics();
for (var i = 0; i < course_ds_date.length; i++){
for (var j = 0; j < course_ds_date[i][1].length; j++) {
cal.addEvent(course_ds_date[i][0][0], '', course_ds_date[i][0][1], mergeDateTime(course_ds_date[i][1][j], course_ds_date[i][2][0]), mergeDateTime(course_ds_date[i][1][j], course_ds_date[i][2][1]), {
freq: 'WEEKLY',
until: endDate,
interval: 1,
});
}
}
// cal.addEvent(subject, description, location, begin, end);
// cal.addEvent(subject, description, location, begin, end); // yes, you can have multiple events :-)
cal.download(startDate + '_' + endDate + '_' + course_ds_date.length + '-courses');
}
</script>
<script>
let myModal = new bootstrap.Modal(document.getElementById('canvasModal'))
function triggerModel(){
let spinner = document.getElementById('generation_loading');
spinner.classList.remove('hidden');
drawCanvas().then(r => {
console.log('done generation')
myModal.show();
spinner.classList.add('hidden');
});
}
</script>
</body>
</html>