Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions css/kunai/site.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
@import './site/sidebar.css';
@import './site/article.css';
@import './site/goog.css';
@import './site/tooltip.css';

16 changes: 15 additions & 1 deletion css/kunai/site/article.css
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,21 @@ div[itemtype="http://schema.org/Article"] {
border: none;
}
}

dfn {
font-weight: bold;
}
a.cpprefjp-defined-word {
text-decoration: underline dotted 2px #08F;
text-underline-offset: 1px;
color: inherit;
}
a.cpprefjp-defined-word:link:hover {
background-color: #DDD;
}
a.cpprefjp-defined-word[data-desc]:not(:link) {
cursor: context-menu;
}
}
}

Expand Down Expand Up @@ -295,4 +310,3 @@ div[itemtype="http://schema.org/Article"] {
}
}
}

18 changes: 18 additions & 0 deletions css/kunai/site/tooltip.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* Note: The tooltip element will be directly added to the top level of <body> */
#kunai-ui-tooltip {
text-decoration: none!important; font-weight: normal!important; font-style: normal!important;
width: max-content; max-width: 40em;
border: 1px solid black; padding: 0.2rem 0.4rem; margin: 0;
background-color: white; color: black; text-decoration: none; font-size: 0.9rem;
position: fixed; box-shadow: 2px 2px 2px 0 rgba(128, 128, 128, 0.6);
cursor: default;
opacity: 0; z-index: -1;
transition: opacity .3s linear .5s, z-index 0s linear .8s;
}
#kunai-ui-tooltip:before {
content: attr(data-desc);
}
#kunai-ui-tooltip.kunai-ui-tooltip-revealed {
opacity: 1; z-index: 1000000;
transition: opacity .3s linear 0s, z-index 0s linear 0s;
}
41 changes: 40 additions & 1 deletion js/kunai/ui/content.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,53 @@
import * as Badge from './badge'
import {Tooltip} from './tooltip'


const _hitElementRects = (elem, x, y) => {
for (const rect of elem.getClientRects())
if (rect.left <= x && x <= rect.right && rect.top <= y && y <= rect.bottom)
return rect
return null
}

class Content {
constructor(log) {
this.log = log.makeContext('Content')
this.log.debug('initialzing...')

this.log.debug(`found ${Badge.sanitize($('main[role="main"] div[itemtype="http://schema.org/Article"] .content-body span.cpp'))} badges`)

this.setupTooltip()
}

setupTooltip() {
const tooltip = new Tooltip(document)
let target = null
Comment thread
yumetodo marked this conversation as resolved.

$('a[data-desc]').on({
mouseover: function(e) {
const rect = _hitElementRects(this, e.clientX, e.clientY)
if (rect) {
target = this
tooltip.show(this.dataset.desc, e.clientX, e.clientY, rect)
}
},
mouseout: function() {
if (this === target) {
target = null
tooltip.hide()
}
}
})

const checkScroll = function(e) {
if (target !== null && !_hitElementRects(target, e.clientX, e.clientY)) {
target = null
tooltip.hide()
}
}
window.addEventListener('scroll', checkScroll, true)
window.addEventListener('resize', checkScroll)
}
}

export {Content}

72 changes: 72 additions & 0 deletions js/kunai/ui/tooltip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
class Tooltip {
/**
* ツールチップを構築します。
* @param {Document} [_document] - 表示対象のドキュメント
* @param {object} [config] - 設定
*/
constructor(_document, config) {
this.document = _document || document
this.view = this.document.defaultView || window
this.config = {
horizontalMargin: 8, // (設定) ツールチップ配置時のビューポート横余白
verticalMargin: 8, // (設定) ツールチップ配置時のビューポート縦余白
verticalOffset: 2, // (設定) ツールチップと対象要素の縦の距離
tooltipId: 'kunai-ui-tooltip',
tooltipClassRevealed: 'kunai-ui-tooltip-revealed'
}
if (config)
Object.assign(this.config, config)

this.span = document.createElement('span')
this.span.id = this.config.tooltipId
this.document.body.appendChild(this.span)
}

_place(x, y) {
// 物理ピクセル位置にぴったり合わせる
const pixelRatio = this.view.devicePixelRatio
x = Math.round(x * pixelRatio) / pixelRatio
y = Math.round(y * pixelRatio) / pixelRatio

this.span.style.left = `${x}px`
this.span.style.top = `${y}px`
this.span.classList.add(this.config.tooltipClassRevealed)
}

/**
* マウス位置および対象領域を元にして、ツールチップを適切な位置に表示します。
* @param {string} desc - 表示する文字列
* @param {number} mouseX - ビューポート内のマウス位置X
* @param {number} mouseY - ビューポート内のマウス位置Y
* @param {DOMRect} rect - 表示対象オブジェクトの領域
*
*/
show(desc, mouseX, mouseY, rect) {
// 幾何情報の取得
this.span.dataset.desc = desc
const tw = this.span.offsetWidth // ツールチップの表示幅
const th = this.span.offsetHeight // ツールチップの表示高さ
const vw = this.document.documentElement.clientWidth // スクロールバーを除くビューポートの幅
const vh = this.document.documentElement.clientHeight // スクロールバーを除くビューポートの高さ

// 位置の決定
let x = Math.max(this.config.horizontalMargin, Math.min(vw - tw - this.config.horizontalMargin, mouseX))
let y = rect.top - this.config.verticalOffset - th
if (y < this.config.verticalMargin) {
y = rect.bottom + this.config.verticalOffset
if (y + th > vh - this.config.verticalMargin)
y = mouseY + this.config.verticalOffset
}

this._place(x, y)
}

/**
* ツールチップを隠します。
*/
hide() {
this.span.classList.remove(this.config.tooltipClassRevealed)
}
}

export {Tooltip}