当前位置: 首页 > news >正文

JavaScript聊天框插入表情: 点击表情时输入框失焦, 无法插入到输入框.

文章目录

      • Preface
      • 问题原因
      • 解决问题
      • 源代码
      • svg 表情

Preface

最近在尝试做一个聊天框,但是在我做表情插入的时候被一个问题卡住了。
表情是使用的 img 标签;
本次最大问题就是: 点击表情时输入框失焦, 无法插入到输入框.

问题原因

当点击表情的时候, 输入框失去焦点, 聚焦到点击的标清处或失去焦点.

我尝试过点击的时候, 聚焦到输入框, 但是又出现了聚焦位置问题...  真是一波三折

解决问题

一开始做的时候, 我一直有个简单的解决思路, 但是我就是没去尝试. 就去搜索各种问题和解决办法.
最后还是妥协了

解决思路 : 既然是因为点击表情的时候, 焦点聚焦到表情选择了, 那我就不让表情选择框不能选中. 👍🏻 还真管用了.

给输入框加这个样式就可以解决, 如果要做兼容 记得添加属性前缀 -webkit- 等…

.input {
	user-select: none;
}

效果:
请添加图片描述

源代码

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

<head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  <title>Document</title>
  <link rel="stylesheet" href="/index.css" />
  <style>
    .emoji-box {
	  width: 300px;
	  user-select: none;
	}
	.emoji-box .emoji {
	  display: inline-block;
	  padding: 3px;
	}
	._emoji {
	  display: inline-block;
	  width: 18px;
	  height: 18px;
	  margin: 0 1px;
	  vertical-align: middle;
	}
	.input {
	  border: 1px solid orange;
	  width: 300px;
	  height: 120px;
	  outline: none;
	  display: inline-block;
	  font-size: 14px;
	}
  </style>
</head>

<body>
	<!-- tabindex: 让元素可聚焦, 拥有focus方法、可用tab切换焦点; -->
  <pre id="input" class="input" tabindex="0" contenteditable></pre>
  <script>
  	// 获取表情 url, 我这里demo使用的是固定的图片.
	function getImgUrl() {
	  return [
	    '1', 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 'sun'
	  ].map((x) => `/image/weather/${x}.png`)
	}

    // 插入表情列表
	function insertUl() {
	  let ul = document.createElement('div')
	  ul.className = 'emoji-box'
	  // 也可以使用 emoji 来作为表情, 但是我觉得太单一, 所以改用了 img方式来做.
	  // let emojis = '😀 🥹 ☺️ 😉 😗 😝 🤓 😏 😕 😫 😤 😳 😃 😅 😊 😌 😙 😜 😎 😒 😶‍🌫️ 🫥 🫢 🫢 🫣 🫣 🫠 🤔 🤫 😯 😵'.split(' ')
	  getImgUrl().forEach((url) => {
	    // ul.innerHTML += `<span class="emoji" data-type="EMOJI" style="cursor: pointer">${emoji}</span>`
	    ul.innerHTML += `<div data-type="EMOJI" data-url="${url}" style="display: inline-block;width: 22px; height: 22px; background: url(${url}) no-repeat center / 18px;cursor: pointer;"></div>`
	  })
	  document.body.appendChild(ul)
	  ul.onclick = tapUl
	}

	// 点击表情事件
	function tapUl(event) {
	  let e = event.target
	  insertImg(e.dataset.url)
	}
	
	// 插入表情到输入框
	function insertImg(src) {
	  if (window.getSelection) {
	      var sel = window.getSelection();
	      var range = sel.getRangeAt(0);
	      var img = new Image();
	      img.className = '_emoji'
	      range.deleteContents()
	      img.src = src;
	      range.insertNode(img);
	      range.collapse(false);
	  }
	}
  </script>
</body>
</html>

svg 表情

我还使用svg来测试插入表情, 存在一个大问题:

svg 不能够选中, 光标也不能移动到svg标签后.

在这里插入图片描述

svg标签的创建方式也比较特殊.
以下为 ts 代码

之前一直不知道 xxNS 的作用, 这下知道用途了
private onClickIcon(iconName: string) {
  const ns: string = "http://www.w3.org/2000/svg"
  const cNs: string = 'http://www.w3.org/1999/xlink'

  // NS 的第一个参数是svg的命名空间URI, svg 和 use 标签都有不同的 URI 注意区分.
  const oSvg: any = document.createElementNS(ns, 'svg')
  const use: any = document.createElementNS(ns, 'use')
  oSvg.setAttribute('style', 'width: 1em;height: 1em;') 
  oSvg.setAttribute('class', `svg-icon ${iconName}`)

  use.setAttributeNS(cNs, 'xlink:href', `#icon-${iconName}`)
  oSvg.appendChild(use)

  Insert.insertContent(oSvg)
}

相关文章:

  • 使用esxcli命令升级VMware ESXi补丁
  • java调用python文件的几种方式【超细讲解!】
  • c++ 关于bfs和dfs的相对统一写法
  • 2023年湖北三类人员安全员A证报考条件需要什么资料?
  • Maven进阶-多环境开发与跳过测试
  • Activiti7工作流引擎
  • 物联网边缘-物联网准入或接入安全防护产品及解决方案
  • Java-序列化和反序列化
  • 怎么批量转换图片格式?这些方法帮助你一键转换
  • ADB基本用法
  • 自定义 Hook(State Hook)_web前端培训
  • python医患档案管理系统vue+elementui+django
  • DPDK的几种buffer分配方式
  • 【图书管理系统】附源码+教程
  • 剑指 Offer II 073+076+078
  • 03Go 类型总结
  • ES6--对象的扩展
  • FineReport中如何实现自动滚屏效果
  • Java编程基础24——递归练习
  • java小心机(3)| 浅析finalize()
  • js正则,这点儿就够用了
  • Laravel 实践之路: 数据库迁移与数据填充
  • STAR法则
  • vuex 学习笔记 01
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 高性能JavaScript阅读简记(三)
  • 规范化安全开发 KOA 手脚架
  • 记一次删除Git记录中的大文件的过程
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 聊一聊前端的监控
  • 判断客户端类型,Android,iOS,PC
  • 设计模式 开闭原则
  • 使用阿里云发布分布式网站,开发时候应该注意什么?
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • 关于Android全面屏虚拟导航栏的适配总结
  • 新海诚画集[秒速5センチメートル:樱花抄·春]
  • #laravel 通过手动安装依赖PHPExcel#
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (2022 CVPR) Unbiased Teacher v2
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (C#)获取字符编码的类
  • (Matlab)基于蝙蝠算法实现电力系统经济调度
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (二)斐波那契Fabonacci函数
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (四)Controller接口控制器详解(三)
  • (一) springboot详细介绍
  • (一) storm的集群安装与配置
  • (一)基于IDEA的JAVA基础12
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .NET Core 和 .NET Framework 中的 MEF2
  • .Net mvc总结
  • .net 提取注释生成API文档 帮助文档