mirror of
https://github.com/S2-/gitlit
synced 2025-08-03 12:50:04 +02:00
fix search window
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
(function($) {
|
(function($) {
|
||||||
const ipcRenderer = require('electron').ipcRenderer;
|
const ipcRenderer = require('electron').ipcRenderer;
|
||||||
|
const remote = require('electron').remote;
|
||||||
|
const electronFind = require('electron-find');
|
||||||
|
let findInPage = new electronFind.FindInPage(remote.getCurrentWebContents());
|
||||||
|
|
||||||
//events
|
//events
|
||||||
ipcRenderer.on('fileList', (event, files) => {
|
ipcRenderer.on('fileList', (event, files) => {
|
||||||
@@ -71,6 +74,11 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
$(document).on('keypress', (ev) => {
|
$(document).on('keypress', (ev) => {
|
||||||
|
//ctrl + f
|
||||||
|
if (ev.ctrlKey && ev.charCode == 6) {
|
||||||
|
findInPage.openFindWindow();
|
||||||
|
}
|
||||||
|
|
||||||
//ctrl + r
|
//ctrl + r
|
||||||
if (ev.ctrlKey && ev.keyCode == 18) {
|
if (ev.ctrlKey && ev.keyCode == 18) {
|
||||||
window.location.reload(false);
|
window.location.reload(false);
|
||||||
|
126
app/node_modules/electron-find/README.md
generated
vendored
Normal file
126
app/node_modules/electron-find/README.md
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# electron-find
|
||||||
|
|
||||||
|
English | [简体中文](./README.zh-CN.md)
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
Find all matches for the text in electron app
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- depend on the API of electron's findInPage
|
||||||
|
- support user config UI of find interface
|
||||||
|
- support case-sensitive
|
||||||
|
- Auto find when user inputing is change
|
||||||
|
- The find interface is separated from electron view
|
||||||
|
- support electron version ^1.8.0, ^2.0.0, ^3.0.0, ^4.0.0
|
||||||
|
- support platform of Windows, Linux, Mac
|
||||||
|
|
||||||
|
## Demo
|
||||||
|
|
||||||
|
### Default UI
|
||||||
|

|
||||||
|
|
||||||
|
### Custom UI
|
||||||
|

|
||||||
|
|
||||||
|
## Install
|
||||||
|
```
|
||||||
|
$ npm install electron-find --save
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
```
|
||||||
|
# import module
|
||||||
|
import { remote, ipcRenderer } from 'electron'
|
||||||
|
import { FindInPage } from 'electron-find'
|
||||||
|
|
||||||
|
# create instance of FindInPage with default config
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents())
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
|
||||||
|
# use preload option, the find interface will be loaded when create instance
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||||
|
preload: true
|
||||||
|
})
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
|
||||||
|
# config parentElement of find interface, default is document.body
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||||
|
parentElement: document.querySelector('#id')
|
||||||
|
})
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
|
||||||
|
# config duration of find interface moving, default is 300 (ms)
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||||
|
duration: 200
|
||||||
|
})
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
|
||||||
|
# config offset relative to parentElement
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||||
|
offsetTop: 20,
|
||||||
|
offsetRight: 30
|
||||||
|
})
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
|
||||||
|
# config UI of find interface
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||||
|
boxBgColor: '#333',
|
||||||
|
boxShadowColor: '#000',
|
||||||
|
inputColor: '#aaa',
|
||||||
|
inputBgColor: '#222',
|
||||||
|
inputFocusColor: '#555',
|
||||||
|
textColor: '#aaa',
|
||||||
|
textHoverBgColor: '#555',
|
||||||
|
caseSelectedColor: '#555'
|
||||||
|
})
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
|
||||||
|
# there is a simply demo for reference
|
||||||
|
npm install
|
||||||
|
npm run e
|
||||||
|
```
|
||||||
|
## Shortcut
|
||||||
|
| keys | function |
|
||||||
|
| ------ | ------ |
|
||||||
|
| Enter | find next |
|
||||||
|
| Shift + Enter| find back |
|
||||||
|
| Esc | close |
|
||||||
|
|
||||||
|
Besides, you can also register global shortcut to open the find window, just like the demo.
|
||||||
|
|
||||||
|
## API
|
||||||
|
### Class: FindInPage
|
||||||
|
` new FindInPage(webContents, [options]) `
|
||||||
|
- ` webContents ` Object(required) - The webContents of renderer process
|
||||||
|
- ` options ` Object(optional)
|
||||||
|
- ` preload ` Boolean - Whether load the find interface when create instance. Default is `false`.
|
||||||
|
- ` parentElement ` Object - Specify parent dom of the find interface. Default is `document.body`.
|
||||||
|
- ` duration ` Number - Specify moving time when the find window open or close. Default is `300` (ms).
|
||||||
|
- ` offsetTop ` Number - Specify offset relative to the top of parentElement. Default is `5`.
|
||||||
|
- ` offsetRight ` Number - Specify offset relative to the right of parentElement. Default is `5`.
|
||||||
|
- ` boxBgColor ` String - Specify background color of the find interface. Default is `"#ffffff"`.
|
||||||
|
- ` boxShadowColor ` String - Specify shadow color of the find interface. Default is `"#909399"`.
|
||||||
|
- ` inputColor ` String - Specify text color of the input form. Default is "#606266".
|
||||||
|
- ` inputBgColor ` String - Specify background color of the input form. Default is `"#f0f0f0"`.
|
||||||
|
- ` inputFocusColor ` String - Specify border color of the input form when focusing. Default is `"#c5ade0"`.
|
||||||
|
- ` textColor ` String - Specify color of the text in find interface. Default is `"#606266"`.
|
||||||
|
- ` textHoverBgColor ` String - Specify background color of text in find interface when hovering. Default is `"#eaeaea"`.
|
||||||
|
- ` caseSelectedColor ` String - Specify border color of the matchCase button when selected. Default is `"#c5ade0"`.
|
||||||
|
|
||||||
|
### Instance Methods
|
||||||
|
Objects created with new FindInPage have the following instance methods:
|
||||||
|
|
||||||
|
` findInPage.openFindWindow() `
|
||||||
|
Open the find window when it is closed. Focus input form when the find window has opened.
|
||||||
|
|
||||||
|
` findInPage.closeFindWindow() `
|
||||||
|
Close the find window when it has opened.
|
||||||
|
|
||||||
|
` findInPage.destroy() `
|
||||||
|
Close the find window, and release memery.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
126
app/node_modules/electron-find/README.zh-CN.md
generated
vendored
Normal file
126
app/node_modules/electron-find/README.zh-CN.md
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
# electron-find
|
||||||
|
|
||||||
|
简体中文 | [English](./README.md)
|
||||||
|
|
||||||
|
## 简介
|
||||||
|
在Electron app页内查找匹配关键字的所有文本字符
|
||||||
|
|
||||||
|
## 特征
|
||||||
|
- 依赖于Electron的findInPage API
|
||||||
|
- 支持使用者灵活配置UI界面
|
||||||
|
- 支持区分大小写
|
||||||
|
- 当用户输入时自动查找
|
||||||
|
- 查找输入框文本隔离,不会被匹配到
|
||||||
|
- 支持以下Electron版本 ^1.8.7, ^2.0.0, ^3.0.0, ^4.0.0
|
||||||
|
- 支持以下平台 Windows, Linux, Mac
|
||||||
|
|
||||||
|
## 演示
|
||||||
|
|
||||||
|
### 默认UI
|
||||||
|

|
||||||
|
|
||||||
|
### 定制化UI
|
||||||
|

|
||||||
|
|
||||||
|
## 安装
|
||||||
|
```
|
||||||
|
$ npm install electron-find --save
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用
|
||||||
|
```
|
||||||
|
# 引入模块
|
||||||
|
import { remote, ipcRenderer } from 'electron'
|
||||||
|
import { FindInPage } from 'electron-find'
|
||||||
|
|
||||||
|
# 使用默认配置来创建实例
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents())
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
|
||||||
|
# 开启预加载选项,创建实例的时候会同时加载查找窗口相关dom
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||||
|
preload: true
|
||||||
|
})
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
|
||||||
|
# 配置父节点元素, 默认为 document.body
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||||
|
parentElement: document.querySelector('#id')
|
||||||
|
})
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
|
||||||
|
# 配置查找窗口显示或隐藏的过渡周期, 默认为 300 (ms)
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||||
|
duration: 200
|
||||||
|
})
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
|
||||||
|
# 配置查找窗口相对于父级定位节点的偏移量
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||||
|
offsetTop: 20,
|
||||||
|
offsetRight: 30
|
||||||
|
})
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
|
||||||
|
# 自定义UI界面颜色
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||||
|
boxBgColor: '#333',
|
||||||
|
boxShadowColor: '#000',
|
||||||
|
inputColor: '#aaa',
|
||||||
|
inputBgColor: '#222',
|
||||||
|
inputFocusColor: '#555',
|
||||||
|
textColor: '#aaa',
|
||||||
|
textHoverBgColor: '#555',
|
||||||
|
caseSelectedColor: '#555'
|
||||||
|
})
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
|
||||||
|
# 参考demo
|
||||||
|
npm install
|
||||||
|
npm run e
|
||||||
|
```
|
||||||
|
## 快捷键
|
||||||
|
| 键 | 功能 |
|
||||||
|
| ------ | ------ |
|
||||||
|
| Enter | 查找上一个 |
|
||||||
|
| Shift + Enter| 查找下一个 |
|
||||||
|
| Esc | 关闭窗口 |
|
||||||
|
|
||||||
|
另外, 可以参考demo,使用全局快捷键来打开窗口。
|
||||||
|
|
||||||
|
## API
|
||||||
|
### Class: FindInPage
|
||||||
|
` new FindInPage(webContents, [options]) `
|
||||||
|
- ` webContents ` Object(required) - 渲染进程的webContents对象
|
||||||
|
- ` options ` Object(optional)
|
||||||
|
- ` preload ` Boolean - 创建实例的时候是否预加载查找窗口。 默认为 `false`。
|
||||||
|
- ` parentElement ` Object - 指定查找窗口的父级节点。 默认为 `document.body`。
|
||||||
|
- ` duration ` Number - 指定查找窗口显示或隐藏的过渡周期。 默认为 `300` (ms)。
|
||||||
|
- ` offsetTop ` Number - 指定查找窗口相对于父级定位元素顶部偏移量。 默认为 `5`。
|
||||||
|
- ` offsetRight ` Number - 指定查找窗口相对于父级定位元素右边偏移量。 默认为 `5`。
|
||||||
|
- ` boxBgColor ` String - 配置查找窗口背景色。 默认为 `"#ffffff"`。
|
||||||
|
- ` boxShadowColor ` String - 配置查找窗口阴影色。 默认为 `"#909399"`。
|
||||||
|
- ` inputColor ` String - 配置输入框文本颜色。 默认为 "#606266"。
|
||||||
|
- ` inputBgColor ` String - 配置输入框背景颜色。 默认为 `"#f0f0f0"`。
|
||||||
|
- ` inputFocusColor ` String - 配置输入框聚焦时的边框颜色。 默认为 `"#c5ade0"`。
|
||||||
|
- ` textColor ` String - 配置查找窗口中文本颜色。 默认为 `"#606266"`。
|
||||||
|
- ` textHoverBgColor ` String - 配置鼠标悬停文本时的背景色。 默认为 `"#eaeaea"`。
|
||||||
|
- ` caseSelectedColor ` String - 配置区分大小写选项选中时的边框颜色。 默认为 `"#c5ade0"`。
|
||||||
|
|
||||||
|
### Instance Methods
|
||||||
|
使用new FindInPage 创建的实例具有以下方法:
|
||||||
|
|
||||||
|
` findInPage.openFindWindow() `
|
||||||
|
当查找窗口关闭时,打开窗口。 当查找窗口已经打开时,聚焦输入框。
|
||||||
|
|
||||||
|
` findInPage.closeFindWindow() `
|
||||||
|
关闭窗口。
|
||||||
|
|
||||||
|
` findInPage.destroy() `
|
||||||
|
关闭窗口,清除对象的引用,释放内存。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
14
app/node_modules/electron-find/example/example.css
generated
vendored
Normal file
14
app/node_modules/electron-find/example/example.css
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
html,
|
||||||
|
body{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
section{
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
h3{
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
26
app/node_modules/electron-find/example/example.js
generated
vendored
Normal file
26
app/node_modules/electron-find/example/example.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
const { remote, ipcRenderer } = require('electron')
|
||||||
|
const { FindInPage } = require('../src/index.js')
|
||||||
|
|
||||||
|
|
||||||
|
let findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||||
|
preload: true,
|
||||||
|
offsetTop: 6,
|
||||||
|
offsetRight: 10
|
||||||
|
})
|
||||||
|
|
||||||
|
// let findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||||
|
// boxBgColor: '#333',
|
||||||
|
// boxShadowColor: '#000',
|
||||||
|
// inputColor: '#aaa',
|
||||||
|
// inputBgColor: '#222',
|
||||||
|
// inputFocusColor: '#555',
|
||||||
|
// textColor: '#aaa',
|
||||||
|
// textHoverBgColor: '#555',
|
||||||
|
// caseSelectedColor: '#555',
|
||||||
|
// offsetTop: 8,
|
||||||
|
// offsetRight: 12
|
||||||
|
// })
|
||||||
|
|
||||||
|
ipcRenderer.on('on-find', (e, args) => {
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
})
|
54
app/node_modules/electron-find/example/index.html
generated
vendored
Normal file
54
app/node_modules/electron-find/example/index.html
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Example</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="./example.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<section>
|
||||||
|
<h3>关于 Electron</h3>
|
||||||
|
<p>
|
||||||
|
Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库。
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Electron通过将Chromium和Node.js合并到同一个运行时环境中,并将其打包为Mac,Windows和Linux系统下的应用来实现这一目的。
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Electron于2013年作为构建Github上可编程的文本编辑器Atom的框架而被开发出来。这两个项目在2014春季开源。
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
目前它已成为开源开发者、初创企业和老牌公司常用的开发工具。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>长期支持</h3>
|
||||||
|
<p>
|
||||||
|
当前并不存在对Electron旧版本的长期支持
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
如果现在你使用的Electron版本跑得不错,你就可以一直使用这个版本。
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
如果你想使用新发布的特性,那就升级到更新的版本。
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
版本v1.0.0发布了重大的更新。 如果你现在没有在用这个版本,你应该了解更多关于v1.0.0的改变。
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>核心理念</h3>
|
||||||
|
<p>
|
||||||
|
为了保持Electron的小巧 (文件体积) 和可持续性开发 (以防依赖库和API的泛滥) ,Electron限制了所使用的核心项目的数量。
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
比如Electron只用了Chromium的渲染库而不是其全部组件。
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
这使得升级Chromium更加容易,但也意味着Electron缺少了Google Chrome里的一些浏览器相关的特性
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
添加到Electron的新功能应该主要是原生 API。 如果可以的话,一个功能应该尽可能的成为一个Node.js模块。
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<script src="example.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
47
app/node_modules/electron-find/example/main.js
generated
vendored
Normal file
47
app/node_modules/electron-find/example/main.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
const electron = require('electron')
|
||||||
|
const { app, BrowserWindow, globalShortcut } = electron
|
||||||
|
const path = require('path')
|
||||||
|
let win
|
||||||
|
const winURL = 'file://' + path.normalize(`${__dirname}/index.html`)
|
||||||
|
|
||||||
|
function createWindow () {
|
||||||
|
win = new BrowserWindow({
|
||||||
|
width: 1280,
|
||||||
|
height: 1040,
|
||||||
|
center: false,
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
plugins: true,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
win.loadURL(winURL)
|
||||||
|
//win.webContents.openDevTools()
|
||||||
|
win.on('closed', () => {
|
||||||
|
win = null
|
||||||
|
})
|
||||||
|
|
||||||
|
win.on('focus', () => {
|
||||||
|
globalShortcut.register('CommandOrControl+F', function () {
|
||||||
|
if (win && win.webContents) {
|
||||||
|
win.webContents.send('on-find', '')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
win.on('blur', () => {
|
||||||
|
globalShortcut.unregister('CommandOrControl+F')
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
app.on('ready', createWindow)
|
||||||
|
app.on('window-all-closed', () => {
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
app.quit()
|
||||||
|
}
|
||||||
|
globalShortcut.unregister('CommandOrControl+F')
|
||||||
|
})
|
||||||
|
|
||||||
|
app.on('activate', () => {
|
||||||
|
if (win === null) createWindow()
|
||||||
|
})
|
||||||
|
|
22
app/node_modules/electron-find/example2/inner1.html
generated
vendored
Normal file
22
app/node_modules/electron-find/example2/inner1.html
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>webview 1</title>
|
||||||
|
<style>
|
||||||
|
.content{
|
||||||
|
margin: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid rgb(236, 119, 236);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="content">
|
||||||
|
<h3>In webview 1</h3>
|
||||||
|
<div>content 1</div>
|
||||||
|
<div>content 1</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
22
app/node_modules/electron-find/example2/inner2.html
generated
vendored
Normal file
22
app/node_modules/electron-find/example2/inner2.html
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>webview 2</title>
|
||||||
|
<style>
|
||||||
|
.content{
|
||||||
|
margin: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid rgb(164, 195, 216);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="content">
|
||||||
|
<h3>In webview 2</h3>
|
||||||
|
<div>content 2</div>
|
||||||
|
<div>content 2</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
47
app/node_modules/electron-find/example2/main.js
generated
vendored
Normal file
47
app/node_modules/electron-find/example2/main.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
const electron = require('electron')
|
||||||
|
const { app, BrowserWindow, globalShortcut } = electron
|
||||||
|
const path = require('path')
|
||||||
|
let win
|
||||||
|
const winURL = 'file://' + path.normalize(`${__dirname}/outer.html`)
|
||||||
|
|
||||||
|
function createWindow () {
|
||||||
|
win = new BrowserWindow({
|
||||||
|
width: 1280,
|
||||||
|
height: 1040,
|
||||||
|
center: false,
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true,
|
||||||
|
plugins: true,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
win.loadURL(winURL)
|
||||||
|
//win.webContents.openDevTools()
|
||||||
|
win.on('closed', () => {
|
||||||
|
win = null
|
||||||
|
})
|
||||||
|
|
||||||
|
win.on('focus', () => {
|
||||||
|
globalShortcut.register('CommandOrControl+F', function () {
|
||||||
|
if (win && win.webContents) {
|
||||||
|
win.webContents.send('on-find', '')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
win.on('blur', () => {
|
||||||
|
globalShortcut.unregister('CommandOrControl+F')
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
app.on('ready', createWindow)
|
||||||
|
app.on('window-all-closed', () => {
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
app.quit()
|
||||||
|
}
|
||||||
|
globalShortcut.unregister('CommandOrControl+F')
|
||||||
|
})
|
||||||
|
|
||||||
|
app.on('activate', () => {
|
||||||
|
if (win === null) createWindow()
|
||||||
|
})
|
||||||
|
|
27
app/node_modules/electron-find/example2/outer.html
generated
vendored
Normal file
27
app/node_modules/electron-find/example2/outer.html
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Outer</title>
|
||||||
|
<style>
|
||||||
|
.app{
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.outer{
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="app">
|
||||||
|
<div class="outer">
|
||||||
|
<h3>Is in app</h3>
|
||||||
|
<div>Main content</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<webview id="webview1" src="./inner1.html"></webview>
|
||||||
|
<webview id="webview2" src="./inner2.html"></webview>
|
||||||
|
</div>
|
||||||
|
<script src="outer.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
37
app/node_modules/electron-find/example2/outer.js
generated
vendored
Normal file
37
app/node_modules/electron-find/example2/outer.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
const { remote, ipcRenderer } = require('electron')
|
||||||
|
const { FindInPage } = require('../src/index.js')
|
||||||
|
|
||||||
|
let findInPage = null
|
||||||
|
const webview1 = document.querySelector('#webview1')
|
||||||
|
webview1.addEventListener('dom-ready', () => {
|
||||||
|
findInPage = new FindInPage(webview1.getWebContents())
|
||||||
|
ipcRenderer.on('on-find', (e, args) => {
|
||||||
|
findInPage.openFindWindow()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
webview1.addEventListener('close', () => {
|
||||||
|
console.log('webview1 close', )
|
||||||
|
if (findInPage) {
|
||||||
|
findInPage.destroy()
|
||||||
|
findInPage = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
webview1.addEventListener('destroyed', () => {
|
||||||
|
console.log('webview1 destroyed', )
|
||||||
|
if (findInPage) {
|
||||||
|
findInPage.destroy()
|
||||||
|
findInPage = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
webview1.addEventListener('crashed', () => {
|
||||||
|
console.log('webview1 crashed', )
|
||||||
|
if (findInPage) {
|
||||||
|
findInPage.destroy()
|
||||||
|
findInPage = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcRenderer.on('on-find', (e, args) => {
|
||||||
|
findInPage ? findInPage.openFindWindow() : ''
|
||||||
|
})
|
BIN
app/node_modules/electron-find/find.gif
generated
vendored
Normal file
BIN
app/node_modules/electron-find/find.gif
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 440 KiB |
BIN
app/node_modules/electron-find/find2.png
generated
vendored
Normal file
BIN
app/node_modules/electron-find/find2.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
57
app/node_modules/electron-find/package.json
generated
vendored
Normal file
57
app/node_modules/electron-find/package.json
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"_from": "electron-find",
|
||||||
|
"_id": "electron-find@1.0.6",
|
||||||
|
"_inBundle": false,
|
||||||
|
"_integrity": "sha512-RenjzlCCzX7edLywLy+qRYvzds11sBv8+SrJu/3l3eVLt9d9uNqCPk+uFZ525uAhSUaUalgZWDlhQdxIgT1khg==",
|
||||||
|
"_location": "/electron-find",
|
||||||
|
"_phantomChildren": {},
|
||||||
|
"_requested": {
|
||||||
|
"type": "tag",
|
||||||
|
"registry": true,
|
||||||
|
"raw": "electron-find",
|
||||||
|
"name": "electron-find",
|
||||||
|
"escapedName": "electron-find",
|
||||||
|
"rawSpec": "",
|
||||||
|
"saveSpec": null,
|
||||||
|
"fetchSpec": "latest"
|
||||||
|
},
|
||||||
|
"_requiredBy": [
|
||||||
|
"#USER",
|
||||||
|
"/"
|
||||||
|
],
|
||||||
|
"_resolved": "https://registry.npmjs.org/electron-find/-/electron-find-1.0.6.tgz",
|
||||||
|
"_shasum": "e10e4be3eb0b634ed0d3acf383720fef39698cdb",
|
||||||
|
"_spec": "electron-find",
|
||||||
|
"_where": "F:\\projects\\p\\gitlit\\app",
|
||||||
|
"author": {
|
||||||
|
"name": "TheoXiong"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/TheoXiong/electron-find/issues"
|
||||||
|
},
|
||||||
|
"bundleDependencies": false,
|
||||||
|
"deprecated": false,
|
||||||
|
"description": "Find all matches for the text in electron app",
|
||||||
|
"devDependencies": {
|
||||||
|
"electron": "^2.0.0"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/TheoXiong/electron-find#readme",
|
||||||
|
"keywords": [
|
||||||
|
"find",
|
||||||
|
"electron",
|
||||||
|
"search",
|
||||||
|
"match"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "src/index.js",
|
||||||
|
"name": "electron-find",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/TheoXiong/electron-find.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"e": "electron example/main.js",
|
||||||
|
"e2": "electron example2/main.js"
|
||||||
|
},
|
||||||
|
"version": "1.0.6"
|
||||||
|
}
|
93
app/node_modules/electron-find/src/find.js
generated
vendored
Normal file
93
app/node_modules/electron-find/src/find.js
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
const EventEmitter = require('events')
|
||||||
|
const { print } = require('./utils.js')
|
||||||
|
|
||||||
|
const stopActions = ['clearSelection', 'keepSelection', 'activateSelection']
|
||||||
|
const wcs = Symbol('webContents')
|
||||||
|
const opts = Symbol('options')
|
||||||
|
const requestId = Symbol('requestId')
|
||||||
|
const activeMatch = Symbol('activeMatch')
|
||||||
|
const matches = Symbol('matches')
|
||||||
|
const initd = Symbol('initd')
|
||||||
|
const preText = Symbol('preText')
|
||||||
|
|
||||||
|
class Find extends EventEmitter {
|
||||||
|
constructor (webContents, options = {}) {
|
||||||
|
super()
|
||||||
|
this[wcs] = webContents
|
||||||
|
this[opts] = options
|
||||||
|
this[requestId] = null
|
||||||
|
this[activeMatch] = 0
|
||||||
|
this[matches] = 0
|
||||||
|
this[initd] = false
|
||||||
|
this[preText] = ''
|
||||||
|
}
|
||||||
|
initFind () {
|
||||||
|
if (this[initd]) return false
|
||||||
|
if (isWebContents.call(this)) {
|
||||||
|
bindFound.call(this)
|
||||||
|
return this[initd] = true
|
||||||
|
} else {
|
||||||
|
throw new Error('[Find] In need of a valid webContents !')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destroyFind () {
|
||||||
|
this[wcs] = null
|
||||||
|
this[opts] = null
|
||||||
|
this[requestId] = null
|
||||||
|
this[activeMatch] = 0
|
||||||
|
this[matches] = 0
|
||||||
|
this[initd] = false
|
||||||
|
this[preText] = ''
|
||||||
|
}
|
||||||
|
isFinding () {
|
||||||
|
return !!this[requestId]
|
||||||
|
}
|
||||||
|
startFind (text = '', forward = true, matchCase = false) {
|
||||||
|
if (!text) return
|
||||||
|
this[activeMatch] = 0
|
||||||
|
this[matches] = 0
|
||||||
|
this[preText] = text
|
||||||
|
this[requestId] = this[wcs].findInPage(this[preText], {
|
||||||
|
forward,
|
||||||
|
matchCase
|
||||||
|
})
|
||||||
|
print(`[Find] startFind text=${text} forward=${forward} matchCase=${matchCase}`)
|
||||||
|
}
|
||||||
|
findNext (forward, matchCase = false) {
|
||||||
|
if (!this.isFinding()) throw new Error('Finding did not start yet !')
|
||||||
|
this[requestId] = this[wcs].findInPage(this[preText], {
|
||||||
|
forward,
|
||||||
|
matchCase,
|
||||||
|
findNext: true
|
||||||
|
})
|
||||||
|
print(`[Find] findNext text=${this[preText]} forward=${forward} matchCase=${matchCase}`)
|
||||||
|
}
|
||||||
|
stopFind (action) {
|
||||||
|
stopActions.includes(action) ? '' : action = 'clearSelection'
|
||||||
|
this[wcs].stopFindInPage(action)
|
||||||
|
print(`[Find] stopFind action=${action}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isWebContents () {
|
||||||
|
return (this[wcs] &&
|
||||||
|
typeof this[wcs].findInPage === 'function' &&
|
||||||
|
typeof this[wcs].stopFindInPage === 'function')
|
||||||
|
}
|
||||||
|
function bindFound () {
|
||||||
|
this[wcs].on('found-in-page', (e, r) => {
|
||||||
|
onFoundInPage.call(this, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function onFoundInPage (result) {
|
||||||
|
print('[Find] onFoundInPage, ', result)
|
||||||
|
if (this[requestId] !== result.requestId) return
|
||||||
|
typeof result.activeMatchOrdinal === 'number' ? this[activeMatch] = result.activeMatchOrdinal : ''
|
||||||
|
typeof result.matches === 'number' ? this[matches] = result.matches : ''
|
||||||
|
result.finalUpdate ? reportResult.call(this) : ''
|
||||||
|
}
|
||||||
|
function reportResult () {
|
||||||
|
this.emit('result', this[activeMatch], this[matches])
|
||||||
|
typeof this[opts].onResult === 'function' ? this[opts].onResult(this[activeMatch], this[matches]) : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Find
|
470
app/node_modules/electron-find/src/findInPage.js
generated
vendored
Normal file
470
app/node_modules/electron-find/src/findInPage.js
generated
vendored
Normal file
@@ -0,0 +1,470 @@
|
|||||||
|
const Find = require('./find.js')
|
||||||
|
const { print, on, off, move } = require('./utils.js')
|
||||||
|
|
||||||
|
const INPUT_INTERVAL_THRESHOLD = 360
|
||||||
|
|
||||||
|
const findBox = Symbol('findBox')
|
||||||
|
const findInput = Symbol('findInput')
|
||||||
|
const findMatches = Symbol('findMatches')
|
||||||
|
const findCase = Symbol('findCase')
|
||||||
|
const findBack = Symbol('findBack')
|
||||||
|
const findForward = Symbol('findForward')
|
||||||
|
const findClose = Symbol('findClose')
|
||||||
|
const hasOpened = Symbol('hasOpened')
|
||||||
|
const matchCase = Symbol('matchCase')
|
||||||
|
|
||||||
|
const documentKeydown = Symbol('documentKeydown')
|
||||||
|
const inputFocus = Symbol('inputFocus')
|
||||||
|
const inputBlur = Symbol('inputBlur')
|
||||||
|
const inputEvent = Symbol('inputEvent')
|
||||||
|
const compositionstart = Symbol('compositionstart')
|
||||||
|
const compositionend = Symbol('compositionend')
|
||||||
|
const caseMouseenter = Symbol('caseMouseenter')
|
||||||
|
const caseMouseleave = Symbol('caseMouseleave')
|
||||||
|
const caseClick = Symbol('caseClick')
|
||||||
|
const backMouseenter = Symbol('backMouseenter')
|
||||||
|
const backMouseleave = Symbol('backMouseleave')
|
||||||
|
const backClick = Symbol('backClick')
|
||||||
|
const forwardMouseenter = Symbol('forwardMouseenter')
|
||||||
|
const forwardMouseleave = Symbol('forwardMouseleave')
|
||||||
|
const forwardClick = Symbol('forwardClick')
|
||||||
|
const closeMouseenter = Symbol('closeMouseenter')
|
||||||
|
const closeMouseleave = Symbol('closeMouseleave')
|
||||||
|
const closeClick = Symbol('closeClick')
|
||||||
|
const events = Symbol('events')
|
||||||
|
|
||||||
|
const inComposition = Symbol('inComposition')
|
||||||
|
const action = Symbol('action')
|
||||||
|
const lastText = Symbol('lastText')
|
||||||
|
const inputCnt = Symbol('inputCnt')
|
||||||
|
const initialized = Symbol('initialized')
|
||||||
|
const config = Symbol('config')
|
||||||
|
|
||||||
|
class FindInPage extends Find{
|
||||||
|
constructor (webContents, options = {}) {
|
||||||
|
super(webContents)
|
||||||
|
this[findBox] = null
|
||||||
|
this[findInput] = null
|
||||||
|
this[findMatches] = null
|
||||||
|
this[findCase] = null
|
||||||
|
this[findBack] = null
|
||||||
|
this[findForward] = null
|
||||||
|
this[findClose] = null
|
||||||
|
this[hasOpened] = false
|
||||||
|
this[matchCase] = false
|
||||||
|
this[inComposition] = false
|
||||||
|
this[action] = ''
|
||||||
|
this[lastText] = ''
|
||||||
|
this[inputCnt] = 0
|
||||||
|
this[initialized] = false
|
||||||
|
this[config] = {}
|
||||||
|
this[events] = []
|
||||||
|
this.parentElement = options.parentElement ? options.parentElement : document.body
|
||||||
|
this.duration = (typeof options.duration === 'number' && options.duration > 0) ? options.duration : 300
|
||||||
|
this.options = options
|
||||||
|
this.options.preload ? this.initialize() : ''
|
||||||
|
}
|
||||||
|
initialize () {
|
||||||
|
if (this[initialized]) {
|
||||||
|
print('[FindInPage] Has initialize.')
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (!this.initFind()) {
|
||||||
|
print('[FindInPage] Failed to initialize.')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this[findBox] = creatElement('find-box')
|
||||||
|
this[findInput] = creatElement('find-input', 'input')
|
||||||
|
this[findMatches] = creatElement('find-matches')
|
||||||
|
this[findCase] = creatElement('find-case')
|
||||||
|
this[findBack] = creatElement('find-back')
|
||||||
|
this[findForward] = creatElement('find-forward')
|
||||||
|
this[findClose] = creatElement('find-close')
|
||||||
|
getUserConfig.call(this, this.options)
|
||||||
|
setBoxStyle.call(this)
|
||||||
|
setInputStyle.call(this)
|
||||||
|
setMatchesStyle.call(this)
|
||||||
|
setCaseStyle.call(this)
|
||||||
|
setBackStyle.call(this)
|
||||||
|
setForwardStyle.call(this)
|
||||||
|
setCloseStyle.call(this)
|
||||||
|
lockNext.call(this)
|
||||||
|
creatEventHandler.call(this)
|
||||||
|
bindEvents.call(this)
|
||||||
|
appendElement.call(this)
|
||||||
|
onResult.call(this)
|
||||||
|
move(this[findBox], (0 - this[findBox].offsetHeight - 10), this.duration)
|
||||||
|
return this[initialized] = true
|
||||||
|
}
|
||||||
|
openFindWindow () {
|
||||||
|
if (this[hasOpened]) {
|
||||||
|
focusInput.call(this)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!this.initialize()) return false
|
||||||
|
setTimeout(() => {
|
||||||
|
this[findBox].style['visibility'] = 'visible'
|
||||||
|
lockNext.call(this)
|
||||||
|
focusInput.call(this)
|
||||||
|
}, 10)
|
||||||
|
move(this[findBox], parseInt(this[config].offsetTop), this.duration)
|
||||||
|
.then(() => {})
|
||||||
|
.catch(err => { throw err })
|
||||||
|
return this[hasOpened] = true
|
||||||
|
}
|
||||||
|
closeFindWindow () {
|
||||||
|
if (!this[hasOpened]) return false
|
||||||
|
this[findInput].value = ''
|
||||||
|
this[action] = ''
|
||||||
|
this[lastText] = ''
|
||||||
|
this[findMatches].innerText = '0/0'
|
||||||
|
this[hasOpened] = false
|
||||||
|
lockNext.call(this)
|
||||||
|
move(this[findBox], (0 - this[findBox].offsetHeight - 10), this.duration)
|
||||||
|
.then(() => { this[findBox].style['visibility'] = 'hidden' })
|
||||||
|
.catch(err => { throw err })
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
destroy () {
|
||||||
|
this.destroyFind()
|
||||||
|
unbindEvents.call(this)
|
||||||
|
this.closeFindWindow()
|
||||||
|
removeElement.call(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function creatElement (className = '', tag = 'div') {
|
||||||
|
const ele = document.createElement(tag)
|
||||||
|
ele.classList.add(className)
|
||||||
|
return ele
|
||||||
|
}
|
||||||
|
function getUserConfig (options) {
|
||||||
|
this[config].offsetTop = typeof options.offsetTop === 'number' ? `${options.offsetTop}px` : '5px'
|
||||||
|
this[config].offsetRight = typeof options.offsetRight === 'number' ? `${options.offsetRight}px` : '5px'
|
||||||
|
this[config].boxBgColor = typeof options.boxBgColor === 'string' ? options.boxBgColor : '#fff'
|
||||||
|
this[config].boxShadowColor = typeof options.boxShadowColor === 'string' ? options.boxShadowColor : '#909399'
|
||||||
|
this[config].inputColor = typeof options.inputColor === 'string' ? options.inputColor : '#606266'
|
||||||
|
this[config].inputBgColor = typeof options.inputBgColor === 'string' ? options.inputBgColor : '#f0f0f0'
|
||||||
|
this[config].inputFocusColor = typeof options.inputFocusColor === 'string' ? options.inputFocusColor : '#c5ade0'
|
||||||
|
this[config].textColor = typeof options.textColor === 'string' ? options.textColor : '#606266'
|
||||||
|
this[config].textHoverBgColor = typeof options.textHoverBgColor === 'string' ? options.textHoverBgColor : '#eaeaea'
|
||||||
|
this[config].caseSelectedColor = typeof options.caseSelectedColor === 'string' ? options.caseSelectedColor : '#c5ade0'
|
||||||
|
}
|
||||||
|
function setBoxStyle () {
|
||||||
|
this[findBox].style.cssText = `position:fixed; top:-110%; z-index: 3001; max-height:48px; min-height:30px;
|
||||||
|
right:${this[config].offsetRight}; display:flex; align-items:center; box-sizing:border-box !important;
|
||||||
|
padding:6px; visibility: hidden; background:${this[config].boxBgColor};
|
||||||
|
box-shadow: 1px 1px 2px 0.5px ${this[config].boxShadowColor};`
|
||||||
|
}
|
||||||
|
function setInputStyle () {
|
||||||
|
this[findInput].style.cssText = `width:168px; outline:0; border:1px solid ${this[config].inputBgColor};
|
||||||
|
background:${this[config].inputBgColor}; margin-right:6px; border-radius:2px; color:${this[config].inputColor}`
|
||||||
|
}
|
||||||
|
function setMatchesStyle () {
|
||||||
|
this[findMatches].innerText = '0/0'
|
||||||
|
this[findMatches].style.cssText = `color:${this[config].textColor}; font-size:14px; display:flex; align-items:center;
|
||||||
|
justify-content:center; min-width:40px; max-width:64px; overflow:hidden; margin-right:4px;`
|
||||||
|
}
|
||||||
|
function setCaseStyle () {
|
||||||
|
this[findCase].innerText = 'Aa'
|
||||||
|
this[findCase].style.cssText = `font-size:14px; font-weight:700; cursor:pointer; -webkit-user-select:none; color:${this[config].textColor};
|
||||||
|
padding:0px 2px; border-radius:2px; border:1px solid transparent; margin-right:4px; display:flex; align-items:center;`
|
||||||
|
}
|
||||||
|
function setBackStyle () {
|
||||||
|
this[findBack].style.cssText = `cursor:pointer; -webkit-user-select:none; position: relative; height: 20px; width: 20px; border-radius:2px;
|
||||||
|
overflow: hidden; display: inline-block; background:${this[config].boxBgColor}; border:0px solid ${this[config].boxBgColor};`
|
||||||
|
|
||||||
|
let backLine = creatElement('find-back-line')
|
||||||
|
backLine.style.cssText = `width:0; height:0; border:7px solid transparent; border-right-color:${this[config].textColor};
|
||||||
|
position: absolute; top:3px; left:-1px;`
|
||||||
|
this[findBack].appendChild(backLine)
|
||||||
|
|
||||||
|
let backCover = creatElement('find-back-cover')
|
||||||
|
backCover.style.cssText = `width:0; height:0; border:7px solid transparent; border-right-color:inherit;
|
||||||
|
position: absolute; top:3px; left:2px; z-index:1001;`
|
||||||
|
this[findBack].appendChild(backCover)
|
||||||
|
}
|
||||||
|
function setForwardStyle () {
|
||||||
|
this[findForward].style.cssText = `cursor:pointer; -webkit-user-select:none; position: relative; height: 20px; width: 20px; border-radius:2px;
|
||||||
|
overflow: hidden; display: inline-block; background:${this[config].boxBgColor}; border:0px solid ${this[config].boxBgColor};`
|
||||||
|
|
||||||
|
let forwardLine = creatElement('find-forward-line')
|
||||||
|
forwardLine.style.cssText = `width:0; height:0; border:7px solid transparent; border-left-color:${this[config].textColor};
|
||||||
|
position: absolute; top:3px; left:6px;`
|
||||||
|
this[findForward].appendChild(forwardLine)
|
||||||
|
|
||||||
|
let forwardCover = creatElement('find-forward-cover')
|
||||||
|
forwardCover.style.cssText = `width:0; height:0; border:7px solid transparent; border-left-color:inherit;
|
||||||
|
position: absolute; top:3px; left:3px; z-index:1001;`
|
||||||
|
this[findForward].appendChild(forwardCover)
|
||||||
|
}
|
||||||
|
function setCloseStyle () {
|
||||||
|
this[findClose].style.cssText = `cursor:pointer; -webkit-user-select:none; position: relative; height: 20px; width: 20px;
|
||||||
|
overflow: hidden; display: inline-block; background:${this[config].boxBgColor}; border-radius:2px;`
|
||||||
|
|
||||||
|
let closeInner1 = creatElement('find-close-inner1')
|
||||||
|
closeInner1.style.cssText = `width:14px; height:2px; background:${this[config].textColor}; transform:rotate(45deg);
|
||||||
|
position: absolute; top:9px; left:3px;`
|
||||||
|
this[findClose].appendChild(closeInner1)
|
||||||
|
|
||||||
|
let closeInner2 = creatElement('find-close-inner2')
|
||||||
|
closeInner2.style.cssText = `width:14px; height:2px; background:${this[config].textColor}; transform:rotate(-45deg);
|
||||||
|
position: absolute; top:9px; left:3px;`
|
||||||
|
this[findClose].appendChild(closeInner2)
|
||||||
|
}
|
||||||
|
function appendElement () {
|
||||||
|
[this[findInput], this[findMatches], this[findCase], this[findBack], this[findForward], this[findClose]].forEach((item) => {
|
||||||
|
this[findBox].appendChild(item)
|
||||||
|
})
|
||||||
|
this.parentElement.appendChild(this[findBox])
|
||||||
|
}
|
||||||
|
function removeElement () {
|
||||||
|
this.parentElement.removeChild(this[findBox])
|
||||||
|
}
|
||||||
|
function creatEventHandler () {
|
||||||
|
this[documentKeydown] = (function (e) {
|
||||||
|
if (!this[hasOpened]) return
|
||||||
|
onKeydown.call(this, e)
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: document, name: 'keydown', fn: this[documentKeydown] })
|
||||||
|
|
||||||
|
this[inputFocus] = (function () {
|
||||||
|
this[findInput].style.border = `1px solid ${this[config].inputFocusColor}`
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findInput], name: 'focus', fn: this[inputFocus] })
|
||||||
|
|
||||||
|
this[inputBlur] = (function () {
|
||||||
|
this[findInput].style.border = `1px solid ${this[config].inputBgColor}`
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findInput], name: 'blur', fn: this[inputBlur] })
|
||||||
|
|
||||||
|
this[inputEvent] = (function () {
|
||||||
|
updateCnt.call(this)
|
||||||
|
isInputing.call(this)
|
||||||
|
.then(res => {
|
||||||
|
res ? '' : onInput.call(this)
|
||||||
|
})
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findInput], name: 'input', fn: this[inputEvent] })
|
||||||
|
|
||||||
|
this[compositionstart] = (function () {
|
||||||
|
print('compositionstart')
|
||||||
|
this[inComposition] = true
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findInput], name: 'compositionstart', fn: this[compositionstart] })
|
||||||
|
|
||||||
|
this[compositionend] = (function () {
|
||||||
|
print('compositionend')
|
||||||
|
this[inComposition] = false
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findInput], name: 'compositionend', fn: this[compositionend] })
|
||||||
|
|
||||||
|
this[caseMouseenter] = (function () {
|
||||||
|
this[findCase].style['background'] = this[config].textHoverBgColor
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findCase], name: 'mouseenter', fn: this[caseMouseenter] })
|
||||||
|
|
||||||
|
this[caseMouseleave] = (function () {
|
||||||
|
this[findCase].style['background'] = this[config].boxBgColor
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findCase], name: 'mouseleave', fn: this[caseMouseleave] })
|
||||||
|
|
||||||
|
this[caseClick] = (function () {
|
||||||
|
onCaseClick.call(this)
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findCase], name: 'click', fn: this[caseClick] })
|
||||||
|
|
||||||
|
this[backMouseenter] = (function () {
|
||||||
|
this[findBack].style['background'] = this[config].textHoverBgColor
|
||||||
|
this[findBack].style['border'] = `0px solid ${this[config].textHoverBgColor}`
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findBack], name: 'mouseenter', fn: this[backMouseenter] })
|
||||||
|
|
||||||
|
this[backMouseleave] = (function () {
|
||||||
|
this[findBack].style['background'] = this[config].boxBgColor
|
||||||
|
this[findBack].style['border'] = `0px solid ${this[config].boxBgColor}`
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findBack], name: 'mouseleave', fn: this[backMouseleave] })
|
||||||
|
|
||||||
|
this[backClick] = (function () {
|
||||||
|
onBackClick.call(this)
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findBack], name: 'click', fn: this[backClick] })
|
||||||
|
|
||||||
|
this[forwardMouseenter] = (function () {
|
||||||
|
this[findForward].style['background'] = this[config].textHoverBgColor
|
||||||
|
this[findForward].style['border'] = `0px solid ${this[config].textHoverBgColor}`
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findForward], name: 'mouseenter', fn: this[forwardMouseenter] })
|
||||||
|
|
||||||
|
this[forwardMouseleave] = (function () {
|
||||||
|
this[findForward].style['background'] = this[config].boxBgColor
|
||||||
|
this[findForward].style['border'] = `0px solid ${this[config].boxBgColor}`
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findForward], name: 'mouseleave', fn: this[forwardMouseleave] })
|
||||||
|
|
||||||
|
this[forwardClick] = (function () {
|
||||||
|
onForwardClick.call(this)
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findForward], name: 'click', fn: this[forwardClick] })
|
||||||
|
|
||||||
|
this[closeMouseenter] = (function () {
|
||||||
|
this[findClose].style['background'] = this[config].textHoverBgColor
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findClose], name: 'mouseenter', fn: this[closeMouseenter] })
|
||||||
|
|
||||||
|
this[closeMouseleave] = (function () {
|
||||||
|
this[findClose].style['background'] = this[config].boxBgColor
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findClose], name: 'mouseleave', fn: this[closeMouseleave] })
|
||||||
|
|
||||||
|
this[closeClick] = (function () {
|
||||||
|
onCloseClick.call(this)
|
||||||
|
}).bind(this)
|
||||||
|
this[events].push({ ele: this[findClose], name: 'click', fn: this[closeClick] })
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindEvents () {
|
||||||
|
this[events].forEach((item) => {
|
||||||
|
on(item.ele, item.name, item.fn)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function unbindEvents () {
|
||||||
|
this[events].forEach((item) => {
|
||||||
|
off(item.ele, item.name, item.fn)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCnt () {
|
||||||
|
if (this[inputCnt] >= 0xFFFFFFFE) {
|
||||||
|
this[inputCnt] = 0
|
||||||
|
}
|
||||||
|
this[inputCnt]++
|
||||||
|
}
|
||||||
|
|
||||||
|
function isInputing () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let currCnt = this[inputCnt]
|
||||||
|
setTimeout(() => {
|
||||||
|
currCnt !== this[inputCnt] ? resolve(true) : resolve(false)
|
||||||
|
}, INPUT_INTERVAL_THRESHOLD)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function focusInput (doBlur = false) {
|
||||||
|
setTimeout(() => {
|
||||||
|
doBlur ? this[findInput].blur() : ''
|
||||||
|
this[findInput].focus()
|
||||||
|
}, 50)
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapInput (inputEle, caseEle, timeout = 50) {
|
||||||
|
inputEle.type = 'password'
|
||||||
|
caseEle.style['visibility'] = 'hidden'
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (inputEle.type !== 'text') {
|
||||||
|
print('[FindInPage] wrapInput timeout..')
|
||||||
|
unwrapInput(inputEle, caseEle)
|
||||||
|
}
|
||||||
|
}, timeout)
|
||||||
|
}
|
||||||
|
function unwrapInput (inputEle, caseEle) {
|
||||||
|
inputEle.type = 'text'
|
||||||
|
caseEle.style['visibility'] = 'visible'
|
||||||
|
}
|
||||||
|
|
||||||
|
function onInput () {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this[inComposition]) return
|
||||||
|
this[action] = 'input'
|
||||||
|
let text = this[findInput].value
|
||||||
|
if (text && text !== this[lastText]) {
|
||||||
|
this[lastText] = text
|
||||||
|
wrapInput(this[findInput], this[findCase], 100)
|
||||||
|
this.startFind(text, true, this[matchCase])
|
||||||
|
} else if (this[lastText] && text === '') {
|
||||||
|
this.stopFind()
|
||||||
|
this[findMatches].innerText = '0/0'
|
||||||
|
lockNext.call(this)
|
||||||
|
focusInput.call(this, true)
|
||||||
|
}
|
||||||
|
}, 50)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onKeydown (e) {
|
||||||
|
if (this[inComposition] || !e) return
|
||||||
|
switch (e.code) {
|
||||||
|
case 'Enter':
|
||||||
|
case 'NumpadEnter':
|
||||||
|
let text = this[findInput].value
|
||||||
|
if (!text) return
|
||||||
|
e.shiftKey ? findKeep.call(this, false) : findKeep.call(this, true)
|
||||||
|
break
|
||||||
|
case 'Escape':
|
||||||
|
onCloseClick.call(this)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findKeep (forward) {
|
||||||
|
if (!this.isFinding()) return
|
||||||
|
forward ? onForwardClick.call(this) : onBackClick.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCaseClick () {
|
||||||
|
if (!this[matchCase]) {
|
||||||
|
this[matchCase] = true
|
||||||
|
this[findCase].style['border-color'] = this[config].caseSelectedColor
|
||||||
|
wrapInput(this[findInput], this[findCase], 100)
|
||||||
|
this.startFind(this[findInput].value, true, this[matchCase])
|
||||||
|
} else {
|
||||||
|
this[matchCase] = false
|
||||||
|
this[findCase].style['border-color'] = 'transparent'
|
||||||
|
wrapInput(this[findInput], this[findCase], 100)
|
||||||
|
this.startFind(this[findInput].value, true, this[matchCase])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onBackClick () {
|
||||||
|
this[action] = 'back'
|
||||||
|
wrapInput(this[findInput], this[findCase], 100)
|
||||||
|
this.findNext(false, this[matchCase])
|
||||||
|
}
|
||||||
|
|
||||||
|
function onForwardClick () {
|
||||||
|
this[action] = 'forward'
|
||||||
|
wrapInput(this[findInput], this[findCase], 100)
|
||||||
|
this.findNext(true, this[matchCase])
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCloseClick () {
|
||||||
|
this.closeFindWindow() ? this.stopFind() : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function onResult () {
|
||||||
|
this.on('result', (activeMatch, matches) => {
|
||||||
|
unwrapInput(this[findInput], this[findCase])
|
||||||
|
this[findMatches].innerText = `${activeMatch}/${matches}`
|
||||||
|
matches > 0 ? unlockNext.call(this) : lockNext.call(this)
|
||||||
|
this[action] === 'input' ? focusInput.call(this) : ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function lockNext () {
|
||||||
|
this[findBack].style['opacity'] = 0.6
|
||||||
|
this[findBack].style['pointer-events'] = 'none'
|
||||||
|
this[findForward].style['opacity'] = 0.6
|
||||||
|
this[findForward].style['pointer-events'] = 'none'
|
||||||
|
}
|
||||||
|
|
||||||
|
function unlockNext () {
|
||||||
|
this[findBack].style['opacity'] = 1
|
||||||
|
this[findBack].style['pointer-events'] = 'auto'
|
||||||
|
this[findForward].style['opacity'] = 1
|
||||||
|
this[findForward].style['pointer-events'] = 'auto'
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = FindInPage
|
8
app/node_modules/electron-find/src/index.js
generated
vendored
Normal file
8
app/node_modules/electron-find/src/index.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
const FindInPage =require('./findInPage')
|
||||||
|
const Find = require('./find.js')
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
FindInPage,
|
||||||
|
Find
|
||||||
|
}
|
107
app/node_modules/electron-find/src/utils.js
generated
vendored
Normal file
107
app/node_modules/electron-find/src/utils.js
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
const debug = false
|
||||||
|
const print = debug ? console.log.bind(console) : () => {}
|
||||||
|
|
||||||
|
const on = (() => {
|
||||||
|
if (document && document.addEventListener) {
|
||||||
|
return (element, event, handler) => {
|
||||||
|
if (element && event && handler) {
|
||||||
|
element.addEventListener(event, handler, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (document && document.attachEvent) {
|
||||||
|
return (element, event, handler) => {
|
||||||
|
if (element && event && handler) {
|
||||||
|
element.attachEvent(`on${event}`, handler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return () => {}
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
const off = (() => {
|
||||||
|
if (document && document.removeEventListener) {
|
||||||
|
return (element, event, handler) => {
|
||||||
|
if (element && event && handler) {
|
||||||
|
element.removeEventListener(event, handler, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (document && document.detachEvent) {
|
||||||
|
return (element, event, handler) => {
|
||||||
|
if (element && event && handler) {
|
||||||
|
element.detachEvent(`on${event}`, handler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return () => {}
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
const once = (element, event, fn) => {
|
||||||
|
let listener = function () {
|
||||||
|
if (typeof fn === 'function') {
|
||||||
|
fn.apply(this, arguments)
|
||||||
|
}
|
||||||
|
off(element, event, listener)
|
||||||
|
}
|
||||||
|
on(element, event, listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
window.requestAnimationFrame = window.requestAnimationFrame ||
|
||||||
|
window.webkitRequestAnimationFrame ||
|
||||||
|
window.mozRequestAnimationFrame ||
|
||||||
|
window.msRequestAnimationFrame ||
|
||||||
|
window.oRequestAnimationFrame ||
|
||||||
|
function (callback) {
|
||||||
|
return window.setTimeout(callback, 1000 / 60)
|
||||||
|
}
|
||||||
|
|
||||||
|
window.cancelAnimationFrame = window.cancelAnimationFrame ||
|
||||||
|
window.webkitCancelAnimationFrame ||
|
||||||
|
window.mozCancelAnimationFrame ||
|
||||||
|
window.msCancelAnimationFrame ||
|
||||||
|
window.oCancelAnimationFrame ||
|
||||||
|
function (id) {
|
||||||
|
window.clearTimeout(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const move = (element, end, duration = 300) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
let winFrameId = null
|
||||||
|
let stepTime = duration / (1000 / 60)
|
||||||
|
let curr = parseInt(element.style.top)
|
||||||
|
let stepDist = (end - curr) / stepTime
|
||||||
|
let stepCnt = 0
|
||||||
|
|
||||||
|
const step = function () {
|
||||||
|
curr += stepDist
|
||||||
|
stepCnt++
|
||||||
|
if (stepCnt >= stepTime || (Math.abs(end - curr) <= (stepDist + 1))) {
|
||||||
|
element.style.top = `${end}px`
|
||||||
|
if (winFrameId) {
|
||||||
|
window.cancelAnimationFrame(winFrameId)
|
||||||
|
winFrameId = null
|
||||||
|
}
|
||||||
|
resolve()
|
||||||
|
} else {
|
||||||
|
element.style.top = `${curr}px`
|
||||||
|
winFrameId = window.requestAnimationFrame(step)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
step()
|
||||||
|
} catch (error) {
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
print,
|
||||||
|
on,
|
||||||
|
off,
|
||||||
|
once,
|
||||||
|
move
|
||||||
|
}
|
5
app/package-lock.json
generated
5
app/package-lock.json
generated
@@ -419,6 +419,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"electron-find": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/electron-find/-/electron-find-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-RenjzlCCzX7edLywLy+qRYvzds11sBv8+SrJu/3l3eVLt9d9uNqCPk+uFZ525uAhSUaUalgZWDlhQdxIgT1khg=="
|
||||||
|
},
|
||||||
"electron-is-accelerator": {
|
"electron-is-accelerator": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/electron-is-accelerator/-/electron-is-accelerator-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/electron-is-accelerator/-/electron-is-accelerator-0.1.2.tgz",
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
"animate.css": "^3.5.2",
|
"animate.css": "^3.5.2",
|
||||||
"bootstrap": "^4.1.3",
|
"bootstrap": "^4.1.3",
|
||||||
"ejs": "^2.6.1",
|
"ejs": "^2.6.1",
|
||||||
|
"electron-find": "^1.0.6",
|
||||||
"electron-localshortcut": "^3.1.0",
|
"electron-localshortcut": "^3.1.0",
|
||||||
"jquery": "^3.3.1",
|
"jquery": "^3.3.1",
|
||||||
"material-design-icons": "^3.0.1",
|
"material-design-icons": "^3.0.1",
|
||||||
|
Reference in New Issue
Block a user