Original link: https://www.zhangxinxu.com/wordpress/2022/08/gitee-feishu-okr-at-mention/
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=10513 Xin Space-Xin Life
This article can be reproduced in full text without authorization, welcome to share, welcome to like.
1. Effect preview
First look at the demo: https://zhangxinxu.gitee.io/okr-at-mention/
The effect is shown in the video below (click to play without moving), enter the @ character and a list of matching names will appear. Since it is a static page, the requested data is dead, and the actual development is dynamically returned by the backend according to the search keyword.
When the mouse hovers over the person’s name, a popover prompt will appear, and you can view information about the person.
In addition, this JS project filters the copied or dragged in rich text to ensure the purity of the content in the input box.
And the carriage return behavior is hijacked, for example, if you want the carriage return to not wrap, but to do other things, it is also possible.
project address
Project address: https://gitee.com/zhangxinxu/okr-at-mention
Welcome to Star, welcome to fork, and welcome to follow my gitee account. I will update some gadgets encountered at work from time to time, or interesting ideas that suddenly sprout.
2. Instructions for use
It is very simple to use, just import the corresponding CSS and JS, and then call it according to the exposed method.
E.g:
<link rel="stylesheet" href="./src/atMention.css">
Suppose there is a container element (that is, an input box element):
<div id="container"></div>
The corresponding JavaScript code can be used like this:
<script type="module"> import atWakaka from './src/atWakaka.js'; atWakaka('container', { url: './cgi/data.json' }); </script>
The corresponding function can be realized. It should be noted that this JS relies on attributejs, a well-known native AT mentioned JS. Therefore, when using it, you need to ensure that atWakaka.js has attributejs in the same directory.
Of course, different projects have different requirements for interaction details. Therefore, the corresponding API parameter interface is also provided.
Syntax and Parameters
The syntax is:
atWakaka(container, options, optionsTribute);
There’s no particular reason why it’s called “wakaka”, it’s just that I had this inexplicable urge at the time.
in:
- container
- An inputable edit box container element, either the DOM element itself or the element’s id string.
- options
- Optional parameters, with comments below.
{ url: '', // After pressing the enter key, if you want to prevent the default carriage return line feed // and do something, this parameter can be used pressEnter: null, // The prompt element passed by the mouse, this component will create it by default // You can also specify a specific element by yourself popOver: 'auto', // The processing of the mouse passing and moving out of the @ element // event is the event object // data is the request data corresponding to the @ element // popover is the floating layer element onMouseOver: function (event, data, popover) {}, onMouseOut: function (event, data, popover) {} }
- optionsTribute
- Optional parameter. See the parameter settings in https://github.com/zurb/tribute , or the use of the corresponding parameters in the source code (as shown below).
{ // Drop-down container class name containerClass: 'ui-at-drop-x', // No space required in front of it requireLeadingSpace: false, // Whether to highlight the match or not, here is to match by yourself// In fact, only skip is valid here searchOpts: { pre: '<mark>', post: '</mark>', // Whether the server searches for data skip: true }, // Dynamically get matching values values: valuesTribute, // HTML content returned when there is no data noMatchTemplate: function () {}, // Select the HTML content returned to the input box selectTemplate: function(item) {}, // HTML content of each item of the drop-down menu menuItemTemplate: function (item) {} };
If you want to change the element structure of the drop-down list, you can use the optional parameters in
optionsTribute
to set it.
3. Implementation skills
Here are three implementation techniques that I think are worth sharing with you.
1. @Description deleted and added
In an editable div element, if you want to make a certain text in it not editable, there is a simple way to set contenteditable="false"
. For example, the <span>
element in the following HTML code cannot be edited, and the text inside Five poisons do not invade.
<div contenteditable="true"> I am text, which can be deleted one by one, <span style="display:inline-block;" contenteditable="false">I can only delete it as a whole</span>! </div>
Then, the above implementation seems perfect, but there is actually a very troublesome problem. The cursor cannot be positioned behind the element with contenteditable="false"
, which leads me to want to position it behind @xxx, then delete it and do No, either JS observes and changes the cursor position in real time, or inserts a zero-width space after it.
No matter which method above, the cost is relatively high.
In the implementation of this JS, the single-tag element <hr>
is innovatively used to simulate the effect of @xxx. Since the textContent of the single-tag element itself is empty, there is no need to set contenteditable="false"
to delete only Delete the whole.
In all browsers, the <hr>
element supports the ::before/::after
pseudo-elements, so rich content and graphics can be created. Interested students can check out my previous article: ” 666, See how the hr tag implements the divider and plays with flowers “.
2. Hover appears floating layer interaction
It is not difficult to realize the interaction of the floating layer in Hover, but what if it is inside an editable div? And, if in a framework like Vue or React.
If you still follow the traditional implementation, find the corresponding trigger element, and then use the component to package it, there may be many problems, for example, the package cannot be packaged, and for example, the event cannot be bound.
Faced with such a scenario, the solution is similar, that is, delegation.
Bind the behavior of mouseover/mouseout to the container, and then perform positioning processing.
Because the container element is fixed, and the elements inside are changeable, binding to the container can be unchanged and the performance is better.
For specific implementation, see the JS source code .
3. Copy and paste or drag and drop into plain text
The rich text editor should not be able to type rich text by hand, but pasting and dragging can get rich text in.
Is there any way to filter rich text so that the content that the user pastes or drags is plain text by default?
Yes!
Browsers actually provide native capabilities.
Including getting the text and rich text content in the clipboard, and getting the text and rich text in the dragged content, at this time, we can prevent the default behavior and insert the plain text content.
Come to a trick to move flowers and trees without knowing it.
The relevant code is as follows (drag and paste combined, because the API is similar):
const doStripHtml = function (event) { var dataInput = event.clipboardData || event.dataTransfer; // rich text let htmlOrigin = dataInput.getData('text/html'); // plain text let textOrigin = dataInput.getData('text'); // if contains rich text if (htmlOrigin) { // Manually inserted // prevent default behavior event.preventDefault(); // Insert only plain text let lastRange = window.getSelection().getRangeAt(0); const newNode = document.createTextNode(textOrigin); lastRange.deleteContents(); lastRange.insertNode(newNode); lastRange.setStartAfter(newNode); event.target.focus(); } };
Among them, this code of inserting content is available for any rich text editor. For more knowledge about cursors and selections, please refer to this public account article: “Selection” and “Cursor” in the Web .
4. Conclusion
Using <hr>
to simulate the effect of @xxx is not flawless, and it is also a sacrifice. First of all, the text content of @xxx cannot be selected and copied, because the text generated by the pseudo element cannot be selected.
Secondly, when the data is submitted, it is not feasible to directly div.textContent, because the information such as @xxx will be lost, and additional processing is required.
However, the benefits are greater than the disadvantages.
Well, that’s all I have said, I hope it will be helpful to friends who encounter similar needs.
…
Tomorrow, September 1st, the children will start school. They should be happy. Unfortunately, they have to have various codes and reports every day.
(End of this article)
This article is reproduced from: https://www.zhangxinxu.com/wordpress/2022/08/gitee-feishu-okr-at-mention/
This site is for inclusion only, and the copyright belongs to the original author.