add legacy support of checkbox, add documents for cookie/lgres/request

This commit is contained in:
Tsanie Lily 2023-03-31 00:11:55 +08:00
parent 5406eea20e
commit 45ae222d25
13 changed files with 222 additions and 18 deletions

View File

@ -8,6 +8,7 @@
<title>UI Lib</title> <title>UI Lib</title>
<script type="module" src="/main.js"></script> <script type="module" src="/main.js"></script>
<script src="/dist/ui.min.js"></script> <script src="/dist/ui.min.js"></script>
<script src="/dist/utility.min.js"></script>
</head> </head>
<body> <body>

View File

@ -10,4 +10,4 @@ interface CheckboxOptions {
} }
export function createCheckbox(opts?: CheckboxOptions): HTMLElement export function createCheckbox(opts?: CheckboxOptions): HTMLElement
export function resolveCheckbox(container: HTMLElement): HTMLElement export function resolveCheckbox(container: HTMLElement, legacy?: boolean): HTMLElement

View File

@ -54,18 +54,23 @@
复选框改变时触发的事件 复选框改变时触发的事件
</p> </p>
<h2>resolveCheckbox</h2> <h2>resolveCheckbox</h2>
<code>function resolveCheckbox(container: HTMLElement): HTMLElement</code> <code>function resolveCheckbox(container: HTMLElement, legacy?: boolean): HTMLElement</code>
<h3>container: HTMLElement</h3> <h3>container: HTMLElement</h3>
<p> <p>
将把此 HTML 元素下的所有 <code>label[data-checkbox]</code> 元素解析为复选框,<code>[data-id]</code> 为复选框元素的 id包含 将把此 HTML 元素下的所有 <code>label[data-checkbox]</code> 元素解析为复选框,<code>[data-id]</code> 为复选框元素的 id包含
<code>[data-checked]</code> 时复选框默认选中。</p> <code>[data-checked]</code> 时复选框默认选中。
</p>
<p>当该元素无子元素时,<code>[data-type]</code> 同上述参数中的 <code>type?: string</code><code>[data-label]</code> 同上述参数中的 <p>当该元素无子元素时,<code>[data-type]</code> 同上述参数中的 <code>type?: string</code><code>[data-label]</code> 同上述参数中的
<code>label?: string</code> <code>label?: string</code>
</p> </p>
<p>当该元素有子元素时解析为图片复选框class 为 <code>checked</code><code>unchecked</code> 的子元素将分别在选中与未选中时显示。</p> <p>当该元素有子元素时解析为图片复选框class 为 <code>checked</code><code>unchecked</code> 的子元素将分别在选中与未选中时显示。</p>
<h3>legacy?: boolean</h3>
<p>
是否开启兼容模式,启用兼容模式时将试图匹配 <code>input[type="checkbox"]</code> 标签,与其周围的 label将其转换为统一样式的复选框。
</p>
<hr />
<h2>示例</h2> <h2>示例</h2>
<pre> <pre>&lt;div id="checkbox-sample"&gt;
&lt;div id="checkbox-sample"&gt;
&lt;label data-checkbox data-type="fa-light" data-label="Checkbox Light"&gt;&lt;/label&gt; &lt;label data-checkbox data-type="fa-light" data-label="Checkbox Light"&gt;&lt;/label&gt;
&lt;label data-checkbox data-checked data-label="Checkbox Regular"&gt;&lt;/label&gt; &lt;label data-checkbox data-checked data-label="Checkbox Regular"&gt;&lt;/label&gt;
&lt;label data-checkbox data-type="fa-solid" data-label="Checkbox Solid"&gt;&lt;/label&gt; &lt;label data-checkbox data-type="fa-solid" data-label="Checkbox Solid"&gt;&lt;/label&gt;
@ -73,10 +78,12 @@
&lt;code class="checked"&gt;Checked&lt;/code&gt; &lt;code class="checked"&gt;Checked&lt;/code&gt;
&lt;code class="unchecked"&gt;Unchecked&lt;/code&gt; &lt;code class="unchecked"&gt;Unchecked&lt;/code&gt;
&lt;/label&gt; &lt;/label&gt;
&lt;input id="check-status" type="checkbox"/&gt;
&lt;label for="check-status"&gt;Label for Status&lt;/label&gt;
&lt;/div&gt; &lt;/div&gt;
&lt;script type="text/javascript"&gt; &lt;script type="text/javascript"&gt;
window["lib-ui"].resolveCheckbox(document.querySelector("#checkbox-sample")); window["lib-ui"].resolveCheckbox(document.querySelector("#checkbox-sample"), true);
&lt;/script&gt;</pre> &lt;/script&gt;</pre>
<div id="checkbox-sample"> <div id="checkbox-sample">
<label data-checkbox data-type="fa-light" data-label="Checkbox Light"></label> <label data-checkbox data-type="fa-light" data-label="Checkbox Light"></label>
@ -86,8 +93,10 @@
<code class="checked">Checked</code> <code class="checked">Checked</code>
<code class="unchecked">Unchecked</code> <code class="unchecked">Unchecked</code>
</label> </label>
<input id="check-status" type="checkbox" />
<label for="check-status">Label for Status</label>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
window["lib-ui"].resolveCheckbox(document.querySelector("#checkbox-sample")); window["lib-ui"].resolveCheckbox(document.querySelector("#checkbox-sample"), true);
</script> </script>
</div> </div>

View File

@ -49,7 +49,40 @@ function createCheckbox(opts) {
return container; return container;
} }
function resolveCheckbox(container) { function resolveCheckbox(container, legacy) {
if (legacy) {
const checks = container.querySelectorAll('input[type="checkbox"]');
for (let chk of checks) {
const id = chk.id;
let label;
if (id != null) {
label = container.querySelector(`label[for="${id}"]`);
}
if (label == null) {
const e = chk.nextElementSibling;
if (e != null && e.tagName === 'LABEL') {
label = e;
}
}
if (label == null) {
const e = chk.previousElementSibling;
if (e != null && e.tagName === 'LABEL') {
label = e;
}
}
let text;
if (label == null) {
label = document.createElement('label');
chk.parentElement.insertBefore(label, chk);
} else {
text = label.innerText;
}
label.className = 'checkbox-wrapper';
label.replaceChildren();
fillCheckbox(label, 'fa-regular', text);
label.insertBefore(chk, label.firstChild);
}
}
const boxes = container.querySelectorAll('label[data-checkbox]'); const boxes = container.querySelectorAll('label[data-checkbox]');
for (let box of boxes) { for (let box of boxes) {
if (!box.classList.contains('checkbox-wrapper')) { if (!box.classList.contains('checkbox-wrapper')) {

View File

@ -24,9 +24,9 @@
同上述 <code>id: string</code><code>[data-type]</code> 同上述 同上述 <code>id: string</code><code>[data-type]</code> 同上述
<code>type: string</code> <code>type: string</code>
</p> </p>
<hr />
<h2>示例</h2> <h2>示例</h2>
<pre> <pre>&lt;div id="icon-sample"&gt;
&lt;div id="icon-sample"&gt;
&lt;svg data-id="address-card" data-type="fa-regular"&gt;&lt;/svg&gt; &lt;svg data-id="address-card" data-type="fa-regular"&gt;&lt;/svg&gt;
&lt;svg data-id="user-edit" data-type="fa-light"&gt;&lt;/svg&gt; &lt;svg data-id="user-edit" data-type="fa-light"&gt;&lt;/svg&gt;
&lt;svg data-id="frog" data-type="fa-solid"&gt;&lt;/svg&gt; &lt;svg data-id="frog" data-type="fa-solid"&gt;&lt;/svg&gt;

View File

@ -20,9 +20,9 @@
<p> <p>
给此元素下的所有含有 title 属性的子元素设置成统一样式的 tooltip 给此元素下的所有含有 title 属性的子元素设置成统一样式的 tooltip
</p> </p>
<hr />
<h2>示例</h2> <h2>示例</h2>
<pre> <pre>&lt;div id="tooltip-sample"&gt;
&lt;div id="tooltip-sample"&gt;
&lt;blockquote title="From MDN Website"&gt;To send an HTTP request, create an XMLHttpRequest object, open a URL, and &lt;blockquote title="From MDN Website"&gt;To send an HTTP request, create an XMLHttpRequest object, open a URL, and
send the request. After the transaction completes, the object will contain useful information such as the send the request. After the transaction completes, the object will contain useful information such as the
response body and the HTTP status of the result.&lt;/blockquote&gt; response body and the HTTP status of the result.&lt;/blockquote&gt;

40
lib/utility/cookie.html Normal file
View File

@ -0,0 +1,40 @@
<div>
<h1>cookie</h1>
<hr />
<p>
cookie 操作工具类:获取、设置、删除。
</p>
<h2>getCookie</h2>
<code>function getCookie(name: string): string</code>
<h3>name: string</h3>
<p>
待获取的 cookie 关键字
</p>
<h2>setCookie</h2>
<code>function setCookie(name: string, value: string, expireDays?: Number): void</code>
<h3>name: string</h3>
<p>
待设置的 cookie 关键字
</p>
<h3>value: string</h3>
<p>
待设置的值
</p>
<h3>expireDays?: Number</h3>
<p>
有效期天数
</p>
<h2>deleteCookie</h2>
<code>function deleteCookie(name: string): void</code>
<h3>name: string</h3>
<p>
待删除的 cookie 关键字
</p>
<hr />
<h2>用法</h2>
<pre>const cookie = window["lib-utility"];
cookie.getCookie('user_id');
cookie.setCookie('user_id', 'guest');
cookie.deleteCookie('user_id');</pre>
</div>

View File

@ -3,7 +3,11 @@ interface LgresOptions {
callback?: (result: any) => void callback?: (result: any) => void
} }
export function init(dom?: HTMLElement, options?: LgresOptions): Promise<any> interface LanguageResource {
r(key: string, defaultValue?: any): any
}
export function init(dom?: HTMLElement, options?: LgresOptions): Promise<LanguageResource>
export function r(key: string, defaultValue?: any): any export function r(key: string, defaultValue?: any): any
export const lang: { export const lang: {
get current(): string, get current(): string,

74
lib/utility/lgres.html Normal file
View File

@ -0,0 +1,74 @@
<div>
<h1>lgres</h1>
<hr />
<p>
语言资源工具类,用以设置页面以及脚本中的多语言。
</p>
<h2>r</h2>
<code>function r(key: string, defaultValue?: any): any</code>
<h3>key: string</h3>
<p>
语言资源的关键字
</p>
<h3>defaultValue?: any</h3>
<p>
资源的默认值,如无法获取该语言资源,则返回该值
</p>
<h2>lang</h2>
<code>const lang : {}</code>
<h3>get current(): string</h3>
<p>
返回当前语言 id
</p>
<h3>get unknownError(): string</h3>
<p>
未知错误的语言资源,默认为 <code>'An unknown error occurred, please contact the administrator.'</code>
</p>
<h3>get savedSuccessfully(): string</h3>
<p>
保存成功的语言资源,默认为 <code>'Saved successfully.'</code>
</p>
<h2>init</h2>
<code>function init(dom?: HTMLElement, options?: LgresOptions): Promise&lt;LanguageResource&gt;</code>
<h3>dom?: HTMLElement</h3>
<p>
待处理的元素,为空时处理整个页面
</p>
<h3>options?: LgresOptions</h3>
<p>
初始化参数,结构为
<pre>interface LgresOptions {
template?: string,
callback?: (result: any) => void
}</pre>
</p>
<h3>template?: string</h3>
<p>
语言资源文件的后缀,资源文件 url 为 <code>`language/${lgid}${template}`</code>
</p>
<h3>callback?: (result: any) => void</h3>
<p>
资源初始化后的回调函数,可能在 DOM 加载完成之前触发。
</p>
<h3>return: Promise&lt;LanguageResource&gt;</h3>
<p>
返回一个包含资源结果的 Promise将在 DOM 加载完成之后触发。
</p>
<p><code>LanguageResource</code> 结构为
<pre>interface LanguageResource {
r(key: string, defaultValue?: any): any
}</pre>
</p>
<hr />
<h2>用法</h2>
<pre>const lgres = window["lib-utility"];
lgres.init(document.body, {
template: '/res.json',
callback: (res) => document.title = res.r('title', 'Default Title')
}).then(res => {
document.querySelector('#header').innerText = res.r('header', 'My Header');
const msg = lgres.lang.unknownError;
document.querySelector('#message').innerText = lgres.lang.unknownError;
});</pre>
</div>

View File

@ -51,19 +51,25 @@ async function doRefreshLgres(template) {
const r = await get(`language/${lgid}${template}`); const r = await get(`language/${lgid}${template}`);
const dict = await r.json(); const dict = await r.json();
localStorage.setItem(getStorageKey(lgid), JSON.stringify(dict)); localStorage.setItem(getStorageKey(lgid), JSON.stringify(dict));
cache = dict;
return dict; return dict;
} }
async function refreshLgres(template, lgres) { async function refreshLgres(template, lgres) {
if (lgres == null || typeof consts === 'undefined') { if (lgres == null || typeof consts === 'undefined') {
return await doRefreshLgres(template); lgres = await doRefreshLgres(template);
} }
const ver = Number(consts.resver); const ver = Number(consts.resver);
if (isNaN(lgres.ver) || isNaN(ver) || ver > lgres.ver) { if (isNaN(lgres.ver) || isNaN(ver) || ver > lgres.ver) {
console.log(`found new language res version: ${lgres.ver} => ${ver}`); console.log(`found new language res version: ${lgres.ver} => ${ver}`);
return await doRefreshLgres(template); lgres = await doRefreshLgres(template);
} }
Object.defineProperty(lgres, 'r', {
writable: false,
configurable: false,
value: function (key, defaultValue) {
return getLanguage(this, key, defaultValue);
}
});
cache = lgres; cache = lgres;
return lgres; return lgres;
} }

View File

@ -9,4 +9,4 @@ interface RequestOptions {
export function get(url: string, options?: RequestOptions): Promise<Response> export function get(url: string, options?: RequestOptions): Promise<Response>
export function post(url: string, data?: BodyInit | null, options?: RequestOptions): Promise<Response> export function post(url: string, data?: BodyInit | null, options?: RequestOptions): Promise<Response>
export function upload(url: string, data: FormData, options?: RequestOptions): Promise<Response> export function upload(url: string, data: FormData, options?: RequestOptions): Promise<XMLHttpRequest>

37
lib/utility/request.html Normal file
View File

@ -0,0 +1,37 @@
<div>
<h1>request</h1>
<hr />
<p>
网络请求工具类,可以实现比较常见的一些请求操作。
</p>
<h2>get</h2>
<code>function get(url: string, options?: RequestOptions): Promise&lt;Response&gt;</code>
<h3>url: string</h3>
<p>
url 地址
</p>
<h3>options?: RequestOptions</h3>
<p>
请求的配置参数,结构为
<pre>interface RequestOptions {
method?: string;
accept?: string;
contentType?: string;
customerHeaders?: { [key: string]: string };
signal?: AbortSignal | null;
progress?: (this: XMLHttpRequestUpload, ev: ProgressEvent&lt;XMLHttpRequestEventTarget&gt;) => any
}</pre>
</p>
<h3>method?: string</h3>
<p>
请求类型,默认为 GET 或 POST
</p>
<h3>accept?: string</h3>
<p>
Accept 请求头的值
</p>
<h3>contentType?: string</h3>
<p>
Content-Type 请求头的值
</p>
</div>

View File

@ -1,5 +1,5 @@
:root { :root {
font-family: 'Franklin Gothic Book', Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; font-family: 'Segoe UI Variable Display', Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
font-size: 1.125rem; font-size: 1.125rem;
line-height: 1.5; line-height: 1.5;
font-weight: 400; font-weight: 400;