create-fesd-app 1.0.16 → 1.0.17

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-fesd-app",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite",
@@ -24,7 +24,7 @@
24
24
  "dependencies": {
25
25
  "@tailwindcss/postcss": "^4.1.10",
26
26
  "@tailwindcss/vite": "^4.1.10",
27
- "@xwadex/fesd": "0.0.38",
27
+ "@xwadex/fesd": "0.0.40",
28
28
  "ansi-colors": "^4.1.3",
29
29
  "chalk": "^5.3.0",
30
30
  "clsx": "^2.1.1",
@@ -1,5 +1,5 @@
1
1
  .cookie-check,
2
- .cookie-settingBlock
2
+ .cookie-setting
3
3
  .button-group
4
4
  display: flex
5
5
  .cookie-btn
@@ -92,7 +92,7 @@
92
92
  display: flex
93
93
  align-items: center
94
94
  gap: 10px
95
- .cookie-settingBtn
95
+ .cookie-setting-btn
96
96
  margin-left: auto
97
97
  display: flex
98
98
  align-items: center
@@ -115,20 +115,20 @@
115
115
  .cookie-container
116
116
  .button-group
117
117
  flex-direction: column
118
- .cookie-settingBtn
118
+ .cookie-setting-btn
119
119
  margin-top: 30px
120
120
  margin-right: auto
121
121
 
122
- [data-step]
123
- opacity: 0
124
- display: none
125
- transition: all .5s
126
- &.show
127
- opacity: 1
128
- &.active
129
- display: block
122
+ // [t4-id]
123
+ // opacity: 0
124
+ // display: none
125
+ // transition: all .5s
126
+ // &.show
127
+ // opacity: 1
128
+ // &.active
129
+ // display: block
130
130
 
131
- .cookie-settingBlock
131
+ .cookie-setting
132
132
  display: flex
133
133
  justify-content: center
134
134
  align-items: center
@@ -336,7 +336,7 @@
336
336
  box-shadow: 0 2px 8px rgba(0,0,0,0.28), 0 0 0 20px rgba(128,128,128,0.1)
337
337
 
338
338
  .setting-container
339
- &[data-step="2"]
339
+ &[t4-id='step2']
340
340
  .back
341
341
  display: flex
342
342
  align-items: center
@@ -1,10 +1,9 @@
1
1
  // 此處為 demo 資料, 後端會用相同資料結構洗資料在 #_wcookie 上
2
- // 給後端 :
3
- // 基本上進階版細項開關不開, 有需求才開; 若開啟進階版細項, 大分類的 close 開關預設會無效, 會以判斷細項是否有開啟 or 全關為主
2
+ // 給後端: 基本上進階版細項開關不開, 有需求才開; 若開啟進階版細項, 大分類的 close 開關預設會無效, 會以判斷細項是否有開啟 or 全關為主
4
3
  // close: 0 -> 開啟; close: 1 -> 關閉
5
4
  export const cookieData = [
6
5
  {
7
- multiType: true, // 是否開啟個別選項設定
6
+ multiType: true, // 進階版是否開啟個別選項設定
8
7
  title: "您的 Cookie 偏好設定",
9
8
  text: "我們使用不同類型的 Cookies 來優化您在我們的網站上的體驗,點擊下面類別以了解其目的與更多訊息。<br>您可以選擇允許的 Cookies 類型,也可以隨時更改您的偏好設定。<br>提醒您,停用 Cookies 可能會影響您在網站上的體驗,您可以瀏覽我們的隱私權政策,進一步了解我們如何使用 Cookie。",
10
9
  options: [
@@ -27,7 +26,7 @@ export const cookieData = [
27
26
  text: "php用來辨識用戶的session id",
28
27
  },
29
28
  {
30
- key: "XSRF",
29
+ key: "XSRF-TOKEN",
31
30
  close: 0,
32
31
  title: "XSRF-TOKEN",
33
32
  text: "網站防止 CSRF(Cross-Site Request Forgery,跨站請求偽造)攻擊 的 token",
@@ -63,14 +62,14 @@ export const cookieData = [
63
62
  text: "第一方 cookies 由用戶訪問的網站(即主機域名)設置。網站通常使用第一方 cookies 用於跟踪訪客在網站上的行為並個性化他們在網站上的瀏覽體驗以及個性化他們的瀏覽體驗。",
64
63
  list: [
65
64
  {
66
- title: "gtm",
67
65
  key: "gtm",
68
66
  close: 1,
67
+ title: "gtm",
69
68
  },
70
69
  {
71
- title: "ga",
72
70
  key: "ga",
73
71
  close: 1,
72
+ title: "ga",
74
73
  detail: [
75
74
  {
76
75
  title: "_ga",
@@ -93,15 +92,15 @@ export const cookieData = [
93
92
  text: "第三方 cookies 是由其他第三方實體放置在網站上,而不是網站本身,即使用者在地址欄中看到的網域以外的域名。第三方 cookies 通常跟踪訪客在網站之間的行為,通常用於針對性廣告目的。",
94
93
  list: [
95
94
  {
96
- title: "googlefont",
97
95
  key: "googlefont",
98
96
  close: 1,
97
+ title: "googlefont",
99
98
  },
100
99
  {
101
- title: "Youtube",
102
- text: "https://www.youtube.com/",
103
100
  key: "Youtube",
104
101
  close: 1,
102
+ title: "Youtube",
103
+ text: "https://www.youtube.com/",
105
104
  detail: [
106
105
  {
107
106
  title: "YSC",
@@ -141,10 +140,10 @@ export const cookieData = [
141
140
  ],
142
141
  },
143
142
  {
144
- title: "Vimeo",
145
- text: "https://vimeo.com/",
146
143
  key: "Vimeo",
147
144
  close: 1,
145
+ title: "Vimeo",
146
+ text: "https://vimeo.com/",
148
147
  detail: [
149
148
  {
150
149
  title: "_cf_bm",
@@ -161,10 +160,10 @@ export const cookieData = [
161
160
  ],
162
161
  },
163
162
  {
164
- title: "Tiktok",
165
- text: "https://www.tiktok.com/zh-Hant-TW/",
166
163
  key: "Tiktok",
167
164
  close: 1,
165
+ title: "Tiktok",
166
+ text: "https://www.tiktok.com/zh-Hant-TW/",
168
167
  detail: [
169
168
  {
170
169
  title: "_ttp",
@@ -193,10 +192,10 @@ export const cookieData = [
193
192
  ],
194
193
  },
195
194
  {
196
- title: "instagram",
197
- text: "https://www.instagram.com/",
198
195
  key: "instagram",
199
196
  close: 1,
197
+ title: "instagram",
198
+ text: "https://www.instagram.com/",
200
199
  detail: [
201
200
  {
202
201
  title: "mid",
@@ -207,10 +206,10 @@ export const cookieData = [
207
206
  ],
208
207
  },
209
208
  {
210
- title: "meta",
211
- text: "https://www.facebook.com/privacy/policy",
212
209
  key: "meta",
213
210
  close: 1,
211
+ title: "meta",
212
+ text: "https://www.facebook.com/privacy/policy",
214
213
  detail: [
215
214
  {
216
215
  title: "_fbp",
@@ -1,22 +1,23 @@
1
- // js cookie 結構方法
2
- /**
3
- * @param {Array} target
4
- * @param {(opt: cookieData[0], index: number) => string} fn
5
- */
6
- const generateHtmlString = (target, fn) => {
7
- return target.map((data, index) => fn(data, index)).join("")
8
- }
1
+ import { generateHtmlString } from "./cookiePolicy"
9
2
 
10
- export const cookieStep1El = (opt, index, isDisabled, isChecked) => {
3
+ // input 開關按鈕使用相同 data-name, 會同步 checked
4
+ // 第一步驟
5
+ export const cookieStep1El = (
6
+ opt,
7
+ index,
8
+ isDisabled,
9
+ isChecked
10
+ ) => {
11
11
  return `
12
- <div class="item" data-index="${index}">
12
+ <div class="item main-option ${isChecked()}" data-index="${index}">
13
13
  <div class="left">
14
14
  <div class="checkbox ${isDisabled}">
15
15
  <div class="input-wrap">
16
- <input type="checkbox"
16
+ <input
17
+ type="checkbox"
17
18
  id="s1-check-${index}"
18
- ${isChecked()}
19
19
  data-name="${opt.key}"
20
+ ${isChecked()}
20
21
  >
21
22
  <div class="fake-checkbox">
22
23
  <i class="icon-check"></i>
@@ -34,17 +35,23 @@ export const cookieStep1El = (opt, index, isDisabled, isChecked) => {
34
35
  <i class="icon-notice"></i>
35
36
  </div>
36
37
  <span>${opt.notice}</span>
37
- </div>` : ""}
38
+ </div>` : ""
39
+ }
38
40
  </div>
39
41
  </div>
40
42
  <div class="right">
41
43
  <div class="switch-box ${isDisabled}">
42
- <input type="checkbox" hidden
44
+ <input
45
+ hidden
46
+ type="checkbox"
43
47
  id="s1-switch-${index}"
44
- ${isChecked()}
45
48
  data-name="${opt.key}"
49
+ ${isChecked()}
46
50
  >
47
- <label class="switch" for="s1-switch-${index}"></label>
51
+ <label
52
+ class="switch"
53
+ for="s1-switch-${index}"
54
+ ></label>
48
55
  </div>
49
56
  <div class="icon" data-open>
50
57
  <i class="icon-arrow"></i>
@@ -54,104 +61,197 @@ export const cookieStep1El = (opt, index, isDisabled, isChecked) => {
54
61
  `
55
62
  }
56
63
 
57
- export const cookieStep2TittleEl = (opt, index, isDisabled, isChecked) => {
64
+ // 第二步驟標題
65
+ export const cookieStep2TittleEl = (
66
+ opt,
67
+ index,
68
+ isDisabled,
69
+ isChecked
70
+ ) => {
58
71
  return `
59
- <div class="box">
60
- <div class="left">
61
- <div class="checkbox ${isDisabled}">
62
- <div class="input-wrap">
63
- <input type="checkbox"
64
- id="s2-check-${index}"
65
- ${isChecked()}
72
+ <div class="main-option ${isChecked()}">
73
+ <div class="box">
74
+ <div class="left">
75
+ <div class="checkbox ${isDisabled}">
76
+ <div class="input-wrap">
77
+ <input
78
+ type="checkbox"
79
+ id="s2-check-${index}"
80
+ data-name="${opt.key}"
81
+ ${isChecked()}
82
+ >
83
+ <div class="fake-checkbox">
84
+ <i class="icon-check"></i>
85
+ </div>
86
+ </div>
87
+ <label for="s2-check-${index}">
88
+ <span>${opt.title}</span>
89
+ </label>
90
+ </div>
91
+ </div>
92
+ <div class="right">
93
+ <div class="switch-box ${isDisabled}">
94
+ <input
95
+ hidden
96
+ type="checkbox"
97
+ id="s2-switch-${index}"
66
98
  data-name="${opt.key}"
99
+ ${isChecked()}
67
100
  >
68
- <div class="fake-checkbox">
69
- <i class="icon-check"></i>
70
- </div>
101
+ <label
102
+ class="switch"
103
+ for="s2-switch-${index}"
104
+ >
105
+ </label>
71
106
  </div>
72
- <label for="s2-check-${index}">
73
- <span>${opt.title}</span>
74
- </label>
75
107
  </div>
76
108
  </div>
77
- <div class="right">
78
- <div class="switch-box ${isDisabled}">
79
- <input type="checkbox" hidden
80
- id="s2-switch-${index}"
81
- ${isChecked()}
82
- data-name="${opt.key}"
83
- >
84
- <label class="switch" for="s2-switch-${index}"></label>
85
- </div>
109
+ <div class="desc">
110
+ <div class="text">${opt.text || ""}</div>
111
+ ${opt.notice ?
112
+ `<div class="notice">
113
+ <div class="icon">
114
+ <i class="icon-notice"></i>
115
+ </div>
116
+ <span>${opt.notice}</span>
117
+ </div> ` : ""
118
+ }
86
119
  </div>
87
120
  </div>
88
- <div class="desc">
89
- <div class="text">${opt.text || ""}</div>
90
- ${opt.notice ?
91
- `<div class="notice">
92
- <div class="icon">
93
- <i class="icon-notice"></i>
94
- </div>
95
- <span>${opt.notice}</span>
96
- </div> ` : ""}
97
- </div>
98
121
  `
99
122
  }
100
123
 
101
- export const cookieStep2DetailEl = (data, li, index, parentKey, num, isDisabled, isListChecked) => {
124
+ // 第二步驟內容大區塊
125
+ export const cookieStep2ContentEl = (
126
+ items,
127
+ cookieNewObj,
128
+ data,
129
+ opt
130
+ ) => {
131
+ if (!items.length > 0) return
132
+ const parentKey = opt.key
102
133
  return `
103
- <div class="list collapseItem" data-collapse>
134
+ ${items.map((item,num) =>
135
+ `
136
+ <div class="item">
137
+ <div class="list">
138
+ <div class="main">${item.main}</div>
139
+ <div class="text">${item.text}</div>
140
+ </div>
141
+ ${(item.list || []).map((li, index) =>
142
+ (li.detail && li.detail.length > 0) ?
143
+ cookieStep2ListCollapseEl(cookieNewObj,data, li, index, parentKey, num)
144
+ : `${cookieStep2ListNormalEl(cookieNewObj,data, opt,num,li, index,parentKey)}`
145
+ ).join("")}
146
+ </div>
147
+ `
148
+ ).join("")}
149
+ `
150
+ }
151
+
152
+ // 第二步驟細項目: 1. 有細項收合結構
153
+ export const cookieStep2ListCollapseEl = (
154
+ cookieNewObj,
155
+ data,
156
+ li,
157
+ index,
158
+ parentKey,
159
+ num
160
+ )=> {
161
+ const isDisabled = li.disabled ? " disabled" : ""
162
+ const isListChecked = cookieNewObj[parentKey].list[li.key].close == 0 ? "checked" : ""
163
+ return `
164
+ <div class="list collapseItem list-option ${isListChecked}" data-collapse>
104
165
  <div class="title collapseTitle" data-collapse-click>
105
166
  <div class="icon">
106
167
  <i class="icon-arrow"></i>
107
168
  </div>
108
169
  <span>${li.title || ""}</span>
109
- ${data.multiType ?
170
+ ${data.multiType ?
110
171
  `<div class="switch-box ${isDisabled}">
111
172
  <input
112
173
  type="checkbox"
113
174
  hidden
114
- id="s2-content-${num}-${index}"
115
- ${isListChecked}
175
+ id="s2-check-${num}-${index}"
116
176
  data-name="${li.key}"
117
177
  data-parent="${parentKey || ""}"
178
+ ${isListChecked}
118
179
  >
119
180
  <label
120
181
  class="switch"
121
- for="s2-content-${num}-${index}">
182
+ for="s2-check-${num}-${index}">
122
183
  </label>
123
- </div>`
124
- : ""
184
+ </div>` : ""
125
185
  }
126
186
  </div>
127
- ${li.text ?
128
- `<div class="text">${li.text}</div>`
129
- : ""
187
+ ${li.text ?
188
+ `<div class="text">${li.text}</div>` : ""
130
189
  }
131
190
  <div class="list-detail collapseBox" data-collapse-content>
132
191
  <div class="innerBox">
133
192
  <div class="content">
134
- ${li.detail?.length > 0 ?
193
+ ${li.detail?.length > 0 ?
135
194
  generateHtmlString(li.detail, (i) => {
136
195
  return `
137
196
  <div class="li">
138
- <div class="title">${i.title || ""}</div>
139
- ${i.text ?
140
- `<div class="text">${i.text}</div>`
141
- : ""
197
+ <div class="title">${i.title}</div>
198
+ ${i.text ?
199
+ `<div class="text">${i.text}</div>` : ""
142
200
  }
143
201
  <div class="flex">
144
- <div class="text bold">${i.typeTitle || ""}</div>
145
- <div class="text">${i.typeDesc || ""}</div>
202
+ <div class="text bold">${i.typeTitle}</div>
203
+ <div class="text">${i.typeDesc}</div>
146
204
  </div>
147
205
  </div>
148
- `
149
- })
150
- : ""
206
+ `
207
+ }) : ""
151
208
  }
152
209
  </div>
153
210
  </div>
154
211
  </div>
155
212
  </div>
156
213
  `
214
+ }
215
+
216
+ // 第二步驟細項目: 2. 無細項收合結構
217
+ export const cookieStep2ListNormalEl = (
218
+ cookieNewObj,
219
+ data,
220
+ opt,
221
+ num,
222
+ li,
223
+ index,
224
+ parentKey
225
+ ) => {
226
+ const isListChecked = cookieNewObj[parentKey].list[li.key].close == 0 ? "checked" : ""
227
+ return `
228
+ <div class="list list-option ${isListChecked}">
229
+ <div class="title">
230
+ ${li.title ?
231
+ `<span>${li.title}</span>` : ""
232
+ }
233
+ ${data.multiType && li.key.length > 0 ?
234
+ `<div class="switch-box ${opt.disabled ? "disabled" : ""}">
235
+ <input
236
+ hidden
237
+ type="checkbox"
238
+ id="s2-check-${num}-${index}"
239
+ data-name="${li.key}"
240
+ data-parent="${opt.key}"
241
+ ${cookieNewObj[opt.key]?.list[li.key]?.close == 0 ? "checked" : ""}
242
+ >
243
+ <label
244
+ class="switch"
245
+ for="s2-check-${num}-${index}"
246
+ >
247
+ </label>
248
+ </div>`
249
+ : ""
250
+ }
251
+ </div>
252
+ ${li.text ?
253
+ `<div class="text">${li.text}</div>` : ""
254
+ }
255
+ </div>
256
+ `
157
257
  }
@@ -8,17 +8,15 @@ import {
8
8
  import Cookies from "js-cookie";
9
9
  import { OverlayScrollbars } from 'overlayscrollbars';
10
10
  import { cookieData } from "./cookieData";
11
- import { cookieStep1El, cookieStep2TittleEl, cookieStep2DetailEl } from "./cookieElement"
11
+ import { cookieStep1El, cookieStep2TittleEl, cookieStep2ContentEl } from "./cookieElement"
12
12
 
13
13
  // 基礎版 cookie
14
14
  const cookieBasic = {}
15
15
  // 進階版 cookie
16
16
  const cookieAdvanced = {}
17
- // 存方法工具
18
17
  const cookieSetting = {}
19
- // 存結構
20
18
  const cookieElements = {}
21
- // 存一個空物件
19
+ // 設定一個預存空間
22
20
  let cookieNewObj = {};
23
21
 
24
22
  // 簡易版 cookie 設定
@@ -61,7 +59,6 @@ cookieBasic.basicCookiePolicy = () => {
61
59
  }
62
60
  });
63
61
 
64
- // ⚠️ 以下可斟酌移除
65
62
  // 開啟 cookie 視窗按鈕
66
63
  $("[data-cookie-open]").on("click", function() {
67
64
  $cookiePolicy.addClass("first-enter");
@@ -78,49 +75,6 @@ cookieBasic.basicCookiePolicy = () => {
78
75
  clickEvent();
79
76
  };
80
77
 
81
- // ⚠️ ** --- 結構這邊修改 --- ** ⚠️
82
- // step 1 結構
83
- cookieElements.getStep1Element = (opt, index) => {
84
- const isDisabled = opt.disabled ? "disabled" : ""
85
- const isChecked = () => {
86
- if (opt.key == "required") {
87
- return "checked"
88
- } else {
89
- if (cookieSetting.hasAnyListItemsOpen(opt.key)) {
90
- return "checked"
91
- } else {
92
- return ""
93
- }
94
- }
95
- }
96
- return cookieStep1El(opt, index, isDisabled, isChecked)
97
- }
98
-
99
- // step 2 上面結構
100
- cookieElements.getStep2TopElement = (opt, index) => {
101
- const isDisabled = opt.disabled ? "disabled" : ""
102
- const isChecked = () => {
103
- if (opt.key == "required") {
104
- return "checked"
105
- } else {
106
- if (cookieSetting.hasAnyListItemsOpen(opt.key)) {
107
- return "checked"
108
- } else {
109
- return ""
110
- }
111
- }
112
- }
113
- return cookieStep2TittleEl(opt, index, isDisabled, isChecked)
114
- }
115
-
116
- // step 2 下面細項結構
117
- cookieElements.getStep2BottomElement = (data, li, index, parentKey, num) => {
118
- const isDisabled = li.disabled ? " disabled" : ""
119
- const isListChecked = cookieNewObj[parentKey].list[li.key].close == 0 ? "checked" : ""
120
-
121
- return cookieStep2DetailEl(data, li, index, parentKey, num, isDisabled, isListChecked)
122
- }
123
-
124
78
  // 產生新物件
125
79
  cookieAdvanced.newObj = () => {
126
80
  if (Cookies.get('_wd') !== undefined) {
@@ -169,184 +123,164 @@ cookieAdvanced.newObj = () => {
169
123
  * @param {Array} target
170
124
  * @param {(opt: cookieData[0], index: number) => string} fn
171
125
  */
172
- cookieElements.generateHtmlString = (target, fn) => {
126
+ export const generateHtmlString = (target, fn) => {
173
127
  return target.map((data, index) => fn(data, index)).join("")
174
128
  }
175
129
 
176
130
  // 產資料結構
177
131
  cookieAdvanced.dataAppend = () => {
178
- const $block = $(".cookie-settingBlock")
132
+ const $block = $(".cookie-setting")
179
133
  if (!$block.length) return
180
134
 
181
- const data = $("#_wcookie").val() ? JSON.parse($("#_wcookie").val())[0] : cookieData[0]
182
- const $step1 = $(".setting-container[data-step='1']")
183
- const $step2 = $(".setting-container[data-step='2']")
135
+ const val = $("#_wcookie").val()
136
+ const data = val ? JSON.parse(val)[0] : cookieData[0]
137
+ const $step1 = $(".setting-container[t4-id='step1']")
138
+ const $step2 = $(".setting-container[t4-id='step2']")
184
139
 
185
140
  // 產 step1 結構
186
- $step1.find(".content-block").html(cookieElements.generateHtmlString(data.options, cookieElements.getStep1Element))
141
+ $step1.find(".content-block").html(
142
+ generateHtmlString(data.options, cookieElements.getStep1Element)
143
+ )
187
144
 
188
- // step2 點擊打開
189
- $("[data-open]").on("click", function () {
145
+ const step2OpenClick = function() {
190
146
  const index = $(this).closest(".item").data("index")
191
147
  const opt = data.options[index]
192
148
  const items = opt.data?.items || []
193
149
 
194
- // ⚠️ ** --- 結構這邊修改 --- ** ⚠️
195
- // 產 step2 下方結構
196
- const htmlStep2bottom = items.length > 0
197
- ? items.map((item,num) => `
198
- <div class="item">
199
- <div class="list">
200
- <div class="main">${item.main}</div>
201
- <div class="text">${item.text}</div>
202
- </div>
203
- ${
204
- (item.list || []).map((li, index) =>
205
- (li.detail && li.detail.length > 0) ?
206
- cookieElements.getStep2BottomElement(data, li, index, opt.key, num)
207
- : `
208
- <div class="list">
209
- <div class="title">
210
- <span>${li.title || ""}</span>
211
- ${data.multiType && li.key.length > 0 ?
212
- `<div class="switch-box ${opt.disabled ? "disabled" : ""}">
213
- <input type="checkbox" hidden
214
- id="s2-content-${num}-${index}"
215
- ${cookieNewObj[opt.key].list[li.key].close == 0 ? "checked" : ""}
216
- data-name="${li.key}"
217
- data-parent="${opt.key || ""}"
218
- >
219
- <label class="switch" for="s2-content-${num}-${index}"></label>
220
- </div>`
221
- : ""
222
- }
223
- </div>
224
- <div class="text">${li.text || ""}</div>
225
- </div>
226
- `
227
- ).join("")
228
- }
229
- </div>
230
- `).join("")
231
- : `<div class="item"><div class="text">此分類目前沒有詳細資料。</div></div>`
232
-
233
150
  // 產 step2 上方結構
234
- $step2.find(".top-block").html(cookieElements.getStep2TopElement(opt, index))
151
+ $step2.find(".top-block").html(
152
+ cookieElements.getStep2TopElement(opt, index)
153
+ )
235
154
  // 產 step2 下方結構
236
- $step2.find(".content-block").html(htmlStep2bottom)
237
-
155
+ $step2.find(".content-block").html(
156
+ cookieStep2ContentEl(items,cookieNewObj,data,opt)
157
+ )
238
158
  // 換頁
239
- methods.pageChange(true)
159
+ document.body.fesd.cookieGoToNext();
240
160
  // 重綁收合
241
- methods.collapseEvent('[data-collapse-click]', '[data-collapse]', '[data-collapse-content]', false, true)
242
- })
161
+ methods.collapseEvent(
162
+ '[data-collapse-click]',
163
+ '[data-collapse]',
164
+ '[data-collapse-content]',
165
+ false,
166
+ true
167
+ )
168
+ }
169
+ // step2 點擊打開
170
+ $step1.off('click.step2Open', '[data-open]').on('click.step2Open', '[data-open]', step2OpenClick)
243
171
  }
244
172
 
245
173
  // switch 的一些狀態
246
174
  cookieAdvanced.switchState = () => {
247
- const $step2contentSwitch = `[data-step="2"] .content-block input[type="checkbox"][data-parent][data-name]:not(.disabled)`
248
- const $step2topSwitch = `[data-step="2"] .top-block input[type="checkbox"][data-name]:not(.disabled)`
175
+ const $step2 = $(".setting-container[t4-id='step2']")
176
+ const $step2contentSwitch = `[t4-id='step2'] .content-block input[type="checkbox"][data-parent][data-name]:not(.disabled)`
177
+ const $step2topSwitch = `[t4-id='step2'] .top-block input[type="checkbox"][data-name]:not(.disabled)`
249
178
 
250
179
  let isSyncing = false
251
180
 
252
181
  // 開關同步連動控制
253
- // ⚠️ 若只有一顆控制按鈕, 可關閉
254
- $(document).on('change', 'input[type="checkbox"][data-name]:not(:disabled)', function () {
255
- const key = $(this).data('name')
256
- const val = $(this).prop('checked')
182
+ $(document).off('change.switch').on('change.switch', 'input[type="checkbox"][data-name]:not(:disabled)', function () {
257
183
  if (isSyncing) return
258
184
  isSyncing = true
259
185
 
186
+ const $this = $(this)
187
+ const key = $this.data('name')
188
+ const val = $this.prop('checked')
189
+
260
190
  $(`input[type="checkbox"][data-name="${key}"]`).not(this).prop('checked', val)
261
-
191
+ if (!val) {
192
+ $($this).parents(".main-option,.list-option").removeClass("checked")
193
+ } else {
194
+ $($this).parents(".main-option,.list-option").addClass("checked")
195
+ }
262
196
  isSyncing = false
263
197
  })
264
198
 
265
199
  // step1 變動 → 更新 cookieNewObj
266
- $(document)
267
- .off('change.cookieStep1')
268
- .on('change.cookieStep1', `[data-step="1"] input[type="checkbox"][data-name]`, function () {
269
- if (isSyncing) return
270
- isSyncing = true
271
-
272
- const key = $(this).data("name")
273
- const val = $(this).prop('checked') ? 0 : 1
274
- if (cookieNewObj[key]) {
275
- cookieNewObj[key].close = val
276
- const targetList = cookieNewObj[key].list;
277
- if (targetList && typeof targetList === 'object') {
278
- Object.keys(targetList).forEach(childKey => {
279
- if (targetList[childKey].close !== undefined) {
280
- targetList[childKey].close = val;
281
- }
282
- });
283
- }
284
- }
285
-
286
- isSyncing = false
287
- })
200
+ $(document).off('change.cookieStep1').on('change.cookieStep1', `[t4-id='step1'] input[type="checkbox"][data-name]`, function () {
201
+ if (isSyncing) return
202
+ isSyncing = true
288
203
 
289
- $(document)
290
- .off("change.step2content")
291
- .on("change.step2content", $step2contentSwitch, function () {
204
+ const $this = $(this)
205
+ const key = $this.data("name")
206
+ const val = $this.prop('checked') ? 0 : 1
207
+
208
+ if (cookieNewObj[key]) {
209
+ cookieNewObj[key].close = val
210
+ const targetList = cookieNewObj[key].list;
211
+ if (targetList && typeof targetList === 'object') {
212
+ Object.keys(targetList).forEach(childKey => {
213
+ if (targetList[childKey].close !== undefined) {
214
+ targetList[childKey].close = val;
215
+ }
216
+ });
217
+ }
218
+ }
219
+ isSyncing = false
220
+ })
292
221
 
293
- if (isSyncing) return
294
- isSyncing = true
222
+ $(document).off("change.step2content").on("change.step2content", $step2contentSwitch, function () {
223
+ if (isSyncing) return
224
+ isSyncing = true
295
225
 
296
- const key = $(this).data("name")
297
- const parent = $(this).data("parent")
298
- const val = $(this).prop('checked') ? 0 : 1
299
- const $step1Switch = $(`[data-step="1"] input[type="checkbox"][data-name='${parent}']:not(.disabled)`)
300
- const total = $($step2contentSwitch).length
301
- const checked = $($step2contentSwitch).filter(':checked').length
226
+ const $step1Switch = $(`[t4-id='step1'] input[type="checkbox"][data-name='${parent}']:not(.disabled)`)
227
+ const key = $(this).data("name")
228
+ const parent = $(this).data("parent")
229
+ const val = $(this).prop('checked') ? 0 : 1
230
+ const total = $($step2contentSwitch).length
231
+ const checked = $($step2contentSwitch).filter(':checked').length
232
+
233
+ // 改變 cookieNewObj 的值
234
+ cookieNewObj[parent].list[key].close = val
235
+
236
+ // Step2 子項全部打開
237
+ if (checked === total || checked > 0) {
238
+ cookieNewObj[parent].close = 0
239
+ $($step2topSwitch).prop("checked", true)
240
+ $step1Switch.prop("checked", true)
241
+ $step2.find(".main-option").addClass("checked")
242
+ }
243
+
244
+ // Step2 子項全部關閉
245
+ else if (checked === 0) {
246
+ cookieNewObj[parent].close = 1
247
+ $($step2topSwitch).prop("checked", false)
248
+ $step1Switch.prop("checked", false)
249
+ $step2.find(".main-option").removeClass("checked")
250
+ }
302
251
 
303
- // 改變 cookieNewObj 的值
304
- cookieNewObj[parent].list[key].close = val
252
+ isSyncing = false
253
+ })
305
254
 
306
- // Step2 子項全部打開
307
- if (checked === total || checked > 0) {
308
- cookieNewObj[parent].close = 0
309
- $($step2topSwitch).prop("checked", true)
310
- $step1Switch.prop("checked", true)
311
- }
312
-
313
- // Step2 子項全部關閉
314
- else if (checked === 0) {
315
- cookieNewObj[parent].close = 1
316
- $($step2topSwitch).prop("checked", false)
317
- $step1Switch.prop("checked", false)
318
- }
255
+ $(document).off("change.step2top").on("change.step2top", $step2topSwitch, function () {
256
+ if (isSyncing) return
257
+ isSyncing = true
319
258
 
320
- isSyncing = false
321
- })
259
+ const $this = $(this)
260
+ const key = $this.data("name")
261
+ const isChecked = $this.prop("checked")
262
+ const detectVal = $this.prop('checked')
263
+ const val = isChecked ? 0 : 1
322
264
 
323
- $(document)
324
- .off("change.step2top")
325
- .on("change.step2top", $step2topSwitch, function () {
326
-
327
- if (isSyncing) return
328
- isSyncing = true
329
-
330
- const key = $(this).data("name")
331
- const isChecked = $(this).prop("checked")
332
- const val = isChecked ? 0 : 1
333
-
334
- // 改所有子項
335
- $($step2contentSwitch)
336
- .prop('checked', isChecked)
337
-
338
- // 改 cookie main
339
- if (cookieNewObj[key]) {
340
- const list = cookieNewObj[key].list
341
- cookieNewObj[key].close = val
342
- if (list) {
343
- Object.keys(list).forEach(childKey => {
344
- list[childKey].close = val
345
- })
346
- }
265
+ // 改所有子項
266
+ $($step2contentSwitch).prop('checked', isChecked)
267
+ if (!detectVal) {
268
+ $step2.find(".list-option").removeClass("checked")
269
+ } else {
270
+ $step2.find(".list-option").addClass("checked")
271
+ }
272
+ // cookie main
273
+ if (cookieNewObj[key]) {
274
+ const list = cookieNewObj[key].list
275
+ cookieNewObj[key].close = val
276
+ if (list) {
277
+ Object.keys(list).forEach(childKey => {
278
+ list[childKey].close = val
279
+ })
347
280
  }
348
- isSyncing = false
349
- })
281
+ }
282
+ isSyncing = false
283
+ })
350
284
  }
351
285
 
352
286
  // 存 cookie
@@ -371,42 +305,18 @@ cookieAdvanced.cookieSaveFn = () => {
371
305
 
372
306
  // 點擊方法
373
307
  cookieAdvanced.clickEvent = () => {
374
- const $settingBtn = $(".cookie-settingBtn")
375
- const $settingBlock = $(".cookie-settingBlock")
376
-
377
- // 打開進階版 cookie 介面
378
- $settingBtn.on("click", () => {
379
- cookieSetting.openEvent($settingBlock)
380
- });
308
+ const $settingBtn = $(".cookie-setting-btn")
309
+ const $settingBlock = $(".cookie-setting")
381
310
 
382
- // 一鍵全開
383
- cookieSetting.enableAll = () => {
384
- $(`input[type="checkbox"][data-name]:not(.disabled)`).prop('checked', true).trigger('change')
385
- cookieNewObj.close = 0
386
- Object.keys(cookieNewObj).forEach(data => {
387
- cookieNewObj[data].close == 0
388
- })
389
- }
390
- // 一鍵全關
391
- cookieSetting.rejectAll = () => {
392
- $(`input[type="checkbox"][data-name]:not([data-name="required"])`).prop('checked', false).trigger('change')
393
- cookieNewObj.close = 1
394
- Object.keys(cookieNewObj).forEach(data => {
395
- cookieNewObj[data].close == 1
396
- })
397
- }
311
+ // 打開進階版 cookie 介面
312
+ $settingBtn.on("click", () => cookieSetting.openEvent($settingBlock));
398
313
  // 綁定按鈕
399
- $("[data-cookie-all]").on('click', function(){
400
- cookieSetting.enableAll()
401
- })
314
+ $("[data-cookie-all]").on('click', cookieSetting.enableAll)
402
315
  // 儲存
403
- $("[data-cookie-save]").on('click', function(){
404
- cookieAdvanced.cookieSaveFn()
405
- })
316
+ $("[data-cookie-save]").on('click', cookieAdvanced.cookieSaveFn)
406
317
  // 關閉視窗
407
- $("[data-cookie-close]").on('click', function(){
408
- cookieSetting.closeEvent($settingBlock)
409
- })
318
+ $("[data-cookie-close]").on('click', () => cookieSetting.closeEvent($settingBlock))
319
+ // 我拒絕
410
320
  $("[data-cookie-reject]").on('click', function() {
411
321
  cookieSetting.rejectAll()
412
322
  cookieAdvanced.cookieSaveFn()
@@ -420,10 +330,11 @@ cookieSetting.openEvent = (el) => {
420
330
  setTimeout(() => {
421
331
  $(el).addClass("show")
422
332
  scrollLock();
423
- const scrollers = $(".cookie-settingBlock").find('.scroller')[0]
333
+ const scrollers = $(".cookie-setting").find('.scroller')[0]
424
334
  OverlayScrollbars(scrollers, {})
425
335
  }, 500);
426
336
  }
337
+
427
338
  // cookie 關閉方法
428
339
  cookieSetting.closeEvent = (el) => {
429
340
  $(el).removeClass("show")
@@ -432,6 +343,27 @@ cookieSetting.closeEvent = (el) => {
432
343
  scrollUnlock();
433
344
  }, 500);
434
345
  }
346
+
347
+ // 全部打開
348
+ cookieSetting.enableAll = () => {
349
+ $(`input[type="checkbox"][data-name]:not(.disabled)`).prop('checked', true).trigger('change')
350
+ $('.main-option:not([data-name="required"]),.list-option:not([data-name="required"])').addClass("checked")
351
+ cookieNewObj.close == 0
352
+ Object.keys(cookieNewObj).forEach(data => {
353
+ cookieNewObj[data].close == 0
354
+ })
355
+ }
356
+
357
+ // 一鍵全關
358
+ cookieSetting.rejectAll = () => {
359
+ $(`input[type="checkbox"][data-name]:not([data-name="required"])`).prop('checked', false).trigger('change')
360
+ $('.main-option:not([data-name="required"]),.list-option:not([data-name="required"])').removeClass("checked")
361
+ cookieNewObj.close = 1
362
+ Object.keys(cookieNewObj).forEach(data => {
363
+ cookieNewObj[data].close = 1
364
+ })
365
+ }
366
+
435
367
  // 判斷該分類底下細項按鈕狀態
436
368
  cookieSetting.hasAnyListItemsOpen = (key) => {
437
369
  const targetList = cookieNewObj[key]?.list;
@@ -449,6 +381,57 @@ cookieSetting.hasAnyListItemsOpen = (key) => {
449
381
  return isOpen;
450
382
  };
451
383
 
384
+ // step 1 結構
385
+ cookieElements.getStep1Element = (opt, index) => {
386
+ const isDisabled = opt.disabled ? "disabled" : ""
387
+ const isChecked = () => {
388
+ if (opt.key == "required") {
389
+ return "checked"
390
+ } else {
391
+ if (cookieSetting.hasAnyListItemsOpen(opt.key)) {
392
+ return "checked"
393
+ } else {
394
+ return ""
395
+ }
396
+ }
397
+ }
398
+ return cookieStep1El(opt, index, isDisabled, isChecked)
399
+ }
400
+ // step 2 上面結構
401
+ cookieElements.getStep2TopElement = (opt, index) => {
402
+ const isDisabled = opt.disabled ? "disabled" : ""
403
+ const isChecked = () => {
404
+ if (opt.key == "required") {
405
+ return "checked"
406
+ } else {
407
+ if (cookieSetting.hasAnyListItemsOpen(opt.key)) {
408
+ return "checked"
409
+ } else {
410
+ return ""
411
+ }
412
+ }
413
+ }
414
+ return cookieStep2TittleEl(opt, index, isDisabled, isChecked)
415
+ }
416
+
417
+ // 頁籤
418
+ cookieSetting.goToTab = (el = true) => {
419
+ const tab = $('tab-el[t4-name="cookie-tab"]')
420
+ const $step2 = $(".setting-container[t4-id='step2']")
421
+ if (el) {
422
+ tab[0].goNext();
423
+ } else {
424
+ tab[0].goPrev();
425
+ $step2.find(".top-block, .content-block").empty();
426
+ }
427
+ }
428
+
429
+ methods.toBackend({
430
+ getCookieValue: (el) => Cookies.get(el),
431
+ cookieGoToNext: (el) => cookieSetting.goToTab(el),
432
+ });
433
+
434
+ // init
452
435
  cookieAdvanced.init = () => {
453
436
  cookieAdvanced.newObj();
454
437
  cookieAdvanced.dataAppend();
@@ -458,8 +441,7 @@ cookieAdvanced.init = () => {
458
441
  cookieAdvanced.switchState();
459
442
  }
460
443
 
461
- methods.toBackend({ getCookieValue: (el) => Cookies.get(el) });
462
-
444
+ // 預設為 false -> 基礎版, true -> 進階版
463
445
  export const init = (isOpenAdvanced = false) => {
464
446
  // cookie 基本版
465
447
  cookieBasic.basicCookiePolicy();
@@ -11,7 +11,7 @@ import {
11
11
  scrollLock,
12
12
  scrollUnlock
13
13
  } from '@xwadex/fesd/tools';
14
- import { toBackend, pageChange } from "@/commons/methods";
14
+ import { toBackend } from "@/commons/methods";
15
15
  import { cookie } from "@/commons";
16
16
  import { lazyLoadImg } from '@/plugins';
17
17
  import { navbar } from '@/ui';
@@ -39,19 +39,22 @@ firstEntryHandler.init = () => {
39
39
  firstEntryHandler.active()
40
40
  }
41
41
 
42
- toBackend({ scrollLock, scrollUnlock, pageChange: (el) => pageChange(el) });
42
+ toBackend({ scrollLock, scrollUnlock });
43
43
 
44
44
  export const inits = () => {
45
45
  // commonInit
46
46
  bodyScrollbarInit();
47
47
  appleDebug();
48
48
  fixMobile100vh();
49
- cgpagechange();
49
+ // 預設為 true -> 無幽靈區塊(以 href-link 為主), false -> 整區塊可觸發點擊(click-block 功能啟動)
50
+ // 詳情可見 a & hover 規範文件
51
+ cgpagechange(true);
50
52
  // pluginInit
51
53
  lazyLoadImg();
52
54
  new ImageValidate();
53
55
  // uiInit
54
56
  navbar.init();
57
+ // 預設為 false -> 基礎版, true -> 進階版
55
58
  cookie.init(true);
56
59
  // coding...
57
60
  firstEntryHandler.init();
@@ -45,32 +45,3 @@ export function noContentCheck() {
45
45
  noContentBox.show();
46
46
  }
47
47
  }
48
-
49
- export const pageChange = (type = true) => {
50
- const $step = $('[step-active]')
51
- let step = Number($step.attr('step-active'));
52
-
53
- if (type) step += 1
54
- else step -= 1
55
-
56
- step = step < 1 ? 1 : step > 3 ? 3 : step
57
- // step = Math.max(1, Math.min(3, step));
58
-
59
- $step.attr('step-active', step);
60
-
61
- // 移除 show class
62
- $('[data-step]').removeClass('show');
63
- // data-step 監聽 transitionend
64
- $('[data-step]').off('transitionend webkitTransitionEnd oTransitionEnd').on('transitionend webkitTransitionEnd oTransitionEnd', function () {
65
- const $this = $(this);
66
-
67
- if (!$this.hasClass('show')) {
68
- $this.removeClass('active');
69
-
70
- $(`[data-step="${step}"]`).addClass('active');
71
- setTimeout(() => {
72
- $(`[data-step="${step}"]`).addClass('show');
73
- }, 100)
74
- }
75
- });
76
- }
@@ -17,9 +17,9 @@ html(lang="zh-Hant-TW" data-overlayscrollbars-initialize)
17
17
  block fontSheet
18
18
  link(rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Afacad:ital,wght@0,400..700;1,400..700&family=Jost:ital,wght@0,100..900;1,100..900&family=Outfit:wght@100..900&family=Noto+Sans+TC:wght@100..900&display=swap")
19
19
  // 共用樣式
20
+ link(rel="stylesheet", href="/src/assets/css/tailwind.css")
20
21
  link(rel="stylesheet", href="/assets/fonts/icomoon/style.css")
21
22
  link(rel="stylesheet", href="/src/assets/css/style.sass")
22
- link(rel="stylesheet", href="/src/assets/css/tailwind.css")
23
23
  // 個別頁面 CSS
24
24
  block stylesheet
25
25
  // 主頁面 CSS
@@ -6,35 +6,41 @@
6
6
  p.title Cookie
7
7
  p.text 關於本網站使用瀏覽器紀錄 Cookie 來提供您最好的使用體驗,我們使用的 Cookie 也包括了第三方 Cookie 。<br>相關資訊請訪問我們的隱私權與 Cookie 政策。如果您選擇繼續瀏覽或關閉這個提示,便表示您已接受我們的網站使用條款。
8
8
  .button-group
9
+ // [data-cookie-reject] -> 全部關閉; [data-cookie-save] -> 儲存 cookie
9
10
  .cookie-btn.close(data-cookie-reject) Reject 我拒絕
10
11
  .cookie-btn.agree(data-cookie-save) OK 我接受
11
- .cookie-settingBtn
12
+ // 若此專案無開進階版 cookie, 請移除以下結構!
13
+ .cookie-setting-btn
12
14
  span Cookie 偏好設定
13
15
  .icon
14
16
  i.icon-arrow
15
17
 
16
18
  // 進階版 cookie
17
- .cookie-settingBlock
19
+ // 若此專案無開進階版 cookie, 請移除以下結構!
20
+ .cookie-setting
18
21
  .scroller
19
- .setting-main(step-active="1")
20
- .setting-container.show.active(data-step="1")
21
- .title-block
22
- .title 您的 Cookie 偏好設定
23
- .text 我們使用不同類型的 Cookies 來優化您在我們的網站上的體驗,點擊下面類別以了解其目的與更多訊息。<br>您可以選擇允許的 Cookies 類型,也可以隨時更改您的偏好設定。<br>提醒您,停用 Cookies 可能會影響您在網站上的體驗,您可以瀏覽我們的隱私權政策,進一步了解我們如何使用 Cookie。
24
- .content-block
25
- // JS append 結構
26
- .button-group
27
- .cookie-btn.open(data-cookie-all) 啟用所有 Cookie
28
- .cookie-btn.save(data-cookie-close) SAVE 儲存本次變更
29
- .setting-container(data-step="2")
30
- .back(onclick="document.body.fesd.pageChange(false)")
31
- .icon
32
- i.icon-arrow
33
- span BACK
34
- .top-block
35
- // JS append 結構
36
- .content-block
37
- // JS append 結構
38
-
39
- // 後端 cookie 資料放這兒
40
- input(input type="hidden" id="_wcookie" value='')
22
+ .setting-main
23
+ tab-el(t4-name="cookie-tab" t4-type="process" t4-group='false')
24
+ // 步驟 1
25
+ .setting-container(t4-role="tabPanel" t4-id='step1')
26
+ .title-block
27
+ .title 您的 Cookie 偏好設定
28
+ .text 我們使用不同類型的 Cookies 來優化您在我們的網站上的體驗,點擊下面類別以了解其目的與更多訊息。<br>您可以選擇允許的 Cookies 類型,也可以隨時更改您的偏好設定。<br>提醒您,停用 Cookies 可能會影響您在網站上的體驗,您可以瀏覽我們的隱私權政策,進一步了解我們如何使用 Cookie。
29
+ .content-block
30
+ // JS append 結構 (cookieStep1El)
31
+ .button-group
32
+ .cookie-btn.open(data-cookie-all) 啟用所有 Cookie
33
+ .cookie-btn.save(data-cookie-close) SAVE 儲存本次變更
34
+ // 步驟 2
35
+ .setting-container(t4-role="tabPanel" t4-id='step2')
36
+ .back(onClick=`document.body.fesd.cookieGoToNext(false)`)
37
+ .icon
38
+ i.icon-arrow
39
+ span BACK
40
+ .top-block
41
+ // JS append 結構 (cookieStep2TittleEl)
42
+ .content-block
43
+ // JS append 結構 (cookieStep2ContentEl)
44
+ // 後端 cookie 資料放這兒, 先放假結構
45
+ // 若此專案無開進階版 cookie, 請移除以下結構!
46
+ input(type="hidden" id="_wcookie" value='')
@@ -79,7 +79,7 @@ block content
79
79
  h3 Video4 👇
80
80
  .row
81
81
  .grid
82
- .photo-box(video-target video-id="" video-type="youtube")
82
+ .photo-box(video-target video-id="5bMdjkfvONE" video-type="youtube")
83
83
  picture
84
84
  source(srcset="https://cdn.wdd.idv.tw/image/video-cover01.webp" type="image/webp")
85
85
  source(srcset="https://cdn.wdd.idv.tw/image/video-cover01.jpg" type="image/jpeg")