-
Notifications
You must be signed in to change notification settings - Fork 123
/
Copy pathscroll_div.js
119 lines (105 loc) · 3.11 KB
/
scroll_div.js
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
110
111
112
113
114
115
116
117
118
119
// ==VimperatorPlugin==
// @name Div Scroller
// @description-ja スクロールができる div 要素などでスクロールする
// @license Creative Commons 2.1 (Attribution + Share Alike)
// @version 0.1
// ==/VimperatorPlugin==
//
// Mappings:
// ]d [d
// スクロール対象を変更
// ]f [f のようなもの
// <Leader>j <Leader>k
// スクロールする
//
// TODO:
// フレーム対応
(function () {
// スクロール可能か?
function isScrollable (elem) {
const re = /auto|scroll/i;
let s = elem.ownerDocument.defaultView.getComputedStyle(elem, '');
if (elem.scrollHeight <= elem.clientHeight)
return false;
return ['overflow', 'overflowY', 'overflowX'].some(function (n)
s[n] && re.test(s[n]));
}
// 光らせる
function flashElement (elem) {
let indicator = elem.ownerDocument.createElement('div');
let rect = elem.getBoundingClientRect();
indicator.id = 'nyantoro-element-indicator';
let style = 'background-color: blue; opacity: 0.5; z-index: 999;' +
'position: fixed; ' +
'top: ' + rect.top + 'px;' +
'height:' + elem.clientHeight + 'px;'+
'left: ' + rect.left + 'px;' +
'width: ' + elem.clientWidth + 'px';
indicator.setAttribute('style', style);
elem.appendChild(indicator);
setTimeout(function () elem.removeChild(indicator), 500);
}
// スクロール可能な要素のリストを返す
function scrollableElements () {
let result = [];
let doc = content.document;
let r = doc.evaluate('//div|//ul', doc, null, 7, null)
for (let i = 0, l = r.snapshotLength; i < l; i++) {
let elem = r.snapshotItem(i);
if (isScrollable(elem))
result.push(elem);
}
return result;
}
// スクロール対象を変更
function shiftScrollElement (n) {
let doc = content.document;
let idx = doc.__div_scroller_index || 0;
let es = scrollableElements();
if (es.length <= 0)
liberator.echoerr('scrollable element not found');
idx += (n || 1);
if (idx < 0)
idx = es.length - 1;
if (idx >= es.length)
idx = 0;
content.document.__div_scroller_index = idx;
flashElement(es[idx]);
}
// 現在のスクロール対象を返す
function currentElement () {
let es = scrollableElements();
let idx = content.document.__div_scroller_index || 0;
return es[idx];
}
// スクロールする
function scroll (down) {
let elem = currentElement();
if (elem)
elem.scrollTop += Math.max(30, elem.clientHeight - 20) * (down ? 1 : -1);
}
mappings.addUserMap(
[modes.NORMAL],
['<Leader>j'],
'Scroll down',
function () scroll(true)
);
mappings.addUserMap(
[modes.NORMAL],
['<Leader>k'],
'Scroll up',
function () scroll(false)
);
mappings.addUserMap(
[modes.NORMAL],
[']d'],
'Shift Scroll Element',
function () shiftScrollElement(1)
);
mappings.addUserMap(
[modes.NORMAL],
['[d'],
'Shift Scroll Element',
function () shiftScrollElement(-1)
);
})();