H5 WebSQL每日成语

news2025/2/4 9:02:00

有一天看到同事发的类似
这种成语填空一样的内容。

================

惟利( )视

为德( )终

质非文( )

( )追耗子

================

烂漫天( )

( )则改之,无则嘉勉

得( )之作

哀( )如潮

================

于是就去网上找成语数据库表的 SQL… 哈哈哈 很容易就找到了.

本来打算写个前后端,想了想可以但没必要。

于是就… 有了这篇 WebSQL 示例

效果

img

WebSQL

打开数据库

openDatabase(数据库名称,版本号,描述文本,数据库大小,创建回调)

例:

var db = openDatabase("idiom-data", "1.0", "这是一个存放成语的数据库", 20 * 1024 * 1024);

新建事务

db.transaction(创建回调)

执行 SQL

tx.executeSql(SQL 语句,SQL 语句需要的参数,回调函数,出错回调函数)

源码


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>每日成语</title>
    <style>
        body {
            margin: 0;
        }

        .idiom-detail,
        .idiom-card {
            /* display: inline-block; */
            position: absolute;
            left: 10px;
            top: 10px;
            display: none;
            padding: 5px 10px;
            background-color: #fff;
            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.3);
            max-width: 200px;
            z-index: 10;
        }

        .idiom-detail {
            top: 0;
        }

        .idiom-detail>div {
            pointer-events: none;
        }


        .title {
            display: inline-block;
            margin-top: 10px;
            margin-left: -10px;
            padding: 0 20px;
            color: #fff;
            background-color: skyblue;
        }

        .name {
            font-weight: bold;
            font-size: 20px;
            margin-top: 4px;
        }


        .spell,
        .content,
        .derivation,
        .samples {
            margin-top: 2px;
            font-size: 14px;
            color: #888;
        }

        .search-card {
            margin: 10px;
            width: 30vw;
            margin: 20vh auto;
            position: relative;
        }

        .search-input {
            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.3);
            background-color: #fff;
            padding: 10px 10px;
            outline: none;
            font-size: 20px;
            border: none;
            width: 100%;
            box-sizing: border-box;
        }

        .search-deduct,
        .search-list {
            margin-top: 20px;
            display: inline-block;
            width: 100%;
            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.3);
        }

        .search-deduct {
            position: absolute;
            left: calc(100% + 20px);
            display: inline-block;
            max-width: 200px;
        }

        .search-deduct .title {
            margin-left: 0;
        }

        .search-deduct .search-item {
            width: 100%;
        }

        .search-item {
            font-size: 14px;
            display: block;
            padding: 5px 10px;
        }

        .search-list .search-item:hover {
            background-color: skyblue;
            font-weight: bold;
        }
    </style>
</head>

<body>
    <div class="idiom-card">
        <div class="title">每日成语</div>
        <div class="name"></div>
        <div class="spell"></div>
        <div class="content"></div>
        <div class="derivation"></div>
        <div class="samples"></div>
    </div>

    <div class="idiom-detail">
        <div class="title">成语详情</div>
        <div class="name"></div>
        <div class="spell"></div>
        <div class="content"></div>
        <div class="derivation"></div>
        <div class="samples"></div>
    </div>
    <div class="search-card">
        <input class="search-input" type="text" placeholder="有意思的搜索框~" maxlength="10">

        <div class="search-deduct"></div>
        <div class="search-list"></div>
    </div>
    <script>

        var db = openDatabase('idiom-data', '1.0', '这是一个存放成语的数据库', 20 * 1024 * 1024);

        /**
         * 执行SQL语句 random() 函数
         */
        function executeSql(tx, sql, data = []) {
            return new Promise((resolve, reject) => {
                tx.executeSql(sql, data, function (tx, results) {
                    resolve(results)
                }, function (tx, err) {
                    console.log('错误信息: ', err, sql);
                });
            })
        }

        /**
         * 新建一个数据库事务
         */
        function transaction() {
            return new Promise((resolve, reject) => {
                db.transaction(function (tx) {
                    resolve(tx)
                });
            })
        }

        /**
         * 读取SQL
         */
        function readSQL(sqlTxt) {
            return new Promise((resolve, reject) => {
                let tx, sqls, count
                transaction().then((res) => {
                    tx = res;
                    sqls = sqlTxt.includes('\r\n') ? sqlTxt.split('\r\n') : sqlTxt.split('\n')
                    console.log(sqls);
                    sqls = sqls.filter(a => a);
                    let createTable = sqls.shift()
                    console.log(createTable);
                    return executeSql(tx, createTable)
                }).then((_) => {
                    console.log(_);
                    return executeSql(tx, "SELECT COUNT(*) As count FROM idiom;")
                }).then((_) => {
                    count = _.rows[0].count
                    if (count === 0) {
                        return Promise.all(sqls.map(sql => executeSql(tx, sql)))
                    }
                }).then((_) => {
                    // 返回总数量
                    return executeSql(tx, "SELECT COUNT(*) As count FROM idiom;")
                }).then((res) => {
                    count = res.rows[0].count
                    // 加载错误
                    if (count < sqls.length) throw { errMsg: 'LOAD_ERROR' }
                    // 随机一条 每日成语
                    const randomID = Math.round(Math.random() * count) + 1
                    return executeSql(tx, `SELECT * FROM idiom Where ID=${randomID};`)
                }).then((res) => {
                    if (res.rows[0]) {
                        let idiomCardDom = document.querySelector('.idiom-card')
                        let nameDom = document.querySelector('.idiom-card > .name')
                        let spellDom = document.querySelector('.idiom-card > .spell')
                        let contentDom = document.querySelector('.idiom-card > .content')
                        let derivationDom = document.querySelector('.idiom-card > .derivation')
                        let samplesDom = document.querySelector('.idiom-card > .samples')
                        let { content, derivation, name, samples, spell } = res.rows[0]
                        nameDom.textContent = name;
                        contentDom.textContent = content;
                        derivationDom.textContent = derivation;
                        spellDom.textContent = spell;
                        samplesDom.textContent = samples;
                        idiomCardDom.setAttribute('style', 'display: inline-block;')
                    }
                }).catch(reject)
            })
        }


        // 加载SQL文件
        function loadSQL() {
            fetch("./assets/idiom.sql", {
                "referrerPolicy": "strict-origin-when-cross-origin",
                "method": "GET",
                "mode": "cors",
                "credentials": "omit"
            }).then((res) => {
                return res.text()
            }).then((res) => {
                return readSQL(res)
            }).catch((err) => {
                console.log(err);
                if (err.errMsg === 'LOAD_ERROR') {
                    // 移除表
                    transaction().then((tx) => executeSql(tx, 'DROP TABLE idiom;')).then(console.log)
                    console.log('加载错误10s后重新加载...');
                    setTimeout(loadSQL, 10000);
                }
            })
        };

        loadSQL()

        let searchInput = document.querySelector('.search-input')
        let timeoutId = null
        let lastText = ''
        searchInput.addEventListener('input', (ev) => {
            // 节流
            if (timeoutId) clearTimeout(timeoutId)
            timeoutId = setTimeout(() => {
                find(ev)
                clearTimeout(timeoutId)
                timeoutId = null
            }, 100);
        })


        /**
         * 获取元素偏移位置
         * @param {HTMLDivElement} ele
         */
        function getOffset(ele, offset) {
            if (ele.tagName === 'HTML') return offset
            if (offset) {
                offset.offsetLeft += ele.offsetLeft
                offset.offsetTop += ele.offsetTop
            }
            else {
                offset = {
                    offsetLeft: ele.offsetLeft,
                    offsetTop: ele.offsetTop,
                }
            }
            return getOffset(ele.parentElement, offset)
        }

        function find(ev) {
            let searchText = ev.target.value;
            let searchZH = searchText.match(/[\u4e00-\u9fa5]/g)
            searchZH = searchZH && searchZH.join(',').split(',')
            // 避免重复搜索
            if (!searchZH || lastText === searchZH.join('')) return
            lastText = searchZH.join('')
            let searchListDom = document.querySelector('.search-list')
            let searchDeductDom = document.querySelector('.search-deduct')

            if (searchZH && searchZH.length) {
                db.transaction(function (tx) {
                    Promise.all([...searchZH.map(char => executeSql(tx, `SELECT * FROM idiom WHERE name LIKE '%${char}%';`)), executeSql(tx, `SELECT * FROM idiom WHERE name LIKE '%${searchZH.join('')}%';`)]).then((res) => {

                        let dist = {}
                        res.map(({ rows }) => {
                            Object.values(rows).map((row) => {
                                if (!dist[row.ID]) dist[row.ID] = row
                            })
                        })
                        console.log(dist);
                        // 匹配搜索文字的正则
                        let matchReg = new RegExp(`[${searchZH.join('')}]`, 'g')
                        let searchList = Object.values(dist).sort((a, b) => b.name.match(matchReg).length - a.name.match(matchReg).length)


                        // 清除之前残余 
                        searchListDom.innerHTML = ''
                        searchDeductDom.innerHTML = ''


                        // 一刀下去只留前十个
                        searchList.slice(0, 10).forEach((item) => {
                            let searchItemDom = document.createElement('div')
                            searchItemDom.className = 'search-item'
                            searchItemDom.textContent = item.name

                            // 详情浮框
                            searchItemDom.addEventListener('mouseenter', function (ev) {
                                let idiomDetailDom = document.querySelector('.idiom-detail')
                                let nameDom = document.querySelector('.idiom-detail > .name')
                                let spellDom = document.querySelector('.idiom-detail > .spell')
                                let contentDom = document.querySelector('.idiom-detail > .content')
                                let derivationDom = document.querySelector('.idiom-detail > .derivation')
                                let samplesDom = document.querySelector('.idiom-detail > .samples')
                                let { content, derivation, name, samples, spell } = item
                                nameDom.textContent = name;
                                contentDom.textContent = content;
                                derivationDom.textContent = derivation;
                                spellDom.textContent = spell;
                                samplesDom.textContent = samples;
                                let { offsetLeft, offsetTop } = getOffset(ev.target)
                                // 不知道哪里样式出问题了
                                let tmpOffsetTop = 35
                                idiomDetailDom.setAttribute('style', `display: inline-block;left:${offsetLeft + ev.target.offsetWidth - 220}px;top:${offsetTop - ev.target.offsetHeight - tmpOffsetTop}px`)

                            })

                            searchListDom.appendChild(searchItemDom)
                        })




                        // 随机产生一组挖空词组
                        let searchDeduct = searchZH.reduce((targ, curr, index) => {
                            let tmpArr = searchList.filter(s => s.name.includes(curr) && !targ[s.name])
                            let tmp = null;
                            // 增加随机
                            if (tmpArr.length) {
                                tmp = tmpArr[Math.round(Math.random() * tmpArr.length)]
                            }
                            // 唯一判断
                            if (tmp && !targ[tmp.name]) {
                                targ[tmp.name] = JSON.parse(JSON.stringify(tmp));
                                targ[tmp.name].name = targ[tmp.name].name.replace(curr, '( )')
                                targ[tmp.name].index = index
                            }
                            return targ;
                        }, {})

                        let searchDeductTitleDom = document.createElement('div')
                        searchDeductTitleDom.className = 'title'
                        searchDeductTitleDom.textContent = '缺省补全'
                        searchDeductDom.appendChild(searchDeductTitleDom)

                        Object.values(searchDeduct).sort((a, b) => a.index - b.index).forEach((item) => {
                            let searchItemDom = document.createElement('div')
                            searchItemDom.className = 'search-item'
                            searchItemDom.textContent = item.name
                            searchDeductDom.appendChild(searchItemDom)
                        })

                    })
                })
            }
        }


        document.addEventListener("mousemove", (ev) => {
            if (!['idiom-detail', 'search-item'].includes(ev.target.className)) {
                let idiomDetailDom = document.querySelector('.idiom-detail')
                idiomDetailDom.setAttribute('style', `display: none;`)
            }
        })
    </script>
</body>

</html>

地址

https://github.com/linyisonger/H5.Examples

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/103508.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Codeforces Round #840 (Div. 2) and Enigma 2022 - Cybros LNMIIT题解

这场好难我是废物&#xff0c;掉大分了 A. Absolute Maximization 利用|找最大值和&找最小值即可 #include <bits/stdc.h> using namespace std; // #define int long long #define endl \nvoid solve() {int n;cin >> n;int maxn 0,minn 1023;for(int i …

TCP报文结构、确认应答机制、超时重传机制、连接管理机制

TCP报文结构、确认应答机制、超时重传机制、连接管理机制一、TCP报文结构二、确认应答机制三、超时重传机制四、连接管理机制4.1 三次握手建立连接4.2 四次挥手断开连接一、TCP报文结构 可靠传输是TCP中最最核心的特性&#xff01;&#xff01;&#xff01; 上篇博客我们已经介…

企事业单位如何做好服务器数据防泄露,防病毒工作

目前现状 无论是中小企业还是大型企事业单位&#xff0c;均有属于自己的内网或公有云服务器。这些服务器有的是专门的SVN、GIT代码服务器&#xff0c;有的是文档存储服务器&#xff0c;有的是应用服务器。服务器是企业的核心命脉&#xff0c;所有知识产权及多年心血都集中汇总…

【学习笔记】JDK源码学习之HashMap(附带面试题)

最近发布 AND 其他好文 &#xff1a;地址 什么是 HashMap &#xff1f;它和 Map 之间又有什么样的关系呢&#xff1f;我们是否能拿它在并发中使用呢&#xff1f; 带着以上问题&#xff0c;让我们一同走入这让人着迷的 HashMap 。 1、什么是HashMap&#xff1f; HashMap 基于…

DOM算法系列005-获取给定节点所属的window对象

UID: 20221220091217 aliases: tags: source: cssclass: created: 2022-12-20 我们知道&#xff0c;在一个HTML页面中&#xff0c;可以包含很多个框架或框架集&#xff0c;那么&#xff0c;当给定一个节点&#xff0c;我们如何获取这个节点所属的window对象呢&#xff1f; 首先…

【填坑向】Linux获取Java程序resource下的文件路径(这次的坑好像没填住……

​╮(&#xffe3;▽&#xffe3;"")╭没错&#xff0c;就是那个传说中的FileNotFoundException&#xff0c;文件找不到了 一开始&#xff0c;特别单纯的俺是把文件直接放在项目根目录的&#xff0c;获取文件地址的位置就只写了一个文件名&#xff08;相对路径&…

Nature子刊:生命的最初几个小时内可快速学习音位辨别—基于fNIRS研究

摘要 人类新生儿可以区分音素&#xff0c;但这种能力背后的神经机制尚不清楚。新生儿的大脑可以学会区分自然&#xff08;前&#xff09;元音和逆向&#xff08;后&#xff09;元音&#xff08;在子宫中学习不到的&#xff09;。利用功能近红外光谱&#xff0c;我们检测了出生…

工控CTF之协议分析2——MMS

协议分析 流量分析 主要以工控流量和恶意流量为主&#xff0c;难度较低的题目主要考察Wireshark使用和找规律&#xff0c;难度较高的题目主要考察协议定义和特征 简单只能简单得干篇一律&#xff0c;难可以难得五花八门 常见的工控协议有&#xff1a;Modbus、MMS、MQTT、CoA…

关于3D可视化的几个知识点

3D可视化&#xff0c;运用三维仿真技术实现信息感知、智能调度以及主动式运营维护&#xff0c;把复杂抽象的数据信息&#xff0c;以合适的人们视觉元素及视角用3D立体方式进行一比一还原呈现&#xff01; 近些年&#xff0c;将繁琐的信息通过可视化的图表视觉化展现出来的应用场…

惠普Elite蜻笔记本系统损坏怎么U盘重装教学

惠普Elite蜻笔记本系统损坏怎么U盘重装教学&#xff0c;有用户使用的惠普Elite蜻笔记本系统受到了其他恶意程序的损坏&#xff0c;导致无法正常的开启使用。所以想要去进行电脑系统的重装。那么如何U盘重装电脑系统&#xff0c;一起来看看详细的重装步骤吧。 准备工作&#xff…

有哪些实用的软件开发项目管理工具?

给大家介绍下&#xff0c;目前最新的免费项目管理工具&#xff0c;希望对大家有所帮助。 1、 Co-Project智能项目管理工具 智能项目管理平台&#xff0c;是CoCode旗下的软件开发全生命周期的项目管理平台&#xff0c;涵盖了从需求、计划、设计、开发、测试再到交付的整个项目周…

青少年关联网络功能地形的性别差异

我们发现了个性化联想网络功能地形的规范性性别差异&#xff0c;包括腹侧注意、默认模式和额顶网络。此外&#xff0c;染色体富集分析显示&#xff0c;功能地形多变量模式的性别差异在空间上与x连锁基因的表达以及星形细胞和兴奋性神经元细胞类型的特征相耦合。这些结果突出了性…

实景三维模型色彩差异大,用模方与DasViewer直接对模型调色

在实际项目生产过程中&#xff0c;由于受到采集天气、设备、时间、季节、航高等各类因素的影响&#xff0c;重建后的三维模型尤其是大面积模型中&#xff0c;纹理不可避免的出现明暗不一、颜色不均匀的现象&#xff0c;导致后期处理时间与成本增高&#xff0c;影响项目工期。 三…

Apache Flink

目录 处理无边界和有边界数据 数据可以作为无边界流或有边界流处理 随时随地部署应用程序 以任何规模运行应用程序 利用内存性能 Apache Flink 起源于一个叫作 Stratosphere 的项目&#xff0c;它是由 3 所地处柏林的大学和欧洲其他一些大学共同进行的研究项目&#xff0c…

[附源码]计算机毕业设计Node.js湖南旅游景点网站(程序+LW)

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

Java码客过去的一周年

入坑伊始 2021年12月20日 我本身就是一名计算机科学与技术的大学生&#xff0c;应该也算是行内的科班出身&#xff0c;但是在2021年12月20日之前&#xff0c;也就是离19届大学生考研差不多一年的时间&#xff0c;那时候有一周的SSM网站编程实训课程&#xff0c;惊讶的是虽然学…

别再用 JWT 作为 Session 系统了,问题重重,后果很危险!

SON Web Tokens&#xff0c;又称 JWT。本文将详解&#xff1a;为何 JWT 不适合存储 Session&#xff0c;以及 JWT 引发的安全隐患。望各位对JWT有更深的理解&#xff01; 十分不幸&#xff0c;我发现越来越多的人开始推荐使用 JWT 管理网站的用户会话&#xff08;Session&…

从头到尾Spring概念,家族,核心技术使用,事务这一篇就够了!!!

目录 1.了解Spring家族 家族成员 Spring常用项目介绍 2.Spring Framework体系结构 概述 体系图 3.Spring框架提供的核心技术 IOC控制反转 1.IOC与Spring的关系 2.什么是Bean DI 依赖注入 IoC/DI技术实现 1.基于XML的实现 2.基于注解的实现 3.基于java的实现 AO…

【案例实践】InVEST实践与进阶及在生态系统服务供需、固碳、城市热岛、论文写作中的应用

【查看原文】InVEST实践与进阶及在生态系统服务供需、固碳、城市热岛、论文写作等实际项目中的具体应用 【专家】&#xff1a; 白老师&#xff08;研究员&#xff09;&#xff1a;长期从事生态系统结构-格局-过程-功能-服务的变化与响应关系等研究工作&#xff1b;重点围绕生…

使用 .NET MAUI 开发 ChatGPT 客户端

最近 chatgpt 很火&#xff0c;由于网页版本限制了 ip&#xff0c;还得必须开代理&#xff0c;用起来比较麻烦&#xff0c;所以我尝试用 maui 开发一个聊天小应用&#xff0c;结合 chatgpt 的开放 api 来实现&#xff08;很多客户端使用网页版本接口用 cookie 的方式&#xff0…