add document, fix tooltip position issue
This commit is contained in:
parent
f5bc42fa20
commit
5406eea20e
@ -8,7 +8,6 @@ $boxDisabledColor: #d9d9d9;
|
||||
.check-box-inner {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-top: 2px;
|
||||
padding: 0;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
|
2
css/ui.min.css
vendored
2
css/ui.min.css
vendored
@ -1 +1 @@
|
||||
.checkbox-image>input[type=checkbox]{display:none}.checkbox-image>input[type=checkbox]:checked~.checked{display:inline}.checkbox-image>input[type=checkbox]:checked~.unchecked{display:none}.checkbox-image>.checked{display:none}.checkbox-image>.unchecked{display:inline}.checkbox-wrapper{display:flex;align-items:center;padding:0 8px;height:36px}.checkbox-wrapper .check-box-inner{position:relative;display:inline-block;margin-top:2px;padding:0;width:14px;height:14px;background-color:#fff;border:1px solid #999898;-moz-user-select:none;user-select:none;-webkit-user-select:none;border-radius:2px;transition:all .2s;cursor:pointer}.checkbox-wrapper .check-box-inner>svg{position:absolute;top:0;left:0;width:100%;height:100%;fill:#fff;transform:scale(0);opacity:0;transition:all .08s cubic-bezier(0.78, 0.14, 0.15, 0.86)}.checkbox-wrapper>input[type=checkbox]{display:none}.checkbox-wrapper>input[type=checkbox]:checked+.check-box-inner{border-color:#1890ff;background-color:#1890ff}.checkbox-wrapper>input[type=checkbox]:checked+.check-box-inner>svg{transform:scale(1);opacity:1}.checkbox-wrapper>input[type=checkbox]:disabled+.check-box-inner{border-color:#d9d9d9;cursor:default}.checkbox-wrapper>input[type=checkbox]:disabled:checked+.check-box-inner{border-color:#d9d9d9;background-color:#d9d9d9}.checkbox-wrapper>input[type=checkbox]:disabled~span{color:#d9d9d9;cursor:default}.checkbox-wrapper .check-box-inner{flex:0 0 auto}.checkbox-wrapper>span{flex:1 1 auto;font-weight:400;font-size:.875rem;padding-left:8px;padding-right:6px;align-self:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;color:#201f1e}.tooltip-color{background-color:#fff;color:#323130;border-color:rgba(204,204,204,.8);outline:none}.tooltip-wrapper{position:fixed;word-wrap:break-word;height:auto;text-align:left;z-index:250;min-width:75px;max-width:480px;min-height:32px;border-radius:2px;box-shadow:0 3.2px 7.2px 0 rgba(0,0,0,.13),0 .6px 1.8px 0 rgba(0,0,0,.11);transition:visibility 0s linear 120ms,opacity 120ms ease}.tooltip-wrapper>.tooltip-pointer{box-sizing:border-box;box-shadow:0 5px 15px 2px rgba(0,0,0,.3);border:1px solid #fff;z-index:-1;width:16px;height:16px;position:absolute;left:calc(50% - 8px);bottom:-8px;transform:rotate(-45deg);transform-origin:center}.tooltip-wrapper>.tooltip-curtain{position:absolute;width:100%;height:100%;z-index:-1}.tooltip-wrapper>.tooltip-content{font-size:.8125rem;line-height:1rem;white-space:normal;overflow:auto;margin:8px;height:calc(100% - 16px);-moz-user-select:none;user-select:none;-webkit-user-select:none}
|
||||
.checkbox-image>input[type=checkbox]{display:none}.checkbox-image>input[type=checkbox]:checked~.checked{display:inline}.checkbox-image>input[type=checkbox]:checked~.unchecked{display:none}.checkbox-image>.checked{display:none}.checkbox-image>.unchecked{display:inline}.checkbox-wrapper{display:flex;align-items:center;padding:0 8px;height:36px}.checkbox-wrapper .check-box-inner{position:relative;display:inline-block;padding:0;width:14px;height:14px;background-color:#fff;border:1px solid #999898;-moz-user-select:none;user-select:none;-webkit-user-select:none;border-radius:2px;transition:all .2s;cursor:pointer}.checkbox-wrapper .check-box-inner>svg{position:absolute;top:0;left:0;width:100%;height:100%;fill:#fff;transform:scale(0);opacity:0;transition:all .08s cubic-bezier(0.78, 0.14, 0.15, 0.86)}.checkbox-wrapper>input[type=checkbox]{display:none}.checkbox-wrapper>input[type=checkbox]:checked+.check-box-inner{border-color:#1890ff;background-color:#1890ff}.checkbox-wrapper>input[type=checkbox]:checked+.check-box-inner>svg{transform:scale(1);opacity:1}.checkbox-wrapper>input[type=checkbox]:disabled+.check-box-inner{border-color:#d9d9d9;cursor:default}.checkbox-wrapper>input[type=checkbox]:disabled:checked+.check-box-inner{border-color:#d9d9d9;background-color:#d9d9d9}.checkbox-wrapper>input[type=checkbox]:disabled~span{color:#d9d9d9;cursor:default}.checkbox-wrapper .check-box-inner{flex:0 0 auto}.checkbox-wrapper>span{flex:1 1 auto;font-weight:400;font-size:.875rem;padding-left:8px;padding-right:6px;align-self:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;color:#201f1e}.tooltip-color{background-color:#fff;color:#323130;border-color:rgba(204,204,204,.8);outline:none}.tooltip-wrapper{position:fixed;word-wrap:break-word;height:auto;text-align:left;z-index:250;min-width:75px;max-width:480px;min-height:32px;border-radius:2px;box-shadow:0 3.2px 7.2px 0 rgba(0,0,0,.13),0 .6px 1.8px 0 rgba(0,0,0,.11);transition:visibility 0s linear 120ms,opacity 120ms ease}.tooltip-wrapper>.tooltip-pointer{box-sizing:border-box;box-shadow:0 5px 15px 2px rgba(0,0,0,.3);border:1px solid #fff;z-index:-1;width:16px;height:16px;position:absolute;left:calc(50% - 8px);bottom:-8px;transform:rotate(-45deg);transform-origin:center}.tooltip-wrapper>.tooltip-curtain{position:absolute;width:100%;height:100%;z-index:-1}.tooltip-wrapper>.tooltip-content{font-size:.8125rem;line-height:1rem;white-space:normal;overflow:auto;margin:8px;height:calc(100% - 16px);-moz-user-select:none;user-select:none;-webkit-user-select:none}
|
76
index.html
76
index.html
@ -1,42 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>UI Lib</title>
|
||||
<script type="module" src="/main.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<div>
|
||||
<a
|
||||
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript"
|
||||
target="_blank"
|
||||
>
|
||||
<img id="js-logo" class="logo vanilla" alt="JavaScript logo" />
|
||||
</a>
|
||||
<div class="card">
|
||||
<div id="create-icon" class="app-module">
|
||||
<div>
|
||||
<svg data-type="fa-solid" data-id="user-edit"></svg>
|
||||
</div>
|
||||
</div>
|
||||
<div id="create-checkbox" class="app-module">
|
||||
<label data-checkbox data-label="Case 1"></label>
|
||||
</div>
|
||||
<div id="buttons" class="app-module">
|
||||
<button
|
||||
data-title-lgid="editContacts"
|
||||
data-lgid="editContacts"
|
||||
title="Edit Contact"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button id="button-fetch" title="Fetch">Fetch</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>UI Lib</title>
|
||||
<script type="module" src="/main.js"></script>
|
||||
<script src="/dist/ui.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="directory">
|
||||
<ul>
|
||||
<li class="title">lib-ui</li>
|
||||
<li>
|
||||
<ol>
|
||||
<li data-page="lib/ui/icon.html">icon</li>
|
||||
<li data-page="lib/ui/checkbox.html">checkbox</li>
|
||||
<li data-page="lib/ui/tooltip.html">tooltip</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li class="title">lib-utility</li>
|
||||
<li>
|
||||
<ol>
|
||||
<li data-page="lib/utility/cookie.html">cookie</li>
|
||||
<li data-page="lib/utility/lgres.html">lgres</li>
|
||||
<li data-page="lib/utility/request.html">request</li>
|
||||
<li data-page="lib/utility/strings.html">strings</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="container"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -3,10 +3,13 @@ import { createCheckbox, resolveCheckbox } from "./ui/checkbox";
|
||||
import { setTooltip, resolveTooltip } from "./ui/tooltip";
|
||||
|
||||
export {
|
||||
// icon
|
||||
createIcon,
|
||||
resolveIcon,
|
||||
// checkbox
|
||||
createCheckbox,
|
||||
resolveCheckbox,
|
||||
// tooltip
|
||||
setTooltip,
|
||||
resolveTooltip
|
||||
}
|
||||
|
13
lib/ui/checkbox.d.ts
vendored
13
lib/ui/checkbox.d.ts
vendored
@ -1,2 +1,13 @@
|
||||
export function createCheckbox(opts: any): HTMLElement
|
||||
interface CheckboxOptions {
|
||||
type?: string;
|
||||
label?: string;
|
||||
checked?: boolean;
|
||||
isImage?: boolean;
|
||||
imageHeight?: Number;
|
||||
checkedNode?: HTMLElement;
|
||||
uncheckedNode?: HTMLElement;
|
||||
onchange?: (this: HTMLInputElement, ev: Event) => any;
|
||||
}
|
||||
|
||||
export function createCheckbox(opts?: CheckboxOptions): HTMLElement
|
||||
export function resolveCheckbox(container: HTMLElement): HTMLElement
|
93
lib/ui/checkbox.html
Normal file
93
lib/ui/checkbox.html
Normal file
@ -0,0 +1,93 @@
|
||||
<div>
|
||||
<h1>checkbox</h1>
|
||||
<hr />
|
||||
<p>
|
||||
创建一个统一样式的复选框元素,或者解析转换页面上特定类型的 label
|
||||
标签为复选框元素。
|
||||
</p>
|
||||
<h2>createCheckbox</h2>
|
||||
<code>function createCheckbox(opts?: CheckboxOptions): HTMLElement</code>
|
||||
<h3>opts?: CheckboxOptions</h3>
|
||||
<p>
|
||||
复选框初始参数,结构为
|
||||
<pre>interface CheckboxOptions {
|
||||
type?: string;
|
||||
label?: string;
|
||||
checked?: boolean;
|
||||
isImage?: boolean;
|
||||
imageHeight?: Number;
|
||||
checkedNode?: HTMLElement;
|
||||
uncheckedNode?: HTMLElement;
|
||||
onchange?: (this: HTMLInputElement, ev: Event) => any;
|
||||
}</pre>
|
||||
</p>
|
||||
<h3>type?: string</h3>
|
||||
<p>
|
||||
复选框图标的样式,可选值目前有 <code>fa-regular</code>、<code>fa-light</code>、<code>fa-solid</code>
|
||||
</p>
|
||||
<h3>label?: string</h3>
|
||||
<p>
|
||||
复选框的标签文本
|
||||
</p>
|
||||
<h3>checked?: boolean</h3>
|
||||
<p>
|
||||
初始是否选中
|
||||
</p>
|
||||
<h3>isImage?: boolean</h3>
|
||||
<p>
|
||||
是否为图片复选框
|
||||
</p>
|
||||
<h3>imageHeight?: Number</h3>
|
||||
<p>
|
||||
为图片复选框时的图片限制高度
|
||||
</p>
|
||||
<h3>checkedNode?: HTMLElement</h3>
|
||||
<p>
|
||||
为图片复选框时的选中时显示的元素
|
||||
</p>
|
||||
<h3>uncheckedNode?: HTMLElement</h3>
|
||||
<p>
|
||||
为图片复选框时的未选中时显示的元素
|
||||
</p>
|
||||
<h3>onchange?: (this: HTMLInputElement, ev: Event) => any</h3>
|
||||
<p>
|
||||
复选框改变时触发的事件
|
||||
</p>
|
||||
<h2>resolveCheckbox</h2>
|
||||
<code>function resolveCheckbox(container: HTMLElement): HTMLElement</code>
|
||||
<h3>container: HTMLElement</h3>
|
||||
<p>
|
||||
将把此 HTML 元素下的所有 <code>label[data-checkbox]</code> 元素解析为复选框,<code>[data-id]</code> 为复选框元素的 id,包含
|
||||
<code>[data-checked]</code> 时复选框默认选中。</p>
|
||||
<p>当该元素无子元素时,<code>[data-type]</code> 同上述参数中的 <code>type?: string</code>,<code>[data-label]</code> 同上述参数中的
|
||||
<code>label?: string</code>。
|
||||
</p>
|
||||
<p>当该元素有子元素时,解析为图片复选框,class 为 <code>checked</code>、<code>unchecked</code> 的子元素将分别在选中与未选中时显示。</p>
|
||||
<h2>示例</h2>
|
||||
<pre>
|
||||
<div id="checkbox-sample">
|
||||
<label data-checkbox data-type="fa-light" data-label="Checkbox Light"></label>
|
||||
<label data-checkbox data-checked data-label="Checkbox Regular"></label>
|
||||
<label data-checkbox data-type="fa-solid" data-label="Checkbox Solid"></label>
|
||||
<label data-checkbox>
|
||||
<code class="checked">Checked</code>
|
||||
<code class="unchecked">Unchecked</code>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
window["lib-ui"].resolveCheckbox(document.querySelector("#checkbox-sample"));
|
||||
</script></pre>
|
||||
<div id="checkbox-sample">
|
||||
<label data-checkbox data-type="fa-light" data-label="Checkbox Light"></label>
|
||||
<label data-checkbox data-checked data-label="Checkbox Regular"></label>
|
||||
<label data-checkbox data-type="fa-solid" data-label="Checkbox Solid"></label>
|
||||
<label data-checkbox>
|
||||
<code class="checked">Checked</code>
|
||||
<code class="unchecked">Unchecked</code>
|
||||
</label>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
window["lib-ui"].resolveCheckbox(document.querySelector("#checkbox-sample"));
|
||||
</script>
|
||||
</div>
|
@ -18,6 +18,9 @@ function createCheckbox(opts) {
|
||||
container.className = 'checkbox-wrapper';
|
||||
const input = document.createElement('input');
|
||||
input.setAttribute('type', 'checkbox');
|
||||
if (opts.checked === true) {
|
||||
input.checked = true;
|
||||
}
|
||||
if (typeof opts.onchange === 'function') {
|
||||
input.addEventListener('change', opts.onchange);
|
||||
}
|
||||
@ -64,6 +67,13 @@ function resolveCheckbox(container) {
|
||||
box.removeAttribute('data-label');
|
||||
}
|
||||
const input = document.createElement('input');
|
||||
const id = box.getAttribute('data-id');
|
||||
if (id != null && id.length > 0) {
|
||||
input.id = id;
|
||||
}
|
||||
if (box.getAttribute('data-checked') != null) {
|
||||
input.checked = true;
|
||||
}
|
||||
input.setAttribute('type', 'checkbox');
|
||||
box.insertBefore(input, box.firstChild);
|
||||
}
|
||||
|
46
lib/ui/icon.html
Normal file
46
lib/ui/icon.html
Normal file
@ -0,0 +1,46 @@
|
||||
<div>
|
||||
<h1>icon</h1>
|
||||
<hr />
|
||||
<p>
|
||||
创建一个 svg 矢量图标元素,或者解析转换页面上特定类型的 svg
|
||||
标签到指定的图标元素。
|
||||
</p>
|
||||
<h2>createIcon</h2>
|
||||
<code>function createIcon(type: string, id: string): SVGElement</code>
|
||||
<h3>type: string</h3>
|
||||
<p>
|
||||
图标类型,可选值目前有 <code>fa-regular</code>、<code>fa-light</code>、<code>fa-solid</code>
|
||||
</p>
|
||||
<h3>id: string</h3>
|
||||
<p>
|
||||
图形 id,例如
|
||||
<code>user-edit</code>、<code>address-card</code>、<code>frog</code>……
|
||||
</p>
|
||||
<h2>resolveIcon</h2>
|
||||
<code>function resolveIcon(container: HTMLElement): HTMLElement</code>
|
||||
<h3>container: HTMLElement</h3>
|
||||
<p>
|
||||
将把此 HTML 元素下的所有 <code>svg[data-id]</code> 元素解析为图标,<code>[data-id]</code>
|
||||
同上述 <code>id: string</code>,<code>[data-type]</code> 同上述
|
||||
<code>type: string</code>
|
||||
</p>
|
||||
<h2>示例</h2>
|
||||
<pre>
|
||||
<div id="icon-sample">
|
||||
<svg data-id="address-card" data-type="fa-regular"></svg>
|
||||
<svg data-id="user-edit" data-type="fa-light"></svg>
|
||||
<svg data-id="frog" data-type="fa-solid"></svg>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
window["lib-ui"].resolveIcon(document.querySelector("#icon-sample"));
|
||||
</script></pre>
|
||||
<div id="icon-sample">
|
||||
<svg data-id="address-card" data-type="fa-regular"></svg>
|
||||
<svg data-id="user-edit" data-type="fa-light"></svg>
|
||||
<svg data-id="frog" data-type="fa-solid"></svg>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
window["lib-ui"].resolveIcon(document.querySelector("#icon-sample"));
|
||||
</script>
|
||||
</div>
|
44
lib/ui/tooltip.html
Normal file
44
lib/ui/tooltip.html
Normal file
@ -0,0 +1,44 @@
|
||||
<div>
|
||||
<h1>tooltip</h1>
|
||||
<hr />
|
||||
<p>
|
||||
给某个元素或者页面上含有 title 属性的元素设置一个统一样式的 tooltip。
|
||||
</p>
|
||||
<h2>setTooltip</h2>
|
||||
<code>function setTooltip(container: HTMLElement, content: string | HTMLElement): void</code>
|
||||
<h3>container: HTMLElement</h3>
|
||||
<p>
|
||||
要设置 tooltip 的元素
|
||||
</p>
|
||||
<h3>content: string | HTMLElement</h3>
|
||||
<p>
|
||||
要设置的 tooltip 内容,允许为字符串或者 HTML 元素
|
||||
</p>
|
||||
<h2>resolveTooltip</h2>
|
||||
<code>function resolveTooltip(container: HTMLElement): HTMLElement</code>
|
||||
<h3>container: HTMLElement</h3>
|
||||
<p>
|
||||
给此元素下的所有含有 title 属性的子元素设置成统一样式的 tooltip
|
||||
</p>
|
||||
<h2>示例</h2>
|
||||
<pre>
|
||||
<div id="tooltip-sample">
|
||||
<blockquote title="From MDN Website">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
|
||||
response body and the HTTP status of the result.</blockquote>
|
||||
<button title="Test to send request through XMLHttpRequest.">Test</button>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
window["lib-ui"].resolveCheckbox(document.querySelector("#checkbox-sample"));
|
||||
</script></pre>
|
||||
<div id="tooltip-sample">
|
||||
<blockquote title="From MDN Website">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
|
||||
response body and the HTTP status of the result.</blockquote>
|
||||
<button title="Test to send request through XMLHttpRequest.">Test</button>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
window["lib-ui"].resolveTooltip(document.querySelector("#tooltip-sample"));
|
||||
</script>
|
||||
</div>
|
@ -23,8 +23,16 @@ function setTooltip(container, content) {
|
||||
container.addEventListener('mouseenter', () => {
|
||||
tid && clearTimeout(tid);
|
||||
tid = setTimeout(() => {
|
||||
const left = container.offsetLeft + container.offsetWidth / 2 - wrapper.offsetWidth / 2;
|
||||
const top = container.offsetTop - wrapper.offsetHeight - 14;
|
||||
let left = container.offsetLeft;
|
||||
let top = container.offsetTop;
|
||||
let parent = container.parentElement;
|
||||
while (parent != null) {
|
||||
left -= parent.scrollLeft;
|
||||
top -= parent.scrollTop;
|
||||
parent = parent.parentElement;
|
||||
}
|
||||
left -= wrapper.offsetWidth / 2 - container.offsetWidth / 2;
|
||||
top -= wrapper.offsetHeight + 14;
|
||||
wrapper.style.left = `${left}px`;
|
||||
wrapper.style.top = `${top}px`;
|
||||
wrapper.style.visibility = 'visible';
|
||||
|
@ -4,15 +4,19 @@ import { get, post, upload } from "./utility/request";
|
||||
import { nullOrEmpty, contains, endsWith, padStart } from "./utility/strings";
|
||||
|
||||
export {
|
||||
// cookie
|
||||
getCookie,
|
||||
setCookie,
|
||||
deleteCookie,
|
||||
// lgres
|
||||
init,
|
||||
r,
|
||||
lang,
|
||||
// request
|
||||
get,
|
||||
post,
|
||||
upload,
|
||||
// strings
|
||||
nullOrEmpty,
|
||||
contains,
|
||||
endsWith,
|
||||
|
7
lib/utility/lgres.d.ts
vendored
7
lib/utility/lgres.d.ts
vendored
@ -1,4 +1,9 @@
|
||||
export function init(dom?: HTMLElement, ahead?: | { callback?: (result: any) => void }): Promise<any>
|
||||
interface LgresOptions {
|
||||
template?: string,
|
||||
callback?: (result: any) => void
|
||||
}
|
||||
|
||||
export function init(dom?: HTMLElement, options?: LgresOptions): Promise<any>
|
||||
export function r(key: string, defaultValue?: any): any
|
||||
export const lang: {
|
||||
get current(): string,
|
||||
|
@ -45,23 +45,24 @@ function getStorageKey(lgid) {
|
||||
return `res_${lgid}`;
|
||||
}
|
||||
|
||||
async function doRefreshLgres() {
|
||||
async function doRefreshLgres(template) {
|
||||
template ??= '';
|
||||
const lgid = getCurrentLgId();
|
||||
const r = await get(`language/${lgid}/res.json`);
|
||||
const r = await get(`language/${lgid}${template}`);
|
||||
const dict = await r.json();
|
||||
localStorage.setItem(getStorageKey(lgid), JSON.stringify(dict));
|
||||
cache = dict;
|
||||
return dict;
|
||||
}
|
||||
|
||||
async function refreshLgres(lgres) {
|
||||
async function refreshLgres(template, lgres) {
|
||||
if (lgres == null || typeof consts === 'undefined') {
|
||||
return await doRefreshLgres();
|
||||
return await doRefreshLgres(template);
|
||||
}
|
||||
const ver = Number(consts.resver);
|
||||
if (isNaN(lgres.ver) || isNaN(ver) || ver > lgres.ver) {
|
||||
console.log(`found new language res version: ${lgres.ver} => ${ver}`);
|
||||
return await doRefreshLgres();
|
||||
return await doRefreshLgres(template);
|
||||
}
|
||||
cache = lgres;
|
||||
return lgres;
|
||||
@ -97,42 +98,40 @@ function applyLanguage(dom, result) {
|
||||
}
|
||||
}
|
||||
|
||||
async function init(dom, ahead) {
|
||||
async function init(dom, options) {
|
||||
options ??= {};
|
||||
const lgid = getCurrentLgId();
|
||||
let lgres = localStorage.getItem(getStorageKey(lgid));
|
||||
let result;
|
||||
if (lgres != null) {
|
||||
try {
|
||||
lgres = JSON.parse(lgres);
|
||||
result = await refreshLgres(lgres);
|
||||
result = await refreshLgres(options.template, lgres);
|
||||
} catch (e) {
|
||||
console.error('error while parsing lgres, try refresh ...', e);
|
||||
result = await refreshLgres();
|
||||
result = await refreshLgres(options.template);
|
||||
}
|
||||
} else {
|
||||
result = await refreshLgres();
|
||||
result = await refreshLgres(options.template);
|
||||
}
|
||||
|
||||
try {
|
||||
if (ahead != null) {
|
||||
// not in defer mode
|
||||
if (document.readyState === 'loading') {
|
||||
return await new Promise((resolve, reject) => {
|
||||
let tid = setTimeout(() => reject('timeout'), 30000);
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
clearTimeout(tid);
|
||||
tid = void 0;
|
||||
if (typeof ahead.callback === 'function') {
|
||||
ahead.callback(result);
|
||||
}
|
||||
applyLanguage(dom, result);
|
||||
resolve(result);
|
||||
});
|
||||
if (document.readyState === 'loading') {
|
||||
return await new Promise((resolve, reject) => {
|
||||
let tid = setTimeout(() => reject('timeout'), 30000);
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
clearTimeout(tid);
|
||||
tid = void 0;
|
||||
if (typeof options.callback === 'function') {
|
||||
options.callback(result);
|
||||
}
|
||||
applyLanguage(dom, result);
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (typeof ahead.callback === 'function') {
|
||||
ahead.callback(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (typeof options.callback === 'function') {
|
||||
options.callback(result);
|
||||
}
|
||||
applyLanguage(dom, result);
|
||||
return result;
|
||||
|
33
main.js
33
main.js
@ -1,8 +1,7 @@
|
||||
import './css/ui.min.css'
|
||||
import './style.css'
|
||||
// import javascriptLogo from './javascript.svg'
|
||||
import { resolveCheckbox, resolveIcon, resolveTooltip } from './lib/ui'
|
||||
import { init, r, lang, get, post, upload } from './lib/utility'
|
||||
import { get } from './lib/utility'
|
||||
|
||||
// document.querySelector('#js-logo').src = javascriptLogo
|
||||
|
||||
@ -11,7 +10,36 @@ window.consts = {
|
||||
resver: 20230329
|
||||
}
|
||||
|
||||
function navigate(page) {
|
||||
get(page, {
|
||||
accept: 'text/html'
|
||||
})
|
||||
.then(r => r.text())
|
||||
.then(html => {
|
||||
const range = document.createRange();
|
||||
range.selectNode(document.body);
|
||||
const doc = range.createContextualFragment(html);
|
||||
document.querySelector('#container').replaceChildren(doc);
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelector('#directory').addEventListener('click', (ev) => {
|
||||
const page = ev.target.getAttribute('data-page');
|
||||
if (typeof page === 'string') {
|
||||
location.hash = page;
|
||||
navigate(page);
|
||||
}
|
||||
});
|
||||
|
||||
let page = location.hash;
|
||||
if (page.length > 1) {
|
||||
page = page.substring(1);
|
||||
navigate(page);
|
||||
}
|
||||
|
||||
/*
|
||||
init(null, {
|
||||
template: '/res.json',
|
||||
callback: (result) => console.log(result)
|
||||
}).then(() => {
|
||||
// document.querySelector('#create-icon').appendChild(createIcon('fa-solid', 'user-edit'))
|
||||
@ -35,3 +63,4 @@ init(null, {
|
||||
.then(blob => document.querySelector('#js-logo').src = URL.createObjectURL(blob));
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
152
style.css
152
style.css
@ -13,6 +13,46 @@
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
|
||||
--border-color: #ccc;
|
||||
--hover-color: #666;
|
||||
--mono-font-family: 'FantasqueSansMono NFM', 'Cascadia Code', 'PT Mono', Consolas, 'Courier New', monospace;
|
||||
}
|
||||
|
||||
code, kbd, pre, samp {
|
||||
font-family: var(--mono-font-family);
|
||||
background-color: var(--hover-color);
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
code {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-size: .875em;
|
||||
}
|
||||
|
||||
h2 + code {
|
||||
margin-left: 70px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h2 + code::before {
|
||||
content: '签名:';
|
||||
position: absolute;
|
||||
margin-left: -70px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-family: var(--mono-font-family);
|
||||
font-size: 1em;
|
||||
margin-left: 10px;
|
||||
/* font-weight: bold; */
|
||||
}
|
||||
|
||||
h3 ~ p {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
a {
|
||||
@ -20,50 +60,11 @@ a {
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
}
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #646cffaa);
|
||||
}
|
||||
.logo.vanilla:hover {
|
||||
filter: drop-shadow(0 0 2em #f7df1eaa);
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
@ -75,14 +76,74 @@ button {
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
#directory {
|
||||
width: 200px;
|
||||
padding: 2rem;
|
||||
border-right: 1px solid var(--border-color);
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
#directory>ul {
|
||||
padding: 0;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
#directory>ul>li {
|
||||
list-style: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#directory>ul>li.title {
|
||||
margin: 20px 0 6px;
|
||||
font-weight: bold;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
#directory ol {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
#directory ol>li {
|
||||
padding: 0 6px;
|
||||
list-style-position: inside;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#directory ol>li:hover {
|
||||
background-color: var(--hover-color);
|
||||
}
|
||||
|
||||
#container {
|
||||
flex: 1 1 auto;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#container>div {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.app-module {
|
||||
margin: 8px 0;
|
||||
}
|
||||
@ -91,6 +152,7 @@ button:focus-visible {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#create-icon svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@ -101,11 +163,13 @@ button:focus-visible {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.checkbox-wrapper .check-box-inner {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
.checkbox-wrapper > span {
|
||||
|
||||
.checkbox-wrapper>span {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
@ -113,11 +177,15 @@ button:focus-visible {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
--border-color: #666;
|
||||
--hover-color: #eee;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user