https://github.com/chinanf-boy/explain-clipboard
explain --> Clipboard copy or cut in bowser
https://github.com/chinanf-boy/explain-clipboard
clipboard explain explain-clipboard
Last synced: 5 months ago
JSON representation
explain --> Clipboard copy or cut in bowser
- Host: GitHub
- URL: https://github.com/chinanf-boy/explain-clipboard
- Owner: chinanf-boy
- Created: 2017-12-20T08:10:09.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2017-12-22T12:29:03.000Z (over 8 years ago)
- Last Synced: 2025-02-08T08:47:14.644Z (over 1 year ago)
- Topics: clipboard, explain, explain-clipboard
- Size: 14.6 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.ClipboardAction.md
Awesome Lists containing this project
README
# ClipboardAction
> 居然找到这里,我行动大魔王把 .btn 抓到这里
> [抢救你的 .btn](#点击事件) `<#######----or----#######>` [返回 Clipboard 类 解释家](./README.md)
---
抢救开始 `explain`
- [配置开始](#配置开始)
- [初始化复制目标](#初始化复制目标)
- [其他](#其他)
- tiny-emitter
- execCommand
- [select库 - 获取元素文本](#选定文本)
- [彩蛋](#类的属性)
---
点击事件之后
## 配置开始
在 ` Clipboard.js `中
``` js
this.clipboardAction = new ClipboardAction({
action : this.action(trigger),
target : this.target(trigger),
text : this.text(trigger),
container : this.container,
trigger : trigger,
emitter : this
});
}
```
### ClipboardAction.js 应用配置
``` js
constructor(options) {
this.resolveOptions(options); //<--
this.initSelection();
}
resolveOptions(options = {}) {
this.action = options.action;
this.container = options.container;
this.emitter = options.emitter;
this.target = options.target;
this.text = options.text;
this.trigger = options.trigger;
this.selectedText = '';
}
```
这个时候要注意啦
`this.action` 的 获得
``` js
constructor(options) {
// this.action == undefined --- 0
this.resolveOptions(options);
// this.action == copy 因为 set ---- 3
this.initSelection();
}
resolveOptions(options = {}) {
//-- set触发 this.action
this.action = options.action; // --- 下面的代码块
// --- 2
//...
}
```
``` js
set action(action = 'copy') { // <--- copy 初始化
this._action = action;
// --- 1
if (this._action !== 'copy' && this._action !== 'cut') {
throw new Error('Invalid "action" value, use either "copy" or "cut"');
}
}
```
可以看到, `this.action` -声明的顺序
>再找遍全代码都没有明确声明
>`this.action 默认 == 'copy'`
>居然用 `set`
[很有想法-讨论](#类的属性) or
next
---
### 初始化,需要复制的文本
``` js
constructor(options) {
this.resolveOptions(options);
this.initSelection(); //<--
}
/**
* Decides which selection strategy is going to be applied based
* on the existence of `text` and `target` properties.
*/
initSelection() {
if (this.text) { // 有没有 指定 text
// 指定了 Text
this.selectFake();
}
else if (this.target) { // 有没有指定 目标元素
// 指定了 目标元素
this.selectTarget();
}
}
```
next
---
## 初始化复制目标
还记得,我们这次的例子吗 `new Clipboard('.btn');`
在本次例子中 target 是存在的 , 当然你也可以看看 selectFake 做了什么
``` html

```
- [text存在 -> this.selectFake ](#文本存在) <-- 随便逛逛
- [target存在 -> this.selectTarget ](#目标存在) <--本次例子来这里
### 文本存在
``` js
/**
* Creates a fake textarea element, sets its value from `text` property,
* and makes a selection on it.
*/
selectFake() {
const isRTL = document.documentElement.getAttribute('dir') == 'rtl';
this.removeFake(); // <-- 进入先
...
}
/**
* Only removes the fake element after another click event, that way
* a user can hit `Ctrl+C` to copy because selection still exists.
*/
removeFake() { // 看来是移除 fake 事件和 元素
if (this.fakeHandler) {
this.container.removeEventListener('click', this.fakeHandlerCallback);
this.fakeHandler = null;
this.fakeHandlerCallback = null;
}
if (this.fakeElem) {
this.container.removeChild(this.fakeElem);
this.fakeElem = null;
}
}
```
next
``` js
selectFake() {
const isRTL = document.documentElement.getAttribute('dir') == 'rtl'; // ?
this.removeFake();
// 接下来
this.fakeHandlerCallback = () => this.removeFake();
// this.container == document.body
this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true;
// 创建一个 textarea 空元素
this.fakeElem = document.createElement('textarea');
// Prevent zooming on iOS
this.fakeElem.style.fontSize = '12pt';
// Reset box model
this.fakeElem.style.border = '0';
this.fakeElem.style.padding = '0';
this.fakeElem.style.margin = '0';
// Move element out of screen horizontally
this.fakeElem.style.position = 'absolute';
this.fakeElem.style[ isRTL ? 'right' : 'left' ] = '-9999px';
// Move element to the same position vertically
let yPosition = window.pageYOffset || document.documentElement.scrollTop;
this.fakeElem.style.top = `${yPosition}px`;
this.fakeElem.setAttribute('readonly', '');
this.fakeElem.value = this.text;
//______********_______*********
// this.fakeElem
//
// this.text is nothing
//
//top: *** 表示滚动网页离最上面的距离
// 所以其实,本次例子,没有进到 selectFake,因为有 target
this.container.appendChild(this.fakeElem);
this.selectedText = select(this.fakeElem); //?
this.copyText();
}
```
``` js
/**
* Only removes the fake element after another click event, that way
* a user can hit `Ctrl+C` to copy because selection still exists.
*/
removeFake() {
if (this.fakeHandler) {
// 全局 事件 remove
this.container.removeEventListener('click', this.fakeHandlerCallback);
this.fakeHandler = null;
this.fakeHandlerCallback = null;
}
if (this.fakeElem) { // 创建的 元素
//remove
this.container.removeChild(this.fakeElem);
this.fakeElem = null;
}
}
```
---
### 目标存在
``` js
/**
* Selects the content from element passed on `target` property.
*/
// 真的短,额不是我是说,真简洁
selectTarget() {
this.selectedText = select(this.target); //
this.copyText();
}
```
看来我们需要,[弄清楚 select库 的能力了--点击](#选定文本)
不过初步看应该是对元素 `element`的 `value` 进行选定
next
---
复制文本
`this.copyText`
``` js
/**
* Executes the copy operation based on the current selection.
*/
copyText() {
let succeeded;
try {
// this.action 默认 copy
succeeded = document.execCommand(this.action);
// 详细 execCommand 在 其他便签
}
catch (err) {
succeeded = false;
}
// succeeded == false
this.handleResult(succeeded);
}
/**
* Fires an event based on the copy operation result.
* @param {Boolean} succeeded
*/
handleResult(succeeded) {
// this.emitter
// Emitter.emit 类
// 触发一个命名的事件
// succeeded == false
this.emitter.emit(succeeded ? 'success' : 'error', {
action: this.action,
text: this.selectedText,
trigger: this.trigger,
clearSelection: this.clearSelection.bind(this)
});
}
```
[传递 `删除函数 destroy`](./README.md#L321)
or [源码--](./clipboard.js-master/src/clipboard.js#111)
``` js
/**
* Destroy lifecycle.
*/
destroy() {
this.removeFake();
}
```
## 其他
- [tiny-emitter 小于1](#https://github.com/scottcorgan/tiny-emitter)
- [document.execCommand- 命令](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/execCommand)
### 选定文本
select 库
``` js
import select from 'select';
```
[https://github.com/zenorocha/select](#https://github.com/zenorocha/select)
## 类的属性
使用 `set` 初始化 变量
示例
[http://jsbin.com/jogewib/edit?js,console](http://jsbin.com/jogewib/edit?js,console)
除了 `action` , 还有 `target`
``` js
/**
* Sets the `target` property using an element
* that will be have its content copied.
* @param {Element} target
*/
set target(target) {
if (target !== undefined) {
if (target && typeof target === 'object' && target.nodeType === 1) {
if (this.action === 'copy' && target.hasAttribute('disabled')) {
throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');
}
if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {
throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');
}
this._target = target;
}
else {
throw new Error('Invalid "target" value, use a valid Element');
}
}
}
/**
* Gets the `target` property.
* @return {String|HTMLElement}
*/
get target() {
return this._target;
}
```
对于 Clipboard 作者来说
`set`的作用似乎是`初始化变量`,以及 对 `变量的错误处理`