Skip to content

Commit

Permalink
fix: 链接修改字号后再点链接按钮无法看到链接地址
Browse files Browse the repository at this point in the history
  • Loading branch information
Gavin-yh committed Feb 10, 2022
1 parent be6c314 commit b396a1e
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 13 deletions.
24 changes: 21 additions & 3 deletions src/menus/link/bind-event/tooltip-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import $, { DomElement } from '../../../utils/dom-core'
import Tooltip, { TooltipConfType } from '../../menu-constructors/Tooltip'
import Editor from '../../../editor/index'
import { EXTRA_TAG } from '../is-active'

/**
* 生成 Tooltip 的显示隐藏函数
Expand Down Expand Up @@ -50,9 +51,26 @@ function createShowHideFn(editor: Editor) {
style=${$selectIMG?.getAttribute('style')}>`
)
} else {
// 用文字,替换链接
const selectionText = $link.text()
editor.cmd.do('insertHTML', '<span>' + selectionText + '</span>')
/**
* 替换链接
*
* 两种情况
* 1. a标签里面可能会含有其他元素如:b, i等,要保留: <a><b></b></a> 先添加链接后加粗
* 2. 特殊标签里嵌套a,也要保留特殊标签:<b><a></a></b> 先加粗后添加链接
*/
const linkElem = $link.elems[0]

// a标签里面的html结构
const selectionContent = linkElem.innerHTML

// a标签的父元素
const linkParentNode = linkElem.parentElement

if (linkParentNode && EXTRA_TAG.includes(linkParentNode.nodeName)) {
linkParentNode.innerHTML = selectionContent
} else {
editor.cmd.do('insertHTML', '<span>' + selectionContent + '</span>')
}
}

// 返回 true,表示执行完之后,隐藏 tooltip。否则不隐藏。
Expand Down
66 changes: 62 additions & 4 deletions src/menus/link/create-panel-conf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Editor from '../../editor/index'
import { PanelConf } from '../menu-constructors/Panel'
import { getRandom } from '../../utils/util'
import $, { DomElement } from '../../utils/dom-core'
import isActive from './is-active'
import isActive, { getParentNodeA, EXTRA_TAG } from './is-active'
import { insertHtml } from './util'

export default function (editor: Editor, text: string, link: string): PanelConf {
Expand Down Expand Up @@ -78,9 +78,35 @@ export default function (editor: Editor, text: string, link: string): PanelConf
}
// 选中整个链接
selectLinkElem()
// 用文本替换链接
const selectionText = $selectedLink.text()
editor.cmd.do('insertHTML', '<span>' + selectionText + '</span>')

/**
* 替换链接
*
* 两种情况
* 1. 特殊标签里嵌套a,也要保留特殊标签:<b><a></a></b> 先加粗后添加链接
* 2. a标签里面可能会含有其他元素如:b, i等,要保留: <a><b></b></a> 先添加链接后加粗
*/

if ($selectedLink.getNodeName() === 'A') {
const linkElem = $selectedLink.elems[0]
const linkParentNode = linkElem.parentElement

// 判断父级元素是不是特殊元素
if (linkParentNode && EXTRA_TAG.includes(linkParentNode.nodeName)) {
// 将特殊元素的内容设置为a标签的内容
linkParentNode.innerHTML = linkElem.innerHTML
} else {
// 如果父级不是特殊元素,直接设置内容
editor.cmd.do('insertHTML', '<span>' + linkElem.innerHTML + '</span>')
}
} else {
// 如果链接上选区是特殊元素,需要获取最近的a标签,获取html结果,以保留特殊元素
const parentNodeA = getParentNodeA($selectedLink)!

const selectionContent = parentNodeA.innerHTML

editor.cmd.do('insertHTML', '<span>' + selectionContent + '</span>')
}
}

/**
Expand Down Expand Up @@ -143,6 +169,10 @@ export default function (editor: Editor, text: string, link: string): PanelConf
selector: '#' + btnOkId,
type: 'click',
fn: () => {
// 获取链接区间的顶层元素
const $selectionContainerElem = editor.selection.getSelectionContainerElem()!
const $elem = $selectionContainerElem?.elems[0]

// 获取选取
editor.selection.restoreSelection()
const topNode = editor.selection
Expand Down Expand Up @@ -181,6 +211,34 @@ export default function (editor: Editor, text: string, link: string): PanelConf
if (!text) text = link
// 校验链接是否满足用户的规则,若不满足则不插入
if (!checkLink(text, link)) return

/**
* 插入链接
* 1、针对首次插入链接,利用选区插入a标签即可
* 1、针对:<a><b>xxxx</b></a> 情况,用户操作修改或者替换链接时,编辑得到a,修改已有a标签的href
* 2、针对:<b><a>xxxx</a></b> 情况, 用户操作修改或者替换链接时,只要修改已有a标签的href
*/

// 选区范围是a标签,直接替换href链接即可
if ($elem?.nodeName === 'A') {
$elem.setAttribute('href', link)

return true
}

// 不是a标签,并且为特殊元素, 需要检查是不是首次设置链接,还是已经设置过链接。
if ($elem?.nodeName !== 'A' && EXTRA_TAG.includes($elem.nodeName)) {
const nodeA = getParentNodeA($selectionContainerElem)

// 防止第一次设置就为特殊元素,这种情况应该为首次设置链接
if (nodeA) {
nodeA.setAttribute('href', link)

return true
}
}

// 首次插入链接
insertLink(text, link)

// 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭
Expand Down
17 changes: 15 additions & 2 deletions src/menus/link/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import PanelMenu from '../menu-constructors/PanelMenu'
import Editor from '../../editor/index'
import $, { DomElement } from '../../utils/dom-core'
import createPanelConf from './create-panel-conf'
import isActive from './is-active'
import isActive, { getParentNodeA } from './is-active'
import Panel from '../menu-constructors/Panel'
import { MenuActive } from '../menu-constructors/Menu'
import bindEvent from './bind-event/index'
Expand Down Expand Up @@ -57,14 +57,27 @@ class Link extends PanelMenu implements MenuActive {
}

if (this.isActive) {
let text = ''
let href = ''

// 菜单被激活,说明选区在链接里
$linkElem = editor.selection.getSelectionContainerElem()

if (!$linkElem) {
return
}

if ($linkElem.getNodeName() !== 'A') {
const parentNodeA = getParentNodeA($linkElem)!

$linkElem = $(parentNodeA)
}

text = $linkElem.text()
href = $linkElem.attr('href')

// 弹出 panel
this.createPanel($linkElem.text(), $linkElem.attr('href'))
this.createPanel(text, href)
} else {
// 菜单未被激活,说明选区不在链接里
if (editor.selection.isSelectionEmpty()) {
Expand Down
37 changes: 33 additions & 4 deletions src/menus/link/is-active.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,46 @@
*/

import Editor from '../../editor/index'
import { DomElement } from '../../utils/dom-core'

function isActive(editor: Editor): boolean {
// 加粗 b
// 字号/字体/颜色 font
// 斜体 i
// 删除线 strike
export const EXTRA_TAG = ['B', 'FONT', 'I', 'STRIKE']

export function getParentNodeA(selectionELem: DomElement) {
let node = selectionELem.elems[0]

while (node && EXTRA_TAG.includes(node.nodeName)) {
node = node.parentElement!

if (node.nodeName === 'A') {
return node
}
}
}

function isActive(editor: Editor) {
const $selectionELem = editor.selection.getSelectionContainerElem()
if (!$selectionELem?.length) {

if (!$selectionELem?.elems?.length) {
return false
}

// 选中直接是a元素
if ($selectionELem.getNodeName() === 'A') {
return true
} else {
return false
}

// 有可能a里面嵌套了其他元素,比如b、i元素等
const parentNode = getParentNodeA($selectionELem)

if (parentNode && parentNode.nodeName === 'A') {
return true
}

return false
}

export default isActive

0 comments on commit b396a1e

Please sign in to comment.