forked from Kenshin/simpread
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtoc.jsx
More file actions
109 lines (95 loc) · 3.42 KB
/
toc.jsx
File metadata and controls
109 lines (95 loc) · 3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
console.log( "=== simpread read toc load ===" )
let is_click = false;
class TOC extends React.Component {
onClick( event ) {
is_click = true;
const $target = $( event.target ).parent();
$target.parent().find( "active" ).removeClass( "toc-outline-active" );
$target.find( "active" ).addClass( "toc-outline-active" );
const href = $( event.target ).attr("href"),
offsetTop = href === "#" ? 0 : $(href).offset().top - 5;
$( "html" ).stop().animate({
scrollTop: offsetTop
}, 300, () => {
setTimeout( ()=>is_click = false, 500 );
});
event.preventDefault();
}
componentDidMount() {
let lastId;
const topMenu = $( "toc" ),
topMenuHeight = topMenu.outerHeight(),
menuItems = topMenu.find( "a" ),
scrollItems = menuItems.map( function() {
const item = $( $(this).attr("href") );
if ( item.length ) { return item; }
});
$( window ).scroll( function() {
if ( is_click ) return;
const fromTop = $(this).scrollTop() + topMenuHeight;
let cur = scrollItems.map( function() {
if ($(this).offset().top < fromTop)
return this;
});
cur = cur[cur.length - 1];
const id = cur && cur.length ? cur[0].id : "";
if ( lastId !== id ) {
lastId = id;
menuItems.parent().find( "active" ).removeClass( "toc-outline-active" );
menuItems.filter("[href='#"+id+"']").parent().find( "active" ).addClass( "toc-outline-active" );
}
});
$( "outline" ).map( ( idx, item ) => {
$(item).width( 180 - parseInt( $(item).css("padding-left") ) );
})
}
render() {
const outline = this.props.table.map( item => {
return (
<outline className={ item.level }>
<active></active>
<a className={ "toc-outline-theme-" + this.props.theme } href={ "#" + item.id} onClick={ evt=>this.onClick(evt) }>{ item.value }</a>
</outline>
)
});
return (
<toc className="simpread-font simpread-theme-root">
{ outline }
</toc>
)
}
}
/**
* Render
*
* @param {string} selector name
* @param {jquery} jquery object
* @param {string} theme
* @param {boolen} hidden
*/
function Render( root, $target, theme, hidden ) {
// hack code
//if ( location.host.includes( "blog.csdn.net" )) return;
//if ( location.host.includes( "post.smzdm.com" )) return;
const table = [],
cls = hidden ? "toc-bg-hidden" : "";
$target.find( "h1, h2, h3, h4" ).map( ( idx, item) => {
const $item = $( item ),
tag = $item[0].tagName.toLowerCase(),
value = $item.text();
let id = $item.attr( "id" );
id = id == undefined ? `sr-toc-${idx}` : `${id}-${idx}`
$item.attr( "id", id );
value && table.push({
level: `toc-level-${tag}`,
id,
value,
});
});
console.log( "current toc is ", table )
$( root ).append( `<toc-bg class=${cls}></tocbg>` );
table.length > 1 && ReactDOM.render( <TOC table={ table } theme={ theme } />, $( "toc-bg" )[0] );
}
export {
Render
}